# Architecture-diagram guide: from “a colored directory tree” to “a diagram an engineer can interrogate”

> **Audience**: the agent that produces `six_projects_architecture_gallery.md` and later architecture diagrams.
> **Stance**: a product architect. Every rule below is an **executable criterion**, not an aesthetic suggestion.
> **Source material**: the twelve file-by-file analyses under this repository’s `项目分析/` (all marked `file:line` and already re-verified) plus the source trees under `参考项目/`.
> **One-line diagnosis**: the problem with the current six diagrams is **not that they look bad; it is that they chose the wrong genre**—they are “directory trees with color,” not architecture diagrams.

---

## Part 1 · Name the disease correctly

### 1.1 The six diagrams share one structure. That fact itself is a signal

Abstract the six Mermaid diagrams and they are **all the same shape**:

```
subgraph 层1 { A }
subgraph 层2 { B }
subgraph 层3 { C, D }
subgraph 层4 { E }
A --> B --> C --> E
```

Six projects whose stacks, languages, process models, and deliverables are **completely different** produce diagrams that could be swapped for one another—**which means the diagrams carry no project-specific information**.

A reliable self-check: **cover every label, leave only boxes and lines. If the six diagrams still look the same, none of them is drawn correctly.**

> Real architectural difference lives in **topology**: OpenCode is a star—“one server + N clients.” Open Design is a trust split—“three processes + one privileged center.” grok-build is a message topology—“one process + Actor mailboxes.” OpenManus is a type topology—“one inheritance chain + one tool pool.” **Those four topologies must not collapse into the same vertical stack.**

### 1.2 “Layers” is the metaphor most often abused

The current diagrams number Claude Code as `Layer 1 / Layer 2 / …`. That implies a **strict top-down call stack**. Reality:

- The permission system (`permissions/`) is **not Layer 4**—it is called **simultaneously** by the tool layer, the main loop, and the UI. It is a **cross-cutting concern**;
- Context assembly is **not a one-shot that happens before the main loop**. It **re-runs every turn**;
- Tool results must **flow back** into context. That back-edge is why an agent is an agent—and the diagram has only a one-way arrow.

**Rule**: draw A above B only when **layer A may call layer B, and layer B does not know layer A exists**. Otherwise use another organizing principle (process partitions / planar partitions / lifecycle partitions).

### 1.3 The diagrams contain nothing that would start an argument

The value of an architecture diagram is that it **carries a judgment someone can challenge**. Every sentence on the current diagrams is unfalsifiable description: “tool registry,” “agent main loop,” “model adapter layer”—nobody disagrees, and nobody learns anything.

**A good architecture diagram should provoke at least one of these reactions**:
- “Wait—why is this synchronous?”
- “This edge crosses a process. What’s the serialization cost?”
- “This state lives on this side. What happens if the other side dies?”
- “There is no line between these two boxes. Do they really not communicate?”

**If a diagram cannot provoke any of those sentences, it is decoration.**

---

## Part 2 · Three questions you must answer before you draw

**Do not start drawing.** First answer these three questions in prose in a draft. If you cannot write the answers, do not pick up the pen.

### Question 1: What question does this diagram answer? (Question)

One diagram answers **one** question. If you cannot write that question in a single sentence, you have not thought it through.

| ❌ Unqualified question | ✅ Qualified question |
|---|---|
| “Claude Code’s architecture” | “After the user presses Enter, until the first token appears on screen, which components hold control, in what order?” |
| “OpenCode’s system design” | “Why can OpenCode let a TUI, a desktop app, and Zed share the same session state?” |
| “What modules does Open Design have” | “Open Design does not write its own main loop. How does it still keep output quality consistent across 25 third-party CLIs?” |
| “grok-build’s layering” | “In Goal Mode, how does a goal survive hours and many model calls without being lost?” |

### Question 2: Who is the reader, and what decision will they make with this diagram? (Audience & Decision)

| Reader | Decision they must make | What the diagram must give them |
|---|---|---|
| An architect choosing a base for a fork | Which project to build on | Where the extension points are, what is hard-coded, blast radius of a change |
| An engineer about to read source | Which file to open first | **Entry + trunk path + exact filenames**; side paths may be omitted |
| A TL assessing risk | Whether it can go to production | Trust boundaries, failure paths, state persistence points |
| A product engineer looking to steal a design | Which pattern is worth copying | **The causal story of that pattern**, not a panorama |

