space-architect 8.0.0 โ†’ 9.1.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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -0
  3. data/README.md +39 -464
  4. data/lib/space_architect/architect_project.rb +90 -39
  5. data/lib/space_architect/bug_report.rb +2 -1
  6. data/lib/space_architect/cli/architect.rb +189 -11
  7. data/lib/space_architect/cli/research.rb +1 -1
  8. data/lib/space_architect/cli.rb +9 -14
  9. data/lib/space_architect/loop_cost.rb +592 -0
  10. data/lib/space_architect/research/supervisor.rb +9 -2
  11. data/lib/space_architect/routing.rb +149 -0
  12. data/lib/space_architect/session_sync/bin_path.rb +1 -1
  13. data/lib/space_architect/session_sync/cursor.rb +1 -1
  14. data/lib/space_architect/session_sync/plist.rb +1 -1
  15. data/lib/{space_core โ†’ space_architect}/version.rb +2 -2
  16. data/lib/space_architect.rb +2 -1
  17. data/skill/architect/SKILL.md +3 -2
  18. data/skill/architect-vocabulary/SKILL.md +2 -2
  19. metadata +20 -177
  20. data/exe/space +0 -13
  21. data/exe/src +0 -13
  22. data/lib/space_architect/cli/space.rb +0 -29
  23. data/lib/space_architect/cli/src.rb +0 -38
  24. data/lib/space_core/atomic_write.rb +0 -21
  25. data/lib/space_core/cli/base_command.rb +0 -19
  26. data/lib/space_core/cli/build.rb +0 -27
  27. data/lib/space_core/cli/config.rb +0 -49
  28. data/lib/space_core/cli/current.rb +0 -16
  29. data/lib/space_core/cli/help.rb +0 -195
  30. data/lib/space_core/cli/helpers.rb +0 -115
  31. data/lib/space_core/cli/init.rb +0 -29
  32. data/lib/space_core/cli/list.rb +0 -24
  33. data/lib/space_core/cli/loop_status.rb +0 -47
  34. data/lib/space_core/cli/new.rb +0 -38
  35. data/lib/space_core/cli/pack.rb +0 -29
  36. data/lib/space_core/cli/path.rb +0 -16
  37. data/lib/space_core/cli/repeatable_options.rb +0 -84
  38. data/lib/space_core/cli/repo.rb +0 -76
  39. data/lib/space_core/cli/run.rb +0 -44
  40. data/lib/space_core/cli/shell.rb +0 -125
  41. data/lib/space_core/cli/show.rb +0 -21
  42. data/lib/space_core/cli/status.rb +0 -74
  43. data/lib/space_core/cli/use.rb +0 -17
  44. data/lib/space_core/cli.rb +0 -177
  45. data/lib/space_core/commands.rb +0 -51
  46. data/lib/space_core/config.rb +0 -152
  47. data/lib/space_core/errors.rb +0 -14
  48. data/lib/space_core/git_client.rb +0 -49
  49. data/lib/space_core/mise_client.rb +0 -37
  50. data/lib/space_core/oci_builder.rb +0 -56
  51. data/lib/space_core/oci_packer.rb +0 -103
  52. data/lib/space_core/oci_runner.rb +0 -89
  53. data/lib/space_core/paths.rb +0 -58
  54. data/lib/space_core/repo_reference.rb +0 -19
  55. data/lib/space_core/repo_resolver.rb +0 -167
  56. data/lib/space_core/shell_integration.rb +0 -438
  57. data/lib/space_core/slugger.rb +0 -16
  58. data/lib/space_core/space.rb +0 -174
  59. data/lib/space_core/space_store.rb +0 -319
  60. data/lib/space_core/state.rb +0 -86
  61. data/lib/space_core/templates/oci/dockerfile.erb +0 -73
  62. data/lib/space_core/templates/oci/dockerignore.erb +0 -17
  63. data/lib/space_core/templates/oci/entrypoint.sh.erb +0 -16
  64. data/lib/space_core/terminal.rb +0 -161
  65. data/lib/space_core/warnings.rb +0 -13
  66. data/lib/space_core/xdg.rb +0 -33
  67. data/lib/space_core.rb +0 -26
  68. data/lib/space_src/cli/clone.rb +0 -54
  69. data/lib/space_src/cli/config.rb +0 -65
  70. data/lib/space_src/cli/daemon.rb +0 -362
  71. data/lib/space_src/cli/options.rb +0 -21
  72. data/lib/space_src/cli/org.rb +0 -199
  73. data/lib/space_src/cli/repo.rb +0 -169
  74. data/lib/space_src/cli/shell.rb +0 -121
  75. data/lib/space_src/cli/status.rb +0 -75
  76. data/lib/space_src/cli/sync.rb +0 -161
  77. data/lib/space_src/cli.rb +0 -159
  78. data/lib/space_src/cloner.rb +0 -77
  79. data/lib/space_src/config/contract.rb +0 -54
  80. data/lib/space_src/config/duration.rb +0 -79
  81. data/lib/space_src/config/model.rb +0 -49
  82. data/lib/space_src/config/store.rb +0 -156
  83. data/lib/space_src/forge/client.rb +0 -31
  84. data/lib/space_src/forge/github.rb +0 -98
  85. data/lib/space_src/launchd/agent.rb +0 -195
  86. data/lib/space_src/launchd/plist.rb +0 -129
  87. data/lib/space_src/log_rotator.rb +0 -46
  88. data/lib/space_src/migration.rb +0 -43
  89. data/lib/space_src/nav.rb +0 -99
  90. data/lib/space_src/paths.rb +0 -72
  91. data/lib/space_src/scm/client.rb +0 -87
  92. data/lib/space_src/scm/git.rb +0 -232
  93. data/lib/space_src/scm/status.rb +0 -24
  94. data/lib/space_src/shell.rb +0 -90
  95. data/lib/space_src/shell_integration.rb +0 -321
  96. data/lib/space_src/state/lock.rb +0 -59
  97. data/lib/space_src/state/store.rb +0 -140
  98. data/lib/space_src/sync/engine.rb +0 -503
  99. data/lib/space_src/sync/repo_plan.rb +0 -215
  100. data/lib/space_src/sync/report.rb +0 -18
  101. data/lib/space_src/ui/interactive_reporter.rb +0 -280
  102. data/lib/space_src/ui/json_reporter.rb +0 -39
  103. data/lib/space_src/ui/mode.rb +0 -68
  104. data/lib/space_src/ui/plain_reporter.rb +0 -53
  105. data/lib/space_src/ui/reporter.rb +0 -48
  106. data/lib/space_src/version.rb +0 -7
  107. data/lib/space_src.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b63abfece4c105ef5b2befd0d8c4e4301d8d5cade10570cd2f41bd0641b8c4be
