space-architect 2.0.0.rc1 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3022f9e726e74aa3edeca3004af6e3af1a7872bd709fb0da75fbeee5fcf33d30
4
- data.tar.gz: f3f2aef35926a99ba14209c550fb0533da777561df7348d4e0bfce19ee240f86
3
+ metadata.gz: a5828b73d6d58a9d14547e9d8be9e7f8a734212c7e7356a01149c4c9cbeadd9c
4
+ data.tar.gz: a8c75e611270a1ff40f0cfd55753549d6972ae2d6af4999695b688f35942bb88
5
5
  SHA512:
6
- metadata.gz: 480cd0f4dbb96653f6c4db809755e8968cf4bb96311472dde9a2e5172d22526589d20ca522bd028180eac6d2c772e41e80236474da9f8ab2b4597128227be21b
7
- data.tar.gz: 7089e119fe3a0b7bee92facd78dd691ddcf84daae4dc783dda80c2513042ab1d1e1767b5afd099012dd4029c9e0a126c8ea3f7c5b48fe3d056bc8a7b7c7a03a8
6
+ metadata.gz: a9ff6975fce076eb36bfcd398129551182662830c1f433dfd3d57c375fa32d0ed8b547c46aca5d3959742a454c7523335109ab3ef5d406c8bd5ea6221797b8f4
7
+ data.tar.gz: 9f20d1e71cc27260fa7e8f1c3090c95b670ae9edea2d9394510e18ddfb6d9543c15655a2ecc2532cd3ba73e4f0250b24a55e00b838b475d64d9331f518d197dd
data/CHANGELOG.md CHANGED
@@ -5,62 +5,258 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [2.0.0] - 2026-06-27
8
+ ## [2.0.0] - 2026-07-01
9
9
 
10
- Re-architects the single `architect` gem into three composable binaries —
11
- **`space` · `architect` · `src`** — over clean `Space::Core` / `Space::Architect`
12
- / `Space::Src` library seams. End-user CLI behaviour is preserved byte-for-byte
13
- except where called out under **Changed** below.
10
+ A ground-up release across four fronts:
11
+
12
+ 1. **Three composable binaries** — `space` · `architect` · `src` over clean
13
+ `Space::Core` / `Space::Architect` / `Space::Src` library seams (retiring the
14
+ single `SpaceArchitect` namespace).
15
+ 2. **An overhauled Architect Loop** — the "mission" vocabulary becomes
16
+ "project," Acceptance Criteria gain a structured, runnable `gates` block, and
17
+ the loop grows first-class verbs (`gate`, `verdict`, `land`, `ground`), an
18
+ integration-branch-by-default workflow, and a SessionStart re-grounding hook.
19
+ 3. **Reproducible space containers** — `space pack` / `build` / `run` turn a
20
+ space into an OCI image.
21
+ 4. **`space-server`** — a new Hanami + React web app to import, view, and share
22
+ Architect spaces and AI-agent transcripts. **It ships in the repo, not in the
23
+ gem** (the gem packages only `lib/`, `exe/`, and `skill/`).
24
+
25
+ This is a major, breaking release for both CLI users and library embedders — see
26
+ the **BREAKING** items under Changed. The repository is now a monorepo; the
27
+ `space-architect` gem lives at the root and the server under `server/`.
14
28
 
15
29
  ### Added
16
30
 
31
+ #### CLI — binaries, research, and dispatch
32
+
17
33
  - **`src` — standalone evergreen-engine binary** (`exe/src`). `repo`, `org`,
18
34
  `sync`, `status`, `config`, `daemon`, and `clone`, plus single-token fuzzy
19
35
  navigation (`src <query>` resolves to a repo and honours the `cd` contract)
20
- and native fish shell integration with completions. Previously this engine was
21
- reachable only as `architect src …`; it is now a first-class binary in its own
22
- right (and still forwarded by `architect src …`).
36
+ and native fish shell integration with completions. Previously reachable only
37
+ as `architect src …`; now a first-class binary (and still forwarded by
38
+ `architect src …`).
23
39
  - **`architect research dispatch | status | wait`** — first-class parallel,