**The current six diagrams default to serving reader type 4, but their content only half-satisfies type 2.**

### Question 3: What is this diagram’s load-bearing wall? (Load-bearing claim)

Every diagram must have **one** core claim. Every other element exists to support it. If you cannot find the load-bearing wall, you are listing.

Verified load-bearing-wall examples (from this repository’s analyses):

| Project | Load-bearing wall | Evidence |
|---|---|---|
| Open Design | **The daemon is the only privileged process**—it binds loopback and exclusively owns SQLite / credentials / project files / spawn rights; the web UI is a shell | `项目分析/open-design-源码分析.md:159` |
| Open Design | **Adapters are data, not classes**—26 definitions describe only “how to talk to this CLI,” never “what to say” or “how to schedule” | same document `:453` |
| OpenCode | **The server is the product**—even an in-process TUI **still walks the full HTTP/RPC path**, so multi-client is free | `项目分析/opencode-源码分析.md` |
| OpenWorker | **Out-of-band approval**—permission requests do not block the session; they land in an inbox and a human handles them when free | `项目分析/openworker-源码分析.md` |
| grok-build | **A Goal is not a prompt; it is a state machine**—plan / execute / verify / strategist-recovery persist as four states | `项目分析/grok-build-源码分析.md` |
| OpenManus | **The inheritance chain is a partial order of capability**—`BaseAgent`(loop + stuck detection) → `ReActAgent`(think/act) → `ToolCallAgent`(tool parse) → concrete agents | `项目分析/OpenManus-源码分析.md:91` |

---

## Part 3 · Six diagram types for agent systems (the core method)

**“Architecture diagram” is not one kind of diagram. It is six.** Draw them on one canvas and they collapse into a directory tree. This is the most important section of this guide.

### Type A · Process and trust topology (Deployment / Trust Topology)

**Answers**: How many address spaces does the code run in? Who may touch what? How are boundaries crossed?

**Must draw**:
- Every **independent process / address space** distinguished with a heavy border (not a casual subgraph ring)
- Every **cross-process edge** labeled with: **transport** (HTTP loopback / stdio / Unix socket / IPC file) + **synchrony** (blocking / streaming / polling)
- **Privilege asymmetry**: who can read credentials, who can write the filesystem, who can spawn processes
- **Network egress**: the only component that can reach the public internet (this is the data-exfiltration surface)

**Why this diagram should be drawn first**: it sets the physical constraints for every later discussion. None of the current six diagrams **draws a process boundary at all**—OpenWorker’s Rust shell and Python engine are two processes, yet they appear as two boxes side by side, with no hint that a serialization hop sits between them.

**Example (Open Design, based on verified facts)**:

```mermaid
flowchart LR
    subgraph BROWSER["① 浏览器 · 无特权"]
        UI["Next.js 16 App Router + React 18"]
    end
    subgraph SIDECAR["② Next.js server 侧车 · 低特权"]
        SSR["SSR / 静态资源"]
    end
    subgraph DAEMON["③ Daemon 进程 · <b>唯一特权方</b>"]
        API["/api/* · 绑 loopback"]
        DB[("SQLite<br/>projects · conversations · runs")]
        CRED["凭证库"]
        SPAWN["子进程 spawn 权"]
    end
    subgraph CHILD["④ 被 spawn 的第三方 CLI · 独立进程 ×N"]
        CLI["claude / codex / cursor-agent …"]
    end
    UI -->|HTTP| SSR
    UI -->|"HTTP · loopback only"| API
    API --- DB
    API --- CRED
    API --> SPAWN
    SPAWN -->|"stdio · SSE/JSON-RPC"| CLI
    CLI -->|"写文件（不回传内容）"| FS[("项目 cwd 文件系统")]
    API -.读取产物.-> FS
```

**Interrogations this diagram immediately invites** (that is the value):
- “The third-party CLI is an independent process. Are credentials forwarded by the daemon, or does the CLI hold its own?”
- “The CLI writes the filesystem directly, bypassing the daemon. So lint and review are after-the-fact?”—**yes. That is Open Design’s design**, and the diagram exposes it.