4
- data.tar.gz: 6b932ae13952dad48f81a2ee68ed52b7cee28ef8edc4a99e7a06f23952c4f107
3
+ metadata.gz: c2dfa94f98278929ea382e4411856749de3af270511f60760ee4e3bed83daf53
4
+ data.tar.gz: 33c9bf994eafc772c67399876826b77f685a7ac9e3417f38b37054d853b5479b
5
5
  SHA512:
6
- metadata.gz: 3cbb55f4fab850bc9fb7b4cf55bb318bf846d54c3f78a399c50b76d325ddbcd12ad52072d224d75a25b6e5830c8fffa6d7e6f51ad522aae231bb2b374ac3980e
7
- data.tar.gz: 4adfa615512c8f6652b85d5948c0a58c9851d30711fc2a1a7f870060601bb6fe0fab9af4ade0c8eebfb5e93a67bf60d1d6516e12fcd0ba96595d530049e0d0da
6
+ metadata.gz: 2b7c099ff9ffc9b1cf6e37d48a687b2c08c4f2c0463ea5f1e77d156f214bdf9e4f5d0059e1be9fa1247de440c50ea091ffb933db5f02c3bb8e2d8d75ed0f3996
7
+ data.tar.gz: 5ce698b9ed448dbab61db46302c5f51f4e0bd850c8748c052131ffea4ef718326a3a4de47562092ba782dcfcfa042c6dedfe1c56675119b9ba2d98e29caf5f49
data/CHANGELOG.md CHANGED
@@ -5,6 +5,60 @@ 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
+ ## [9.0.0] - 2026-10-09
9
+
10
+ ### Changed
11
+
12
+ - **The split: space-architect is now the Architect Loop only.** The monolith
13
+ carved the space tool and the evergreen engine into their own gems โ€”
14
+ **space-cadet** 9.0.0 (`Space::Core`, the `space` binary) and **repo-tender**
15
+ 1.0.0 (`RepoTender`, the `repo-tender` binary with the deprecated `src`
16
+ shim) โ€” and this gem consumes them as libraries instead of vendoring them.
17
+ Dropped: the vendored `lib/space_core` / `lib/space_src` subtrees, the
18
+ `exe/space` and `exe/src` binaries, and the `architect space โ€ฆ` / `architect
19
+ src โ€ฆ` forwarder intercepts. `architect space โ€ฆ` / `architect src โ€ฆ` are now
20
+ ordinary unknown commands (dry-cli usage + non-zero exit) โ€” the `space`
21
+ binary comes from space-cadet and the `src` binary from repo-tender; re-point
22
+ 8.x scripts and aliases accordingly.
23
+ - **Upgrading from 8.x:** `gem uninstall space-architect` first โ€” the 8.x gem's
24
+ `space` and `src` executables collide with the ones the new gems ship โ€” then
25
+ `gem install space-architect` (pulls space-cadet) and, for the session-sync
26
+ rail, `gem install repo-tender`. Config/state: space-cadet โ‰ฅ 9.1 migrates the
27
+ substrate's `config.yml`/`state.yml` from the old
28
+ `~/.config|state/space-architect/` dirs automatically on first run of either
29
+ `space` or `architect` (on 9.0.0, move them across by hand); the loop's own
30
+ session-sync cursor stays where it is.
31
+ - **Host-branded help header.** `architect --help`'s root header now brands
32
+ the loop (`architect 9.0.0 โ€” โ€ฆ`) via space-cadet's product-name/version seam
33
+ instead of the substrate's identity โ€” hence the `space-cadet ~> 9.1`
34
+ dependency floor.
35
+ - **Own version line.** The loop's version is now
36
+ `Space::Architect::VERSION = "9.0.0"` (`lib/space_architect/version.rb`) โ€”
37
+ its first, decoupled from `Space::Core::VERSION`. The gemspec version,
38
+ `architect --version`, the bug-report diagnostics, and the bug-report command
39
+ footer all derive from the loop's own constant; the bug report additionally
40
+ lists `space-cadet: <version>` as a dependency diagnostic.
41
+ - **Dependency posture.** Hard dependency: `space-cadet ~> 9.0`. The declared
42
+ set shrank to what the loop itself requires (`async-http`, `async-process`,
43
+ `protocol-http`, `pastel`, `dry-cli`, `dry-monads`, `dry-validation` โ€” `xdg`,
44
+ `tty-cursor`, `dry-struct`/`dry-types`, and bare `async` were the vendored
45
+ trees' deps, not the loop's). repo-tender is deliberately **not** a gemspec
46
+ runtime dependency: the `sessions agent` launchd seam requires it lazily and,
47
+ when the gem is absent, fails with a short actionable error naming the fix
48
+ (`gem install repo-tender`) instead of a LoadError backtrace. The dev
49
+ Gemfile includes repo-tender so the suite exercises the real integration.
50
+ - **Tests and mutation subjects classified, not carried.** Tests whose subject
51
+ was the vendored tools' functionality (everything under `test/space_core/`
52
+ and `test/space_src/`, the forwarder tests, the space-tool surface,
53
+ shell-integration, slugger, repo-resolver, warnings) dropped with the code โ€”
54
+ their coverage lives in the two gems. Loop tests keep running against the
55
+ gem-served `Space::Core`; fixture setup routes through the gem's own CLI.
56
+ The `:mutant` task now subjects `Space::Architect::GateEvaluator` and
57
+ `Space::Architect::GateLint` only.
58
+ - **Docs and skills updated to the split reality** (README, command reference,
59
+ releasing guide, design doc, skills): one binary, two gem dependencies, no
60
+ forwarders or vendored subtrees.
61
+
8
62
  ## [8.0.0] - 2026-10-09
