space-architect 1.3.0 → 2.0.0.rc2
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 +267 -158
- data/exe/architect +1 -1
- data/exe/space +2 -2
- data/exe/src +13 -0
- data/lib/space_architect/{architect_mission.rb → architect_project.rb} +475 -125
- data/lib/space_architect/cli/architect.rb +248 -178
- 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/gate_evaluator.rb +65 -0
- data/lib/space_architect/gate_lint.rb +140 -0
- data/lib/space_architect/harness.rb +145 -17
- 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 +81 -79
- data/lib/space_architect/templates/architect.md.erb +15 -4
- data/lib/space_architect/templates/brief.md.erb +5 -5
- data/lib/space_architect/templates/iteration.md.erb +17 -6
- data/lib/space_architect.rb +8 -21
- 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/build.rb +27 -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 +123 -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/pack.rb +29 -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/run.rb +29 -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 +177 -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_core/oci_builder.rb +56 -0
- data/lib/space_core/oci_packer.rb +99 -0
- data/lib/space_core/oci_runner.rb +73 -0
- 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 +11 -3
- data/lib/{space_architect → space_core}/space_store.rb +13 -13
- data/lib/{space_architect → space_core}/state.rb +1 -1
- data/lib/space_core/templates/oci/dockerfile.erb +63 -0
- data/lib/space_core/templates/oci/dockerignore.erb +17 -0
- data/lib/space_core/templates/oci/entrypoint.sh.erb +10 -0
- data/lib/{space_architect → space_core}/terminal.rb +1 -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 +42 -11
- 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 +110 -54
- data/skill/architect/dispatch.md +147 -39
- data/skill/architect/research.md +46 -37
- data/skill/architect-research/SKILL.md +2 -2
- data/skill/architect-vocabulary/SKILL.md +24 -21
- metadata +127 -68
- 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 -44
data/skill/architect/SKILL.md
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: architect
|
|
3
3
|
description: >
|
|
4
|
-
Run the Architect Loop:
|
|
5
|
-
only: arbitration, judging raw evidence against frozen Acceptance
|
|
6
|
-
splitting iterations into disjoint lanes, kill/continue calls. The
|
|
7
|
-
are 1-4 parallel
|
|
8
|
-
own git worktree; the architect reviews, merges, and
|
|
4
|
+
Run the Architect Loop: a strong reasoning model (or a human) is the ARCHITECT
|
|
5
|
+
— judgment only: arbitration, judging raw evidence against frozen Acceptance
|
|
6
|
+
Criteria, splitting iterations into disjoint lanes, kill/continue calls. The
|
|
7
|
+
BUILDERS are 1-4 parallel cheaper agents run headless (reference harness:
|
|
8
|
+
`claude -p`), each in its own git worktree; the architect reviews, merges, and
|
|
9
|
+
integrates their work.
|
|
9
10
|
The space is the memory: one file per iteration at
|
|
10
11
|
architecture/I<NN>-<name>.md (Grounds / Specification / Acceptance Criteria /
|
|
11
12
|
Builder Prompt / Builder Report / Verdict), indexed by
|
|
12
|
-
architecture/ARCHITECT.md; a
|
|
13
|
+
architecture/ARCHITECT.md; a project spans the repos under repos/. Use when
|
|
13
14
|
asked to "architect", "run the loop", "next iteration", "judge the builder's
|
|
14
15
|
work", or at the start of a work block in a space using the handoff system.
|
|
15
16
|
---
|
|
16
17
|
|
|
17
18
|
# Architect
|
|
18
19
|
|
|
19
|
-
You are the ARCHITECT
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
You are the ARCHITECT — the judgment role: a strong reasoning model (or a human),
|
|
21
|
+
run interactively. The BUILDER is a cheaper model run headless (reference
|
|
22
|
+
harness: `claude -p`), one or more per iteration — the models filling both roles
|
|
23
|
+
are an operator choice (see `docs/DESIGN.md` §1–§2), not fixed. The space is the
|
|
24
|
+
memory — project artifacts live in the space's `architecture/` dir (committed),
|
|
25
|
+
scratch in `build/` (gitignored); the project spans the repos under `repos/`.
|
|
23
26
|
Your output is judgment and a dispatch — never implementation code. When you
|
|
24
27
|
have enough information to act, act.
|
|
25
28
|
|
|
@@ -33,7 +36,7 @@ change guarantees, so there are no separate `gates/`, `lanes/`, or `prd/` dirs:
|
|
|
33
36
|
|---|---|---|
|
|
34
37
|
| **Grounds** | why — research/brief distilled (optional) | `architect section <it> grounds --from <f>` |
|
|
35
38
|
| **Specification** | what/how — the full delegation contract | `architect section <it> specification --from <f>` |
|
|
36
|
-
| **Acceptance Criteria** | proof —
|
|
39
|
+
| **Acceptance Criteria** | proof — prose conditions (AC1, AC2, …) + fenced ` ```gates ` block of runnable checks | `architect freeze <it>` ❄️ **= the freeze** |
|
|
37
40
|
| **Builder Prompt** | the exact lane-prompt(s) dispatched | `architect section <it> prompt --append --lane <l> --from <f>` |
|
|
38
41
|
| **Builder Report** | raw evidence, transcribed verbatim from scratch | `architect evidence <it> --lane <l>` |
|
|
39
42
|
| **Verdict** | rulings + per-AC PASS/FAIL/INVALID + KILL/CONTINUE | `architect section <it> verdict --from <f>` (later session) |
|
|
@@ -53,19 +56,21 @@ report in `build/<id>-<lane>/report.md`; `architect evidence` transcribes it
|
|
|
53
56
|
commit — `architect section` refuses to write a frozen section once frozen; only
|
|
54
57
|
Builder Prompt, Builder Report, and Verdict are appended after.
|
|
55
58
|
|
|
56
|
-
**The
|
|
59
|
+
**The project brief (`architecture/BRIEF.md`).** A project with a durable spec
|
|
57
60
|
carries one brief — numbered §sections (§1 goal, §2 constraints, … §N definition
|
|
58
61
|
of done) that span iterations. Every iteration's Grounds/Specification/Acceptance
|
|
59
62
|
Criteria/Verdict cites it as **BRIEF §N** (e.g. `(BRIEF §3.1)`), the way each gate
|
|
60
63
|
addresses its intent back to one frozen reference: the Acceptance Criteria table
|
|
61
64
|
carries a `Brief §` column, the Specification Objective cites it, the Verdict
|
|
62
65
|
reads "diff vs BRIEF §1/§3.3 — CONTINUE". Scaffold it with `architect brief new`.
|
|
63
|
-
The brief is frozen at the
|
|
64
|
-
decisions in `ARCHITECT.md`, never silent per-iteration drift. Discovery
|
|
66
|
+
The brief is frozen at the project level — edits to a §section are logged
|
|
67
|
+
decisions in `ARCHITECT.md`, never silent per-iteration drift. Discovery projects
|
|
65
68
|
that are still finding their shape defer the brief, cite per-iteration Grounds,
|
|
66
69
|
and promote the consolidated picture into BRIEF.md once it stabilizes.
|
|
67
70
|
|
|
68
|
-
Full rationale and citations: `DESIGN.md` in this skill's repo
|
|
71
|
+
Full rationale and citations: `docs/DESIGN.md` in this skill's repo — the
|
|
72
|
+
source-backed "why" behind these rules (the **R**-numbers and **§**-numbers cited
|
|
73
|
+
throughout this skill point into it). Exact dispatch
|
|
69
74
|
commands and the lane-prompt template: `dispatch.md` next to this file. To load
|
|
70
75
|
this system's vocabulary without running the loop (e.g. when working *on* the
|
|
71
76
|
skill), invoke the `/architect-vocabulary` skill — it is the glossary, not the
|
|
@@ -114,20 +119,20 @@ loop.
|
|
|
114
119
|
`AGENTS.md` → `README.md` → architecture docs. Learn the exact verification
|
|
115
120
|
gate (test/lint/typecheck/build commands) from docs or CI config.
|
|
116
121
|
- Once per environment: `claude --version` and confirm the builder model
|
|
117
|
-
resolves (`echo ok | claude -p --model
|
|
122
|
+
resolves (`echo ok | claude -p --model <builder-model> --max-turns 1`;
|
|
118
123
|
details in `dispatch.md`). First dispatch in a new environment is a canary —
|
|
119
124
|
confirm it starts cleanly before fanning out.
|
|
120
125
|
- Read `architecture/ARCHITECT.md` (the cross-iteration table of contents),
|
|
121
|
-
`architecture/BRIEF.md` if present (the durable §-numbered
|
|
126
|
+
`architecture/BRIEF.md` if present (the durable §-numbered project contract you
|
|
122
127
|
cite as BRIEF §N), and the iteration file `architecture/I<NN>-<name>.md` for any
|
|
123
128
|
in-flight iteration. If `ARCHITECT.md` is missing, run `architect init` (scaffolds
|
|
124
|
-
`architecture/ARCHITECT.md` and the `
|
|
129
|
+
`architecture/ARCHITECT.md` and the `project:` block in `space.yaml`,
|
|
125
130
|
commits). Keep the handoff a short TOC (~150 lines): TL;DR + repos in scope +
|
|
126
131
|
an iteration index pointing at each iteration file; per-iteration detail lives
|
|
127
132
|
in the iteration file, never duplicated into the handoff. `architect status`
|
|
128
|
-
prints
|
|
129
|
-
- **Space setup (first time):** `architect space new "
|
|
130
|
-
(
|
|
133
|
+
prints project state (iterations, freeze_shas, lanes, verdicts) at any point.
|
|
134
|
+
- **Space setup (first time):** `architect space new "Project Name" -r org/repo -r …`
|
|
135
|
+
(each repo is a repeatable `-r` flag after the title), then `architect init` inside
|
|
131
136
|
the space to scaffold `architecture/ARCHITECT.md`.
|
|
132
137
|
- Scale to the task: trivial fixes don't need the loop — say so and let the
|
|
133
138
|
human do it inline or in a normal session. The loop is for iteration-sized
|
|
@@ -166,11 +171,13 @@ re-derivation — the simplification that re-sees the shape is often the
|
|
|
166
171
|
architect's or human's to name.) Then
|
|
167
172
|
one iteration-level call: **KILL / CONTINUE**, with the single decisive reason,
|
|
168
173
|
written into the Verdict. For high-stakes iterations
|
|
169
|
-
(schema/API/persistence/security), add a review before the verdict.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
(schema/API/persistence/security), add a review before the verdict. The
|
|
175
|
+
architect reading the diff is already a stronger-model, fresh-context pass over
|
|
176
|
+
the builder's work — a capability-gap read whose independence depends on the
|
|
177
|
+
pairing: a same-lab architect/builder shares the builder's blind spots (so the
|
|
178
|
+
frozen gates stay the independent check), while a cross-vendor pairing is more
|
|
179
|
+
independent (see `docs/DESIGN.md` §1/R3). For an extra adversarial pass, pipe the
|
|
180
|
+
diff to a fresh read-only `claude -p` reviewer (command in `dispatch.md`) or a
|
|
174
181
|
fresh-context subagent prompted to break confidence — calibrated to flag only
|
|
175
182
|
correctness/requirement/invariant gaps with file:line evidence, no style.
|
|
176
183
|
|
|
@@ -194,7 +201,7 @@ Two scales, two routes:
|
|
|
194
201
|
researcher maps the topic, the orchestrator designs topic-specific parallel
|
|
195
202
|
researcher lanes, claims verified against sources, synthesized into a cited
|
|
196
203
|
report). Its report then distills into `architecture/BRIEF.md` §sections when
|
|
197
|
-
it is
|
|
204
|
+
it is project-scope (a durable contract that spans iterations), or the
|
|
198
205
|
iteration's **Grounds** section when it is iteration-scope.
|
|
199
206
|
- **Iteration scale** — run the inline fan-out below only when at least one
|
|
200
207
|
trigger holds: (a) the iteration depends on external APIs, libraries, or
|
|
@@ -214,8 +221,13 @@ and write Grounds. Findings without a source URL don't enter Grounds.
|
|
|
214
221
|
### 4. Spec the next iteration
|
|
215
222
|
|
|
216
223
|
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`)
|
|
224
|
+
`architecture/I<NN>-<name>.md` (it allocates the next ordinal **at spec-time** and records the
|
|
225
|
+
iteration in `space.yaml`). The iteration index in `ARCHITECT.md` holds only scaffolded
|
|
226
|
+
iterations — planned/queued work lives un-numbered in the ordered Backlog until it is
|
|
227
|
+
about to be specced. Pre-numbering planned work forces renumber churn every time priorities
|
|
228
|
+
reshuffle; the ordinal belongs to the work only once `architect new` is called.
|
|
229
|
+
|
|
230
|
+
Then write the **Specification** section with
|
|
219
231
|
`architect section <name> specification --from <file>` — the full delegation
|
|
220
232
|
contract, self-contained:
|
|
221
233
|
|
|
@@ -236,22 +248,47 @@ contract, self-contained:
|
|
|
236
248
|
repos are inherently disjoint; same-repo lanes with any file overlap run as
|
|
237
249
|
one. Each lane gets its own objective, output format, and boundaries. Most
|
|
238
250
|
iterations are one lane — fan out only when the work is genuinely parallel (a
|
|
239
|
-
cross-repo
|
|
251
|
+
cross-repo project often is). Two first-class patterns — runnable recipes in `dispatch.md`: **parallel +
|
|
252
|
+
fast-follow** (disjoint lanes integrate first; a fast-follow lane off
|
|
253
|
+
`project/<slug>` carries the seam — see `### Parallel + fast-follow`) and
|
|
254
|
+
**serial deferred judgment** (iterations run to gates-green with `architect
|
|
255
|
+
verdict` withheld; one later batch session judges each against its own frozen
|
|
256
|
+
AC — see `### Serial deferred judgment`).
|
|
240
257
|
- **Effort call** — thinking budget set in the lane-prompt via the escalation
|
|
241
258
|
keywords (`think hard` … `ultrathink`); default unattended builder work high,
|
|
242
259
|
downgrade a routine, tightly-specified lane (record which and why). Claude
|
|
243
260
|
Code has no per-invocation effort flag — see `dispatch.md`.
|
|
244
261
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
262
|
+
**Spike (probe) iterations.** When the open question is too uncertain for a
|
|
263
|
+
build — the repo can't answer it and routine API-verification won't resolve it
|
|
264
|
+
— spec a *spike* (probe) instead of a build iteration. A spike is
|
|
265
|
+
investigate-only: its deliverable is a **recommendation**, not merged behavior.
|
|
266
|
+
Its lane reads, experiments in throwaway scratch (never the worktree), and
|
|
267
|
+
writes a structured recommendation to its scratch report; there is usually
|
|
268
|
+
nothing to integrate. Acceptance Criteria are **read-bound** — gates are
|
|
269
|
+
minimal (at most suite-green confirming the probe broke nothing), because the
|
|
270
|
+
proof is the architect reading the recommendation against the question the spike
|
|
271
|
+
was set, not a runnable check; the AC names that question. The spike verdict
|
|
272
|
+
uses **ADOPT / REVISE / REJECT** (not KILL/CONTINUE): the architect transcribes
|
|
273
|
+
the recommendation into Builder Report, then the Verdict records the
|
|
274
|
+
disposition and, if adopted, names the follow-up build iteration it spawns. A
|
|
275
|
+
spike's CONTINUE means "recommendation accepted + disposition recorded." This
|
|
276
|
+
is distinct from discovery-scale research (`/architect-research`, which surveys
|
|
277
|
+
a whole topic): a spike is one iteration-sized, decision-oriented probe run
|
|
278
|
+
through the normal builder/lane machinery.
|
|
279
|
+
|
|
280
|
+
Then write the **Acceptance Criteria** section — prose conditions (AC1, AC2, …)
|
|
281
|
+
that the architect judges against, followed by a fenced ` ```gates ` block of
|
|
282
|
+
runnable checks (each gate carries `id`, `ac`, `cmd`, and `expect`; `cwd` is
|
|
283
|
+
optional) — and run `architect freeze <name>`. What must be frozen before
|
|
284
|
+
dispatch is the Acceptance Criteria: `architect freeze` lints the gates block
|
|
285
|
+
(absent or empty gates is allowed but warns; malformed fails), commits any
|
|
286
|
+
pending content in the frozen region (Grounds/Specification/Acceptance Criteria)
|
|
287
|
+
in one freeze commit, records the `freeze_sha` in `space.yaml`, and prints the
|
|
288
|
+
frozen AC back; **that commit is the freeze** ❄️ and is the last thing before
|
|
289
|
+
dispatch. You needn't sequence Grounds and Specification into separate commits
|
|
290
|
+
first — the freeze snapshots the whole frozen region and refuses to re-freeze
|
|
291
|
+
once a frozen section changed afterward.
|
|
255
292
|
|
|
256
293
|
### 5. Dispatch (one fresh `claude -p` per lane, worktree-isolated)
|
|
257
294
|
|
|
@@ -279,14 +316,23 @@ files and writes raw results to `build/<id>-<lane>/report.md` — it never
|
|
|
279
316
|
touches `architecture/`, so lanes never collide and the Acceptance Criteria
|
|
280
317
|
stay untouchable.
|
|
281
318
|
|
|
282
|
-
Do not block — end the turn or do other judgment work;
|
|
319
|
+
Do not block — end the turn or do other judgment work; long runs (30–60 minutes) are
|
|
283
320
|
normal. Print the lane-prompts too, so the human can run any lane in an
|
|
284
321
|
interactive `claude` session instead. Whenever you return to a running lane,
|
|
285
322
|
check liveness: the lane's `run.jsonl` must still be growing. If it has been
|
|
286
323
|
silent 15+ minutes on one in-flight command, follow "Stall detection and
|
|
287
324
|
rescue" in `dispatch.md` — kill the stuck child process, not the run.
|
|
288
325
|
|
|
289
|
-
|
|
326
|
+
When all lanes complete, **the dispatch session's job is done** — babysit
|
|
327
|
+
liveness per `dispatch.md` but do not run gates, transcribe evidence, integrate
|
|
328
|
+
lanes, or write the Verdict. Hand off to a fresh judging session (§6).
|
|
329
|
+
|
|
330
|
+
### 6. Post-flight, judge, and integrate (judging session)
|
|
331
|
+
|
|
332
|
+
A fresh judging session — not the session that dispatched (see §1 and §5) —
|
|
333
|
+
opens with the **MECHANICAL POST-FLIGHT CHECKS** and owns everything through the
|
|
334
|
+
Verdict and integration. Because this session did not dispatch, §1's
|
|
335
|
+
fresh-session-judgment is intact: it is the correct session to evaluate results.
|
|
290
336
|
|
|
291
337
|
`architect verify <iteration>` REPORTS (it never judges) per lane: frozen
|
|
292
338
|
sections untouched, no builder commits, scratch report present, in-bounds.
|
|
@@ -307,20 +353,30 @@ commits it, and echoes the builder's STATUS line. The builder never wrote into
|
|
|
307
353
|
|
|
308
354
|
**Then integrate** — you decide which lanes pass, the CLI does the git
|
|
309
355
|
mechanics. `architect integrate <iteration> --lanes <passing-set>` commits each
|
|
310
|
-
named lane on its branch and merges it `--no-ff` into the
|
|
311
|
-
|
|
356
|
+
named lane on its branch and merges it `--no-ff` into the stable
|
|
357
|
+
`project/<slug>` branch (slug derived from `space.title`; persistent and shared
|
|
358
|
+
across all iterations), in order; it **refuses** a lane that left builder
|
|
312
359
|
commits or wrote out-of-bounds, and stops on a merge conflict — which means the
|
|
313
360
|
lane plan wasn't disjoint, a spec defect: kill the conflicting lane and re-spec
|
|
314
|
-
it (never hand-resolve).
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
the iteration index in `architecture/ARCHITECT.md`
|
|
318
|
-
|
|
319
|
-
or `architect worktree remove <iteration> <lane>`), and
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
361
|
+
it (never hand-resolve). A cross-repo project yields one `project/<slug>` branch
|
|
362
|
+
per touched repo. `main` is never touched per-iteration — `--teardown` deletes
|
|
363
|
+
only the per-lane `lane/<iteration>-<lane>` branches and worktrees, never the
|
|
364
|
+
project branch. Update the iteration index in `architecture/ARCHITECT.md`
|
|
365
|
+
(recording the `project/<slug>` branch), remove the worktrees (`architect
|
|
366
|
+
integrate … --teardown`, or `architect worktree remove <iteration> <lane>`), and
|
|
367
|
+
commit the space.
|
|
368
|
+
|
|
369
|
+
**Run the frozen gates cold** — `architect gate <iteration>` runs the frozen
|
|
370
|
+
gate commands against the integration tree and streams raw output (a runner, not
|
|
371
|
+
a judge). Read the output, check the diff against the Specification and the
|
|
372
|
+
cited BRIEF §sections (per §2), then write the **Verdict** (`architect verdict
|
|
373
|
+
<iteration> continue|kill --from <file>`): disagreement rulings, per-AC
|
|
374
|
+
PASS/FAIL/INVALID, the KILL/CONTINUE call.
|
|
375
|
+
|
|
376
|
+
At project end, `architect land` prints the single `gh pr create --base main
|
|
377
|
+
--head project/<slug>` command per touched repo and writes a PR body to
|
|
378
|
+
`build/land/` — no push, no `gh` call; the human runs it from the repo when
|
|
379
|
+
the project is ready to ship.
|
|
324
380
|
|
|
325
381
|
## Maintenance
|
|
326
382
|
|
data/skill/architect/dispatch.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Builder dispatch reference
|
|
2
2
|
|
|
3
|
-
Verified against the `claude` CLI (Claude Code) headless mode
|
|
4
|
-
builder is `claude -p` (`--print`, the non-interactive
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
Verified against the `claude` CLI (Claude Code) headless mode — the reference
|
|
4
|
+
harness — June 2026. The builder is `claude -p` (`--print`, the non-interactive
|
|
5
|
+
headless mode) pinned to the configured builder model (`<builder-model>`) — a
|
|
6
|
+
cheaper model run headless via the same harness the architect uses. Key facts the
|
|
7
|
+
skill encodes: lane-prompts go in on **stdin** (Claude Code has no `@file`, and a
|
|
8
|
+
big quoted lane-prompt as a shell argument gets mangled); the model is pinned with
|
|
9
|
+
`--model <builder-model>` (a floating alias drifts to whatever ships next — pin
|
|
10
|
+
the full id); there is **no `-C`/working-dir flag**, so
|
|
10
11
|
per-lane dispatch `cd`s into the worktree; permissions are the **tool
|
|
11
12
|
allow/deny lists** (`--allowedTools`/`--disallowedTools`) plus
|
|
12
13
|
`--permission-mode`, not a sandbox; web access is the built-in
|
|
@@ -27,21 +28,22 @@ If a lane committed, treat the worktree as tampered: reset and re-dispatch.
|
|
|
27
28
|
|
|
28
29
|
**Preflight (once per environment):** run `claude --version`, and confirm the
|
|
29
30
|
builder model resolves with a one-shot canary
|
|
30
|
-
(`echo ok | claude -p --model
|
|
31
|
+
(`echo ok | claude -p --model <builder-model> --max-turns 1`). No API key —
|
|
31
32
|
the builder runs on your Claude plan — but note headless `claude -p` draws on
|
|
32
33
|
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
|
+
see `docs/DESIGN.md` §4). On the first real dispatch in a new environment, launch
|
|
34
35
|
ONE canary lane and confirm it starts cleanly before fanning anything out.
|
|
35
36
|
|
|
36
37
|
## Canonical dispatch — `architect dispatch <iteration> <lane>`
|
|
37
38
|
|
|
38
39
|
The canonical path is `architect dispatch <iteration> <lane>`. The tool
|
|
39
|
-
assembles the canonical `claude -p` argv, pins the model
|
|
40
|
+
assembles the canonical `claude -p` argv, pins the builder model (the lane's
|
|
41
|
+
configured model or the CLI's reference default; see `docs/DESIGN.md` §4),
|
|
40
42
|
reads the lane prompt from `build/<id>-<lane>/prompt.md` on stdin, and streams
|
|
41
43
|
`--output-format stream-json --verbose` output to
|
|
42
44
|
`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
|
|
44
|
-
|
|
45
|
+
call** (`run_in_background`) so your turn doesn't block for the full run (30–60
|
|
46
|
+
minutes is typical).
|
|
45
47
|
|
|
46
48
|
Write the lane's prompt to `build/<id>-<lane>/prompt.md` first (never pass a
|
|
47
49
|
big prompt as a shell argument — shells mangle quotes), then:
|
|
@@ -72,7 +74,7 @@ reaps those now-orphaned `claude` processes, and every lane dies at once with no
|
|
|
72
74
|
`result` — partial diffs, no reports (this exact failure has happened: three
|
|
73
75
|
lanes killed at the same second, zero output). One blocking dispatch per
|
|
74
76
|
background Bash tool keeps each lane attached to a harness-tracked task that
|
|
75
|
-
survives the full
|
|
77
|
+
survives the full run and reports completion per lane.
|
|
76
78
|
|
|
77
79
|
### What the tool runs under the hood
|
|
78
80
|
|
|
@@ -82,7 +84,7 @@ and as the manual fallback:
|
|
|
82
84
|
```bash
|
|
83
85
|
# write prompt to build/<id>-<lane>/prompt.md first, then:
|
|
84
86
|
( cd build/<id>-<lane>/wt && \
|
|
85
|
-
claude -p --model
|
|
87
|
+
claude -p --model <builder-model> \
|
|
86
88
|
--permission-mode acceptEdits \
|
|
87
89
|
--allowedTools 'Read,Edit,Write,Grep,Glob,Bash,WebSearch,WebFetch' \
|
|
88
90
|
--disallowedTools 'Bash(git commit:*),Bash(git push:*),Bash(git reset:*),Bash(git merge:*),Bash(git rebase:*),Bash(git checkout:*),Bash(git branch:*)' \
|
|
@@ -100,48 +102,153 @@ over the allow list (deny always takes precedence) as the runtime first line
|
|
|
100
102
|
against commits. Redirect stderr (`2>&1`) into the run-log so a dispatch error
|
|
101
103
|
lands somewhere instead of vanishing.
|
|
102
104
|
|
|
103
|
-
### Integration (
|
|
105
|
+
### Integration (judging session — after per-lane post-flight passes)
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
This block runs in the judging session, not the dispatch session — the dispatch
|
|
108
|
+
session's job ends when builders finish (see SKILL.md §5–6). You decide which
|
|
109
|
+
lanes pass; the CLI does the git mechanics. Canonical path:
|
|
106
110
|
|
|
107
111
|
```bash
|
|
108
112
|
architect integrate <iteration> --lanes <passing-set> # e.g. --lanes lane-a,lane-b
|
|
109
113
|
architect gate <iteration> # integration smoke (raw output; verdict stays yours)
|
|
110
114
|
architect integrate <iteration> --lanes <passing-set> --teardown # or remove worktrees + lane branches after
|
|
115
|
+
architect land # end of project: prints gh pr create --base main --head project/<slug>
|
|
111
116
|
```
|
|
112
117
|
|
|
113
118
|
`architect integrate` commits each named lane on its branch and merges it
|
|
114
|
-
`--no-ff` into the repo's `
|
|
115
|
-
**refuses** a lane that left
|
|
116
|
-
mechanical post-flight checks), and
|
|
117
|
-
= the lane plan wasn't disjoint = a
|
|
118
|
-
re-spec; don't hand-resolve builder
|
|
119
|
-
verdict** — `architect gate` streams
|
|
119
|
+
`--no-ff` into the repo's stable `project/<slug>` branch (slug of `space.title`,
|
|
120
|
+
persistent across all iterations), in order. It **refuses** a lane that left
|
|
121
|
+
builder commits or wrote out-of-bounds (the mechanical post-flight checks), and
|
|
122
|
+
aborts on a merge conflict. A merge conflict = the lane plan wasn't disjoint = a
|
|
123
|
+
spec defect: kill the conflicting lane and re-spec; don't hand-resolve builder
|
|
124
|
+
conflicts. It runs **no gates and makes no verdict** — `architect gate` streams
|
|
125
|
+
the raw gate output for you to judge. `--teardown` deletes only the per-lane
|
|
126
|
+
`lane/<iteration>-<lane>` branches and worktrees; it never deletes the
|
|
127
|
+
`project/<slug>` branch.
|
|
120
128
|
|
|
121
129
|
Under the hood / manual fallback (one lane shown):
|
|
122
130
|
|
|
123
131
|
```bash
|
|
124
|
-
|
|
132
|
+
# check out or create the project integration branch:
|
|
133
|
+
git -C repos/<repo> checkout project/<slug> 2>/dev/null || \
|
|
134
|
+
git -C repos/<repo> checkout -b project/<slug> <repo-base>
|
|
125
135
|
git -C build/<id>-<lane>/wt add -A
|
|
126
136
|
git -C build/<id>-<lane>/wt commit -m "lane <lane>: <what>"
|
|
127
137
|
git -C repos/<repo> merge --no-ff lane/<iteration>-<lane>
|
|
128
138
|
<run the gate commands> # integration smoke after every merge
|
|
129
139
|
architect worktree remove <iteration> <lane>
|
|
130
140
|
git -C repos/<repo> branch -d lane/<iteration>-<lane>
|
|
141
|
+
# at project end:
|
|
142
|
+
architect land # prints gh pr create --base main --head project/<slug>
|
|
131
143
|
```
|
|
132
144
|
|
|
145
|
+
### Parallel + fast-follow
|
|
146
|
+
|
|
147
|
+
Use when an iteration is near-disjoint — all but a thin shared seam (a
|
|
148
|
+
registration line, an index entry, a shared require). Route the seam into a
|
|
149
|
+
dedicated fast-follow lane; the parallel lanes stay genuinely disjoint and
|
|
150
|
+
integrate without conflict.
|
|
151
|
+
|
|
152
|
+
**Recipe:**
|
|
153
|
+
|
|
154
|
+
1. **Spec the seam out of the parallel lanes.** Assign the seam file(s) to the
|
|
155
|
+
fast-follow lane's `--touch` set and exclude them from every parallel lane's
|
|
156
|
+
touch-set — so the parallel set is disjoint by construction.
|
|
157
|
+
|
|
158
|
+
2. **Create worktrees and dispatch the parallel lanes** (off the repo base):
|
|
159
|
+
```bash
|
|
160
|
+
architect worktree add <repo> <iteration> lane-a
|
|
161
|
+
architect worktree add <repo> <iteration> lane-b
|
|
162
|
+
architect dispatch <iteration> lane-a # own background Bash call each
|
|
163
|
+
architect dispatch <iteration> lane-b
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
3. **Judging session — integrate the parallel set.** `project/<slug>` advances
|
|
167
|
+
to their merged tip:
|
|
168
|
+
```bash
|
|
169
|
+
architect integrate <iteration> --lanes lane-a,lane-b
|
|
170
|
+
architect gate <iteration>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
4. **Create the fast-follow lane off the integrated tip.** `--base` accepts any
|
|
174
|
+
git ref — passing `project/<slug>` roots the new worktree at the merged tip
|
|
175
|
+
(the keystone move):
|
|
176
|
+
```bash
|
|
177
|
+
architect worktree add <repo> <iteration> ff --base project/<slug>
|
|
178
|
+
architect dispatch <iteration> ff
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
5. **Judging session — integrate the fast-follow lane.** Because it descends
|
|
182
|
+
directly from `project/<slug>`, the `--no-ff` merge appends cleanly with no
|
|
183
|
+
conflicts:
|
|
184
|
+
```bash
|
|
185
|
+
architect integrate <iteration> --lanes ff
|
|
186
|
+
architect gate <iteration>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Invariant:** the parallel lanes must stay disjoint — a conflict among them is
|
|
190
|
+
still a disjointness defect (kill and re-spec; never hand-resolve). The
|
|
191
|
+
fast-follow lane is the sanctioned home for the seam and never conflicts because
|
|
192
|
+
it is a descendant of the integrated tip.
|
|
193
|
+
|
|
194
|
+
### Serial deferred judgment
|
|
195
|
+
|
|
196
|
+
Use when several iterations (or serial same-file lanes within one iteration)
|
|
197
|
+
should run to gates-green without a judging session between each — batching cold
|
|
198
|
+
AC judgment into one later session.
|
|
199
|
+
|
|
200
|
+
**Recipe:**
|
|
201
|
+
|
|
202
|
+
Per iteration, freeze and dispatch as normal. In a fresh judging session, run
|
|
203
|
+
post-flight, integrate, and gate — but **withhold `architect verdict`**:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# judging session (per iteration) — stop before verdict:
|
|
207
|
+
architect integrate <iteration> --lanes <passing-set>
|
|
208
|
+
architect gate <iteration>
|
|
209
|
+
# do NOT run: architect verdict <iteration> continue|kill
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Each integrated-but-unjudged iteration surfaces as `awaiting-verdict` in
|
|
213
|
+
`architect status`:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
architect status
|
|
217
|
+
# II Iteration … Verdict
|
|
218
|
+
# 03 some-feature … awaiting-verdict
|
|
219
|
+
# 04 another-feature … awaiting-verdict
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
One later batch judging session evaluates all `awaiting-verdict` iterations,
|
|
223
|
+
oldest-first. For each: read its own frozen AC from its freeze commit, run its
|
|
224
|
+
gates cold, and record the verdict:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
architect gate <iteration> # run the frozen gates cold
|
|
228
|
+
architect verdict <iteration> continue # or: kill
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**§1 preserved:** each verdict is cold and fresh-session — the batch judging
|
|
232
|
+
session did not dispatch any of these iterations, so the §1
|
|
233
|
+
fresh-session-judgment rule holds for every verdict in the batch.
|
|
234
|
+
|
|
235
|
+
**Deliberate risk:** iteration N+1 integrated on top of N's not-yet-judged work
|
|
236
|
+
rests on a foundation that a later KILL at N would revert. Accept this coupling
|
|
237
|
+
only consciously, and always judge oldest-first so a KILL stops you before you
|
|
238
|
+
compound it.
|
|
239
|
+
|
|
133
240
|
## Operating guidance
|
|
134
241
|
|
|
135
242
|
- Background each lane as its own harness task and let the **per-lane
|
|
136
|
-
completion notification** bring you back (
|
|
243
|
+
completion notification** bring you back (long runs — 30–60 minutes — are normal); read
|
|
137
244
|
`build/<id>-<lane>/run.jsonl` and the repo state afterwards. Do not write a
|
|
138
245
|
blocking `while pgrep …; sleep` wait loop as a Bash command — that is itself
|
|
139
246
|
a launcher that ties up a turn. When you return to a lane, check liveness via
|
|
140
247
|
run-log growth (the stall rules below still apply unchanged).
|
|
141
248
|
- Pin the model explicitly. The tool does this automatically (`--model
|
|
142
|
-
|
|
143
|
-
interactively, but automations pin the full id so a
|
|
144
|
-
change builder behavior mid-project.
|
|
249
|
+
<builder-model>`). A floating alias (a bare "latest"/tier tag) drifts to
|
|
250
|
+
whatever ships next — fine interactively, but automations pin the full id so a
|
|
251
|
+
model bump can't silently change builder behavior mid-project.
|
|
145
252
|
- Effort = thinking budget. Claude Code has no per-invocation effort flag the
|
|
146
253
|
way Codex exposed `model_reasoning_effort`; the builder sets thinking depth
|
|
147
254
|
**in the block** via the escalation keywords (`think` < `think hard` <
|
|
@@ -166,16 +273,17 @@ git -C repos/<repo> branch -d lane/<iteration>-<lane>
|
|
|
166
273
|
`claude -p --continue …`, never a `&` loop (a `&` launcher orphans the
|
|
167
274
|
resumed lanes exactly as it does fresh ones). Never resume across iterations —
|
|
168
275
|
every iteration gets a fresh context.
|
|
169
|
-
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
architect
|
|
173
|
-
|
|
174
|
-
|
|
276
|
+
- Capability-gap review gate (high-stakes iterations): the architect outranks the
|
|
277
|
+
builder, so the architect reading the diff is already a stronger-model,
|
|
278
|
+
fresh-context pass over it. How independent that read is depends on the pairing
|
|
279
|
+
— a same-lab architect/builder shares the builder's blind spots (the frozen
|
|
280
|
+
gates stay the independent check), a cross-vendor pairing is more independent
|
|
281
|
+
(see `docs/DESIGN.md` §1/R3). For an extra adversarial pass, pipe the
|
|
282
|
+
instruction + diff to a fresh read-only reviewer:
|
|
175
283
|
```bash
|
|
176
284
|
{ echo "Review this diff against the spec. Flag ONLY correctness/requirement/invariant gaps with file:line evidence. No style."; \
|
|
177
285
|
git -C <repo-root> diff <base>...HEAD; } \
|
|
178
|
-
| claude -p --model
|
|
286
|
+
| claude -p --model <builder-model> --allowedTools 'Read,Grep,Glob'
|
|
179
287
|
```
|
|
180
288
|
- `build/` is already gitignored by the space, so no extra `.gitignore` entry
|
|
181
289
|
is needed. Scratch never reaches the space repo; only `architecture/` is
|
|
@@ -287,11 +395,11 @@ against them, do not edit or work around) ===
|
|
|
287
395
|
|
|
288
396
|
## Builder-side standing setup (one time per machine/repo)
|
|
289
397
|
|
|
290
|
-
- The builder is the same `claude` binary as the architect
|
|
291
|
-
nothing extra to install. `architect dispatch` pins
|
|
292
|
-
(`--model
|
|
293
|
-
is fine interactively, but automations pin it explicitly so a
|
|
294
|
-
silently swap the builder.
|
|
398
|
+
- The builder is the same `claude` binary as the architect (reference harness),
|
|
399
|
+
running a cheaper model — nothing extra to install. `architect dispatch` pins
|
|
400
|
+
the model per dispatch (`--model <builder-model>`); a `~/.claude/settings.json`
|
|
401
|
+
`"model"` default is fine interactively, but automations pin it explicitly so a
|
|
402
|
+
default can't silently swap the builder.
|
|
295
403
|
- Repo `CLAUDE.md` is the builder's standing context — Claude Code loads it
|
|
296
404
|
root-down automatically. Put exact build/test commands and repo gotchas there;
|
|
297
405
|
the loop's PHASE rules stay in the dispatch block so they version with the
|