### Type B · Sequence of one turn (Turn Sequence)

**Answers**: In one interaction, how do control and data flow along the time axis?

The essence of an agent system is a **loop**, and a loop **cannot be expressed by a flowchart**—a flowchart can only draw a single pass. You must use `sequenceDiagram`.

**Must draw**:
- **Loop boundary** (`loop` block)—visually separate “one turn” from “one session”
- **What re-runs every turn** (context reassembly, tool-set recomputation) vs **what is one-shot** (session init)
- **Back-edge**: how tool results enter the next turn’s input
- **Early-exit points**: which conditions break the loop

**Example (Claude Code main-loop skeleton; paths verified to exist)**:

```mermaid
sequenceDiagram
    autonumber
    participant U as 用户
    participant R as REPL.tsx
    participant H as handlePromptSubmit.ts
    participant Q as query.ts::queryLoop
    participant C as 上下文组装
    participant A as services/api/claude.ts
    participant T as tools/（43 个）
    participant P as utils/permissions/

    U->>R: 回车
    R->>H: 原始输入
    H->>H: 分流：/命令 · !shell · 普通 prompt
    H->>Q: 进入循环

    loop 每一轮（不是每次会话）
        Q->>C: 重新组装上下文
        Note over C: 系统提示 + CLAUDE.md + git 状态<br/>每轮都重跑，不是启动时一次
        C-->>Q: messages[]
        Q->>A: SSE 流式请求
        A-->>Q: token 流 + tool_use 块
        alt 模型要调工具
            Q->>P: 该工具此次调用允许吗
            P-->>Q: 允许 / 拒绝 / 需询问用户
            opt 需询问
                P->>U: 权限弹窗
                U-->>P: 决定
            end
            Q->>T: 执行
            T-->>Q: 结果
            Note over Q: 结果<b>回流</b>进 messages，进入下一轮
        else 只有文本
            Q-->>R: 收敛，退出循环
        end
    end
```

> **This diagram makes three things a flowchart cannot**: ① context is **reassembled every turn**; ② permission checks happen **before tool execution** and may **interrupt out to the user**; ③ the loop’s **exit condition** is “the model returned text only.”

### Type C · Control plane vs data plane (Control / Data Plane Split)

**Answers**: Which components **decide what to do**, and which **move content**?

This is the classic split from telecom and cloud infrastructure. **It holds in agent systems and is extremely useful**, and none of the six current diagrams uses it.

- **Control plane**: main loop, permission adjudication, goal state machine, scheduler, compaction decisions
- **Data plane**: token stream, tool I/O, file reads/writes, context buffers

**How to draw**: **left/right columns**, not top/bottom layers. Control-plane edges as **solid lines**; data-plane edges as **thick / a different color**.

**Why it is worth money**: you see at a glance **where this project put decision rights**.
- Claude Code: the control plane is **entirely in the local process**; the model only proposes
- Open Design: the control plane is **outsourced to third-party CLIs**; it keeps only the **entry prompt** and the **exit quality gate**—its most counterintuitive fact, and the one that most needs to be drawn
- grok-build: `GoalTracker` is a **control-plane state machine independent of the model**; if the model drifts, it is still there

### Type D · State ownership and lifecycle (State Ownership)

**Answers**: Where does state live, who owns it, how long does it live, and what is lost on crash?

**Every state container must be labeled with three attributes**:

| Attribute | Values |
|---|---|
| **Medium** | memory / SQLite / JSONL file / remote service |
| **Lifecycle** | single turn / single session / cross-session persistent / cross-machine |
| **Crash semantics** | lost / reconstructable / already persisted |

**Example fragment**:

```mermaid
flowchart TB
    subgraph EPH["回合级 · 崩溃即丢"]
        S1["step_context 工具可见集快照"]
        S2["本轮 token 缓冲"]
    end
    subgraph SESS["会话级 · 内存"]
        S3["messages[] 对话历史"]
        S4["审批缓存 approval store"]
    end
    subgraph PERSIST["持久 · 落盘"]
        S5[("rollout / JSONL 会话资产")]
        S6[("SQLite: projects · runs")]
        S7["项目 cwd 的真实文件"]
    end
    S3 -.压缩时截断.-> S3
    S3 -->|每轮追加| S5
```

