# 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 `<repo-root>/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-<phase><nn>` 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<T>` 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<TRecord,TInsert,TUpdate>` (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<T>` 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<I,O>` 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_<ulid>`; 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<TResult>` (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<TResult>` 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 `<repo-root>/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 <fixture>
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.
