When you own a Gitea ticket end-to-end, work it in this order:
- Read, then act. Read the issue AND its latest comments (scope usually lives in the newest comment, not the body), identify the components it touches, make the necessary changes, and follow the instructions faithfully. Drive parallel sub-agents (the
Agenttool) to explore/implement/review/test concurrently — reserve your own context for synthesis and verification (see DRY/KISS below). - Wire the PR to auto-close the issue. In the PR body, reference the ticket with a closing keyword (
Closes #N/Fixes #N) so merging the PR closes it automatically. For an umbrella with deliberately-open children (e.g. ops-only), name which ones stay open. - Reconcile with the target branch. After opening the PR, confirm it is mergeable against the current remote target (
mainmoves under you) — fetch, check for conflicts, and rebase/merge + resolve them if any, then re-run the suite before requesting merge. - Uphold DRY & KISS. Smallest diff that solves it; search for an existing utility/component before writing anything custom; one atomic class per feature; no speculative abstractions. Spawn sub-agents per the parallel-delegation principle in (1).
- Reply on the ticket. Post a completion comment cross-referencing the PR # + commit SHA, the corrected root cause, and an honest validation caveat; keep the phased checklist in the body in lockstep.
At the start of every conversation and every non-trivial task, ask a configured code-wiki MCP tool a question about bearlike/Assistant — try the primary configured one first, falling back to a secondary if one is configured. Use read_wiki_structure → read_wiki_contents for deeper exploration. Only read local files after hydration. Include this directive in subagent prompts.
Wikis lag the repo (miss
mewbo_graph/#25, cite removedmewbo_chat). Use them for intuition; verify structure against local source.
An AI assistant modelled as a conversation state machine with a hierarchical agent hypervisor. Core engine: a single async ToolUseLoop bound to an LLM via native bind_tools. Sub-agents admitted via spawn_agent, tracked by AgentHypervisor, resolved into one of four terminal states (completed, failed, cancelled, rejected). Interfaces: CLI, web console, REST API, Home Assistant, Nextcloud Talk — all share the core engine. For architecture details, query the wiki.
Dependencies flow strictly down this DAG; never up, not even a lazy try/except ImportError:
mewbo_core (lean SDK) → mewbo_tools · mewbo_graph → apps
mewbo_core— lean orchestration SDK: generic, dependency-light primitives only. No product/graph code; heavy optional deps go behind amewbo-core[...]extra.mewbo_tools— subprocess/remote integrations (MCP, LSP, file edit). Deps core only.mewbo_graph— optional capability library (graph, memory, embedding, SCG). Heavy deps behind extras + import-guards. Deps core only; never an app.- apps — thin product surfaces: HTTP routes, wire contracts, transport, glue. Compose libraries; never host a reusable engine.
Placement rule. Reusable engine → a library. Orchestration primitive → core. Subprocess/integration → tools. HTTP route/transport → an app. (1) A reusable engine must never live inside an app. (2) Two apps must never import each other — extract the shared part into a library.
"Optional" means both layers: PEP 621 extras AND a graceful try/except ImportError at every import site. Plugins/AgentDefs ship with the library whose substrate they wrap — mewbo_graph.plugins.{wiki,scg} are canonical. A library pushes its plugin root via mewbo_core.plugins.register_builtin_root; core never imports up to discover it.
KISS & DRY. Bias toward less code. Search for an existing utility before writing anything custom.
Proven libraries: LiteLLM (LLM+embeddings), Pydantic (validation), Flask-RESTX (API), Rich/Textual (terminal), Langfuse (tracing), Jinja2 (prompts), Tiktoken (tokens), Loguru (logging), langchain-mcp-adapters (MCP), PyMongo (Mongo).
- Validate at definition: Pydantic
field_validator,ConfigDict(extra="forbid"). - One atomic class per feature: state attrs + class/static methods + DI.
- Smallest diff that solves the problem. No speculative abstractions.
- Tool contracts stable:
AbstractTool,ActionStep,TaskQueue,tool_id/operation/tool_input. - Tests prefer real code paths; stub only I/O boundaries.
- Cross-model tool-calling differences are normalization concerns — fix at the LiteLLM/adapter seam, never by detecting text format in the orchestration loop. See
packages/mewbo_core/CLAUDE.md→ "LLM client". - Gitmoji + Conventional Commits (
✨ feat: ...). See.github/git-commit-instructions.md. - Never push unless explicitly asked. Treat LLMs as non-deterministic black-box APIs.
discover_all_instructions() loads four levels (low→high): user ~/.claude/CLAUDE.md, project CLAUDE.md / .claude/CLAUDE.md walking up to git root, rules .claude/rules/*.md, local CLAUDE.local.md. Subtree discovery walks DOWN from CWD (max depth 5) and indexes nested files for on-demand reading. Add <!-- mewbo:noload --> on line 1 to skip auto-loading a heavy file.
Read the deepest file that applies before editing. Every child carries > ↑ parent · root at the top.
| Scope | File |
|---|---|
| Engine: tool-use loop, hypervisor, hooks, plugins | packages/mewbo_core/CLAUDE.md |
| Integrations: MCP pool, file edit, LSP, Aider | packages/mewbo_tools/CLAUDE.md |
| Graph/memory/embedding/SCG substrate | packages/mewbo_graph/CLAUDE.md |
| SCG plugin tools (map + search) | packages/mewbo_graph/src/mewbo_graph/plugins/scg/CLAUDE.md |
| HTTP API server (routes, channels, Web IDE) | apps/mewbo_api/CLAUDE.md |
| MewboWiki — API side | apps/mewbo_api/src/mewbo_api/wiki/CLAUDE.md |
| Agentic Search — API side | apps/mewbo_api/src/mewbo_api/agentic_search/CLAUDE.md |
| Agentic Search — SCG lifecycle glue | apps/mewbo_api/src/mewbo_api/agentic_search/scg/CLAUDE.md |
| Web console (React, shadcn, TanStack Query) | apps/mewbo_console/CLAUDE.md (noload — heavy) |
| MewboWiki — Console side | apps/mewbo_console/src/components/wiki/CLAUDE.md |
| Agentic Search — Console side | apps/mewbo_console/src/components/agentic_search/CLAUDE.md |
| MCP server: tools exposing Mewbo to agents | apps/mewbo_mcp/CLAUDE.md |
| CLI (Rich/Textual display, agent panel) | apps/mewbo_cli/CLAUDE.md |
| Aura Android client (Compose, orb overlay, redroid dev loop) | apps/mewbo_aura/CLAUDE.md |
| Home Assistant conversation agent | apps/mewbo_ha_conversation/CLAUDE.md |
| Test patterns + fixtures | tests/CLAUDE.md |
| Docs site: code-ref badges, Scalar, authoring | docs/CLAUDE.md |
- Code-wiki MCP tools (
ask_question,read_wiki_structure,read_wiki_contents) — primary context source. Try the primary configured wiki tool first, fall back to a secondary if configured. Handles up to 10 repos at once. - Remote coding-agent session tools (
*_session_create,*_session_interact, etc.) — delegate long-running tasks, manage knowledge notes, schedule automated work. Session IDs need a provider-specific prefix when reused. - Langfuse (
mcp__langfuse__*) — observability. Path:get_error_count(age)→fetch_sessions→fetch_traces→fetch_trace(id, include_observations=true)→fetch_observation(id). Filter bysessionId== Mewbo session_id.mewbo-tool-usearrives as a trace TAG (trace name isstep:N);mewbo-task-master/mewbo-contextareuser_idvalues, not trace names.agein minutes (max 10080). Useoutput_mode="full_json_file"for large payloads. - SearXNG (
searxng_web_search) +web_url_read— current events, docs, errors outside codebase. - Context7 (
resolve_library_id→query_docs) — library/framework API docs.
Fire MCP calls in parallel. The code-wiki tool = "how should it work"; Langfuse = "how did it actually work."
See apps/mewbo_api/CLAUDE.md → "Debugging session errors" for the full trace methodology. Quick orientation: MongoDB db.events.find({session_id}).sort({ts:1}) (port 27018) is authoritative; Langfuse for LLM conversation chain. Per-agent attribution lives in Mongo llm_call_start/llm_call_end events (agent_id/depth/step); token counts live ONLY in Langfuse — Mongo llm_call events and /usage currently report zeros, and Langfuse's span tree orphans parents under concurrent sub-agents, so join the two by session, not by span. Cost/cache-hit truth is the LiteLLM proxy's Postgres spend log (litellm-postgres, LiteLLM_SpendLogs.metadata->usage_object → cache_creation/read_input_tokens); Langfuse mis-costs at full list price for any model string lacking a Langfuse Model Definition, and its cache_hit column tracks the Redis response cache, not Anthropic prompt caching.
- Tests:
pytestundertests/. - Install:
uv sync(core) oruv sync --all-extras --all-groups(dev). - Run:
uv run mewbo/uv run mewbo-apifrom repo root, ornpm run devinapps/mewbo_console. - Config chain:
CWD/configs/→$MEWBO_HOME/→~/.mewbo/. Override with--config. Run/initto scaffold. - Lint:
ruff check .(auto-fix:ruff check --fix .). Types:mypy. Helpers:make lint,make lint-fix,make typecheck,make precommit-install. - Never blind
ruff --fix— always re-runruff check .after any autofix (strips intentionalnoqa). - Browser automation / Playwright: if a remote Selenium/Chrome grid is configured for this environment, connect to its warm Chrome via Playwright
connectOverCDPinstead of launching a local browser — check your local ops docs (outside this repo) for the grid's connection details before falling back to a locally-launched browser.