space-architect 3.0.0 → 4.0.0

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.
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "pastel"
4
4
  require "dry/monads"
5
- require "space_src/cli"
6
5
  require "space_src/cli/options"
7
6
  require "space_src/cloner"
8
7
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "pastel"
4
4
  require "yaml"
5
- require "space_src/cli"
6
5
  require "space_src/ui/mode"
7
6
  require "space_src/cli/options"
8
7
 
@@ -3,7 +3,6 @@
3
3
  require "pastel"
4
4
  require "fileutils"
5
5
  require "dry/monads"
6
- require "space_src/cli"
7
6
  require "space_src/ui/mode"
8
7
  require "space_src/cli/options"
9
8
  require "space_src/launchd/agent"
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "pastel"
4
4
  require "dry/monads"
5
- require "space_src/cli"
6
5
  require "space_src/ui/mode"
7
6
  require "space_src/cli/options"
8
7
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "pastel"
4
4
  require "dry/monads"
5
- require "space_src/cli"
6
5
  require "space_src/ui/mode"
7
6
  require "space_src/cli/options"
8
7
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "space_src/cli"
4
3
  require "space_src/shell_integration"
5
4
 
6
5
  module Space::Src
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pastel"
4
- require "space_src/cli"
5
4
  require "space_src/ui/mode"
6
5
  require "space_src/cli/options"
7
6
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/monads"
4
- require "space_src/cli"
5
4
  require "space_src/cli/repo" # for Repo::Helpers.parse_ref
6
5
  require "space_src/cli/options"
7
6
  require "space_src/ui/mode"
data/lib/space_src/cli.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/cli"
4
- require "space_src"
5
4
  require "space_src/migration"
6
5
 
7
6
  module Space::Src
@@ -121,8 +121,11 @@ loop.
121
121
  gate (test/lint/typecheck/build commands) from docs or CI config.
122
122
  - Once per environment: `claude --version` and confirm the builder model