9
63
 
10
64
  ### Changed
data/README.md CHANGED
@@ -2,481 +2,62 @@
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 projects โ€” for humans and their agents!** โœจ๐Ÿ›ฐ๏ธ
5
+ > **The Architect Loop โ€” structured judgment-and-build cycles for humans and their agents!** โœจ๐Ÿ›ฐ๏ธ
6
6
 
7
- `space-architect` is a Ruby toolkit for **spaces** โ€” task-scoped project
8
- workspaces that hold repos, notes, and artifacts under one obvious filesystem
9
- root โ€” fused with the **Architect Loop**: a structured judgment-and-build cycle
10
- for you and a fleet of headless AI builders. ๐ŸŒŒ
7
+ `space-architect` is the gem behind the **Architect Loop**: a structured
8
+ judgment-and-build cycle in which a strong reasoning model (the *architect*)
9
+ plans, freezes acceptance criteria, and judges the work of a fleet of headless
10
+ AI *builders* โ€” one per lane, each in its own git worktree. The loop runs inside
11
+ task-scoped **spaces**: directories that hold repos, notes, and artifacts under
12
+ one obvious filesystem root. Nothing lives only in a chat window โ€” every
13
+ decision, spec, and verdict is committed to the space repo.
11
14
 
12
- The gem ships **three composable binaries** over clean library seams:
15
+ It installs **one executable**, `architect`. The spaces substrate and the
16
+ evergreen-checkout engine are two sibling gems:
13
17
 
14
- | Binary | What it does | Library |
15
- |--------|--------------|---------|
16
- | **`space`** ๐Ÿช | Create, manage & containerize task-scoped workspaces | `Space::Core` |
17
- | **`architect`** ๐Ÿ—๏ธ | Run the Architect Loop โ€” judgment + headless builders | `Space::Architect` |
18
- | **`src`** ๐ŸŒฒ | Tend evergreen repo checkouts for copy-on-write provisioning | `Space::Src` |
19
-
20
- Each is a first-class executable. `architect` also forwards `architect space โ€ฆ`
21
- and `architect src โ€ฆ` to the other two, so a project can drive everything from
22
- one command when that's handier. ๐ŸŽ€
23
-
24
- ## What's a space? ๐Ÿช
25
-
26
- A space is just a regular directory with a tiny YAML identity file and room for
27
- everything a task needs:
28
-
29
- ```text
30
- ~/architect/spaces/20260531-name-of-space/
31
- space.yaml # identity: id, title, status, repos, notes, tags
32
- README.md
33
- repos/ # cloned (or copy-on-write'd) repositories
34
- notes/ # scratch, prompts, logs
35
- architecture/ # iteration files: I<NN>-<name>.md + ARCHITECT.md index + BRIEF.md
36
- build/ # lane worktrees + scratch (build/<id>-<lane>/)
37
- tmp/ # workspace-local temp โ€” use this instead of /tmp
38
- ```
39
-
40
- Run a command from anywhere inside a space and it just works โ€” `space` and
41
- `architect` walk up from `$PWD` until they find the nearest `space.yaml`. No
42
- "current space" state to get out of sync; where you *are* is the space you
43
- mean. ๐Ÿงญ
18
+ | Gem | Dependency | What it provides |
19
+ |-----|------------|------------------|
20
+ | **space-cadet** | hard | The spaces substrate (`Space::Core`): create, manage & containerize task-scoped workspaces โ€” the `space` binary โ€” plus the copy-on-write evergreen-checkout substrate repos provision from |
21
+ | **repo-tender** | soft | Evergreen clone tending โ€” the `repo-tender` binary (with the deprecated `src` shim) โ€” and the launchd agent the `architect sessions agent` commands drive. Install with `gem install repo-tender` when you want the session-sync rail โ€” everything else works without it |
44
22
 