> **A fact you cannot see unless you draw it**: most agents’ “memory” is **three different media glued together**, and the pit engineers fall into most often is getting one segment’s lifecycle wrong.

### Type E · Extension surface and blast radius (Extension Surface)

**Answers**: If I add a new capability, what do I change? Who is affected?

**How to draw**: put the **extension point** at the center; radiate outward “files you must touch to add this thing.”

**You must distinguish three kinds of extension point**:
1. **Data extension** (add a definition / a JSON)—zero code; blast radius = 1 file
2. **Interface extension** (implement a trait / interface)—blast radius = a new file + one registration site
3. **Core rewrite** (change the main loop)—blast radius uncontrollable

**This diagram is the highest-value artifact for a “selection” reader**, and the current six diagrams have none of it.

**Open Design’s example is decisive**: adding the 26th CLI = **append one `RuntimeAgentDef` datum to `registry.ts`**, with no new logic. That is the **verifiable consequence** of “adapters are data,” a hundred times stronger than writing “26 CLI adapters” inside a box.

### Type F · Failure and degradation paths (Failure Modes)

**Answers**: What happens when something goes wrong?

**The shared trait of almost every amateur architecture diagram: it draws only the happy path.**

**You must draw at least three kinds**:
- **Retry edges** (with backoff policy)
- **Degradation edges** (capability drops but the system does not halt, e.g. semantic retrieval fails → fall back to keyword match)
- **Circuit-break / terminate edges** (stuck detection, step cap, cancellation-token propagation)

Distinguish them from the main path with **dashed lines + red**.

---

## Part 4 · Discipline of visual channels

**Iron law: one visual channel encodes one variable.** In the current diagrams, color and stroke are pure decoration—the two strongest channels are wasted.

| Channel | Suggested encoding | Forbidden |
|---|---|---|
| **Stroke weight** | process / address-space boundary | arbitrary emphasis |
| **Fill color** | plane membership (control / data / storage / external) | coloring because it “looks good” |
| **Line style** | solid = sync call; dashed = async / event; dotted = optional / degradation | mixing them |
| **Arrows** | one-way = call; two-way = request–response (**use sparingly; most of the time split into two edges**) | using a two-way arrow to hide unclarity |
| **Edge labels** | transport + synchrony (`HTTP/SSE`, `stdio`, `poll 500ms`) | leaving them blank |
| **Shape** | rectangle = component; cylinder = persistence; diamond = decision; parallelogram = external system | all rectangles |

**You must include a legend.** Custom encoding without a legend = no encoding.

### On two-way arrows

`A <--> B` appears 5 times in the current six diagrams, **almost always covering a place that has not been thought through**.

What does `LOOP <--> PERM` actually mean? The main loop calls permissions and permissions answer (that is **one synchronous call**: draw one-way + annotate the return value)? Or does the permission system **actively interrupt** the main loop (that is **two different edges**, with completely different semantics)?

**Rule: use a two-way arrow only for true bidirectional peer communication (e.g. full-duplex WebSocket). For request–response, draw one-way and write the return in the label.**

---

## Part 5 · Seven load-bearing kinds of information that are specific to agent architecture

This is what lifts a diagram from “generic software architecture” to “**an agent architecture diagram**.” Of the seven kinds below, **every agent architecture diagram must carry at least three**.

### ① Context assembly pipeline (Context Assembly Pipeline)

This is where an agent’s competitive advantage lives, yet of the six diagrams only Open Design mentions “20-layer context assembly” in a single sentence.

**Draw it as**: a left-to-right pipeline. Each segment labeled with:
- **Content source** (system prompt / project brief / tool catalog / history / environment snapshot)
- **Change frequency** (globally static / session-stable / project-stable / turn-volatile)
- **Whether it sits inside the cache prefix**

> **Why frequency matters this much**: change frequency determines **how long the cache prefix can be**, and the cache prefix directly determines **cost and time-to-first-token**. Accidentally placing high-frequency content at the front invalidates the entire prefix. That is one of the most expensive bug classes in agent engineering, and it is fully visible on an architecture diagram.