24
- read-only research lanes. Detached `claude -p` researchers (no Edit/Write/Bash)
25
- run in the background; a socketry/async fiber mux tails each lane's `run.jsonl`
26
- and extracts its report. The architect verifies claims and writes Grounds.
40
+ read-only research lanes. Detached `claude -p` researchers restricted to
41
+ `Read,Grep,Glob,WebSearch,WebFetch` (no Edit/Write/Bash) run in the background;
42
+ a socketry/async fiber mux tails each lane's `run.jsonl` and extracts its
43
+ report. The architect verifies claims and writes Grounds.
27
44
  - **`architect dispatch --detach`** — detached builder launch that returns
28
45
  immediately with a PID and survives the harness wall-clock reap; poll the
29
46
  lane's report for completion.
47
+ - **`architect dispatch` HTTP push** — stream a builder's live output to an
48
+ ingest server. `--push-url <url> --push-token <tok>` POSTs the NDJSON stream to
49
+ an existing run's ingest URL; `--push-host <host> --push-token <tok>` first
50
+ creates the run (`POST <host>/runs`), derives `<host>/runs/<id>/ingest`, streams
51
+ there, and prints the run id. `--push-url`/`--push-host` are mutually exclusive,
52
+ both require `--push-token` (Bearer auth), and neither combines with `--detach`.
53
+ The stream is teed to the run log and the endpoint concurrently over fibers.
54
+ - **`architect dispatch --timeout`** — wall-clock timeout for a builder (default
55
+ `14400`s / 4h; `0` disables; foreground only). A wedged builder's process group
56
+ is escalated TERM→grace→KILL and reported as timed out (exit 124).
57
+
58
+ #### Architect Loop — gates and new verbs
59
+
60
+ - **A fenced ` ```gates ` block inside each iteration's Acceptance Criteria.**
61
+ Runnable checks are now structured YAML gates — `id`, `ac` (which prose AC it
62
+ backs), `cmd`, optional `cwd`, an `expect` block (`exit_code` / `stdout_match`
63
+ / `threshold`), and an optional per-gate `timeout` (seconds; default 900),
64
+ replacing the old free-text AC table.
65
+ - **Gate linting at freeze time** (`GateLint`, via dry-validation). `architect
66
+ freeze` validates the gates block: malformed gates fail the freeze; absent or
67
+ empty gates warn but are allowed (prose-judged iterations); duplicate ids, bad
68
+ threshold operators, and non-single-capture regexes are caught.
69
+ - **`architect gate` — a gate runner.** Runs the frozen Acceptance-Criteria gate
70
+ commands (always read from the freeze commit, never the working copy) in the
71
+ resolved repo or lane worktree, scoring captured output against each `expect`
72
+ block with a pure `GateEvaluator`.
73
+ - **`architect verdict <iteration> continue|kill`** — records the decision in the
74
+ `project:` block and writes the `## Verdict` prose in one commit; the first tool
75
+ that actually persists a verdict decision.
76
+ - **`architect land`** — generates the end-of-project PR for each integrated repo
77
+ (writes a `build/land/<repo>-pr-body.md` and prints the `gh pr create …`
78
+ invocation). Side-effect-free: no git write, no push, no `gh` call.
79
+ - **`architect ground` + a SessionStart re-grounding hook.** `architect init`
80
+ now also writes `.claude/settings.json` registering SessionStart hooks
81
+ (startup/clear/resume) that run `architect ground`, re-emitting `ARCHITECT.md`,
82
+ `BRIEF.md`, and the in-flight iteration file so a freshly cleared or resumed
83
+ session self-orients. A worktree guard suppresses grounding inside builder
84
+ worktrees, so builders are never fed architect context.
85
+
86
+ #### Space containers (require a `container` / OCI runtime)
87
+
88
+ - **`space pack`** — generate a portable OCI build context for the current space
89
+ (writes `Dockerfile`, `entrypoint.sh`, and a `.dockerignore` into `build/oci/`,
90
+ overridable with `-o/--output`) and print a build hint.
91
+ - **`space build`** — pack, then `container build`, tagging reproducibly by commit
92
+ as `<space-id>:<git-short-sha>` plus `<space-id>:latest` (SHA suffixed `-dirty`
93
+ when the tree is dirty).
94
+ - **`space run`** — `container run --rm` on `<space-id>:latest`, defaulting to an
95
+ interactive login shell or a passed command, auto-detecting TTY (`--tty` to
96
+ force). Forwards `ANTHROPIC_API_KEY` / `CLAUDE_CODE_OAUTH_TOKEN` /
97
+ `ANTHROPIC_BASE_URL` from the host only if set — credentials are never baked
98
+ into a layer. (All three commands are also reachable as `architect space …`.)
99
+ - **Declarative `pack:` config in `space.yaml`.** `pack.provision` — build-time
100
+ provisioning scripts (space-relative) emitted as ordered `RUN` steps;
101
+ `pack.persist` — absolute guest paths bind-mounted from `.state/<guest>` so
102
+ state survives across runs. Provision paths are validated (must exist, be
103
+ relative, and stay within the space root).
104
+ - **Git baked into the image + in-container worktrees.** The image copies the
105
+ whole space tree (repos and history) into `/space`, installs the pinned
106
+ in-space `space-architect`, seeds a default git identity, and sets `git
107
+ safe.directory '*'` so `git worktree` works on the root-owned tree.
108
+
109
+ #### `space-server` (repo, not shipped in the gem)
110
+
111
+ - **A Hanami web app to view and share Architect work** (`server/`). Imports an
112
+ Architect space and renders its iterations against the canonical six-section
113
+ shape (Grounds · Specification · Acceptance Criteria · Builder Prompt · Builder
114
+ Report · Verdict), alongside that space's runs and artifacts; separately ingests
115
+ exported AI chat transcripts (Claude Code, Codex, pi, opencode) for markdown/code
116
+ browsing, per-turn annotation, and read-only public sharing.
117
+ - **Architect-space data model + `SpaceImporter`.** New `spaces` / `iterations` /
118
+ `artifacts` tables and a `rake space:import[/path]` task that reads a space's
119
+ `space.yaml`, markdown artifacts, and builder run streams (`build/*/run.jsonl`)
120
+ into Postgres — idempotent, keyed by slug/ordinal/path.
121
+ - **A stitched per-space read view (Inertia/React).** `Spaces/Index` and
122
+ `Spaces/Show` interleave iterations and architect sessions into one
123
+ timestamp-ordered timeline with inline transcript cards and run/artifact
124
+ drill-downs; imported timestamps are timezone-faithful and each run carries a
125
+ `harness · model` badge.
126
+ - **Live agent-run streaming.** Machine clients push run events over Bearer token
127
+ auth; browsers replay them live over SSE. Pairs with the CLI's
128
+ `architect dispatch --push-*`.
129
+ - **Session normalizers for architect transcripts.** `Normalizer::ClaudeSession`
130
+ understands Claude Code's `~/.claude/projects/**.jsonl` session-log shape and
131
+ `Normalizer::OpencodeSession` reads opencode's SQLite DB read-only, both
132
+ emitting the same normalized event stream as the builder-dispatch parser.
133
+ - **Five in-tree Hanami extension gems** under `server/gems/*` (each path-loaded,
134
+ with its own gemspec and tests): `hanami-healthcheck` (a `/up` endpoint),
135
+ `inertia-hanami` (an Inertia.js protocol adapter), `hanami-credentials`
136
+ (encrypted credentials store), `hanami-force-ssl` (Rack 3 HTTPS/HSTS
137
+ middleware), and `vite-hanami` (Vite tag helpers + dev-server proxy).
30
138
 
