# `src/models.py` — Legacy Re-Export Shim [Top](../Readme.md) | [Architecture](guide_architecture.md) | [MMA](guide_mma.md) | [App Controller](guide_app_controller.md) --- ## Overview `src/models.py` is now a **~1.5KB legacy re-export shim**. It is NOT a data model registry anymore. 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) **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 from src.mma import TrackMetadata Metadata = TrackMetadata # legacy class name re-export 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}") ``` --- ## Where the data models actually live now 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: | 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 | **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`. --- ## Where the constants live now | 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 | **Audit:** `scripts/audit_providers_source_of_truth.py` fails if `PROVIDERS` is declared as a literal in `src/models.py`. --- ## Why the shim exists at all 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. 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` --- ## `parse_plan_md` 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. --- ## `AppState` `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). --- ## Adding a new model 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_.py`. 6. If the model warrants a GUI surface, add a rendering helper in `src/gui_2.py` (module-level `render_(app: App)`). 7. Update the relevant `docs/guide_.md` to document the new model. **Do NOT** add new `src/.py` files without explicit user authorization — see `AGENTS.md` "File Size and Naming Convention" HARD RULE. --- ## V2 Capability Matrix `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: **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/.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. --- ## 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`, `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 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