123
123
  resolves (`echo ok | claude -p --model <builder-model> --max-turns 1`;
124
- details in `dispatch.md`). First dispatch in a new environment is a canary —
125
- confirm it starts cleanly before fanning out.
124
+ details in `dispatch.md`). Past that one-time check, every foreground dispatch
125
+ self-verifies it prints a liveness line naming the streamed model and
126
+ confirming the run log is growing (a WARN line instead if the streamed model
127
+ disagrees with the pin or the log isn't growing) — so no lone lane needs
128
+ launching-and-watching before the fan-out.
126
129
  - Read `architecture/ARCHITECT.md` (the cross-iteration table of contents),
127
130
  `architecture/BRIEF.md` if present (the durable §-numbered project contract you
128
131
  cite as BRIEF §N), and the iteration file `architecture/I<NN>-<name>.md` for any
@@ -245,9 +248,17 @@ contract, self-contained:
245
248
  task.
246
249
  - **Lane plan** — split the iteration into 1–4 parallel lanes, each declaring
247
250
  its **target repo + file-touch set, checked for overlap**: name the repo
248
- (`repos/<repo>`) and every file each lane may touch. Lanes in *different*
249
- repos are inherently disjoint; same-repo lanes with any file overlap run as
250
- one. Each lane gets its own objective, output format, and boundaries. Most
251
+ (`repos/<repo>`) and every file each lane may touch. The machine-readable
252
+ declaration lives in a fenced ` ```lanes ` block in the Specification — one
253
+ entry per lane (`name`, `repo`, `touch` globs) the single frozen source of
254
+ truth `architect freeze` records into `space.yaml` and `architect provision`
255
+ materializes. The touch-set now lives *with* the frozen spec by design: it
256
+ closes the drift where a `worktree add --touch` flag could diverge from the
257
+ spec's intent. The scaffold ships a commented ` ```lanes ` stub in the
258
+ Specification (see `templates/iteration.md.erb`) — uncomment it. Lanes in
259
+ *different* repos are inherently disjoint; same-repo lanes with any file
260
+ overlap run as one. Each lane gets its own objective, output format, and
261
+ boundaries. Most
251
262
  iterations are one lane — fan out only when the work is genuinely parallel (a
252
263
  cross-repo project often is). Two first-class patterns — runnable recipes in `dispatch.md`: **parallel +
253
264
  fast-follow** (disjoint lanes integrate first; a fast-follow lane off
@@ -293,13 +304,24 @@ once a frozen section changed afterward.
293
304
 
294
305
  ### 5. Dispatch (one fresh `claude -p` per lane, worktree-isolated)
295
306
 
296
- Per the mechanics in `dispatch.md`:
297
-
298
- - **1 lane** → dispatch in the target repo's checkout (`repos/<repo>`).
299
- - **2–4 lanes** → `architect worktree add <repo> <iteration> <lane>
300
- [--base <repo-base>]` per lane (creates `build/<id>-<lane>/wt` off the target
301
- repo's base commit a repo commit, distinct from the freeze, which is a
302
- space commit — and records it in `space.yaml`).
307
+ Per the mechanics in `dispatch.md`. The lane lifecycle is **declare → freeze →
308
+ provision → write prompts → dispatch** — every lane gets a worktree; there is no
309
+ dispatch-in-the-checkout path:
310
+
311
+ - **Declare** at spec time, each lane is one entry in the Specification's
312
+ fenced ` ```lanes ` block (§4): `name`, `repo`, `touch` globs.
313
+ - **Freeze**`architect freeze` parses that block and records each lane
314
+ (name, repo, touch_set) into `space.yaml`.
315
+ - **Provision** — `architect provision <iteration>` materializes every declared
316
+ lane's worktree + `lane/<id>-<lane>` branch in one shot, each off the resolved
317
+ base (`--base` override, else `project/<slug>` when it exists, else the repo's
318
+ default branch — a repo commit, distinct from the freeze, which is a space
319
+ commit) and recorded in `space.yaml`; it is idempotent, and `--lane <name>`
320
+ provisions a single lane. The manual `architect worktree add` it wraps stays
321
+ registered as an internal primitive for edge cases — not a step you run.
322
+ - `dispatch`, `integrate`, and `gate` auto-materialize a lane whose worktree is
323
+ missing from its frozen declaration, so a lane you didn't pre-provision can't
324
+ dead-end the flow.
303
325
 
304
326
  Assemble each lane's lane-prompt (the template in `dispatch.md` + this lane's
305
327
  section of the Specification + the frozen Acceptance Criteria) and write it to
@@ -363,9 +385,9 @@ it (never hand-resolve). A cross-repo project yields one `project/<slug>` branch
363
385
  per touched repo. `main` is never touched per-iteration — `--teardown` deletes
364
386
  only the per-lane `lane/<iteration>-<lane>` branches and worktrees, never the
365
387
  project branch. Update the iteration index in `architecture/ARCHITECT.md`
366
- (recording the `project/<slug>` branch), remove the worktrees (`architect
367
- integrate … --teardown`, or `architect worktree remove <iteration> <lane>`), and
368
- commit the space.
388
+ (recording the `project/<slug>` branch), remove the provisioned worktrees
389
+ (`architect integrate … --teardown`, or `architect worktree remove <iteration>
390
+ <lane>`), and commit the space.
369
391
 
370
392
  **Run the frozen gates cold** — `architect gate <iteration>` runs the frozen
371
393
  gate commands against the integration tree and streams raw output (a runner, not
@@ -27,12 +27,15 @@ pattern match), so the post-flight `git log` is what the loop actually trusts.
27
27
  If a lane committed, treat the worktree as tampered: reset and re-dispatch.
28
28
 
29
29
  **Preflight (once per environment):** run `claude --version`, and confirm the
30
- builder model resolves with a one-shot canary
30
+ builder model resolves with a one-shot
31
31
  (`echo ok | claude -p --model <builder-model> --max-turns 1`). No API key —
32
32
  the builder runs on your Claude plan — but note headless `claude -p` draws on
33
33
  the Agent SDK credit pool (separate from interactive usage since June 15 2026;
34
- see `docs/DESIGN.md` §4). On the first real dispatch in a new environment, launch
35
- ONE canary lane and confirm it starts cleanly before fanning anything out.
34
+ see `docs/DESIGN.md` §4). Past that one-time check, no dispatch needs a manual
35
+ start-check: every foreground dispatch self-verifies. Shortly after launch it
36
+ prints a liveness line to stderr naming the streamed model and confirming the
37
+ run log is growing — or a WARN line instead when the streamed model disagrees
38
+ with the pinned `<builder-model>` or the log isn't growing.
36
39
 
37
40
  ## Canonical dispatch — `architect dispatch <iteration> <lane>`
38
41
 
@@ -49,23 +52,30 @@ Write the lane's prompt to `build/<id>-<lane>/prompt.md` first (never pass a
49
52
  big prompt as a shell argument — shells mangle quotes), then:
50
53
 
51
54
  ```bash
52
- # single-lane iteration — run from the space root
55
+ # single-lane iteration — run from the space root; dispatch runs in the lane's
56
+ # provisioned worktree (materialized on demand from the frozen declaration)
53
57
  architect dispatch <iteration> <lane>
54
58
  ```
55
59
 
56
- For multi-lane iterations, create worktrees first (one per lane), then dispatch
57
- each lane from its worktree:
60
+ For multi-lane iterations, materialize every declared lane in one shot with
61
+ `architect provision`, then dispatch each lane from its worktree:
58
62
 
59
63
  ```bash
60
- # per lane:
61
- architect worktree add <repo> <iteration> <lane> [--base <repo-base>]
62
- architect dispatch <iteration> <lane>
64
+ architect provision <iteration> # all declared lanes: worktree + lane/<id>-<lane> branch
65
+ architect dispatch <iteration> lane-a # own background Bash call each
66
+ architect dispatch <iteration> lane-b
63
67
  ```
64
68
 
65
- `architect worktree add` creates `build/<id>-<lane>/wt` off the target repo's
66
- base commit (a repo commit — distinct from the freeze, which is a space
67
- commit), adds it with a `lane/<iteration>-<lane>` branch, and records it in
68
- `space.yaml`.
69
+ `architect provision` reads the frozen lane declarations from `space.yaml` and,
70
+ per lane, creates `build/<id>-<lane>/wt` off the resolved base (`--base`
71
+ override, else `project/<slug>` when it exists, else the repo's default branch —
72
+ a repo commit, distinct from the freeze, which is a space commit), adds it with a
73
+ `lane/<iteration>-<lane>` branch, and records it in `space.yaml`. It is
74
+ idempotent (`--lane <name>` provisions a single lane), and wraps the
75
+ `architect worktree add` primitive — still registered for edge cases, not a step
76
+ in the flow. `dispatch`, `integrate`, and `gate` also lazily materialize a lane
77
+ whose worktree is missing from its frozen declaration, so the flow can't
78
+ dead-end on a missing worktree.
69
79
 
70
80
  Issue each dispatch as its **own background Bash tool call** — one call per
71
81
  lane. Never use a shell `&` loop. A `for … & done` launcher is a *launcher*
@@ -157,10 +167,12 @@ integrate without conflict.
157
167
  fast-follow lane's `--touch` set and exclude them from every parallel lane's
158
168
  touch-set — so the parallel set is disjoint by construction.
159
169
 
160
- 2. **Create worktrees and dispatch the parallel lanes** (off the repo base):
170
+ 2. **Provision and dispatch the parallel lanes** (off the repo base). Provision
171
+ only the parallel lanes by name — leave the fast-follow lane unmaterialized
172
+ until step 4, so it can root at the integrated tip:
161
173
  ```bash
162
- architect worktree add <repo> <iteration> lane-a
163
- architect worktree add <repo> <iteration> lane-b
174
+ architect provision <iteration> --lane lane-a
175
+ architect provision <iteration> --lane lane-b
164
176
  architect dispatch <iteration> lane-a # own background Bash call each
165
177
  architect dispatch <iteration> lane-b
166
178
  ```
@@ -172,11 +184,11 @@ integrate without conflict.
172
184
  architect gate <iteration>
173
185
  ```
174
186
 
175
- 4. **Create the fast-follow lane off the integrated tip.** `--base` accepts any
176
- git ref — passing `project/<slug>` roots the new worktree at the merged tip
177
- (the keystone move):
187
+ 4. **Provision the fast-follow lane off the integrated tip.** `--base` accepts
188
+ any git ref — passing `project/<slug>` roots the new worktree at the merged
189
+ tip (the keystone move); `--lane ff` provisions just that lane:
178
190
  ```bash
179
- architect worktree add <repo> <iteration> ff --base project/<slug>
191
+ architect provision <iteration> --lane ff --base project/<slug>
180
192
  architect dispatch <iteration> ff
181
193
  ```
182
194
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: space-architect
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Jacobs
@@ -272,6 +272,7 @@ files:
272
272
  - lib/space_core/cli/helpers.rb
273
273
  - lib/space_core/cli/init.rb
274
274
  - lib/space_core/cli/list.rb
275
+ - lib/space_core/cli/loop_status.rb
275
276
  - lib/space_core/cli/new.rb
276
277
  - lib/space_core/cli/pack.rb
277
278
  - lib/space_core/cli/path.rb