Add system-detailed-design.md (2033 lines, 23 sections) derived from frozen baselines and overview. Complete four-model cross-review: - DeepSeek: baseline coverage audit (PASS, 9.6/10) - MIMO 2.5 Pro: internal consistency (PASS, 9.4/10) - GPT-5.5 Pro: baseline conflict detection (Requires repair) - Opus 4.8: validation + root cause analysis (CONDITIONAL PASS, 9.1/10) Key findings requiring resolution before freeze: - P1-01: Worker exit code semantic conflict (baselineV1 vs overview) - P1-02: PromptLayerLevel enum vs L0-L9 layer name mismatch - P1-03: EventStore.project() error handling undefined - P1-04: PromptLayerLoader interface incomplete for 10 layers Coverage verified: 100% contracts, events, DB schema, state machines. Architecture validated: no circular dependencies, proper separation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2034 lines
81 KiB
Markdown
2034 lines
81 KiB
Markdown
# AirCoding V1.0.0 Alpha System Detailed Design and UML Class Model
|
|
|
|
Date: 2026-05-29
|
|
Status: Detailed design derived strictly from frozen baselines and system overview design
|
|
Scope: Implementation-facing class/method design, UML, sequence, and state designs for V1.0.0 Alpha
|
|
|
|
## 0. Authority and Traceability
|
|
|
|
This document is bound by the following frozen sources. It elaborates them into class-level
|
|
design but does not introduce new public contracts, new event types, new DB columns, or new
|
|
runtime semantics. Where a detail is not fixed by a baseline, it is marked `IMPL` (implementation
|
|
freedom inside the contract boundary).
|
|
|
|
| Source | Role in this document |
|
|
|---|---|
|
|
| `interface-contracts-v1.md` | Public TypeScript contracts. All classes implement these as-is. |
|
|
| `c4/code-view.md` | Package/file layout and class inventory. |
|
|
| `c4/module.md` | Container dependency direction. |
|
|
| `db-schema-v1.md` | SQLite tables, enums, indexes. |
|
|
| `event-registry-v1.md` | Event names, payloads, persistence policy. |
|
|
| `scheduler-state-machine-v1.md` | Scheduler lifecycle and transitions. |
|
|
| `main-agent-state-machine.md` | Main Agent lifecycle. |
|
|
| `runtime-semantics-v1.md` | Ingestion boundary, FK-off, outbox, execution primitives. |
|
|
| `scope-escalation-v1.md` | Escalation/impact routing. |
|
|
| `security-model-v1.md` | Path/command risk, permission layering. |
|
|
| `error-taxonomy-v1.md` | `AirError`, `ErrorKind`, retryability, signature. |
|
|
| `prompt-layering-v1.md` | PromptLayer L0-L9. |
|
|
| `provider-capability-matrix-v1.md` | Provider adapter behavior. |
|
|
| `capability-trust-v1.md` | Capability lifecycle/trust. |
|
|
| `artifact-naming-v1.md` | Artifact URI/ID/filename. |
|
|
| `system-overview-design.md` | Container/component/flow overview. |
|
|
|
|
Naming rule (from contracts §1): exported contract fields are `snake_case`; class names are
|
|
`PascalCase`; private methods may use local camelCase. Method signatures below restate the frozen
|
|
contract types verbatim.
|
|
|
|
## 1. Document Structure
|
|
|
|
1. §2 System decomposition and module ownership
|
|
2. §3 Contracts package detailed design
|
|
3. §4 Storage and repositories
|
|
4. §5 Event subsystem (Ingestor/Store/Bus/SchemaRegistry)
|
|
5. §6 Project/session lifecycle
|
|
6. §7 Scheduler subsystem
|
|
7. §8 Worker/IPC subsystem
|
|
8. §9 Tool + Permission + Capability subsystem
|
|
9. §10 Context/Prompt/Compaction subsystem
|
|
10. §11 Artifact/Evidence/Knowledge subsystem
|
|
11. §12 Provider (LLM) subsystem
|
|
12. §13 Projection + TUI subsystem
|
|
13. §14 Agents (Main, Architecture Designer) subsystem
|
|
14. §15 Toolchain C++ subsystem
|
|
15. §16 Doctor/Logging/Migration/Recovery subsystem
|
|
16. §17 CLI subsystem
|
|
17. §18 Cross-cutting designs (error, transaction, FK-off, outbox)
|
|
18. §19 Sequence designs
|
|
19. §20 State machine designs
|
|
20. §21 Traceability matrix
|
|
|
|
## 2. System Decomposition and Module Ownership
|
|
|
|
Dependency direction (frozen by `c4/module.md`), expressed as allowed imports:
|
|
|
|
```text
|
|
contracts → (none)
|
|
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 edges (frozen by contracts §23) are enforced by lint boundaries and reviewed at the
|
|
architecture gate. The detailed class design below never crosses these edges.
|
|
|
|
Ownership summary (frozen by code-view §11 State Ownership):
|
|
|
|
| State | Owning class | Reader access |
|
|
|---|---|---|
|
|
| session DB | `SessionStore`, `EventStore` | runtime services only |
|
|
| live events | `EventBus` | runtime publish/subscribe |
|
|
| UI projection | `ProjectionStore` | TUI read-only via `ProjectionClient` |
|
|
| artifacts | `ArtifactStore` | tools/workers via runtime API |
|
|
| evidence | `EvidenceStore` | reports/reviews/debug |
|
|
| tasks/agents | `Scheduler` | repositories are storage-only |
|
|
| permission decisions | `PermissionEngine` | `ToolRegistry` requests |
|
|
| model config | `ProviderManager` | runtime/Doctor read via API |
|
|
| project rules/context | `ContextAssembler`/`ProjectStore` | workers get excerpts |
|
|
|
|
## 3. Contracts Package Detailed Design
|
|
|
|
`packages/contracts` is type-only. It contains zero runtime logic, only `export interface`,
|
|
`export type`, and nominal aliases. File layout is frozen by code-view §3.
|
|
|
|
`IMPL` note: the contracts package may include tiny pure type-guards (e.g. `is_air_error`) only if
|
|
they have no dependencies; default is to keep it declaration-only to satisfy code-view §3 rule
|
|
"type-only package has no implementation deps" (todo T-002).
|
|
|
|
Design rules for the contracts package:
|
|
|
|
1. Every interface in `interface-contracts-v1.md` §2-§21 is exported from the file mapped in
|
|
code-view §3 "Contract Ownership".
|
|
2. No interface gains extra fields here. Field additions require an ADR (contracts §22 rule 6).
|
|
3. `JsonSchema<T>` stays nominal (`JsonObject`); no runtime schema engine lives in contracts.
|
|
4. Re-export surface is `index.ts` which barrel-exports every contract file.
|
|
|
|
Contract-to-file map (frozen by code-view §3):
|
|
|
|
```text
|
|
ids.ts → primitive ID aliases, Clock, IdGenerator
|
|
error.ts → ErrorKind, ErrorSeverity, Retryability, AirError
|
|
event.ts → EntityType, EntityRef, EventSource, RuntimeEvent, EventFilter
|
|
runtime.ts → AgentType, AgentRuntimeContext, ContextPack
|
|
ipc.ts → IpcDirection, IpcEnvelope, IpcKind, IpcMessage, ControlMessage, payloads
|
|
task.ts → Task*, VerificationPolicy, TaskConstraints, TaskSpec, TaskGraph, Scheduler*
|
|
worker-result.ts→ WorkerStatus, WorkerResult, ExecutorResult, ReviewerResult, DebuggerResult,
|
|
CompactorResult, ExperienceMinerResult, BlockerReport, Risk, FollowUpTask
|
|
tool.ts → ToolCategory, ToolDefinition, ToolExecutor, StreamingToolExecutor,
|
|
ToolExecutionContext, ToolResultEnvelope, ToolEvent, ToolRegistry
|
|
permission.ts → PathPolicy, PermissionRequestContext, PermissionAction, PermissionGrantScope,
|
|
PermissionDecision, PermissionRecordResult, PermissionEngine
|
|
artifact.ts → ArtifactRef, ArtifactCreateInput, ArtifactContext, ArtifactReadResult,
|
|
ArtifactStore
|
|
evidence.ts → EvidenceRef, EvidenceCreateInput, EvidenceStore
|
|
project.ts → ProjectContext, ProjectInitOptions, ProjectStore, SessionContext,
|
|
OpenSessionOptions, SessionManager
|
|
provider.ts → ProviderCapabilityMatrix, ModelRequirement, ProviderCompletionInput,
|
|
ProviderStreamEvent, ProviderAdapter, ProviderManager, ModelAssignment
|
|
ui.ts → all *Projection, ProjectionSnapshot, ProjectionStore, ProjectionClient
|
|
capability.ts → CapabilityManifestV1, ValidationResult, CapabilityRegistry
|
|
platform.ts → cross-platform tier enums referenced by Doctor (from cross-platform-matrix)
|
|
```
|
|
|
|
`IMPL`: `storage.ts`, `scheduler.ts`, `workers.ts`, `context.ts`, `projection.ts`, `doctor.ts`,
|
|
`knowledge.ts`, `diagnostics.ts` from overview §4 may either be separate files or be merged into the
|
|
above; the binding requirement is that the exported symbol set equals the contract set. This design
|
|
keeps the code-view §3 list as canonical and treats overview §4 as the superset note.
|
|
|
|
## 4. Storage and Repositories
|
|
|
|
Module: `packages/runtime/src/storage/`. Classes: `DatabaseManager`, `MigrationRunner`,
|
|
repositories under `repositories/`.
|
|
|
|
### 4.1 DatabaseManager
|
|
|
|
Implements `TransactionManager` (contracts §6) over Bun's SQLite.
|
|
|
|
```text
|
|
class DatabaseManager implements TransactionManager
|
|
+open(path: string): DatabaseHandle
|
|
+transaction<T>(fn: (tx: TransactionHandle) => Promise<T>): Promise<T>
|
|
-applyPragmas(db): void // WAL, synchronous=NORMAL, foreign_keys=OFF (db-schema §1)
|
|
-handleFor(tx): RawDb
|
|
```
|
|
|
|
Rules (db-schema §1): on `open`, set `journal_mode=WAL`, `synchronous=NORMAL`, `foreign_keys=OFF`.
|
|
`transaction` wraps `BEGIN`/`COMMIT`/`ROLLBACK`. A durable event insert plus its domain update run
|
|
inside one `transaction` call (runtime-semantics §3). `TransactionHandle.id` is an opaque token
|
|
mapping to the active raw transaction; nested calls reuse the active handle (`IMPL`: single-writer
|
|
per session DB, so no real nesting needed).
|
|
|
|
### 4.2 MigrationRunner
|
|
|
|
```text
|
|
class MigrationRunner
|
|
+migrate(db: DatabaseHandle): Promise<void>
|
|
-currentVersion(db): number // reads schema_meta.schema_version
|
|
-targetVersion(): number // = 1 for V1.0.0 Alpha
|
|
-applyV1(db): void // creates all tables/indexes from db-schema §2-§18
|
|
```
|
|
|
|
V1 has a single target `schema_version = 1`. `migrate` is idempotent: if `schema_meta` is missing it
|
|
creates the full schema and seeds the initial keys (db-schema §2). It updates
|
|
`aircoding_version_last_opened` on every open. Destructive/non-trivial migrations follow overview §15
|
|
(plan, backup, confirm) but V1 only needs create-on-empty.
|
|
|
|
### 4.3 Repository layer
|
|
|
|
All repositories implement `Repository<TRecord, TInsert, TUpdate>` (contracts §6) or its narrow
|
|
extensions. They are thin persistence adapters: no scheduling, permission, or projection policy
|
|
(contracts §6, code-view §9). Records mirror db-schema columns exactly (`snake_case`).
|
|
|
|
Repository inventory (code-view §9) and their record types:
|
|
|
|
| Repository | Record (db-schema table) | Notable methods beyond CRUD |
|
|
|---|---|---|
|
|
| `SessionRepository` | `sessions` (§3) | `list_active()` |
|
|
| `MessageRepository` | `messages` (§4) | `list_by_session(session_id, since?)` |
|
|
| `MessageDraftRepository` | `message_drafts` (§5) | `upsert`, `delete_for_message` |
|
|
| `EventRepository` | `events` (§6) | `insert(rec, tx)`, `query(filter)` (contracts §6) |
|
|
| `TaskRepository` | `tasks` (§7) | `list_by_status`, `list_runnable_candidates` (contracts §6) |
|
|
| `TaskDependencyRepository` | `task_dependencies` (§8) | `list_for_task`, `list_dependents` |
|
|
| `TaskAttemptRepository` | `task_attempts` (§9) | `next_attempt_index(task_id)`, `list_by_task` |
|
|
| `AgentRepository` | `agents` (§10) | `list_active`, `update_heartbeat` |
|
|
| `ToolRunRepository` | `tool_runs` (§11) | `list_by_task`, `list_by_origin_message` |
|
|
| `CommandRunRepository` | `command_runs` (§12) | `list_by_task` (status derived, §4.4) |
|
|
| `ArtifactRepository` | `artifacts` (§13) | `list_by_entity`, `get_by_uri` |
|
|
| `DiagnosticRepository` | `diagnostics` (§14) | `list_by_signature`, `list_by_command_run` |
|
|
| `EvidenceRepository` | `evidence_refs` (§15) | `list_for_entity(type,id)` |
|
|
| `WorkspaceRepository` | `workspaces` (§16) | `list_by_status`, `list_gc_candidates` |
|
|
| `SummaryRepository` | `summaries` (§17) | `get`, `insert` |
|
|
| `UiStateRepository` | `ui_state` (§18) | `upsert(scope,key,value)`, `read(scope,key)` |
|
|
|
|
`SessionStore` aggregates all repositories (code-view §9):
|
|
|
|
```text
|
|
class SessionStore
|
|
+sessions: SessionRepository
|
|
+messages: MessageRepository
|
|
+message_drafts: MessageDraftRepository
|
|
+events: EventRepository
|
|
+tasks: TaskRepository
|
|
+task_dependencies: TaskDependencyRepository
|
|
+task_attempts: TaskAttemptRepository
|
|
+agents: AgentRepository
|
|
+tool_runs: ToolRunRepository
|
|
+command_runs: CommandRunRepository
|
|
+artifacts: ArtifactRepository
|
|
+diagnostics: DiagnosticRepository
|
|
+evidence: EvidenceRepository
|
|
+workspaces: WorkspaceRepository
|
|
+summaries: SummaryRepository
|
|
+ui_state: UiStateRepository
|
|
+referential_check(): Promise<OrphanReport> // FK-off invariants (§18.3)
|
|
```
|
|
|
|
### 4.4 Derived command status
|
|
|
|
`command_runs` has no physical `status` column (db-schema §12, runtime-semantics §5). The repository
|
|
exposes a pure derivation used by projection and reports:
|
|
|
|
```text
|
|
function derive_command_status(row): "running" | "ok" | "error" | "cancelled" | "unknown"
|
|
completed_at == null → "running"
|
|
cancellation metadata present → "cancelled"
|
|
exit_code === 0 → "ok"
|
|
exit_code != 0 (non-null) → "error"
|
|
otherwise → "unknown"
|
|
```
|
|
|
|
This matches `CommandRunProjection.status` (contracts §17) so projection never invents a value.
|
|
|
|
### 4.5 Enum validation
|
|
|
|
Every closed-enum TEXT column (db-schema §21, 18 rows) is validated on insert/update. `IMPL`: a
|
|
shared `assert_enum(table, column, value)` helper backed by the db-schema §21 table; on violation it
|
|
throws an `AirError` of kind `system_error` (programmer error, never user-facing).
|
|
|
|
## 5. Event Subsystem
|
|
|
|
Module: `packages/runtime/src/events/`. Classes: `EventSchemaRegistry`, `EventStore`, `EventBus`,
|
|
`EventIngestor`. All implement contracts §7 verbatim.
|
|
|
|
### 5.1 EventIngestor
|
|
|
|
The single runtime entry point for events from agents/tools/workers (runtime-semantics §2).
|
|
|
|
```text
|
|
class EventIngestor implements EventIngestor (contracts §7)
|
|
+ingest<T>(event: RuntimeEvent<T>): Promise<void>
|
|
+ingest_ephemeral<T>(event: RuntimeEvent<T>): Promise<void>
|
|
-policyFor(type): EventPersistence // durable | ephemeral, from registry
|
|
```
|
|
|
|
`ingest` flow (runtime-semantics §2):
|
|
|
|
```text
|
|
validate envelope + schema/version (EventSchemaRegistry)
|
|
→ look up persistence policy by event.type
|
|
→ durable: EventStore.append(event) // tx + projection + post-commit publish
|
|
→ ephemeral: EventBus.publish(event) // live only
|
|
```
|
|
|
|
If `ingest` receives a type whose policy is `ephemeral`, it delegates to `ingest_ephemeral`. The
|
|
ingestor never creates scheduler tasks, permission decisions, or memory promotions; those are
|
|
follow-up events emitted by owning services (runtime-semantics §2).
|
|
|
|
### 5.2 EventSchemaRegistry
|
|
|
|
```text
|
|
class EventSchemaRegistry implements EventSchemaRegistry (contracts §7)
|
|
+register(type, version, schema: JsonObject): void
|
|
+validate(type, version, payload): boolean
|
|
+list(): Array<{type, version}>
|
|
+get_schema(type, version): JsonObject | undefined
|
|
```
|
|
|
|
Seeded at startup from `event-registry-v1.md` §3 (durable) and §4 (ephemeral). Unknown
|
|
`type`+`version` fails validation → ingestion rejects with `AirError` kind `system_error`.
|
|
Payload schema change requires a new `version` (event-registry §2 rule 7).
|
|
|
|
### 5.3 EventStore
|
|
|
|
```text
|
|
class EventStore implements EventStore (contracts §7)
|
|
+append<T>(event, options?): Promise<void>
|
|
+append_many(events, options?): Promise<void>
|
|
+query(filter: EventFilter): Promise<RuntimeEvent[]>
|
|
-toRecord(event): PersistedEventRecord // route_text = route.join("/")
|
|
-project(event, tx): void // domain table update per registry map
|
|
```
|
|
|
|
`append` algorithm (runtime-semantics §3, event-registry §2):
|
|
|
|
```text
|
|
DatabaseManager.transaction(tx => {
|
|
schema validate (must already be durable policy)
|
|
EventRepository.insert(toRecord(event), tx)
|
|
project(event, tx) // domain projection from §5.4 map
|
|
})
|
|
EventBus.publish(event) // AFTER commit (contracts §7 rule 3)
|
|
```
|
|
|
|
`route_text` is always derived `route.join("/")` (event-registry §2 rule 6); `route` itself is
|
|
append-only (rule 5) — `EventStore` never rewrites prior route entries.
|
|
|
|
### 5.4 Durable projection map
|
|
|
|
`project(event, tx)` switches on `event.type` and applies exactly the domain update fixed by
|
|
event-registry §3. The full map (no event may project differently):
|
|
|
|
| Event type | Domain update |
|
|
|---|---|
|
|
| `session.created` | insert `sessions` |
|
|
| `session.archived` / `session.deleted` | update `sessions.status` |
|
|
| `user.message.created` | insert `messages` |
|
|
| `assistant.message.started` | upsert `message_drafts` (status=streaming) |
|
|
| `assistant.message.created` | insert `messages` + delete matching `message_drafts` |
|
|
| `assistant.message.failed` | `message_drafts.status=error` or failure artifact |
|
|
| `agent.started` | insert `agents` (starting/running) |
|
|
| `agent.completed/failed/lost/cancelled` | update `agents.status` |
|
|
| `task.created` | insert `tasks` (+ optional `task_dependencies`) |
|
|
| `task.started` | `tasks.status=running`, set started/agent/workspace; insert `task_attempts` |
|
|
| `task.completed` | `tasks.status=completed`, set worker_result_json, completed_at; update attempt |
|
|
| `task.blocked` | `tasks.status=blocked`; update attempt |
|
|
| `task.failed` | `tasks.status=failed`; update `task_attempts.failure_*` |
|
|
| `task.cancelled` | `tasks.status=cancelled` |
|
|
| `task.interrupted` | `tasks.status=interrupted` |
|
|
| `tool.started` | insert `tool_runs` (running) |
|
|
| `tool.completed` | `tool_runs.status=ok` + output/artifacts/evidence/duration |
|
|
| `tool.failed` | `tool_runs.status=error` |
|
|
| `tool.cancelled` | `tool_runs.status=cancelled` |
|
|
| `command.started` | insert `command_runs` |
|
|
| `command.completed` | update exit_code, artifact refs, diagnostics, duration |
|
|
| `command.failed` | update exit_code when available + failure artifacts |
|
|
| `artifact.created` | insert `artifacts` (after temp→rename) |
|
|
| `diagnostic.created` | insert `diagnostics` |
|
|
| `evidence.created` | insert `evidence_refs` |
|
|
| `context.compaction.requested` | insert compaction task if accepted |
|
|
| `context.compaction.started` | mark compaction task running |
|
|
| `context.compaction.completed` | mark compaction task complete (no summary row) |
|
|
| `context.compaction.failed` | mark compaction task failed/blocked |
|
|
| `summary.created` | insert `summaries` (only place that does) |
|
|
| `permission.decision.recorded` | append (optional future projection table) |
|
|
| `permission.prompt.requested/resolved` | append (optional UI projection) |
|
|
| `doctor.*` | append (+ optional report artifact / command rows) |
|
|
| `requirement.changed` | append; mark impacted tasks when Scheduler applies |
|
|
| `architecture.plan.updated` | append + plan/artifact refs |
|
|
| `architecture.impact.completed` | append; Scheduler consumes |
|
|
| `workspace.created` | insert `workspaces` |
|
|
| `workspace.merge.started` | append + mark merge in progress (metadata) |
|
|
| `workspace.merge.completed` | `workspaces.status=merged`, set merged_at |
|
|
| `workspace.merge.conflicted` | `workspaces.status=conflicted` |
|
|
| `workspace.cleaned` | `workspaces.status=cleaned` |
|
|
| `memory.candidate.created` | append |
|
|
| `memory.promoted` | append + write rules/skill/learned-memory.db via owner (outbox §18.4) |
|
|
| `memory.archived` | append + mark memory inactive via owner |
|
|
| `debug.record.created` | insert/update debug-records.db (outbox §18.4) + append session event |
|
|
|
|
### 5.5 EventBus
|
|
|
|
```text
|
|
class EventBus implements EventBus (contracts §7)
|
|
+publish<T>(event: RuntimeEvent<T>): void
|
|
+subscribe(filter: EventFilter, handler): Subscription
|
|
+drain?(): Promise<void>
|
|
-match(filter, event): boolean
|
|
```
|
|
|
|
Rules: live transport only, never a recovery source of truth (contracts §7 rule 4). If a handler
|
|
throws, the error is caught, logged to developer log, and does not propagate; subscription stays
|
|
active (contracts §7 rule 5). `drain` flushes pending async handlers for clean shutdown.
|
|
|
|
Ephemeral coalescing (event-registry §4): `agent.heartbeat`, `task.progress`,
|
|
`assistant.message.delta`, `tool.progress`, `command.stdout.delta`, `command.stderr.delta`,
|
|
`hud.frame.rendered` may be throttled before reaching subscribers.
|
|
|
|
## 6. Project and Session Lifecycle
|
|
|
|
Module: `packages/runtime/src/project/` and `sessions/`. Classes: `ProjectLocator`,
|
|
`ProjectInitializer`, `ProjectStore`, `SessionManager`, `SessionStore`.
|
|
|
|
### 6.1 ProjectStore
|
|
|
|
Implements contracts §8.
|
|
|
|
```text
|
|
class ProjectStore implements ProjectStore
|
|
+locate(start_path): Promise<ProjectContext | undefined>
|
|
+initialize(project_root, options?): Promise<ProjectContext>
|
|
+open(project_root): Promise<ProjectContext>
|
|
```
|
|
|
|
`locate` walks up from `start_path` looking for `.air/shared/project.json` (overview §8.1). `initialize`
|
|
creates the `.air/shared` and `.air/local` trees (overview §8.1), generates a stable `project_id`
|
|
UUID stored in `.air/shared/project.json` (not derived from path; overview §8.1), seeds default rules
|
|
when `options.default_rules`, and emits nothing durable yet (no session DB until a session opens).
|
|
`open` loads the existing `ProjectContext` (project_id, roots, schema_version).
|
|
|
|
Delegated helpers (`IMPL`, code-view §4):
|
|
- `ProjectLocator.locate(start)` — upward search.
|
|
- `ProjectInitializer.scaffold(root, options)` — directory + file creation.
|
|
|
|
### 6.2 SessionManager and SessionStore
|
|
|
|
```text
|
|
class SessionManager implements SessionManager (contracts §8)
|
|
+open_session(project, options?): Promise<SessionContext>
|
|
+close_session(session_id): Promise<void>
|
|
|
|
class SessionStore // §4.3 aggregate of repositories
|
|
```
|
|
|
|
`open_session` flow:
|
|
|
|
```text
|
|
resolve session_id (options or IdGenerator.session_id())
|
|
compute db_path = .air/local/sessions/<session-id>/session.db (db-schema header)
|
|
DatabaseManager.open(db_path); MigrationRunner.migrate(db)
|
|
SessionStore bound to this db
|
|
ingest session.created (durable → inserts sessions row)
|
|
return SessionContext { session_id, project_id, project_root, db_path, artifact_root }
|
|
```
|
|
|
|
`close_session` flushes `ui_state` (db-schema §1), publishes a terminal session event when archiving,
|
|
and releases the DB handle. Session provider/model selection (`model_provider_id`, `model_id`) is
|
|
captured at open and is immutable for the session (overview §14).
|
|
|
|
## 7. Scheduler Subsystem
|
|
|
|
Module: `packages/runtime/src/scheduler/`. Classes: `Scheduler`, `TaskGraph`, `WavePlanner`,
|
|
`RetryPlanner`, `WorkspaceManager`, `AgentMonitor` (code-view §4). The Scheduler is an orchestration
|
|
service, not a coding agent (scheduler-state-machine §intro). All durable state goes through
|
|
EventStore; in-memory queues rebuild from SQLite (scheduler-state-machine §1).
|
|
|
|
### 7.1 Scheduler
|
|
|
|
Implements contracts §9.
|
|
|
|
```text
|
|
class Scheduler implements Scheduler
|
|
+create_tasks(session_id, specs: TaskSpec[]): Promise<void>
|
|
+add_dependency(session_id, task_id, dependency: TaskDependencySpec): Promise<void>
|
|
+load_graph(session_id): Promise<TaskGraph>
|
|
+run_until_idle(session_id): Promise<SchedulerRunResult>
|
|
+cancel_task(task_id, reason): Promise<void>
|
|
-plan_wave(graph): SchedulerWavePlan
|
|
-dispatch(wave): Promise<void>
|
|
-collect_results(): Promise<void>
|
|
-state: SchedulerState // §20.2 lifecycle
|
|
```
|
|
|
|
`create_tasks` ingests `task.created` per spec (durable → inserts `tasks` + dependency rows).
|
|
`run_until_idle` drives the lifecycle in §20.2 until a terminal graph state, returning
|
|
`SchedulerRunResult` (contracts §9). The Scheduler asks the user only through Main Agent /
|
|
PermissionEngine (scheduler-state-machine §8); it never prompts directly.
|
|
|
|
### 7.2 TaskGraph
|
|
|
|
```text
|
|
class TaskGraph
|
|
+session_id: SessionID
|
|
+tasks: Map<TaskID, TaskNode>
|
|
+dependencies: TaskDependencyRecord[]
|
|
+get_runnable_tasks(): TaskNode[] // hard deps satisfied, not conflicting
|
|
+mark_terminal(task_id, status): void
|
|
+dependents_of(task_id): TaskNode[]
|
|
+validate_refs(): OrphanReport // FK-off (§18.3)
|
|
```
|
|
|
|
`get_runnable_tasks` honors dependency semantics (scheduler-state-machine §4 PLANNING_WAVE): hard
|
|
deps must be completed; soft deps affect priority only; conflict/serialization deps block concurrent
|
|
dispatch on overlapping write areas.
|
|
|
|
### 7.3 WavePlanner
|
|
|
|
```text
|
|
class WavePlanner
|
|
+plan(graph, resources: ResourceSnapshot): SchedulerWavePlan
|
|
-serialize_write_conflicts(candidates): {runnable, serialized}
|
|
-assign_workspace(task): WorkspacePlan
|
|
-assign_model(task): ModelAssignment
|
|
```
|
|
|
|
Produces `SchedulerWavePlan` (contracts §9). Rules from scheduler-state-machine §4:
|
|
different write areas → concurrent; same area uncertain conflict → serialize; reviewers read-only and
|
|
concurrent except against unstable unmerged outputs; debugger serializes on same failure surface;
|
|
machine resources cap concurrency (§7 resource-aware). Inferred `conflict`/`serialization` edges are
|
|
persisted via `task_dependencies` + durable events so restart need not rediscover them
|
|
(scheduler-state-machine §1).
|
|
|
|
### 7.4 RetryPlanner
|
|
|
|
```text
|
|
class RetryPlanner
|
|
+decide(task: TaskNode, attempts: TaskAttemptRecord[], error: AirError): RetryDecision
|
|
```
|
|
|
|
`RetryDecision` (scheduler-state-machine §5):
|
|
`action ∈ {retry, retry_serial, debug, skip, block, cancel}`. Rules: retry only when plausibly
|
|
recoverable; later retries change one dimension (model/context/command/serialization/debugger);
|
|
identical `failure_signature` escalates faster; environment impossibility → `block`, never infinite
|
|
retry; architecture/interface mismatch → route to Architecture Designer; fallback skip only when
|
|
`VerificationPolicy.fallback_allowed` and task non-critical. Budget = `TaskConstraints.retry_budget`.
|
|
|
|
### 7.5 WorkspaceManager
|
|
|
|
```text
|
|
class WorkspaceManager
|
|
+create_workspace(plan: WorkspacePlan): Promise<WorkspaceRef>
|
|
+merge_workspace(workspace_id): Promise<MergeResult>
|
|
+cleanup_workspace(workspace_id): Promise<void>
|
|
```
|
|
|
|
Strategies (db-schema §16, scheduler-state-machine §MERGING): `main` (no merge), `worktree`
|
|
(git merge/patch), `isolated_copy` (copy-back/patch). Emits `workspace.created`,
|
|
`workspace.merge.started`, and a terminal `workspace.merge.completed` or `workspace.merge.conflicted`.
|
|
GC retention follows overview §15 (active until merge/cancel; merged 7d; abandoned 3d; cleaned keeps
|
|
DB row).
|
|
|
|
### 7.6 AgentMonitor
|
|
|
|
```text
|
|
class AgentMonitor
|
|
+record_heartbeat(event): void // coalesced into agents.last_heartbeat_at + tasks.heartbeat_at
|
|
+detect_lost_agents(): Promise<AgentLost[]>
|
|
+enforce_timeouts(): Promise<void>
|
|
```
|
|
|
|
Heartbeat coalescing interval default 5s or meaningful status change (runtime-semantics §4).
|
|
Missing heartbeat past threshold → inspect process → alive-but-silent → status ping/soft cancel;
|
|
gone-without-result → emit `agent.lost` (scheduler-state-machine §MONITORING). Soft timeout asks for
|
|
checkpoint and may extend; hard timeout cancels/kills and marks task failed/interrupted
|
|
(scheduler-state-machine §MONITORING timeout table).
|
|
|
|
## 8. Worker and IPC Subsystem
|
|
|
|
Module: `packages/runtime/src/workers/`. Classes: `WorkerManager`, `WorkerProcess`,
|
|
`WorkerProtocol`, and roles under `roles/`. IPC is NDJSON over stdio (contracts §10, ADR-0005).
|
|
|
|
### 8.1 WorkerManager and WorkerProcess
|
|
|
|
```text
|
|
class WorkerManager
|
|
+spawn(task_spec: TaskSpec, context_pack: ContextPack): Promise<WorkerProcess>
|
|
+cancel(agent_id, reason): Promise<void>
|
|
|
|
class WorkerProcess
|
|
+agent_id: AgentID
|
|
+pid?: number
|
|
+send(envelope: IpcEnvelope): void
|
|
+on_message(handler: (m: IpcEnvelope) => void): void
|
|
```
|
|
|
|
`spawn` starts a Bun child process, then performs the handshake (§8.2). `WorkerProcess` owns the
|
|
NDJSON pipe; stdout carries protocol only, stderr is fatal/logging (overview §11). Worker exit codes
|
|
0-5 map to outcomes (overview §11): 0 success, 1 task failed, 2 crashed, 3 protocol error,
|
|
4 cancelled, 5 permission/policy blocked.
|
|
|
|
### 8.2 WorkerProtocol and handshake
|
|
|
|
```text
|
|
class WorkerProtocol
|
|
+encode(msg: IpcMessage): string // NDJSON line
|
|
+decode(line: string): IpcMessage
|
|
+validate_direction(msg): void // parent_to_worker vs worker_to_parent
|
|
+check_protocol_version(v: number): boolean
|
|
```
|
|
|
|
Handshake (contracts §10): parent spawns → parent sends `agent.start` control (with `TaskSpec`,
|
|
`ContextPack`, `AgentRuntimeContext`) → worker replies `worker.ready { protocol_version, worker_version }`
|
|
→ parent validates `protocol_version`; mismatch terminates worker with `protocol.error`.
|
|
|
|
Direction typing (contracts §10): parent→worker = `control`, `tool.result`, `tool.stream`;
|
|
worker→parent = `event`, `log`, `tool.call`, `worker.result`, `worker.checkpoint`, `protocol.error`.
|
|
`validate_direction` rejects messages on the wrong channel.
|
|
|
|
### 8.3 Worker roles and WorkerRuntime
|
|
|
|
Roles implement `WorkerRole<TResult>` (contracts §10). The in-worker `WorkerRuntime` is the only
|
|
side-effect surface (contracts §10, §23: workers never write SQLite or touch fs/shell/network except
|
|
through parent-mediated tools).
|
|
|
|
```text
|
|
interface WorkerRole<TResult> { run(task_spec, context_pack, runtime): Promise<WorkerResult<TResult>> }
|
|
|
|
class WorkerRuntime
|
|
+emit(event: RuntimeEvent): Promise<void> // → IPC event → parent EventIngestor
|
|
+call_tool<I,O>(name, input): Promise<ToolResultEnvelope<O>> // → IPC tool.call
|
|
+checkpoint(data): Promise<void> // → IPC worker.checkpoint
|
|
```
|
|
|
|
Role inventory and constraints (code-view §10):
|
|
|
|
| Role class | `output_contract` | Write access | Required result |
|
|
|---|---|---|---|
|
|
| `ExecutorRole` | `ExecutorResult` | scoped project writes | ExecutorResult in WorkerResult |
|
|
| `ReviewerRole` | `ReviewerResult` | read-only | ReviewerResult |
|
|
| `DebuggerRole` | `DebuggerResult` | scoped writes only when assigned | DebuggerResult |
|
|
| `CompactorRole` | `CompactorResult` | summaries/artifacts only | CompactorResult |
|
|
| `ExperienceMinerRole` | `ExperienceMinerResult` | candidates/rules/skills only when assigned | ExperienceMinerResult |
|
|
|
|
Each role's `run` ends by returning a `WorkerResult<TResult>` with the matching `agent_type`
|
|
(contracts §11). `status ∈ {completed, failed, blocked, cancelled}`; a code-changing result cannot be
|
|
`completed` unless verification passed or was explicitly skipped with evidence/risk and
|
|
`fallback_allowed` (runtime-semantics §9.4, overview §10.9). Self-escalation returns `blocked` with a
|
|
`BlockerReport` rather than improvising (scope-escalation §9).
|
|
|
|
### 8.4 Execution discipline enforcement (Executor/Debugger)
|
|
|
|
Read-before-edit and exact-edit are enforced at the tool layer, not just by prompt (§9.4); the role
|
|
loop additionally:
|
|
1. records a read observation before `fs.edit`/`fs.patch` (runtime-semantics §9.1);
|
|
2. keeps changes within `TaskScope.write_area`/`allowed_paths` (overview §10.9 rule 3);
|
|
3. runs `VerificationPolicy.commands` before declaring `completed` (contracts §9, §11);
|
|
4. attaches evidence refs for diffs/builds/tests (overview §10.9 rule 6).
|
|
|
|
## 9. Tool, Permission, and Capability Subsystem
|
|
|
|
Module: `packages/runtime/src/tools/`, `security/`, `capabilities/`.
|
|
|
|
### 9.1 ToolRegistry
|
|
|
|
Implements contracts §12.
|
|
|
|
```text
|
|
class ToolRegistry implements ToolRegistry
|
|
+register<I,O>(definition: ToolDefinition<I,O>, executor: ToolExecutor<I,O>): void
|
|
+register_streaming<I,O>(definition, executor: StreamingToolExecutor<I,O>): void
|
|
+call<I,O>(name, input, context: ToolExecutionContext): Promise<ToolResultEnvelope<O>>
|
|
+call_streaming<I,O>(name, input, context): AsyncIterable<ToolEvent | ToolResultEnvelope<O>>
|
|
+list(): ToolDefinition[]
|
|
-validate_input(def, input): void // JsonSchema check
|
|
```
|
|
|
|
`call` algorithm (contracts §12, §23 "tool → side effect without PermissionEngine" forbidden):
|
|
|
|
```text
|
|
look up definition+executor (else AirError tool_error)
|
|
validate input against input_schema
|
|
build PermissionRequestContext from context + definition.permissions + input paths/command
|
|
decision = PermissionEngine.evaluate(request)
|
|
branch on decision.action (§9.3)
|
|
emit tool.started (durable → tool_runs running)
|
|
run executor.execute(input, context) // streaming consumed internally for call()
|
|
emit tool.completed | tool.failed | tool.cancelled
|
|
return ToolResultEnvelope
|
|
```
|
|
|
|
`call_streaming` exposes `ToolEvent` progress and ends with exactly one final `ToolResultEnvelope`
|
|
(contracts §12 streaming rule). `BuiltInToolRegistrar` registers fs/shell/git/project/artifact/
|
|
context/permission/doctor tools (code-view §4); each tool declares `category`, `permissions`, and
|
|
`streaming` (contracts §12).
|
|
|
|
### 9.2 PermissionEngine
|
|
|
|
Implements contracts §13.
|
|
|
|
```text
|
|
class PermissionEngine implements PermissionEngine
|
|
+evaluate(context: PermissionRequestContext): Promise<PermissionDecision>
|
|
+record(decision, context): Promise<PermissionRecordResult>
|
|
|
|
class PathClassifier
|
|
+classify(path, project_root): PathRiskClassification // 8 categories, realpath-normalized
|
|
|
|
class CommandRiskAnalyzer
|
|
+analyze(command, cwd): CommandRiskAnalysis // 10 categories
|
|
|
|
class SecretRedactor
|
|
+redact(text): string // for logs/evidence
|
|
```
|
|
|
|
`evaluate` applies the frozen layered order (contracts §13, runtime-semantics §8, overview §12):
|
|
|
|
```text
|
|
1 tool capability declaration
|
|
2 permission profile (permission_template)
|
|
3 TaskSpec scope allowed/denied paths
|
|
4 path/command/network risk classification (PathClassifier + CommandRiskAnalyzer)
|
|
5 credential/system-sensitive override
|
|
6 user prompt workflow if required
|
|
```
|
|
|
|
Key invariants: project-level allow never overrides task scope; credential/system-sensitive overrides
|
|
broad allows (runtime-semantics §8, overview §12 rules 8-9); paths normalized via realpath before
|
|
prefix checks (overview §12 rule 1); `.git/` internals protected (rule 2). `record` writes a
|
|
`permission.decision.recorded` durable event and returns `PermissionRecordResult`; on write failure it
|
|
returns `{ok:false, error}` (contracts §13).
|
|
|
|
### 9.3 PermissionDecision branching
|
|
|
|
`ToolRegistry.call` branches on `PermissionDecision.action` (contracts §13, scope-escalation §7):
|
|
|
|
| action | ToolRegistry behavior |
|
|
|---|---|
|
|
| `allow` | execute; create backup first if `backup_required` |
|
|
| `announce_then_run` | emit visible notice, then execute unless interrupted; bounded by `grant_scope` |
|
|
| `ask_user` | suspend; emit `permission.prompt.requested`; resume on `permission.prompt.resolved` |
|
|
| `deny` | do not execute; return `ToolResultEnvelope{status:"error"}`; caller may pick safe path |
|
|
| `block` | return blocked outcome → task.blocked upstream |
|
|
| `refuse` | return `AirError{kind:"policy_error"}`; no execution |
|
|
|
|
### 9.4 Filesystem tool execution rules
|
|
|
|
`fs.edit`/`fs.patch` enforce read-before-edit (runtime-semantics §9.1-§9.3, overview §10.9):
|
|
- require an active task read observation for the target file or explicit `expected_existing_sha256`;
|
|
- `old_string` exact match; non-unique match fails unless `replace_all`; no indentation guessing;
|
|
- patch paths must be within scope; rejected hunks become artifacts; partial apply only if unchanged
|
|
rejected paths are provably untouched, else atomic fail;
|
|
- successful edit/patch emits a diff artifact (→ `artifact.created`).
|
|
|
|
### 9.5 CapabilityRegistry
|
|
|
|
Implements contracts §18; lifecycle/trust from capability-trust-v1.
|
|
|
|
```text
|
|
class CapabilityRegistry implements CapabilityRegistry
|
|
+discover(): Promise<CapabilityManifestV1[]>
|
|
+validate(manifest): Promise<ValidationResult>
|
|
+enable(capability_id): Promise<void>
|
|
+disable(capability_id): Promise<void>
|
|
+register_tools(tool_registry: ToolRegistry): Promise<void>
|
|
|
|
class CapabilityManifestValidator
|
|
+validate(manifest): ValidationResult // schema_version=1, tool schemas, permissions
|
|
```
|
|
|
|
Lifecycle (overview §6, capability-trust §7): discovered → validated → doctor_checked → enabled →
|
|
registered → active → disabled|failed|updated. Trust levels (contracts §18): built_in, project_local,
|
|
user_installed, verified_publisher, untrusted. Trust affects default enablement/prompt posture but
|
|
never bypasses ToolRegistry or PermissionEngine (overview §6). Dependency installs go only through
|
|
Doctor (contracts §23 "capability → dependency install outside Doctor" forbidden).
|
|
|
|
## 10. Context, Prompt, and Compaction Subsystem
|
|
|
|
Module: `packages/runtime/src/context/`. Classes: `ContextAssembler`, `PromptLayerLoader`,
|
|
`CompactionPolicy` (contracts §16).
|
|
|
|
### 10.1 ContextAssembler
|
|
|
|
```text
|
|
class ContextAssembler implements ContextAssembler
|
|
+assemble(input: ContextAssembleInput): Promise<AssembledContext>
|
|
-load_layers(purpose): Promise<PromptLayer[]>
|
|
-fit_budget(layers, budget): BudgetFitResult
|
|
```
|
|
|
|
`assemble` builds an Anthropic-canonical context (`AssembledContext.canonical_format="anthropic"`,
|
|
contracts §16). It loads ordered layers (§10.2), fits them to `token_budget` via `fit_budget`, and
|
|
reports `omissions`. When the context is too large for inline return it writes a messages artifact and
|
|
sets `messages_artifact_id`; `ContextPack.assembled_context_ref` points to it (contracts §16). If the
|
|
budget cannot fit required layers it sets `compaction_requested=true` (consumed by Scheduler, §10.3).
|
|
|
|
### 10.2 PromptLayerLoader and layer order
|
|
|
|
```text
|
|
class PromptLayerLoader implements PromptLayerLoader
|
|
+load_runtime_invariant(): PromptLayer
|
|
+load_role(role: AgentType): PromptLayer
|
|
+load_project_rules(project: ProjectContext): PromptLayer[]
|
|
+load_task_context(spec: TaskSpec, refs: TaskContextRefs): PromptLayer[]
|
|
```
|
|
|
|
`PromptLayer.level` is the frozen `PromptLayerLevel` union (contracts §16), ordered L0-L9 per
|
|
prompt-layering-v1 §2 and overview §13:
|
|
|
|
| Level enum (contracts) | L# (prompt-layering) |
|
|
|---|---|
|
|
| `runtime_invariant` | L0 Runtime invariant |
|
|
| `role` | L1 Role / agent mode |
|
|
| (safety/permission policy) | L2 Safety and permission policy |
|
|
| `project_rules` | L3 Project rules and user preferences |
|
|
| `architecture` | L4 Architecture baseline and current plan |
|
|
| `task_spec` | L5 Task specification and acceptance criteria |
|
|
| `evidence` | L6 Relevant code / artifacts / evidence |
|
|
| `conversation` | L7 Recent conversation and decision context |
|
|
| `tool_output` | L8 Tool result history / diagnostics |
|
|
| `user_override` | L9 Immediate instruction |
|
|
| `system_debug` | (system debug directive, applied within L9 when present) |
|
|
|
|
`IMPL` note: contracts §16 enumerates 10 `PromptLayerLevel` symbols; prompt-layering L2 (safety) is
|
|
carried by the `runtime_invariant`/`role` immutable layers and a dedicated safety layer is loaded with
|
|
`immutable=true`. Higher-priority layers win on budget pressure; `immutable` layers are never dropped
|
|
(prompt-layering L0 `Mutable: no`).
|
|
|
|
### 10.3 CompactionPolicy
|
|
|
|
```text
|
|
class CompactionPolicy implements CompactionPolicy
|
|
+should_compact(messages, token_budget): boolean
|
|
+compact(messages, target_tokens): Promise<CompactionResult>
|
|
```
|
|
|
|
`ContextAssembler` may request compaction but does not compact itself; Scheduler creates a `compact`
|
|
task that runs `CompactorRole` (overview §13, runtime-semantics §7). Sequence:
|
|
`context.compaction.requested → context.compaction.started → summary.created → context.compaction.completed`.
|
|
Only `summary.created` inserts the `summaries` row (runtime-semantics §7); the completion event
|
|
references the `summary_id` and never duplicates the row. Original messages are preserved for
|
|
backtracking.
|
|
|
|
## 11. Artifact, Evidence, and Knowledge Subsystem
|
|
|
|
Module: `packages/runtime/src/artifacts/` and `knowledge/`.
|
|
|
|
### 11.1 ArtifactStore
|
|
|
|
Implements contracts §14; naming from artifact-naming-v1.
|
|
|
|
```text
|
|
class ArtifactStore implements ArtifactStore
|
|
+create(input: ArtifactCreateInput, context: ArtifactContext): Promise<ArtifactRef>
|
|
+get(artifact_id): Promise<ArtifactRef | undefined>
|
|
+read(artifact_id): Promise<ArtifactReadResult>
|
|
-write_temp_then_rename(bytes): {path, sha256, size}
|
|
```
|
|
|
|
`create` algorithm (runtime-semantics §6.2, overview §8.4):
|
|
|
|
```text
|
|
write temp file → compute sha256 + size → atomic rename to artifact path
|
|
artifact_id = art_<ulid>
|
|
uri = artifact://project/<project-id>/session/<session-id>/<artifact-id>
|
|
filename = <timestamp>-<artifact-id>-<slug><extension>
|
|
ingest artifact.created (durable → inserts artifacts row)
|
|
```
|
|
|
|
If the DB insert fails after rename, startup recovery scans orphaned files and registers or
|
|
quarantines them (runtime-semantics §6.2). Artifact `type` is from the closed set (db-schema §21:
|
|
log, diff, screenshot, pcap, report, diagnostic, bundle, other).
|
|
|
|
### 11.2 EvidenceStore
|
|
|
|
```text
|
|
class EvidenceStore implements EvidenceStore
|
|
+create(input: EvidenceCreateInput): Promise<EvidenceRef>
|
|
+list_for_entity(entity_type, entity_id): Promise<EvidenceRef[]>
|
|
```
|
|
|
|
Emits `evidence.created` (durable → `evidence_refs`). Worker results embed full `EvidenceRef[]` when
|
|
evidence is part of the conclusion; lightweight payloads carry `evidence_ref_ids` (contracts §14).
|
|
`kind` is from the closed set (db-schema §21: build_output, test_output, log, screenshot, diff,
|
|
metric, other).
|
|
|
|
### 11.3 DebugKnowledgeStore and LearnedMemoryStore
|
|
|
|
Project-level DBs (db-schema §20), implement contracts §20.
|
|
|
|
```text
|
|
class DebugKnowledgeStore implements DebugKnowledgeStore // debug-records.db
|
|
+insert(record: DebugRecord): Promise<void>
|
|
+lookup_by_signature(failure_signature): Promise<DebugRecord[]>
|
|
+lookup_by_task(task_id): Promise<DebugRecord[]>
|
|
+update(debug_record_id, patch): Promise<void>
|
|
|
|
class LearnedMemoryStore implements LearnedMemoryStore // learned-memory.db
|
|
+insert(memory: LearnedMemory): Promise<void>
|
|
+lookup_by_type(memory_type): Promise<LearnedMemory[]>
|
|
+update_status(memory_id, status): Promise<void>
|
|
+scan_stale(): Promise<LearnedMemory[]>
|
|
```
|
|
|
|
Writes to these DBs are cross-store side effects: the session DB records intent/completion events and
|
|
the owning store performs the external write (outbox model, §18.4; runtime-semantics §6.3-§6.4).
|
|
`debug.record.created` and `memory.promoted` are the session-side durable markers.
|
|
|
|
## 12. Provider (LLM) Subsystem
|
|
|
|
Module: `packages/llm/src/`. Classes per code-view §5. `packages/llm` owns adapters, model config,
|
|
conversion, and `ProviderManager`; `runtime` calls it only through the facade (code-view §2 rule 5).
|
|
|
|
### 12.1 ProviderManager
|
|
|
|
Implements contracts §15.
|
|
|
|
```text
|
|
class ProviderManager implements ProviderManager
|
|
+load_config(): Promise<void>
|
|
+select_model(requirement: ModelRequirement): Promise<ModelAssignment>
|
|
+complete(input: ProviderCompletionInput): AsyncIterable<ProviderStreamEvent>
|
|
-adapter_for(provider_id): ProviderAdapter
|
|
```
|
|
|
|
`select_model` matches a `ModelRequirement` against the capability matrix and returns a
|
|
`ModelAssignment` (contracts §9/§15). `complete` routes to the right adapter and yields normalized
|
|
`ProviderStreamEvent`s. Runtime/session provider+model are fixed for the session; there is no runtime
|
|
switching API (overview §14).
|
|
|
|
### 12.2 ProviderAdapter implementations
|
|
|
|
```text
|
|
interface ProviderAdapter (contracts §15)
|
|
provider_id; list_models(); validate_model(model_id); complete(input); count_tokens?(input)
|
|
|
|
class AnthropicAdapter implements ProviderAdapter
|
|
class OpenAICompatibleAdapter implements ProviderAdapter
|
|
-converter: AnthropicCanonicalConverter
|
|
class AnthropicCanonicalConverter // canonical ↔ provider format
|
|
class ToolUseConverter
|
|
class StreamNormalizer // provider stream → ProviderStreamEvent
|
|
```
|
|
|
|
Adapters convert external formats to/from the Anthropic canonical internal format and must not
|
|
silently drop semantic prompt/tool information (contracts §23 "provider adapter → silent semantic
|
|
prompt loss" forbidden; overview §14). `ModelConfigLoader` loads global `~/.air/models.yaml` and
|
|
project config; `CapabilityMatrixRegistry` holds `ProviderCapabilityMatrix` rows
|
|
(provider-capability-matrix-v1). LLM output is never allowed to perform direct file/shell side effects
|
|
(contracts §23).
|
|
|
|
## 13. Projection and TUI Subsystem
|
|
|
|
Modules: `packages/runtime/src/projection/` (ProjectionStore) and `packages/tui/src/`.
|
|
|
|
### 13.1 ProjectionStore
|
|
|
|
Implements contracts §17.
|
|
|
|
```text
|
|
class ProjectionStore implements ProjectionStore
|
|
+hydrate(session_id): Promise<void>
|
|
+apply(event: RuntimeEvent): void
|
|
+snapshot(): ProjectionSnapshot
|
|
+subscribe(handler): Subscription
|
|
-projections: { session, tasks, agents, tool_runs, command_runs, artifacts, permission_prompts, blockers }
|
|
```
|
|
|
|
`hydrate` rebuilds from DB via repositories (code-view §4: `ProjectionStore → SessionStore`). `apply`
|
|
handles all durable events plus key ephemeral events (`agent.heartbeat`, `task.progress`,
|
|
`assistant.message.delta`, `tool.progress`, `command.stdout.delta`, `command.stderr.delta`); unknown
|
|
event types are ignored (contracts §17 comment). `command_runs` projection status uses the derivation
|
|
in §4.4. ProjectionStore is never a scheduling/recovery source of truth (overview §9.3).
|
|
|
|
### 13.2 TUI
|
|
|
|
Module `packages/tui/src/` (code-view §7). `TuiApp` consumes a `ProjectionClient` and renders
|
|
components; it imports only `packages/contracts` (contracts §17, §23; code-view §2 rule 3).
|
|
|
|
```text
|
|
class TuiApp
|
|
+start(): void
|
|
+stop(): void
|
|
class ProjectionClient implements ProjectionClient
|
|
+snapshot(): ProjectionSnapshot
|
|
+subscribe(handler): Subscription
|
|
components: SessionView, TaskListView, AgentStatusView, ToolRunView, DiffView, EvidenceView,
|
|
PermissionPrompt, BlockerReport, HudView
|
|
```
|
|
|
|
Rules (code-view §7): components render projections only; permission prompts emit user decisions
|
|
through the narrow `UiCommandChannel` (contracts §17), never private runtime services; UI never
|
|
mutates domain tables; diff/evidence views link back to artifact/evidence refs. V1 transport is
|
|
in-process (contracts §17): `ProjectionClient` is a direct interface reference, not IPC. HUD presets
|
|
Full/Essential/Minimal and permission `announce_then_run` visualization per overview §14.
|
|
|
|
## 14. Agents Subsystem
|
|
|
|
Module: `packages/runtime/src/agents/main/` and `architecture/`. These run inside the runtime process
|
|
(overview §7). Main Agent stays idle-ready; background work is dispatched to workers via Scheduler
|
|
(main-agent-state-machine §Idle Principle).
|
|
|
|
### 14.1 MainAgent
|
|
|
|
```text
|
|
class MainAgent
|
|
+handle_user_message(message): Promise<void>
|
|
+present_progress(): Promise<void>
|
|
+present_blocker(blocker: BlockerReport): Promise<void>
|
|
-classify_intent(message): "chat" | "task" | "direct"
|
|
-state: MainAgentState // §20.1
|
|
```
|
|
|
|
Lifecycle is the frozen state machine (main-agent-state-machine.md, §20.1 here):
|
|
IDLE → CLASSIFYING → ANSWERING | DELEGATING | DIRECT_MODE; DELEGATING → SCHEDULING |
|
|
ARCHITECTURE_DESIGNING → CONFIRMING → EXECUTING → (INTERRUPTING | ARCHITECTURE_REVISING) →
|
|
SUMMARIZING → IDLE. Direct mode uses `permission_template="main_direct"` and writes only to the main
|
|
workspace (contracts §10, runtime-semantics §16). Requirement changes emit `requirement.changed`
|
|
(main-agent-state-machine events table). Confirmation gating: implementation-only silent → EXECUTING;
|
|
architecture-level → Architecture Designer assessment → low-permission user confirm / high-permission
|
|
auto-proceed (main-agent-state-machine §Confirmation Gating).
|
|
|
|
### 14.2 ArchitectureDesigner
|
|
|
|
```text
|
|
class ArchitectureDesigner
|
|
+assess_impact(change): Promise<ArchitectureImpact>
|
|
+update_architecture_docs(update): Promise<DocumentUpdate>
|
|
```
|
|
|
|
Emits `architecture.impact.completed` and `architecture.plan.updated` (event-registry §3, overview
|
|
§10.7). It owns the architecture review gate: interface/schema/event/package-boundary/security/
|
|
runtime-semantics/ADR/C4/plan consistency; it does not replace Reviewer (overview §10.7). Gate trigger
|
|
conditions and result rules (`silent_continue` / `requires_user_confirmation` / `requires_replan` /
|
|
`reject_or_escalate`) follow scope-escalation §4 and overview §10.7. It calls the LLM only through the
|
|
`ProviderManager` facade (code-view §4) and routes escalations through Main Agent.
|
|
|
|
## 15. Toolchain C++ Subsystem
|
|
|
|
Module: `packages/toolchain-cpp/src/` (code-view §6). Exposes `cpp.*` tools through capability
|
|
registration, not direct runtime coupling (code-view §2 rule 4).
|
|
|
|
```text
|
|
class CppToolRegistrar { +register(tool_registry): void }
|
|
class CppProjectDetector { +detect(project_root): Promise<CppDetectOutput> }
|
|
class CMakeConfigurator { +configure(input): Promise<CppCmakeConfigureOutput> }
|
|
class CppBuilder { +build(input): Promise<CppBuildOutput> }
|
|
class CppTestRunner { +run_tests(input): Promise<CppTestOutput> }
|
|
class CppcheckRunner { +run(input): Promise<CppcheckOutput> }
|
|
class ClangdClient { +query(input): Promise<ClangdQueryOutput> }
|
|
class DiagnosticParser {
|
|
+parse_compiler_output(output): Diagnostic[]
|
|
+semantic_signature(diagnostic): string
|
|
}
|
|
```
|
|
|
|
Workflow (overview §10.8): detect → configure (CMake+Ninja preferred, Make fallback) → build → parse
|
|
diagnostics → test → cppcheck → clangd query when needed → Debugger on failure → scoped fix → Reviewer
|
|
→ architecture gate if contracts/schema/events/boundaries changed. `DiagnosticParser` performs
|
|
deterministic extraction and `semantic_signature` only; LLM interpretation lives in runtime
|
|
Debugger/Reviewer, never inside `toolchain-cpp` (runtime-semantics §12). `Diagnostic` matches
|
|
contracts §21; `compile_commands.json` is generated/located when clangd/static analysis needs it
|
|
(overview §10.8).
|
|
|
|
## 16. Doctor, Logging, Migration, and Recovery Subsystem
|
|
|
|
Module: `packages/runtime/src/doctor/`, `logging/`, plus `MigrationRunner` (§4.2) and recovery in
|
|
SessionManager/Scheduler.
|
|
|
|
### 16.1 DoctorService
|
|
|
|
Implements contracts §19.
|
|
|
|
```text
|
|
class DoctorService implements DoctorService
|
|
+run(input: DoctorRunInput): Promise<DoctorRunOutput>
|
|
+check_capability(capability): Promise<DoctorIssue[]>
|
|
-self_bootstrap(): DoctorIssue[] // Bun, SQLite, shell, .air writability
|
|
```
|
|
|
|
Self-bootstrap before any capability check (runtime-semantics §18, overview §15): verify Bun runtime,
|
|
SQLite, basic shell, `.air/` writability; on failure report a blocking issue and skip remaining
|
|
checks. Modes (contracts §19): `read_only`, `fix` (under PermissionEngine), and `bundle` export (local
|
|
artifact, no auto-upload, overview §15). Emits `doctor.*` events (event-registry §3).
|
|
|
|
### 16.2 Logging
|
|
|
|
```text
|
|
class Logger implements Logger { debug/info/warn/error(message, data?) }
|
|
class DeveloperLogEncryptor implements DeveloperLogEncryptor { encrypt_log_chunk(chunk): Promise<Uint8Array> }
|
|
class SecretRedactor { redact(text): string } // shared with PermissionEngine §9.2
|
|
```
|
|
|
|
`air.log` is user-facing with redacted operational errors; `air.developer.log` is encrypted and more
|
|
detailed (overview §15, baselineV1 §23). All logs redact secrets/auth refs/provider keys via
|
|
`SecretRedactor`. Failures link log artifacts through evidence refs rather than copying sensitive
|
|
content into user summaries.
|
|
|
|
### 16.3 Recovery
|
|
|
|
On startup/resume (scheduler-state-machine §9, overview §15, runtime-semantics §6.2/§14):
|
|
1. load `tasks` with status `running`/`interrupted`, active `agents`/`workspaces`;
|
|
2. check process liveness by PID; reconnect IPC if alive, else emit `agent.lost`;
|
|
3. mark task failed/interrupted by resumability;
|
|
4. preserve workspaces until merge/cleanup decision;
|
|
5. orphan-artifact scan registers or quarantines files;
|
|
6. FK-off orphan scan (§18.3) logs and re-parents/archives dangling references;
|
|
7. workspace GC applies retention (overview §15);
|
|
8. rebuild scheduler queue from pending/failed-with-retry tasks.
|
|
|
|
## 17. CLI Subsystem
|
|
|
|
Module: `packages/cli/src/` (code-view §8). `CliEntrypoint.main(argv)` routes to command classes; a
|
|
`RuntimeFactory` builds the `RuntimeApp`.
|
|
|
|
```text
|
|
class CliEntrypoint { +main(argv): Promise<number> }
|
|
class RuntimeFactory { +create(options): Promise<RuntimeApp> }
|
|
commands: RunCommand, InitCommand, DoctorCommand, ProviderCommand (read-only), E2ECommand,
|
|
ReleaseCommand, plus catalog: resume, compact, history, session list, restore (overview §14)
|
|
```
|
|
|
|
`ProviderCommand` is read-only (`provider list`/`current`); there is no runtime provider/model switch
|
|
command (overview §14). `restore` supports file/time/session granularities over the git-backed backup
|
|
repo (overview §15, runtime-semantics §19).
|
|
|
|
## 18. Cross-Cutting Designs
|
|
|
|
### 18.1 AirError construction
|
|
|
|
All failures use `AirError` (contracts §3, error-taxonomy-v1). Construction helper:
|
|
|
|
```text
|
|
function make_air_error(opts: {
|
|
kind: ErrorKind,
|
|
severity?: ErrorSeverity, // default "error"
|
|
message: string,
|
|
detail?: string,
|
|
retryability?: Retryability, // default "unknown"
|
|
semantic_signature?: string, // default derived from kind+message hash
|
|
cause_ref?: EntityRef,
|
|
cause_refs?: EntityRef[],
|
|
user_action?: string,
|
|
metadata?: JsonObject
|
|
}): AirError
|
|
```
|
|
|
|
`semantic_signature` is the stable grouping key for repeated failure detection, debug knowledge
|
|
lookup, and Scheduler retry/debug/escalation routing (error-taxonomy §3, overview §9.2). When not
|
|
provided, derive from `kind + normalized_message_hash`. Scheduler decisions use kind, retryability,
|
|
severity, task scope, permission result, architecture impact, verification evidence, and repetition
|
|
count (overview §9.2).
|
|
|
|
### 18.2 Transaction discipline
|
|
|
|
All durable event + domain update pairs run inside one `DatabaseManager.transaction` call
|
|
(runtime-semantics §3, db-schema §1). Pseudo-code:
|
|
|
|
```text
|
|
await db.transaction(async tx => {
|
|
await event_repo.insert(to_record(event), tx)
|
|
await domain_repo.insert_or_update(domain_row, tx)
|
|
})
|
|
event_bus.publish(event) // AFTER commit
|
|
```
|
|
|
|
Artifact file writes use temp → sha256/size → atomic rename → DB record (runtime-semantics §6.2).
|
|
If the DB insert fails after rename, recovery scans orphaned files (§16.3).
|
|
|
|
### 18.3 FK-off invariants
|
|
|
|
`foreign_keys = OFF` (db-schema §1) is compensated by application-level checks (runtime-semantics §5,
|
|
overview §8.2). The 8 invariants:
|
|
|
|
1. `tasks.session_id` → existing `sessions.id`
|
|
2. `task_attempts.task_id` → existing `tasks.id`
|
|
3. `agents.task_id` → existing `tasks.id` when not null
|
|
4. `tool_runs.task_id`, `tool_runs.agent_id` → existing rows when not null
|
|
5. `command_runs.task_id`, `command_runs.agent_id`, `command_runs.tool_run_id` → existing rows
|
|
6. `workspaces.task_id`, `workspaces.agent_id` → existing rows when not null
|
|
7. `diagnostics.command_run_id`, `diagnostics.artifact_id` → existing rows when not null
|
|
8. `evidence_refs` foreign columns → existing rows when not null
|
|
|
|
`SessionStore.referential_check()` (§4.3) runs at startup and periodically; violations are logged to
|
|
developer log and either re-parented or archived (runtime-semantics §5).
|
|
|
|
### 18.4 Outbox / compensation for cross-DB writes
|
|
|
|
Writes to project-level DBs (`debug-records.db`, `learned-memory.db`) or external files follow the
|
|
outbox model (runtime-semantics §6.3-§6.4, overview §8.3):
|
|
|
|
```text
|
|
1. Insert durable session event recording intent/request
|
|
2. Insert/update session domain row with pending/external status where applicable
|
|
3. Perform external DB/file operation through owning service
|
|
4. Emit durable completed/failed event with evidence
|
|
5. On restart, recovery scans pending external intents and reconciles
|
|
```
|
|
|
|
Example: `memory.promoted` → session event (step 1) → `LearnedMemoryStore.insert` (step 3) →
|
|
`memory.promoted` completion evidence (step 4). If step 3 fails, the session event remains and
|
|
recovery retries or marks failed.
|
|
|
|
### 18.5 Security invariants
|
|
|
|
From contracts §23, security-model-v1, overview §12:
|
|
|
|
- LLM output is untrusted until validated by runtime/tool schemas and PermissionEngine.
|
|
- Provider output cannot directly modify files or run commands.
|
|
- Credentials are referenced by `auth_ref`, never copied into events/artifacts.
|
|
- No automatic upload of source, logs, screenshots, bundles, pcaps, or artifacts.
|
|
- Destructive/system-sensitive actions require confirmation or policy block.
|
|
- Path policy uses realpath normalization; symlink escapes are not allowed by string-prefix checks.
|
|
- `.git/` internals are protected from arbitrary write tools.
|
|
- `sudo` risk is determined by command intent/target/system sensitivity, not string alone.
|
|
|
|
## 19. Sequence Designs
|
|
|
|
### 19.1 User request → task execution → completion
|
|
|
|
```text
|
|
User
|
|
│ user.message.created
|
|
▼
|
|
MainAgent (CLASSIFYING)
|
|
│ classify_intent → "task"
|
|
▼
|
|
MainAgent (DELEGATING)
|
|
│ architecture impact? → ArchitectureDesigner.assess_impact
|
|
│ architecture.impact.completed
|
|
▼
|
|
MainAgent (SCHEDULING)
|
|
│ Scheduler.create_tasks(specs)
|
|
│ task.created (durable)
|
|
▼
|
|
Scheduler (PLANNING_WAVE)
|
|
│ WavePlanner.plan → SchedulerWavePlan
|
|
▼
|
|
Scheduler (DISPATCHING)
|
|
│ WorkspaceManager.create_workspace
|
|
│ workspace.created (durable)
|
|
│ ContextAssembler.assemble → ContextPack
|
|
│ WorkerManager.spawn
|
|
│ agent.started (durable)
|
|
│ task.started (durable)
|
|
▼
|
|
WorkerProcess (ExecutorRole)
|
|
│ WorkerRuntime.call_tool("fs.read", ...)
|
|
│ → IPC tool.call → parent ToolRegistry.call
|
|
│ → PermissionEngine.evaluate → allow
|
|
│ → tool.started (durable)
|
|
│ → execute → tool.completed (durable)
|
|
│ → IPC tool.result
|
|
│ WorkerRuntime.call_tool("fs.edit", ...)
|
|
│ → (same flow, read-before-edit enforced)
|
|
│ WorkerRuntime.call_tool("shell.run", verification)
|
|
│ → command.started, command.completed (durable)
|
|
│ return WorkerResult { status: "completed", ... }
|
|
▼
|
|
Scheduler (COLLECTING_RESULTS)
|
|
│ validate WorkerResult
|
|
│ task.completed (durable)
|
|
│ agent.completed (durable)
|
|
▼
|
|
Scheduler (MERGING)
|
|
│ WorkspaceManager.merge_workspace
|
|
│ workspace.merge.completed (durable)
|
|
▼
|
|
Scheduler (REVIEWING_WAVE) [if required]
|
|
│ create review task → ReviewerRole
|
|
│ ReviewerResult { verdict: "approved" }
|
|
▼
|
|
Scheduler (COMPLETED)
|
|
│ SchedulerRunResult { status: "completed" }
|
|
▼
|
|
MainAgent (SUMMARIZING)
|
|
│ present result to user
|
|
│ trigger ExperienceMiner task (optional)
|
|
▼
|
|
MainAgent (IDLE)
|
|
```
|
|
|
|
### 19.2 Tool call with permission prompt
|
|
|
|
```text
|
|
WorkerRuntime.call_tool("shell.run", { command: "rm -rf build/" })
|
|
│
|
|
▼
|
|
ToolRegistry.call
|
|
│ PermissionEngine.evaluate
|
|
│ → PathClassifier.classify → project_build_output
|
|
│ → CommandRiskAnalyzer.analyze → destructive
|
|
│ → decision: ask_user (risk: medium)
|
|
▼
|
|
ToolRegistry suspends
|
|
│ permission.prompt.requested (durable)
|
|
▼
|
|
ProjectionStore.apply → PermissionPromptProjection
|
|
│
|
|
▼
|
|
TUI PermissionPrompt renders
|
|
│ user selects "Allow once"
|
|
▼
|
|
UiCommandChannel emits permission response
|
|
│ permission.prompt.resolved (durable)
|
|
│ PermissionEngine.record
|
|
▼
|
|
ToolRegistry resumes
|
|
│ tool.started (durable)
|
|
│ execute shell command
|
|
│ command.started, command.completed (durable)
|
|
│ tool.completed (durable)
|
|
▼
|
|
IPC tool.result → WorkerRuntime
|
|
```
|
|
|
|
### 19.3 Compaction flow
|
|
|
|
```text
|
|
ContextAssembler.assemble
|
|
│ fit_budget fails → compaction_requested = true
|
|
▼
|
|
Scheduler receives compaction request
|
|
│ create_tasks([{ type: "compact", ... }])
|
|
│ task.created (durable)
|
|
│ context.compaction.requested (durable)
|
|
▼
|
|
Scheduler dispatches CompactorRole
|
|
│ task.started, agent.started (durable)
|
|
│ context.compaction.started (durable)
|
|
▼
|
|
CompactorRole
|
|
│ snapshot immutable message range
|
|
│ generate summary via LLM
|
|
│ ArtifactStore.create(summary artifact)
|
|
│ artifact.created (durable)
|
|
│ return CompactorResult { summary_id }
|
|
▼
|
|
Scheduler collects result
|
|
│ summary.created (durable) ← inserts summaries row
|
|
│ context.compaction.completed (durable)
|
|
│ task.completed (durable)
|
|
▼
|
|
Original messages preserved for backtracking
|
|
```
|
|
|
|
### 19.4 Debug knowledge capture
|
|
|
|
```text
|
|
ExecutorRole fails with build error
|
|
│ WorkerResult { status: "failed", error: AirError }
|
|
▼
|
|
Scheduler (REPAIRING_OR_CONTINUING)
|
|
│ RetryPlanner.decide → "debug"
|
|
│ create debug task
|
|
▼
|
|
DebuggerRole
|
|
│ analyze failure evidence
|
|
│ lookup DebugKnowledgeStore.lookup_by_signature
|
|
│ (no match) → diagnose root cause
|
|
│ fix or return blocker
|
|
│ return DebuggerResult { diagnosis, root_cause, fixed: true }
|
|
▼
|
|
Scheduler
|
|
│ task.completed (durable)
|
|
│ debug.record.created (durable) ← session event
|
|
│ DebugKnowledgeStore.insert (outbox step 3)
|
|
▼
|
|
Future similar failure
|
|
│ DebugKnowledgeStore.lookup_by_signature → hit
|
|
│ DebuggerRole applies known fix faster
|
|
```
|
|
|
|
## 20. State Machine Designs
|
|
|
|
### 20.1 Main Agent State Machine
|
|
|
|
From main-agent-state-machine.md. States and transitions:
|
|
|
|
```text
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ IDLE │
|
|
│ Waiting for user input │
|
|
└───────────────────────────┬─────────────────────────────────────┘
|
|
│ user.message.created
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ CLASSIFYING │
|
|
│ LLM classifies intent │
|
|
└────────┬──────────────────┬──────────────────┬──────────────────┘
|
|
│ chat/Q&A │ task request │ /direct
|
|
▼ ▼ ▼
|
|
┌─────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ANSWERING│ │ DELEGATING │ │ DIRECT_MODE │
|
|
│→ IDLE │ └──┬──────┬───┘ │ /done→IDLE │
|
|
└─────────┘ │ │ └─────────────┘
|
|
simple│ needs│plan
|
|
▼ ▼
|
|
┌──────────┐ ┌─────────────────────┐
|
|
│SCHEDULING│ │ARCHITECTURE_DESIGNING│
|
|
│→ EXECUTING│ │→ CONFIRMING │
|
|
└──────────┘ └─────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────┐
|
|
│ CONFIRMING │
|
|
│ user confirm│
|
|
└──┬──────┬───┘
|
|
confirm │ │ reject → IDLE
|
|
▼
|
|
┌─────────────┐
|
|
│ EXECUTING │
|
|
│ Scheduler │
|
|
└──┬──────┬───┘
|
|
requirement │ │ all done
|
|
change ▼ │
|
|
┌─────────────┐│
|
|
│INTERRUPTING ││
|
|
└──┬──────┬───┘│
|
|
exec-only│ design │
|
|
▼ ▼ │
|
|
resume ┌──────────┐ │
|
|
EXECUTING│ARCH_REV │ │
|
|
│→CONFIRM │ │
|
|
└─────────┘ │
|
|
▼
|
|
┌─────────────┐
|
|
│ SUMMARIZING │
|
|
│ → IDLE │
|
|
└─────────────┘
|
|
```
|
|
|
|
State-to-permission_template (main-agent-state-machine §State-to-AgentRuntimeContext):
|
|
|
|
| State | permission_template |
|
|
|---|---|
|
|
| IDLE, CLASSIFYING, ANSWERING, CONFIRMING, SUMMARIZING | N/A |
|
|
| DIRECT_MODE | `main_direct` |
|
|
| EXECUTING | per-task (Scheduler assigns) |
|
|
| INTERRUPTING, ARCHITECTURE_REVISING | N/A (delegation) |
|
|
|
|
### 20.2 Scheduler State Machine
|
|
|
|
From scheduler-state-machine-v1.md §4. States:
|
|
|
|
```text
|
|
IDLE
|
|
│ task.created / execution request
|
|
▼
|
|
LOADING_GRAPH
|
|
│ reconstruct TaskGraph from DB
|
|
│ detect orphaned agents → agent.lost
|
|
│ validate dependencies
|
|
├─ valid runnable → PLANNING_WAVE
|
|
├─ no runnable + blocked → BLOCKED
|
|
├─ all terminal success → COMPLETED
|
|
└─ invalid beyond repair → BLOCKED
|
|
|
|
PLANNING_WAVE
|
|
│ WavePlanner.plan
|
|
├─ runnable wave → DISPATCHING
|
|
└─ no runnable → BLOCKED
|
|
|
|
DISPATCHING
|
|
│ create workspaces
|
|
│ assemble context
|
|
│ spawn workers
|
|
│ emit task.started, agent.started
|
|
└─ → MONITORING
|
|
|
|
MONITORING
|
|
│ track heartbeats, progress, timeouts
|
|
│ handle requirement.changed
|
|
├─ all agents terminal → COLLECTING_RESULTS
|
|
├─ user/global cancel → CANCELLED
|
|
└─ architecture/user blocker → BLOCKED
|
|
|
|
COLLECTING_RESULTS
|
|
│ validate WorkerResult
|
|
│ persist artifacts/evidence
|
|
│ classify task terminal status
|
|
├─ workspaces need merge → MERGING
|
|
├─ review required → REVIEWING_WAVE
|
|
├─ more work → REPAIRING_OR_CONTINUING
|
|
└─ all done → COMPLETED
|
|
|
|
MERGING
|
|
│ WorkspaceManager.merge_workspace
|
|
├─ success + review → REVIEWING_WAVE
|
|
├─ success + more → REPAIRING_OR_CONTINUING
|
|
├─ conflict recoverable → REPAIRING_OR_CONTINUING
|
|
└─ unrecoverable → BLOCKED
|
|
|
|
REVIEWING_WAVE
|
|
│ schedule review tasks
|
|
│ collect ReviewerResult
|
|
└─ → REPAIRING_OR_CONTINUING
|
|
|
|
REPAIRING_OR_CONTINUING
|
|
│ retry failed within budget
|
|
│ create repair tasks
|
|
│ skip allowed failures
|
|
├─ more runnable → PLANNING_WAVE
|
|
├─ blocked → BLOCKED
|
|
├─ all done → COMPLETED
|
|
└─ cancelled → CANCELLED
|
|
|
|
Terminal: COMPLETED | BLOCKED | CANCELLED
|
|
```
|
|
|
|
### 20.3 Task Status Transitions
|
|
|
|
From db-schema §7, scheduler-state-machine §2:
|
|
|
|
```text
|
|
pending ──task.started──▶ running
|
|
running ──task.completed──▶ completed
|
|
running ──task.failed──▶ failed
|
|
running ──task.blocked──▶ blocked
|
|
running ──task.cancelled──▶ cancelled
|
|
running ──task.interrupted──▶ interrupted
|
|
failed ──retry──▶ pending (new attempt)
|
|
interrupted ──resume──▶ pending
|
|
blocked ──decision received──▶ pending
|
|
```
|
|
|
|
### 20.4 Agent Status Transitions
|
|
|
|
From db-schema §10:
|
|
|
|
```text
|
|
starting ──ready──▶ running
|
|
running ──agent.completed──▶ completed
|
|
running ──agent.failed──▶ failed
|
|
running ──agent.lost──▶ lost
|
|
running ──agent.cancelled──▶ cancelled
|
|
```
|
|
|
|
### 20.5 Workspace Status Transitions
|
|
|
|
From db-schema §16:
|
|
|
|
```text
|
|
active ──merge success──▶ merged
|
|
active ──merge conflict──▶ conflicted
|
|
active ──abandon──▶ abandoned
|
|
conflicted ──decision──▶ abandoned | active (retry)
|
|
merged ──GC (7d)──▶ cleaned
|
|
abandoned ──GC (3d)──▶ cleaned
|
|
```
|
|
|
|
### 20.6 Capability Lifecycle
|
|
|
|
From capability-trust-v1 §7, overview §6:
|
|
|
|
```text
|
|
discovered ──validate──▶ validated
|
|
validated ──doctor_check──▶ doctor_checked
|
|
doctor_checked ──enable──▶ enabled
|
|
enabled ──register_tools──▶ registered
|
|
registered ──activate──▶ active
|
|
active ──disable──▶ disabled
|
|
active ──failure──▶ failed
|
|
active ──update──▶ updated (→ discovered)
|
|
```
|
|
|
|
## 21. Traceability Matrix
|
|
|
|
This matrix maps frozen baseline sections to detailed design sections, ensuring no baseline
|
|
requirement is unaddressed.
|
|
|
|
### 21.1 Contracts → Detailed Design
|
|
|
|
| Contracts section | Detailed design section |
|
|
|---|---|
|
|
| §2 Core Primitive Types | §3 (contracts package) |
|
|
| §3 Error Contracts | §3, §18.1 |
|
|
| §4 Entity References | §3 |
|
|
| §5 Runtime Event Contracts | §3, §5 |
|
|
| §6 Transaction and Storage | §4, §18.2 |
|
|
| §7 EventBus/Store/Ingestor | §5 |
|
|
| §8 Project and Session | §6 |
|
|
| §9 Task and Scheduler | §7 |
|
|
| §10 Worker and IPC | §8 |
|
|
| §11 WorkerResult | §8.3 |
|
|
| §12 Tool Contracts | §9.1 |
|
|
| §13 Permission Contracts | §9.2, §9.3 |
|
|
| §14 Artifact and Evidence | §11 |
|
|
| §15 Provider Contracts | §12 |
|
|
| §16 Context Contracts | §10 |
|
|
| §17 Projection/UI Contracts | §13 |
|
|
| §18 Capability Contracts | §9.5 |
|
|
| §19 Doctor and Logging | §16 |
|
|
| §20 Debug/Learned Memory | §11.3 |
|
|
| §21 Diagnostic Contracts | §15 (DiagnosticParser) |
|
|
| §22 Versioning Rules | §3 (contracts package rules) |
|
|
| §23 Boundary Rules | §2, §18.5 |
|
|
|
|
### 21.2 State Machines → Detailed Design
|
|
|
|
| State machine baseline | Detailed design section |
|
|
|---|---|
|
|
| main-agent-state-machine.md | §14.1, §20.1 |
|
|
| scheduler-state-machine-v1.md | §7, §20.2 |
|
|
| db-schema §7 task status | §20.3 |
|
|
| db-schema §10 agent status | §20.4 |
|
|
| db-schema §16 workspace status | §20.5 |
|
|
| capability-trust-v1 §7 | §9.5, §20.6 |
|
|
|
|
### 21.3 DB Schema → Detailed Design
|
|
|
|
| DB schema table | Repository (§4.3) | Event projection (§5.4) |
|
|
|---|---|---|
|
|
| schema_meta | MigrationRunner | — |
|
|
| sessions | SessionRepository | session.* |
|
|
| messages | MessageRepository | user/assistant.message.* |
|
|
| message_drafts | MessageDraftRepository | assistant.message.started/failed |
|
|
| events | EventRepository | all durable |
|
|
| tasks | TaskRepository | task.* |
|
|
| task_dependencies | TaskDependencyRepository | task.created |
|
|
| task_attempts | TaskAttemptRepository | task.started/completed/failed |
|
|
| agents | AgentRepository | agent.* |
|
|
| tool_runs | ToolRunRepository | tool.* |
|
|
| command_runs | CommandRunRepository | command.* |
|
|
| artifacts | ArtifactRepository | artifact.created |
|
|
| diagnostics | DiagnosticRepository | diagnostic.created |
|
|
| evidence_refs | EvidenceRepository | evidence.created |
|
|
| workspaces | WorkspaceRepository | workspace.* |
|
|
| summaries | SummaryRepository | summary.created |
|
|
| ui_state | UiStateRepository | — (not event-driven) |
|
|
| debug_records (project DB) | DebugKnowledgeStore | debug.record.created |
|
|
| learned_memories (project DB) | LearnedMemoryStore | memory.* |
|
|
|
|
### 21.4 Code View → Detailed Design
|
|
|
|
| Code view package | Detailed design sections |
|
|
|---|---|
|
|
| packages/contracts | §3 |
|
|
| packages/runtime | §4-§11, §13-§14, §16 |
|
|
| packages/llm | §12 |
|
|
| packages/toolchain-cpp | §15 |
|
|
| packages/tui | §13.2 |
|
|
| packages/cli | §17 |
|
|
|
|
### 21.5 Overview → Detailed Design
|
|
|
|
| Overview section | Detailed design section |
|
|
|---|---|
|
|
| §2 System Goal | §0 (authority), §2 |
|
|
| §4 Container Overview | §2, §3 |
|
|
| §5 Dependency Rules | §2 |
|
|
| §6 Runtime Component Overview | §4-§11 |
|
|
| §7 Runtime Agent Overview | §14 |
|
|
| §8 State and Data Overview | §4, §6, §11 |
|
|
| §9 Event, Error, Projection | §5, §18.1, §13.1 |
|
|
| §10 Execution Flow Overview | §7, §8, §9, §19 |
|
|
| §11 IPC and Worker Overview | §8 |
|
|
| §12 Permission and Security | §9.2, §9.3, §18.5 |
|
|
| §13 Context, Memory, Compaction | §10, §11.3, §19.3 |
|
|
| §14 UI/HUD and Provider | §12, §13 |
|
|
| §15 Doctor, Restore, Recovery | §16 |
|
|
| §16 Implementation Phase Mapping | (implementation phase, not design) |
|
|
| §17 Validation Overview | (test phase, not design) |
|
|
|
|
## 22. UML Class Diagrams (Mermaid)
|
|
|
|
### 22.1 Contracts Package
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class RuntimeEvent~T~ {
|
|
+id: UUID
|
|
+type: string
|
|
+version: number
|
|
+timestamp: ISOTimeString
|
|
+session_id: SessionID
|
|
+project_id?: ProjectID
|
|
+source: EventSource
|
|
+route: string[]
|
|
+payload: T
|
|
}
|
|
class EventSource {
|
|
+kind: "main"|"architecture_designer"|"scheduler"|"agent"|"tool"|"system"
|
|
+id?: string
|
|
+agent_type?: AgentType
|
|
}
|
|
class TaskSpec {
|
|
+id: TaskID
|
|
+type: TaskType
|
|
+title: string
|
|
+description: string
|
|
+acceptance_criteria: string[]
|
|
+scope: TaskScope
|
|
+dependencies: TaskDependencySpec[]
|
|
+verification: VerificationPolicy
|
|
+constraints: TaskConstraints
|
|
+context_refs: TaskContextRefs
|
|
+output_contract: WorkerOutputContract
|
|
}
|
|
class WorkerResult~T~ {
|
|
+task_id: TaskID
|
|
+agent_id: AgentID
|
|
+agent_type: AgentType
|
|
+status: WorkerStatus
|
|
+summary: string
|
|
+changed_files: string[]
|
|
+artifacts: ArtifactRef[]
|
|
+verification: VerificationResult[]
|
|
+risks: Risk[]
|
|
+follow_up_tasks: FollowUpTask[]
|
|
+evidence_refs: EvidenceRef[]
|
|
+result: T
|
|
}
|
|
class AirError {
|
|
+error_id: UUID
|
|
+kind: ErrorKind
|
|
+severity: ErrorSeverity
|
|
+message: string
|
|
+detail?: string
|
|
+retryability: Retryability
|
|
+semantic_signature: string
|
|
+cause_ref?: EntityRef
|
|
+cause_refs?: EntityRef[]
|
|
+user_action?: string
|
|
+metadata?: JsonObject
|
|
}
|
|
class ToolDefinition~I,O~ {
|
|
+name: string
|
|
+version: number
|
|
+description: string
|
|
+input_schema: JsonSchema~I~
|
|
+output_schema: JsonSchema~O~
|
|
+category: ToolCategory
|
|
+permissions: ToolPermissionSpec
|
|
+streaming: boolean
|
|
}
|
|
class PermissionDecision {
|
|
+action: PermissionAction
|
|
+grant_scope: PermissionGrantScope
|
|
+risk_level: string
|
|
+reason: string
|
|
+required_confirmation?: boolean
|
|
+backup_required?: boolean
|
|
+evidence_ref_ids?: EvidenceRefID[]
|
|
}
|
|
class ArtifactRef {
|
|
+artifact_id: ArtifactID
|
|
+uri: string
|
|
+path: string
|
|
+type: string
|
|
+sha256?: string
|
|
+size_bytes?: number
|
|
}
|
|
class EvidenceRef {
|
|
+evidence_ref_id: EvidenceRefID
|
|
+kind: string
|
|
+ref: string
|
|
+claim: string
|
|
+location_json?: unknown
|
|
}
|
|
RuntimeEvent --> EventSource
|
|
WorkerResult --> ArtifactRef
|
|
WorkerResult --> EvidenceRef
|
|
AirError --> EntityRef
|
|
```
|
|
|
|
### 22.2 Runtime Core Services
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class RuntimeApp {
|
|
+start(options): Promise~void~
|
|
+shutdown(): Promise~void~
|
|
}
|
|
class ServiceRegistry {
|
|
+get~T~(token): T
|
|
+register(token, service): void
|
|
}
|
|
class ProjectStore {
|
|
+locate(start_path): Promise~ProjectContext~
|
|
+initialize(root, options): Promise~ProjectContext~
|
|
+open(root): Promise~ProjectContext~
|
|
}
|
|
class SessionManager {
|
|
+open_session(project, options): Promise~SessionContext~
|
|
+close_session(session_id): Promise~void~
|
|
}
|
|
class DatabaseManager {
|
|
+open(path): DatabaseHandle
|
|
+transaction~T~(fn): Promise~T~
|
|
}
|
|
class EventIngestor {
|
|
+ingest~T~(event): Promise~void~
|
|
+ingest_ephemeral~T~(event): Promise~void~
|
|
}
|
|
class EventStore {
|
|
+append~T~(event, options): Promise~void~
|
|
+append_many(events, options): Promise~void~
|
|
+query(filter): Promise~RuntimeEvent[]~
|
|
}
|
|
class EventBus {
|
|
+publish~T~(event): void
|
|
+subscribe(filter, handler): Subscription
|
|
+drain(): Promise~void~
|
|
}
|
|
class ProjectionStore {
|
|
+hydrate(session_id): Promise~void~
|
|
+apply(event): void
|
|
+snapshot(): ProjectionSnapshot
|
|
+subscribe(handler): Subscription
|
|
}
|
|
RuntimeApp --> ServiceRegistry
|
|
RuntimeApp --> ProjectStore
|
|
RuntimeApp --> SessionManager
|
|
SessionManager --> DatabaseManager
|
|
EventIngestor --> EventStore
|
|
EventIngestor --> EventBus
|
|
EventStore --> DatabaseManager
|
|
EventStore --> EventBus : publishes after commit
|
|
ProjectionStore --> EventBus : subscribes
|
|
```
|
|
|
|
### 22.3 Scheduler Subsystem
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class Scheduler {
|
|
+create_tasks(session_id, specs): Promise~void~
|
|
+add_dependency(session_id, task_id, dep): Promise~void~
|
|
+load_graph(session_id): Promise~TaskGraph~
|
|
+run_until_idle(session_id): Promise~SchedulerRunResult~
|
|
+cancel_task(task_id, reason): Promise~void~
|
|
-plan_wave(graph): SchedulerWavePlan
|
|
-dispatch(wave): Promise~void~
|
|
-collect_results(): Promise~void~
|
|
}
|
|
class TaskGraph {
|
|
+session_id: SessionID
|
|
+tasks: Map~TaskID, TaskNode~
|
|
+dependencies: TaskDependencyRecord[]
|
|
+get_runnable_tasks(): TaskNode[]
|
|
+mark_terminal(task_id, status): void
|
|
}
|
|
class WavePlanner {
|
|
+plan(graph, resources): SchedulerWavePlan
|
|
}
|
|
class RetryPlanner {
|
|
+decide(task, attempts, error): RetryDecision
|
|
}
|
|
class WorkspaceManager {
|
|
+create_workspace(plan): Promise~WorkspaceRef~
|
|
+merge_workspace(workspace_id): Promise~MergeResult~
|
|
+cleanup_workspace(workspace_id): Promise~void~
|
|
}
|
|
class AgentMonitor {
|
|
+record_heartbeat(event): void
|
|
+detect_lost_agents(): Promise~AgentLost[]~
|
|
+enforce_timeouts(): Promise~void~
|
|
}
|
|
class WorkerManager {
|
|
+spawn(task_spec, context_pack): Promise~WorkerProcess~
|
|
+cancel(agent_id, reason): Promise~void~
|
|
}
|
|
Scheduler --> TaskGraph
|
|
Scheduler --> WavePlanner
|
|
Scheduler --> RetryPlanner
|
|
Scheduler --> WorkspaceManager
|
|
Scheduler --> AgentMonitor
|
|
Scheduler --> WorkerManager
|
|
```
|
|
|
|
### 22.4 Tool and Permission Subsystem
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class ToolRegistry {
|
|
+register~I,O~(definition, executor): void
|
|
+register_streaming~I,O~(definition, executor): void
|
|
+call~I,O~(name, input, context): Promise~ToolResultEnvelope~O~~
|
|
+call_streaming~I,O~(name, input, context): AsyncIterable
|
|
+list(): ToolDefinition[]
|
|
}
|
|
class PermissionEngine {
|
|
+evaluate(context): Promise~PermissionDecision~
|
|
+record(decision, context): Promise~PermissionRecordResult~
|
|
}
|
|
class PathClassifier {
|
|
+classify(path, project_root): PathRiskClassification
|
|
}
|
|
class CommandRiskAnalyzer {
|
|
+analyze(command, cwd): CommandRiskAnalysis
|
|
}
|
|
class CapabilityRegistry {
|
|
+discover(): Promise~CapabilityManifestV1[]~
|
|
+validate(manifest): Promise~ValidationResult~
|
|
+enable(capability_id): Promise~void~
|
|
+disable(capability_id): Promise~void~
|
|
+register_tools(tool_registry): Promise~void~
|
|
}
|
|
ToolRegistry --> PermissionEngine
|
|
PermissionEngine --> PathClassifier
|
|
PermissionEngine --> CommandRiskAnalyzer
|
|
CapabilityRegistry --> ToolRegistry : registers tools
|
|
```
|
|
|
|
### 22.5 Worker and IPC
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class WorkerProcess {
|
|
+agent_id: AgentID
|
|
+pid?: number
|
|
+send(envelope): void
|
|
+on_message(handler): void
|
|
}
|
|
class WorkerProtocol {
|
|
+encode(msg): string
|
|
+decode(line): IpcMessage
|
|
+validate_direction(msg): void
|
|
+check_protocol_version(v): boolean
|
|
}
|
|
class WorkerRuntime {
|
|
+emit(event): Promise~void~
|
|
+call_tool~I,O~(name, input): Promise~ToolResultEnvelope~O~~
|
|
+checkpoint(data): Promise~void~
|
|
}
|
|
class WorkerRole~T~ {
|
|
<<interface>>
|
|
+run(task_spec, context_pack, runtime): Promise~WorkerResult~T~~
|
|
}
|
|
class ExecutorRole {
|
|
+run(...): Promise~WorkerResult~ExecutorResult~~
|
|
}
|
|
class ReviewerRole {
|
|
+run(...): Promise~WorkerResult~ReviewerResult~~
|
|
}
|
|
class DebuggerRole {
|
|
+run(...): Promise~WorkerResult~DebuggerResult~~
|
|
}
|
|
class CompactorRole {
|
|
+run(...): Promise~WorkerResult~CompactorResult~~
|
|
}
|
|
class ExperienceMinerRole {
|
|
+run(...): Promise~WorkerResult~ExperienceMinerResult~~
|
|
}
|
|
WorkerRole <|.. ExecutorRole
|
|
WorkerRole <|.. ReviewerRole
|
|
WorkerRole <|.. DebuggerRole
|
|
WorkerRole <|.. CompactorRole
|
|
WorkerRole <|.. ExperienceMinerRole
|
|
WorkerRole --> WorkerRuntime
|
|
WorkerProcess --> WorkerProtocol
|
|
```
|
|
|
|
### 22.6 Provider (LLM) Subsystem
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class ProviderManager {
|
|
+load_config(): Promise~void~
|
|
+select_model(requirement): Promise~ModelAssignment~
|
|
+complete(input): AsyncIterable~ProviderStreamEvent~
|
|
}
|
|
class ProviderAdapter {
|
|
<<interface>>
|
|
+provider_id: ProviderID
|
|
+list_models(): Promise~ProviderCapabilityMatrix[]~
|
|
+validate_model(model_id): Promise~ProviderCapabilityMatrix~
|
|
+complete(input): AsyncIterable~ProviderStreamEvent~
|
|
+count_tokens?(input): Promise~number~
|
|
}
|
|
class AnthropicAdapter {
|
|
+provider_id: "anthropic"
|
|
}
|
|
class OpenAICompatibleAdapter {
|
|
+provider_id: string
|
|
-converter: AnthropicCanonicalConverter
|
|
}
|
|
class AnthropicCanonicalConverter {
|
|
+to_provider(messages): unknown[]
|
|
+from_provider(response): unknown[]
|
|
}
|
|
class StreamNormalizer {
|
|
+normalize(stream): AsyncIterable~ProviderStreamEvent~
|
|
}
|
|
ProviderManager --> ProviderAdapter
|
|
ProviderAdapter <|.. AnthropicAdapter
|
|
ProviderAdapter <|.. OpenAICompatibleAdapter
|
|
OpenAICompatibleAdapter --> AnthropicCanonicalConverter
|
|
ProviderAdapter --> StreamNormalizer
|
|
```
|
|
|
|
### 22.7 Context and Compaction
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class ContextAssembler {
|
|
+assemble(input): Promise~AssembledContext~
|
|
-load_layers(purpose): Promise~PromptLayer[]~
|
|
-fit_budget(layers, budget): BudgetFitResult
|
|
}
|
|
class PromptLayerLoader {
|
|
+load_runtime_invariant(): PromptLayer
|
|
+load_role(role): PromptLayer
|
|
+load_project_rules(project): PromptLayer[]
|
|
+load_task_context(spec, refs): PromptLayer[]
|
|
}
|
|
class CompactionPolicy {
|
|
+should_compact(messages, budget): boolean
|
|
+compact(messages, target): Promise~CompactionResult~
|
|
}
|
|
class PromptLayer {
|
|
+level: PromptLayerLevel
|
|
+priority: number
|
|
+content: unknown
|
|
+token_estimate?: number
|
|
+source_ref?: string
|
|
+immutable?: boolean
|
|
}
|
|
ContextAssembler --> PromptLayerLoader
|
|
ContextAssembler --> CompactionPolicy
|
|
PromptLayerLoader --> PromptLayer
|
|
```
|
|
|
|
### 22.8 Agents
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class MainAgent {
|
|
+handle_user_message(message): Promise~void~
|
|
+present_progress(): Promise~void~
|
|
+present_blocker(blocker): Promise~void~
|
|
-classify_intent(message): string
|
|
-state: MainAgentState
|
|
}
|
|
class ArchitectureDesigner {
|
|
+assess_impact(change): Promise~ArchitectureImpact~
|
|
+update_architecture_docs(update): Promise~DocumentUpdate~
|
|
}
|
|
MainAgent --> Scheduler
|
|
MainAgent --> ContextAssembler
|
|
MainAgent --> ProviderManager
|
|
ArchitectureDesigner --> ContextAssembler
|
|
ArchitectureDesigner --> ProviderManager
|
|
ArchitectureDesigner --> EventIngestor
|
|
```
|
|
|
|
## 23. Design Freeze Checklist
|
|
|
|
Before implementation begins, verify:
|
|
|
|
- [ ] All contracts §2-§21 interfaces are exported from `packages/contracts`
|
|
- [ ] All db-schema §3-§18 tables have corresponding repositories
|
|
- [ ] All event-registry §3 durable events have projection handlers in EventStore
|
|
- [ ] All state machines (Main Agent, Scheduler, Task, Agent, Workspace, Capability) are implemented
|
|
- [ ] All forbidden paths (contracts §23) are enforced by lint/import boundaries
|
|
- [ ] All closed enums (db-schema §21) are validated on insert/update
|
|
- [ ] FK-off invariants (§18.3) are checked at startup and periodically
|
|
- [ ] Outbox model (§18.4) is used for cross-DB writes
|
|
- [ ] Security invariants (§18.5) are enforced
|
|
|
|
---
|
|
|
|
End of System Detailed Design.
|