31
139
  ### Changed
32
140
 
33
- - **BREAKING — three binaries over clean seams.** `space` now runs on
34
- `Space::Core` alone (`exe/space`); `architect` forwards `space …` / `src …` to
35
- their surfaces; `src` is its own executable (`exe/src`). The gem now installs
36
- three executables (`architect`, `space`, `src`) where 1.3.0 installed two.
141
+ - **BREAKING — three binaries over clean seams.** `space` runs on `Space::Core`
142
+ alone (`exe/space`); `architect` (`exe/architect`) forwards `space …` / `src …`
143
+ to their surfaces; `src` is its own executable. The gem now installs three
144
+ executables where 1.3.0 installed two.
37
145
  - **BREAKING — Ruby namespace overhaul (library embedders).** The single
38
146
  `SpaceArchitect::*` module is retired and split into `Space::Core::*`
39
- (foundation: config, state, XDG, terminal, git/mise clients, space store),
40
- `Space::Architect::*` (mission, harness, dispatch, research), and
41
- `Space::Src::*` (the evergreen engine). Update any `require`s and constant
42
- references. The CLI surface is unaffected.
147
+ (config, state, XDG, terminal, git/mise clients, space store),
148
+ `Space::Architect::*` (project, harness, dispatch, research), and
149
+ `Space::Src::*` (the evergreen engine). No `SpaceArchitect` constant remains —
150
+ update any `require`s and constant references. The CLI surface is unaffected.
151
+ - **BREAKING — "mission" is now "project," with no back-compat shim.** The
152
+ `space.yaml` project-state key `architect:` becomes `project:`; existing spaces
153
+ are not read until the key is renamed. The core class `ArchitectMission` becomes
154
+ `ArchitectProject`, all user-facing output follows (`Project ready:` /
155
+ `Project status:`), and the default integration branch is `project/<slug>`.
156
+ No deprecation alias is provided.
43
157
  - **BREAKING — `repo-tender` absorbed into `space-src`.** The vendored
