Files
AirCoding/Opus4.7三视角审查.md
AirCoding 82f3140847 Initial commit: AirCoding V1.0.0 Alpha architecture baseline
Complete architecture document set with multi-model review remediation:
- Frozen interface contracts, runtime semantics, DB schemas
- Event/tool/error/provider registries
- Scheduler and main agent state machines
- C4 module/code views, solution architecture, baseline V1
- Multi-model review reports and joint assessment
- Phase-gate remediation complete (P0/P1/P2/UX resolved)
- Implementation plan with T-000A through T-045
- Reference folders kept as placeholders only
2026-05-28 18:45:01 +08:00

416 lines
40 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Opus 4.7 三视角审查
> 由 Claude Opus 4.7 并行启动三个独立审查代理生成,基于约 12K 行最新文档集。
> 生成日期:2026-05-28
---
## 一、架构师视角 (Architect Perspective)
# AirCoding V1 Architecture Review
Reviewing 11 architecture documents as a senior software architect. Note: I deliberately did not invoke TaskCreate/TaskUpdate; the review is read-only and the existing task list already tracks the architecture review itself.
---
## 1. Top Critical Architectural Issues
### C1. Vocabulary split: "V1.0.0 Alpha" vs "MVP" undermines scope discipline
The two newest documents (`solution-architecture.md §14`, `runtime-semantics-v1.md §13`) use **"V1.0.0 Alpha cut line"** and explicitly include a *complete* C++ workflow plus plugin foundation. But six older-but-canonical docs still say **"MVP cut line / Post-MVP"** with narrower content:
- `scheduler-state-machine-v1.md §11` "MVP Cut Line"
- `scope-escalation-v1.md §13` "MVP Cut Line"
- `security-model-v1.md §14` "MVP Cut Line"
- `capability-trust-v1.md §14` "MVP Cut Line"
- `cross-platform-matrix-v1.md §13` "MVP Cut Line"
- `c4/module.md §12` "MVP Skeleton Module Cut"
Effect: implementers cannot tell whether "MVP" in those docs is a synonym for V1.0.0 Alpha or a smaller earlier slice. The user's stated goal ("complete C++ workflow + plugin foundation, NOT half-finished MVP") is therefore not unambiguously expressed in the binding documents.
### C2. `main-agent-state-machine.md` is out of step with the rest of V1
- Mixed Chinese/English ASCII art, undated, no V1 status header — clearly an earlier draft.
- Uses event names (`UserMessageReceived`, `PlanProduced`, `ExecutionRequested`, `ImpactAssessmentCompleted`, `UserRequirementChanged`) that do not match the canonical event names used elsewhere (`requirement.changed`, `architecture.impact.completed`, `task.created/started/completed`).
- Introduces a `DIRECT_MODE` state with "Executor-level permission" (line ~22) without specifying: write-area conflict with Scheduler-owned tasks, audit trail beyond a single mention, how it interacts with `permission_profile: "main_direct"` in `AgentRuntimeContext`, or how `/done` reconciles in-flight side effects.
- Violates `solution-architecture.md §2` precedence rule: this is a state machine doc but doesn't carry V1 framing or align to the event registry it implicitly depends on.
### C3. C++ DiagnosticParser ownership is contradicted across documents
- `baselineV1.md §20`: "DiagnosticParser: **LLM-based** compiler/linker parsing and semantic signatures."
- `c4/code-view.md §6`: `DiagnosticParser` lives inside `packages/toolchain-cpp` and is wired into `CMakeConfigurator`, `CppBuilder`, `CppTestRunner`, `CppcheckRunner`.
- `runtime-semantics-v1.md §12`: "**LLM-based interpretation belongs to runtime Debugger/Reviewer context, not hidden inside low-level toolchain code.** … `toolchain-cpp → contracts`, `runtime/debugger → llm/provider facade`."
If runtime-semantics is authoritative (and it claims to be for V1.0.0 Alpha), then baselineV1 §20 wording and code-view's placement together imply an implicit `toolchain-cpp → llm` dependency that violates the package direction in `c4/module.md §3`.
### C4. TUI ↔ Runtime transport boundary is unspecified
- `c4/module.md §2` shows TUI and runtime as separate containers; TUI must **not** query SQLite or EventBus directly.
- `c4/code-view.md §7` says TUI uses a `ProjectionClient` and a "narrow runtime UI command API."
- No document specifies whether TUI is in the same Bun process as runtime, in a child process, or remote-capable. No protocol (function call vs. NDJSON vs. pipe) is defined for `ProjectionClient.subscribe`, permission prompts, or user blocker confirmations.
This is a load-bearing decision: if TUI is in-process, the "do not import runtime private modules" rule is enforced only by convention; if out-of-process, an entire IPC contract is missing from the V1 baselines.
### C5. `PRAGMA foreign_keys = OFF` on the source-of-truth DB
`solution-architecture.md §6` mandates FK off, while:
- The same schema requires transactional `events` insert + domain projection (§6).
- `runtime-semantics-v1.md §6` adds outbox-style cross-DB compensation for `debug-records.db`, `learned-memory.db`, artifact files, and rules.
- Recovery semantics rely on consistency of `tasks`/`task_attempts`/`agents`/`workspaces`/`tool_runs`/`command_runs`.
Disabling FK is defensible for migration flexibility, but no document states the rationale or compensating invariant checks. Combined with cross-DB outbox, the correctness burden on application code is significant and currently unguarded.
### C6. ProjectionStore dependency direction conflicts with module rules
- `c4/module.md §3` Rule 6: "`ProjectionStore → EventBus` … one-way."
- `c4/code-view.md §4` (Runtime Service UML): `ProjectionStore --> SessionStore : hydrate via repositories` and `ProjectionStore --> EventBus : subscribes`.
- `c4/code-view.md §11` State Ownership: "session DB | SessionStore/EventStore | runtime services only" — but `ProjectionStore` reads through SessionStore, which leaks domain repository surface to a UI-projection component.
Not a hard cycle, but the projection layer is doing both event-sourced and DB-replay reads with no documented conflict-resolution rule when DB and live-event ordering disagree under coalescing.
---
## 2. Should-Fix Before Detailed Design
1. **Unify cut-line vocabulary.** Replace every "MVP cut line" with "V1.0.0 Alpha cut line" (or define both, with one being a strict subset of the other) in the six docs listed in C1. Without this, the "complete C++ workflow + plugin foundation" goal is not auditable.
2. **Rewrite or retire `main-agent-state-machine.md`.** Bring its event names into the registry, add a V1 header, define DIRECT_MODE write-scope rules, and align state names with `scheduler-state-machine-v1.md` (`requirement.changed` flow already covers `INTERRUPTING`).
3. **Resolve DiagnosticParser ownership.** Either:
- keep deterministic extraction in `toolchain-cpp` and explicitly delete LLM language from `baselineV1.md §20`, or
- introduce a `DiagnosticInterpretationService` in runtime that toolchain-cpp depends on through a contracts-only interface.
4. **Specify the TUI ↔ Runtime transport** (in-process vs. NDJSON child) and add a `ProjectionTransport` contract to `packages/contracts`. Without it, `interface-contracts-v1.md` cannot be considered frozen.
5. **Justify or rescind `foreign_keys = OFF`.** At minimum, document the integrity invariants the runtime promises to enforce in code, and add them to the release-gate test list in `cross-platform-matrix-v1.md §11`.
6. **Define the V1.0.0 Alpha status of Compactor and ExperienceMiner explicitly.** Both appear in `solution-architecture.md §5` and `c4/module.md §5` as runtime agents, but neither `solution-architecture.md §14` nor `runtime-semantics-v1.md §13` lists them as in-scope. The user's "not half-finished" criterion requires a yes/no decision.
7. **Specify ExperienceMiner trigger ownership.** `baselineV1.md §16` lists triggers; `runtime-semantics-v1.md §11` requires an "explicit promotion task." Who creates that task — Main Agent, Scheduler on `task.completed`, or a periodic service — is undefined.
8. **Doctor bootstrap loop.** `core-doctor` is itself a capability (`capability-trust-v1.md §12`). Define how Doctor's own dependencies (Bun, SQLite, basic shell) are validated before the capability lifecycle (`discovered → validated → doctor_checked → enabled`) can run.
9. **Workspace GC policy.** `<project>/.air/local/workspaces/` and the `workspaces` table both grow; only "preserve until merge/cleanup decision recorded" is stated (`scheduler-state-machine-v1.md §9`). Add an explicit cleanup transition and retention bound.
10. **Add `packages/contracts` to `baselineV1.md §4`** package list (currently only listed in §14 and `solution-architecture.md §4`). Trivial but the precedence rule makes baselineV1 a normative source for this list.
---
## 3. Acceptable Tradeoffs
- **Outbox/compensation across session.db ↔ debug-records.db ↔ learned-memory.db ↔ files** (`runtime-semantics-v1.md §6`). Full distributed transactions are out of scope; the session-DB-first-intent pattern with restart reconciliation is a reasonable V1 choice as long as recovery scanners actually exist.
- **Coalesced heartbeats (5s) and derived `command_runs.status`** (`runtime-semantics-v1.md §45`). Saves write amplification and a schema column; acceptable while ProjectionStore exposes the derived status uniformly.
- **No process sandbox / no plugin signing in V1** (`security-model-v1.md §14`, `capability-trust-v1.md §14`). Acceptable given Linux-tier-1 + local-only positioning, since `PermissionEngine` is on the unavoidable path.
- **Linux-first, Windows experimental** (`cross-platform-matrix-v1.md §2`). Aligns with stated product positioning; the "PathClassifier must not rely on string prefix before realpath" rule is the right minimum portability guard.
- **Workers as independent Bun processes with NDJSON IPC, exit-code mapped error classes** (`baselineV1.md §8`). Simple, debuggable, and matches the stated "Main Agent must remain idle" principle.
- **Anthropic-canonical internal format with adapter conversion at boundary** (`solution-architecture.md §9`). Correct — minimizes per-call lossy translation when staying on Anthropic.
---
## 4. Strengths
1. **Clear precedence rule** (`solution-architecture.md §2`) for resolving conflicts among baselines. Rare in young architectures and immediately useful to implementers.
2. **State ownership is mostly enumerated.** `c4/code-view.md §11` lists 9 ownership rows; `c4/module.md §4` adds component-level data ownership. This is the strongest part of the architecture.
3. **Event-driven core with explicit durable vs. ephemeral split** (`runtime-semantics-v1.md §23`, `baselineV1.md §7`). The "EventStore must not create scheduler tasks / permission decisions / memory promotions / doctor fixes by policy" rule (runtime-semantics §2) correctly prevents the most common event-sourced anti-pattern (policy migrating into the event log).
4. **Project-local `.air/{shared,local}` split with `project_id` decoupled from path.** Clean separation between git-shareable rules/plans and machine-local sessions/artifacts/backups.
5. **Read-before-edit token + exact `old_string` semantics** (`runtime-semantics-v1.md §9`). Operationalizes Claude Code-quality discipline as a tool contract, not a prompt instruction — this is the right level for enforcement.
6. **Scope escalation taxonomy** (`scope-escalation-v1.md §2`, 7 levels) is well-scoped and integrates cleanly with `PermissionEngine` actions and Scheduler decisions.
7. **Capability manifest model** (`capability-trust-v1.md`) leaves a credible path to signed third-party plugins post-V1 without restructuring V1 — namespacing rule + permission declaration + Doctor-owned dependency install is the right shape.
8. **Recovery semantics are concrete** (`scheduler-state-machine-v1.md §9`, `runtime-semantics-v1.md §6`) rather than handwaved — process liveness, attempt rows, agent.lost emission, workspace preservation are all explicit.
---
## 5. Overall Score: **7.4 / 10**
**Reasoning.** The architecture is materially better than typical at this stage:
- precedence rule established,
- containers/components/data stores/state ownership documented at three C4 levels,
- event-driven core with explicit durability boundary,
- security and capability models are coherent and not over-engineered,
- recovery semantics are operational, not aspirational.
It is held back from 8+ by:
- **Document drift** between the V1 layer (`solution-architecture`, `runtime-semantics`) and the older layer (six "MVP" docs + `main-agent-state-machine`). For a project whose explicit goal is "not half-finished," the wording must catch up.
- **One genuine contradiction** (DiagnosticParser ownership) that crosses package boundaries.
- **One missing decision** (TUI ↔ Runtime transport) that blocks freezing `interface-contracts-v1.md`.
- **One risk-unjustified rule** (`foreign_keys = OFF` over outbox-coordinated multi-DB writes).
- **Underspecified surface** for DIRECT_MODE, ExperienceMiner triggers, workspace GC, and Doctor self-bootstrap.
None of the issues are structural; all are tractable in a single editing pass before detailed design begins. After fixing items in §2 (especially C1C4), I would expect this architecture to move into the 8.5+ band.
---
### Files referenced
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/solution-architecture.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/baselineV1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/c4/module.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/c4/code-view.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/runtime-semantics-v1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/scheduler-state-machine-v1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/scope-escalation-v1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/main-agent-state-machine.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/security-model-v1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/capability-trust-v1.md
- /run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/cross-platform-matrix-v1.mdagentId: ae082ba701e248209 (use SendMessage with to: 'ae082ba701e248209' to continue this agent)
<usage>total_tokens: 80627
tool_uses: 11
duration_ms: 213238</usage>
---
## 二、工程师视角 (Engineer Perspective)
# AirCoding Architecture Review — Senior Engineer Pass
## 1. Blocking Implementation Issues (must fix before compiling contracts)
### 1.1 `AirError.cause_ref` shape conflict
- `interface-contracts-v1.md` §3: `cause_ref?: EntityRef` (a `{type, id}` 2-tuple).
- `error-taxonomy-v1.md` §2: `cause_ref?: { event_id?, task_id?, agent_id?, tool_run_id?, command_run_id?, artifact_id?, diagnostic_id? }` (multi-key object).
- These are mutually incompatible. An `AirError` produced under one definition will fail validation under the other. Pick one (the multi-key form is more useful for diagnostics; the `EntityRef` form is too narrow — a single error can reference both a tool_run and a diagnostic).
### 1.2 `EntityRef.type` enum drift
- `interface-contracts-v1.md` §4: 12 entries including `"capability"` and `"provider"`.
- `event-registry-v1.md` §1: 10 entries, omits `capability` and `provider`.
- Will cause `ts(2322)` mismatches anywhere `EntityRef` is shared between event payloads and contract callers (e.g., `RequirementChangedPayload.affected_refs?: EntityRef[]`, `PermissionPromptRequestedPayload.request_ref?: EntityRef`). Single-source `EntityType` from `contracts/ids.ts`.
### 1.3 Provider adapter method-name divergence
- `interface-contracts-v1.md` §15: `list_models`, `validate_model`, `count_tokens` (snake_case).
- `provider-capability-matrix-v1.md` §7: `listModels`, `validateModel`, `countTokens` (camelCase).
- The §1 "snake_case for exported contracts" rule makes interface-contracts authoritative; capability-matrix doc must be updated or contracts will compile but adapters written from the matrix doc will silently miss the interface.
### 1.4 `JsonValue` recursive type compileability
```ts
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }
```
This compiles in modern TS, but only when used directly. Some older `tsc`/IDE setups will hit "type is referenced before declaration" if emitted into a `.d.ts` without `noImplicitAny` discipline. Confirm `tsconfig` has `"strict": true` and verify with `tsc --emitDeclarationOnly`.
### 1.5 `JsonSchema<T = unknown> = JsonObject` is a phantom generic
`T` is never used inside the alias. `ToolDefinition<I, O>.input_schema: JsonSchema<I>` therefore provides zero compile-time linkage between schema and the inferred I/O types of `ToolExecutor<I, O>`. This is technically compileable but defeats the type contract. Either (a) accept the phantom and document it, or (b) introduce a runtime validator type pair (e.g., `JsonSchema<T> = JsonObject & { __t?: T }` or use a real schema lib like Zod with branded types). At minimum, mark `JsonSchema` as nominal-only in §2.
### 1.6 Missing `Diagnostic` interface
- C4 `code-view.md` §6 declares `DiagnosticParser.parse_compiler_output(output): Diagnostic[]` and `semantic_signature(diagnostic): string`.
- `interface-contracts-v1.md` defines no `Diagnostic` type; only `DiagnosticCreatedPayload` (event payload) and a `diagnostics` DB row exist. Workers/toolchain need a typed `Diagnostic` to flow between parser → registrar → event emit. Add `Diagnostic` (mirror of `DiagnosticRecord`) to `contracts/error.ts` or a new `diagnostic.ts`.
### 1.7 IPC envelope cannot enforce direction by type
`IpcMessage = IpcEnvelope<ControlMessage> | IpcEnvelope<WorkerResult> | …` — but `ControlMessage` is parent→worker only and `WorkerResult` is worker→parent only. There is no compile-time link between `kind`/payload-type and `direction`. A handler accepting `IpcMessage` will not narrow on direction. For V1 this risks hard-to-debug protocol bugs; consider tagged union by both `kind` AND `direction`, or document runtime guard requirements.
### 1.8 IPC handshake/lifecycle gap
`ControlMessage` covers `agent.start | cancel | pause | resume | extend_timeout`. There is no:
- worker-side `worker.ready` / `worker.hello` (version negotiation),
- explicit `worker.exiting` / `worker.exited`,
- protocol-version field at envelope level (only `agent.start.version: 1` is versioned; `cancel/pause/resume/extend_timeout` have no version).
Without a hello, mismatched parent/worker binaries will deadlock on first message. Add `IpcEnvelope.protocol_version` or a mandatory hello round-trip before `agent.start`.
---
## 2. Should-Fix During Contracts Implementation
### 2.1 Permission subject enum drift
- `permission.decision.recorded` payload: `subject: "tool" | "command" | "path" | "network" | "dependency" | "migration"`.
- `PermissionRequestContext` (contracts §13): no `subject` field at all; conveys via free-form `requested_action: string`.
- `PermissionPromptProjection.subject: string`: free-form.
Promote `PermissionSubject` to `contracts/permission.ts` and use it on all three.
### 2.2 `PermissionDecision` missing `decision_id`
The event `permission.decision.recorded.decision_id` cannot be produced unless `PermissionEngine.evaluate()` or `record()` returns it. Add `decision_id: UUID` to `PermissionDecision`.
### 2.3 `MessageRecord.role: string` too loose
DB and contracts both use `string`. Anthropic canonical roles are bounded (`user | assistant | system | tool`). Tighten to a union in contracts; keep DB column TEXT.
### 2.4 Missing enums in DB schema doc
- `task_attempts.status` — no enum given.
- `summaries.type` — no enum given.
- `evidence_refs.kind` — no enum (the contract `EvidenceRef.kind: string`).
- `artifacts.type` — listed informally in `artifact-naming-v1.md` §6 but neither db-schema nor contracts encode the canonical set.
- `diagnostics.severity` — no enum.
At minimum, document closed enums in `db-schema-v1.md` so projections/repositories can validate.
### 2.5 Internal types referenced but undefined
Used by C4 but absent from contracts:
- `RetryDecision` (RetryPlanner)
- `WorkspaceRef`, `MergeResult` (WorkspaceManager)
- `PathRiskClassification`, `CommandRiskAnalysis` (security)
- `PromptLayer`, `BudgetFitResult` (context)
- `ArchitectureImpact`, `DocumentUpdate` (architecture)
- `AgentLost` (AgentMonitor.detectLostAgents)
- `FileReadObservation` (runtime-semantics §9.1) — needed for read-before-edit token plumbing
These are runtime-internal but should still live in `packages/contracts` to avoid circular `runtime → runtime` type imports between sub-modules.
### 2.6 `EventBus.publish` synchronous vs `WorkerRuntime.emit` async
`EventBus.publish: void`, but `WorkerRuntime.emit: Promise<void>`. Workers emit through IPC, so async is correct — but document explicitly that `WorkerRuntime.emit` resolves on send-ack, not on parent-side commit, to prevent subtle ordering assumptions.
### 2.7 `TaskInsert = TaskRecord` is too strict
Forces callers to construct `retry_count: 0`, `created_at`, etc., at insert time even though they're scheduler-owned. Recommend `TaskInsert = Omit<TaskRecord, "retry_count" | "started_at" | "completed_at" | "heartbeat_at" | "worker_result_json"> & { retry_count?: number }`.
### 2.8 EventStore reject-unknown-types policy
`event-registry-v1.md` §5: "Reject unknown durable event types unless explicitly allowed by development-mode config." But `EventSchemaRegistry` is shown only in the C4 directory listing, with no contract. Add `EventSchemaRegistry` interface (`register/validate/list/getVersion`) to `contracts/event.ts`.
### 2.9 Route prefix querying performance
`events.route_text` is indexed for equality, but `EventFilter.route_prefix` requires `LIKE 'a/b/%'`. SQLite can use the index for left-anchored LIKE only with `COLLATE NOCASE` or `BINARY` plus the right query form. Add an explicit note + small migration covering this; or store `route_text` as fixed depth segments.
### 2.10 `ToolExecutor.execute()` return-type union
```ts
execute(...): AsyncIterable<ToolEvent> | Promise<ToolResultEnvelope<O>>
```
Forces every caller (and `ToolRegistry.call`) to runtime-discriminate. Simpler: split `ToolExecutor` and `StreamingToolExecutor` interfaces, with `streaming: boolean` on the definition selecting which is required. This also makes registry `register<I,O>` overloads cleaner and prevents accidentally implementing the wrong shape.
### 2.11 `command_runs` has no `status` column
Runtime derives it (`runtime-semantics-v1.md` §5). Acceptable, but `CommandRunProjection.status: "running"|"ok"|"error"|"cancelled"|"unknown"` is computed each snapshot. Add `idx_command_runs_session_completed` to make "running" filtering cheap, or accept the cost — but call this out as known.
### 2.12 `EventBus.drain?()` optional
Tests need deterministic drainage. Drop the `?` (make required) for V1, or formalize a `TestableEventBus` extension. Currently the absence of `drain` would cause flaky tests for "after publish, subscriber sees X".
### 2.13 `ProviderManager.complete` lacks task/agent linkage
`ProviderCompletionInput.metadata?: JsonObject` is the only carrier for task/agent IDs — too loose. Provider rate limiting and cost tracking per-task need first-class fields.
---
## 3. Acceptable Gaps
- **Foreign keys OFF**: documented rationale; orphan handling deferred. Acceptable for Alpha.
- **`JsonObject = Record<string, unknown>`** vs strict types in events: V1 uses TS-side validators, plan to migrate to Zod/JSON-schema generation post-MVP.
- **Phantom `JsonSchema<T>`**: only blocks if you intend type safety; mark as nominal.
- **`schema_meta` migration story** is conceptual only; deferring an actual `MigrationRunner` migration ledger table is fine for V1 if the runner refuses to open DBs at unknown `schema_version`.
- **GUI/network tools** (`gui.screenshot`, `network.capture`) requiring host tooling (xdotool, tcpdump+sudo) — Doctor checks listed; fallbacks to "blocked" are acceptable.
- **Outbox for cross-DB writes** (debug-records.db, learned-memory.db) is described in semantics §6 but no dedicated table; acceptable since each external store can carry its own pending state, but document recovery scan ownership.
- **No `worker_id` separate from `agent_id`** — using `agent_id` as the worker identity is fine.
- **`message_drafts` not source of truth**: documented; OK.
---
## 4. Strengths
1. **Clear single-writer DB architecture** with explicit "no worker → SQLite direct write" rule (§21 boundary list).
2. **Disciplined event vs domain transactionality** (`runtime-semantics-v1.md` §3) — event-sourcing avoids the typical drift between events table and domain projections.
3. **Layered prompt model L0L9** is unusually rigorous; explicitly forbids project override of L0 invariants.
4. **`semantic_signature` from `error-taxonomy-v1.md` §6** — the volatile-data exclusion list is the right discipline for retry-loop detection.
5. **Read-before-edit token (`FileReadObservation`)** as a tool-level enforcement, not a prompt rule (`runtime-semantics-v1.md` §9.1). Best practice for execution-discipline integrity.
6. **Compaction ownership rule** ("only `summary.created` inserts a `summaries` row", §7) eliminates duplicate-row class of bug.
7. **Capability manifest v1** allows plugin foundation without runtime coupling: `CapabilityRegistry.register_tools(tool_registry)` is the only seam.
8. **Provider conversion report** (`ProviderConversionReport.omissions/warnings/required_confirmation`) makes lossy translation auditable rather than silent.
9. **TUI → ProjectionClient only** is properly enforced at the package boundary level (`code-view.md` §2).
10. **Permission decision space** (`allow|deny|ask_user|block|refuse|announce_then_run` × `none|once|session|project|global`) is well-thought-out and matches Claude-Code-style flows.
11. **Artifact naming with ULID + temp-then-rename + sha256** (`artifact-naming-v1.md` §8) — production-grade.
---
## 5. Engineering Quality Score: **7.5 / 10**
Reasoning:
- **+** Coverage breadth is high: events, errors, tools, schemas, prompts, permissions, capabilities, IPC, providers all addressed at architecture-only level.
- **+** Persistence/transaction story is consistent and recovery-aware.
- **+** Boundary rules are enforced architecturally (TUI/runtime/contracts/llm/cpp/tui dependency direction).
- **** Several cross-document type drifts (§1.1, §1.2, §1.3) will cause `tsc` errors on first compile of `packages/contracts`. Must be reconciled before code starts.
- **** Phantom generics (`JsonSchema<T>`) and loose `unknown`/`string` typing on hot paths reduce the usefulness of the strict TypeScript stance.
- **** IPC missing handshake/protocol-version & direction-typing — high risk for first multi-process integration milestone.
- **** ~10 internal types referenced in C4 are not in contracts; contracts package will be rewritten mid-implementation when Scheduler/Workspace/Permission classifiers need them.
- **** Several enum sets (artifact.type, diagnostic.severity, evidence.kind, permission.subject, summary.type, task_attempt.status, message.role) are open `string` in DB/contracts despite being closed in practice.
Once the §1 blocking items are resolved, this jumps to ~**8.5/10**: the architecture is well-disciplined and demonstrably production-aware — the remaining gaps are typical of an alpha contract pass and are tractable during implementation.
Files referenced (all absolute):
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/interface-contracts-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/db-schema-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/event-registry-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/tool-registry-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/error-taxonomy-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/artifact-naming-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/provider-capability-matrix-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/prompt-layering-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/runtime-semantics-v1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/c4/code-view.md`agentId: a26080831ed2e7713 (use SendMessage with to: 'a26080831ed2e7713' to continue this agent)
<usage>total_tokens: 94458
tool_uses: 10
duration_ms: 224290</usage>
---
## 三、用户视角 (User Perspective)
# AirCoding Architecture Alignment Review (User Perspective)
I'm operating in pure read-only review mode; no files edited, no task tools used since this is a one-shot analysis.
## 1. Original requirements FULLY satisfied
- **Self-owned runtime, not a Claude Code plugin wrapper** — explicit in `baselineV1.md` §1, `solution-architecture.md` §1, `requirements.md` §1.
- **Claude Code-quality execution layer** — D-059, FR-009, principle 1 in solution-architecture; read-before-edit, exact small edits, verification-before-completion enshrined.
- **OpenTUI/Solid TUI reuse, not OpenCode business state** — D-002, D-048, baseline §18, solution §4 (TUI container constraints).
- **Hermes-style learning / Curator / SKILL.md** — D-024, baseline §16, runtime-semantics integration; ExperienceMiner is a first-class worker.
- **Project-local portable state** — D-049, FR-002, `.air/shared` + `.air/local` with project-id UUID, gitignore guidance.
- **Independent worker subprocesses** — D-007, D-039, FR-008, baseline §6/§8 (NDJSON over stdio, exit codes, per-worker independent loops).
- **C++ as first deep profile** — FR-017, baseline §20, plan Phase 5; runtime kept language-agnostic via `toolchain-*` (D-036, NFR-003).
- **Multi-agent set (Main, Architect, Scheduler, Executor, Reviewer, Debugger, Compactor, ExperienceMiner)** — present in §5 of solution-architecture and baseline §6. Note user's "Debugger absorbed Fixer" is honored.
- **High-permission announce-then-run, credentials/system-sensitive explicit confirmation** — D-045, baseline §11/§12, security model.
- **Anthropic canonical message storage + provider boundary conversion** — D-009, D-051, baseline §17.
- **Binary tarball distribution; defer public channels** — D-034, baseline §25.
- **Reference projects taxonomy (OpenCode/CC/Hermes/Codex/Skills/asciinema/atuin/claude-hud)** — preserved in baseline §2.
## 2. Original requirements PARTIALLY satisfied
- **VibeBox downstream branch (ARM Linux Electron appliance)** — `vibeboxbaseline.md` exists at top level but is marked historical; the canonical version is at `branchvibebox/vibeboxbaseline.md` (not read here). The main `plan.md` / `todo.md` / `requirements.md` make **no mention of VibeBox** at all. V1.0.0 Alpha plan and release gate ignore the VibeBox branch entirely. Risk: VibeBox derivation is decoupled but has no scheduling visibility in the Alpha workstream.
- **CLI/TUI experience (OpenCode-style UX)** — TUI container, ProjectionStore, HUD presets defined; but actual interaction surfaces (`/direct`/`/done` modes from idea.md §5.2, command palette, history/rewind/resume/compact UX from idea.md §3.2) are **not mentioned** in plan.md or todo.md. T-027/T-028 cover startup and permission prompts only.
- **Error handling and evidence display to user** — Evidence refs and structured WorkerResult exist; error-taxonomy-v1.md is referenced but not directly visible. The user-facing error escalation/blocker reporting flow exists structurally (T-028) but no UX detail.
- **"Goal upgraded to V1.0.0 Alpha (complete C++ + plugin foundation)"** — captured in requirements §2 and plan, but plan Phase 7 (agent prompt integration) and Phase 5 (C++ workflow) carry the entire weight; the Alpha is realistic only if Phases 47 ship cleanly. No contingency for partial delivery.
- **Hermes Nudge Engine N-turn mid-session triggers** — D-024 lists "N turns/tool calls interval" but plan.md/todo.md only deliver T-033 "candidate flow" — mid-session Nudge cadence is not separately scheduled.
- **Memory/skill self-patch ("agent finds rule wrong → patch")** — D-024 design exists, but no todo item explicitly schedules the self-patch path.
- **Doctor `--fix` mode with announce-then-run** — D-045/FR-018 designed; T-034 only delivers read-only Doctor; permissioned fix mode is mentioned in requirements but not scheduled as a distinct todo.
## 3. Original requirements NOT satisfied (or missing in Alpha scope)
- **Direct mode (`/direct` enter, `/done` exit) as a first-class Main Agent lane** — referenced in baseline §6 ("Direct mode is a foreground execution lane") but no contract, no IPC, no todo. User explicitly wanted this.
- **`compact` / `resume` / `history` / `rewind` user-facing commands** (idea.md §3.2) — not surfaced in CLI/TUI todo.
- **`air restore` three-granularity (file / time / session)** — D-032 designs it; plan.md and todo.md never schedule a restore command.
- **Local DebugRecord network with provider interface for sharing** — baseline §13 mentions it, but no T-* item creates `debug-records.db` schema or sharing interface in Alpha. Only T-031 (debugger loop) gets touched.
- **Curator Daemon periodic dedup/archive** — D-024 designs, todo doesn't schedule.
- **`air doctor --bundle` diagnostic export** — D-050 designs; not in todo.
- **Crash detection on next startup with prompt** — D-035 designs; not scheduled.
- **PTY/asciinema-style command capture + Atuin-style structured history search** — referenced in idea.md §3.6, dropped from Alpha entirely. Not necessarily wrong, but unacknowledged scope reduction.
- **VibeBox Alpha integration / branch tracking** — no plan-level treatment; user wanted it as a downstream branch baseline.
## 4. Architecture decisions BEYOND what user asked (over-engineering risks)
- **C4 model + 14 frozen prerequisite baseline docs** (interface-contracts-v1, runtime-semantics-v1, scheduler-state-machine-v1, prompt-layering-v1, provider-capability-matrix-v1, error-taxonomy-v1, artifact-naming-v1, scope-escalation-v1, security-model-v1, capability-trust-v1, cross-platform-matrix-v1, etc.) — user asked for a working agent, not 14 frozen v1 spec docs before any code. This is heavy formalism for an Alpha.
- **`packages/contracts` typed package as Phase 0 hard gate** — sensible engineering, but creates a serialization bottleneck (plan §"Must serialize") that can stall the whole project on contract churn.
- **Provider capability matrix + conversion report mechanism** — user only said "Anthropic + OpenAI + compatibles". Capability matrix is more elaborate than was requested.
- **L0L9 prompt layering** — formalized to ten layers; user did not specify layering depth.
- **Five worker types as independent Bun processes including Compactor and ExperienceMiner** — user explicitly listed Compactor and ExperienceMiner as separate agents, but spawning them as full child processes (vs in-process background tasks) adds IPC/heartbeat/timeout cost for what are largely background async jobs. Justifiable but heavy.
- **Route-chain (`route: string[]`) instead of correlation/causation IDs** (D-038) — clever but a non-standard choice with no requested benefit.
- **`message_drafts` separate table for streaming intermediate state** — a fine touch, but not requested.
- **Static path whitelist plus LLM escape hatch** for high-risk detection — user said "static whitelist for system paths"; LLM escape hatch is an addition.
- **Scope-escalation v1 model as a separate frozen doc** — user already said "implementation silent / architecture confirm"; turning it into a frozen ADR-class document is over-formalized.
## 5. Architecture decisions that CONFLICT with user intent
- **None outright conflicting**, but borderline:
- User wanted "Hermes-style learning" with Nudge Engine mid-session triggers; D-024 includes them but **plan/todo do not schedule the mid-session cadence implementation**. If shipped without it, "Hermes-style" reduces to "session-end miner".
- User wanted Compactor as an independent subagent (idea.md §12.3 "Copy-on-Write … 独立 Compactor 子代理"). Architecture honors this — but `runtime-semantics-v1` (referenced, not read) reportedly governs "compaction ownership", which could centralize control again. Worth verifying.
- User wanted "高权限模式 announce_then_run … 凭据/系统操作显式确认". D-045 honors this for capabilities/dependencies, but it's unclear whether the same model applies to *general* shell command execution (the security-model-v1 doc, not read here, is the source of truth). Visible parts of the security model show only path classification and `.git/` protection — the broader announce-then-run for arbitrary shell isn't visible at this level.
- User wanted Codex-style "tool breadth" as a reference. Architecture explicitly subordinates breadth to Claude Code edit discipline (D-059 last paragraph). This is a legitimate choice the user implied, but worth flagging that breadth (image gen, vision, browser/computer use) is mostly deferred.
## 6. User-experience gaps
- **No CLI command surface design.** plan.md/todo.md show `air doctor`, `air init`, `air -- e2e ...`, `bun run air -- tui-smoke`, but there's no consolidated CLI catalog (no `air resume`, `air compact`, `air restore`, `air history`, `air session list`, `air provider list`, etc.).
- **No spec for `/direct` and `/done` modes** in TUI or Main Agent state machine artifacts referenced from todo.
- **Permission prompt UX** is a single todo (T-028) — no design for what the user sees, what defaults exist, how high-permission mode visualizes "announce_then_run", how confirmations are batched.
- **Evidence display in TUI** — ProjectionStore exposes evidence_refs, but there's no defined "user clicks/expands evidence" UX (artifact preview, log tail, screenshot inline).
- **HUD presets (Full/Essential/Minimal)** — referenced in idea.md §16 but not in todo.
- **Error messaging policy** — `error-taxonomy-v1.md` referenced for routing, but not for user-facing copy.
- **Internationalization / Chinese labels** — idea.md notes "中文 label"; nothing in plan.md.
- **Onboarding / first-run experience** — Doctor read-only is scheduled, but there is no "welcome / models.yaml setup / API key prompt" UX.
## 7. Overall alignment score
**7.5 / 10**
Reasoning:
- **Strengths (why ≥7):** The architecture genuinely captures the user's hardest asks — self-owned runtime, project-local state, independent worker processes, Claude Code execution discipline, Hermes-style miner, Anthropic-canonical storage, C++-first multi-language toolchain plan, OpenTUI without OpenCode business state. The core technical bones are well-aligned and internally consistent.
- **Why not ≥8.5:** The user-facing surface (`/direct`/`/done`, restore/resume/compact/history commands, HUD presets, Chinese labels, permission prompt UX, doctor bundle export, mid-session Nudge cadence, Curator Daemon scheduling, VibeBox branch integration) is largely undeferred-but-undelivered: the documents describe these intentions but plan/todo don't schedule them. The Alpha as currently scheduled would ship a strong runtime with a thin user-experience skin.
- **Why not <7:** The over-engineering (14 frozen v1 baseline docs, full C4, route-chain, capability matrix) is real but does not contradict user intent — it's gold-plating that risks burning time, not direction error. The requirements doc and solution-architecture are tight and traceable.
## Key files referenced
- `/run/media/airlongdian/EasyU/AirCoding/idea.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/analysis/requirements.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/solution-architecture.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/baselineV1.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/decisions-round-1.md` / `decisions-round-2.md` / `decisions-round-3.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/docs/architecture/vibeboxbaseline.md` (and the canonical `branchvibebox/vibeboxbaseline.md` not read here)
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/plan.md`
- `/run/media/airlongdian/EasyU/AirCoding/AirPlan/todo.md`
## Recommended follow-ups (non-blocking)
1. Add todo entries for the user-facing CLI catalog and TUI commands (`/direct`, `/done`, `air resume`, `air restore`, `air compact`, `air history`).
2. Schedule mid-session Nudge cadence and Curator Daemon as concrete T-* tasks.
3. Schedule `air doctor --bundle` and `doctor --fix` paths.
4. Decide explicit Alpha posture toward VibeBox (parallel branch in plan, or explicit "post-Alpha").
5. Consider trimming the 14 frozen v1 docs to what Alpha actually consumes; convert the rest to "design-as-needed".agentId: a86a8f5ed442d26e9 (use SendMessage with to: 'a86a8f5ed442d26e9' to continue this agent)
<usage>total_tokens: 76830
tool_uses: 10
duration_ms: 176409</usage>