45
23
  ## Installation ๐Ÿ“ฆ
46
24
 
47
- Add it to your `Gemfile`:
48
-
49
- ```ruby
50
- gem "space-architect"
51
- ```
52
-
53
- ```bash
54
- bundle install
55
- ```
56
-
57
- Or grab it yourself:
58
-
59
25
  ```bash
60
26
  gem install space-architect
27
+ gem install repo-tender # optional: enables the sessions launchd agent
61
28
  ```
62
29
 
63
- The gem is `space-architect`; it installs three executables โ€” `space`,
64
- `architect`, and `src`. ๐ŸŽ€
65
-
66
- ## Quick start ๐ŸŽ€
67
-
68
- ```sh
69
- # Spaces
70
- space init # create XDG config + state files
71
- space new "Name of Space" # blast off a new space ๐Ÿš€
72
- space new "Name of Space" -r org/repo -r org/lib # โ€ฆwith repos cloned in (repeat -r)
73
- space list # see all your spaces
74
- space show # show the space you're standing in
75
-
76
- # Evergreen checkouts (copy-on-write sources for fast provisioning)
77
- src repo add github.com/example-org/example-app # tend it ๐ŸŒฒ
78
- src sync # one sync pass
79
- src status # per-repo evergreen status
80
-
81
- # Architect Loop (run from inside a space)
82
- architect install-skills # install agent skills (once per machine)
83
- architect init # scaffold ARCHITECT.md + architecture/
84
- architect new my-feature # scaffold the next iteration file
85
- architect freeze my-feature # lock the Acceptance Criteria โ„๏ธ
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
92
- ```
93
-
94
- ## `space` โ€” task-scoped workspaces ๐ŸŒŒ
95
-
96
- ```sh
97
- space init
98
- space new "Name of Space"
99
- space new "Name of Space" -r org/repo -r example-tools/alpha -r example-tools/beta
100
- space list # alias: space ls
101
- space show 20260531-name-of-space
102
- space path 20260531-name-of-space
103
- space current # based on $PWD
104
- space show # based on $PWD
105
- space status # report: metadata + loop status (based on $PWD)
106
- space status 20260531-name-of-space # report another space
107
- space status done # set: active | paused | done | archived
108
- space status 20260531-name-of-space done
109
- space config set default_provider github.com
110
- space config set default_organization example-org
111
- space repo add example-app # github.com/example-org/example-app
112
- space repo add example-tools/alpha example-tools/beta
113
- space repo add gitlab.com/example-org/api
114
- space repo resolve example-app example-tools/async
115
- space repo ls # alias: space repos ls
116
- space use 20260531-name-of-space # records recent state, prints the path
117
- space ls --color=always # auto | always | never (--colors also accepted)
118
- ```
119
-
120
- `space status` is **report-or-set**: with no status keyword (bare, or with just
121
- a space id) it *reports* the space โ€” its metadata plus a compact loop-status
122
- block (project status, current iteration, derived state) when the space runs an
123
- Architect project, quietly omitted otherwise; pass a status keyword (`active`,
124
- `paused`, `done`, `archived`) to *set* it instead. ๐Ÿ”
125
-
126
- Repos are passed with a repeatable `-r` flag (`-r org/repo -r org/lib`); the
127
- comma form (`-r a,b`) works too. Space ids are date-prefixed
128
- (`20260531-name-of-space`) so they sort naturally, and duplicate names on the
129
- same day get a counter (`โ€ฆ-name-of-space-2`). ๐Ÿ“…
130
-
131
- Everything `space` does is also reachable as `architect space โ€ฆ` from within a
132
- project.
133
-
134
- ## Containerize a space: `pack` ยท `build` ยท `run` ๐Ÿ“ฆ
135
-
136
- A space is self-describing enough to become a container. `space pack` renders a
137
- portable OCI build context from the space; `space build` packs and builds it into
138
- a **reproducible-by-SHA** image; `space run` runs that image with your auth
139
- injected at runtime and stateful paths bind-mounted back to the host. ๐Ÿณ
140
-
141
- ```sh
142
- space pack # render build/oci/ (Dockerfile + entrypoint + ignore file)
143
- space pack -o /tmp/ctx # โ€ฆto a different output directory
144
- space build # pack, then build & tag <space-id>:<git-sha> and :latest
145
- space run # run <space-id>:latest โ€” login shell, auth from your env
146
- space run architect status # โ€ฆor run a one-off command instead of the login shell
147
- space run --tty # force an interactive TTY (default: auto-detect)
148
- ```
149
-
150
- **What lands in the image.** The context copies the whole space tree (filtered by
151
- a generated `Dockerfile.dockerignore`) onto a `ruby:4.0.5` base with `git`, the
152
- Claude Code CLI, and the `space-architect` gem โ€” installed from the in-space
153
- `repos/space-architect` checkout when present (a pinned build), else from
154
- RubyGems. Secrets never enter the layers: `.env`, `*.key`, `*.pem`, ssh keys,
155
- `build/`, and `tmp/` are all excluded by the generated ignore file. ๐Ÿ”’
156
-
157
- **Reproducible by SHA.** `space build` tags the image `<space-id>:<sha>`, where
158
- `<sha>` is the space repo's 12-char `HEAD` (suffixed `-dirty` when the tree has
159
- uncommitted changes), plus a moving `:latest`. Same commit โ†’ same tag โ†’ same
160
- image. It drives the `container` CLI, but the output is an ordinary OCI/Docker
161
- build context, so `docker build -f build/oci/Dockerfile .` (from the space root)
162
- works just as well.
163
-
164
- **Auth stays out of the layers.** `space run` injects only the auth environment
165
- variables that are actually set โ€” `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`,
166
- `ANTHROPIC_BASE_URL` โ€” with `-e` at run time, so credentials live in your shell,
167
- never in the image. ๐Ÿ—๏ธ
168
-
169
- **Forwarding payload credentials.** Beyond the always-on auth trio, a space can declare
170
- `run.env:` in `space.yaml` โ€” a list of host env var names forwarded into the container at
171
- run time. You can also pass `space run --env VAR` (repeatable) for ad hoc additions. All
172
- forwarding is bare `-e VAR` passthrough: values never appear in argv, `ps`, or the image.
173
- A requested-but-unset var warns on stderr instead of silently failing inside the guest.
174
-
175
- ```yaml
176
- run:
177
- env: # run-time: host var names, forwarded as bare -e VAR
178
- - FIREWORKS_API_KEY
179
- - OPENAI_API_KEY
180
- ```
181
-
182
- **Declaring provisioning & persistence** โ€” two optional keys in `space.yaml`:
183
-
184
- ```yaml
185
- pack:
186
- provision: # build-time: relative scripts, baked in by `space build`
187
- - scripts/setup-toolchain.sh
188
- persist: # run-time: absolute guest paths, bind-mounted per run
189
- - /root/.claude
190
- - /root/.local/state
191
- ```
192
-
193
- `provision` scripts must live under the space root and be executable. Each script is
194
- copied into the image individually (`COPY <script> /space/<script>`) and then invoked
195
- (`RUN /space/<script>`) **before** the full space tree lands and **before** the gem is
196
- installed. This ordering is the cache-hygiene guarantee: editing any other space file
197
- leaves the provision and gem-install layers cached, so a rebuild completes in seconds
198
- instead of minutes. Scripts must therefore be self-contained โ€” they run with only the
199
- base system layers and any earlier provision scripts' outputs; they cannot read other
200
- space files or call `architect`/`space`. Scripts must have the executable bit set; COPY
201
- preserves the mode from the build context.
202
-
203
- `persist` paths must be absolute; `space run` bind-mounts each one from
204
- `<space>/.state<path>` on the host (created on first run) so a container's mutable state
205
- survives across runs. Both are validated at pack time.
206
-
207
- Like everything else, these are reachable as `architect space pack|build|run`
208
- from inside a project.
209
-
210
- ## `src` โ€” the evergreen engine ๐ŸŒฒ
211
-
212
- `src` keeps local clones under `<src_dir>/<host>/<owner>/<repo>` (default
213
- `~/architect/src/โ€ฆ`) clean, on their default branch, and freshly fetched โ€” so
214
- spaces can provision repos by **copy-on-write** instead of cloning over the
215
- network.
216
-
217
- ```sh
218
- src repo add github.com/example-org/example-app # track + tend a repo
219
- src org add github.com/example-org # track a whole org
220
- src sync # run one sync pass (--repo to scope)
221
- src status # per-repo evergreen status table
222
- src clone example-app # APFS copy-on-write into $PWD
223
- src daemon install # per-user launchd agent for background sync
224
- ```
225
-
226
- When `space repo add` finds a matching evergreen checkout, it copy-on-writes
227
- from it instead of hitting the network โ€” instant provisioning. โšก The two
228
- surfaces share one layout by design, so they line up with zero configuration:
229
-
230
- ```sh
231
- src repo add github.com/example-org/example-app # tend it: keep it evergreen ๐ŸŒฒ
232
- space repo add example-app # copies it instantly โšก
233
- ```
234
-
235
- `src` has its own `--plain` / `--json` output modes for scripting, and its own
236
- fish integration (`src shell fish install`).
237
-
238
- ## `architect` โ€” the Architect Loop ๐Ÿ—๏ธ
239
-
240
- The **Architect Loop** is a structured build cycle for you and headless AI
241
- builders. Each loop lives inside a space as a *project*.
242
-
243
- **Roles:**
244
-
245
- - **Architect** โ€” the judgment role: a strong reasoning model (or you), run
246
- interactively. Arbitrates disagreements, writes and freezes iteration files,
247
- calls kill/continue, merges builder output. Never writes implementation code.
248
- - **Builder** โ€” the execution role: a cheaper model run headless via `architect
249
- dispatch`, one per lane in its own git worktree. Reads the iteration's Builder
250
- Prompt, does the work, writes raw evidence to `build/<id>-<lane>/report.md`.
251
- Never grades its own work; never edits `architecture/`.
252
-
253
- The loop is **model-agnostic** โ€” which models fill the two roles is your choice
254
- (e.g. a strong Claude model judging a cheaper one on the same plan, or a
255
- cross-vendor pairing for more independent review). Set it per dispatch with
256
- `architect dispatch --model โ€ฆ`, or run several pairings head-to-head as a
257
- **variant set** (`architect variant add`). See
258
- [docs/DESIGN.md](docs/DESIGN.md) ยง1โ€“ยง2 for the reasoning.
259
-
260
- **Filesystem layout:**
261
-
262
- ```text
263
- architecture/
264
- ARCHITECT.md # cross-iteration index; project-wide state
265
- BRIEF.md # durable ยง-numbered project contract (optional)
266
- I01-<iteration>.md # one self-contained file per iteration
267
- build/
268
- I01-<iteration>-<lane>/ # lane worktree + scratch per dispatch
269
- run.jsonl # streamed builder output
270
- report.md # builder report (transcribed into the iteration file verbatim)
271
- ```
272
-
273
- **Iteration file anatomy** โ€” one file, grown section by section. You author the
274
- *content* in fresh scratch files; the CLI owns the *persistence* (each command
275
- writes the section, commits it, and prints back what changed). Every committing
276
- command takes `-m`/`--message` and `--message-from <file>` โ€” your first line
277
- completes the subject after a short canonical prefix (`I01 spec: <subject>`),
278
- the rest becomes the body. The space's git log is the loop's durable memory:
279
- write detailed messages.
280
-
281
- | Section | Holds | How you persist it |
282
- |---------|-------|--------------------|
283
- | `## Grounds` | why โ€” research / brief distilled (optional) | `architect section <it> grounds --from <f>` |
284
- | `## Specification` | what/how โ€” the full delegation contract | `architect section <it> specification --from <f>` |
285
- | `## Acceptance Criteria` | proof โ€” exact gate commands + thresholds | `architect freeze <it>` โ„๏ธ |
286
- | `## Builder Prompt` | the exact lane-prompt(s) dispatched | `architect section <it> prompt --append --lane <l> --from <f>` |
287
- | `## Builder Report` | raw evidence, transcribed verbatim | `architect evidence <it> --lane <l>` |
288
- | `## Verdict` | rulings + per-AC PASS/FAIL + KILL/CONTINUE | `architect section <it> verdict --from <f>` |
30
+ The gem installs one executable: `architect`. ๐ŸŽ€ (Or add
31
+ `gem "space-architect"` to your Gemfile and `bundle install`.)
289
32
 