### ② Stop protocol and loop control (Termination Protocol)

“When to stop” is the hardest part of an agent, and the place where implementations differ most. **None of the six diagrams draws it.**

- Claude Code: the model returns text only → converge
- Codex: a three-party protocol of `follow-up × compaction × stop hook`
- OpenManus: `BaseAgent` **stuck detection** + `max_steps` cap
- grok-build: `GoalTracker` decides the goal is met
- MiMo Code: an independent judge model + four infinite-loop gates

**Draw it as**: a `stateDiagram-v2` with explicit transitions for “continue / continue after compaction / hook demands another run / terminate.”

### ③ Authorization and trust boundary (Authorization Boundary)

**Must answer**: who approves? when? is the approval cached? is there a second wall at the kernel?

Codex is the clearest example: **`AskForApproval` (does a human agree) × `SandboxType` (does the kernel allow it) are two orthogonal walls**—the user may click allow, and the OS sandbox may still refuse. **That orthogonality must be drawn as two dimensions, not two boxes in series.**

### ④ Dynamism of tool assembly (Tool Set Resolution)

The current diagrams all draw tools as a static box (“40+ tools,” “~25 Rust tools”). In a mature implementation, **“which tools the model can see this turn” is computed every turn**, from: model family, current mode, connected MCP servers, skill activation, permission policy.

**Draw it as**: an **evaluation node with inputs**, not a static inventory.

### ⑤ Model boundary (Model Boundary)

**You must mark “beyond this line is the model”**, and label the protocol shape (Anthropic Messages / OpenAI Responses / in-house runtime).

**Why**: the model boundary is the **only unreliable, undebuggable, costly, latent** edge. It must be the most visually salient edge on the diagram. The current six diagrams draw it as an ordinary box like everything else.

### ⑥ Sub-agent / concurrency topology

Projects with sub-agents (Claude Code’s `AgentTool`, grok-build’s `WorkflowManager`, OpenManus’s `PlanningFlow`) must draw:
- **Who may spawn whom** (a directed graph; note whether recursion is allowed)
- **Where the depth cap sits**
- Whether a sub-agent’s **context is inherited or isolated**
- **How results flow back**

### ⑦ Artifact egress (Artifact Egress)

The point where the agent finally changes the world: write a file / send a message / change a calendar / open a PR.

**Annotate**: whether it is reversible, whether it goes through approval, whether there is a dry-run.

---

## Part 6 · Concrete prescriptions for the six projects

For each of the existing six diagrams, a **replacement** (not a supplement—the current diagram should be replaced).

| Project | What is drawn now | **What should be drawn** | Primary types |
|---|---|---|---|
| **Claude Code** | 5-layer vertical stack | **Full sequence of one turn**: split → reassemble context every turn → SSE → permission adjudication → tool → result back-flow → converge | B + ② |
| **Open Design** | 4 function boxes | **Three-process trust topology**: the daemon is the only privileged party; third-party CLIs are independent processes and **write the filesystem directly**; the quality gate intervenes **after the fact** | A + E |
| **OpenCode** | client / server / model three segments | **Star topology + the counterintuitive edge “even the local TUI walks full HTTP”**—that edge is why multi-client is free | A + C |
| **OpenWorker** | three boxes side by side | **Cross-language process boundary (Rust shell ↔ Python engine) + unified event stream + out-of-band approval inbox**: approval **does not block** the main loop | A + D |
| **grok-build** | 4-layer crate inventory | **Goal Mode state machine**: plan / execute / verify / strategist-recovery four states + multi-hour persistence + decoupling from model output | ② + D |
| **OpenManus** | inheritance chain + toolbox | **Inheritance chain as a partial order of capability** (what each layer adds) + **dual termination of stuck detection and max_steps** | ② + E |

### On misuse of “Kimi K3 style”

Using diagrams in the Sebastian Raschka vein is a good idea, but you have to understand **why they work**:

Their information density comes from a **two-level structure of “main structure + local zoom”**—the main diagram gives the global skeleton; callout boxes give **internal detail of a critical local** (tensor shapes, dimension transforms, concrete operators).