44
- `repo-tender` engine is gone; its functionality now ships as `Space::Src`.
45
- State migrates automatically from `$XDG_STATE_HOME/repo-tender/` to
46
- `$XDG_STATE_HOME/space-src/` on first run (data-preserving).
47
- - **BREAKING — `space new` takes repeatable `-r` flags.** Repos are now passed
48
- as `space new "My Space" -r org/repo -r example/alpha` instead of as positional
49
- arguments after the title. Repeated `-r` accumulate; the comma form still works.
50
- - **Colourful global help** for `space` and `architect` (`--help` listing), with
51
- global colour options (`--color` / `--colors`) inherited by every command via a
52
- shared `BaseCommand`. The `src` binary keeps its own `--plain` / `--json`
53
- output system.
54
- - `space --version` now reports the space-surface (`Space::Core`) version
55
- independently of the architect mission tooling.
158
+ `repo-tender` engine is gone; its functionality now ships as `Space::Src`. State
159
+ migrates automatically from `$XDG_STATE_HOME/repo-tender/` to
160
+ `$XDG_STATE_HOME/space-src/` (and the launchd label likewise) on first run,
161
+ data-preserving.
162
+ - **BREAKING — `space new` takes repeatable `-r` flags.** Repos are passed as
163
+ `space new "My Space" -r org/repo -r example/alpha` instead of as trailing
164
+ positional arguments. Repeated `-r` accumulate; the comma form still works.
165
+ - **Acceptance Criteria are prose (AC1, AC2, ) plus the gates block, not a
166
+ `| AC# | Command | Threshold |` table.** The prose is what the architect judges
167
+ against; gates are the necessary-not-sufficient mechanical check.
168
+ - **`architect new` allocates the ordinal at spec-time.** The `I<NN>` number is
169
+ assigned by `new`, not pre-numbered; `ARCHITECT.md` gains an un-numbered ordered
170
+ **Backlog** so reshuffling priorities no longer forces renumber churn.
171
+ - **Integration branch by default.** Lanes merge `--no-ff` into one shared,
172
+ stable `project/<slug>` branch instead of into `main` or per-iteration branches;
173
+ the end-of-project PR is deferred to `architect land`. Merge conflicts abort
174
+ cleanly and are treated as a lane-plan disjointness defect.
175
+ - **`architect gate` reports PASS/FAIL per gate and exits nonzero on any
176
+ failure** (it began as a raw-output-only runner) — while the framing keeps the
177
+ Acceptance-Criteria verdict with the architect, not the runner.
178
+ - **Post-flight moved out of the dispatching session.** The dispatch session now
179
+ only babysits builders to completion and hands off; a fresh judging session owns
180
+ post-flight checks, gates, verdict, and integration. Two first-class lane
181
+ patterns are documented: **parallel + fast-follow** and **serial deferred
182
+ judgment**.
183
+ - **`architect status` tells the truth about verdicts** — rendering
184
+ `awaiting-verdict` for integrated-but-unjudged iterations and the recorded
185
+ `continue`/`kill`, instead of a freeze/lane placeholder.
186
+ - **The loop is model-agnostic.** `dispatch --model` help clarifies any
187
+ provider/tier is fine (pin a full id, not a floating alias); the probe/spike is
188
+ documented as a first-class iteration type; `docs/DESIGN.md` was revived.
189
+ - **Builder streams now include partial messages.** The claude harness argv gained
190
+ `--include-partial-messages`, so `run.jsonl` (and any HTTP push) carries
191
+ streaming partial-message events, not just completed turns — consumers should
192
+ expect the finer-grained shape.
193
+ - **Colourful global help** for `space` and `architect`, with global colour
194
+ options `--color` (auto/always/never) and its `--colors` alias inherited by
195
+ every command via a shared `BaseCommand`. `src` keeps its own `--plain` /
196
+ `--json` system.
197
+ - **`space --version`** now reports the space-surface (`Space::Core`) version
198
+ independently of the architect project tooling.
199
+ - **The repository is now a monorepo.** The gem keeps the root (`lib/`, `exe/`,
200
+ `skill/`, `space-architect.gemspec`); the `space-server` app lives under
201
+ `server/`. Gem consumers are unaffected — `server/` is never packaged.
202
+
203
+ ### Removed
204
+
205
+ - **The `architect:` `space.yaml` key and the `ArchitectMission` class** —
206
+ renamed to `project:` / `ArchitectProject` with no alias (BREAKING; see above).
207
+ - **The Acceptance-Criteria command/threshold markdown table** — replaced by
208
+ prose ACs plus the fenced `gates` block.
209
+ - **The post-flight phase in the dispatching session** — that work now belongs to
210
+ a fresh judging session.
211
+
212
+ ### Fixed
213
+
214
+ - **Gate thresholds matched the first occurrence instead of the last.**
215
+ `GateEvaluator#check_threshold` now takes the last regex match, repairing frozen
216
+ `(\d+) runs`-style suite-green gates without editing the frozen AC.
217
+ - **A frozen per-gate `cwd` ran against the checked-out repo instead of the lane
218
+ worktree.** `run_gates` now re-roots a `cwd` pointing into the lane's repo onto
219
+ the lane worktree.
220
+ - **`architect verify` false-FAILed "no builder commits" after integration.** The
221
+ architect's own `integrate` commit was miscounted; `merge_lane!` now records
222
+ `integrate_sha` and the mechanical checks exclude exactly that SHA.
223
+ - **A missing `touch_set` rendered a silent `N/A`.** Bounds now render
224
+ `WARN — no touch_set recorded`, distinguishing "unchecked" from "clean."
225
+ - **Bounds glob matching was unsafe.** `fnmatch` now uses
226
+ `FNM_PATHNAME | FNM_EXTGLOB` and parses NUL-delimited `git status --porcelain
227
+ -z`, so `*` no longer crosses `/`, `**` works, and renames/spaced paths are
228
+ handled.
229
+ - **HTTP push is now best-effort and isolated.** If the ingest server's transport
230
+ fails or a push write errors mid-stream, `dispatch` logs a one-line warning and
231
+ keeps the run log intact rather than tearing down the builder; a failed push
232
+ disables further pushes for that run without dropping log output.
233
+ - **Container login-shell PATH and git identity.** The image writes
234
+ `/etc/profile.d/space-architect.sh` so `bash --login` finds `architect` /
235
+ `space` / `claude`, and the entrypoint seeds `user.name` / `user.email` if
236
+ unset so in-image commits and worktrees no longer fail on a missing identity.
237
+ - **The gate evaluator lacked a discriminating threshold test** — added one that
238
+ genuinely separates pass from fail, closing a hole where a broken evaluator
239
+ could still pass its own suite.
56
240
 