290
- **The freeze โ„๏ธ** โ€” `architect freeze <iteration>` commits the frozen region
291
- (Grounds / Specification / Acceptance Criteria), records the `freeze_sha`, and
292
- prints the frozen Acceptance Criteria back. Any change to those sections
293
- afterward is an automatic iteration FAIL. The builder never edits the iteration
294
- file.
33
+ Upgrading from the 8.x monolith? Uninstall `space-architect` 8.x **first** โ€”
34
+ its `space`/`src` executables collide with the ones the new gems ship โ€” see
35
+ [the upgrade guide](docs/how-to/upgrade-from-the-8x-monolith.md).
295
36
 
296
- **Re-grounding ๐Ÿงญ** โ€” `architect init` also scaffolds a `SessionStart` hook that
297
- runs `architect ground` (emitting `ARCHITECT.md`, `BRIEF.md`, and the in-flight
298
- iteration) so every fresh session starts oriented โ€” the loop leans on
299
- fresh-session judgment, and this is what makes picking up cold cheap. Builders
300
- inside a lane worktree are never grounded.
37
+ ## 60-second start ๐ŸŽ€
301
38
 
302
- **Command surface:**
39
+ Run one full loop iteration in a scratch space โ€” the
40
+ [tutorial](docs/tutorials/one-loop-iteration.md) walks it end to end:
303
41
 