**The current implementation copied the layout, not the information structure**: the right-hand callouts hold “module blurbs,” which are **the same abstraction level as the main diagram**, not a **drill-down**.

**Correct use**: the main diagram draws process topology; the callout holds **the internal implementation of that one load-bearing mechanism**—e.g. Open Design’s main diagram draws three processes, the callout holds the **real field list of `RuntimeAgentDef`**, so the reader sees “an adapter is this 20-field data structure, with not one line of behavior code.”

---

## Part 7 · Mermaid engineering tactics

1. **Prefer `flowchart LR` over `TB`.** Vertical layout naturally induces a “layers” misreading; horizontal layout induces a “flow” reading. Use TB only when you are truly expressing hierarchy.
2. **Use `stateDiagram-v2` and `sequenceDiagram`.** Do **not** force loops, state machines, and sequences into a flowchart. The current six diagrams are 100% flowcharts; that is itself a genre error.
3. **Color with `classDef`**, not inline style:
   ```
   classDef ctrl fill:#eef4ff,stroke:#4a6fa5
   classDef data fill:#f4fff0,stroke:#4a8f3c
   classDef ext  fill:#fff4ec,stroke:#c96442,stroke-dasharray:4 3
   class LOOP,PERM ctrl
   class API,SDK ext
   ```
4. **Node text ≤ 3 lines.** More than that means split the node or drill into a subgraph.
5. **Put the file path on the node’s second line**, separated with `<br/>`, and it **must be a real path you can open**.
6. **Every diagram gets a `figcaption`**, one sentence stating the load-bearing wall. Diagram and caption are **one artifact**; do not deliver a diagram alone.
7. **Subgraph nesting ≤ 2 levels.** A third level means split into two diagrams.
8. **Nodes per diagram ≤ 15.** More than that means you stuffed two questions into one diagram.

---

## Part 8 · Anti-pattern checklist (item-by-item against the current artifacts)

| # | Anti-pattern | Example in current artifacts | Fix |
|---|---|---|---|
| 1 | **Directory tree dressed as architecture** | all six diagrams | answer Part 2’s three questions first |
| 2 | **Fake layering** | Claude Code “Layers 1–5” | permissions are cross-cutting, not a layer |
| 3 | **Two-way arrows hiding semantics** | `LOOP <--> PERM`, `WEB <--> DAEMON` | split into labeled one-way edges |
| 4 | **Happy path only** | all six diagrams | add retry / degradation / circuit-break edges |
| 5 | **No process boundary** | all six diagrams | add Type A |
| 6 | **No time dimension** | all six diagrams | loops must use sequenceDiagram |
| 7 | **Static tool inventory** | “40+ tools,” “~25 Rust tools” | turn into a per-turn evaluation node |
| 8 | **Model boundary not salient** | all six diagrams | the model is the only unreliable edge; it must be visually heaviest |
| 9 | **Counts as insight** | “26 adapters,” “25+ connectors” | numbers serve the claim: 26 entries **because they are data, so you can have 26** |
| 10 | **Color without semantics** | all of them | `classDef` + legend |
| 11 | **Callout at the same level as the main diagram** | Kimi-style diagrams | a callout must drill down one level |
| 12 | **Comparison table mixing dimensions** | “architectural highlights” mixing language / pattern / feature | one column, one dimension |

---

## Part 9 · Fact-check protocol (prompted by errors found this round)

This review found **4 hard errors + several precision problems** in the six diagrams, all of a type that **could have been avoided**. The following process is mandatory.

### 9.1 Errors found this round