57
241
  ### Internal
58
242
 
59
- - `Space::Core` carved out as a standalone, leak-free foundation (no
60
- `SpaceArchitect` references); behaviour preserved byte-for-byte across the
61
- carve, the module rename, and the binary split.
62
- - CI: `softprops/action-gh-release` bumped to v3 (Node 24 runtime).
63
- - Test suite: 762 runs, 0 failures.
243
+ - **`Space::Core` carved out as a standalone, leak-free foundation** (no
244
+ `SpaceArchitect` references), with behaviour preserved across the carve, the
245
+ module rename, and the binary split.
246
+ - **New runtime dependencies:** `async-http ~> 0.95` and `protocol-http ~> 0.62`
247
+ (backing the HTTP push tee and the research mux).
248
+ - **Split, per-subtree CI.** The gem keeps a lean workflow (Ruby tests +
249
+ bundler-audit); a separate `server-ci.yml` runs the server suite against
250
+ Postgres 17 / Redis 7 service containers, a Node 24 frontend job, a matrix that
251
+ tests all five `server/gems/*` independently, and a server bundler-audit.
252
+ Toolchain is pinned via `mise.toml` (Ruby 4.0.5) at both the root and `server/`.
253
+ - **CI bumps:** `softprops/action-gh-release` v2 → v3 (Node 24 runtime),
254
+ `actions/cache` 5 → 6, `actions/checkout` 5 → 7, `actions/setup-node` 5 → 6,
255
+ and `shrine` 3.8.0 (server).
256
+ - **Prerelease-aware release pipeline.** `release.yml` marks rc/beta/alpha/pre
257
+ tags as GitHub prereleases so an RC tag is not published as `latest`; `2.0.0.rc1`
258
+ and `2.0.0.rc2` were cut ahead of this final.
259
+ - Gem test suite: 948 runs, 3611 assertions, 0 failures, 0 errors, 0 skips.
64
260
 