304
42
  ```sh
305
- architect init # scaffold ARCHITECT.md + the space.yaml project: block + SessionStart hook
306
- architect brief new --from <f> # write the durable project BRIEF.md (authored in a scratch file)
307
- architect new <iteration> # scaffold architecture/I<NN>-<iteration>.md
308
- architect section <it> <section> --from <f> # write + commit a section (add -m/--message-from for a detailed commit)
309
- architect freeze <iteration> # freeze the Acceptance Criteria โ„๏ธ
310
- architect worktree add <repo> <it> <lane> # isolated worktree per lane (2โ€“4 lanes)
311
- architect dispatch <it> <lane> --prompt <f> # copy the lane prompt in + dispatch a builder (--detach to survive long runs)
312
- architect verify <iteration> # post-flight mechanical checks (reports only)
313
- architect evidence <it> --lane <lane> # transcribe the builder's report verbatim
314
- architect gate <iteration> # run the frozen gate commands, stream raw output
315
- architect merge <it> <lane> # integrate ONE judged-passing lane (--no-ff)
316
- architect integrate <it> --lanes a,b # integrate a set of passing lanes, in order
317
- # landing (PR body + push/PR command) is the architect's end-of-project procedure (see skill)
318
- architect status # project state (read-only)
319
- architect variant add|compare|promote โ€ฆ # competing (harness, model) lanes over one frozen spec
320
- architect research dispatch|status|wait โ€ฆ # parallel read-only research lanes (see below)
43
+ space init # create the XDG config + state files (space-cadet gem)
44
+ space new "Docsmith Tutorial" # blast off a new space ๐Ÿš€
45
+ cd ~/architect/spaces/<id>-docsmith-tutorial
46
+ architect init # scaffold ARCHITECT.md + the space.yaml project: block
321
47
  ```
