From 071283df8f90d5978343b4af8dc0b89dca82ed0e Mon Sep 17 00:00:00 2001 From: AirCoding Date: Tue, 2 Jun 2026 10:06:58 +0800 Subject: [PATCH] Add implementation plan & task breakdown for V1.0.0 Alpha MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 70+ granular tasks (T-001..T-809) across 9 phases, derived strictly from frozen detailed design. Each task is self-contained for context-isolated executor agents: file list, contract refs, applicable INV-1..5, dependencies, DoD/verify. Includes invariant injection (§A1), import graph (§A2), reference reuse map (§A3), validation gates (§A4), phase dependency summary (§A5). Co-Authored-By: Claude Opus 4.7 --- .../implementation/IMPLEMENTATION-PLAN.md | 770 ++++++++++++++++++ 1 file changed, 770 insertions(+) create mode 100755 AirPlan/docs/implementation/IMPLEMENTATION-PLAN.md diff --git a/AirPlan/docs/implementation/IMPLEMENTATION-PLAN.md b/AirPlan/docs/implementation/IMPLEMENTATION-PLAN.md new file mode 100755 index 0000000..bbe888d --- /dev/null +++ b/AirPlan/docs/implementation/IMPLEMENTATION-PLAN.md @@ -0,0 +1,770 @@ +# AirCoding V1.0.0 Alpha — Implementation Plan & Task Breakdown + +Date: 2026-06-02 +Status: **Implementation plan derived strictly from the FROZEN detailed design.** Architecture is frozen (DD §24). This plan adds **no** new contracts, events, DB columns, or runtime semantics. +Branch: `GLM5-Achieve` +Audience: **context-isolated executor agents (AirDo / cheap-model subagents).** Each task below is self-contained enough that an agent holding only that task's slice can implement it correctly. + +--- + +## 0. How To Use This Plan (READ FIRST — every executor agent) + +You are likely an **isolated subagent with partial context**. To avoid the most common slice-local mistakes: + +1. **You MUST obey the 5 domain invariants** (DD §18.6), reproduced in §A1 below. Inject §A1 into your working context verbatim. INV-1 is the one partial context cannot otherwise detect. +2. **You MUST NOT introduce new public contracts, event types, DB columns, or runtime semantics.** Everything is frozen. If a task seems to need one, STOP and emit a blocker — do not improvise. (DD §0) +3. **Field naming**: exported contract fields are `snake_case`; class names `PascalCase`; private methods may be local `camelCase`. (DD §0) +4. **Import direction is one-way and enforced by lint** (DD §2, §A2). Never cross a forbidden edge. +5. **Authority precedence** when in doubt: `interface-contracts-v1.md` > `db-schema-v1.md` / `event-registry-v1.md` > `system-detailed-design.md` > this plan. This plan never overrides a frozen source; it routes you to the exact section. +6. **Definition of Done** for any code task: (a) implements the cited contract verbatim; (b) passes `bun run typecheck`; (c) has unit tests green via `bun test`; (d) respects INV-1..5; (e) crosses no forbidden import edge. Side-effect tasks additionally need evidence (test output) attached. +7. **Reference reuse**: if your task row in DD §23 names a reference project, consult it before re-deriving (renderer, diff engine, skill format, provider conversion). Reference checkouts are under `/reference/` (git-ignored). See §A3. + +**Tech stack (frozen, ADR-0002):** TypeScript on **Bun**, Bun workspaces + **Turborepo**. Worker agents are independent Bun child processes (ADR-0005). IPC is NDJSON over stdio. + +**Source-of-truth documents (all under `AirPlan/docs/architecture/`):** +`interface-contracts-v1.md`, `db-schema-v1.md`, `event-registry-v1.md`, `c4/code-view.md`, `c4/module.md`, `scheduler-state-machine-v1.md`, `main-agent-state-machine.md`, `runtime-semantics-v1.md`, `scope-escalation-v1.md`, `security-model-v1.md`, `error-taxonomy-v1.md`, `prompt-layering-v1.md`, `provider-capability-matrix-v1.md`, `capability-trust-v1.md`, `artifact-naming-v1.md`, `system-overview-design.md`, `system-detailed-design.md`. + +--- + +## 1. Phase Map & Critical Serialization + +Phases follow overview §16. **Phases must be serialized at the boundaries below; tasks *within* a phase (and across phases with no dependency) are parallelizable.** + +| Phase | Scope | Gate to next phase | +|---|---|---| +| **P0** | Monorepo skeleton + `packages/contracts` (type-only) | contracts compile; barrel exports complete | +| **P1** | `.air` project/session storage, SQLite, migrations, EventStore/Bus/Ingestor, ArtifactStore/EvidenceStore | EventStore append+project+publish green; FK-off check green | +| **P2** | ToolRegistry, PermissionEngine, built-in tools, CapabilityRegistry | tool call → permission → event flow green | +| **P3** | Provider layer (`packages/llm`), ContextAssembler, prompt resources | provider stream normalized; context assembled Anthropic-canonical | +| **P4** | Worker IPC, WorkerManager, Scheduler subsystem | worker-fixture E2E green; scheduler run_until_idle green | +| **P5** | `packages/toolchain-cpp` complete C++ workflow | cpp detect→configure→build→parse→test→cppcheck green | +| **P6** | ProjectionStore, `packages/tui` TUI/HUD | tui-smoke green; projection renders | +| **P7** | MainAgent / ArchitectureDesigner / worker-role integration | direct-mode + architecture-gate E2E green | +| **P8** | Release gates, Doctor bundle, packaging | `bun run release:check` green | + +**Hard serialization edges (overview §16):** +1. `contracts` before ALL implementation packages. +2. DB schema (migrations) before storage/EventStore tests. +3. ToolRegistry + PermissionEngine before any side-effect tool/worker. +4. Provider/context contracts before agent prompts. +5. IPC before real worker E2E. +6. Projection contracts before TUI implementation. + +**Parallelization guidance for cheap-model fan-out:** +- Within P0: all 16 contract files are independent — fan out 16-wide. +- Within P1: repositories (16) are independent of each other once `DatabaseManager`+migrations land — fan out wide; EventStore projection depends on repositories. +- Within P2: each built-in tool is independent once ToolRegistry+PermissionEngine land. +- P5 (cpp) and P6 (projection/TUI scaffolding) can overlap P4 partially since they depend on contracts + tool layer, not on Scheduler internals. + +--- + +## 2. Task ID Scheme + +`T-` e.g. `T-001` (P0), `T-1xx` (P1) … `T-8xx` (P8). Each task lists: **Files**, **Implements** (contract/DD ref), **INV** (applicable invariants), **Depends on**, **DoD/verify**. + +--- + +## Phase 0 — Skeleton & Contracts (`packages/contracts`) + +> Gate: `bun install && bun run typecheck` green at repo root; every contract symbol in `interface-contracts-v1.md` §2–§21 is exported from the barrel. Contracts package is **type-only** (DD §3) — zero runtime deps. + +### T-001 — Monorepo skeleton (root) +- **Files:** `package.json` (root, Bun workspaces), `turbo.json`, `tsconfig.base.json`, `tsconfig.json`, `bunfig.toml`, `.gitignore` (merge — keep existing `/reference/` rule), `packages/*/package.json` + `packages/*/tsconfig.json` for all 6 packages. +- **Implements:** ADR-0002 (Bun + workspaces + Turborepo); code-view §1 package list. +- **Depends on:** none. +- **DoD:** `bun install` resolves; `bun run typecheck` runs across the empty packages; package dependency graph in each `package.json` matches DD §2 allowed imports (contracts depends on nothing; runtime → contracts,llm; cli → runtime,tui,llm,cpp; tui → contracts; llm → contracts; cpp → contracts). +- **INV:** INV-4 (encode import direction in workspace deps). + +### T-002 — `contracts/ids.ts` + `error.ts` +- **Files:** `packages/contracts/src/ids.ts`, `packages/contracts/src/error.ts`. +- **Implements:** contracts §2 (primitive ID aliases, `Clock`, `IdGenerator`), §3 (`ErrorKind`, `ErrorSeverity`, `Retryability`, `AirError`). DD §3, §18.1. +- **Depends on:** T-001. +- **DoD:** all aliases + `AirError` interface exported verbatim from contracts §2/§3. Optional pure type-guard `is_air_error` allowed only if dependency-free (DD §3 IMPL). + +### T-003 — `contracts/event.ts` +- **Files:** `packages/contracts/src/event.ts`. +- **Implements:** contracts §5 (`EntityType`, `EntityRef`, `EventSource`, `RuntimeEvent`, `EventFilter`). Note `EventSource.kind` literal set `"main"|"architecture_designer"|"scheduler"|"agent"|"tool"|"system"` (DD §2, §22.1). +- **Depends on:** T-002. +- **DoD:** `RuntimeEvent` shape matches DD §22.1 exactly; `agent_type?: AgentType` optional field present. + +### T-004 — `contracts/runtime.ts` +- **Files:** `packages/contracts/src/runtime.ts`. +- **Implements:** contracts: `AgentType` (`executor|reviewer|debugger|compactor|experience_miner`), `AgentRuntimeContext`, `ContextPack`; co-locate PromptLayer types + `ContextAssembler`-facing context types per DD §3 mapping (context.ts symbols → runtime.ts). +- **Depends on:** T-002. +- **DoD:** `AgentType` union is exactly the 5 worker roles (DD §2). PromptLayer/PromptLayerLevel L0–L9 union present (DD §10.2). + +### T-005 — `contracts/ipc.ts` +- **Files:** `packages/contracts/src/ipc.ts`. +- **Implements:** contracts §10 IPC: `IpcDirection`, `IpcEnvelope`, `IpcKind`, `IpcMessage`, `ControlMessage`, payloads; plus `workers.ts` symbols (`WorkerRole`, `WorkerRuntime`, IPC payloads) merged here per DD §3. +- **Depends on:** T-003, T-004. +- **DoD:** direction typing present (parent→worker: `control`/`tool.result`/`tool.stream`; worker→parent: `event`/`log`/`tool.call`/`worker.result`/`worker.checkpoint`/`protocol.error`). DD §8.2. + +### T-006 — `contracts/task.ts` +- **Files:** `packages/contracts/src/task.ts`. +- **Implements:** contracts §9: `TaskType`, `TaskScope`, `TaskDependencySpec`, `VerificationPolicy`, `TaskConstraints`, `TaskContextRefs`, `WorkerOutputContract`, `TaskSpec`, `TaskGraph` types, `Scheduler*` (`SchedulerWavePlan`, `SchedulerRunResult`), `TransactionManager`, `Repository` (storage.ts symbols merged here per DD §3). +- **Depends on:** T-004. +- **DoD:** `TaskSpec` matches DD §22.1; `TaskType` includes `execute|review|debug|compact|mine_experience|docs` (DD §8.3). + +### T-007 — `contracts/worker-result.ts` +- **Files:** `packages/contracts/src/worker-result.ts`. +- **Implements:** contracts §11: `WorkerStatus`, `WorkerResult`, `ExecutorResult`, `ReviewerResult`, `DebuggerResult`, `CompactorResult`, `ExperienceMinerResult`, `BlockerReport`, `Risk`, `FollowUpTask`. +- **Depends on:** T-006, T-002 (AirError), T-009 (Evidence/Artifact refs) — see note. +- **DoD:** `WorkerResult` matches DD §22.1; `status ∈ {completed,failed,blocked,cancelled}`. + +### T-008 — `contracts/tool.ts` +- **Files:** `packages/contracts/src/tool.ts`. +- **Implements:** contracts §12 + §21: `ToolCategory`, `ToolDefinition`, `ToolExecutor`, `StreamingToolExecutor`, `ToolExecutionContext`, `ToolResultEnvelope`, `ToolEvent`, `ToolRegistry`, plus `Diagnostic` + `semantic_signature` types (diagnostics.ts merged here, DD §3). +- **Depends on:** T-004, T-009 (ArtifactRef/EvidenceRef referenced by envelopes). +- **DoD:** `ToolDefinition` matches DD §22.1; `Diagnostic` matches contracts §21. + +### T-009 — `contracts/artifact.ts` + `evidence.ts` +- **Files:** `packages/contracts/src/artifact.ts`, `packages/contracts/src/evidence.ts`. +- **Implements:** contracts §14: `ArtifactRef`, `ArtifactCreateInput`, `ArtifactContext`, `ArtifactReadResult`, `ArtifactStore`, `EvidenceRef`, `EvidenceCreateInput`, `EvidenceStore`; plus `knowledge.ts` symbols (`DebugKnowledgeStore`, `LearnedMemoryStore`, `DebugRecord`, `LearnedMemory`) merged into `artifact.ts` per DD §3. +- **Depends on:** T-002. +- **DoD:** `EvidenceStore.list_for_entity(entity_type, entity_id)` present (NOT `list_for_task`). `ArtifactRef` matches DD §22.1. + +### T-010 — `contracts/project.ts` +- **Files:** `packages/contracts/src/project.ts`. +- **Implements:** contracts §8: `ProjectContext`, `ProjectInitOptions`, `ProjectStore`, `SessionContext`, `OpenSessionOptions`, `SessionManager`. +- **Depends on:** T-002. +- **DoD:** matches contracts §8 verbatim. + +### T-011 — `contracts/provider.ts` +- **Files:** `packages/contracts/src/provider.ts`. +- **Implements:** contracts §15: `ProviderCapabilityMatrix`, `ModelRequirement`, `ProviderCompletionInput`, `ProviderStreamEvent`, `ProviderAdapter`, `ProviderManager`, `ModelAssignment`. +- **Depends on:** T-004. +- **DoD:** matches contracts §15; `ProviderAdapter` matches DD §22.6. + +### T-012 — `contracts/permission.ts` +- **Files:** `packages/contracts/src/permission.ts`. +- **Implements:** contracts §13: `PathPolicy`, `PermissionRequestContext`, `PermissionAction`, `PermissionGrantScope`, `PermissionDecision`, `PermissionRecordResult`, `PermissionEngine`. +- **Depends on:** T-009. +- **DoD:** `PermissionAction` covers `allow|announce_then_run|ask_user|deny|block|refuse` (DD §9.3). `PermissionDecision` matches DD §22.1. + +### T-013 — `contracts/ui.ts` +- **Files:** `packages/contracts/src/ui.ts`. +- **Implements:** contracts §17: all `*Projection`, `ProjectionSnapshot`, `ProjectionStore`, `ProjectionClient`, `UiCommandChannel`; (projection.ts symbols merged here). +- **Depends on:** T-006, T-009. +- **DoD:** `CommandRunProjection.status` derivable values match DD §4.4 (`running|ok|error|cancelled|unknown`). + +### T-014 — `contracts/capability.ts` + `platform.ts` +- **Files:** `packages/contracts/src/capability.ts`, `packages/contracts/src/platform.ts`. +- **Implements:** contracts §18 (`CapabilityManifestV1`, `ValidationResult`, `CapabilityRegistry`, trust levels), §19 (`DoctorService`, `DoctorRunInput`/`Output`, `DoctorIssue` — doctor.ts merged into platform.ts), cross-platform tier enums (from `cross-platform-matrix-v1.md`). +- **Depends on:** T-008 (ToolRegistry ref), T-002. +- **DoD:** trust levels `built_in|project_local|user_installed|verified_publisher|untrusted`; `CapabilityManifestV1.schema_version=1`. + +### T-015 — `contracts/index.ts` barrel + boundary lint +- **Files:** `packages/contracts/src/index.ts`, root ESLint/import-boundary config (e.g. `eslint-plugin-import` or `dependency-cruiser`) enforcing DD §2 / code-view §12 forbidden edges. +- **Implements:** DD §3 rule 4 (barrel exports every contract file); DD §A2 forbidden edges. +- **Depends on:** T-002..T-014. +- **DoD:** barrel re-exports the full union; `bun run typecheck` green; lint fails on a deliberately-added forbidden import (test fixture), passes otherwise. **This is the P0 gate.** + +--- + +## Phase 1 — Storage, Events, Artifacts (`packages/runtime`) + +> Gate: migrations create all db-schema §2–§18 tables; `EventStore.append` runs insert+project in one tx then publishes after commit; `SessionStore.referential_check()` green; ArtifactStore temp→rename→record green. + +### T-101 — `DatabaseManager` +- **Files:** `packages/runtime/src/storage/DatabaseManager.ts`. +- **Implements:** `TransactionManager` (contracts §6) over Bun SQLite. DD §4.1. +- **INV:** enables INV-1/INV-2 infra (single-writer tx). +- **Depends on:** T-006, T-015. +- **DoD:** on `open` sets `journal_mode=WAL`, `synchronous=NORMAL`, `foreign_keys=OFF` (db-schema §1); `transaction` wraps BEGIN/COMMIT/ROLLBACK; nested calls reuse active handle. + +### T-102 — `MigrationRunner` + full V1 schema +- **Files:** `packages/runtime/src/storage/MigrationRunner.ts`. +- **Implements:** DD §4.2; creates ALL tables/indexes from `db-schema-v1.md` §2–§18; seeds `schema_meta` (`schema_version=1`). +- **Depends on:** T-101. +- **DoD:** idempotent create-on-empty; `currentVersion`/`targetVersion()=1`; updates `aircoding_version_last_opened` on open. Unit test: fresh DB → all 17 session tables present. + +### T-103 — `assert_enum` helper + enum table +- **Files:** `packages/runtime/src/storage/assertEnum.ts`. +- **Implements:** DD §4.5; backs every closed-enum TEXT column (db-schema §21, 18 rows). Throws `AirError{kind:"system_error"}` on violation. +- **Depends on:** T-102, T-002. +- **DoD:** rejects an invalid enum value for each of the 18 columns (table-driven test). + +### T-104..T-119 — Repositories (one task each, all parallel after T-103) +Each implements `Repository<...>` (contracts §6), thin persistence only (no policy). Records mirror db-schema columns `snake_case`. DD §4.3. + +| Task | File | Table (db-schema §) | Extra methods (DD §4.3) | +|---|---|---|---| +| T-104 | `repositories/SessionRepository.ts` | sessions (§3) | `list_active()` | +| T-105 | `repositories/MessageRepository.ts` | messages (§4) | `list_by_session(session_id, since?)` | +| T-106 | `repositories/MessageDraftRepository.ts` | message_drafts (§5) | `upsert`, `delete_for_message` | +| T-107 | `repositories/EventRepository.ts` | events (§6) | `insert(rec,tx)`, `query(filter)` | +| T-108 | `repositories/TaskRepository.ts` | tasks (§7) | `list_by_status`, `list_runnable_candidates` | +| T-109 | `repositories/TaskDependencyRepository.ts` | task_dependencies (§8) | `list_for_task`, `list_dependents` | +| T-110 | `repositories/TaskAttemptRepository.ts` | task_attempts (§9) | `next_attempt_index`, `list_by_task` | +| T-111 | `repositories/AgentRepository.ts` | agents (§10) | `list_active`, `update_heartbeat` | +| T-112 | `repositories/ToolRunRepository.ts` | tool_runs (§11) | `list_by_task`, `list_by_origin_message` | +| T-113 | `repositories/CommandRunRepository.ts` | command_runs (§12) | `list_by_task` + `derive_command_status` (DD §4.4) | +| T-114 | `repositories/ArtifactRepository.ts` | artifacts (§13) | `list_by_entity`, `get_by_uri` | +| T-115 | `repositories/DiagnosticRepository.ts` | diagnostics (§14) | `list_by_signature`, `list_by_command_run` | +| T-116 | `repositories/EvidenceRepository.ts` | evidence_refs (§15) | `list_for_entity(type,id)` | +| T-117 | `repositories/WorkspaceRepository.ts` | workspaces (§16) | `list_by_status`, `list_gc_candidates` | +| T-118 | `repositories/SummaryRepository.ts` | summaries (§17) | `get`, `insert` | +| T-119 | `repositories/UiStateRepository.ts` | ui_state (§18) | `upsert(scope,key,value)`, `read(scope,key)` | + +- **INV (all):** INV-1 — repositories are storage-only; they **do not** set status columns by policy. Status columns are written only via EventStore.project. **Exemptions:** T-111 `update_heartbeat` (agents.last_heartbeat_at) and T-119 ui_state are the explicit INV-1 exemptions (DD §18.6). +- **Depends on:** T-103. +- **DoD (each):** CRUD + listed methods; columns match db-schema exactly; unit test round-trips a row. + +### T-120 — `SessionStore` aggregate + `referential_check()` +- **Files:** `packages/runtime/src/sessions/SessionStore.ts`. +- **Implements:** DD §4.3 aggregate; `referential_check(): OrphanReport` implementing the 8 FK-off invariants (DD §18.3). +- **Depends on:** T-104..T-119. +- **DoD:** exposes all 16 repositories; `referential_check` detects each of the 8 invariant violations (table-driven test). + +### T-121 — `EventSchemaRegistry` +- **Files:** `packages/runtime/src/events/EventSchemaRegistry.ts`. +- **Implements:** contracts §7; DD §5.2. Seeded from `event-registry-v1.md` §3 (durable) + §4 (ephemeral). +- **Depends on:** T-003, T-015. +- **DoD:** `register/validate/list/get_schema`; unknown type+version fails → ingestion can reject with `system_error`; all 55 durable + 7 ephemeral types registered. + +### T-122 — `EventStore` (append + projection map) +- **Files:** `packages/runtime/src/events/EventStore.ts`. +- **Implements:** contracts §7; DD §5.3 + **§5.4 projection map (Table A + Table B)**. `append` = tx{ validate → EventRepository.insert → project(event,tx) } then `EventBus.publish` AFTER commit. +- **INV:** **INV-1 (this is the ONLY place status columns are written)**, INV-2 (project never opens external DB/file), INV-5 (publish is post-commit transport). +- **Depends on:** T-120, T-121, T-123 (EventBus). +- **DoD:** every durable event in event-registry §3 has a projection case (Table A); Table B events (`memory.promoted`, `memory.archived`, `debug.record.created`) append event row only, no external write; project() throw → full rollback, no publish (DD §5.3 error handling). Unit test per projection case. + +### T-123 — `EventBus` +- **Files:** `packages/runtime/src/events/EventBus.ts`. +- **Implements:** contracts §7; DD §5.5. Live transport only; handler throw is caught+logged, subscription survives; `drain()` flushes; ephemeral coalescing for the 7 ephemeral types. +- **INV:** INV-5. +- **Depends on:** T-003, T-015. +- **DoD:** publish/subscribe/match/drain; never a recovery source. + +### T-124 — `EventIngestor` +- **Files:** `packages/runtime/src/events/EventIngestor.ts`. +- **Implements:** contracts §7; DD §5.1. `ingest` routes durable→EventStore.append, ephemeral→EventBus.publish by registry policy. +- **Depends on:** T-122, T-123. +- **DoD:** durable type → EventStore path; ephemeral type → bus path; never creates tasks/permissions/memory itself. + +### T-125 — `ProjectStore` (+ `ProjectLocator`, `ProjectInitializer`) +- **Files:** `packages/runtime/src/project/ProjectStore.ts`, `ProjectLocator.ts`, `ProjectInitializer.ts`. +- **Implements:** contracts §8; DD §6.1. `.air/shared` + `.air/local` scaffolding (overview §8.1); stable `project_id` UUID in `.air/shared/project.json`. +- **Depends on:** T-010, T-015. +- **DoD:** `locate` walks up to `.air/shared/project.json`; `initialize` creates trees + project_id; `open` loads ProjectContext. No session DB created until session opens. + +### T-126 — `SessionManager` +- **Files:** `packages/runtime/src/sessions/SessionManager.ts`. +- **Implements:** contracts §8; DD §6.2. `open_session` computes db_path, opens+migrates, ingests `session.created`; provider/model fixed at open (immutable, overview §14). +- **Depends on:** T-125, T-126-dep: T-124, T-102, T-120. +- **DoD:** open→migrate→ingest `session.created`→returns SessionContext; `close_session` flushes ui_state + releases handle. + +### T-127 — `ArtifactStore` +- **Files:** `packages/runtime/src/artifacts/ArtifactStore.ts`. +- **Implements:** contracts §14; DD §11.1; naming from `artifact-naming-v1.md`. +- **INV:** INV-1 (artifact.created writes session row via projection — store calls EventIngestor, does not UPDATE). +- **Depends on:** T-124, T-009. +- **DoD:** `create` = write temp → sha256+size → atomic rename → ingest `artifact.created`; `artifact_id=art_`; uri/filename per artifact-naming-v1; type from closed set. DB-insert-after-rename failure path documented for recovery (DD §16.3). + +### T-128 — `EvidenceStore` +- **Files:** `packages/runtime/src/artifacts/EvidenceStore.ts`. +- **Implements:** contracts §14; DD §11.2. +- **INV:** INV-1. +- **Depends on:** T-124, T-009. +- **DoD:** `create` ingests `evidence.created`; `list_for_entity(entity_type,entity_id)`; `kind` from closed set. + +### T-129 — Recovery: orphan-artifact + FK-off scan wiring +- **Files:** `packages/runtime/src/storage/Recovery.ts` (recovery helpers used by SessionManager/Scheduler startup). +- **Implements:** DD §16.3 steps 5–6 (orphan-artifact scan; FK-off orphan scan calls `SessionStore.referential_check`). +- **Depends on:** T-120, T-127. +- **DoD:** orphaned artifact file → registered or quarantined; dangling ref → logged + re-parented/archived. (Full recovery sequence completed in P4 T-4xx.) + +--- + +## Phase 2 — Tools, Permission, Capability (`packages/runtime`) + +> Gate: `ToolRegistry.call` runs lookup→validate→PermissionEngine.evaluate→branch→emit tool.started→execute→emit tool.completed/failed/cancelled. No side effect bypasses PermissionEngine (code-view §12). + +### T-201 — `PathClassifier` +- **Files:** `packages/runtime/src/security/PathClassifier.ts`. +- **Implements:** DD §9.2; `security-model-v1.md`. 8 path categories; realpath normalization before prefix checks; `.git/` internals protected. +- **Depends on:** T-012. +- **DoD:** classifies the 8 categories; symlink escape not allowed by string-prefix (realpath test). + +### T-202 — `CommandRiskAnalyzer` +- **Files:** `packages/runtime/src/security/CommandRiskAnalyzer.ts`. +- **Implements:** DD §9.2; security-model-v1. 10 command-risk categories; `sudo` risk by intent/target, not string alone (DD §18.5). +- **Depends on:** T-012. +- **DoD:** 10 categories covered; destructive command flagged; intent-based sudo test. + +### T-203 — `SecretRedactor` +- **Files:** `packages/runtime/src/security/SecretRedactor.ts`. +- **Implements:** DD §9.2 / §16.2. Redacts secrets/auth refs/provider keys for logs/evidence. +- **Depends on:** T-001. +- **DoD:** redacts known secret patterns; shared by PermissionEngine + Logger. + +### T-204 — `PermissionEngine` +- **Files:** `packages/runtime/src/security/PermissionEngine.ts`. +- **Implements:** contracts §13; DD §9.2. Layered order 1–6 (capability → profile → task scope → risk → credential override → user prompt). `record` writes `permission.decision.recorded`. +- **INV:** INV-3 (the mandatory gate for all side effects). +- **Depends on:** T-201, T-202, T-203, T-124. +- **DoD:** project-allow never overrides task scope; credential/system-sensitive overrides broad allow; realpath prefix; `record` returns `{ok:false,error}` on write failure. + +### T-205 — `ToolRegistry` +- **Files:** `packages/runtime/src/tools/ToolRegistry.ts`. +- **Implements:** contracts §12; DD §9.1 + §9.3 branching table. +- **INV:** INV-3. +- **Depends on:** T-204, T-124, T-127 (backup/artifact). +- **DoD:** `call`/`call_streaming` per DD §9.1 algorithm; branches on all 6 `PermissionAction`s (DD §9.3); `call_streaming` ends with exactly one final `ToolResultEnvelope`. + +### T-206..T-213 — Built-in tools (one task each, parallel after T-205) +Each: a `ToolDefinition` (declares `category`,`permissions`,`streaming`) + `ToolExecutor`, registered via `BuiltInToolRegistrar`. DD §9.1, code-view §4. + +| Task | File group | Tools | Notes / DD | +|---|---|---|---| +| T-206 | `tools/fs/` | `fs.read`, `fs.edit`, `fs.patch`, `fs.write`, `fs.list` | **read-before-edit + exact-edit enforced at tool layer** (DD §9.4); successful edit/patch emits diff artifact. Reference: DD §23 (Claude Code behavioral, Codex pattern). | +| T-207 | `tools/shell/` | `shell.run` | emits `command.started`/`command.completed`; streaming stdout/stderr deltas (ephemeral). | +| T-208 | `tools/git/` | `git.*` (status/diff/commit/branch/merge as scoped) | `.git/` internals protected (DD §18.5). | +| T-209 | `tools/project/` | `project.*` (rules/context read) | read-only project metadata. | +| T-210 | `tools/artifact/` | `artifact.create/read` | wraps ArtifactStore. | +| T-211 | `tools/context/` | `context.*` (assemble/compact triggers) | wraps ContextAssembler (available P3). Stub acceptable in P2; finalize in P3. | +| T-212 | `tools/permission/` | `permission.*` (prompt resolve plumbing) | emits `permission.prompt.requested/resolved`. | +| T-213 | `tools/doctor/` | `doctor.*` | wraps DoctorService (P8). Stub acceptable in P2. | +| T-214 | `tools/BuiltInToolRegistrar.ts` | registrar | registers all of the above into a ToolRegistry. | + +- **INV (all):** INV-3 (every tool goes through evaluate first — guaranteed by going through ToolRegistry.call, do NOT call side effects directly). +- **Depends on:** T-205. +- **DoD (each):** input schema validated; permission consulted; correct events emitted; unit test with a fake PermissionEngine returning each action. + +### T-215 — `CapabilityManifestValidator` +- **Files:** `packages/runtime/src/capabilities/CapabilityManifestValidator.ts`. +- **Implements:** contracts §18; DD §9.5. Validates `schema_version=1`, tool schemas, permissions. +- **Depends on:** T-014. +- **DoD:** accepts a valid manifest, rejects bad schema_version/missing fields. + +### T-216 — `CapabilityRegistry` +- **Files:** `packages/runtime/src/capabilities/CapabilityRegistry.ts`. +- **Implements:** contracts §18; DD §9.5. Lifecycle discovered→validated→doctor_checked→enabled→registered→active. Trust levels affect default posture, never bypass ToolRegistry/PermissionEngine. +- **INV:** INV-4 (dependency installs go only through Doctor). +- **Depends on:** T-215, T-205. +- **DoD:** `discover/validate/enable/disable/register_tools`; enabling registers tools into ToolRegistry; dependency install delegates to Doctor (no direct install). + +--- + +## Phase 3 — Provider & Context (`packages/llm` + `packages/runtime/context`) + +> Gate: provider stream normalized to `ProviderStreamEvent`; `ContextAssembler.assemble` returns Anthropic-canonical AssembledContext; prompt layers L0–L9 ordered. + +### T-301 — `ModelConfigLoader` +- **Files:** `packages/llm/src/ModelConfigLoader.ts`. +- **Implements:** DD §12.2. Loads global `~/.air/models.yaml` + project config. +- **Depends on:** T-011, T-001. +- **DoD:** loads model config; validates required fields. + +### T-302 — `CapabilityMatrixRegistry` +- **Files:** `packages/llm/src/CapabilityMatrix.ts`. +- **Implements:** DD §12.2; holds `ProviderCapabilityMatrix` rows (`provider-capability-matrix-v1.md`). +- **Depends on:** T-011. +- **DoD:** lookup by provider/model; matches matrix doc. + +### T-303 — `AnthropicCanonicalConverter` + `ToolUseConverter` + `StreamNormalizer` +- **Files:** `packages/llm/src/canonical/AnthropicCanonical.ts`, `ToolUseConverter.ts`, `StreamNormalizer.ts`. +- **Implements:** DD §12.2; Anthropic-canonical internal format (D-016 / DD §23 behavioral ref: Claude Code message model). **Must not silently drop semantic prompt/tool info** (contracts §23). +- **Reference:** DD §23 — `@opencode-ai/llm` (fork/adapt) for conversion structure; Claude Code message model (behavioral). +- **Depends on:** T-011. +- **DoD:** round-trips canonical↔provider for text/thinking/tool_use/tool_result blocks; conversion report flags any dropped field. + +### T-304 — `AnthropicAdapter` +- **Files:** `packages/llm/src/adapters/AnthropicAdapter.ts`. +- **Implements:** `ProviderAdapter` (contracts §15); DD §12.2. +- **Depends on:** T-303. +- **DoD:** `list_models/validate_model/complete/count_tokens?`; streams normalized events. + +### T-305 — `OpenAICompatibleAdapter` +- **Files:** `packages/llm/src/adapters/OpenAICompatibleAdapter.ts`. +- **Implements:** `ProviderAdapter`; uses `AnthropicCanonicalConverter`. +- **Depends on:** T-303. +- **DoD:** converts canonical↔OpenAI-compatible; streams normalized; no silent semantic loss. + +### T-306 — `ProviderManager` +- **Files:** `packages/llm/src/ProviderManager.ts`, `packages/llm/src/index.ts` (facade export). +- **Implements:** contracts §15; DD §12.1. `load_config/select_model/complete`; `adapter_for`. No runtime model switching (immutable per session). +- **INV:** INV-4 (runtime calls llm only via this facade). +- **Depends on:** T-301, T-302, T-304, T-305. +- **DoD:** `select_model` matches ModelRequirement against matrix → ModelAssignment; `complete` routes to adapter; facade is the only export surface runtime imports. + +### T-307 — `PromptLayerLoader` +- **Files:** `packages/runtime/src/context/PromptLayerLoader.ts`. +- **Implements:** contracts §16; DD §10.2. 4 methods: `load_runtime_invariant` (L0), `load_role` (L1, worker AgentType only), `load_project_rules` (L3), `load_task_context` (L5). +- **Depends on:** T-004, T-010. +- **DoD:** loads L0/L1/L3/L5; `load_role` accepts only worker AgentType (runtime roles load built-in directly). + +### T-308 — Built-in prompt resources (L0/L1) +- **Files:** `packages/runtime/src/context/prompts/` (runtime_invariant.md, roles/{executor,reviewer,debugger,compactor,experience_miner}.md, main.md, architecture.md). +- **Implements:** prompt-layering-v1 L0/L1; DD §10.2. Inject §A1 (INV-1..5) into runtime_invariant L0. +- **Depends on:** T-307. +- **DoD:** L0 includes the 5 invariants; each worker role + main + architecture has a role prompt. + +### T-309 — `CompactionPolicy` +- **Files:** `packages/runtime/src/context/CompactionPolicy.ts`. +- **Implements:** contracts §16; DD §10.3. `should_compact`, `compact` (compaction is executed by CompactorRole; policy decides + summarizes interface). +- **Depends on:** T-004. +- **DoD:** `should_compact` honors token budget; sequence ref documented (requested→started→summary.created→completed). + +### T-310 — `ContextAssembler` +- **Files:** `packages/runtime/src/context/ContextAssembler.ts`. +- **Implements:** contracts §16; DD §10.1 + §10.2 layer-assembly table (L2/L4/L6/L7/L8/L9 internal). +- **INV:** reads EvidenceStore (L6) + SessionStore (L7/L8) — read-only. +- **Depends on:** T-307, T-309, T-120, T-128. +- **DoD:** `assemble` → Anthropic-canonical AssembledContext; fits token_budget, reports omissions; writes messages artifact + sets `messages_artifact_id` when too large; sets `compaction_requested=true` when required layers don't fit; L0/L1/L2 never dropped. + +--- + +## Phase 4 — Worker IPC & Scheduler (`packages/runtime` + `packages/workers`) + +> Gate: worker-fixture E2E green (spawn→handshake→tool.call round-trip→worker.result); `Scheduler.run_until_idle` drives §20.2 to a terminal state. + +### T-401 — `WorkerProtocol` +- **Files:** `packages/runtime/src/workers/WorkerProtocol.ts`. +- **Implements:** contracts §10; DD §8.2. NDJSON encode/decode, direction validation, protocol-version check. +- **Depends on:** T-005. +- **DoD:** encode/decode NDJSON line; `validate_direction` rejects wrong-channel msg; version mismatch handling. + +### T-402 — `WorkerProcess` +- **Files:** `packages/runtime/src/workers/WorkerProcess.ts`. +- **Implements:** DD §8.1. Owns NDJSON pipe; stdout=protocol, stderr=fatal/log; exit-code table 0–5. +- **Depends on:** T-401. +- **DoD:** send/on_message; exit-code semantics per DD §8.1 table. + +### T-403 — `WorkerManager` +- **Files:** `packages/runtime/src/workers/WorkerManager.ts`. +- **Implements:** DD §8.1. `spawn` (Bun child process + handshake), `cancel`. +- **INV:** **INV-1 — WorkerManager never writes `agents.status` directly**; `worker.ready` handshake is a live signal, not a status write. `agent.started` projection sets status. +- **Depends on:** T-402, T-124. +- **DoD:** spawn→handshake (`agent.start`→`worker.ready`→validate protocol_version); cancel terminates worker; no direct agents.status UPDATE. + +### T-404 — `WorkerRuntime` (in-worker side-effect surface) +- **Files:** `packages/workers/src/WorkerRuntime.ts`. +- **Implements:** contracts §10; DD §8.3. `emit`/`call_tool`/`checkpoint` — all via IPC to parent. +- **INV:** **INV-3 — workers reach fs/shell/network/SQLite ONLY through parent-mediated tool IPC.** Never open SQLite or touch fs directly. +- **Depends on:** T-401, T-005. (`packages/workers` imports only contracts + IPC surface — DD §2.) +- **DoD:** `call_tool` → IPC `tool.call` → awaits `tool.result`; `emit` → IPC `event`; `checkpoint` → IPC `worker.checkpoint`. No direct side effects. + +### T-405..T-409 — Worker roles (one task each, parallel after T-404) +Each implements `WorkerRole` (contracts §10/§11); DD §8.3/§8.4. + +| Task | File | Role | Output | Write access | +|---|---|---|---|---| +| T-405 | `packages/workers/src/roles/ExecutorRole.ts` | Executor (also handles `docs`) | ExecutorResult | scoped project writes | +| T-406 | `packages/workers/src/roles/ReviewerRole.ts` | Reviewer | ReviewerResult | read-only | +| T-407 | `packages/workers/src/roles/DebuggerRole.ts` | Debugger | DebuggerResult | scoped writes when assigned | +| T-408 | `packages/workers/src/roles/CompactorRole.ts` | Compactor | CompactorResult | summaries/artifacts only | +| T-409 | `packages/workers/src/roles/ExperienceMinerRole.ts` | ExperienceMiner | ExperienceMinerResult | candidates/rules/skills when assigned | + +- **INV (all):** INV-3 (all side effects via `WorkerRuntime.call_tool`). Executor/Debugger also enforce DD §8.4: read-before-edit, stay in write_area, run verification before `completed`, attach evidence. +- **Depends on:** T-404. +- **DoD (each):** `run` returns `WorkerResult` with matching `agent_type`; code-changing result not `completed` unless verification passed or skipped-with-evidence; self-escalation returns `blocked` + BlockerReport. + +### T-410 — worker entrypoint +- **Files:** `packages/workers/src/main.ts` (child-process entry; reads `agent.start`, dispatches to role, returns `worker.result`). +- **Depends on:** T-405..T-409. +- **DoD:** handshake replies `worker.ready{protocol_version,worker_version}`; routes TaskType→role (DD §8.3 mapping); exit codes per DD §8.1. + +### T-411 — `TaskGraph` +- **Files:** `packages/runtime/src/scheduler/TaskGraph.ts`. +- **Implements:** DD §7.2. `get_runnable_tasks` (hard deps done, conflicts blocked), `mark_terminal`, `dependents_of`, `validate_refs`. +- **Depends on:** T-006, T-120. +- **DoD:** dependency semantics per scheduler-state-machine §4; FK-off `validate_refs`. + +### T-412 — `WavePlanner` +- **Files:** `packages/runtime/src/scheduler/WavePlanner.ts`. +- **Implements:** DD §7.3. `plan`→SchedulerWavePlan; serialize write conflicts; `assign_workspace`; `assign_model`. +- **Depends on:** T-411, T-306. +- **DoD:** different write areas→concurrent; same uncertain area→serialize; reviewers concurrent except vs unstable outputs; resource cap; inferred conflict/serialization edges persisted via task_dependencies + events. + +### T-413 — `RetryPlanner` +- **Files:** `packages/runtime/src/scheduler/RetryPlanner.ts`. +- **Implements:** DD §7.4. `decide`→RetryDecision (`retry|retry_serial|debug|skip|block|cancel`). +- **Depends on:** T-006, T-002. +- **DoD:** identical failure_signature escalates faster; env impossibility→block; arch/interface mismatch→route to ArchitectureDesigner; budget = retry_budget. + +### T-414 — `WorkspaceManager` +- **Files:** `packages/runtime/src/scheduler/WorkspaceManager.ts`. +- **Implements:** DD §7.5. `create_workspace`/`merge_workspace`/`cleanup_workspace`. Strategies main/worktree/isolated_copy. **Mechanism owner only — never plans.** +- **INV:** INV-1 (workspaces.status only via workspace.* event projection). +- **Depends on:** T-124, T-117, T-208 (git). +- **DoD:** emits workspace.created/merge.started/merge.completed|conflicted/cleaned; GC retention (active→merged 7d→cleaned; abandoned 3d). + +### T-415 — `AgentMonitor` +- **Files:** `packages/runtime/src/scheduler/AgentMonitor.ts`. +- **Implements:** DD §7.6. `record_heartbeat` (coalesced), `detect_lost_agents`, `enforce_timeouts`. +- **INV:** INV-1 exemption — heartbeat timestamps are the ONLY direct writes allowed (agents.last_heartbeat_at, tasks.heartbeat_at). +- **Depends on:** T-111, T-124. +- **DoD:** 5s coalescing; missing heartbeat→inspect→ping/soft-cancel or `agent.lost`; soft/hard timeout per scheduler-state-machine §MONITORING. + +### T-416 — `Scheduler` +- **Files:** `packages/runtime/src/scheduler/Scheduler.ts`. +- **Implements:** contracts §9; DD §7.1 + state machine §20.2. +- **INV:** **INV-1 (status only via emitted events for projection), INV-5 (rebuild queues from SQLite, not EventBus replay).** +- **Depends on:** T-411, T-412, T-413, T-414, T-415, T-403, T-310. +- **DoD:** `create_tasks` ingests task.created; `run_until_idle` drives IDLE→LOADING_GRAPH→PLANNING_WAVE→DISPATCHING→MONITORING→COLLECTING_RESULTS→(MERGING|REVIEWING_WAVE|REPAIRING_OR_CONTINUING)→terminal; never prompts directly (via Main Agent/PermissionEngine). + +### T-417 — Recovery completion (startup/resume) +- **Files:** extend `packages/runtime/src/storage/Recovery.ts`. +- **Implements:** DD §16.3 full 8-step sequence (load running/interrupted tasks, PID liveness, agent.lost, preserve workspaces, orphan scan, FK-off scan, workspace GC, rebuild queue). +- **INV:** INV-5 (rebuild from SQLite). +- **Depends on:** T-416, T-129. +- **DoD:** restart with in-flight tasks reconstructs scheduler queue; dead PID→agent.lost; workspaces preserved until decision. + +### T-418 — worker-fixture E2E +- **Files:** `packages/runtime/test/e2e/worker-fixture.test.ts` + fixture worker. +- **Implements:** overview §17 `e2e worker-fixture`. +- **Depends on:** T-410, T-416. +- **DoD:** spawn→handshake→tool.call round-trip→worker.result→task.completed; **P4 gate**. + +--- + +## Phase 5 — C++ Toolchain (`packages/toolchain-cpp`) + +> Gate: detect→configure→build→parse diagnostics→test→cppcheck green on a fixture C++ project. Exposed via capability registration (code-view §2 rule 4), not direct runtime coupling. + +### T-501 — `DiagnosticParser` +- **Files:** `packages/toolchain-cpp/src/analysis/DiagnosticParser.ts`. +- **Implements:** DD §15. `parse_compiler_output`→Diagnostic[] (contracts §21), `semantic_signature` (deterministic; NO LLM here). +- **Depends on:** T-008. +- **DoD:** parses gcc/clang output to Diagnostic; stable semantic_signature. + +### T-502 — `CppProjectDetector` +- **Files:** `packages/toolchain-cpp/src/detect/CppProjectDetector.ts`. +- **Implements:** DD §15. `detect`→CppDetectOutput. +- **Depends on:** T-008. +- **DoD:** detects CMake/Make project, toolchain presence. + +### T-503 — `CMakeConfigurator` +- **Files:** `packages/toolchain-cpp/src/build/CMakeConfigurator.ts`. +- **Implements:** DD §15. CMake+Ninja preferred, Make fallback; generates/locates `compile_commands.json`. +- **Depends on:** T-501. +- **DoD:** configure output + compile_commands.json path. + +### T-504 — `CppBuilder` +- **Files:** `packages/toolchain-cpp/src/build/CppBuilder.ts`. +- **Implements:** DD §15. `build`→CppBuildOutput; diagnostics via DiagnosticParser. +- **Depends on:** T-501, T-503. +- **DoD:** build + parsed diagnostics. + +### T-505 — `CppTestRunner` +- **Files:** `packages/toolchain-cpp/src/test/CppTestRunner.ts`. +- **Implements:** DD §15. `run_tests`→CppTestOutput. +- **Depends on:** T-501. +- **DoD:** runs ctest/test target; parses results. + +### T-506 — `CppcheckRunner` +- **Files:** `packages/toolchain-cpp/src/analysis/CppcheckRunner.ts`. +- **Implements:** DD §15. `run`→CppcheckOutput; exhaustive branch checking. +- **Reference:** DD §23 (airsdb cppcheck pattern, asciinema/atuin PTY not needed here). +- **Depends on:** T-501. +- **DoD:** cppcheck invocation + parsed diagnostics. + +### T-507 — `ClangdClient` +- **Files:** `packages/toolchain-cpp/src/analysis/ClangdClient.ts`. +- **Implements:** DD §15. `query`→ClangdQueryOutput (uses compile_commands.json). +- **Depends on:** T-501, T-503. +- **DoD:** clangd LSP query for symbol/diagnostic. + +### T-508 — `CppToolRegistrar` + capability manifest +- **Files:** `packages/toolchain-cpp/src/CppToolRegistrar.ts`, `packages/toolchain-cpp/src/capability.ts`, `index.ts`. +- **Implements:** DD §15; registers `cpp.*` tools through CapabilityRegistry. +- **INV:** INV-4 (registered via capability boundary, not direct runtime import). +- **Depends on:** T-502..T-507, T-216. +- **DoD:** `cpp.*` tools registered through capability registration; **P5 gate** (cpp fixture E2E). + +--- + +## Phase 6 — Projection & TUI (`packages/runtime/projection` + `packages/tui`) + +> Gate: tui-smoke green; projections render from snapshot+events. TUI imports ONLY contracts + ProjectionClient (code-view §2 rule 3 / §7). + +### T-601 — `ProjectionStore` +- **Files:** `packages/runtime/src/projection/ProjectionStore.ts`, `projections/*`. +- **Implements:** contracts §17; DD §13.1. `hydrate` (from repositories), `apply` (durable + key ephemeral), `snapshot`, `subscribe`. command_runs status via DD §4.4. Never a scheduling/recovery source. +- **Depends on:** T-013, T-120, T-123. +- **DoD:** hydrate rebuilds from DB; apply handles all durable + listed ephemeral; unknown events ignored. + +### T-602 — `ProjectionClient` + `TuiApp` shell +- **Files:** `packages/tui/src/ProjectionClient.ts`, `packages/tui/src/TuiApp.tsx`, `index.ts`. +- **Implements:** contracts §17; DD §13.2. In-process ProjectionClient (direct ref, not IPC). +- **Reference:** DD §23 — **OpenTUI `@opentui/*` is `npm-dep`, do NOT build a renderer**; OpenCode TUI patterns (pattern, no SDK/session state). +- **INV:** INV-4 (tui imports only contracts). +- **Depends on:** T-601. +- **DoD:** TuiApp start/stop; consumes ProjectionClient; no runtime-private import, no SQLite, no EventBus subscribe. + +### T-603..T-610 — TUI components (parallel after T-602) +| Task | File | Component | DD/notes | +|---|---|---|---| +| T-603 | `components/SessionView.tsx` | SessionView | render session projection | +| T-604 | `components/TaskListView.tsx` | TaskListView | render tasks | +| T-605 | `components/AgentStatusView.tsx` | AgentStatusView | render agents | +| T-606 | `components/ToolRunView.tsx` | ToolRunView | render tool/command runs | +| T-607 | `components/DiffView.tsx` + `EvidenceView.tsx` | Diff/Evidence | link back to artifact/evidence refs (code-view §7 rule 5) | +| T-608 | `components/PermissionPrompt.tsx` | PermissionPrompt | emits via UiCommandChannel only (never private services) | +| T-609 | `components/BlockerReport.tsx` | BlockerReport | render BlockerReport | +| T-610 | `components/HudView.tsx` + `theme/` + `keymap/` | HudView | HUD presets Full/Essential/Minimal; reference claude-hud/atuin/asciinema (pattern) | + +- **INV (all):** components render projections only; never mutate domain tables; permission decisions only via UiCommandChannel. +- **Depends on:** T-602. +- **DoD (each):** renders from snapshot; no domain mutation. **P6 gate:** tui-smoke. + +--- + +## Phase 7 — Agents Integration (`packages/runtime/agents`) + +> Gate: direct-mode-fixture + architecture-review-gate E2E green. + +### T-701 — `MainAgent` +- **Files:** `packages/runtime/src/agents/main/MainAgent.ts`. +- **Implements:** DD §14.1 + state machine §20.1 (main-agent-state-machine.md). +- **INV:** INV-1 (no direct status writes; works via Scheduler/events), INV-3. +- **Depends on:** T-416, T-310, T-306. +- **DoD:** `handle_user_message`→classify→ANSWERING|DELEGATING|DIRECT_MODE; full lifecycle to SUMMARIZING→IDLE; direct mode uses `main_direct` template; emits `requirement.changed`; confirmation gating per state machine. + +### T-702 — `ArchitectureDesigner` +- **Files:** `packages/runtime/src/agents/architecture/ArchitectureDesigner.ts`. +- **Implements:** DD §14.2 + sequence §19.4. Review gate; result classes `silent_continue|requires_user_confirmation|requires_replan|reject_or_escalate` (scope-escalation §4). +- **INV:** INV-3 (doc writes via ToolRegistry+PermissionEngine; no direct fs/shell). +- **Depends on:** T-310, T-306, T-124. +- **DoD:** `assess_impact`→ArchitectureImpact; emits `architecture.impact.completed`; `update_architecture_docs` only if confirmed→`architecture.plan.updated`; never replaces Reviewer. + +### T-703 — `DebugKnowledgeStore` +- **Files:** `packages/runtime/src/knowledge/DebugKnowledgeStore.ts`. +- **Implements:** contracts §20; DD §11.3. Project DB `debug-records.db`. +- **INV:** **INV-2 (single writer; outbox: external write first → then emit `debug.record.created`).** +- **Depends on:** T-009, T-124. +- **DoD:** insert/lookup_by_signature/lookup_by_task/update; outbox sequence per DD §18.4; never written by anyone else. + +### T-704 — `LearnedMemoryStore` +- **Files:** `packages/runtime/src/knowledge/LearnedMemoryStore.ts`. +- **Implements:** contracts §20; DD §11.3. Project DB `learned-memory.db`. +- **INV:** **INV-2 (single writer; outbox: external write first → then emit `memory.promoted`).** +- **Reference:** DD §23 — Hermes Agent (pattern: Nudge/Curator); Anthropic Skills (pattern: SKILL.md format). +- **Depends on:** T-009, T-124. +- **DoD:** insert/lookup_by_type/update_status/scan_stale; `memory.promoted`/`memory.archived` outbox semantics (DD §18.4); never written by anyone else. + +### T-705 — Role integration wiring + knowledge sequences +- **Files:** wiring in `Scheduler`/`agents` to route DebuggerRole↔DebugKnowledgeStore and ExperienceMinerRole↔LearnedMemoryStore per sequences §19.5. +- **Depends on:** T-703, T-704, T-407, T-409, T-416. +- **DoD:** debug-knowledge-capture (§19.5) green; experience-mining promotes via outbox. + +### T-706 — agent E2E fixtures +- **Files:** `packages/runtime/test/e2e/{direct-mode-fixture,architecture-review-fixture}.test.ts`. +- **Implements:** overview §17 additional UX gates. +- **Depends on:** T-701, T-702. +- **DoD:** direct-mode + architecture-gate E2E green; **P7 gate**. + +--- + +## Phase 8 — CLI, Doctor, Release (`packages/cli` + `packages/runtime/doctor`) + +> Gate: `bun run release:check` green; full validation suite (overview §17). + +### T-801 — `Logger` + `DeveloperLogEncryptor` +- **Files:** `packages/runtime/src/logging/Logger.ts`, `DeveloperLogEncryptor.ts`. +- **Implements:** DD §16.2. `air.log` (redacted user-facing) + `air.developer.log` (encrypted). Uses SecretRedactor. +- **Depends on:** T-203. +- **DoD:** redacts secrets in both logs; encrypts developer log chunks. + +### T-802 — `DoctorService` +- **Files:** `packages/runtime/src/doctor/DoctorService.ts`, `checks/*`. +- **Implements:** contracts §19; DD §16.1. Self-bootstrap (Bun/SQLite/shell/.air writability) before capability checks; modes read_only/fix(under PermissionEngine)/bundle. +- **INV:** INV-4 (dependency installs originate here). +- **Depends on:** T-216, T-204, T-127. +- **DoD:** self_bootstrap blocks on failure; emits `doctor.*`; bundle = local artifact, no auto-upload (DD §18.5). + +### T-803 — `RuntimeApp` + `ServiceRegistry` + `RuntimeFactory` +- **Files:** `packages/runtime/src/app/RuntimeApp.ts`, `ServiceRegistry.ts`, `packages/cli/src/bootstrap/createRuntime.ts`, `loadConfig.ts`. +- **Implements:** DD §22.2 (RuntimeApp/ServiceRegistry); wires all subsystems. +- **Depends on:** T-126, T-416, T-601, T-802, T-306. +- **DoD:** `start`/`shutdown` builds full service graph respecting dependency direction. + +### T-804..T-808 — CLI commands (parallel after T-803) +Each routes side effects through RuntimeApp services; never bypasses ToolRegistry/PermissionEngine (DD §17). + +| Task | File | Command class | Subcommands | +|---|---|---|---| +| T-804 | `commands/run.ts` | RunCommand | `run [project]` (+ spawns TUI) | +| T-805 | `commands/init.ts` | InitCommand | `init` (first-run wizard) | +| T-806 | `commands/doctor.ts` | DoctorCommand | `doctor [--fix\|--bundle]` | +| T-807 | `commands/provider.ts` | ProviderCommand | `provider list`, `provider current` (read-only, no switch) | +| T-808 | `commands/{e2e,release,resume,compact,history,session,restore}.ts` | E2E/Release/Resume/Compact/History/SessionList/Restore | per DD §17 table | + +- **Depends on:** T-803. +- **DoD (each):** CliEntrypoint routes argv→command; matches DD §17 table; ProviderCommand read-only; RestoreCommand git-backed file/time/session granularity. + +### T-809 — `CliEntrypoint` + release gate +- **Files:** `packages/cli/src/index.ts`, `release:check` script, CI-less local harness. +- **Implements:** overview §17 full validation list. +- **Depends on:** T-804..T-808. +- **DoD:** `bun run typecheck && bun test && bun run lint && bun run air -- doctor --read-only && ... && bun run release:check` all green. **P8 gate — release readiness.** + +--- + +## Appendix + +### A1 — The 5 Domain Invariants (DD §18.6) — INJECT INTO EVERY EXECUTOR CONTEXT + +- **INV-1 — Session-DB state/lifecycle columns are written ONLY by `EventStore.project(event, tx)`.** No service issues a direct `UPDATE` to `*.status`/lifecycle columns. Authoritative table→event map in DD §18.6. **Exemptions (safe to write directly):** `agents.last_heartbeat_at`, `tasks.heartbeat_at` (AgentMonitor coalesce); `ui_state.*` (UiStateRepository). `command_runs` has NO status column — it's derived (DD §4.4). +- **INV-2 — Cross-DB/external writes use the outbox model with a single writer.** `debug-records.db`, `learned-memory.db`, `rules/`, `skills/`, artifact files go through the owning store (single writer), external write FIRST → then ingest ONE completion event. `EventStore.project()` never opens an external DB/file. +- **INV-3 — Side effects ONLY through `ToolRegistry.call` → `PermissionEngine.evaluate` first.** Workers reach fs/shell/network/SQLite only via parent-mediated tool IPC. LLM/provider output never performs a direct side effect. +- **INV-4 — Import/dependency direction is one-way** (see A2). Capabilities install dependencies only through Doctor. +- **INV-5 — EventBus is transport, never a source of truth.** Recovery/scheduling rebuild from SQLite, never from EventBus replay. Dropped/duplicated delivery must never change durable state. + +### A2 — Allowed import graph (DD §2, frozen by c4/module.md + contracts §23) +``` +contracts → (nothing) +llm → contracts +toolchain-cpp → contracts +tui → contracts +runtime → contracts, llm (facade only) +cli → contracts, runtime, tui, llm, toolchain-cpp +workers → contracts + WorkerRuntime IPC surface (NO direct runtime import) +``` +Forbidden (enforced by lint, code-view §12): TUI direct DB access; worker direct SQLite writes; capability direct dependency install; provider adapter changing prompt semantics silently; tool execution without PermissionEngine; repositories containing scheduling policy. + +### A3 — Reference reuse map (DD §23) — consult before re-deriving +Reference checkouts under `/reference/` (git-ignored). Verify present & non-empty first. + +| Slice | Reference | Mode | +|---|---|---| +| TUI renderer | OpenTUI `@opentui/*` | **npm-dep (do NOT reimplement)** | +| TUI patterns | `reference/opencode-1.15.5/` | pattern (no SDK/session state) | +| Provider/converters | `@opencode-ai/llm` (`reference/opencode-1.15.5/`) | fork/adapt (output stays Anthropic-canonical) | +| Edit/patch discipline | `reference/claude-code-cli/` | behavioral (quality bar, no code) | +| fs.edit/patch + test loop | `reference/openai-codex/` | pattern | +| Knowledge/ExperienceMiner/Curator | `reference/hermes-agent-2026.5.16/` | pattern | +| Skills (SKILL.md) | `reference/anthropic-skills/` | pattern | +| Logging/HUD/PTY | `reference/asciinema-3.2.0/`, `reference/atuin-18.16.1/`, `reference/claude-hud-0.0.12/` | pattern | +| Message format | `reference/claude-code-cli/` | behavioral | + +### A4 — Validation gates (overview §17) +```bash +bun install +bun run typecheck +bun test +bun run lint +bun run air -- doctor --read-only +bun run air -- e2e worker-fixture +bun run air -- fixture cpp-build-test +bun run air -- e2e cpp-fix-fixture +bun run air -- e2e cpp-debug-review-fixture +bun run air -- capability validate --all +bun run air -- e2e direct-mode-fixture +bun run air -- doctor --bundle +bun run air -- tui-smoke --project +bun run release:check +``` + +### A5 — Dependency summary (phase gates) +``` +P0(contracts) ─▶ P1(storage/events) ─▶ P2(tools/perm) ─▶ P3(provider/context) ─▶ P4(workers/scheduler) ─▶ P7(agents) ─▶ P8(cli/release) + │ │ + └────────────▶ P5(cpp, after P2) └─▶ P6(projection/TUI, after P3 contracts) +``` +P5 and P6 may overlap P4 once their dependencies (P2 tools / P3 provider+context contracts) are met. + +--- + +End of Implementation Plan.