# 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.