322
48
 
323
- `architect help` (or bare `architect`, `architect --help`) lists these grouped by
324
- loop phase โ€” **Spec ยท Build ยท Judge ยท Land ยท Project ยท Groups**, in canonical
325
- order โ€” and, inside an architect space, ends with a compact loop-status block
326
- (project status + current iteration) so you can see where you are in the loop. ๐Ÿงญ
49
+ From there the loop is: `architect new` โ†’ `architect section โ€ฆ` โ†’ `architect
50
+ freeze` โ†’ `architect dispatch` โ†’ `architect gate` โ†’ `architect integrate`. The
51
+ tutorial runs every step on a scratch repo.
327
52
 
328
- A typical session:
329
-
330
- ```sh
331
- architect init # first time
332
- architect new my-feature # scaffold I01-my-feature.md
333
- architect section my-feature specification --from spec.md -m "pull-based dispatcher seam"
334
- architect freeze my-feature # lock it โ„๏ธ
335
- architect dispatch my-feature lane-a --prompt tmp/prompts/I01-lane-a.md --detach # send a builder; poll the report
336
- architect verify my-feature # mechanical post-flight checks
337
- architect evidence my-feature --lane lane-a # transcribe raw evidence
338
- architect gate my-feature # run the frozen gates yourself
339
- # โ€ฆ read the diff against the spec, then write the Verdict โ€ฆ
340
- architect integrate my-feature --lanes lane-a # merge passing lanes โ†’ project/<slug>
341
- # landing (PR body + push/PR command) is the architect's end-of-project procedure (see skill)
342
- ```
343
-
344
- ### Streaming builder output ๐Ÿ“ก
345
-
346
- `architect dispatch` can push the builder's pi JSONL event stream to an ingest
347
- server for
348
- live viewing:
349
-
350
- ```sh
351
- # Push to an already-created run (you supply the full ingest URL):
352
- architect dispatch my-feature lane-a \
353
- --push-url $HOST/runs/<id>/ingest \
354
- --push-token $INGEST_TOKEN
355
-
356
- # Create a run and push in one step (requires --push-token = server's INGEST_TOKEN):
357
- architect dispatch my-feature lane-a \
358
- --push-host $HOST \
359
- --push-token $INGEST_TOKEN
360
- ```
361
-
362
- `--push-host` POSTs to `<HOST>/runs`, parses the new run id from the `201`
363
- response, derives `<HOST>/runs/<id>/ingest`, and streams there; the created run
364
- id and ingest URL are printed after dispatch starts. `--push-url` and
365
- `--push-host` are mutually exclusive, both require `--push-token`, and neither
366
- can be combined with `--detach` (the push tees the live pipe in-process).
367
-
368
- ### Research lanes ๐Ÿ”ญ
369
-
370
- When an iteration needs facts the repo doesn't already have, fan out parallel
371
- **read-only** research lanes โ€” detached `pi -p --mode json` researchers
372
- (read-only by prompt contract; the supervisor-injected guard denies git writes)
373
- that you supervise:
374
-
375
- ```sh
376
- architect research dispatch 01-official-api.prompt.md 02-changelog.prompt.md
377
- architect research wait # tails each lane's run.jsonl; --level 1-4, --quiet, --thinking
378
- architect research status # status of dispatched runs
379
- ```
380
-
381
- Researchers gather; the architect verifies the load-bearing claims against
382
- sources and writes the iteration's **Grounds** section.
383
-
384
- ### Skills ๐Ÿง 
385
-
386
- `architect install-skills` installs the bundled `architect`,
387
- `architect-research`, and `architect-vocabulary` skills for your harness:
388
-
389
- ```sh
390
- architect install-skills # default: claude (~/.claude/skills/)
391
- architect install-skills --provider opencode # or codex | pi
392
- architect install-skills --project # into ./โ€ฆ instead of globally
393
- architect install-skills --dry-run # show what would change
394
- ```
53
+ ## The four quadrants ๐Ÿงญ
395
54
 
