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 +4 -4
- data/CHANGELOG.md +232 -36
- data/README.md +94 -19
- data/lib/space_architect/{architect_mission.rb → architect_project.rb} +396 -77
- data/lib/space_architect/cli/architect.rb +170 -60
- data/lib/space_architect/cli/research.rb +1 -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 +24 -3
- 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 +3 -1
- data/lib/space_core/cli/build.rb +27 -0
- data/lib/space_core/cli/help.rb +15 -2
- data/lib/space_core/cli/pack.rb +29 -0
- data/lib/space_core/cli/repo.rb +1 -1
- data/lib/space_core/cli/run.rb +29 -0
- data/lib/space_core/cli.rb +6 -0
- 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_core/space.rb +10 -2
- data/lib/space_core/space_store.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_core/version.rb +1 -1
- data/skill/architect/SKILL.md +109 -53
- data/skill/architect/dispatch.md +147 -39
- data/skill/architect/research.md +1 -1
- data/skill/architect-research/SKILL.md +2 -2
- data/skill/architect-vocabulary/SKILL.md +24 -21
- metadata +13 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a5828b73d6d58a9d14547e9d8be9e7f8a734212c7e7356a01149c4c9cbeadd9c
|
|
4
|
+
data.tar.gz: a8c75e611270a1ff40f0cfd55753549d6972ae2d6af4999695b688f35942bb88
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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-
|
|
8
|
+
## [2.0.0] - 2026-07-01
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
25
|
-
run in the background;
|
|
26
|
-
|
|
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`
|
|
34
|
-
|
|
35
|
-
their surfaces; `src` is its own executable
|
|
36
|
-
|
|
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
|
-
(
|
|
40
|
-
`Space::Architect::*` (
|
|
41
|
-
`Space::Src::*` (the evergreen engine).
|
|
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
|
-
|
|
46
|
-
`$XDG_STATE_HOME/space-src/` on first run
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
|
|
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
|
-
-
|
|
60
|
-
`SpaceArchitect` references)
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
|
|
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
|
[](https://badge.fury.io/rb/space-architect)
|
|
4
4
|
|
|
5
|
-
> **Task-scoped workspaces that double as Architect Loop
|
|
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
|
|
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
|
|
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
|
-
|
|
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 *
|
|
211
|
+
builders. Each loop lives inside a space as a *project*.
|
|
153
212
|
|
|
154
213
|
**Roles:**
|
|
155
214
|
|
|
156
|
-
- **Architect** —
|
|
157
|
-
disagreements, writes and freezes iteration files,
|
|
158
|
-
builder output. Never writes implementation code.
|
|
159
|
-
- **Builder** —
|
|
160
|
-
lane in its own git worktree
|
|
161
|
-
work, writes raw evidence to `build/<id>-<lane>/report.md`.
|
|
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;
|
|
169
|
-
BRIEF.md # durable §-numbered
|
|
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
|
|
200
|
-
architect brief new # scaffold the durable
|
|
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
|
|
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`** —
|
|
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/
|
|
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 🛠️
|