Private
Public Access
0
0

Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-07-02 20:53:31 -04:00
28 changed files with 267 additions and 691 deletions
@@ -280,9 +280,8 @@ For Manual Slop's current state:
| Dim | Where in `src/` | Line range | What to look at |
|---|---|---|---|
| Curation | `src/models.py` | 510-559 | `FileItem` schema |
| Curation | `src/models.py` | 909-937 | `ContextPreset` schema |
| Curation | `src/context_presets.py` | (small) | `ContextPresetManager` |
| Curation | `src/project_files.py` | (whole file) | `FileItem` schema (moved out of `src/models.py` per `module_taxonomy_refactor_20260627`) |
| Curation | `src/context_presets.py` | (whole file) | `ContextPreset` schema + `ContextPresetManager` (moved out of `src/models.py`) |
| Curation | `src/aggregate.py` | (518 lines) | `build_file_items`, `build_markdown` |
| Discussion | `src/gui_2.py` | 3770-3853 | `render_discussion_entry` (A1-A7) |
| Discussion | `src/gui_2.py` | 4239-4260 | `render_discussion_entry_controls` (B1-B11) |
@@ -2,7 +2,9 @@
**Rule:** The `AppController` is the single source of truth for the
in-memory config (`self.config`) and the only authorized caller of
the file I/O primitives in `src/models.py`.
the file I/O primitives (the config-load/save helpers, which moved out
of `src/models.py` to `src/project_manager.py` per
`module_taxonomy_refactor_20260627`).
## Why
+10 -10
View File
@@ -137,22 +137,22 @@ When refactoring a class to functions:
| Class | File:Line | State held |
|---|---|---|
| `App` | `src/gui_2.py:307` | GUI state (show_windows, active_discussion, disc_entries), delegation proxies |
| `AppController` | `src/app_controller.py:795` | 11 locks, all subsystem managers, presets/personas/RAG state |
| `App` | `src/gui_2.py:314` | GUI state (show_windows, active_discussion, disc_entries), delegation proxies |
| `AppController` | `src/app_controller.py:801` | 11 locks, all subsystem managers, presets/personas/RAG state |
| `ConductorEngine` | `src/multi_agent_conductor.py:112` | TrackDAG, ExecutionEngine, WorkerPool, tier_usage |
| `WorkerPool` | `src/multi_agent_conductor.py:52` | active workers dict, semaphore, lock |
| `RAGEngine` | `src/rag_engine.py:123` | embedding provider, chroma client/collection |
| `RAGEngine` | `src/rag_engine.py:125` | embedding provider, chroma client/collection |
| `BaseEmbeddingProvider` + subclasses (`LocalEmbeddingProvider`, `GeminiEmbeddingProvider`) | `src/rag_engine.py:74,78,87` | loaded model state |
| `EventEmitter` | `src/events.py:40` | listeners dict |
| `AsyncEventQueue` | `src/events.py:77` | asyncio.Queue |
| `HistoryManager` | `src/history.py:71` | undo/redo stack (100-snapshot capacity) |
| `HookServer` + `HookServerInstance` + `HookHandler` + `WebSocketServer` | `src/api_hooks.py:856,130,155,908` | HTTP server thread, port binding, event queue |
| `HookServer` + `HookServerInstance` + `HookHandler` + `WebSocketServer` | `src/api_hooks.py:941,171,208,993` | HTTP server thread, port binding, event queue |
| `HotReloader` + `HotModule` | `src/hot_reloader.py:21,15` | HOT_MODULES registry, last_error, is_error_state |
**NOT exempt** (these are dataclasses / data carriers / context managers, not stateful subsystems):
- All `@dataclass(frozen=True)` types in `src/type_aliases.py` (12 per-aggregate types) — pure data
- All `@dataclass(frozen=True)` types in `src/type_aliases.py` (~19 per-aggregate types: Metadata, CommsLogEntry, HistoryMessage, ToolDefinition, SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats, ProviderPayload, UIPanelConfig, PathInfo, FileItemsDiff, JsonPrimitive, JsonValue, etc.) — pure data
- All `@dataclass(frozen=True)` types in `src/openai_schemas.py` (`ToolCall`, `ChatMessage`, `UsageStats`, `NormalizedResponse`, etc.) — pure data
- All `@dataclass` types in `src/models.py` (Ticket, Track, Persona, FileItem, ContextPreset, etc.) — pure data
- All `@dataclass` types in the per-system files (formerly in `src/models.py`, now moved out per `module_taxonomy_refactor_20260627`): `Ticket`/`Track`/`WorkerContext`/`TrackMetadata` in `src/mma.py`, `FileItem` in `src/project_files.py`, `ToolSpec` in `src/mcp_tool_specs.py`, `Result`/`ErrorInfo` in `src/result_types.py`, `Persona` in `src/personas.py`, `WorkspaceProfile` in `src/workspace_manager.py`, `RAGConfig`/`MCPServerConfig` in `src/mcp_client.py` — pure data
- All context-manager wrappers in `src/imgui_scopes.py` (`_ScopeChild`, `_ScopeGroup`, etc.) — they wrap scope, not state
- `HotModule` is exempt only because it's paired with the `HotReloader` registry class — keep them together
@@ -356,7 +356,7 @@ The ONLY place these patterns are allowed is at the literal wire boundary — th
### 17.8 Enforcement
- `scripts/audit_weak_types.py --strict` — flags `dict[str, Any]`, `Any`, anonymous tuple returns
- `scripts/audit_optional_returns.py --strict` — flags `Optional[T]` return types in ALL `src/*.py` (post-2026-06-27; was `audit_optional_in_3_files.py` covering 4 baseline files only — old script retained for code_path_audit_20260607 cross-reference contract)
- `scripts/audit_optional_in_3_files.py --strict` — flags `Optional[T]` return types in the baseline 4 files (`src/mcp_client.py`, `src/ai_client.py`, `src/rag_engine.py`, plus one more). An all-`src/*.py` successor (`audit_optional_returns.py`) is referenced in older planning docs but is NOT yet built — the live script today is `audit_optional_in_3_files.py`.
- `scripts/audit_imports.py --strict` — flags local imports (§17.9a) + `_PREFIX` aliasing (§17.9b) in all `src/*.py`; reads `scripts/audit_imports_whitelist.toml` for warmed-imports/hot-reload exceptions (use `--no-whitelist` to audit all files; `--show-whitelist` to inspect current whitelist)
- The new `boundary_layer` audit (planned in `conductor/tracks/cruft_elimination_20260627/spec.md`) — documents every `Metadata` usage with justification
- Pre-commit: every commit MUST pass all four audits above
@@ -449,7 +449,7 @@ The CORRECT pattern (preferred): promote the type at the boundary. After `cruft_
| Banned pattern | Audit script | Status |
|---|---|---|
| `dict[str, Any]`, `Any`, anonymous tuple returns | `scripts/audit_weak_types.py --strict` | ✅ implemented |
| `Optional[T]` return types in `src/*.py` | `scripts/audit_optional_returns.py --strict` (successor to `audit_optional_in_3_files.py` 2026-06-27; now scans all `src/*.py`) | ✅ implemented |
| `Optional[T]` return types in `src/*.py` | `scripts/audit_optional_in_3_files.py --strict` (live; covers the 4 baseline refactored files only — an all-src successor `audit_optional_returns.py` is referenced in older planning docs but is NOT yet built) | ✅ implemented (baseline files only) |
| Silent swallow (`try/except: pass` or log-only) | `scripts/audit_exception_handling.py --strict` | ✅ implemented |
| `Metadata` used as `dict[str, Any]` escape hatch | (planned per `conductor/tracks/cruft_elimination_20260627/spec.md` boundary-layer audit) | ⚠️ not yet built |
| Local imports inside function bodies (outside `try/except ImportError`) | `scripts/audit_imports.py` | ⚠️ not yet built (planned per §17.9a) |
@@ -461,12 +461,12 @@ The CORRECT pattern (preferred): promote the type at the boundary. After `cruft_
```bash
# Run before claiming "done"
uv run python scripts/audit_weak_types.py
uv run python scripts/audit_optional_returns.py
uv run python scripts/audit_optional_in_3_files.py
uv run python scripts/audit_exception_handling.py
# In CI / pre-commit hook (exit 1 on any violation)
uv run python scripts/audit_weak_types.py --strict
uv run python scripts/audit_optional_returns.py --strict
uv run python scripts/audit_optional_in_3_files.py --strict
uv run python scripts/audit_exception_handling.py --strict
```
+8 -3
View File
@@ -250,8 +250,13 @@ uv run python scripts/generate_type_registry.py --diff
**When the LLM needs the fields of a type:**
```bash
cat docs/type_registry/src_models.md # for src/models.py types
cat docs/type_registry/type_aliases.md # for the 10 TypeAliases
cat docs/type_registry/src_mma.md # for src/mma.py types (Ticket, Track, WorkerContext, TrackMetadata)
cat docs/type_registry/src_project_files.md # for src/project_files.py (FileItem)
cat docs/type_registry/type_aliases.md # for the per-aggregate dataclasses in src/type_aliases.py
cat docs/type_registry/src_mcp_tool_specs.md # for src/mcp_tool_specs.py (ToolSpec, ToolParameter)
cat docs/type_registry/src_result_types.md # for src/result_types.py (Result, ErrorInfo)
# (the old docs/type_registry/src_models.md reflected the pre-refactor src/models.py;
# models.py is now a ~1.5KB shim — see guide_models.md for the per-system file map)
```
**The "delete to turn off" pattern** (per `feature_flags.md`): `rm -rf docs/type_registry/` disables the registry. Re-enable by running `python scripts/generate_type_registry.py`.
@@ -333,7 +338,7 @@ uv run python scripts/generate_type_registry.py
**`src/app_controller.py`**: 62 `dict[str, Any]` -> `Metadata`; 20 `list[dict[str, Any]]` -> `list[Metadata]`; 4 `Optional[dict[str, Any]]` -> `Optional[Metadata]`.
**`src/models.py`**: 48 dataclass field types converted to `Optional[Metadata]` / `list[Metadata]`.
**`src/models.py`** (historical — at the time of the `data_structure_strengthening_20260606` track): 48 dataclass field types converted to `Optional[Metadata]` / `list[Metadata]`. **Note:** `src/models.py` has since been reduced to a ~1.5KB re-export shim per `module_taxonomy_refactor_20260627`; the dataclasses moved to per-system files (`src/mma.py`, `src/project_files.py`, `src/type_aliases.py`, etc.). The 48-site count reflects the pre-refactor state.
**`src/api_hook_client.py`**: HTTP request/response payloads use `Metadata` (the canonical "API payload" shape).
+2 -2
View File
@@ -199,8 +199,8 @@ Files & Media works. Context Composition needs:
## Key Files
- `src/gui_2.py` - Main GUI (1-space indentation, CRLF)
- `src/models.py` - Data models including FileItem
- Context Composition function: line ~2748
- `src/project_files.py` - `FileItem` dataclass (moved out of `src/models.py` per `module_taxonomy_refactor_20260627`); `src/models.py` is now a ~1.5KB re-export shim
- Context Composition function: line ~2748 (verify with `py_get_code_outline` before editing — line refs drift)
## Test Command
+2 -2
View File
@@ -5,7 +5,7 @@
- [Product Definition](./product.md) — Vision, primary use cases, and key features
- [Product Guidelines](./product-guidelines.md) — Code style, process, and architectural patterns
- [Tech Stack](./tech-stack.md) — Python 3.11+, ImGui Bundle, FastAPI, all SDKs and modules
- [Human-Facing Documentation](../docs/Readme.md) — **27 deep-dive guides** (architecture, MMA, tools, simulations, testing, per-source-file references, RAG, Beads, hot reload, personas, NERV theme, workspace profiles, command palette, themes, context curation, AI client, MCP client, app controller, GUI main, models, multi-agent conductor, state lifecycle, discussions, context aggregation, docker deployment, and more)
- [Human-Facing Documentation](../docs/Readme.md) — **41 deep-dive guides** (architecture, MMA, tools, simulations, testing, per-source-file references, RAG, Beads, hot reload, personas, NERV theme, workspace profiles, command palette, themes, context curation, AI client, MCP client, app controller, GUI main, models, multi-agent conductor, state lifecycle, discussions, context aggregation, docker deployment, and more)
## Workflow
@@ -23,4 +23,4 @@
- [Recently Shipped: Multi-Theme TOML System](./tracks/multi_themes_20260604/) — 8 new theme files, public API (`load_themes_from_disk`, `get_syntax_palette_for_theme`, `apply_syntax_palette`), color-callable convention. See [../docs/guide_themes.md](../docs/guide_themes.md) for the authoring guide.
- [Recently Shipped: Test Regression Fixes (post multi-themes ship)](./tracks/regression_fixes_20260605/) — 11 of 21 failing tests fixed, root cause of remaining live_gui C-level crash identified (`_ini_capture_ready` defer-not-catch pattern).
Last comprehensive doc refresh: 2026-06-10 (27 guide_*.md files, all now indexed in [docs/Readme.md](../docs/Readme.md)). 8 new guides added in the 2026-06-02 docs layer refresh: testing + 7 per-source-file references. Latest addition: `guide_themes.md` (2026-06-04, multi_themes_20260604 ship). The docs_sync_test_era_20260610 track (closed 2026-06-10) verified all 27 guides against the current `src/` source; see [docs/reports/docs_sync_test_era_20260610.md](../docs/reports/docs_sync_test_era_20260610.md) for the closing report. See [docs/Readme.md](../docs/Readme.md) for the full index.
Last comprehensive doc refresh: 2026-07-02 (41 guide_*.md files in `docs/`, all indexed in [docs/Readme.md](../docs/Readme.md)). Earlier refreshes: 2026-06-10 (27 guides verified against src/), 2026-06-02 (8 per-source-file guides added). Latest drift-fix pass: 2026-07-02 (guide_models.md rewritten for src/models.py shim reality; provider count + file sizes + mcp_tool_specs split corrected in product.md + tech-stack.md; send_result claim corrected in product-guidelines.md; audit_optional_returns.py phantom-script reference fixed in python.md). See [docs/Readme.md](../docs/Readme.md) for the full index.
+22 -8
View File
@@ -98,9 +98,12 @@ section for the full taxonomy.
The codebase follows the "names for shapes" pattern: every `dict[str, Any]`
or `list[dict[...]]` should use a `TypeAlias` from `src/type_aliases.py`.
The 10 aliases (`Metadata`, `CommsLogEntry`, `CommsLog`, `HistoryMessage`,
The core aliases (`Metadata`, `CommsLogEntry`, `CommsLog`, `HistoryMessage`,
`History`, `FileItem`, `FileItems`, `ToolDefinition`, `ToolCall`,
`CommsLogCallback`) cover the 86% of common patterns. The canonical
`CommsLogCallback`) plus the extended per-aggregate dataclasses
(`SessionInsights`, `DiscussionSettings`, `CustomSlice`, `MMAUsageStats`,
`ProviderPayload`, `UIPanelConfig`, `PathInfo`, `FileItemsDiff`, plus
the `JsonPrimitive`/`JsonValue` pair) cover the common patterns. The canonical
reference is in
[`conductor/code_styleguides/type_aliases.md`](code_styleguides/type_aliases.md).
@@ -188,13 +191,24 @@ function. The audit script `scripts/audit_optional_in_3_files.py` enforces
this rule by failing CI on new `Optional[X]` return types in the 3
refactored files.
### Public API: `ai_client.send_result()` (RESOLVED 2026-06-15)
### Public API: `ai_client.send()` (current as of 2026-07-02)
The public `ai_client.send_result()` is the canonical public API. It
returns `Result[str, ErrorInfo]`. The legacy `ai_client.send()` was
removed in the `public_api_migration_and_ui_polish_20260615` track on
2026-06-15 (see `conductor/tracks/public_api_migration_and_ui_polish_20260615/spec.md`).
All production call sites and tests now use `send_result()`.
The public `ai_client.send()` is the canonical public API. It returns
`Result[str, ErrorInfo]` (the data-oriented error type from
`src/result_types.py`). Check `result.ok` for success; on failure,
`result.errors` holds classified `ErrorInfo` instances. All provider
calls go through `send()`, which routes to the provider-specific
`_send_<vendor>()` helpers. The tests in `tests/test_ai_client_result.py`
verify the `Result` contract.
> **Note (corrected 2026-07-02):** a previous version of this section
> claimed `send_result()` was the canonical API and `send()` was
> removed. That was backwards against the current code — `send()` is
> live and `send_result` does not exist as a public function (it
> appears only as a local variable in `_send_gemini_cli`). The
> migration may have been reverted or the prior claim was always wrong;
> either way, the source of truth is `src/ai_client.py:send` and
> `tests/test_ai_client_result.py`.
</new_content>
## Testing Requirements
+8 -8
View File
@@ -16,13 +16,13 @@ For deep implementation details when planning or implementing tracks, consult `d
- **[docs/guide_simulations.md](../docs/guide_simulations.md):** Test framework, mock provider, Puppeteer pattern, test areas by subsystem
**Per-source-file references (NEW):**
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md):** `src/gui_2.py` (260KB): App class lifecycle, ~90 module-level render functions, Multi-Viewport docks, panel registry, ImGuiScope context managers, hot reload support
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md):** `src/ai_client.py` (116KB): multi-provider LLM singleton (5 providers), async dispatch via `asyncio.gather`, threading.local source tier tagging, Anthropic ephemeral + Gemini explicit caching, Tier 4 QA error interception
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md):** `src/api_hooks.py` + `src/api_hook_client.py` (38KB + 31KB): HookServer on `127.0.0.1:8999`, ApiHookClient wrapper, 8+ endpoints, Remote Confirmation Protocol via `/api/ask`
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md):** `src/mcp_client.py` (81KB, 45 tools): 3-layer security (Allowlist → Validate → Resolve), all native tools (File I/O, Python AST, C/C++ AST, Analysis, Network, Runtime, Beads), ExternalMCPManager (Stdio + SSE), JSON-RPC 2.0 engine
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md):** `src/app_controller.py` (166KB): headless orchestrator, AppState dataclass, all subsystem managers, `_predefined_callbacks`/`_gettable_fields` Hook API registries, SyncEventQueue, headless mode
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md):** `src/multi_agent_conductor.py` + `src/dag_engine.py` (28KB + 10KB): TrackDAG (iterative DFS cycle detection, Kahn's topological sort), ExecutionEngine (Auto-Queue / Step Mode), MultiAgentConductor + WorkerPool (concurrency 4), per-ticket Python subprocess spawning via `subprocess.Popen` (the WorkerPool's internal subprocess template, NOT the meta-tooling `mma_exec.py` — that's only used by external AI agents in the meta-tooling domain; see `docs/guide_meta_boundary.md`)
- **[docs/guide_models.md](../docs/guide_models.md):** `src/models.py` (132KB): centralized data model registry, `AGENT_TOOL_NAMES` canonical 45-tool list, `PROVIDERS` constant, `parse_plan_md` utility, validation patterns, SDM tags
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md):** `src/gui_2.py` (~437KB): App class lifecycle, ~90 module-level render functions, Multi-Viewport docks, panel registry, ImGuiScope context managers, hot reload support
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md):** `src/ai_client.py` (~166KB): multi-provider LLM singleton (8 providers: gemini, anthropic, gemini_cli, deepseek, minimax, qwen, grok, llama), async dispatch via `asyncio.gather`, threading.local source tier tagging, Anthropic ephemeral + Gemini explicit caching, Tier 4 QA error interception, inlined `VendorCapabilities` registry (moved from the deleted `src/vendor_capabilities.py`)
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md):** `src/api_hooks.py` + `src/api_hook_client.py` (~51KB + ~38KB): HookServer on `127.0.0.1:8999`, ApiHookClient wrapper, 8+ endpoints, Remote Confirmation Protocol via `/api/ask`
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md):** `src/mcp_client.py` (~92KB, 45 tools): 3-layer security (Allowlist → Validate → Resolve), all native tools (File I/O, Python AST, C/C++ AST, Analysis, Network, Runtime, Beads), ExternalMCPManager (Stdio + SSE), JSON-RPC 2.0 engine. Tool specs now live in `src/mcp_tool_specs.py` (typed `ToolSpec` dataclass + `_REGISTRY`); `mcp_client.py` re-exports `TOOL_NAMES` for backward compat.
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md):** `src/app_controller.py` (~240KB): headless orchestrator, AppState dataclass, all subsystem managers, `_predefined_callbacks`/`_gettable_fields` Hook API registries, SyncEventQueue, headless mode
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md):** `src/multi_agent_conductor.py` + `src/dag_engine.py` (~30KB + ~11KB): TrackDAG (iterative DFS cycle detection, Kahn's topological sort), ExecutionEngine (Auto-Queue / Step Mode), MultiAgentConductor + WorkerPool (concurrency 4), per-ticket Python subprocess spawning via `subprocess.Popen` (the WorkerPool's internal subprocess template, NOT the meta-tooling `mma_exec.py` — that's only used by external AI agents in the meta-tooling domain; see `docs/guide_meta_boundary.md`)
- **[docs/guide_models.md](../docs/guide_models.md):** `src/models.py` is now a ~1.5KB legacy re-export shim (`Metadata = TrackMetadata` alias + `PROVIDERS` lazy `__getattr__`). Data models moved to per-system files: `src/mma.py` (TrackMetadata, Ticket, Track, WorkerContext), `src/project_files.py` (FileItem), `src/type_aliases.py` (typed boundary + per-aggregate dataclasses), `src/mcp_tool_specs.py` (typed ToolSpec registry, 45 tools), `src/result_types.py` (Result[T], ErrorInfo). `VendorCapabilities` lives in `src/ai_client.py` `#region: Vendor Capabilities`.
**Testing (NEW):**
- **[docs/guide_testing.md](../docs/guide_testing.md):** 251 test files, 5 categories, 7 conftest fixtures (`isolate_workspace`, `reset_paths`, `reset_ai_client`, `vlogger`, `kill_process_tree`, `mock_app`, `live_gui` session-scoped), Puppeteer pattern, mock provider, structural testing contract
@@ -49,7 +49,7 @@ For deep implementation details when planning or implementing tracks, consult `d
## Key Features
- **Multi-Provider Integration:** Supports Gemini, Anthropic, DeepSeek, Gemini CLI (headless), and MiniMax with seamless switching.
- **Multi-Provider Integration:** Supports Gemini, Anthropic, DeepSeek, Gemini CLI (headless), MiniMax, Qwen, Grok, and Llama (Ollama) with seamless switching.
- **4-Tier Hierarchical Multi-Model Architecture:** Orchestrates an intelligent cascade of specialized models to isolate cognitive loads and minimize token burn.
- **Tier 1 (Orchestrator):** Strategic product alignment, setup (`/conductor:setup`), and track initialization (`/conductor:newTrack`) using `gemini-3.1-pro-preview`.
- **Tier 2 (Tech Lead):** Technical oversight and track execution (`/conductor:implement`) using `gemini-3-flash-preview`. Maintains persistent context throughout implementation.
+9 -10
View File
@@ -45,7 +45,7 @@
- **src/tool_bias.py:** Implements the `ToolBiasEngine` for semantic tool description nudging and dynamic tooling strategy generation.
- **src/tool_presets.py:** Extends `ToolPresetManager` to handle nested `Tool` models, weights, and global `BiasProfile` persistence within `tool_presets.toml`.
- **src/mcp_client.py:** Implements the native tool registry (45 tools) and the `ExternalMCPManager` for orchestrating third-party Model Context Protocol servers. Provides dynamic tool discovery and validation. See [docs/guide_mcp_client.md](../docs/guide_mcp_client.md) for the complete 3-layer security model (Allowlist → Validate → Resolve) and tool inventory.
- **src/mcp_client.py:** Implements the native tool dispatch (45 tools) and the `ExternalMCPManager` for orchestrating third-party Model Context Protocol servers. The typed `ToolSpec` registry now lives in `src/mcp_tool_specs.py` (`ToolSpec` dataclass + `_REGISTRY` + `tool_names()`); `mcp_client.py` re-exports `TOOL_NAMES = mcp_tool_specs.tool_names()` for backward compat. See [docs/guide_mcp_client.md](../docs/guide_mcp_client.md) for the complete 3-layer security model (Allowlist → Validate → Resolve) and tool inventory.
- **StdioMCPServer:** Manages local MCP servers via asynchronous subprocess pipes (stdin/stdout/stderr).
- **RemoteMCPServer (SSE):** Provides a foundation for remote MCP integration via Server-Sent Events.
- **JSON-RPC 2.0 Engine:** Handles asynchronous message routing, request/response matching, and error handling for all external MCP communication.
@@ -70,7 +70,6 @@
- **src/workspace_manager.py:** Implements the `WorkspaceManager` and `WorkspaceProfile` data models for saving, loading, and merging ImGui docking layouts and window states across global and project-specific configurations.
- **src/paths.py:** Centralized module for path resolution.
- **tree-sitter / AST Parsing:** For deterministic AST parsing and automated generation of curated "Skeleton Views" and "Targeted Views" (extracting specific functions and their dependencies). Supports Python, C, and C++. Features an integrated AST cache with mtime-based invalidation to minimize re-parsing overhead. Supplemented by `SummaryCache` which provides persistent, hash-based (SHA256) caching with LRU eviction for AI-generated file summaries.
- **pydantic / dataclasses:** For defining strict state schemas (Tracks, Tickets) used in linear orchestration.
- **tomli-w:** For writing TOML configuration files.
@@ -96,7 +95,7 @@
## Architectural Patterns
- **Centralized Registry Management:** Consolidation of critical application constants (e.g., `PROVIDERS`, `AGENT_TOOL_NAMES`) into `src/models.py` as a single source of truth, eliminating redundant list definitions across the UI and Controller.
- **Per-System Registry Management:** Critical application constants live in the system that owns them: `PROVIDERS` and `DEFAULT_TOOL_CATEGORIES` in `src/ai_client.py`; `VendorCapabilities` + `_VENDOR_REGISTRY` in `src/ai_client.py` `#region: Vendor Capabilities`; the 45-tool registry in `src/mcp_tool_specs.py` (`ToolSpec` dataclass + `_REGISTRY`, re-exported as `mcp_client.TOOL_NAMES`); `TrackMetadata`/`Ticket`/`Track`/`WorkerContext` in `src/mma.py`; `Result[T]`/`ErrorInfo` in `src/result_types.py`. The legacy `src/models.py` is a ~1.5KB re-export shim only.
- **Event-Driven Metrics:** Uses a custom `EventEmitter` to decouple API lifecycle events from UI rendering, improving performance and responsiveness.
- **Synchronous Event Queue:** Employs a `SyncEventQueue` based on `queue.Queue` to manage communication between the UI and backend agents, maintaining responsiveness through a threaded execution model.
- **Synchronous IPC Approval Flow:** A specialized bridge mechanism that allows headless AI providers (like Gemini CLI) to synchronously request and receive human approval for tool calls and manual ticket transitions (Step Mode) via the GUI's REST API hooks.
@@ -117,13 +116,13 @@
## Per-Source-File Deep Dives
For the largest source files, consult the dedicated guides in `docs/`:
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md)** — `src/gui_2.py` (260KB main GUI)
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md)** — `src/ai_client.py` (116KB multi-provider LLM)
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md)** — `src/api_hooks.py` + `src/api_hook_client.py` (38KB + 31KB Hook API)
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md)** — `src/mcp_client.py` (81KB, 45 tools)
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md)** — `src/app_controller.py` (166KB headless controller)
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md)** — `src/multi_agent_conductor.py` + `src/dag_engine.py` (28KB + 10KB MMA)
- **[docs/guide_models.md](../docs/guide_models.md)** — `src/models.py` (132KB data models)
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md)** — `src/gui_2.py` (~437KB main GUI)
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md)** — `src/ai_client.py` (~166KB multi-provider LLM, 8 providers; inlined `VendorCapabilities` registry)
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md)** — `src/api_hooks.py` + `src/api_hook_client.py` (~51KB + ~38KB Hook API)
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md)** — `src/mcp_client.py` (~92KB, 45 tools; tool specs live in `src/mcp_tool_specs.py`)
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md)** — `src/app_controller.py` (~240KB headless controller)
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md)** — `src/multi_agent_conductor.py` + `src/dag_engine.py` (~30KB + ~11KB MMA)
- **[docs/guide_models.md](../docs/guide_models.md)** — `src/models.py` is now a ~1.5KB legacy re-export shim (`Metadata = TrackMetadata` alias + `PROVIDERS` lazy `__getattr__`). Data models moved to per-system files (`src/mma.py`, `src/project_files.py`, `src/type_aliases.py`, `src/mcp_tool_specs.py`, `src/result_types.py`).
- **[docs/guide_testing.md](../docs/guide_testing.md)** — Test suite architecture (251 files, 7 conftest fixtures)
ter/ImGui) and the business logic (AppController). All platform-native UI actions, such as file and directory selection, are handled exclusively within the GUI layer.
+5 -3
View File
@@ -18,11 +18,11 @@ Tracks that are unblocked and ready to start. Ordered by **dependency** (blocked
| # | Priority | Track | Status | Blocked By |
|---|---|---|---|---|
| 36 | A (sunset) | [MMA Quarantine + RAG Test Decoupling](#track-mma-quarantine--rag-test-decoupling) | spec ✓, plan pending | (none) |
| 2 | A | [Qwen, Llama & Grok Vendor Integration](#track-qwen-llama-grok-vendor-integration) | Phase 6 in progress (docs); NOT archiving — has follow-up | test_infrastructure_hardening_20260609 (merged) |
| 3 | A | [Data-Oriented Error Handling (Fleury Pattern)](#track-data-oriented-error-handling) | spec ✓, plan ✓, ready to start | test_infrastructure_hardening_20260609 (merged), qwen_llama_grok |
| 2 | A | [Qwen, Llama & Grok Vendor Integration](#track-qwen-llama-grok-vendor-integration) | **Completed** (per chronology.md; Phase 6 follow-up shipped) — row retained for cross-ref; archive candidate | test_infrastructure_hardening_20260609 (merged) |
| 3 | A | [Data-Oriented Error Handling (Fleury Pattern)](#track-data-oriented-error-handling) | **Completed** (per chronology.md) — archive candidate | test_infrastructure_hardening_20260609 (merged), qwen_llama_grok |
| 4 | A | [MCP Architecture Refactor (Sub-MCP Extraction)](#track-mcp-architecture-refactor) | spec ✓, plan pending | test_infrastructure_hardening_20260609 (merged), data_oriented_error_handling, data_structure_strengthening |
| 16 | A | [Test Sandbox Hardening](#track-test-sandbox-hardening) | spec ✓, plan ✓, ready to start | (none) |
| 17 | A | [Code Path Audit](#track-code-path-audit) | spec ✓ + plan ✓ | test_infrastructure_hardening_20260609 (merged), any_type_componentization (shipped), phase2_4_5_call_site_completion (shipped) |
| 17 | A | [Code Path Audit](#track-code-path-audit) | **Completed** (per chronology.md) — archive candidate | test_infrastructure_hardening_20260609 (merged), any_type_componentization (shipped), phase2_4_5_call_site_completion (shipped) |
| 22b | A | [Meta-Tooling Workflow Review](#track-meta-tooling-workflow-review) | spec ✓, plan ✓, parked | (none) |
| 23 | A | [Intent-Based Scripting Languages Survey](#track-intent-dsl-survey) | spec ✓, plan pending | (none) |
| 25 | B | [Fable System Prompt Review](#track-fable-review) | spec ✓, plan pending | (none) |
@@ -33,6 +33,8 @@ Tracks that are unblocked and ready to start. Ordered by **dependency** (blocked
| 7c | B | [SQLite-Granularity Inline Docs for ai_client.py](#track-sqlite-docs-ai-client) | spec ✓, plan ✓, ready to start | (none) |
| 19 | — | [Context First Message Fix](#track-context-first-message-fix) | spec TBD | (none) |
> **Stale-row cleanup (2026-07-02):** rows 2, 3, 17 marked Completed per `conductor/chronology.md` (which is the canonical status source). They are retained here as archive candidates pending a `git mv` to `conductor/archive/`. `data_structure_strengthening_20260606` (also Completed per chronology) was already dropped from this table.
### Track detail anchors
- **MMA Quarantine + RAG Test Decoupling** → `conductor/tracks/mma_quarantine_rag_test_decoupling_20260701/`
@@ -101,17 +101,17 @@ Each task creates one or more `conductor/directives/<name>/v1.md` files. The v1
- [ ] **Step 1.1: Harvest §17 banned patterns (7 directives)**
**Files to read:**
- `conductor/code_styleguides/python.md:216-409` (§17 Banned Patterns — the 7 banned patterns + §17.7 boundary exception + §17.8 enforcement + §17.9 local imports + §17.10 enforcement inventory)
- `conductor/code_styleguides/python.md:243-473` (§17 Banned Patterns — the 7 banned patterns + §17.7 boundary exception + §17.8 enforcement + §17.9 local imports + §17.10 enforcement inventory)
**Directives to create:**
1. `conductor/directives/ban_dict_any/v1.md` — source: `python.md:220-237` (§17.1). Content: the `dict[str, Any]` ban + before/after examples + the boundary exception cross-ref.
2. `conductor/directives/ban_any_type/v1.md` — source: `python.md:239-250` (§17.2). Content: the `Any` ban + before/after.
3. `conductor/directives/ban_optional_returns/v1.md` — source: `python.md:252-272` (§17.3). Content: the `Optional[T]` return ban + the `Result[T]` replacement pattern.
4. `conductor/directives/ban_hasattr_dispatch/v1.md` — source: `python.md:274-299` (§17.4). Content: the `hasattr()` for entity type dispatch ban + the typed Union alternative.
5. `conductor/directives/ban_getattr_dispatch/v1.md` — source: `python.md:301-311` (§17.5). Content: the `getattr(x, 'field', default)` for type dispatch ban.
6. `conductor/directives/ban_dict_get_on_known_fields/v1.md` — source: `python.md:313-323` (§17.6). Content: the `.get('field', default)` on a `dict[str, Any]` ban + direct attribute access alternative.
7. `conductor/directives/boundary_layer_exception/v1.md` — source: `python.md:325-327` (§17.7). Content: the ONE exception — the wire boundary (TOML/JSON parse) where `dict[str, Any]` is allowed.
1. `conductor/directives/ban_dict_any/v1.md` — source: `python.md:247-264` (§17.1). Content: the `dict[str, Any]` ban + before/after examples + the boundary exception cross-ref.
2. `conductor/directives/ban_any_type/v1.md` — source: `python.md:266-277` (§17.2). Content: the `Any` ban + before/after.
3. `conductor/directives/ban_optional_returns/v1.md` — source: `python.md:279-299` (§17.3). Content: the `Optional[T]` return ban + the `Result[T]` replacement pattern.
4. `conductor/directives/ban_hasattr_dispatch/v1.md` — source: `python.md:301-326` (§17.4). Content: the `hasattr()` for entity type dispatch ban + the typed Union alternative.
5. `conductor/directives/ban_getattr_dispatch/v1.md` — source: `python.md:328-338` (§17.5). Content: the `getattr(x, 'field', default)` for type dispatch ban.
6. `conductor/directives/ban_dict_get_on_known_fields/v1.md` — source: `python.md:340-350` (§17.6). Content: the `.get('field', default)` on a `dict[str, Any]` ban + direct attribute access alternative.
7. `conductor/directives/boundary_layer_exception/v1.md` — source: `python.md:352-354` (§17.7). Content: the ONE exception — the wire boundary (TOML/JSON parse) where `dict[str, Any]` is allowed.
**Variant header format** (use for ALL v1 files):
```markdown
@@ -131,18 +131,18 @@ will test alternative encodings (rationale-first, before/after, tabular) against
- [ ] **Step 1.2: Harvest §17.9 import/aliasing bans (3 directives)**
**Files to read:**
- `conductor/code_styleguides/python.md:336-409` (§17.9 local imports + aliasing + repeated from_dict)
- `conductor/code_styleguides/python.md:364-443` (§17.9 local imports + aliasing + repeated from_dict)
**Directives to create:**
8. `conductor/directives/ban_local_imports/v1.md` — source: `python.md:336-360` (§17.9a). Content: local imports inside functions are banned + the `try/except ImportError` exception + the vendor-SDK-warmup whitelist.
8. `conductor/directives/ban_local_imports/v1.md` — source: `python.md:364-443` (§17.9a). Content: local imports inside functions are banned + the `try/except ImportError` exception + the vendor-SDK-warmup whitelist.
9. `conductor/directives/ban_prefix_aliasing/v1.md` — source: `python.md` (§17.9b, within the 336-409 range). Content: `import X as _X` aliasing-for-naming-convenience is banned.
10. `conductor/directives/ban_repeated_from_dict/v1.md` — source: `python.md` (§17.9c, within the 336-409 range). Content: repeated `.from_dict()` calls in the same expression are banned.
- [ ] **Step 1.3: Harvest error handling conventions (2 directives)**
**Files to read:**
- `conductor/code_styleguides/error_handling.md:22-56` (the 5 patterns) + `error_handling.md:212-242` (hard rules) + `error_handling.md:274-311` (boundary types)
- `conductor/code_styleguides/error_handling.md:22-56` (the 5 patterns) + `error_handling.md:212-264` (hard rules) + `error_handling.md:284-365` (boundary types)
**Directives to create:**
@@ -153,7 +153,7 @@ will test alternative encodings (rationale-first, before/after, tabular) against
**Files to read:**
- `conductor/code_styleguides/data_oriented_design.md:176-215` (§8.5 Python Type Promotion Mandate + §8.6 Boundary Layer + §8.7 C11 framing)
- `conductor/code_styleguides/type_aliases.md:40-81` (Metadata boundary type + when to promote + when NOT to promote)
- `conductor/code_styleguides/type_aliases.md:13-87` (the canonical alias set + the extended per-aggregate dataclasses table) + `type_aliases.md:89-160` (Decision Pattern 2.5 — when to promote to its own dataclass) + `type_aliases.md:284-365` (boundary types + anti-patterns)
**Directives to create:**
@@ -166,8 +166,8 @@ will test alternative encodings (rationale-first, before/after, tabular) against
**Files to read:**
- `conductor/code_styleguides/python.md:7-21` (§1 Indentation + §2 Type Annotations)
- `conductor/code_styleguides/python.md:64-71` (§8 AI-Agent Specific Conventions — no comments, no diagnostic noise)
- `conductor/code_styleguides/python.md:185-199` (§13 Vertical Compaction)
- `conductor/code_styleguides/python.md:175-184` (§12 SDM)
- `conductor/code_styleguides/python.md:202-211` (§12 SDM)
- `conductor/code_styleguides/python.md:212-224` (§13 Vertical Compaction)
- `conductor/workflow.md:5-20` (Code Style section)
**Directives to create:**
@@ -176,14 +176,14 @@ will test alternative encodings (rationale-first, before/after, tabular) against
17. `conductor/directives/no_comments_in_body/v1.md` — source: `python.md:66` + `AGENTS.md:56`. Content: no comments in source code; documentation lives in `/docs`. Only comment on *why* when non-obvious.
18. `conductor/directives/no_diagnostic_noise/v1.md` — source: `python.md:70` + `AGENTS.md` "No Diagnostic Noise in Production" section. Content: no `sys.stderr.write("[XYZ_DIAG] ...")` in production code. Diag goes to log files or temp scripts.
19. `conductor/directives/type_hints_required/v1.md` — source: `python.md:24-31` + `product-guidelines.md:58`. Content: mandatory strict type hints for all parameters, return types, and global variables.
20. `conductor/directives/sdm_dependency_tags/v1.md` — source: `python.md:175-184` (§12) + `product-guidelines.md:59`. Content: Structural Dependency Mapping tags (`[C: ...]`, `[M: ...]`, `[U: ...]`) in docstrings for AI-assisted impact analysis.
20. `conductor/directives/sdm_dependency_tags/v1.md` — source: `python.md:202-211` (§12) + `product-guidelines.md:59`. Content: Structural Dependency Mapping tags (`[C: ...]`, `[M: ...]`, `[U: ...]`) in docstrings for AI-assisted impact analysis.
- [ ] **Step 1.6: Harvest file/taxonomy conventions (3 directives)**
**Files to read:**
- `AGENTS.md:62-76` (File Size and Naming Convention HARD RULE)
- `conductor/workflow.md:45` (File Naming Convention HARD RULE)
- `conductor/code_styleguides/python.md:205-215` (§15 Modular Controller Pattern)
- `conductor/code_styleguides/python.md:234-241` (§15 Modular Controller Pattern)
**Directives to create:**
@@ -131,7 +131,7 @@ The directives are NOT limited to the 11 files the role prompts mandate. They're
- Architecture documentation ("Thread domains are separated by...")
- Reference material ("The 45-tool inventory includes...")
**Sources to comb (non-exhaustive):**
**Sources to comb (non-exhaustive; updated 2026-07-02 to cover all 14 `conductor/code_styleguides/*.md`):**
- `AGENTS.md` — "Critical Anti-Patterns", "File Size and Naming Convention", "Session-Learned Anti-Patterns", "Process Anti-Patterns"
- `conductor/workflow.md` — "Code Style", "Guiding Principles", "Testing Requirements", "Known Pitfalls", "Process Anti-Patterns", "Tier 2 Autonomous Sandbox conventions"
- `conductor/product-guidelines.md` — "Core Value", "Code Standards & Architecture", "Data-Oriented Error Handling", "Phase 5: Heavy Curation"
@@ -145,9 +145,16 @@ The directives are NOT limited to the 11 files the role prompts mandate. They're
- `conductor/code_styleguides/rag_integration_discipline.md` — "conservative-RAG rule"
- `conductor/code_styleguides/cache_friendly_context.md` — stable-to-volatile ordering
- `conductor/code_styleguides/knowledge_artifacts.md` — the harvest pattern
- `conductor/code_styleguides/config_state_owner.md` — AppController is the single source of truth for config I/O (directive: no `models.save_config`/`models.load_config` in `src/`; enforced by `scripts/audit_no_models_config_io.py`)
- `conductor/code_styleguides/workspace_paths.md` — test-infrastructure paths must live under `./tests/` (directive: no `tmp_path_factory.mktemp`, no env vars for test paths, no CLI args for test paths; conftest is the right place)
- `conductor/code_styleguides/test_sandbox.md` — the test-sandbox hardening conventions (FR1 runtime guard, FR2 live_gui workspace fixture, FR3 sync coalescing)
- `conductor/code_styleguides/chroma_cache.md` — ChromaDB cache conventions (if directive-like content present)
- `conductor/code_styleguides/code_path_audit.md` — the per-aggregate data-pipeline audit convention
- `docs/AGENTS.md` — "Convention Enforcement"
- `docs/Readme.md` — any directive-like content in feature descriptions
> **Note (added 2026-07-02):** the original source list named 9 of the 14 styleguides. The 5 added here (`config_state_owner.md`, `workspace_paths.md`, `test_sandbox.md`, `chroma_cache.md`, `code_path_audit.md`) contain directive-like content that should be harvested. The harvester should verify each contains a harvestable directive before creating a `v1.md`; if a styleguide is purely descriptive (no imperative/ban/preference), skip it and note the skip in the harvest commit.
**Granularity resolution:** the harvest produces a candidate list. Then the question of which directives to merge (e.g., `ban_prefix_aliasing` + `no_local_imports` might become `import_hygiene`), split, or keep standalone is resolved in the harvest phase — not locked in upfront.
### The original docs stay untouched
@@ -220,7 +227,7 @@ The video analysis track is initialized as a separate conductor track (`video_an
## See Also
- `conductor/tier2/agents/tier2-autonomous.md` — the role prompt that will be updated with `warm with:`
- `conductor/tier2/agents/tier2-autonomous.md` — the role prompt that will be updated with `warm with:` (verified present 2026-07-02; 17,940 bytes)
- `conductor/tier2/commands/tier-2-auto-execute.md` — the slash command template
- `conductor/code_styleguides/python.md` §17 — the primary source of directives to harvest
- `conductor/code_styleguides/error_handling.md` — the Result[T] convention to harvest
+11 -11
View File
@@ -50,14 +50,14 @@ with open('file.py', 'w', encoding='utf-8', newline='') as f:
- **[docs/guide_mma.md](../docs/guide_mma.md):** Ticket/Track/WorkerContext data structures, DAG engine, ConductorEngine, Tier 2/3/4 lifecycles, persona application.
- **[docs/guide_simulations.md](../docs/guide_simulations.md):** `live_gui` fixture, Puppeteer pattern, mock provider, test areas by subsystem.
- **[docs/guide_testing.md](../docs/guide_testing.md):** **NEW** — 251 test files, 5 categories, 7 conftest fixtures (`isolate_workspace`, `reset_paths`, `reset_ai_client`, `vlogger`, `kill_process_tree`, `mock_app`, `live_gui` session-scoped), Puppeteer pattern, mock provider, structural testing contract.
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md):** **NEW**`src/gui_2.py` (260KB main GUI): App class lifecycle, ~90 module-level render functions, Multi-Viewport docks, panel registry, command palette integration, ImGuiScope context managers, hot reload support.
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md):** **NEW**`src/ai_client.py` (116KB): multi-provider LLM singleton (5 providers), async dispatch via `asyncio.gather`, threading.local for source tier tagging, Anthropic ephemeral caching + Gemini explicit caching, Tier 4 QA error interception.
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md):** **NEW**`src/api_hooks.py` + `src/api_hook_client.py` (38KB + 31KB): HookServer on `127.0.0.1:8999`, ApiHookClient wrapper, 8+ endpoints, Remote Confirmation Protocol via `/api/ask`.
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md):** **NEW**`src/mcp_client.py` (81KB, 45 tools): 3-layer security (Allowlist → Validate → Resolve), all native tools (File I/O, Python AST, C/C++ AST, Analysis, Network, Runtime, Beads), ExternalMCPManager (Stdio + SSE), JSON-RPC 2.0 engine.
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md):** **NEW**`src/app_controller.py` (166KB): headless orchestrator, AppState dataclass, all subsystem managers, `_predefined_callbacks`/`_gettable_fields` Hook API registries, SyncEventQueue, headless mode.
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md):** **NEW**`src/multi_agent_conductor.py` + `src/dag_engine.py` (28KB + 10KB): TrackDAG (iterative DFS cycle detection, Kahn's topological sort), ExecutionEngine (Auto-Queue / Step Mode), MultiAgentConductor + WorkerPool (concurrency 4), mma_exec.py sub-agent invocation.
- **[docs/guide_models.md](../docs/guide_models.md):** **NEW**`src/models.py` (132KB): centralized data model registry, `AGENT_TOOL_NAMES` canonical 45-tool list, `PROVIDERS` constant, `parse_plan_md` utility, validation patterns, SDM tags.
- See [docs/Readme.md](../docs/Readme.md) for the full **14-guide index** covering context curation, shaders, RAG, Beads, hot reload, personas, NERV theme, workspace profiles, and command palette.
- **[docs/guide_gui_2.md](../docs/guide_gui_2.md):** **NEW**`src/gui_2.py` (~437KB main GUI): App class lifecycle, ~90 module-level render functions, Multi-Viewport docks, panel registry, command palette integration, ImGuiScope context managers, hot reload support.
- **[docs/guide_ai_client.md](../docs/guide_ai_client.md):** **NEW**`src/ai_client.py` (~166KB): multi-provider LLM singleton (8 providers: gemini, anthropic, gemini_cli, deepseek, minimax, qwen, grok, llama), async dispatch via `asyncio.gather`, threading.local for source tier tagging, Anthropic ephemeral caching + Gemini explicit caching, Tier 4 QA error interception, inlined `VendorCapabilities` registry (moved from the deleted `src/vendor_capabilities.py`).
- **[docs/guide_api_hooks.md](../docs/guide_api_hooks.md):** **NEW**`src/api_hooks.py` + `src/api_hook_client.py` (~51KB + ~38KB): HookServer on `127.0.0.1:8999`, ApiHookClient wrapper, 8+ endpoints, Remote Confirmation Protocol via `/api/ask`.
- **[docs/guide_mcp_client.md](../docs/guide_mcp_client.md):** **NEW**`src/mcp_client.py` (~92KB, 45 tools; tool specs live in `src/mcp_tool_specs.py`): 3-layer security (Allowlist → Validate → Resolve), all native tools (File I/O, Python AST, C/C++ AST, Analysis, Network, Runtime, Beads), ExternalMCPManager (Stdio + SSE), JSON-RPC 2.0 engine.
- **[docs/guide_app_controller.md](../docs/guide_app_controller.md):** **NEW**`src/app_controller.py` (~240KB): headless orchestrator, AppState dataclass, all subsystem managers, `_predefined_callbacks`/`_gettable_fields` Hook API registries, SyncEventQueue, headless mode.
- **[docs/guide_multi_agent_conductor.md](../docs/guide_multi_agent_conductor.md):** **NEW**`src/multi_agent_conductor.py` + `src/dag_engine.py` (~30KB + ~11KB): TrackDAG (iterative DFS cycle detection, Kahn's topological sort), ExecutionEngine (Auto-Queue / Step Mode), MultiAgentConductor + WorkerPool (concurrency 4), the WorkerPool's internal `run_worker_lifecycle` subprocess template (NOT the deprecated `mma_exec.py`; see `docs/guide_meta_boundary.md`).
- **[docs/guide_models.md](../docs/guide_models.md):** **UPDATED 2026-07-02**`src/models.py` is now a ~1.5KB legacy re-export shim (`Metadata = TrackMetadata` alias + `PROVIDERS` lazy `__getattr__`). Data models moved to per-system files per `module_taxonomy_refactor_20260627`: `src/mma.py` (TrackMetadata, Ticket, Track, WorkerContext), `src/project_files.py` (FileItem), `src/type_aliases.py` (typed boundary + per-aggregate dataclasses), `src/mcp_tool_specs.py` (typed ToolSpec registry, 45 tools), `src/result_types.py` (Result[T], ErrorInfo). `VendorCapabilities` lives in `src/ai_client.py`.
- See [docs/Readme.md](../docs/Readme.md) for the full **41-guide index** covering context curation, shaders, RAG, Beads, hot reload, personas, NERV theme, workspace profiles, and command palette.
## Task Workflow
@@ -81,14 +81,14 @@ All tasks follow a strict lifecycle:
- **Pre-Delegation Checkpoint:** Before spawning a worker for dangerous or non-trivial changes, ensure your current progress is staged (`git add .`) or committed. This prevents losing iterations if a sub-agent incorrectly uses `git restore`.
- **Zero-Assertion Ban:** You MUST NOT write tests that contain only `pass` or lack meaningful assertions. A test is only valid if it contains assertions that explicitly test the behavioral change and verify the failure condition.
- **Code Style:** ALWAYS explicitly mention "Use exactly 1-space indentation for Python code" when prompting a sub-agent.
- **Delegate Test Creation:** Do NOT write test code directly. Spawn a Tier 3 Worker (`python scripts/mma_exec.py --role tier3-worker "[PROMPT]"`) with a **surgical prompt** specifying WHERE (file:line range), WHAT (test to create), HOW (which assertions/fixtures to use), and SAFETY (thread constraints if applicable). Example: `"Write tests in tests/test_cost_tracker.py for cost_tracker.py:estimate_cost(). Test all model patterns in MODEL_PRICING dict. Assert unknown model returns 0. Use 1-space indentation."` (If repeating due to failures, pass `--failure-count X` to switch to a more capable model).
- **Delegate Test Creation:** Do NOT write test code directly. Spawn a Tier 3 Worker via the **OpenCode Task tool** with `subagent_type: "tier3-worker"` and a **surgical prompt** specifying WHERE (file:line range), WHAT (test to create), HOW (which assertions/fixtures to use), and SAFETY (thread constraints if applicable). Example: `"Write tests in tests/test_cost_tracker.py for cost_tracker.py:estimate_cost(). Test all model patterns in MODEL_PRICING dict. Assert unknown model returns 0. Use 1-space indentation."` (If repeating due to failures, set the subagent's `failure_count` higher to switch to a more capable model.) **Note:** the legacy `python scripts/mma_exec.py --role tier3-worker` invocation is DEPRECATED (see §"Conductor Token Firewalling" below); use the OpenCode Task tool instead.
- Take the code generated by the Worker and apply it.
- **CRITICAL:** Run the tests and confirm that they fail as expected. This is the "Red" phase of TDD. Do not proceed until you have failing tests.
5. **Implement to Pass Tests (Green Phase):**
- **Pre-Delegation Checkpoint:** Ensure current progress is staged or committed before delegating.
- **Code Style:** ALWAYS explicitly mention "Use exactly 1-space indentation for Python code" when prompting a sub-agent.
- **Delegate Implementation:** Do NOT write the implementation code directly. Spawn a Tier 3 Worker (`python scripts/mma_exec.py --role tier3-worker "[PROMPT]"`) with a **surgical prompt** specifying WHERE (file:line range to modify), WHAT (the specific change), HOW (which API calls, data structures, or patterns to use), and SAFETY (thread-safety constraints). Example: `"In gui_2.py _render_mma_dashboard (lines 2685-2699), extend the token usage table from 3 to 5 columns. Add 'Model' and 'Est. Cost' using imgui.table_setup_column(). Call cost_tracker.estimate_cost(model, input_tokens, output_tokens). Use 1-space indentation."` (If repeating due to failures, pass `--failure-count X` to switch to a more capable model).
- **Delegate Implementation:** Do NOT write the implementation code directly. Spawn a Tier 3 Worker via the **OpenCode Task tool** (`subagent_type: "tier3-worker"`) with a **surgical prompt** specifying WHERE (file:line range to modify), WHAT (the specific change), HOW (which API calls, data structures, or patterns to use), and SAFETY (thread-safety constraints). Example: `"In gui_2.py _render_mma_dashboard (lines 2685-2699), extend the token usage table from 3 to 5 columns. Add 'Model' and 'Est. Cost' using imgui.table_setup_column(). Call cost_tracker.estimate_cost(model, input_tokens, output_tokens). Use 1-space indentation."` (If repeating due to failures, set `failure_count` higher to switch to a more capable model.) **Note:** the legacy `python scripts/mma_exec.py --role tier3-worker` invocation is DEPRECATED; use the OpenCode Task tool.
- Take the code generated by the Worker and apply it.
- Run the test suite again and confirm that all tests now pass. This is the "Green" phase.
@@ -151,7 +151,7 @@ All tasks follow a strict lifecycle:
- **CRITICAL:** When verifying changes, **do not run the full suite (`pytest tests/`)**. Instead, run tests in small, targeted batches (maximum 4 test files at a time). Only use long timeouts (`--timeout=60` or `--timeout=120`) if the specific tests in the batch are known to be slow (e.g., simulation tests).
- **Example Announcement:** "I will now run the automated test suite to verify the phase. **Command:** `uv run pytest tests/test_specific_feature.py`"
- Execute the announced command.
- If tests fail with significant output (e.g., a large traceback), **DO NOT** attempt to read the raw `stderr` directly into your context. Instead, pipe the output to a log file and **spawn a Tier 4 QA Agent (`python scripts/mma_exec.py --role tier4-qa "[PROMPT]"`)** to summarize the failure.
- If tests fail with significant output (e.g., a large traceback), **DO NOT** attempt to read the raw `stderr` directly into your context. Instead, pipe the output to a log file and **spawn a Tier 4 QA Agent via the OpenCode Task tool (`subagent_type: "tier4-qa"`)** with the error output + an explicit instruction "DO NOT fix — provide root cause analysis only". (The legacy `python scripts/mma_exec.py --role tier4-qa` invocation is DEPRECATED; use the OpenCode Task tool.)
- You **must** inform the user and begin debugging using the QA Agent's summary. You may attempt to propose a fix a **maximum of two times**. If the tests still fail after your second proposed fix, you **must stop**, report the persistent failure, and ask the user for guidance.
4. **Execute Automated API Hook Verification:**
+2 -2
View File
@@ -34,7 +34,7 @@ The canonical mandate is in [`conductor/code_styleguides/data_oriented_design.md
4. **The enforcement audit scripts** — the project-level enforcement set:
- `scripts/audit_weak_types.py --strict` — flags `dict[str, Any]`, `Any`, anonymous tuples
- `scripts/audit_optional_returns.py --strict` — flags `Optional[T]` return types in ALL `src/*.py` (post-2026-06-27 successor to `audit_optional_in_3_files.py`)
- `scripts/audit_optional_in_3_files.py --strict` — flags `Optional[T]` return types in the 4 baseline refactored files (`src/mcp_client.py`, `src/ai_client.py`, `src/rag_engine.py`, plus one more). An all-`src/*.py` successor (`audit_optional_returns.py`) is referenced in older planning docs but is NOT yet built — the live script today is `audit_optional_in_3_files.py`.
- `scripts/audit_exception_handling.py --strict` — the data-oriented error handling convention
- `scripts/audit_main_thread_imports.py` — always strict; the import graph gate
- `scripts/audit_no_models_config_io.py` — the config-I/O ownership gate
@@ -45,7 +45,7 @@ The canonical mandate is in [`conductor/code_styleguides/data_oriented_design.md
```bash
# Run before claiming "done"
uv run python scripts/audit_weak_types.py
uv run python scripts/audit_optional_returns.py
uv run python scripts/audit_optional_in_3_files.py
uv run python scripts/audit_exception_handling.py
uv run python scripts/audit_main_thread_imports.py
uv run python scripts/audit_no_models_config_io.py
+3 -3
View File
@@ -31,12 +31,12 @@ This documentation suite provides comprehensive technical reference for the Manu
| [Testing](guide_testing.md) | 322 test files, 5 test categories (unit, integration, live_gui, perf, simulation), 7 conftest fixtures (`isolate_workspace`, `reset_paths`, `reset_ai_client`, `vlogger`, `kill_process_tree`, `mock_app`, `live_gui` session-scoped), Hook API testing pattern, Puppeteer pattern for MMA simulation, mock provider strategy, opt-in clean install test, opt-in docker test, coverage targets, anti-patterns (no arbitrary core mocking, artifact isolation to `tests/artifacts/`), early-render C-level crash pattern (`_ini_capture_ready` defer-not-catch for `imgui.save_ini_settings_to_memory`), live_gui authoring contract (wait-for-ready pattern over `time.sleep`, narrow test paths over kitchen-sink `render_main_interface` mocks), test-ordering sensitivity (session-scoped fixture) |
| [Themes](guide_themes.md) | TOML-based theming system: file layout (`themes/<name>.toml` global + `project_themes.toml` per-project), schema (`syntax_palette` + `[colors]` table with `imgui.Col_` snake_case keys), 4-syntax-palette upstream limit (`imgui-bundle` ships `dark`/`light`/`mariana`/`retro_blue` only), built-in vs TOML palette dispatch, `load_themes_from_disk` / `get_syntax_palette_for_theme` / `apply_syntax_palette` public API, hot-reload behavior, color-callable convention (`C_LBL()` / `C_VAL()` for theme-aware helpers) |
| [GUI Main](guide_gui_2.md) | `src/gui_2.py` reference: App class lifecycle, ~90 module-level render functions (UI Delegation Pattern), immgui immediate-mode rendering, Multi-Viewport docks, panel registry, command palette integration, ImGuiScope context managers, hot reload support, key bindings (Ctrl+Shift+P, Ctrl+Alt+R, Ctrl+Z/Y), `_capture_workspace_profile` defer-not-catch pattern (line 813-841, `_ini_capture_ready` flag for `imgui.save_ini_settings_to_memory`), theme color-callable pattern (e.g. `DIR_COLORS`/`KIND_COLORS` dicts store `C_VAL` not `C_VAL()` and are called at use site), `__getattr__` ui_ attrs hasattr-guard (bcdc26d0 silent-None fix), `_LazyModule` / `_FiledialogStub` lazy import proxies, `startup_profiler` + `render_warmup_status_indicator` integration, native `_detect_refresh_rate_win32` (ctypes.EnumDisplaySettingsW) |
| [AI Client](guide_ai_client.md) | `src/ai_client.py` reference: multi-provider LLM singleton (5 providers: Gemini, Anthropic, DeepSeek, MiniMax, Gemini CLI), async dispatch with `asyncio.gather`, threading.local for source tier tagging, context caching (Anthropic ephemeral + Gemini explicit), system prompt assembly, error interception for Tier 4 QA |
| [AI Client](guide_ai_client.md) | `src/ai_client.py` reference: multi-provider LLM singleton (8 providers: gemini, anthropic, gemini_cli, deepseek, minimax, qwen, grok, llama), async dispatch with `asyncio.gather`, threading.local for source tier tagging, context caching (Anthropic ephemeral + Gemini explicit), system prompt assembly, error interception for Tier 4 QA, inlined `VendorCapabilities` registry (moved from the deleted `src/vendor_capabilities.py`), `Result[str]`-returning `send()` public API |
| [API Hooks](guide_api_hooks.md) | `src/api_hooks.py` + `src/api_hook_client.py` reference: HookServer on `127.0.0.1:8999`, ApiHookClient Python wrapper, 8+ endpoints (`/status`, `/api/gui`, `/api/ask`, `/api/gui/mma_status`, `/api/performance`, `/api/comms`, `/api/diagnostics`), Remote Confirmation Protocol via `/api/ask` (synchronous blocking HITL), `custom_callback` action for invoking any registered App method |
| [MCP Client](guide_mcp_client.md) | `src/mcp_client.py` reference: 45 native tools (File I/O, Python AST, C/C++ AST, Analysis, Network, Runtime, Beads), 3-layer security model (Allowlist Construction, Path Validation, Resolution Gate), `dispatch()`/`async_dispatch()` entry points, ExternalMCPManager for external MCP servers (Stdio + SSE), JSON-RPC 2.0 engine, public API, configuration |
| [App Controller](guide_app_controller.md) | `src/app_controller.py` reference: headless orchestrator owning AppState and all subsystem managers (PresetManager, PersonaManager, ContextPresetManager, ToolPresetManager, ToolBiasEngine, RAGEngine, HistoryManager, WorkspaceManager, HookServer, HotReloader, PathManager), `_predefined_callbacks` and `_gettable_fields` registries for Hook API, SyncEventQueue bridge, preset/persona/context coordination, headless mode |
| [MMA Engine](guide_multi_agent_conductor.md) | `src/multi_agent_conductor.py` + `src/dag_engine.py` reference: TrackDAG with cycle detection (iterative DFS) and topological sort (Kahn's variant), ExecutionEngine with Auto-Queue / Step Mode state machine, MultiAgentConductor with WorkerPool (configurable concurrency, default 4), mma_exec.py sub-agent invocation for Token Firewall, parse_plan_md utility, Beads mode delegation |
| [Data Models](guide_models.md) | `src/models.py` reference: centralized data model registry using pydantic + dataclasses, model categories (Core, AI, Preset, Persona, Context, MMA, UI State, Logging, Hook, Workspace, RAG), `AGENT_TOOL_NAMES` canonical 45-tool list, `PROVIDERS` constant, `parse_plan_md` utility, validation patterns, SDM tags, serialization strategies (TOML, JSON-L) |
| [MMA Engine](guide_multi_agent_conductor.md) | `src/multi_agent_conductor.py` + `src/dag_engine.py` reference: TrackDAG with cycle detection (iterative DFS) and topological sort (Kahn's variant), ExecutionEngine with Auto-Queue / Step Mode state machine, MultiAgentConductor with WorkerPool (configurable concurrency, default 4), the WorkerPool's internal `run_worker_lifecycle` subprocess template (NOT the meta-tooling `mma_exec.py` — that's deprecated; see `guide_meta_boundary.md`), parse_plan_md utility (now in `src/mma.py`), Beads mode delegation |
| [Data Models](guide_models.md) | `src/models.py` is now a ~1.5KB legacy re-export shim (`Metadata = TrackMetadata` alias + `PROVIDERS` lazy `__getattr__`). Data models moved to per-system files per `module_taxonomy_refactor_20260627`: `src/mma.py` (TrackMetadata, Ticket, Track, WorkerContext), `src/project_files.py` (FileItem), `src/type_aliases.py` (typed boundary + per-aggregate dataclasses: Metadata, CommsLogEntry, HistoryMessage, ToolDefinition, SessionInsights, DiscussionSettings, CustomSlice, MMAUsageStats, ProviderPayload, UIPanelConfig, PathInfo, FileItemsDiff, JsonPrimitive/JsonValue), `src/mcp_tool_specs.py` (typed ToolSpec registry, 45 tools), `src/result_types.py` (Result[T], ErrorInfo, ErrorKind). `VendorCapabilities` lives in `src/ai_client.py` `#region: Vendor Capabilities`. `PROVIDERS` constant in `src/ai_client.py` (8 providers: gemini, anthropic, gemini_cli, deepseek, minimax, qwen, grok, llama). |
| [Discussions](guide_discussions.md) | The Discussion system: 23-operation matrix A1-A7 (per-entry) + B1-B11 (discussion-level) + C1-C5 (undo/redo), Take naming convention (`<base>_take_<n>`), branching at any entry (`project_manager.branch_discussion`), promotion to top-level (`project_manager.promote_take`), user-managed role list (`app.disc_roles`), per-role filter linked to MMA persona focus, `_disc_entries_lock` thread-safety contract, Hook API session endpoints |
| [State Lifecycle](guide_state_lifecycle.md) | Undo/redo via `HistoryManager` + `UISnapshot` (13 captured fields, 100-snapshot capacity, debounced change detection at render frame), reset flow (`_handle_reset_session` — clears 30+ fields, replaces project, preserves `active_project_path` per the 2026-06-08 regression fix), `App.__getattr__`/`__setattr__` state delegation to Controller, 8-thread io_pool with 11 lock-protected regions (per `IO_POOL_MAX_WORKERS = 8` in `src/io_pool.py:20`; bumped 4→8 in 4a338486 on 2026-06-06), hot-reload integration |
| [Context Aggregation](guide_context_aggregation.md) | The `aggregate.py` (518-line) pipeline: 3 aggregation strategies (`auto`/`summarize`/`full`), 7 per-file view modes (`full`/`summary`/`skeleton`/`outline`/`masked`/`custom`/`none`), full `FileItem` schema (9 fields + `__post_init__` normalizer), `ContextPreset` schema and `ContextPresetManager`, Tier 3 worker variant (`build_tier3_context` with FuzzyAnchor re-resolution and focus-file handling), `force_full`/`auto_aggregate` short-circuits, output file numbering, cache strategy (static prefix + dynamic history) |
+1 -1
View File
@@ -77,7 +77,7 @@ A `ContextPreset` is a named, persisted set of `FileItem`s. Both persist in the
**The shape rule.** Curation is per-file, per-discussion, structural. Edited at the Structural File Editor. Persisted in TOML. The file's `FileItem` is the single source of truth for "how do I render this file in the AI's context."
**See:** `docs/guide_context_curation.md`; `src/models.py:510-559` (FileItem schema); `src/context_presets.py` (ContextPresetManager).
**See:** `docs/guide_context_curation.md`; `src/project_files.py` (FileItem dataclass, moved out of `src/models.py` per `module_taxonomy_refactor_20260627`); `src/context_presets.py` (ContextPresetManager).
---
+17 -14
View File
@@ -6,7 +6,7 @@
## Overview
`src/ai_client.py` (~116KB) is the **unified LLM client** for 8 providers. It abstracts the differences between providers (Gemini, Anthropic, DeepSeek, MiniMax, Gemini CLI, Qwen, Grok, Llama) behind a single `send()` function.
`src/ai_client.py` (~166KB) is the **unified LLM client** for 8 providers. It abstracts the differences between providers (Gemini, Anthropic, DeepSeek, MiniMax, Gemini CLI, Qwen, Grok, Llama) behind a single `send()` function.
The module is a **stateful singleton** — all provider state is held in module-level globals. There is no class wrapping; the module itself is the abstraction layer.
@@ -21,7 +21,7 @@ The OpenAI-compatible vendors all call the shared helper in `src/openai_compatib
## Module-Level Imports
> **Important:** The 5 provider SDKs are **NOT** imported at module level. `import google.genai`, `import anthropic`, `import openai`, and `import fastapi` are heavy (~430-955ms each on cold load) and are now obtained via `src.module_loader._require_warmed("google.genai")` and similar calls, after the `WarmupManager` has loaded them in the background. The module-level globals you see in the State section (`_gemini_client`, `_anthropic_client`, etc.) are typed as `Optional` because they're populated by `_require_warmed()` on first use, not at import time.
> **Important:** The provider SDKs are **NOT** imported at module level. `import google.genai`, `import anthropic`, `import openai`, `import dashscope`, and `import fastapi` are heavy (~430-955ms each on cold load) and are now obtained via `src.module_loader._require_warmed("google.genai")` and similar calls, after the `WarmupManager` has loaded them in the background. The module-level globals you see in the State section (`_gemini_client`, `_anthropic_client`, etc.) are typed as `Optional` because they're populated by `_require_warmed()` on first use, not at import time. (Updated 2026-07-02: there are 8 providers, not 5 — the original "5 SDKs" count predated the qwen/grok/llama additions.)
This change was part of the 2026-06-06 `startup_speedup_20260606` track. Before: `import src.ai_client` took ~1800ms. After: ~161ms. The remaining cost is the bare module skeleton.
@@ -52,7 +52,7 @@ All state is module-level globals. The most important:
| Variable | Type | Purpose |
|---|---|---|
| `_provider: str` | `"gemini" \| "anthropic" \| "deepseek" \| "minimax" \| "gemini_cli"` | Active provider |
| `_provider: str` | `"gemini" \| "anthropic" \| "gemini_cli" \| "deepseek" \| "minimax" \| "qwen" \| "grok" \| "llama"` | Active provider (8 total) |
| `_model: str` | `str` | Active model name |
| `_temperature: float` | `0.0` | Sampling temperature |
| `_top_p: float` | `1.0` | Nucleus sampling |
@@ -106,10 +106,10 @@ def send(
stream_callback: Optional[Callable] = None,
patch_callback: Optional[Callable] = None,
rag_engine: Optional[Any] = None,
) -> str:
) -> Result[str]:
```
Returns the model's response as a string. All provider calls go through here.
Returns the model's response as a `Result[str, ErrorInfo]` (the data-oriented error type from `src/result_types.py`). Check `result.ok` for success; on failure, `result.errors` holds `ErrorInfo` instances with classified `ErrorKind`. All provider calls go through here.
**Parameters:**
- `md_content` — the system prompt + context (markdown)
@@ -129,10 +129,13 @@ Returns the model's response as a string. All provider calls go through here.
```python
from src import ai_client
ai_client.set_provider("gemini", "gemini-3-flash-preview")
ai_client.set_provider("anthropic", "claude-3-5-sonnet-latest")
ai_client.set_provider("deepseek", "deepseek-chat")
ai_client.set_provider("minimax", "grok-2-latest")
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
ai_client.set_provider("anthropic", "claude-sonnet-4-5-20250929")
ai_client.set_provider("deepseek", "deepseek-v3")
ai_client.set_provider("minimax", "MiniMax-M2")
ai_client.set_provider("gemini_cli", "gemini-2.5-flash")
ai_client.set_provider("qwen", "qwen-plus")
ai_client.set_provider("grok", "grok-2")
ai_client.set_provider("llama", "llama-3.1-8b-instant")
```
### Parameter Setters
@@ -507,7 +510,7 @@ print(r.data)
- **[guide_architecture.md](guide_architecture.md#ai-client-multi-provider-architecture)** — Threading model and provider dispatch
- **[guide_mma.md](guide_mma.md#tier-3-worker-lifecycle-run_worker_lifecycle)** — How Tier 3 workers use ai_client
- **[guide_mcp_client.md](guide_mcp_client.md)** — The 46 tools that ai_client can invoke (canonical list in `models.AGENT_TOOL_NAMES`)
- **[guide_mcp_client.md](guide_mcp_client.md)** — The 45 MCP tools (plus the PowerShell shell tool defined here in ai_client.py) that ai_client can invoke (canonical list in `models.AGENT_TOOL_NAMES`)
- **[guide_rag.md](guide_rag.md)** — RAG engine integration via `rag_engine` parameter
- **[guide_state_lifecycle.md](guide_state_lifecycle.md)** — The per-provider history globals (`_anthropic_history`, etc.) are managed here; their locking and reset behavior is documented
- **[guide_context_aggregation.md](guide_context_aggregation.md)** — The `aggregate.py` pipeline that produces the markdown the AI client sends
@@ -556,7 +559,7 @@ class OpenAICompatibleRequest:
def send_openai_compatible(
client: Any, # openai.OpenAI client with vendor-specific base_url + auth
request: OpenAICompatibleRequest,
*, capabilities: "VendorCapabilities", # from src/vendor_capabilities.py
*, capabilities: "VendorCapabilities", # from src/ai_client.py #region: Vendor Capabilities
) -> NormalizedResponse:
```
@@ -661,7 +664,7 @@ For OpenRouter, custom URLs, and other cloud Llama endpoints, the existing OpenA
### V2 Capability Matrix (Phase 4)
Added 2026-06-11. The `VendorCapabilities` dataclass in `src/vendor_capabilities.py` now has 12 v2 fields beyond the original 7 v1 fields:
Added 2026-06-11. The `VendorCapabilities` dataclass (now inlined in `src/ai_client.py` `#region: Vendor Capabilities`; moved from the deleted `src/vendor_capabilities.py` per `module_taxonomy_refactor_20260627` Phase 2.1) has 12 v2 fields beyond the original 7 v1 fields:
**V1 fields** (unchanged):
- `vision`, `tool_calling`, `caching`, `streaming`, `model_discovery`, `context_window`, `cost_tracking`
@@ -686,9 +689,9 @@ Added 2026-06-11. The `VendorCapabilities` dataclass in `src/vendor_capabilities
### PROVIDERS Location (Phase 2)
The `PROVIDERS` list moved from `src/models.py` to `src/ai_client.py:56` per the AGENTS.md HARD RULE (no new `src/<thing>.py` files). A PEP 562 `__getattr__` re-export in `src/models.py:261` maintains backward compatibility (lazy import; breaks the circular dependency where `src/ai_client.py` imports `ToolPreset` from `src/models.py`).
The `PROVIDERS` list moved from `src/models.py` to `src/ai_client.py:62` per the AGENTS.md HARD RULE (no new `src/<thing>.py` files; system code lives in the system module). A PEP 562 `__getattr__` re-export in `src/models.py:31` maintains backward compatibility (lazy import; breaks the circular dependency where `src/ai_client.py` imports `ToolPreset` from `src/tool_presets.py` and `src/models.py` is now a thin shim).
Audit: `scripts/audit_providers_source_of_truth.py` fails if `PROVIDERS` is declared in `src/models.py`.
Audit: `scripts/audit_providers_source_of_truth.py` fails if `PROVIDERS` is declared as a literal in `src/models.py`.
### Tests
+5 -5
View File
@@ -87,7 +87,7 @@ The `auto` strategy is the *only* one that respects `config.project.summary_only
## The FileItem Schema (Full)
`src/models.py:510-559 FileItem` is the **per-file curation memory** that nagent_review identified as Manual Slop's strongest dimension. The dataclass has 9 mutable fields + a `__post_init__` normalizer:
`src/project_files.py:FileItem` is the **per-file curation memory** that nagent_review identified as Manual Slop's strongest dimension (moved out of `src/models.py` per `module_taxonomy_refactor_20260627`). The dataclass has 9 mutable fields + a `__post_init__` normalizer:
```python
@dataclass
@@ -139,7 +139,7 @@ Multiple slices in a file are joined with `\n\n`.
## The ContextPreset Schema
`src/models.py:909-937 ContextPreset` is a *named, persisted set* of `FileItem`s — a reusable "context composition":
`src/context_presets.py:ContextPreset` is a *named, persisted set* of `FileItem`s — a reusable "context composition" (moved out of `src/models.py`; see [guide_models.md](guide_models.md) for the current per-system file map):
```python
@dataclass
@@ -381,10 +381,10 @@ For very large codebases (1000+ files), the bottleneck is the tree-sitter parsin
## Cross-References
- **The pipeline source:** `src/aggregate.py` (518 lines)
- **FileItem schema:** `src/models.py:510-559 FileItem`
- **ContextPreset schema:** `src/models.py:909-937 ContextPreset`
- **FileItem schema:** `src/project_files.py:FileItem` (moved out of `src/models.py`)
- **ContextPreset schema:** `src/context_presets.py:ContextPreset` (moved out of `src/models.py`)
- **ContextPresetManager:** `src/context_presets.py` (30 lines)
- **AI client consumption:** `src/ai_client.py:_send_<provider>` × 5, see `guide_ai_client.md`
- **AI client consumption:** `src/ai_client.py:_send_<provider>` × 8 (gemini, anthropic, gemini_cli, deepseek, minimax, qwen, grok, llama), see `guide_ai_client.md`
- **Tier 3 worker consumption:** `src/multi_agent_conductor.py:run_worker_lifecycle`, see `guide_multi_agent_conductor.md`
- **Per-file curation features:** `guide_context_curation.md` (Fuzzy Anchors, AST Inspector, Granular AST Control)
- **Cache strategy:** `guide_architecture.md §"Cache Hit Strategy"`, `guide_ai_client.md §"Caching"`
+1 -1
View File
@@ -319,7 +319,7 @@ This is a UX consolidation, not a data model change. The underlying `ast_mask: d
- **[guide_context_aggregation.md](guide_context_aggregation.md)** — The full `aggregate.py` pipeline that consumes the FileItem schema documented here. Includes the 7 `view_mode` values (`full`, `summary`, `skeleton`, `outline`, `masked`, `none`, `custom`) and the 3 `aggregation_strategy` values (`auto`, `summarize`, `full`)
- **[guide_context_presets.md](guide_context_aggregation.md)** — now part of the Context Aggregation guide — The `ContextPreset` schema (named, persisted set of FileItems)
- **[guide_models.md](guide_models.md)** — Full FileItem and ContextPreset dataclass definitions at `src/models.py:510` and `src/models.py:909`
- **[guide_models.md](guide_models.md)** — Full FileItem and ContextPreset dataclass definitions (now in `src/project_files.py` and `src/context_presets.py` respectively; moved out of `src/models.py` per `module_taxonomy_refactor_20260627`)
- **[guide_architecture.md](guide_architecture.md)** — How the FileItem list is built up in `App.init_state` and how the aggregation pipeline consumes it
- **[conductor/tracks/nagent_review_20260608/report.md §6](../conductor/tracks/nagent_review_20260608/report.md)** — Deep-dive on per-file memory; compares Manual Slop's curation dimension (this guide) to nagent's conversation-log dimension
- **[conductor/tracks/nagent_review_20260608/nagent_takeaways_20260608.md §4](../conductor/tracks/nagent_review_20260608/nagent_takeaways_20260608.md)** — Actionable: add a `file_id: st_dev:st_ino` field to FileItem for rename-safe identity
+2 -2
View File
@@ -28,7 +28,7 @@ This is a *deliberate* design choice. Manual Slop treats the discussion as user-
### The Entry Dict
The smallest unit of a discussion is the **entry**, a `dict[str, Any]` with this shape (`src/models.py:parse_history_entries` builds it; `src/gui_2.py:render_discussion_entry` reads it):
The smallest unit of a discussion is the **entry**, a `dict[str, Any]` with this shape (`parse_history_entries` builds it — moved out of `src/models.py` to `src/mma.py` per `module_taxonomy_refactor_20260627`; `src/gui_2.py:render_discussion_entry` reads it):
| Field | Type | Source | Purpose |
|---|---|---|---|
@@ -343,7 +343,7 @@ The POST endpoint allows external automation to *replace* the entire discussion.
## Cross-References
- **Discussion data model:** `src/models.py:196 parse_history_entries`, `src/models.py:909 ContextPreset`, `src/models.py:510 FileItem`
- **Discussion data model:** `parse_history_entries` (moved out of `src/models.py` to `src/mma.py`), `ContextPreset` (now in `src/context_presets.py`), `FileItem` (now in `src/project_files.py`)
- **Discussion persistence:** `src/project_manager.py:429 branch_discussion`, `src/project_manager.py:447 promote_take`, `src/project_manager.py:396 calculate_track_progress`
- **Discussion switching/management:** `src/app_controller.py:3199 _switch_discussion`, `src/app_controller.py:3225 _flush_disc_entries_to_project`, `src/app_controller.py:3286 _handle_reset_session`, `src/app_controller.py:3357 _handle_compress_discussion`, `src/app_controller.py:3503 _branch_discussion`, `src/app_controller.py:3521 _rename_discussion`, `src/app_controller.py:3537 _delete_discussion`
- **GUI render functions:** `src/gui_2.py:175 truncate_entries`, `src/gui_2.py:735 _take_snapshot`, `src/gui_2.py:754 _apply_snapshot`, `src/gui_2.py:3770 render_discussion_entry`, `src/gui_2.py:4227 render_discussion_entries`, `src/gui_2.py:4239 render_discussion_entry_controls`, `src/gui_2.py:4317 render_discussion_roles`, `src/gui_2.py:4330 render_discussion_selector`
+3 -3
View File
@@ -6,7 +6,7 @@
## Overview
`src/gui_2.py` is the **largest file** in the project (~260KB, ~5400 lines). It contains the `App` class — the main ImGui application orchestrator — and ~90 module-level render functions that draw the GUI.
`src/gui_2.py` is the **largest file** in the project (~437KB, ~8970 lines as of 2026-07-02; was ~260KB / ~5400 lines when this guide was first written — extended by the 2026-07 hot-reload and event-sourcing refactors). It contains the `App` class — the main ImGui application orchestrator — and ~90 module-level render functions that draw the GUI.
The file is divided into:
@@ -100,7 +100,7 @@ The App holds dozens of state attributes. The most important:
| `self._tool_log` | `deque` | Tool call log |
| `show_command_palette` | `bool` | Command palette visibility |
### Render Entry Point: `_gui_func` (line 754)
### Render Entry Point: `_gui_func` (line 1062)
The main render loop, called by imgui-bundle's Hello ImGui runner every frame:
@@ -130,7 +130,7 @@ def _gui_func(self) -> None:
render_error_tint(self)
```
### `render_main_interface` (line 1259)
### `render_main_interface` (line 1898)
The "main content" renderer. Iterates over the major panels and calls the right render function for each:
+6 -2
View File
@@ -17,7 +17,9 @@ Tier 4: QA — stateless error analysis, no fixes
---
## Data Structures (`models.py`)
## Data Structures (`src/mma.py`)
> **Note (updated 2026-07-02):** the MMA data structures (`Ticket`, `Track`, `WorkerContext`, `TrackMetadata`, `TicketStatus`, `TicketPriority`, `TrackCheckpoint`) moved out of `src/models.py` into `src/mma.py` per `module_taxonomy_refactor_20260627`. The old heading "models.py" is retained as a section anchor for readers following older references; the live location is `src/mma.py`.
### Ticket
@@ -632,7 +634,9 @@ class SubConversationResult:
class SubConversationRunner:
async def spawn(self, prompt: str, *, allowed_tools: list[str] = None, ...) -> SubConversationResult:
# Reuses mma_exec.py as the subprocess template
# Would reuse the WorkerPool's internal subprocess template (NOT the
# deprecated mma_exec.py — see docs/guide_meta_boundary.md for the
# meta-tooling vs application domain distinction).
# Returns the child's <nagent-response> content + token usage
...
```
+76 -537
View File
@@ -1,4 +1,4 @@
# `src/models.py` — Data Models
# `src/models.py` — Legacy Re-Export Shim
[Top](../Readme.md) | [Architecture](guide_architecture.md) | [MMA](guide_mma.md) | [App Controller](guide_app_controller.md)
@@ -6,591 +6,130 @@
## Overview
`src/models.py` (~132KB) is the **centralized data model registry**. It defines every data structure used across the app — Tickets, Tracks, Personas, Presets, Discussion entries, Context files, etc. — using `pydantic` and `dataclasses`.
`src/models.py` is now a **~1.5KB legacy re-export shim**. It is NOT a data model registry anymore.
The file exists to **eliminate redundant model definitions** scattered across modules. It also serves as the single source of truth for serialization (TOML, JSON-L, Markdown).
The dataclass definitions, `DEFAULT_TOOL_CATEGORIES`, the `__getattr__` shim, and the Pydantic proxies were moved out per:
- `module_taxonomy_refactor_20260627` Phase 5 (reduce to Pydantic proxies)
- `post_module_taxonomy_de_cruft_20260627` Phases 2-4 (de-cruft removals)
---
## Design Principles
1. **One place to look for any data structure**: If you need to know what fields a `Ticket` has, look here.
2. **Strict types**: `pydantic` for fields with validation, `dataclasses` for internal structures.
3. **No business logic**: Models are pure data. Methods like `to_toml()` are allowed; methods like `execute()` are not.
4. **SDM tags**: Every model has `[C: ...]` (callers) and `[M: ...]` (mutators) tags in docstrings for AI-assisted impact analysis.
---
## Model Categories
The file is organized into regions:
**Remaining content:**
- The legacy `Metadata = TrackMetadata` alias — tests that import `from src.models import Metadata` expecting the dataclass still resolve to the same object. The `Metadata` TYPE ALIAS (from `src.type_aliases`) is the boundary wire type; legacy consumers wanting the dataclass should migrate to `from src.mma import TrackMetadata`.
- The `PROVIDERS` lazy `__getattr__` (loads from `src.ai_client` on first access; required to break a startup-speedup circular import).
```python
#region: Core Models
#endregion: Core Models
from src.mma import TrackMetadata
#region: AI Models
#endregion: AI Models
Metadata = TrackMetadata # legacy class name re-export
#region: Preset Models
#endregion: Preset Models
#region: Persona Models
#endregion: Persona Models
#region: Context Models
#endregion: Context Models
#region: MMA Models
#endregion: MMA Models
#region: UI State Models
#endregion: UI State Models
#region: Logging Models
#endregion: Logging Models
```
### `Provider`, `ModelInfo` — AI Models
```python
class Provider(str, Enum):
GEMINI = "gemini"
ANTHROPIC = "anthropic"
DEEPSEEK = "deepseek"
MINIMAX = "MiniMax"
GEMINI_CLI = "gemini-cli"
@dataclass
class ModelInfo:
name: str
provider: Provider
context_window: int
max_output_tokens: int
supports_caching: bool = False
cost_per_1k_input: float = 0.0
cost_per_1k_output: float = 0.0
```
These back the AI Settings panel and the cost tracker.
### `DiscussionEntry`, `Message` — Discussion History
```python
@dataclass
class Message:
role: Literal["user", "assistant", "system", "tool"]
content: str
timestamp: float
metadata: dict[str, Any] = field(default_factory=dict)
@dataclass
class DiscussionEntry:
entry_id: str
messages: list[Message]
is_take_root: bool = False # First message of a "take" (timeline branch)
parent_take_id: str | None = None
metadata: dict[str, Any] = field(default_factory=dict)
```
Discussion history is a list of `DiscussionEntry` objects, each containing one or more `Message` objects. The branching structure supports "takes" (alternative timeline branches).
### `ContextFileEntry`, `ContextScreenshot` — Context
```python
class ViewMode(str, Enum):
FULL = "full"
SUMMARIZE = "summarize"
SKELETON = "skeleton"
OUTLINE = "outline"
NONE = "none"
@dataclass
class ContextFileEntry:
path: str # Absolute or relative to project root
view_mode: ViewMode = ViewMode.FULL
annotations: list[Annotation] = field(default_factory=list)
fuzzy_slice: FuzzySlice | None = None # Optional line range
@dataclass
class ContextScreenshot:
path: str # Absolute path to image
caption: str = ""
```
Context is a composition of files + screenshots, each with optional view mode and line-range slicing.
### `FuzzySlice`, `Annotation` — Visual Slice Editor
```python
@dataclass
class FuzzySlice:
start_anchor: str # Fuzzy-matched string
end_anchor: str
start_offset: int = 0
end_offset: int = 0
fallback_start_line: int | None = None
fallback_end_line: int | None = None
@dataclass
class Annotation:
kind: Literal["tag", "comment"]
text: str
line_range: tuple[int, int] | None = None
```
Fuzzy slices use **anchor-based matching** to survive code modifications. If `start_anchor` shifts due to edits, the slice re-anchors on the next render.
See **[docs/guide_context_curation.md](guide_context_curation.md)** for the full Visual Slice Editor.
### `Ticket`, `Track`, `WorkerContext` — MMA
```python
class TicketStatus(str, Enum):
PENDING = "pending"
RUNNING = "running"
DONE = "done"
BLOCKED = "blocked"
SKIPPED = "skipped"
class TicketPriority(str, Enum):
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
@dataclass
class Ticket:
ticket_id: str
title: str
description: str
status: TicketStatus = TicketStatus.PENDING
priority: TicketPriority = TicketPriority.MEDIUM
depends_on: list[str] = field(default_factory=list)
blocks: list[str] = field(default_factory=list)
files_involved: list[str] = field(default_factory=list)
persona: str | None = None
result: dict | None = None
error: str | None = None
commit_sha: str | None = None
@dataclass
class Track:
track_id: str
title: str
description: str
tickets: list[Ticket]
plan_path: str
created_at: float
checkpoints: list[TrackCheckpoint] = field(default_factory=list)
@dataclass
class TrackCheckpoint:
sha: str
phase: str
timestamp: float
note: str
@dataclass
class WorkerContext:
"""The minimal context slice given to a tier3-worker sub-agent."""
ticket_id: str
track_id: str
persona: str | None
focus_files: list[str]
skeleton_views: dict[str, str] # path -> skeleton string
history: list[Message] # Recent messages from the parent
conductor_notes: str
```
`WorkerContext` is the **Token Firewall** boundary: this is exactly what each Tier 3 worker sees. It includes only the focus files, their skeletons, and recent history. The parent agent's full state is never visible.
### `Persona`, `Preset`, `ContextPreset`, `ToolPreset` — Configuration
```python
@dataclass
class Persona:
name: str
model: str | None = None
system_prompt: str | None = None
tool_weights: dict[str, int] = field(default_factory=dict) # tool_name -> 1..5
parameter_biases: dict[str, Any] = field(default_factory=dict)
bias_profile: str | None = None
tier_assignments: dict[str, str] = field(default_factory=dict) # tier -> persona_name
description: str = ""
@dataclass
class Preset:
name: str
base_prompt: str
user_instructions: str
full_text: str # base_prompt + user_instructions
temperature: float = 0.7
top_p: float = 0.95
max_output_tokens: int = 8192
is_foundation: bool = False # True for the foundational base prompt
@dataclass
class ContextPreset:
name: str
files: list[ContextFileEntry]
screenshots: list[ContextScreenshot]
description: str = ""
last_validated: float = 0.0
@dataclass
class ToolPreset:
name: str
enabled_tools: dict[str, bool] = field(default_factory=dict) # tool_name -> enabled
weights: dict[str, int] = field(default_factory=dict) # tool_name -> 1..5
parameter_biases: dict[str, Any] = field(default_factory=dict)
bias_profile: str | None = None
description: str = ""
```
Personas consolidate **everything an agent needs** into a single named entity. Presets are simpler — just system prompt + parameters.
### `CommsLogEntry`, `LogEntry` — Logging
```python
@dataclass
class CommsLogEntry:
timestamp: float
source: str # "main", "tier3-worker", "tier4-qa"
role: str # "user", "assistant", "system"
payload_type: str # "prompt", "response", "tool_call", "tool_result"
content: str
metadata: dict[str, Any] = field(default_factory=dict)
ticket_id: str | None = None
@dataclass
class LogEntry:
timestamp: float
level: Literal["DEBUG", "INFO", "WARNING", "ERROR"]
message: str
source: str # Module or subsystem name
context: dict[str, Any] = field(default_factory=dict)
```
Comms logs are append-only and stored as JSON-L. They are the **primary debugging surface** for AI interactions.
### `UIPerformanceSnapshot`, `DiagnosticEntry` — Diagnostics
```python
@dataclass
class UIPerformanceSnapshot:
timestamp: float
fps: float
frame_time_ms: float
cpu_pct: float
input_lag_ms: float
@dataclass
class DiagnosticEntry:
timestamp: float
component: str # "DAG Engine", "Aggregation", "Panel:Command Palette"
hit_count: int
total_latency_ms: float
peak_latency_ms: float
min_latency_ms: float
```
Diagnostics power the **Performance Diagnostics** panel (FPS, Frame Time, CPU, plus per-component hit counts and latencies).
### `HookRequest`, `HookResponse` — Hook API
```python
@dataclass
class HookRequest:
action: str # "click", "set_value", "custom_callback", etc.
item: str | None = None
value: Any = None
callback: str | None = None
args: list[Any] = field(default_factory=list)
kwargs: dict[str, Any] = field(default_factory=dict)
@dataclass
class HookResponse:
status: Literal["ok", "error", "queued", "rejected"]
message: str = ""
data: dict[str, Any] = field(default_factory=dict)
```
### `WorkspaceProfile` — Layouts
```python
class WorkspaceProfile:
name: str
ini_content: str # ImGui ini settings string (from SaveIniSettingsToMemory)
show_windows: Dict[str, bool] = field(default_factory=dict)
panel_states: Dict[str, Any] = field(default_factory=dict)
```
> **Note:** The 2026-06-05 refactor (per `live_gui_fragility_fixes_20260605`) collapsed the previous design (which had `docking_layout: bytes` with base64, plus `theme`, `theme_fx_enabled`, `captured_at`, `description` as additional fields) into a 4-field model. `ini_content` is a plain `str` (not base64) because `ImGui.SaveIniSettingsToMemory()` returns a string and `tomli_w` rejects `bytes`. `LayoutPreset` is no longer a separate class; multi-viewport state lives in `panel_states`. See [guide_workspace_profiles.md](guide_workspace_profiles.md) for the full data model and TOML example.
### `RAGConfig`, `RAGChunk`, `RAGResult` — RAG
```python
@dataclass
class RAGConfig:
enabled: bool = False
source: Literal["chromadb", "external_mcp"] = "chromadb"
embedding_provider: str = "gemini-embedding-001"
chunk_size: int = 512
chunk_overlap: int = 64
top_k: int = 5
external_mcp_server: str | None = None
@dataclass(frozen=True)
class RAGChunk:
id: str = ""
document: str = ""
path: str = ""
score: float = 0.0
metadata: Metadata = field(default_factory=dict)
@dataclass
class RAGResult:
chunks: list[RAGChunk]
query: str
distance_threshold: float = 0.0
def __getattr__(name: str) -> Any:
if name == "PROVIDERS":
from src import ai_client
return ai_client.PROVIDERS
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
```
---
## Constants
## Where the data models actually live now
The file also defines several module-level constants used across the app:
The old "one registry to look at" goal is now achieved by **per-system files**. Each subsystem owns its own data models in its own file:
```python
# Provider routing
PROVIDERS: list[str] = ["gemini", "anthropic", "gemini_cli", "deepseek", "minimax", "qwen", "grok", "llama"]
| Model(s) | Current location | Notes |
|---|---|---|
| `TrackMetadata` (formerly `Metadata` dataclass) | `src/mma.py` | The track/ticket data layer |
| `Ticket`, `Track`, `WorkerContext` | `src/mma.py` | MMA domain models |
| `VendorCapabilities`, `VendorMetric` | `src/ai_client.py` (`#region: Vendor Capabilities`) | Moved from the deleted `src/vendor_capabilities.py` |
| `FileItem`, `FileItems` | `src/project_files.py` | Per-file curation memory |
| `Result[T]`, `ErrorInfo`, `ErrorKind`, `NilPath` | `src/result_types.py` | Data-oriented error handling |
| `Metadata`, `CommsLogEntry`, `HistoryMessage`, `ToolDefinition`, `ToolCall`, `CommsLogCallback`, `SessionInsights`, `DiscussionSettings`, `CustomSlice`, `MMAUsageStats`, `ProviderPayload`, `UIPanelConfig`, `PathInfo`, `JsonPrimitive`, `JsonValue`, `FileItemsDiff` | `src/type_aliases.py` | The typed boundary + per-aggregate dataclasses (see [guide_context_aggregation.md](guide_context_aggregation.md)) |
| `ToolSpec`, `ToolParameter` | `src/mcp_tool_specs.py` | Typed tool-spec registry (replaces the legacy `MCP_TOOL_SPECS: list[dict[str, Any]]`) |
| `MCPServerConfig`, `MCPConfiguration`, `VectorStoreConfig`, `RAGConfig` | `src/mcp_client.py` | MCP subsystem data layer |
| `WorkspaceProfile` | `src/workspace_manager.py` | Layout profiles |
| `Persona`, `Preset`, `ContextPreset`, `ToolPreset`, `Tool`, `BiasProfile` | `src/personas.py`, `src/presets.py`, `src/context_presets.py`, `src/tool_presets.py` | Manager-owned config models |
| `TicketStatus`, `TicketPriority`, `TrackCheckpoint` | `src/mma.py` | MMA enums |
# Tool categories (for Tool Bias)
TOOL_CATEGORIES: list[str] = [
"File I/O",
"Python AST",
"C/C++ AST",
"Analysis",
"Network",
"Runtime",
"Beads",
]
# MMA tier -> default persona
DEFAULT_TIER_PERSONAS: dict[str, str] = {
"tier1": "orchestrator",
"tier2": "tech-lead",
"tier3": "worker",
"tier4": "qa",
}
# AGENT_TOOL_NAMES — the canonical list of all 45 tool names
AGENT_TOOL_NAMES: list[str] = [
"read_file", "list_directory", "search_files", "get_file_summary",
"get_file_slice", "set_file_slice", "edit_file",
# ... all 45 ...
]
```
These constants eliminate the **scattered list definitions** problem — every module imports the same source of truth.
**Rule of thumb:** if you need to know what fields a type has, read the per-system guide (e.g., [guide_context_aggregation.md](guide_context_aggregation.md) for `FileItem`, [guide_mma.md](guide_mma.md) for `Ticket`/`Track`), or read the file directly with `py_get_skeleton`.
---
## Serialization
## Where the constants live now
Models use a mix of strategies:
- **`pydantic` models**: For TOML round-trip with validation (Persona, Preset, ContextPreset, ToolPreset, WorkspaceProfile, RAGConfig).
- **`dataclasses.asdict()`**: For JSON-L logging (CommsLogEntry, LogEntry, DiscussionEntry, Message).
- **Custom tomli-w / tomllib**: For the modules that need precise control over TOML output ordering.
| Constant | Current location | Notes |
|---|---|---|
| `PROVIDERS` | `src/ai_client.py` (re-exported by `src/models.py` via lazy `__getattr__`) | `List[str]` of 8 providers: `gemini`, `anthropic`, `gemini_cli`, `deepseek`, `minimax`, `qwen`, `grok`, `llama` |
| `DEFAULT_TOOL_CATEGORIES` | `src/ai_client.py` | The canonical grouping of the MCP tool registry for the UI's category filter |
| Tool names (formerly `AGENT_TOOL_NAMES`) | `src/mcp_tool_specs.py:_REGISTRY` + `mcp_tool_specs.tool_names()` | 45 tools. Re-exported as `mcp_client.TOOL_NAMES` for backward compat |
| `DEFAULT_TIER_PERSONAS` | `src/mma_prompts.py` | MMA tier → default persona mapping |
| `_VENDOR_REGISTRY` | `src/ai_client.py` | The `VendorCapabilities` registry, populated via `register()` at import time |
Most serialization is done by the **manager classes** (PresetManager, PersonaManager, etc.) — the model itself is pure data.
**Audit:** `scripts/audit_providers_source_of_truth.py` fails if `PROVIDERS` is declared as a literal in `src/models.py`.
---
## Validation
## Why the shim exists at all
`pydantic` validators enforce constraints:
Backward compatibility. The refactor tracks moved the dataclasses out, but a long tail of tests and consumers still import `from src.models import Metadata` expecting the dataclass. The shim re-exports `TrackMetadata` under the legacy name so those imports keep resolving to the same object.
```python
class Preset(BaseModel):
name: str = Field(..., min_length=1, max_length=64)
temperature: float = Field(0.7, ge=0.0, le=2.0)
top_p: float = Field(0.95, ge=0.0, le=1.0)
max_output_tokens: int = Field(8192, ge=1, le=200000)
@validator('name')
def name_must_be_safe(cls, v):
if '/' in v or '\\' in v:
raise ValueError("name cannot contain path separators")
return v
```
Validators run on load and on save. The managers call `.model_dump()` / `Preset.parse_obj(dict)` to round-trip.
New code should import directly from the owning file:
- `from src.mma import TrackMetadata` (the dataclass)
- `from src.type_aliases import Metadata` (the boundary wire type — different thing)
- `from src.ai_client import PROVIDERS, VendorCapabilities, get_capabilities`
- `from src.mcp_tool_specs import tool_names, get_tool_spec`
---
## The `parse_plan_md` Function
## `parse_plan_md`
A critical utility that converts a markdown plan file to `Track` and `Ticket` objects:
```python
def parse_plan_md(plan_path: Path) -> list[Ticket]:
"""Parse a plan.md file into a list of Ticket objects."""
text = plan_path.read_text(encoding="utf-8")
tickets = []
current_phase = None
for line in text.splitlines():
line = line.rstrip()
if not line:
continue
# Phase heading
if line.startswith("# "):
current_phase = line[2:].strip()
continue
# Ticket line
m = re.match(r'^\s*-\s*\[(.)\]\s*(.+?)(?:\s*\[depends:\s*([^\]]+)\])?\s*$', line)
if not m:
continue
marker, rest, deps = m.groups()
status = {" ": "pending", "~": "running", "x": "done", "!": "blocked"}.get(marker, "pending")
# Split rest into ticket_id and title
id_match = re.match(r'(\S+):\s*(.+)', rest)
if id_match:
tid, title = id_match.groups()
else:
tid, title = rest, rest
tickets.append(Ticket(
ticket_id=tid.strip(),
title=title.strip(),
description="",
status=TicketStatus(status),
depends_on=[d.strip() for d in (deps or "").split(",") if d.strip()],
))
return tickets
```
The DAG engine uses the returned `Ticket` objects to build the dependency graph.
The plan-parsing utility was moved to `src/mma.py` alongside the `Track`/`Ticket` models it constructs. See [guide_mma.md](guide_mma.md) for the current signature and usage.
---
## The `AppState` Class
## `AppState`
A separate large dataclass that aggregates all GUI-visible state. **Lives in `src/app_controller.py`**, not here, because it holds the controller's runtime state (not a pure data model). But it follows the same conventions (typed fields, no methods, SDM tags).
`AppState` (the controller's runtime state aggregate) lives in `src/app_controller.py` as before. It was never in `src/models.py`; the old version of this guide was correct to note that. See [guide_app_controller.md](guide_app_controller.md).
---
## How Models Are Used
## Adding a new model
### In `src/presets.py`
1. Add the dataclass to the **owning system's file** (e.g., a new MMA model goes in `src/mma.py`; a new tool-spec shape goes in `src/mcp_tool_specs.py`). Do NOT add it to `src/models.py` — that file is a shim only.
2. If the model is a typed boundary/aggregate shape, add it to `src/type_aliases.py` instead.
3. Add `to_dict()` / `from_dict()` if the model is persisted.
4. Add a docstring with `[C: ...]` (callers) and `[M: ...]` (mutators) SDM tags.
5. Add tests in the relevant `tests/test_<system>.py`.
6. If the model warrants a GUI surface, add a rendering helper in `src/gui_2.py` (module-level `render_<thing>(app: App)`).
7. Update the relevant `docs/guide_<system>.md` to document the new model.
```python
def save_preset(preset: Preset) -> None:
data = preset.model_dump()
tomli_w.dump(data, open(self.presets_path, "wb"))
```
### In `src/ai_client.py`
```python
def send(self, request: AIRequest) -> AIResponse:
"""Sends a request. AIRequest is defined in models.py."""
```
### In `src/multi_agent_conductor.py`
```python
def load_track(self, track_id: str) -> Track:
tickets = parse_plan_md(plan_path)
return Track(
track_id=track_id,
title=...,
tickets=tickets,
plan_path=str(plan_path),
created_at=time.time(),
)
```
**Do NOT** add new `src/<thing>.py` files without explicit user authorization — see `AGENTS.md` "File Size and Naming Convention" HARD RULE.
---
## Testing
## V2 Capability Matrix
Models are tested for:
- **Round-trip serialization** (`to_toml``from_toml` → equal)
- **Validation** (invalid values rejected)
- **Default values** (all fields have sensible defaults)
- **Field types** (TypeScript-like strict checking via `pydantic`)
`VendorCapabilities` is defined in `src/ai_client.py` under `#region: Vendor Capabilities (moved from src/vendor_capabilities.py)`. The dataclass has 12 v2 fields on top of the v1 fields:
Tests live in `tests/test_models.py` and module-specific test files (e.g., `tests/test_preset_manager.py` exercises the `Preset` model).
**V1 fields:** `vision`, `tool_calling`, `caching`, `streaming`, `model_discovery`, `context_window`, `cost_tracking`
**V2 fields:** `local`, `reasoning`, `structured_output`, `code_execution`, `web_search`, `x_search`, `file_search`, `mcp_support`, `audio`, `video`, `grounding`, `computer_use`
All v2 fields default to `False`. The dataclass is `frozen=True`; per-vendor entries use `register()` at module-import time in `src/ai_client.py`. The GUI reads the matrix via `get_capabilities(vendor, model)` and adapts UI elements accordingly (see [guide_ai_client.md §V2 Capability Matrix](guide_ai_client.md#v2-capability-matrix-phase-4)).
**Adding a new v2 field:** the HARD RULE is that all AI-client code lives in `src/ai_client.py`. New v2 fields go in the `VendorCapabilities` dataclass in `src/ai_client.py` (the region that replaced the deleted `src/vendor_capabilities.py`) — NOT in a new `src/<v2_thing>.py` file. Update the dataclass, populate per-model in `_VENDOR_REGISTRY` via `register()`, add a small rendering helper in `src/gui_2.py` if the field warrants a UI badge.
---
## Adding a New Model
1. Add the model to the appropriate region block in `src/models.py`.
2. Add validators if any fields have constraints.
3. Add a docstring with `[C: ...]` (callers) and `[M: ...]` (mutators) SDM tags.
4. If the model is persisted, write a `to_<format>()` / `from_<format>()` pair in the relevant manager.
5. Add tests in `tests/test_models.py` (round-trip + validation).
6. Update `docs/guide_models.md` (this file) to document the new model.
---
## PROVIDERS Constant (Location Change 2026-06-11)
The `PROVIDERS` list was moved from `src/models.py` to `src/ai_client.py:56` per the AGENTS.md HARD RULE (no new `src/<thing>.py` files; system code lives in the system module).
**Current location**: `src/ai_client.py` (import as `from src.ai_client import PROVIDERS`)
**Backward compat**: `src/models.py:261-264` has a PEP 562 `__getattr__` that re-exports `PROVIDERS` via lazy import. This breaks the circular dependency where `src/ai_client.py:50` imports `ToolPreset` from `src/models.py` (a top-level `from src.ai_client import PROVIDERS` in `models.py` would deadlock).
**Audit**: `scripts/audit_providers_source_of_truth.py` fails if `PROVIDERS` is declared as a literal in `src/models.py`.
The 4 internal import sites were updated in commit `6c6a4aef`:
- `src/app_controller.py:3093`
- `src/gui_2.py:2293, 2849, 5377`
---
## V2 Capability Matrix (Added 2026-06-11)
`src/vendor_capabilities.py` defines the `VendorCapabilities` dataclass (NOT in `src/models.py` — it's in its own file because it's not a "data model" but a "capability registry"). The dataclass was extended with 12 v2 fields:
**V1 fields** (unchanged from parent track):
- `vision`, `tool_calling`, `caching`, `streaming`, `model_discovery`, `context_window`, `cost_tracking`
**V2 fields** (added in `qwen_llama_grok_followup_20260611` Phase 4):
- `local` — backend is on-device (Ollama, etc.)
- `reasoning` — model supports `thinking` / reasoning traces
- `structured_output` — model supports JSON / tool-use output
- `code_execution` — model can run code (server-side)
- `web_search` — model can do live web search
- `x_search` — X/Twitter search (grok-specific)
- `file_search` — model has a file_search tool (Anthropic)
- `mcp_support` — model supports the Model Context Protocol
- `audio` — model accepts audio input
- `video` — model accepts video input
- `grounding` — model supports grounding (gemini)
- `computer_use` — model can drive a computer (Anthropic claude-3.5+)
All v2 fields default to `False`. The dataclass is `frozen=True`; per-vendor entries use `register()` at module-import time. The GUI reads the matrix via `get_capabilities(vendor, model)` and adapts 9+ UI elements accordingly (see [guide_ai_client.md §V2 Capability Matrix](guide_ai_client.md#v2-capability-matrix-phase-4)).
**Adding a new v2 field**: The HARD RULE is that all AI-client code lives in `src/ai_client.py`. New v2 fields go in `src/vendor_capabilities.py` (existing file) — NOT in a new `src/<v2_thing>.py` file. Update the dataclass, populate per-model in the registry, add a small rendering helper in `src/gui_2.py` (e.g., `_render_v2_capability_badges` for the existing 11 v2 fields).
---
## See Also
- **[guide_architecture.md](guide_architecture.md)** — How models flow through the system
- **[guide_app_controller.md](guide_app_controller.md)** — `AppState` and controller-owned models
- **[guide_mma.md](guide_mma.md)** — `Ticket`, `Track`, `WorkerContext` usage in MMA
- **[guide_mma.md](guide_mma.md)** — `Ticket`, `Track`, `WorkerContext`, `TrackMetadata` in `src/mma.py`
- **[guide_ai_client.md](guide_ai_client.md)** — `VendorCapabilities`, `PROVIDERS`, `_VENDOR_REGISTRY` in `src/ai_client.py`
- **[guide_personas.md](guide_personas.md)** — `Persona` model in detail
- **[guide_workspace_profiles.md](guide_workspace_profiles.md)** — `WorkspaceProfile` model in detail
- **[guide_rag.md](guide_rag.md)** — `RAGConfig`, `RAGChunk`, `RAGResult` models
- **[guide_context_aggregation.md](guide_context_aggregation.md)** — How the `FileItem` and `ContextPreset` schemas flow through the `aggregate.py` pipeline
- **[guide_discussions.md](guide_discussions.md)** — The entry dict shape (`{role, content, collapsed, ts, ...}`) consumed by `parse_history_entries`
- **`src/presets.py`, `src/personas.py`, `src/context_presets.py`, `src/tool_presets.py`** — Managers that use these models
- **`src/multi_agent_conductor.py`** — Uses `Ticket`, `Track`, `WorkerContext`
- **[conductor/tracks/nagent_review_20260608/report.md §6](../conductor/tracks/nagent_review_20260608/report.md)** — Deep-dive on the `FileItem` schema as Manual Slop's strongest curation dimension
- **`src/ai_client.py`** — Uses `Provider`, `ModelInfo`, `AIRequest`, `AIResponse`
- **[guide_discussions.md](guide_discussions.md)** — The entry dict shape consumed by `parse_history_entries`
- **`src/type_aliases.py`** — The typed boundary + per-aggregate dataclasses
- **`src/mcp_tool_specs.py`** — The typed `ToolSpec` registry (45 tools)
- **`src/result_types.py`** — `Result[T]`, `ErrorInfo`, `ErrorKind` for data-oriented error handling
- **[conductor/tracks/nagent_review_20260608/report.md §6](../conductor/tracks/nagent_review_20260608/report.md)** — Deep-dive on the `FileItem` schema as Manual Slop's strongest curation dimension
+9 -7
View File
@@ -35,12 +35,14 @@ Together they implement a **non-blocking execution engine** with thread-safe sta
│ WorkerPool │
│ - Configurable concurrency (default 4) │
│ - Threads pull ready tickets, spawn workers │
│ - Workers call mma_exec.py with sub-prompt
│ - Workers run via the internal subprocess
│ template (run_worker_lifecycle; NOT the │
│ deprecated meta-tooling mma_exec.py) │
└─────────────────┬───────────────────────────────┘
│ per ticket
┌─────────────────────────────────────────────────┐
mma_exec.py (tier3-worker / tier4-qa)
run_worker_lifecycle (tier3-worker / tier4-qa) │
│ - Stateless Tier 3 or Tier 4 sub-agent │
│ - TDD cycle: red → green → refactor │
│ - Commits per task │
@@ -72,7 +74,7 @@ class TrackDAG:
self.ticket_map = {t.id: t for t in tickets} # dict[str, Ticket] (O(1) lookup)
```
The `Ticket` dataclass itself is defined in `src/models.py` (see [guide_models.md](guide_models.md)). It carries the dependencies and status directly — there is no separate `TicketNode` wrapper, no `edges` dict, no `reverse_edges` dict. Adjacency lists are computed on demand inside `cascade_blocks()` and `topological_sort()`.
The `Ticket` dataclass itself is defined in `src/mma.py` (moved out of `src/models.py` per `module_taxonomy_refactor_20260627`; see [guide_models.md](guide_models.md)). It carries the dependencies and status directly — there is no separate `TicketNode` wrapper, no `edges` dict, no `reverse_edges` dict. Adjacency lists are computed on demand inside `cascade_blocks()` and `topological_sort()`.
### Public Methods (actual signatures from `src/dag_engine.py:41-163`)
@@ -192,7 +194,7 @@ class ExecutionEngine:
---
## The `ConductorEngine` (in `src/multi_agent_conductor.py:116+`)
## The `ConductorEngine` (in `src/multi_agent_conductor.py:112+`)
The actual class is named `ConductorEngine`, not `MultiAgentConductor`. It owns the DAG, the engine, and a `WorkerPool`; pushes state to the GUI; and runs the main async dispatch loop.
@@ -263,7 +265,7 @@ async def _push_state(self, status: str = "running", active_tier: str = None) ->
---
## The `WorkerPool` (in `src/multi_agent_conductor.py:50-114`)
## The `WorkerPool` (in `src/multi_agent_conductor.py:52-110`)
A `dict[str, Thread]` + `threading.Lock` + `threading.Semaphore`, NOT a `ThreadPoolExecutor` wrapper.
@@ -457,7 +459,7 @@ Tests use `unittest.mock.patch` to mock `subprocess.Popen` and `ai_client.send`
- **[guide_architecture.md](guide_architecture.md)** — Threading model
- **[guide_mma.md](guide_mma.md)** — MMA concepts (4-Tier hierarchy, Token Firewall)
- **[guide_app_controller.md](guide_app_controller.md)** — How the conductor is owned by the controller
- **[guide_models.md](guide_models.md)** — `Ticket` and `Track` data structures
- **`scripts/mma_exec.py`** — The sub-agent entry point
- **[guide_models.md](guide_models.md)** — `Ticket` and `Track` data structures (now in `src/mma.py`; moved out of `src/models.py`)
- **`src/multi_agent_conductor.py:run_worker_lifecycle`** — The WorkerPool's internal subprocess template (the application-domain worker entry point; NOT the deprecated meta-tooling `scripts/mma_exec.py` — see `docs/guide_meta_boundary.md`)
- **`scripts/mma.ps1`** — PowerShell wrapper
- **`conductor/workflow.md`**](../conductor/workflow.md) — Track execution protocol
+2 -3
View File
@@ -23,7 +23,7 @@ This guide covers:
## Data Model
### `Persona` (`src/models.py:704`)
### `Persona` (defined in `src/personas.py`; moved out of `src/models.py` per `module_taxonomy_refactor_20260627`)
```python
class Persona:
@@ -138,8 +138,7 @@ aggregation_strategy = "summarize"
`PersonaManager` is the CRUD interface.
```python
from src.personas import PersonaManager
from src.models import Persona
from src.personas import PersonaManager, Persona
manager = PersonaManager(project_root=Path("/path/to/project"))
all_personas = manager.load_all() # Merged global + project
+2 -2
View File
@@ -69,7 +69,7 @@ class RAGEngine:
...
```
**Construction**: Takes a `RAGConfig` (from `src/models.py`) and a `base_dir`. The config specifies the embedding provider type, the vector store path, the chunk size, and the chunk overlap.
**Construction**: Takes a `RAGConfig` (defined in `src/mcp_client.py` — moved out of `src/models.py` per `module_taxonomy_refactor_20260627`) and a `base_dir`. The config specifies the embedding provider type, the vector store path, the chunk size, and the chunk overlap.
**Internal state**:
- `embedding_provider: BaseEmbeddingProvider` — set by `_init_embedding_provider`
@@ -322,7 +322,7 @@ chunk_size = 1000
chunk_overlap = 200
```
### `RAGConfig` + `VectorStoreConfig` Schema (`src/models.py`)
### `RAGConfig` + `VectorStoreConfig` Schema (defined in `src/mcp_client.py`; moved out of `src/models.py`)
```python
@dataclass
+1 -1
View File
@@ -64,7 +64,7 @@ Workspace Profiles live at the boundary between the ImGui render loop and the pe
## Data Model
### `WorkspaceProfile` (`src/models.py`)
### `WorkspaceProfile` (defined in `src/workspace_manager.py`; moved out of `src/models.py` per `module_taxonomy_refactor_20260627`)
A snapshot of window state at a moment in time.
+30 -29
View File
@@ -1,34 +1,30 @@
---
name: mma-orchestrator
description: Enforces the 4-Tier Hierarchical Multi-Model Architecture (MMA) within Gemini CLI using Token Firewalling and sub-agent task delegation.
description: Enforces the 4-Tier Hierarchical Multi-Model Architecture (MMA) within the Manual Slop meta-tooling environment using Token Firewalling and sub-agent task delegation via the OpenCode Task tool.
---
# MMA Token Firewall & Tiered Delegation Protocol
You are operating within the MMA Framework, acting as either the **Tier 1 Orchestrator** (for setup/init) or the **Tier 2 Tech Lead** (for execution). Your context window is extremely valuable and must be protected from token bloat (such as raw, repetitive code edits, trial-and-error histories, or massive stack traces).
To accomplish this, you MUST delegate token-heavy or stateless tasks to **Tier 3 Workers** or **Tier 4 QA Agents** by spawning secondary Gemini CLI instances via `run_shell_command`.
**CRITICAL Prerequisite:**
To ensure proper environment handling and logging, you MUST NOT call the `gemini` command directly for sub-tasks. Instead, use the wrapper script:
`uv run python scripts/mma_exec.py --role <Role> "..."`
To accomplish this, you MUST delegate token-heavy or stateless tasks to **Tier 3 Workers** or **Tier 4 QA Agents** via the **OpenCode Task tool** (subagent invocation with the `subagent_type` parameter). The canonical mechanism is the OpenCode Task tool; the legacy `scripts/mma_exec.py` / `scripts/claude_mma_exec.py` bridge scripts are **DEPRECATED for meta-tooling sub-agent delegation as of 2026-06-27** (see `conductor/workflow.md` §"Conductor Token Firewalling" + `docs/guide_meta_boundary.md`). The Application-domain WorkerPool at `src/multi_agent_conductor.py:run_worker_lifecycle` uses its own internal subprocess template — that is NOT the meta-tooling mechanism and is also unrelated to the OpenCode Task tool.
## 0. Architecture Fallback & Surgical Methodology
**Before creating or refining any track**, consult the deep-dive architecture docs:
- `docs/guide_architecture.md`: Thread domains, event system (`AsyncEventQueue`, `_pending_gui_tasks` action catalog), AI client multi-provider architecture, HITL Execution Clutch blocking flow, frame-sync mechanism
- `docs/guide_tools.md`: MCP Bridge 3-layer security model, full 26-tool inventory with params, Hook API GET/POST endpoints with request/response formats, ApiHookClient method reference
- `docs/guide_mma.md`: Ticket/Track/WorkerContext data structures, DAG engine (cycle detection, topological sort), ConductorEngine execution loop, Tier 2 ticket generation, Tier 3 worker lifecycle with context amnesia
- `docs/guide_tools.md`: MCP Bridge 3-layer security model, full 45-tool inventory (now in `src/mcp_tool_specs.py`) with params, Hook API GET/POST endpoints with request/response formats, ApiHookClient method reference
- `docs/guide_mma.md`: Ticket/Track/WorkerContext data structures (now in `src/mma.py`; moved out of `src/models.py`), DAG engine (cycle detection, topological sort), ConductorEngine execution loop, Tier 2 ticket generation, Tier 3 worker lifecycle with context amnesia
- `docs/guide_simulations.md`: `live_gui` fixture lifecycle, Puppeteer pattern, mock provider JSON-L protocol, visual verification patterns
### The Surgical Spec Protocol (MANDATORY for track creation)
When creating tracks (`activate_skill mma-tier1-orchestrator`), follow this protocol:
1. **AUDIT BEFORE SPECIFYING**: Use `get_code_outline`, `py_get_definition`, `grep_search`, and `get_git_diff` to map what already exists. Previous track specs asked to re-implement existing features (Track Browser, DAG tree, approval dialogs) because no audit was done. Document findings in a "Current State Audit" section with file:line references.
1. **AUDIT BEFORE SPECIFYING**: Use `py_get_code_outline`, `py_get_definition`, `py_find_usages`, and `get_git_diff` to map what already exists. Previous track specs asked to re-implement existing features (Track Browser, DAG tree, approval dialogs) because no audit was done. Document findings in a "Current State Audit" section with file:line references.
2. **GAPS, NOT FEATURES**: Frame requirements as what's MISSING relative to what exists.
- GOOD: "The existing `_render_mma_dashboard` (gui_2.py:2633-2724) has a token usage table but no cost column."
- GOOD: "The existing `_render_mma_dashboard` (gui_2.py ~line 2633-2724) has a token usage table but no cost column."
- BAD: "Build a metrics dashboard with token and cost tracking."
3. **WORKER-READY TASKS**: Each plan task must specify:
@@ -49,17 +45,16 @@ When performing code modifications or implementing specific requirements:
2. **Code Style Enforcement:** You MUST explicitly remind the worker to "use exactly 1-space indentation for Python code" in your prompt to prevent them from breaking the established codebase style.
3. **DO NOT** perform large code writes yourself.
4. **DO** construct a single, highly specific prompt with a clear objective. Include exact file:line references and the specific API calls to use (from your audit or the architecture docs).
5. **DO** spawn a Tier 3 Worker.
*Command:* `uv run python scripts/mma_exec.py --role tier3-worker "Implement [SPECIFIC_INSTRUCTION] in [FILE_PATH] at lines [N-M]. Use [SPECIFIC_API_CALL]. Use 1-space indentation."`
6. **Handling Repeated Failures:** If a Tier 3 Worker fails multiple times on the same task, it may lack the necessary capability. You must track failures and retry with `--failure-count <N>` (e.g., `--failure-count 2`). This tells `mma_exec.py` to escalate the sub-agent to a more powerful reasoning model (like `gemini-3-flash`).
5. **DO** spawn a Tier 3 Worker via the OpenCode Task tool with `subagent_type: "tier3-worker"` and a surgical prompt specifying WHERE/WHAT/HOW/SAFETY/COMMIT structure. The Task tool invokes the `.opencode/agents/tier3-worker.md` sub-agent prompt which carries the tier-specific operating constraints.
6. **Handling Repeated Failures:** If a Tier 3 Worker fails multiple times on the same task, it may lack the necessary capability. Re-dispatch with a more capable model tier (e.g., request a higher-capability model in the prompt). The OpenCode Task tool's sub-agent contracts are stateless — failures show up as the returned task result, not as in-band escalation flags.
7. The Tier 3 Worker is stateless and has tool access for file I/O.
## 2. The Tier 4 QA Agent (Diagnostics)
If you run a test or command that fails with a significant error or large traceback:
1. **DO NOT** analyze the raw logs in your own context window.
2. **DO** spawn a stateless Tier 4 agent to diagnose the failure.
3. *Command:* `uv run python scripts/mma_exec.py --role tier4-qa "Analyze this failure and summarize the root cause: [LOG_DATA]"`
4. **Mandatory Research-First Protocol:** Avoid direct `read_file` calls for any file over 50 lines. Use `get_file_summary`, `py_get_skeleton`, or `py_get_code_outline` first to identify relevant sections. Use `git diff` to understand changes.
3. **Spawn via the OpenCode Task tool** with `subagent_type: "tier4-qa"` and a prompt structured as "DO NOT fix — provide root cause analysis only: [LOG_DATA]".
4. **Mandatory Research-First Protocol:** Avoid direct `read_file` calls for any file over 50 lines. Use `get_file_summary`, `py_get_skeleton`, or `py_get_code_outline` first to identify relevant sections. Use `get_git_diff` to understand changes.
## 3. Persistent Tech Lead Memory (Tier 2)
Unlike the stateless sub-agents (Tiers 3 & 4), the **Tier 2 Tech Lead** maintains persistent context throughout the implementation of a track. Do NOT apply "Context Amnesia" to your own session during track implementation. You are responsible for the continuity of the technical strategy.
@@ -78,36 +73,41 @@ To minimize context bloat for Tier 2 & 3:
When your current role requires capabilities from another tier, use `activate_skill`:
- **Track creation/refinement**: `activate_skill mma-tier1-orchestrator` — applies the Surgical Spec Protocol
- **Track execution**: `activate_skill mma-tier2-tech-lead` — applies persistent context and TDD workflow
- **Quick code task**: Spawn via `mma_exec.py --role tier3-worker` (stateless, no skill activation needed)
- **Error analysis**: Spawn via `mma_exec.py --role tier4-qa` (stateless, no skill activation needed)
- **Quick code task**: Spawn via the OpenCode Task tool with `subagent_type: "tier3-worker"` (stateless, no skill activation needed)
- **Error analysis**: Spawn via the OpenCode Task tool with `subagent_type: "tier4-qa"` (stateless, no skill activation needed)
<examples>
### Example 1: Spawning a Tier 4 QA Agent
**User / System:** `pytest tests/test_gui.py` failed with 400 lines of output.
**Agent (You):**
```json
{
"command": "python scripts/mma_exec.py --role tier4-qa \"Summarize this stack trace into a 20-word fix: [snip first 30 lines...]\"",
"description": "Spawning Tier 4 QA to compress error trace statelessly."
}
```python
# OpenCode Task tool invocation (subagent_type="tier4-qa", not a shell command)
prompt = ("DO NOT fix — provide root cause analysis only. "
"Summarize this stack trace into a 20-word fix: "
"<snip first 30 lines of the traceback> "
"Inputs: [the relevant test + file paths]")
```
### Example 2: Spawning a Tier 3 Worker with Surgical Prompt
**User:** Please implement the cost tracking column in the token usage table.
**Agent (You):**
```json
{
"command": "python scripts/mma_exec.py --role tier3-worker \"In gui_2.py, modify _render_mma_dashboard (lines 2685-2699). Extend the token usage table from 3 columns to 5 by adding 'Model' and 'Est. Cost' columns. Use imgui.table_setup_column() for the new columns. Import cost_tracker and call cost_tracker.estimate_cost(model, input_tokens, output_tokens) for each tier row. Add a total row at the bottom. Use 1-space indentation.\"",
"description": "Delegating surgical implementation to Tier 3 Worker with exact line refs."
}
```python
# OpenCode Task tool invocation (subagent_type="tier3-worker")
prompt = ("In gui_2.py, modify _render_mma_dashboard (lines ~2685-2699). "
"Extend the token usage table from 3 columns to 5 by adding "
"'Model' and 'Est. Cost' columns. Use imgui.table_setup_column() "
"for the new columns. Import cost_tracker and call "
"cost_tracker.estimate_cost(model, input_tokens, output_tokens) "
"for each tier row. Add a total row at the bottom. "
"Use 1-space indentation.")
```
### Example 3: Creating a Track with Audit
**User:** Create a track for adding dark mode support.
**Agent (You):**
1. First, audit the codebase: `py_get_code_outline gui_2.py` → find `_render_theme_panel` (lines 2993-3030).
1. First, audit the codebase: `py_get_code_outline gui_2.py` → find `_render_theme_panel`.
2. Read the existing implementation: `py_get_definition gui_2.py _render_theme_panel`.
3. Check for existing color constants: `grep_search "vec4\|C_" gui_2.py`.
3. Check for existing color constants: `py_find_usages src/gui_2.py C_LBL`.
4. Now write the spec with a "Current State Audit" section documenting what the theme panel already does.
5. Write tasks referencing the exact lines and imgui color APIs to use.
</examples>
@@ -119,3 +119,4 @@ When your current role requires capabilities from another tier, use `activate_sk
- When managing complex, multi-file Track implementations.
- When creating or refining conductor tracks (MUST follow Surgical Spec Protocol).
</triggers>
</body</content>