396
- `architect-vocabulary` loads the system's terms and a short orientation when
397
- you're in a space but don't want to run the loop.
398
-
399
- ## Fish shell integration ๐ŸŸ
400
-
401
- Shells can't let a child process change *their* working directory, so `space`
402
- and `src` each ship a small fish wrapper function plus completions (commands,
403
- subcommands, spaces, statuses, config keys, repo refs). Install into fish's
404
- autoloaded directories:
405
-
406
- ```fish
407
- space shell fish install
408
- src shell fish install
409
- exec fish
410
- ```
411
-
412
- After restarting fish (or `exec fish`), `space new "โ€ฆ"` and
413
- `space use <id>` will `cd` into the selected space once the command succeeds;
414
- every other command keeps normal CLI behavior. ๐Ÿšช The functions and completions
415
- are written under `~/.config/fish/`, so there's no need to edit `config.fish`.
416
- For one-off testing without installing:
417
-
418
- ```fish
419
- space shell init fish | source
420
- ```
421
-
422
- ## Configuration โš™๏ธ
423
-
424
- Config lives at `~/.config/space-architect/config.yml` (XDG-aware) and defaults to:
425
-
426
- ```yaml
427
- version: 1
428
- base_dir: ~/architect # spaces_dir + src_dir hang off this by default
429
- default_provider: github.com
430
- default_organization:
431
- git_clone_protocol: ssh # ssh | https
432
- ```
433
-
434
- Derived defaults: `spaces_dir` โ†’ `<base_dir>/spaces`, `src_dir` (evergreen
435
- checkout root) โ†’ `<base_dir>/src`. Override either explicitly. View values with
436
- `space config show`; set one with `space config set KEY VALUE`. Editable keys:
437
- `base_dir`, `spaces_dir`, `src_dir`, `default_provider`, `default_organization`,
438
- `git_clone_protocol`.
439
-
440
- ## Repos: evergreen, copy-on-write, concurrent โšก
441
-
442
- Repos are added to the current space under `repos/` and tracked in `space.yaml`.
443
- When an up-to-date evergreen checkout exists at
444
- `<src_dir>/<host>/<owner>/<name>` (e.g.
445
- `~/architect/src/github.com/example-org/example-app`), `space` copies it into the
446
- space instead of cloning over the network โ€” a copy-on-write clone on APFS. โšก
447
- Set `src_dir` empty to always clone:
448
-
449
- ```sh
450
- space config set src_dir ""
451
- ```
452
-
453
- Clone URLs default to SSH (`git@github.com:example-org/example-app.git`); switch
454
- with `space config set git_clone_protocol https`. Multiple repos passed to
455
- `space repo add` are fetched **concurrently**, up to five at a time, on fibers โ€”
456
- no threads, all cooperative. ๐Ÿงต After each repo lands, `space` runs `mise trust`
457
- in it. Each space also gets a workspace-local `tmp/` โ€” use it instead of `/tmp`.
458
-
459
- ## Embedding ๐Ÿ“š
460
-
461
- The library is split into three namespaces you can require independently:
462
-
463
- - **`Space::Core`** โ€” the foundation: config, state, XDG, terminal, git/mise
464
- clients, the space store. The `space` CLI runs on this alone.
465
- - **`Space::Architect`** โ€” project state, the builder harness, dispatch, and the
466
- research supervisor.
467
- - **`Space::Src`** โ€” the evergreen engine (tracking, sync, copy-on-write clone).
468
-
469
- ```ruby
470
- require "space_core" # just spaces
471
- require "space_architect" # the full loop (pulls in core + src)
472
- require "space_src" # just the evergreen engine
473
- ```
474
-
475
- ## Documentation ๐Ÿ“–
476
-
477
- - **[Command Reference](docs/reference.md)** โ€” every command, flag, and behavior
478
- - **[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
479
- - **[Changelog](CHANGELOG.md)** โ€” release history
55
+ | Quadrant | Read it when youโ€ฆ | Start here |
56
+ |----------|-------------------|------------|
57
+ | **Tutorials** โ€” learning-oriented | are new and want a guided journey | [docs/tutorials](docs/tutorials/) |
58
+ | **How-to guides** โ€” goal-oriented | have a specific task to do | [docs/how-to](docs/how-to/) |
59
+ | **Reference** โ€” information-oriented | need a fact about a command, flag, or file | [docs/reference](docs/reference/) |
60
+ | **Explanation** โ€” understanding-oriented | want the why behind the design | [docs/explanation](docs/explanation/) |
480
61
 
481
62
  ## Development ๐Ÿ› ๏ธ
482
63
 
@@ -487,15 +68,9 @@ bundle exec rake build # build the gem into pkg/
487
68
  bundle exec rake install # build + install into your user gem home
488
69
  ```
489
70
 
490
- ## Contributing ๐Ÿ’
491
-
492
71
  Bug reports and pull requests are welcome on GitHub at
493
- [https://github.com/jetpks/space-architect](https://github.com/jetpks/space-architect)!
494
-
495
- ## License ๐Ÿ“„
496
-
497
- Available as open source under the terms of the
498
- [MIT License](https://opensource.org/licenses/MIT).
72
+ [https://github.com/jetpks/space-architect](https://github.com/jetpks/space-architect).
73
+ Available as open source under the [MIT License](LICENSE.txt).
499
74
 
500
75
  ---
501
76