space-architect 1.2.0 → 2.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +103 -0
- data/README.md +248 -146
- data/exe/architect +1 -1
- data/exe/space +2 -2
- data/exe/src +13 -0
- data/lib/space_architect/architect_mission.rb +84 -53
- data/lib/space_architect/cli/architect.rb +107 -121
- data/lib/space_architect/cli/research.rb +94 -0
- data/lib/space_architect/cli/space.rb +25 -31
- data/lib/space_architect/cli/src.rb +20 -14
- data/lib/space_architect/cli.rb +22 -22
- data/lib/space_architect/dispatcher.rb +5 -1
- data/lib/space_architect/harness.rb +123 -16
- data/lib/space_architect/research/mux.rb +127 -0
- data/lib/space_architect/research/registry.rb +70 -0
- data/lib/space_architect/research/renderer.rb +101 -0
- data/lib/space_architect/research/run.rb +7 -0
- data/lib/space_architect/research/supervisor.rb +108 -0
- data/lib/space_architect/research.rb +13 -0
- data/lib/space_architect/run_creator.rb +53 -0
- data/lib/space_architect/skill_installer.rb +109 -0
- data/lib/space_architect.rb +5 -19
- data/lib/{space_architect → space_core}/atomic_write.rb +1 -1
- data/lib/space_core/cli/base_command.rb +19 -0
- data/lib/space_core/cli/config.rb +49 -0
- data/lib/space_core/cli/current.rb +16 -0
- data/lib/space_core/cli/help.rb +110 -0
- data/lib/space_core/cli/helpers.rb +115 -0
- data/lib/space_core/cli/init.rb +29 -0
- data/lib/space_core/cli/list.rb +24 -0
- data/lib/space_core/cli/new.rb +38 -0
- data/lib/space_core/cli/path.rb +16 -0
- data/lib/space_core/cli/repeatable_options.rb +75 -0
- data/lib/space_core/cli/repo.rb +76 -0
- data/lib/space_core/cli/shell.rb +125 -0
- data/lib/space_core/cli/show.rb +21 -0
- data/lib/space_core/cli/status.rb +33 -0
- data/lib/space_core/cli/use.rb +17 -0
- data/lib/space_core/cli.rb +171 -0
- data/lib/{space_architect → space_core}/config.rb +1 -1
- data/lib/{space_architect → space_core}/errors.rb +1 -1
- data/lib/{space_architect → space_core}/git_client.rb +1 -1
- data/lib/{space_architect → space_core}/mise_client.rb +1 -1
- data/lib/{space_architect → space_core}/repo_reference.rb +1 -1
- data/lib/{space_architect → space_core}/repo_resolver.rb +1 -1
- data/lib/{space_architect → space_core}/shell_integration.rb +1 -1
- data/lib/{space_architect → space_core}/slugger.rb +1 -1
- data/lib/{space_architect → space_core}/space.rb +1 -1
- data/lib/{space_architect → space_core}/space_store.rb +12 -12
- data/lib/{space_architect → space_core}/state.rb +1 -1
- data/lib/{space_architect → space_core}/terminal.rb +16 -1
- data/lib/space_core/version.rb +7 -0
- data/lib/{space_architect → space_core}/warnings.rb +1 -1
- data/lib/{space_architect → space_core}/xdg.rb +1 -1
- data/lib/space_core.rb +24 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/clone.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/config.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/daemon.rb +46 -30
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/options.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/org.rb +9 -9
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/repo.rb +9 -9
- data/lib/space_src/cli/shell.rb +122 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/status.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/sync.rb +17 -17
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli.rb +40 -18
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cloner.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/contract.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/duration.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/model.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/store.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/client.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/github.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/agent.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/plist.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/log_rotator.rb +1 -1
- data/lib/space_src/migration.rb +43 -0
- data/lib/space_src/nav.rb +98 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/paths.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/client.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/git.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/status.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/shell.rb +1 -1
- data/lib/space_src/shell_integration.rb +321 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/lock.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/store.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/engine.rb +12 -12
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/repo_plan.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/interactive_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/json_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/mode.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/plain_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/version.rb +2 -2
- data/lib/space_src.rb +37 -0
- data/skill/architect/SKILL.md +329 -0
- data/skill/architect/dispatch.md +308 -0
- data/skill/architect/research.md +98 -0
- data/skill/architect-research/SKILL.md +165 -0
- data/skill/architect-research/lanes.md +191 -0
- data/skill/architect-vocabulary/SKILL.md +141 -0
- metadata +122 -67
- data/lib/space_architect/cli/config.rb +0 -61
- data/lib/space_architect/cli/current.rb +0 -22
- data/lib/space_architect/cli/helpers.rb +0 -117
- data/lib/space_architect/cli/init.rb +0 -35
- data/lib/space_architect/cli/list.rb +0 -30
- data/lib/space_architect/cli/new.rb +0 -43
- data/lib/space_architect/cli/options.rb +0 -12
- data/lib/space_architect/cli/path.rb +0 -22
- data/lib/space_architect/cli/repo.rb +0 -88
- data/lib/space_architect/cli/shell.rb +0 -137
- data/lib/space_architect/cli/show.rb +0 -27
- data/lib/space_architect/cli/status.rb +0 -39
- data/lib/space_architect/cli/use.rb +0 -23
- data/lib/space_architect/version.rb +0 -5
- data/vendor/repo-tender/lib/space_architect/pristine.rb +0 -37
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architect
|
|
3
|
+
description: >
|
|
4
|
+
Run the Architect Loop: Opus 4.8 in Claude Code is the ARCHITECT — judgment
|
|
5
|
+
only: arbitration, judging raw evidence against frozen Acceptance Criteria,
|
|
6
|
+
splitting iterations into disjoint lanes, kill/continue calls. The BUILDERS
|
|
7
|
+
are 1-4 parallel Sonnet 4.6 agents run headless via `claude -p`, each in its
|
|
8
|
+
own git worktree; the architect reviews, merges, and integrates their work.
|
|
9
|
+
The space is the memory: one file per iteration at
|
|
10
|
+
architecture/I<NN>-<name>.md (Grounds / Specification / Acceptance Criteria /
|
|
11
|
+
Builder Prompt / Builder Report / Verdict), indexed by
|
|
12
|
+
architecture/ARCHITECT.md; a mission spans the repos under repos/. Use when
|
|
13
|
+
asked to "architect", "run the loop", "next iteration", "judge the builder's
|
|
14
|
+
work", or at the start of a work block in a space using the handoff system.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Architect
|
|
18
|
+
|
|
19
|
+
You are the ARCHITECT (Opus 4.8 in Claude Code). Sonnet 4.6 via headless
|
|
20
|
+
`claude -p` is the BUILDER — the same harness, one tier down. The space is the
|
|
21
|
+
memory — mission artifacts live in the space's `architecture/` dir (committed),
|
|
22
|
+
scratch in `build/` (gitignored); the mission spans the repos under `repos/`.
|
|
23
|
+
Your output is judgment and a dispatch — never implementation code. When you
|
|
24
|
+
have enough information to act, act.
|
|
25
|
+
|
|
26
|
+
Each iteration is **one self-contained file**,
|
|
27
|
+
`architecture/I<NN>-<name>.md` (`<NN>` = zero-padded ordinality), grown section
|
|
28
|
+
by section. The `architect` CLI writes and commits each section for you with the
|
|
29
|
+
canonical message — the commits give the differentiation and git gives the
|
|
30
|
+
change guarantees, so there are no separate `gates/`, `lanes/`, or `prd/` dirs:
|
|
31
|
+
|
|
32
|
+
| Section | Holds | How you persist it |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| **Grounds** | why — research/brief distilled (optional) | `architect section <it> grounds --from <f>` |
|
|
35
|
+
| **Specification** | what/how — the full delegation contract | `architect section <it> specification --from <f>` |
|
|
36
|
+
| **Acceptance Criteria** | proof — exact gate commands + thresholds | `architect freeze <it>` ❄️ **= the freeze** |
|
|
37
|
+
| **Builder Prompt** | the exact lane-prompt(s) dispatched | `architect section <it> prompt --append --lane <l> --from <f>` |
|
|
38
|
+
| **Builder Report** | raw evidence, transcribed verbatim from scratch | `architect evidence <it> --lane <l>` |
|
|
39
|
+
| **Verdict** | rulings + per-AC PASS/FAIL/INVALID + KILL/CONTINUE | `architect section <it> verdict --from <f>` (later session) |
|
|
40
|
+
|
|
41
|
+
Each command writes the section, commits it with the canonical `I<NN>: …`
|
|
42
|
+
message, and prints back what changed (SHA + diff stat; `freeze` prints the
|
|
43
|
+
frozen AC; `evidence` echoes the builder's STATUS line) — so you don't hand-edit
|
|
44
|
+
the file or run a separate `git add`/`commit`, and you don't run three follow-ups
|
|
45
|
+
to see what happened. You still author the *content*; the CLI owns the
|
|
46
|
+
*persistence*.
|
|
47
|
+
|
|
48
|
+
The builder **never** writes this file — the Acceptance Criteria must stay out
|
|
49
|
+
of its editable blast radius. Each lane builder writes raw evidence to a scratch
|
|
50
|
+
report in `build/<id>-<lane>/report.md`; `architect evidence` transcribes it
|
|
51
|
+
**verbatim** into Builder Report. Frozen sections
|
|
52
|
+
(Grounds/Specification/Acceptance Criteria) are read-only after the freeze
|
|
53
|
+
commit — `architect section` refuses to write a frozen section once frozen; only
|
|
54
|
+
Builder Prompt, Builder Report, and Verdict are appended after.
|
|
55
|
+
|
|
56
|
+
**The mission brief (`architecture/BRIEF.md`).** A mission with a durable spec
|
|
57
|
+
carries one brief — numbered §sections (§1 goal, §2 constraints, … §N definition
|
|
58
|
+
of done) that span iterations. Every iteration's Grounds/Specification/Acceptance
|
|
59
|
+
Criteria/Verdict cites it as **BRIEF §N** (e.g. `(BRIEF §3.1)`), the way each gate
|
|
60
|
+
addresses its intent back to one frozen reference: the Acceptance Criteria table
|
|
61
|
+
carries a `Brief §` column, the Specification Objective cites it, the Verdict
|
|
62
|
+
reads "diff vs BRIEF §1/§3.3 — CONTINUE". Scaffold it with `architect brief new`.
|
|
63
|
+
The brief is frozen at the mission level — edits to a §section are logged
|
|
64
|
+
decisions in `ARCHITECT.md`, never silent per-iteration drift. Discovery missions
|
|
65
|
+
that are still finding their shape defer the brief, cite per-iteration Grounds,
|
|
66
|
+
and promote the consolidated picture into BRIEF.md once it stabilizes.
|
|
67
|
+
|
|
68
|
+
Full rationale and citations: `DESIGN.md` in this skill's repo. Exact dispatch
|
|
69
|
+
commands and the lane-prompt template: `dispatch.md` next to this file. To load
|
|
70
|
+
this system's vocabulary without running the loop (e.g. when working *on* the
|
|
71
|
+
skill), invoke the `/architect-vocabulary` skill — it is the glossary, not the
|
|
72
|
+
loop.
|
|
73
|
+
|
|
74
|
+
## Hard rules
|
|
75
|
+
|
|
76
|
+
1. **Never write implementation code.** Anything that must change goes in the
|
|
77
|
+
iteration Specification.
|
|
78
|
+
2. **Not in the space's committed architecture = didn't happen.** Refuse to
|
|
79
|
+
judge results that exist only in conversation or builder chat output.
|
|
80
|
+
3. **The Acceptance Criteria freeze before results exist** — written as the
|
|
81
|
+
iteration file's Acceptance Criteria section and committed (the freeze commit)
|
|
82
|
+
*before* dispatch. Quote them verbatim when judging, reading from the freeze
|
|
83
|
+
commit (`git show <freeze-sha>:architecture/I<NN>-<name>.md`); never restate
|
|
84
|
+
from memory; never edit after results. Any change to
|
|
85
|
+
Grounds/Specification/Acceptance Criteria lines since the freeze (caught by
|
|
86
|
+
`git diff <freeze-sha> HEAD`) is an automatic iteration FAIL — only Builder
|
|
87
|
+
Prompt/Report/Verdict may be appended afterward.
|
|
88
|
+
4. **Nobody grades their own work.** The builder reports raw evidence only (to
|
|
89
|
+
scratch); you transcribe it, run the gates yourself, and read the output —
|
|
90
|
+
builder claims are hearsay. You never judge a run in the same session that
|
|
91
|
+
dispatched it.
|
|
92
|
+
5. **Disagreement is mandatory.** Builder PHASE 0 must raise disagreements
|
|
93
|
+
citing real files; silent compliance = defect. You rule on every one in the
|
|
94
|
+
Verdict: ACCEPT / REJECT / MODIFY + one line why. Flag the human's scope
|
|
95
|
+
creep and goalpost-moving bluntly too.
|
|
96
|
+
6. **Audit every status claim** — yours and the builder's — against a tool
|
|
97
|
+
result from the session before reporting it.
|
|
98
|
+
7. **Fresh builder context per lane, worktree isolation between lanes.**
|
|
99
|
+
`claude -p --continue` (from the lane's worktree) only for follow-ups within
|
|
100
|
+
the current lane. Builders never commit — Claude Code has no sandbox to
|
|
101
|
+
enforce that, so verify it yourself post-flight (`git -C <worktree> log
|
|
102
|
+
<repo-base>..` must be empty). If a run leaves a worktree broken or
|
|
103
|
+
committed, discard that lane + re-dispatch over rescue prompting — lanes are
|
|
104
|
+
cheap by construction.
|
|
105
|
+
8. **Stop conditions:** failing verification you can't root-cause, instructions
|
|
106
|
+
conflicting with project docs, irreversible/destructive calls, or scope
|
|
107
|
+
growth beyond the iteration → checkpoint to the handoff and ask the human.
|
|
108
|
+
|
|
109
|
+
## Procedure
|
|
110
|
+
|
|
111
|
+
### 0. Ground (every session — never skip because the task "looks small")
|
|
112
|
+
|
|
113
|
+
- Read the project's operating docs in authority order: `CLAUDE.md` /
|
|
114
|
+
`AGENTS.md` → `README.md` → architecture docs. Learn the exact verification
|
|
115
|
+
gate (test/lint/typecheck/build commands) from docs or CI config.
|
|
116
|
+
- Once per environment: `claude --version` and confirm the builder model
|
|
117
|
+
resolves (`echo ok | claude -p --model claude-sonnet-4-6 --max-turns 1`;
|
|
118
|
+
details in `dispatch.md`). First dispatch in a new environment is a canary —
|
|
119
|
+
confirm it starts cleanly before fanning out.
|
|
120
|
+
- Read `architecture/ARCHITECT.md` (the cross-iteration table of contents),
|
|
121
|
+
`architecture/BRIEF.md` if present (the durable §-numbered mission contract you
|
|
122
|
+
cite as BRIEF §N), and the iteration file `architecture/I<NN>-<name>.md` for any
|
|
123
|
+
in-flight iteration. If `ARCHITECT.md` is missing, run `architect init` (scaffolds
|
|
124
|
+
`architecture/ARCHITECT.md` and the `architect:` block in `space.yaml`,
|
|
125
|
+
commits). Keep the handoff a short TOC (~150 lines): TL;DR + repos in scope +
|
|
126
|
+
an iteration index pointing at each iteration file; per-iteration detail lives
|
|
127
|
+
in the iteration file, never duplicated into the handoff. `architect status`
|
|
128
|
+
prints mission state (iterations, freeze_shas, lanes, verdicts) at any point.
|
|
129
|
+
- **Space setup (first time):** `architect space new "Mission Name" -r org/repo -r …`
|
|
130
|
+
(each repo is a repeatable `-r` flag after the title), then `architect init` inside
|
|
131
|
+
the space to scaffold `architecture/ARCHITECT.md`.
|
|
132
|
+
- Scale to the task: trivial fixes don't need the loop — say so and let the
|
|
133
|
+
human do it inline or in a normal session. The loop is for iteration-sized
|
|
134
|
+
work.
|
|
135
|
+
|
|
136
|
+
### 1. Arbitrate
|
|
137
|
+
|
|
138
|
+
Every open disagreement from the last iteration's Builder Report gets
|
|
139
|
+
**ACCEPT / REJECT / MODIFY + one line why**, written into that iteration's
|
|
140
|
+
Verdict. No deferrals.
|
|
141
|
+
|
|
142
|
+
### 2. Judge
|
|
143
|
+
|
|
144
|
+
Read the frozen Acceptance Criteria from the freeze commit (`architect freeze`
|
|
145
|
+
re-prints them, or `git show <freeze-sha>:architecture/I<NN>-<name>.md`). For each
|
|
146
|
+
gate: run the gate command yourself — `architect gate <iteration>` runs the
|
|
147
|
+
frozen gate commands in the resolved repo/worktree and streams raw output (it is a
|
|
148
|
+
runner, never a judge), or run them by hand — then compare the output against the
|
|
149
|
+
verbatim frozen text → **PASS / FAIL / INVALID** (INVALID = not measured the way
|
|
150
|
+
the gate specifies). Check `git diff <freeze-sha> HEAD --
|
|
151
|
+
architecture/I<NN>-<name>.md` — any change to Grounds/Specification/Acceptance
|
|
152
|
+
Criteria lines is an automatic FAIL.
|
|
153
|
+
Gate-pass is necessary, not sufficient: read the diff against the
|
|
154
|
+
Specification's intent **and the cited BRIEF §sections** before the verdict —
|
|
155
|
+
test-passing changes are frequently
|
|
156
|
+
unmergeable, and iterating against visible tests is a known gaming vector. Read
|
|
157
|
+
for **idiomaticity and style**, not just correctness: does the code match the
|
|
158
|
+
target repo's house conventions (naming, guards, predicates, error/persistence
|
|
159
|
+
idioms, the language's expressive forms), stay well-factored and DRY-ish, avoid
|
|
160
|
+
needless repetition or abstraction it doesn't need, and read like the
|
|
161
|
+
surrounding code? A gate-green diff that fights the house style — or introduces
|
|
162
|
+
an inconsistency a careful reader of that repo would never write — is a defect:
|
|
163
|
+
flag it in the Verdict with file:line, and weight it in a head-to-head. (Models
|
|
164
|
+
are strong on *local* idiom and restraint but weak on *structural*
|
|
165
|
+
re-derivation — the simplification that re-sees the shape is often the
|
|
166
|
+
architect's or human's to name.) Then
|
|
167
|
+
one iteration-level call: **KILL / CONTINUE**, with the single decisive reason,
|
|
168
|
+
written into the Verdict. For high-stakes iterations
|
|
169
|
+
(schema/API/persistence/security), add a review before the verdict. You
|
|
170
|
+
(Opus 4.8) reading the diff is already a stronger-model, fresh-context pass
|
|
171
|
+
over the Sonnet builder's work — a cross-tier read, though not cross-vendor
|
|
172
|
+
(both are Claude Code). For an extra adversarial pass, pipe the diff to a fresh
|
|
173
|
+
read-only `claude -p` reviewer (command in `dispatch.md`) or a
|
|
174
|
+
fresh-context subagent prompted to break confidence — calibrated to flag only
|
|
175
|
+
correctness/requirement/invariant gaps with file:line evidence, no style.
|
|
176
|
+
|
|
177
|
+
**Variant sets — human in the loop.** When the iteration was built as a variant
|
|
178
|
+
set (multiple `(harness, model)` lanes over one frozen spec), judge every
|
|
179
|
+
variant against the same frozen AC, then **do not pick the winner unilaterally**
|
|
180
|
+
— assume the human wants to be involved in selection. Present the head-to-head:
|
|
181
|
+
per-variant gate results plus the deltas that decide it (correctness/invariants,
|
|
182
|
+
idiomaticity + house-style, tests, user-facing behavior), with your
|
|
183
|
+
recommendation and its reasoning. Let the human choose (`AskUserQuestion` or a
|
|
184
|
+
checkpoint); you then execute the promote/merge they pick. Surface a
|
|
185
|
+
recommendation — the call is theirs. (A standing handoff that pre-delegates the
|
|
186
|
+
pick still gets the comparison surfaced before you act on it.)
|
|
187
|
+
|
|
188
|
+
### 3. Research fan-out (optional — most iterations skip this)
|
|
189
|
+
|
|
190
|
+
Two scales, two routes:
|
|
191
|
+
|
|
192
|
+
- **Discovery scale** — brainstorming what to build, technology selection,
|
|
193
|
+
state-of-the-art surveys → invoke the `/architect-research` skill (a scout
|
|
194
|
+
researcher maps the topic, the orchestrator designs topic-specific parallel
|
|
195
|
+
researcher lanes, claims verified against sources, synthesized into a cited
|
|
196
|
+
report). Its report then distills into `architecture/BRIEF.md` §sections when
|
|
197
|
+
it is mission-scope (a durable contract that spans iterations), or the
|
|
198
|
+
iteration's **Grounds** section when it is iteration-scope.
|
|
199
|
+
- **Iteration scale** — run the inline fan-out below only when at least one
|
|
200
|
+
trigger holds: (a) the iteration depends on external APIs, libraries, or
|
|
201
|
+
versions not already used in the target repo; (b) a narrow approach choice
|
|
202
|
+
needs facts neither you nor the repo has; (c) the human asked
|
|
203
|
+
(`/architect research: <question>`). Otherwise skip — the builder's
|
|
204
|
+
verify-against-reality requirement already covers routine API checks, and
|
|
205
|
+
researching well-understood iterations is pure cost.
|
|
206
|
+
|
|
207
|
+
When a trigger fires, read `research.md` next to this file and follow it:
|
|
208
|
+
3–5 narrow non-overlapping questions → parallel read-only `claude -p`
|
|
209
|
+
researchers (built-in `WebSearch`/`WebFetch`) in the background → you
|
|
210
|
+
adversarially verify the load-bearing claims → you write the iteration's
|
|
211
|
+
**Grounds** section with citations and commit it. Researchers gather; you judge
|
|
212
|
+
and write Grounds. Findings without a source URL don't enter Grounds.
|
|
213
|
+
|
|
214
|
+
### 4. Spec the next iteration
|
|
215
|
+
|
|
216
|
+
One-PR-sized. Run `architect new <name>` to scaffold
|
|
217
|
+
`architecture/I<NN>-<name>.md` (it allocates the next ordinal and records the
|
|
218
|
+
iteration in `space.yaml`), then write the **Specification** section with
|
|
219
|
+
`architect section <name> specification --from <file>` — the full delegation
|
|
220
|
+
contract, self-contained:
|
|
221
|
+
|
|
222
|
+
- **Objective** — what to build and why (give the reason, not just the ask).
|
|
223
|
+
Cite **BRIEF §N** for durable context and a Grounds section for
|
|
224
|
+
iteration-local research, rather than restating either.
|
|
225
|
+
- **Output format** — what the builder reports: raw tables, numbers, commit
|
|
226
|
+
SHAs, test output paths. No interpretation.
|
|
227
|
+
- **Tool guidance** — the exact verification commands for the target repo, and
|
|
228
|
+
the specific APIs/formats/versions the builder must verify against the live
|
|
229
|
+
dependencies *before* writing code.
|
|
230
|
+
- **Boundaries** — files it may touch, files it must not, explicit out-of-scope
|
|
231
|
+
list, "no placeholders; search before implementing", no refactors beyond the
|
|
232
|
+
task.
|
|
233
|
+
- **Lane plan** — split the iteration into 1–4 parallel lanes, each declaring
|
|
234
|
+
its **target repo + file-touch set, checked for overlap**: name the repo
|
|
235
|
+
(`repos/<repo>`) and every file each lane may touch. Lanes in *different*
|
|
236
|
+
repos are inherently disjoint; same-repo lanes with any file overlap run as
|
|
237
|
+
one. Each lane gets its own objective, output format, and boundaries. Most
|
|
238
|
+
iterations are one lane — fan out only when the work is genuinely parallel (a
|
|
239
|
+
cross-repo mission often is).
|
|
240
|
+
- **Effort call** — thinking budget set in the lane-prompt via the escalation
|
|
241
|
+
keywords (`think hard` … `ultrathink`); default unattended builder work high,
|
|
242
|
+
downgrade a routine, tightly-specified lane (record which and why). Claude
|
|
243
|
+
Code has no per-invocation effort flag — see `dispatch.md`.
|
|
244
|
+
|
|
245
|
+
Then write the **Acceptance Criteria** section — exact gate commands +
|
|
246
|
+
thresholds, each row carrying a `Brief §` column that addresses it back to
|
|
247
|
+
intent — and run `architect freeze <name>`. What must be frozen before dispatch
|
|
248
|
+
is the Acceptance Criteria: `architect freeze` commits any pending content in the
|
|
249
|
+
frozen region (Grounds/Specification/Acceptance Criteria) in one freeze commit,
|
|
250
|
+
records the `freeze_sha` in `space.yaml`, and prints the frozen AC back; **that
|
|
251
|
+
commit is the freeze** ❄️ and is the last thing before dispatch. You needn't
|
|
252
|
+
sequence Grounds and Specification into separate commits first — the freeze
|
|
253
|
+
snapshots the whole frozen region and refuses to re-freeze once a frozen section
|
|
254
|
+
changed afterward.
|
|
255
|
+
|
|
256
|
+
### 5. Dispatch (one fresh `claude -p` per lane, worktree-isolated)
|
|
257
|
+
|
|
258
|
+
Per the mechanics in `dispatch.md`:
|
|
259
|
+
|
|
260
|
+
- **1 lane** → dispatch in the target repo's checkout (`repos/<repo>`).
|
|
261
|
+
- **2–4 lanes** → `architect worktree add <repo> <iteration> <lane>
|
|
262
|
+
[--base <repo-base>]` per lane (creates `build/<id>-<lane>/wt` off the target
|
|
263
|
+
repo's base commit — a repo commit, distinct from the freeze, which is a
|
|
264
|
+
space commit — and records it in `space.yaml`).
|
|
265
|
+
|
|
266
|
+
Assemble each lane's lane-prompt (the template in `dispatch.md` + this lane's
|
|
267
|
+
section of the Specification + the frozen Acceptance Criteria) and write it to
|
|
268
|
+
`build/<id>-<lane>/prompt.md` (fed to the builder on stdin); record it in the
|
|
269
|
+
iteration file's **Builder Prompt** section — the dispatched-prompt provenance —
|
|
270
|
+
with `architect section <iteration> prompt --append --lane <lane> --from
|
|
271
|
+
build/<id>-<lane>/prompt.md`. Then run `architect dispatch <iteration> <lane>` — it assembles the
|
|
272
|
+
canonical `claude -p` argv, pins the model, and streams stream-json to
|
|
273
|
+
`build/<id>-<lane>/run.jsonl`. Launch one dispatch per worktree — each as its
|
|
274
|
+
**own background Bash tool call** (your harness's `run_in_background`), **not**
|
|
275
|
+
shell `&`. The harness keeps each lane alive for its full run and notifies you
|
|
276
|
+
per lane; a `for … & done` launcher instead orphans the lanes and the harness
|
|
277
|
+
reaps them all at once (see `dispatch.md`). Each lane builds only its declared
|
|
278
|
+
files and writes raw results to `build/<id>-<lane>/report.md` — it never
|
|
279
|
+
touches `architecture/`, so lanes never collide and the Acceptance Criteria
|
|
280
|
+
stay untouchable.
|
|
281
|
+
|
|
282
|
+
Do not block — end the turn or do other judgment work; multi-hour runs are
|
|
283
|
+
normal. Print the lane-prompts too, so the human can run any lane in an
|
|
284
|
+
interactive `claude` session instead. Whenever you return to a running lane,
|
|
285
|
+
check liveness: the lane's `run.jsonl` must still be growing. If it has been
|
|
286
|
+
silent 15+ minutes on one in-flight command, follow "Stall detection and
|
|
287
|
+
rescue" in `dispatch.md` — kill the stuck child process, not the run.
|
|
288
|
+
|
|
289
|
+
### 6. Post-flight and integrate (when the runs complete)
|
|
290
|
+
|
|
291
|
+
`architect verify <iteration>` REPORTS (it never judges) per lane: frozen
|
|
292
|
+
sections untouched, no builder commits, scratch report present, in-bounds.
|
|
293
|
+
Confirm each yourself with evidence: (a) the scratch report has raw results
|
|
294
|
+
only, (b) PHASE 0 disagreements were raised (silent compliance = defect to
|
|
295
|
+
log), (c) the iteration file's frozen sections are untouched — `git diff
|
|
296
|
+
<freeze-sha> HEAD -- architecture/I<NN>-<name>.md` shows no change to
|
|
297
|
+
Grounds/Specification/Acceptance Criteria, (d) `git status` in the worktree
|
|
298
|
+
shows **only files inside the lane's declared set** — an out-of-bounds write
|
|
299
|
+
fails the lane, (e) `git -C <worktree> log <repo-base>..` is empty — a builder
|
|
300
|
+
commit means a tampered worktree (reset and re-dispatch).
|
|
301
|
+
|
|
302
|
+
**Transcribe** each lane's scratch report into the **Builder Report** section
|
|
303
|
+
with `architect evidence <iteration> --lane <lane>` — it copies
|
|
304
|
+
`build/<id>-<lane>/report.md` **verbatim** (byte-for-byte, no interpretation),
|
|
305
|
+
commits it, and echoes the builder's STATUS line. The builder never wrote into
|
|
306
|
+
`architecture/`; the CLI transcribes, preserving raw-results-only.
|
|
307
|
+
|
|
308
|
+
**Then integrate** — you decide which lanes pass, the CLI does the git
|
|
309
|
+
mechanics. `architect integrate <iteration> --lanes <passing-set>` commits each
|
|
310
|
+
named lane on its branch and merges it `--no-ff` into the repo's integration
|
|
311
|
+
branch `lane/<iteration>`, in order; it **refuses** a lane that left builder
|
|
312
|
+
commits or wrote out-of-bounds, and stops on a merge conflict — which means the
|
|
313
|
+
lane plan wasn't disjoint, a spec defect: kill the conflicting lane and re-spec
|
|
314
|
+
it (never hand-resolve). Then run `architect gate <iteration>` against the
|
|
315
|
+
integration branch as a smoke check (raw output; the verdict stays yours). A
|
|
316
|
+
cross-repo mission yields one `lane/<iteration>` branch per touched repo. Update
|
|
317
|
+
the iteration index in `architecture/ARCHITECT.md` (recording each repo's
|
|
318
|
+
integration branch), remove the worktrees (`architect integrate … --teardown`,
|
|
319
|
+
or `architect worktree remove <iteration> <lane>`), and commit the space.
|
|
320
|
+
|
|
321
|
+
**Do not judge now** — the Verdict on the integration branch belongs to the
|
|
322
|
+
next architect session; merge to each repo's main only on a CONTINUE verdict
|
|
323
|
+
there.
|
|
324
|
+
|
|
325
|
+
## Maintenance
|
|
326
|
+
|
|
327
|
+
Re-read this skill against each new model generation and delete what the models
|
|
328
|
+
now do unprompted — over-prescription degrades current-model output. The rules
|
|
329
|
+
above are invariants; everything else is prunable.
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Builder dispatch reference
|
|
2
|
+
|
|
3
|
+
Verified against the `claude` CLI (Claude Code) headless mode, June 2026. The
|
|
4
|
+
builder is `claude -p` (`--print`, the non-interactive headless mode) pinned to
|
|
5
|
+
`claude-sonnet-4-6` — the *same binary the architect runs, one tier down*. Key
|
|
6
|
+
facts the skill encodes: lane-prompts go in on **stdin** (Claude Code has no
|
|
7
|
+
`@file`, and a big quoted lane-prompt as a shell argument gets mangled); the
|
|
8
|
+
model is pinned with `--model claude-sonnet-4-6` (the `sonnet` alias floats to
|
|
9
|
+
the latest Sonnet — pin the full id); there is **no `-C`/working-dir flag**, so
|
|
10
|
+
per-lane dispatch `cd`s into the worktree; permissions are the **tool
|
|
11
|
+
allow/deny lists** (`--allowedTools`/`--disallowedTools`) plus
|
|
12
|
+
`--permission-mode`, not a sandbox; web access is the built-in
|
|
13
|
+
`WebSearch`/`WebFetch` tools (no extension to install).
|
|
14
|
+
|
|
15
|
+
**The one load-bearing difference from the Codex design:** Codex's
|
|
16
|
+
`--sandbox workspace-write` made `.git` physically read-only. Claude Code has
|
|
17
|
+
**no automatic filesystem sandbox** in headless mode (the sandbox is opt-in via
|
|
18
|
+
settings, off by default), so `.git` is not hardware-protected. "Builders never
|
|
19
|
+
commit" (hard rule 7) is now enforced in three layers, weakest to strongest:
|
|
20
|
+
(1) a runtime first line — deny the git-write tools with
|
|
21
|
+
`--disallowedTools 'Bash(git commit:*)' …`; (2) worktree isolation between
|
|
22
|
+
lanes; (3) the authoritative check — an architect post-flight
|
|
23
|
+
`git -C <worktree> log <repo-base>..` that must be empty. The deny rules are
|
|
24
|
+
not airtight (a builder can shell out — `sh -c 'git commit …'` — past the
|
|
25
|
+
pattern match), so the post-flight `git log` is what the loop actually trusts.
|
|
26
|
+
If a lane committed, treat the worktree as tampered: reset and re-dispatch.
|
|
27
|
+
|
|
28
|
+
**Preflight (once per environment):** run `claude --version`, and confirm the
|
|
29
|
+
builder model resolves with a one-shot canary
|
|
30
|
+
(`echo ok | claude -p --model claude-sonnet-4-6 --max-turns 1`). No API key —
|
|
31
|
+
the builder runs on your Claude plan — but note headless `claude -p` draws on
|
|
32
|
+
the Agent SDK credit pool (separate from interactive usage since June 15 2026;
|
|
33
|
+
see `DESIGN.md` §4). On the first real dispatch in a new environment, launch
|
|
34
|
+
ONE canary lane and confirm it starts cleanly before fanning anything out.
|
|
35
|
+
|
|
36
|
+
## Canonical dispatch — `architect dispatch <iteration> <lane>`
|
|
37
|
+
|
|
38
|
+
The canonical path is `architect dispatch <iteration> <lane>`. The tool
|
|
39
|
+
assembles the canonical `claude -p` argv, pins the model to `claude-sonnet-4-6`,
|
|
40
|
+
reads the lane prompt from `build/<id>-<lane>/prompt.md` on stdin, and streams
|
|
41
|
+
`--output-format stream-json --verbose` output to
|
|
42
|
+
`build/<id>-<lane>/run.jsonl`. Run each lane as its own **background Bash tool
|
|
43
|
+
call** (`run_in_background`) so your turn doesn't block for the full multi-hour
|
|
44
|
+
run.
|
|
45
|
+
|
|
46
|
+
Write the lane's prompt to `build/<id>-<lane>/prompt.md` first (never pass a
|
|
47
|
+
big prompt as a shell argument — shells mangle quotes), then:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# single-lane iteration — run from the space root
|
|
51
|
+
architect dispatch <iteration> <lane>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For multi-lane iterations, create worktrees first (one per lane), then dispatch
|
|
55
|
+
each lane from its worktree:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# per lane:
|
|
59
|
+
architect worktree add <repo> <iteration> <lane> [--base <repo-base>]
|
|
60
|
+
architect dispatch <iteration> <lane>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`architect worktree add` creates `build/<id>-<lane>/wt` off the target repo's
|
|
64
|
+
base commit (a repo commit — distinct from the freeze, which is a space
|
|
65
|
+
commit), adds it with a `lane/<iteration>-<lane>` branch, and records it in
|
|
66
|
+
`space.yaml`.
|
|
67
|
+
|
|
68
|
+
Issue each dispatch as its **own background Bash tool call** — one call per
|
|
69
|
+
lane. Never use a shell `&` loop. A `for … & done` launcher is a *launcher*
|
|
70
|
+
process: it returns the instant it has spawned the lane children, the harness
|
|
71
|
+
reaps those now-orphaned `claude` processes, and every lane dies at once with no
|
|
72
|
+
`result` — partial diffs, no reports (this exact failure has happened: three
|
|
73
|
+
lanes killed at the same second, zero output). One blocking dispatch per
|
|
74
|
+
background Bash tool keeps each lane attached to a harness-tracked task that
|
|
75
|
+
survives the full multi-hour run and reports completion per lane.
|
|
76
|
+
|
|
77
|
+
### What the tool runs under the hood
|
|
78
|
+
|
|
79
|
+
`architect dispatch` is equivalent to this — documented here for transparency
|
|
80
|
+
and as the manual fallback:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# write prompt to build/<id>-<lane>/prompt.md first, then:
|
|
84
|
+
( cd build/<id>-<lane>/wt && \
|
|
85
|
+
claude -p --model claude-sonnet-4-6 \
|
|
86
|
+
--permission-mode acceptEdits \
|
|
87
|
+
--allowedTools 'Read,Edit,Write,Grep,Glob,Bash,WebSearch,WebFetch' \
|
|
88
|
+
--disallowedTools 'Bash(git commit:*),Bash(git push:*),Bash(git reset:*),Bash(git merge:*),Bash(git rebase:*),Bash(git checkout:*),Bash(git branch:*)' \
|
|
89
|
+
--output-format stream-json --verbose \
|
|
90
|
+
--max-turns 200 \
|
|
91
|
+
< <space>/build/<id>-<lane>/prompt.md \
|
|
92
|
+
> <space>/build/<id>-<lane>/run.jsonl 2>&1 )
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`acceptEdits` auto-approves file writes; listing `Bash` in `--allowedTools`
|
|
96
|
+
auto-approves shell commands so the run never blocks on a prompt; any tool *not*
|
|
97
|
+
on the allow list is denied rather than prompted in `-p` mode (so the builder
|
|
98
|
+
can't wander outside its toolset), and the `--disallowedTools` deny rules win
|
|
99
|
+
over the allow list (deny always takes precedence) as the runtime first line
|
|
100
|
+
against commits. Redirect stderr (`2>&1`) into the run-log so a dispatch error
|
|
101
|
+
lands somewhere instead of vanishing.
|
|
102
|
+
|
|
103
|
+
### Integration (architect-only, after per-lane post-flight passes)
|
|
104
|
+
|
|
105
|
+
You decide which lanes pass; the CLI does the git mechanics. Canonical path:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
architect integrate <iteration> --lanes <passing-set> # e.g. --lanes lane-a,lane-b
|
|
109
|
+
architect gate <iteration> # integration smoke (raw output; verdict stays yours)
|
|
110
|
+
architect integrate <iteration> --lanes <passing-set> --teardown # or remove worktrees + lane branches after
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`architect integrate` commits each named lane on its branch and merges it
|
|
114
|
+
`--no-ff` into the repo's `lane/<iteration>` integration branch, in order. It
|
|
115
|
+
**refuses** a lane that left builder commits or wrote out-of-bounds (the
|
|
116
|
+
mechanical post-flight checks), and aborts on a merge conflict. A merge conflict
|
|
117
|
+
= the lane plan wasn't disjoint = a spec defect: kill the conflicting lane and
|
|
118
|
+
re-spec; don't hand-resolve builder conflicts. It runs **no gates and makes no
|
|
119
|
+
verdict** — `architect gate` streams the raw gate output for you to judge.
|
|
120
|
+
|
|
121
|
+
Under the hood / manual fallback (one lane shown):
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git -C repos/<repo> checkout -b lane/<iteration> <repo-base>
|
|
125
|
+
git -C build/<id>-<lane>/wt add -A
|
|
126
|
+
git -C build/<id>-<lane>/wt commit -m "lane <lane>: <what>"
|
|
127
|
+
git -C repos/<repo> merge --no-ff lane/<iteration>-<lane>
|
|
128
|
+
<run the gate commands> # integration smoke after every merge
|
|
129
|
+
architect worktree remove <iteration> <lane>
|
|
130
|
+
git -C repos/<repo> branch -d lane/<iteration>-<lane>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Operating guidance
|
|
134
|
+
|
|
135
|
+
- Background each lane as its own harness task and let the **per-lane
|
|
136
|
+
completion notification** bring you back (multi-hour runs are normal); read
|
|
137
|
+
`build/<id>-<lane>/run.jsonl` and the repo state afterwards. Do not write a
|
|
138
|
+
blocking `while pgrep …; sleep` wait loop as a Bash command — that is itself
|
|
139
|
+
a launcher that ties up a turn. When you return to a lane, check liveness via
|
|
140
|
+
run-log growth (the stall rules below still apply unchanged).
|
|
141
|
+
- Pin the model explicitly. The tool does this automatically (`--model
|
|
142
|
+
claude-sonnet-4-6`). The `sonnet` alias floats to the latest Sonnet — fine
|
|
143
|
+
interactively, but automations pin the full id so a model bump can't silently
|
|
144
|
+
change builder behavior mid-project.
|
|
145
|
+
- Effort = thinking budget. Claude Code has no per-invocation effort flag the
|
|
146
|
+
way Codex exposed `model_reasoning_effort`; the builder sets thinking depth
|
|
147
|
+
**in the block** via the escalation keywords (`think` < `think hard` <
|
|
148
|
+
`think harder` < `ultrathink`), or you floor it with the `MAX_THINKING_TOKENS`
|
|
149
|
+
env var on the dispatch. Default unattended builder work to a high budget
|
|
150
|
+
(open the block with "Think harder…"); downgrade a routine,
|
|
151
|
+
tightly-specified lane to "think hard" (record which and why in the spec).
|
|
152
|
+
- **Builders never commit, and the architect verifies it.** Claude Code has no
|
|
153
|
+
sandbox to make `.git` read-only, so this is enforced by the deny rules at
|
|
154
|
+
dispatch *and* checked after the run: before integrating a lane, confirm
|
|
155
|
+
`git -C build/<id>-<lane>/wt log <repo-base>..` is empty and
|
|
156
|
+
`git -C build/<id>-<lane>/wt status` shows only files inside the lane's
|
|
157
|
+
declared set. A commit or an out-of-bounds write fails the lane — reset and
|
|
158
|
+
re-dispatch (lanes are cheap, hard rule 7).
|
|
159
|
+
- Same-iteration follow-up (e.g. answering PHASE 0 disagreements after the
|
|
160
|
+
human rules): from the lane's worktree, `claude -p --continue "<rulings +
|
|
161
|
+
proceed>"` resumes that worktree's most recent session with full context —
|
|
162
|
+
sessions are scoped per directory, so `--continue` (`-c`) is deterministic
|
|
163
|
+
even with parallel lanes. (Alternatively pin `--session-id <uuid>` at
|
|
164
|
+
dispatch and resume with `--resume <uuid>`.) Resume the **same way you
|
|
165
|
+
dispatch** — one background Bash tool call per lane, each a single blocking
|
|
166
|
+
`claude -p --continue …`, never a `&` loop (a `&` launcher orphans the
|
|
167
|
+
resumed lanes exactly as it does fresh ones). Never resume across iterations —
|
|
168
|
+
every iteration gets a fresh context.
|
|
169
|
+
- Cross-model review gate (high-stakes iterations): the architect is Opus 4.8
|
|
170
|
+
and the builder is Sonnet 4.6 — both Claude Code, so this is a
|
|
171
|
+
cross-*tier* read inside one lab, not cross-vendor (see `DESIGN.md` R3). The
|
|
172
|
+
architect (Opus) reading the diff is already the stronger-model fresh-context
|
|
173
|
+
pass. For an extra adversarial pass, pipe the instruction + diff to a fresh
|
|
174
|
+
read-only reviewer:
|
|
175
|
+
```bash
|
|
176
|
+
{ echo "Review this diff against the spec. Flag ONLY correctness/requirement/invariant gaps with file:line evidence. No style."; \
|
|
177
|
+
git -C <repo-root> diff <base>...HEAD; } \
|
|
178
|
+
| claude -p --model claude-sonnet-4-6 --allowedTools 'Read,Grep,Glob'
|
|
179
|
+
```
|
|
180
|
+
- `build/` is already gitignored by the space, so no extra `.gitignore` entry
|
|
181
|
+
is needed. Scratch never reaches the space repo; only `architecture/` is
|
|
182
|
+
committed.
|
|
183
|
+
|
|
184
|
+
## Stall detection and rescue
|
|
185
|
+
|
|
186
|
+
A dispatched run is STALLED when its `run.jsonl`
|
|
187
|
+
(`build/<id>-<lane>/run.jsonl`) has not grown for 15+ minutes AND the last
|
|
188
|
+
event is an in-flight `Bash` tool call (a `tool_use` for `Bash` with no
|
|
189
|
+
matching `tool_result` yet). Silent gaps between events are normal model
|
|
190
|
+
thinking; a shell command that should take seconds sitting in flight for 15+
|
|
191
|
+
minutes is not.
|
|
192
|
+
|
|
193
|
+
Diagnose before killing: find the command's child under the `claude` PID
|
|
194
|
+
(claude → shell → child). Hot-spinning (high CPU) or blocked (zero CPU and none
|
|
195
|
+
of its expected side effects on disk) — hung either way.
|
|
196
|
+
|
|
197
|
+
Kill the NARROWEST thing: the stuck child process, not the `claude` run. The
|
|
198
|
+
command returns a failure to the builder, which adapts with its full context
|
|
199
|
+
intact. Kill the whole run only when the builder re-enters the same hang or the
|
|
200
|
+
worktree is broken; then discard the lane and re-dispatch (hard rule 7).
|
|
201
|
+
|
|
202
|
+
Claude Code runs the `Bash` tool directly with no sandbox, so the Codex-era
|
|
203
|
+
sandbox-specific hang sources don't apply — but long-running and interactive
|
|
204
|
+
commands still hang an unattended run. Spec consequence: give every potentially
|
|
205
|
+
long command an explicit timeout in the lane-prompt (the `Bash` tool also takes
|
|
206
|
+
a per-call timeout), cap the run with `--max-turns` as a loop backstop, steer
|
|
207
|
+
builders toward the repo's existing test fixtures over hand-rolled long-running
|
|
208
|
+
harnesses, and when a gate needs a runtime that can't run unattended
|
|
209
|
+
(interactive prompts, servers without a timeout), have the builder record the
|
|
210
|
+
exact failure as a disagreement/blocker and verify what it can — gate verdicts
|
|
211
|
+
are architect-run anyway (hard rule 4). Write the gate file anticipating this.
|
|
212
|
+
|
|
213
|
+
## Manual alternative (human-driven)
|
|
214
|
+
|
|
215
|
+
Paste the lane-prompt into an interactive `claude` session (no `-p`). Claude
|
|
216
|
+
Code's agent loop runs plan→act→test against the block's stopping condition
|
|
217
|
+
while you watch and steer — approve tools as they come, or set `/permissions`
|
|
218
|
+
first. Use when the human wants to babysit a run.
|
|
219
|
+
|
|
220
|
+
## Lane-prompt template
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Execute the architect spec below. Operating rules:
|
|
224
|
+
|
|
225
|
+
PHASE 0 — Before any code: reply with your plan and EVERY disagreement you have
|
|
226
|
+
with this spec, with reasons, citing real files in this repo. Silent compliance
|
|
227
|
+
is a failure. Silent scope additions are a failure. If you have no
|
|
228
|
+
disagreements, state what you checked before concluding the spec is sound.
|
|
229
|
+
Verify the named APIs/formats/versions against the live dependencies before
|
|
230
|
+
planning around them.
|
|
231
|
+
|
|
232
|
+
PHASE 1 — Treat the shared contracts (schemas/interfaces) named in the spec,
|
|
233
|
+
and the repo's existing public interfaces, as FROZEN: do not change them —
|
|
234
|
+
other lanes depend on them. You have no access to the space's architecture/
|
|
235
|
+
directory; the architect owns it. The ACCEPTANCE CRITERIA below are frozen —
|
|
236
|
+
verify your work against them; never weaken or work around them.
|
|
237
|
+
|
|
238
|
+
PHASE 2 — Build YOUR LANE ONLY: exactly the files listed in BOUNDARIES. You
|
|
239
|
+
are one of several parallel lane agents working in isolated worktrees; files
|
|
240
|
+
outside your lane belong to other agents — touching them fails your lane.
|
|
241
|
+
No placeholder implementations — search the codebase before implementing;
|
|
242
|
+
full implementations only. Write IDIOMATIC, house-consistent code: read the
|
|
243
|
+
neighbouring code and match its conventions (naming, guards, predicates,
|
|
244
|
+
error/persistence idioms, the language's expressive collection/enumerable
|
|
245
|
+
forms); well-factored and DRY-ish; terse but clear; pragmatic, not clever — the
|
|
246
|
+
smallest change that does the job, no abstraction it doesn't need. Consistency
|
|
247
|
+
with the surrounding code is part of correctness here: a change that works but
|
|
248
|
+
fights the house style (or introduces an inconsistency a careful reader of this
|
|
249
|
+
repo would never write) is not done. Tests stay simple and terse, exercising
|
|
250
|
+
public behavior, no mock/stub of the class under test. Verify your work by
|
|
251
|
+
running the acceptance criteria's gate commands and record the verbatim output. Do NOT commit and do NOT run any
|
|
252
|
+
git write command (commit/add/branch/reset/checkout) — the architect commits
|
|
253
|
+
and merges after verification, and verifies you made no commits. Do NOT delete
|
|
254
|
+
lock files or escalate privileges if a command fails; record the exact error
|
|
255
|
+
and continue. Give every potentially long command an explicit timeout; if a
|
|
256
|
+
runtime will not start unattended (interactive prompt, server with no timeout),
|
|
257
|
+
record the exact failure in your report and route around it — never busy-wait
|
|
258
|
+
or retry in a loop. When done, write your report to the scratch file given to
|
|
259
|
+
you, build/<id>-<lane>/report.md (an absolute path outside your worktree),
|
|
260
|
+
with RAW results only — tables, numbers, command output — no interpretation, no
|
|
261
|
+
"promising". Every status claim must be backed by a command result from this
|
|
262
|
+
run. Keep the report compact — tables and numbers, not prose. End it with
|
|
263
|
+
exactly one status line: STATUS: COMPLETE | COMPLETE_WITH_CONCERNS (list them)
|
|
264
|
+
| BLOCKED (exact blocker + what you tried). Verdicts belong to the architect
|
|
265
|
+
and the human. Persist until your lane is fully handled end-to-end; do not stop
|
|
266
|
+
at analysis or partial fixes.
|
|
267
|
+
|
|
268
|
+
=== OBJECTIVE (and why) ===
|
|
269
|
+
...
|
|
270
|
+
|
|
271
|
+
=== OUTPUT FORMAT ===
|
|
272
|
+
...
|
|
273
|
+
|
|
274
|
+
=== TOOL GUIDANCE (verification commands; verify-against-reality list) ===
|
|
275
|
+
...
|
|
276
|
+
|
|
277
|
+
=== BOUNDARIES (may touch / must not touch / out of scope) ===
|
|
278
|
+
...
|
|
279
|
+
|
|
280
|
+
=== DISAGREEMENT RULINGS (from last session) ===
|
|
281
|
+
...
|
|
282
|
+
|
|
283
|
+
=== ACCEPTANCE CRITERIA (frozen — the architect re-runs these to judge; verify
|
|
284
|
+
against them, do not edit or work around) ===
|
|
285
|
+
...
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Builder-side standing setup (one time per machine/repo)
|
|
289
|
+
|
|
290
|
+
- The builder is the same `claude` binary as the architect, one tier down —
|
|
291
|
+
nothing extra to install. `architect dispatch` pins the model per dispatch
|
|
292
|
+
(`--model claude-sonnet-4-6`); a `~/.claude/settings.json` `"model"` default
|
|
293
|
+
is fine interactively, but automations pin it explicitly so a default can't
|
|
294
|
+
silently swap the builder.
|
|
295
|
+
- Repo `CLAUDE.md` is the builder's standing context — Claude Code loads it
|
|
296
|
+
root-down automatically. Put exact build/test commands and repo gotchas there;
|
|
297
|
+
the loop's PHASE rules stay in the dispatch block so they version with the
|
|
298
|
+
skill. (Claude Code does **not** auto-read `AGENTS.md`; if the repo keeps its
|
|
299
|
+
build/test docs there, add `@AGENTS.md` to `CLAUDE.md` to pull it in.)
|
|
300
|
+
- The builder is a bare `claude -p` over the block — it is not invoking the
|
|
301
|
+
`/architect` skills, the block is its entire instruction set. (`--bare` would
|
|
302
|
+
give a leaner builder context but also drops `CLAUDE.md`/skills/hooks — keep
|
|
303
|
+
`CLAUDE.md`, so skip `--bare` unless the repo has no standing build/test doc.)
|
|
304
|
+
- Billing: headless `claude -p` draws on the Agent SDK credit pool on your
|
|
305
|
+
Claude plan (separate from interactive usage limits since June 15 2026).
|
|
306
|
+
There's no per-window quota that dies mid-run the way a chat session can, but
|
|
307
|
+
a long parallel fan-out does spend that pool. The architect runs as your
|
|
308
|
+
interactive Claude Code session.
|