65
261
  ## [1.3.0] - 2026-06-25
66
262
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/space-architect.svg)](https://badge.fury.io/rb/space-architect)
4
4
 
5
- > **Task-scoped workspaces that double as Architect Loop missions — for humans and their agents!** ✨🛰️
5
+ > **Task-scoped workspaces that double as Architect Loop projects — for humans and their agents!** ✨🛰️
6
6
 
7
7
  `space-architect` is a Ruby toolkit for **spaces** — task-scoped project
8
8
  workspaces that hold repos, notes, and artifacts under one obvious filesystem
@@ -13,12 +13,12 @@ The gem ships **three composable binaries** over clean library seams:
13
13
 
14
14
  | Binary | What it does | Library |
15
15
  |--------|--------------|---------|
16
- | **`space`** 🪐 | Create and manage task-scoped workspaces | `Space::Core` |
16
+ | **`space`** 🪐 | Create, manage & containerize task-scoped workspaces | `Space::Core` |
17
17
  | **`architect`** 🏗️ | Run the Architect Loop — judgment + headless builders | `Space::Architect` |
18
18
  | **`src`** 🌲 | Tend evergreen repo checkouts for copy-on-write provisioning | `Space::Src` |
19
19
 
20
20
  Each is a first-class executable. `architect` also forwards `architect space …`
21
- and `architect src …` to the other two, so a mission can drive everything from
21
+ and `architect src …` to the other two, so a project can drive everything from
22
22
  one command when that's handier. 🎀
23
23
 
24
24
  ## What's a space? 🪐
@@ -84,6 +84,11 @@ architect init # scaffold ARCHITECT.md + arch
84
84
  architect new my-feature # scaffold the next iteration file
85
85
  architect freeze my-feature # lock the Acceptance Criteria ❄️
86
86
  architect dispatch my-feature lane-a # send a headless builder to work
87
+
88
+ # Containers (run from inside a space) — a portable, reproducible-by-SHA image of the space
89
+ space pack # render build/oci/ (Dockerfile + entrypoint)
90
+ space build # pack + build & tag <space-id>:<git-sha>
91
+ space run # run it — login shell, auth from your env
87
92
  ```
88
93
 
89
94
  ## `space` — task-scoped workspaces 🌌
@@ -116,7 +121,61 @@ comma form (`-r a,b`) works too. Space ids are date-prefixed
116
121
  same day get a counter (`…-name-of-space-2`). 📅
117
122
 
118
123
  Everything `space` does is also reachable as `architect space …` from within a
119
- mission.
124
+ project.
125
+
126
+ ## Containerize a space: `pack` · `build` · `run` 📦
127
+
128
+ A space is self-describing enough to become a container. `space pack` renders a
129
+ portable OCI build context from the space; `space build` packs and builds it into
130
+ a **reproducible-by-SHA** image; `space run` runs that image with your auth
131
+ injected at runtime and stateful paths bind-mounted back to the host. 🐳
132
+
133
+ ```sh
134
+ space pack # render build/oci/ (Dockerfile + entrypoint + ignore file)
135
+ space pack -o /tmp/ctx # …to a different output directory
136
+ space build # pack, then build & tag <space-id>:<git-sha> and :latest
137
+ space run # run <space-id>:latest — login shell, auth from your env
138
+ space run architect status # …or run a one-off command instead of the login shell
139
+ space run --tty # force an interactive TTY (default: auto-detect)
140
+ ```
141
+
142
+ **What lands in the image.** The context copies the whole space tree (filtered by
143
+ a generated `Dockerfile.dockerignore`) onto a `ruby:4.0.5` base with `git`, the
144
+ Claude Code CLI, and the `space-architect` gem — installed from the in-space
145
+ `repos/space-architect` checkout when present (a pinned build), else from
146
+ RubyGems. Secrets never enter the layers: `.env`, `*.key`, `*.pem`, ssh keys,
147
+ `build/`, and `tmp/` are all excluded by the generated ignore file. 🔒
148
+
149
+ **Reproducible by SHA.** `space build` tags the image `<space-id>:<sha>`, where
150
+ `<sha>` is the space repo's 12-char `HEAD` (suffixed `-dirty` when the tree has
151
+ uncommitted changes), plus a moving `:latest`. Same commit → same tag → same
152
+ image. It drives the `container` CLI, but the output is an ordinary OCI/Docker
153
+ build context, so `docker build -f build/oci/Dockerfile .` (from the space root)
154
+ works just as well.
155
+
156
+ **Auth stays out of the layers.** `space run` injects only the auth environment
157
+ variables that are actually set — `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`,
158
+ `ANTHROPIC_BASE_URL` — with `-e` at run time, so credentials live in your shell,
159
+ never in the image. 🗝️
160
+
161
+ **Declaring provisioning & persistence** — two optional keys in `space.yaml`:
162
+
163
+ ```yaml
164
+ pack:
165
+ provision: # build-time: relative scripts, baked in by `space build`
166
+ - scripts/setup-toolchain.sh
167
+ persist: # run-time: absolute guest paths, bind-mounted per run
168
+ - /root/.claude
169
+ - /root/.local/state
170
+ ```
171
+
172
+ `provision` scripts must live under the space root and run as `RUN /space/<script>`
173
+ while the image builds. `persist` paths must be absolute; `space run` bind-mounts
174
+ each one from `<space>/.state<path>` on the host (created on first run) so a
175
+ container's mutable state survives across runs. Both are validated at pack time.
176
+
177
+ Like everything else, these are reachable as `architect space pack|build|run`
178
+ from inside a project.
120
179
 
121
180
  ## `src` — the evergreen engine 🌲
122
181
 
@@ -149,24 +208,31 @@ fish integration (`src shell fish install`).
149
208
  ## `architect` — the Architect Loop 🏗️
150
209
 
151
210
  The **Architect Loop** is a structured build cycle for you and headless AI
152
- builders. Each loop lives inside a space as a *mission*.
211
+ builders. Each loop lives inside a space as a *project*.
153
212
 
154
213
  **Roles:**
155
214
 
156
- - **Architect** — you (or Claude Opus 4.8 in judgment mode): arbitrates
157
- disagreements, writes and freezes iteration files, calls kill/continue, merges
158
- builder output. Never writes implementation code.
159
- - **Builder** — Claude Sonnet 4.6 run headless via `architect dispatch`, one per
160
- lane in its own git worktree: reads the iteration's Builder Prompt, does the
161
- work, writes raw evidence to `build/<id>-<lane>/report.md`. Never grades its
162
- own work; never edits `architecture/`.
215
+ - **Architect** — the judgment role: a strong reasoning model (or you), run
216
+ interactively. Arbitrates disagreements, writes and freezes iteration files,
217
+ calls kill/continue, merges builder output. Never writes implementation code.
218
+ - **Builder** — the execution role: a cheaper model run headless via `architect
219
+ dispatch`, one per lane in its own git worktree. Reads the iteration's Builder
220
+ Prompt, does the work, writes raw evidence to `build/<id>-<lane>/report.md`.
221
+ Never grades its own work; never edits `architecture/`.
222
+
223
+ The loop is **model-agnostic** — which models fill the two roles is your choice
224
+ (e.g. a strong Claude model judging a cheaper one on the same plan, or a
225
+ cross-vendor pairing for more independent review). Set it per dispatch with
226
+ `architect dispatch --model …`, or run several pairings head-to-head as a
227
+ **variant set** (`architect variant add`). See
228
+ [docs/DESIGN.md](docs/DESIGN.md) §1–§2 for the reasoning.
163
229
 
164
230
  **Filesystem layout:**
165
231
 
166
232
  ```text
167
233
  architecture/
168
- ARCHITECT.md # cross-iteration index; mission-wide state
169
- BRIEF.md # durable §-numbered mission contract (optional)
234
+ ARCHITECT.md # cross-iteration index; project-wide state
235
+ BRIEF.md # durable §-numbered project contract (optional)
170
236
  I01-<iteration>.md # one self-contained file per iteration
171
237
  build/
172
238
  I01-<iteration>-<lane>/ # lane worktree + scratch per dispatch
@@ -193,11 +259,17 @@ prints the frozen Acceptance Criteria back. Any change to those sections
193
259
  afterward is an automatic iteration FAIL. The builder never edits the iteration
194
260
  file.
195
261
 
262
+ **Re-grounding 🧭** — `architect init` also scaffolds a `SessionStart` hook that
263
+ runs `architect ground` (emitting `ARCHITECT.md`, `BRIEF.md`, and the in-flight
264
+ iteration) so every fresh session starts oriented — the loop leans on
265
+ fresh-session judgment, and this is what makes picking up cold cheap. Builders
266
+ inside a lane worktree are never grounded.
267
+
196
268
  **Command surface:**
197
269
 
198
270
  ```sh
199
- architect init # scaffold ARCHITECT.md + the space.yaml architect: block
200
- architect brief new # scaffold the durable mission BRIEF.md
271
+ architect init # scaffold ARCHITECT.md + the space.yaml project: block + SessionStart hook
272
+ architect brief new # scaffold the durable project BRIEF.md
201
273
  architect new <iteration> # scaffold architecture/I<NN>-<iteration>.md
202
274
  architect section <it> <section> --from <f> # write + commit a section
203
275
  architect freeze <iteration> # freeze the Acceptance Criteria ❄️
@@ -208,7 +280,8 @@ architect evidence <it> --lane <lane> # transcribe the builder's report ve
208
280
  architect gate <iteration> # run the frozen gate commands, stream raw output
209
281
  architect merge <it> <lane> # integrate ONE judged-passing lane (--no-ff)
210
282
  architect integrate <it> --lanes a,b # integrate a set of passing lanes, in order
211
- architect status # mission state (read-only)
283
+ architect land # end-of-project PR command (no push, no gh)
284
+ architect status # project state (read-only)
212
285
  architect variant add|compare|promote … # competing (harness, model) lanes over one frozen spec
213
286
  architect research dispatch|status|wait … # parallel read-only research lanes (see below)
214
287
  ```
@@ -225,6 +298,8 @@ architect verify my-feature # mechanical post-flight checks
225
298
  architect evidence my-feature --lane lane-a # transcribe raw evidence
226
299
  architect gate my-feature # run the frozen gates yourself
227
300
  # … read the diff against the spec, then write the Verdict …
301
+ architect integrate my-feature --lanes lane-a # merge passing lanes → project/<slug>
302
+ architect land # print gh pr create at project end
228
303
  ```
229
304
 
230
305
  ### Streaming builder output 📡
@@ -346,7 +421,7 @@ The library is split into three namespaces you can require independently:
346
421
 
347
422
  - **`Space::Core`** — the foundation: config, state, XDG, terminal, git/mise
348
423
  clients, the space store. The `space` CLI runs on this alone.
349
- - **`Space::Architect`** — mission state, the builder harness, dispatch, and the
424
+ - **`Space::Architect`** — project state, the builder harness, dispatch, and the
350
425
  research supervisor.
351
426
  - **`Space::Src`** — the evergreen engine (tracking, sync, copy-on-write clone).
352
427
 
@@ -359,7 +434,7 @@ require "space_src" # just the evergreen engine
359
434
  ## Documentation 📖
360
435
 
361
436
  - **[Command Reference](docs/reference.md)** — every command, flag, and behavior
362
- - **[Design](docs/design.md)** — why spaces and the Architect Loop exist, and how they're shaped
437
+ - **[Design](docs/DESIGN.md)** — the source-backed rationale: the twelve invariant rules (R1–R12), the failure-mode → mitigation table, and why the loop is shaped this way
363
438
  - **[Changelog](CHANGELOG.md)** — release history
364
439
 
365
440
  ## Development 🛠️