| # | Location | Error | Fact | Evidence |
|---|---|---|---|---|
| 1 | Title §4 | **“OpenWorker (OpenClaw)”** treats OpenClaw as an alias | OpenClaw is an **acknowledged external project**, not an alias. Original: `Design (from OpenClaw): secrets **never enter the model's context, prompts, or traces**` | `参考项目/openworker/coworker/secrets.py:3` |
| 2 | §2 | Open Design daemon written as **“Fastify + SQLite”** | It is **Express + better-sqlite3**. The repo’s own `apps/daemon/AGENTS.md:96` says: *"Do not move daemon-only Node, SQLite, **Express**, filesystem, or process types into contracts."* | `项目分析/open-design-源码分析.md:126,1787` |
| 3 | §3 | **`acp/` drawn as a top-level client package peer to `packages/tui`** | ACP lives in **`packages/opencode/src/acp/`**, i.e. **inside the server package**. The diagram took “a subdirectory of the server” and drew it as “a peer client of the server,” **inverting the real boundary** | `参考项目/opencode/packages/opencode/src/acp` |
| 4 | §4 | `scheduler.py` path | Actually `coworker/automation/scheduler.py` | `参考项目/openworker/` |

**Precision problems** (not false, but below a “professional” bar):

- **Claude Code’s main loop is labeled only `src/query.ts : queryLoop()`**, omitting `src/QueryEngine.ts` (**1 295 lines**) and the `src/query/` subdirectory (`config.ts` / `deps.ts` / `stopHooks.ts` / `tokenBudget.ts`). **The heart is distributed.** Pointing at one file misleads someone reading the source.
- **“40+ tools”**: `claude-code/src/tools/` actually has **43** entries. If you can count, write the exact number.
- **OpenManus agent inventory** omitted `DataAnalysis` (`data_analysis.py`) and `SandboxManus` (`sandbox_agent.py`).
- **“26 CLI runtime adapter layer” and “25 CLIs” coexist on the same diagram with no explanation**. Correct statement: **26 runtime definitions correspond to 25 distinct executables**—`byok-opencode` reuses OpenCode’s binary, so there is one more definition than binary. **That extra definition is itself a design detail worth drawing.**

### 9.2 Mandatory process

**Rule 1 · Every proper noun must have a source.**
Every name you put on a diagram (project alias, framework name, file path, class name) must be attachable to a `file:line` or to command output. If you cannot, do not write it.

**Rule 2 · The naming triple must be resolved.**
Repo name / package name / command name often differ. OpenWorker is all three different (repo `openworker` / Python package `coworker` / CLI `openworker`). **Which one you write on the diagram depends on who the diagram is for**—a source reader wants the package name; a selection reader wants the product name.

**Rule 3 · Every path must have been `ls`’d in the checkout.**
```bash
for f in src/query.ts src/tools/ ...; do
  [ -e "$f" ] && echo "✅ $f" || echo "❌ $f"
done
```

**Rule 4 · Every number must be computed now.**
`ls | wc -l`, `wc -l`, `grep -c`. Ban “about,” “40+,” and other estimates from memory—unless that is how upstream documents it, and you cite the source.

**Rule 5 · Hierarchy must be verified.**
Before drawing X as a child of Y, confirm that X’s real path is under Y. Error #3 is exactly skipping this step.

**Rule 6 · Cross-check against existing analyses.**
The twelve documents under `项目分析/` have already been line-verified. **On conflict, the analysis document wins, or go back to source for a three-way confrontation**—do not silently trust your impression.

---

## Part 10 · Pre-delivery self-check (tick every box; do not ship if any is unchecked)

### Content
- [ ] This diagram can state **in one sentence** what question it answers
- [ ] There is a clear **load-bearing-wall claim**, and every other element supports it
- [ ] It carries at least **three** of Part 5’s seven kinds of information
- [ ] With all text covered, this diagram’s **shape differs** from the other projects’ diagrams
- [ ] There is at least one place an engineer would **follow up**
- [ ] There is a **failure path**, not only a happy path

### Structure
- [ ] Genre is right (loop → sequence / state → state / topology → flowchart LR)
- [ ] Process / address-space boundaries are drawn explicitly
- [ ] Cross-process edges are labeled with **transport + synchrony**
- [ ] The model boundary is visually most salient
- [ ] No naked two-way arrows (or they are defined in the legend)
- [ ] Nodes ≤ 15, subgraph nesting ≤ 2 levels

### Expression
- [ ] There is a **legend**; color / line style have semantics
- [ ] Every node’s second line is a **real, openable path**
- [ ] There is a **figcaption** stating the load-bearing wall
- [ ] Callouts (if any) **drill down one level**, they do not restate the same level

### Facts
- [ ] Every proper noun has a `file:line` source
- [ ] Every path was `ls`-verified to exist
- [ ] Every number was computed now
- [ ] Every hierarchy was verified
- [ ] Cross-checked against `项目分析/`; conflicts resolved

---

## Appendix · A complete “good diagram” specimen

**Question**: Open Design does not write its own main loop. How does it still keep output quality consistent across 25 third-party CLIs?
**Load-bearing wall**: **It cedes control to third parties and keeps only the entry prompt and the exit quality gate—an architecture of “close both ends, let go of the middle.”**

```mermaid
flowchart LR
    IN["<b>① 入口收口</b><br/>prompts/system.ts · 2 075 行<br/>20 层上下文 · 按变化频率分带"]
    ASSETS["skills 164 · design-systems 153<br/>design-templates 115 · craft 11"]
    DEF["<b>RuntimeAgentDef ×26</b><br/><i>只描述「怎么说话」<br/>不描述「说什么」「怎么调度」</i>"]
    CLI["② 第三方 CLI · 独立进程 ×25<br/>claude / codex / cursor-agent<br/>opencode / devin / qwen …"]
    FS[("项目 cwd 文件系统<br/>HTML · PDF · PPTX · MP4")]
    OUT["<b>③ 出口收口</b><br/>lint-artifact 程序化反 AI 味<br/>Design Jury 五陪审评审"]

    ASSETS --> IN
    IN -->|"拼进 spawn 参数"| DEF
    DEF -->|"spawn · stdio"| CLI
    CLI -->|"<b>直接写盘</b><br/>产物不回传 daemon"| FS
    FS -->|"事后读取"| OUT
    OUT -.->|"不合格则重跑"| IN

    classDef own   fill:#eef4ff,stroke:#4a6fa5,stroke-width:2.5px
    classDef third fill:#fff4ec,stroke:#c96442,stroke-width:2px,stroke-dasharray:5 3
    classDef store fill:#f4fff0,stroke:#4a8f3c
    class IN,ASSETS,OUT own
    class DEF,CLI third
    class FS store
```

**Legend**: <span style="color:#4a6fa5">■</span> solid blue box = Open Design’s own code · <span style="color:#c96442">■</span> dashed orange box = third-party process, behavior uncontrollable · <span style="color:#4a8f3c">■</span> green box = persistence · dotted = feedback / degradation edge.

> ⚠️ **A layout lesson you must remember**: an earlier draft grouped “entry” and “exit” in one `subgraph OWN` to express “close both ends.”
> **Mermaid’s LR layout then shoved that group to the right as a whole, destroying left-to-right flow semantics**—the reader saw the third party first, then the entry. Logic inverted.
>
> **Rule: when “grouping” and “flow” conflict, let position express flow and color express ownership.**
> The diagram above dropped the `subgraph` and used `classDef` coloring instead: blue nodes appear at **both ends**, orange in the **middle**. “Close both ends, let go of the middle” emerges from **the spatial distribution of color**, and left→right flow is not destroyed.
> That is more accurate than forcing a box, and it looks better.

**figcaption**: *Close both ends, let go of the middle. Open Design does not control third-party CLI loops, so quality assurance can only sit on the **entry prompt** and **exit programmatic checks**—note that artifacts are **written to disk directly by the CLI** and not returned to the daemon, so lint and review are architecturally **after the fact**. That constraint is not implementation laziness; it is the **necessary cost** of ceding control.*

**Why this diagram passes**:
1. It answers a concrete question, not “exhibit the architecture”
2. It has a load-bearing wall, and the diagram’s **topology itself** (narrow at both ends, wide in the middle, dashed enclosure) expresses it
3. It exposes a fact that can be interrogated (artifacts are not returned → the gate can only be after the fact)
4. It has a degradation edge (fail → re-run)
5. Color and line style have semantics and a legend
6. Numbers serve the claim (26 definitions vs 25 binaries is labeled explicitly)
7. With text covered, its **shape is completely different** from the other five projects’ diagrams

---

*This guide is written from the twelve file-by-file analyses under this repository’s `项目分析/` and the source trees under `参考项目/`. Every error listed in Part 9 was re-checked with `grep -n` / `ls` / the source text itself.*
