space-architect 1.3.0 → 2.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +103 -0
- data/README.md +267 -158
- data/exe/architect +1 -1
- data/exe/space +2 -2
- data/exe/src +13 -0
- data/lib/space_architect/{architect_mission.rb → architect_project.rb} +475 -125
- data/lib/space_architect/cli/architect.rb +248 -178
- data/lib/space_architect/cli/research.rb +94 -0
- data/lib/space_architect/cli/space.rb +25 -31
- data/lib/space_architect/cli/src.rb +20 -14
- data/lib/space_architect/cli.rb +22 -22
- data/lib/space_architect/dispatcher.rb +5 -1
- data/lib/space_architect/gate_evaluator.rb +65 -0
- data/lib/space_architect/gate_lint.rb +140 -0
- data/lib/space_architect/harness.rb +145 -17
- data/lib/space_architect/research/mux.rb +127 -0
- data/lib/space_architect/research/registry.rb +70 -0
- data/lib/space_architect/research/renderer.rb +101 -0
- data/lib/space_architect/research/run.rb +7 -0
- data/lib/space_architect/research/supervisor.rb +108 -0
- data/lib/space_architect/research.rb +13 -0
- data/lib/space_architect/run_creator.rb +53 -0
- data/lib/space_architect/skill_installer.rb +81 -79
- data/lib/space_architect/templates/architect.md.erb +15 -4
- data/lib/space_architect/templates/brief.md.erb +5 -5
- data/lib/space_architect/templates/iteration.md.erb +17 -6
- data/lib/space_architect.rb +8 -21
- data/lib/{space_architect → space_core}/atomic_write.rb +1 -1
- data/lib/space_core/cli/base_command.rb +19 -0
- data/lib/space_core/cli/build.rb +27 -0
- data/lib/space_core/cli/config.rb +49 -0
- data/lib/space_core/cli/current.rb +16 -0
- data/lib/space_core/cli/help.rb +123 -0
- data/lib/space_core/cli/helpers.rb +115 -0
- data/lib/space_core/cli/init.rb +29 -0
- data/lib/space_core/cli/list.rb +24 -0
- data/lib/space_core/cli/new.rb +38 -0
- data/lib/space_core/cli/pack.rb +29 -0
- data/lib/space_core/cli/path.rb +16 -0
- data/lib/space_core/cli/repeatable_options.rb +75 -0
- data/lib/space_core/cli/repo.rb +76 -0
- data/lib/space_core/cli/run.rb +29 -0
- data/lib/space_core/cli/shell.rb +125 -0
- data/lib/space_core/cli/show.rb +21 -0
- data/lib/space_core/cli/status.rb +33 -0
- data/lib/space_core/cli/use.rb +17 -0
- data/lib/space_core/cli.rb +177 -0
- data/lib/{space_architect → space_core}/config.rb +1 -1
- data/lib/{space_architect → space_core}/errors.rb +1 -1
- data/lib/{space_architect → space_core}/git_client.rb +1 -1
- data/lib/{space_architect → space_core}/mise_client.rb +1 -1
- data/lib/space_core/oci_builder.rb +56 -0
- data/lib/space_core/oci_packer.rb +99 -0
- data/lib/space_core/oci_runner.rb +73 -0
- data/lib/{space_architect → space_core}/repo_reference.rb +1 -1
- data/lib/{space_architect → space_core}/repo_resolver.rb +1 -1
- data/lib/{space_architect → space_core}/shell_integration.rb +1 -1
- data/lib/{space_architect → space_core}/slugger.rb +1 -1
- data/lib/{space_architect → space_core}/space.rb +11 -3
- data/lib/{space_architect → space_core}/space_store.rb +13 -13
- data/lib/{space_architect → space_core}/state.rb +1 -1
- data/lib/space_core/templates/oci/dockerfile.erb +63 -0
- data/lib/space_core/templates/oci/dockerignore.erb +17 -0
- data/lib/space_core/templates/oci/entrypoint.sh.erb +10 -0
- data/lib/{space_architect → space_core}/terminal.rb +1 -1
- data/lib/space_core/version.rb +7 -0
- data/lib/{space_architect → space_core}/warnings.rb +1 -1
- data/lib/{space_architect → space_core}/xdg.rb +1 -1
- data/lib/space_core.rb +24 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/clone.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/config.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/daemon.rb +46 -30
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/options.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/org.rb +9 -9
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/repo.rb +9 -9
- data/lib/space_src/cli/shell.rb +122 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/status.rb +7 -7
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli/sync.rb +17 -17
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cli.rb +42 -11
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/cloner.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/contract.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/duration.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/model.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/config/store.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/client.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/forge/github.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/agent.rb +5 -5
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/launchd/plist.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/log_rotator.rb +1 -1
- data/lib/space_src/migration.rb +43 -0
- data/lib/space_src/nav.rb +98 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/paths.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/client.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/git.rb +4 -4
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/scm/status.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/shell.rb +1 -1
- data/lib/space_src/shell_integration.rb +321 -0
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/lock.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/state/store.rb +2 -2
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/engine.rb +12 -12
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/sync/repo_plan.rb +3 -3
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/interactive_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/json_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/mode.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/plain_reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/ui/reporter.rb +1 -1
- data/{vendor/repo-tender/lib/space_architect/pristine → lib/space_src}/version.rb +2 -2
- data/lib/space_src.rb +37 -0
- data/skill/architect/SKILL.md +110 -54
- data/skill/architect/dispatch.md +147 -39
- data/skill/architect/research.md +46 -37
- data/skill/architect-research/SKILL.md +2 -2
- data/skill/architect-vocabulary/SKILL.md +24 -21
- metadata +127 -68
- data/lib/space_architect/cli/config.rb +0 -61
- data/lib/space_architect/cli/current.rb +0 -22
- data/lib/space_architect/cli/helpers.rb +0 -117
- data/lib/space_architect/cli/init.rb +0 -35
- data/lib/space_architect/cli/list.rb +0 -30
- data/lib/space_architect/cli/new.rb +0 -43
- data/lib/space_architect/cli/options.rb +0 -12
- data/lib/space_architect/cli/path.rb +0 -22
- data/lib/space_architect/cli/repo.rb +0 -88
- data/lib/space_architect/cli/shell.rb +0 -137
- data/lib/space_architect/cli/show.rb +0 -27
- data/lib/space_architect/cli/status.rb +0 -39
- data/lib/space_architect/cli/use.rb +0 -23
- data/lib/space_architect/version.rb +0 -5
- data/vendor/repo-tender/lib/space_architect/pristine.rb +0 -44
data/README.md
CHANGED
|
@@ -2,12 +2,24 @@
|
|
|
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
|
-
`space-architect` is a Ruby
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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. 🌌
|
|
11
|
+
|
|
12
|
+
The gem ships **three composable binaries** over clean library seams:
|
|
13
|
+
|
|
14
|
+
| Binary | What it does | Library |
|
|
15
|
+
|--------|--------------|---------|
|
|
16
|
+
| **`space`** 🪐 | Create and manage 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. 🎀
|
|
11
23
|
|
|
12
24
|
## What's a space? 🪐
|
|
13
25
|
|
|
@@ -15,19 +27,20 @@ A space is just a regular directory with a tiny YAML identity file and room for
|
|
|
15
27
|
everything a task needs:
|
|
16
28
|
|
|
17
29
|
```text
|
|
18
|
-
~/
|
|
30
|
+
~/architect/spaces/20260531-name-of-space/
|
|
19
31
|
space.yaml # identity: id, title, status, repos, notes, tags
|
|
20
32
|
README.md
|
|
21
33
|
repos/ # cloned (or copy-on-write'd) repositories
|
|
22
34
|
notes/ # scratch, prompts, logs
|
|
23
|
-
architecture/ # iteration files: I<NN>-<name>.md + ARCHITECT.md index
|
|
35
|
+
architecture/ # iteration files: I<NN>-<name>.md + ARCHITECT.md index + BRIEF.md
|
|
24
36
|
build/ # lane worktrees + scratch (build/<id>-<lane>/)
|
|
25
37
|
tmp/ # workspace-local temp — use this instead of /tmp
|
|
26
38
|
```
|
|
27
39
|
|
|
28
|
-
Run a command from anywhere inside a space and it just works — `
|
|
29
|
-
up from `$PWD` until
|
|
30
|
-
get out of sync; where you *are* is the space you
|
|
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. 🧭
|
|
31
44
|
|
|
32
45
|
## Installation 📦
|
|
33
46
|
|
|
@@ -37,8 +50,6 @@ Add it to your `Gemfile`:
|
|
|
37
50
|
gem "space-architect"
|
|
38
51
|
```
|
|
39
52
|
|
|
40
|
-
Then:
|
|
41
|
-
|
|
42
53
|
```bash
|
|
43
54
|
bundle install
|
|
44
55
|
```
|
|
@@ -49,225 +60,323 @@ Or grab it yourself:
|
|
|
49
60
|
gem install space-architect
|
|
50
61
|
```
|
|
51
62
|
|
|
52
|
-
The
|
|
53
|
-
|
|
54
|
-
for convenience.
|
|
55
|
-
|
|
56
|
-
## Quick Start 🎀
|
|
63
|
+
The gem is `space-architect`; it installs three executables — `space`,
|
|
64
|
+
`architect`, and `src`. 🎀
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
## Quick start 🎀
|
|
59
67
|
|
|
60
68
|
```sh
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
67
87
|
```
|
|
68
88
|
|
|
69
|
-
|
|
89
|
+
## `space` — task-scoped workspaces 🌌
|
|
70
90
|
|
|
71
91
|
```sh
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
space init
|
|
93
|
+
space new "Name of Space"
|
|
94
|
+
space new "Name of Space" -r org/repo -r example-tools/alpha -r example-tools/beta
|
|
95
|
+
space list # alias: space ls
|
|
96
|
+
space show 20260531-name-of-space
|
|
97
|
+
space path 20260531-name-of-space
|
|
98
|
+
space current # based on $PWD
|
|
99
|
+
space show # based on $PWD
|
|
100
|
+
space status done # based on $PWD
|
|
101
|
+
space status 20260531-name-of-space done
|
|
102
|
+
space config set default_provider github.com
|
|
103
|
+
space config set default_organization example-org
|
|
104
|
+
space repo add example-app # github.com/example-org/example-app
|
|
105
|
+
space repo add example-tools/alpha example-tools/beta
|
|
106
|
+
space repo add gitlab.com/example-org/api
|
|
107
|
+
space repo resolve example-app example-tools/async
|
|
108
|
+
space repo ls # alias: space repos ls
|
|
109
|
+
space use 20260531-name-of-space # records recent state, prints the path
|
|
110
|
+
space ls --color=always # auto | always | never (--colors also accepted)
|
|
79
111
|
```
|
|
80
112
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
113
|
+
Repos are passed with a repeatable `-r` flag (`-r org/repo -r org/lib`); the
|
|
114
|
+
comma form (`-r a,b`) works too. Space ids are date-prefixed
|
|
115
|
+
(`20260531-name-of-space`) so they sort naturally, and duplicate names on the
|
|
116
|
+
same day get a counter (`…-name-of-space-2`). 📅
|
|
117
|
+
|
|
118
|
+
Everything `space` does is also reachable as `architect space …` from within a
|
|
119
|
+
project.
|
|
120
|
+
|
|
121
|
+
## `src` — the evergreen engine 🌲
|
|
122
|
+
|
|
123
|
+
`src` keeps local clones under `<src_dir>/<host>/<owner>/<repo>` (default
|
|
124
|
+
`~/architect/src/…`) clean, on their default branch, and freshly fetched — so
|
|
125
|
+
spaces can provision repos by **copy-on-write** instead of cloning over the
|
|
126
|
+
network.
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
src repo add github.com/example-org/example-app # track + tend a repo
|
|
130
|
+
src org add github.com/example-org # track a whole org
|
|
131
|
+
src sync # run one sync pass (--repo to scope)
|
|
132
|
+
src status # per-repo evergreen status table
|
|
133
|
+
src clone example-app # APFS copy-on-write into $PWD
|
|
134
|
+
src daemon install # per-user launchd agent for background sync
|
|
135
|
+
```
|
|
88
136
|
|
|
89
|
-
|
|
137
|
+
When `space repo add` finds a matching evergreen checkout, it copy-on-writes
|
|
138
|
+
from it instead of hitting the network — instant provisioning. ⚡ The two
|
|
139
|
+
surfaces share one layout by design, so they line up with zero configuration:
|
|
90
140
|
|
|
91
141
|
```sh
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
architect space new "Name of Space" org/repo example-tools/alpha example-tools/beta
|
|
95
|
-
architect space list
|
|
96
|
-
architect space show 20260531-name-of-space
|
|
97
|
-
architect space path 20260531-name-of-space
|
|
98
|
-
architect space current # based on $PWD
|
|
99
|
-
architect space show # based on $PWD
|
|
100
|
-
architect space status done # based on $PWD
|
|
101
|
-
architect space status 20260531-name-of-space done
|
|
102
|
-
architect space config set default_provider github.com
|
|
103
|
-
architect space config set default_organization example-org
|
|
104
|
-
architect space repo add example-app # github.com/example-org/example-app
|
|
105
|
-
architect space repo add example-tools/alpha example-tools/beta
|
|
106
|
-
architect space repo add gitlab.com/example-org/api
|
|
107
|
-
architect space repo resolve example-app example-tools/async
|
|
108
|
-
architect space repo ls
|
|
109
|
-
architect space use 20260531-name-of-space # records recent state and prints the path
|
|
110
|
-
architect space ls --color=always # auto, always, or never; --colors is also accepted
|
|
142
|
+
src repo add github.com/example-org/example-app # tend it: keep it evergreen 🌲
|
|
143
|
+
space repo add example-app # copies it instantly ⚡
|
|
111
144
|
```
|
|
112
145
|
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
`src` has its own `--plain` / `--json` output modes for scripting, and its own
|
|
147
|
+
fish integration (`src shell fish install`).
|
|
115
148
|
|
|
116
|
-
##
|
|
149
|
+
## `architect` — the Architect Loop 🏗️
|
|
117
150
|
|
|
118
|
-
|
|
119
|
-
|
|
151
|
+
The **Architect Loop** is a structured build cycle for you and headless AI
|
|
152
|
+
builders. Each loop lives inside a space as a *project*.
|
|
120
153
|
|
|
121
154
|
**Roles:**
|
|
122
155
|
|
|
123
|
-
- **Architect** —
|
|
124
|
-
writes and freezes iteration files,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
156
|
+
- **Architect** — the judgment role: a strong reasoning model (or you), run
|
|
157
|
+
interactively. Arbitrates disagreements, writes and freezes iteration files,
|
|
158
|
+
calls kill/continue, merges builder output. Never writes implementation code.
|
|
159
|
+
- **Builder** — the execution role: a cheaper model run headless via `architect
|
|
160
|
+
dispatch`, one per lane in its own git worktree. Reads the iteration's Builder
|
|
161
|
+
Prompt, does the work, writes raw evidence to `build/<id>-<lane>/report.md`.
|
|
162
|
+
Never grades its own work; never edits `architecture/`.
|
|
163
|
+
|
|
164
|
+
The loop is **model-agnostic** — which models fill the two roles is your choice
|
|
165
|
+
(e.g. a strong Claude model judging a cheaper one on the same plan, or a
|
|
166
|
+
cross-vendor pairing for more independent review). Set it per dispatch with
|
|
167
|
+
`architect dispatch --model …`, or run several pairings head-to-head as a
|
|
168
|
+
**variant set** (`architect variant add`). See
|
|
169
|
+
[docs/DESIGN.md](docs/DESIGN.md) §1–§2 for the reasoning.
|
|
128
170
|
|
|
129
171
|
**Filesystem layout:**
|
|
130
172
|
|
|
131
173
|
```text
|
|
132
174
|
architecture/
|
|
133
|
-
ARCHITECT.md # cross-iteration index;
|
|
134
|
-
|
|
135
|
-
|
|
175
|
+
ARCHITECT.md # cross-iteration index; project-wide state
|
|
176
|
+
BRIEF.md # durable §-numbered project contract (optional)
|
|
177
|
+
I01-<iteration>.md # one self-contained file per iteration
|
|
136
178
|
build/
|
|
137
179
|
I01-<iteration>-<lane>/ # lane worktree + scratch per dispatch
|
|
138
180
|
run.jsonl # streamed builder output
|
|
139
|
-
report.md # builder report (transcribed
|
|
181
|
+
report.md # builder report (transcribed into the iteration file verbatim)
|
|
140
182
|
```
|
|
141
183
|
|
|
142
|
-
**Iteration file anatomy**
|
|
184
|
+
**Iteration file anatomy** — one file, grown section by section. You author the
|
|
185
|
+
*content*; the CLI owns the *persistence* (each command writes the section,
|
|
186
|
+
commits it with the canonical message, and prints back what changed):
|
|
187
|
+
|
|
188
|
+
| Section | Holds | How you persist it |
|
|
189
|
+
|---------|-------|--------------------|
|
|
190
|
+
| `## Grounds` | why — research / brief distilled (optional) | `architect section <it> grounds --from <f>` |
|
|
191
|
+
| `## Specification` | what/how — the full delegation contract | `architect section <it> specification --from <f>` |
|
|
192
|
+
| `## Acceptance Criteria` | proof — exact gate commands + thresholds | `architect freeze <it>` ❄️ |
|
|
193
|
+
| `## Builder Prompt` | the exact lane-prompt(s) dispatched | `architect section <it> prompt --append --lane <l> --from <f>` |
|
|
194
|
+
| `## Builder Report` | raw evidence, transcribed verbatim | `architect evidence <it> --lane <l>` |
|
|
195
|
+
| `## Verdict` | rulings + per-AC PASS/FAIL + KILL/CONTINUE | `architect section <it> verdict --from <f>` |
|
|
196
|
+
|
|
197
|
+
**The freeze ❄️** — `architect freeze <iteration>` commits the frozen region
|
|
198
|
+
(Grounds / Specification / Acceptance Criteria), records the `freeze_sha`, and
|
|
199
|
+
prints the frozen Acceptance Criteria back. Any change to those sections
|
|
200
|
+
afterward is an automatic iteration FAIL. The builder never edits the iteration
|
|
201
|
+
file.
|
|
202
|
+
|
|
203
|
+
**Re-grounding 🧭** — `architect init` also scaffolds a `SessionStart` hook that
|
|
204
|
+
runs `architect ground` (emitting `ARCHITECT.md`, `BRIEF.md`, and the in-flight
|
|
205
|
+
iteration) so every fresh session starts oriented — the loop leans on
|
|
206
|
+
fresh-session judgment, and this is what makes picking up cold cheap. Builders
|
|
207
|
+
inside a lane worktree are never grounded.
|
|
208
|
+
|
|
209
|
+
**Command surface:**
|
|
143
210
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
211
|
+
```sh
|
|
212
|
+
architect init # scaffold ARCHITECT.md + the space.yaml project: block + SessionStart hook
|
|
213
|
+
architect brief new # scaffold the durable project BRIEF.md
|
|
214
|
+
architect new <iteration> # scaffold architecture/I<NN>-<iteration>.md
|
|
215
|
+
architect section <it> <section> --from <f> # write + commit a section
|
|
216
|
+
architect freeze <iteration> # freeze the Acceptance Criteria ❄️
|
|
217
|
+
architect worktree add <repo> <it> <lane> # isolated worktree per lane (2–4 lanes)
|
|
218
|
+
architect dispatch <it> <lane> # dispatch a builder (add --detach to survive long runs)
|
|
219
|
+
architect verify <iteration> # post-flight mechanical checks (reports only)
|
|
220
|
+
architect evidence <it> --lane <lane> # transcribe the builder's report verbatim
|
|
221
|
+
architect gate <iteration> # run the frozen gate commands, stream raw output
|
|
222
|
+
architect merge <it> <lane> # integrate ONE judged-passing lane (--no-ff)
|
|
223
|
+
architect integrate <it> --lanes a,b # integrate a set of passing lanes, in order
|
|
224
|
+
architect land # end-of-project PR command (no push, no gh)
|
|
225
|
+
architect status # project state (read-only)
|
|
226
|
+
architect variant add|compare|promote … # competing (harness, model) lanes over one frozen spec
|
|
227
|
+
architect research dispatch|status|wait … # parallel read-only research lanes (see below)
|
|
228
|
+
```
|
|
157
229
|
|
|
158
|
-
|
|
230
|
+
A typical session:
|
|
159
231
|
|
|
160
232
|
```sh
|
|
161
|
-
#
|
|
162
|
-
architect
|
|
163
|
-
architect
|
|
164
|
-
|
|
165
|
-
architect
|
|
166
|
-
architect dispatch my-feature lane-A # send builder to work
|
|
167
|
-
# … builder runs, writes build/I01-my-feature-lane-A/report.md …
|
|
233
|
+
architect init # first time
|
|
234
|
+
architect new my-feature # scaffold I01-my-feature.md
|
|
235
|
+
architect section my-feature specification --from spec.md
|
|
236
|
+
architect freeze my-feature # lock it ❄️
|
|
237
|
+
architect dispatch my-feature lane-a --detach # send a builder; poll the report
|
|
168
238
|
architect verify my-feature # mechanical post-flight checks
|
|
169
|
-
architect
|
|
170
|
-
|
|
239
|
+
architect evidence my-feature --lane lane-a # transcribe raw evidence
|
|
240
|
+
architect gate my-feature # run the frozen gates yourself
|
|
241
|
+
# … read the diff against the spec, then write the Verdict …
|
|
242
|
+
architect integrate my-feature --lanes lane-a # merge passing lanes → project/<slug>
|
|
243
|
+
architect land # print gh pr create at project end
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Streaming builder output 📡
|
|
247
|
+
|
|
248
|
+
`architect dispatch` can push the builder's stream-json to an ingest server for
|
|
249
|
+
live viewing:
|
|
250
|
+
|
|
251
|
+
```sh
|
|
252
|
+
# Push to an already-created run (you supply the full ingest URL):
|
|
253
|
+
architect dispatch my-feature lane-a \
|
|
254
|
+
--push-url $HOST/runs/<id>/ingest \
|
|
255
|
+
--push-token $INGEST_TOKEN
|
|
256
|
+
|
|
257
|
+
# Create a run and push in one step (requires --push-token = server's INGEST_TOKEN):
|
|
258
|
+
architect dispatch my-feature lane-a \
|
|
259
|
+
--push-host $HOST \
|
|
260
|
+
--push-token $INGEST_TOKEN
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`--push-host` POSTs to `<HOST>/runs`, parses the new run id from the `201`
|
|
264
|
+
response, derives `<HOST>/runs/<id>/ingest`, and streams there; the created run
|
|
265
|
+
id and ingest URL are printed after dispatch starts. `--push-url` and
|
|
266
|
+
`--push-host` are mutually exclusive, both require `--push-token`, and neither
|
|
267
|
+
can be combined with `--detach` (the push tees the live pipe in-process).
|
|
268
|
+
|
|
269
|
+
### Research lanes 🔭
|
|
270
|
+
|
|
271
|
+
When an iteration needs facts the repo doesn't already have, fan out parallel
|
|
272
|
+
**read-only** research lanes — detached `claude -p` researchers (no
|
|
273
|
+
Edit/Write/Bash) that you supervise:
|
|
274
|
+
|
|
275
|
+
```sh
|
|
276
|
+
architect research dispatch 01-official-api.prompt.md 02-changelog.prompt.md
|
|
277
|
+
architect research wait # tails each lane's run.jsonl; --level 1-4, --quiet, --thinking
|
|
278
|
+
architect research status # status of dispatched runs
|
|
171
279
|
```
|
|
172
280
|
|
|
281
|
+
Researchers gather; the architect verifies the load-bearing claims against
|
|
282
|
+
sources and writes the iteration's **Grounds** section.
|
|
283
|
+
|
|
284
|
+
### Skills 🧠
|
|
285
|
+
|
|
286
|
+
`architect install-skills` installs the bundled `architect`,
|
|
287
|
+
`architect-research`, and `architect-vocabulary` skills for your harness:
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
architect install-skills # default: claude (~/.claude/skills/)
|
|
291
|
+
architect install-skills --provider opencode # or codex | pi
|
|
292
|
+
architect install-skills --project # into ./… instead of globally
|
|
293
|
+
architect install-skills --dry-run # show what would change
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
`architect-vocabulary` loads the system's terms and a short orientation when
|
|
297
|
+
you're in a space but don't want to run the loop.
|
|
298
|
+
|
|
173
299
|
## Fish shell integration 🐟
|
|
174
300
|
|
|
175
|
-
Shells can't let a child process change *their* working directory, so `
|
|
176
|
-
|
|
177
|
-
subcommands, spaces, statuses, config keys,
|
|
178
|
-
|
|
301
|
+
Shells can't let a child process change *their* working directory, so `space`
|
|
302
|
+
and `src` each ship a small fish wrapper function plus completions (commands,
|
|
303
|
+
subcommands, spaces, statuses, config keys, repo refs). Install into fish's
|
|
304
|
+
autoloaded directories:
|
|
179
305
|
|
|
180
306
|
```fish
|
|
181
|
-
|
|
307
|
+
space shell fish install
|
|
308
|
+
src shell fish install
|
|
182
309
|
exec fish
|
|
183
310
|
```
|
|
184
311
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
The function is written to `~/.config/fish/functions/space.fish` and completions to
|
|
191
|
-
`~/.config/fish/completions/space.fish`, so there's no need to edit `config.fish`.
|
|
312
|
+
After restarting fish (or `exec fish`), `space new "…"` and
|
|
313
|
+
`space use <id>` will `cd` into the selected space once the command succeeds;
|
|
314
|
+
every other command keeps normal CLI behavior. 🚪 The functions and completions
|
|
315
|
+
are written under `~/.config/fish/`, so there's no need to edit `config.fish`.
|
|
192
316
|
For one-off testing without installing:
|
|
193
317
|
|
|
194
318
|
```fish
|
|
195
|
-
|
|
319
|
+
space shell init fish | source
|
|
196
320
|
```
|
|
197
321
|
|
|
198
322
|
## Configuration ⚙️
|
|
199
323
|
|
|
200
|
-
|
|
324
|
+
Config lives at `~/.config/space-architect/config.yml` (XDG-aware) and defaults to:
|
|
201
325
|
|
|
202
326
|
```yaml
|
|
203
327
|
version: 1
|
|
204
|
-
|
|
205
|
-
evergreen_dir: ~/src/evergreen
|
|
328
|
+
base_dir: ~/architect # spaces_dir + src_dir hang off this by default
|
|
206
329
|
default_provider: github.com
|
|
207
330
|
default_organization:
|
|
208
|
-
git_clone_protocol: ssh
|
|
331
|
+
git_clone_protocol: ssh # ssh | https
|
|
209
332
|
```
|
|
210
333
|
|
|
211
|
-
|
|
334
|
+
Derived defaults: `spaces_dir` → `<base_dir>/spaces`, `src_dir` (evergreen
|
|
335
|
+
checkout root) → `<base_dir>/src`. Override either explicitly. View values with
|
|
336
|
+
`space config show`; set one with `space config set KEY VALUE`. Editable keys:
|
|
337
|
+
`base_dir`, `spaces_dir`, `src_dir`, `default_provider`, `default_organization`,
|
|
338
|
+
`git_clone_protocol`.
|
|
212
339
|
|
|
213
|
-
## Repos: evergreen, copy-on-write, concurrent
|
|
340
|
+
## Repos: evergreen, copy-on-write, concurrent ⚡
|
|
214
341
|
|
|
215
342
|
Repos are added to the current space under `repos/` and tracked in `space.yaml`.
|
|
216
|
-
When an up-to-date
|
|
217
|
-
`<
|
|
218
|
-
`~/src/
|
|
219
|
-
space instead of cloning over the network —
|
|
220
|
-
|
|
343
|
+
When an up-to-date evergreen checkout exists at
|
|
344
|
+
`<src_dir>/<host>/<owner>/<name>` (e.g.
|
|
345
|
+
`~/architect/src/github.com/example-org/example-app`), `space` copies it into the
|
|
346
|
+
space instead of cloning over the network — a copy-on-write clone on APFS. ⚡
|
|
347
|
+
Set `src_dir` empty to always clone:
|
|
221
348
|
|
|
222
349
|
```sh
|
|
223
|
-
|
|
350
|
+
space config set src_dir ""
|
|
224
351
|
```
|
|
225
352
|
|
|
226
|
-
|
|
227
|
-
|
|
353
|
+
Clone URLs default to SSH (`git@github.com:example-org/example-app.git`); switch
|
|
354
|
+
with `space config set git_clone_protocol https`. Multiple repos passed to
|
|
355
|
+
`space repo add` are fetched **concurrently**, up to five at a time, on fibers —
|
|
356
|
+
no threads, all cooperative. 🧵 After each repo lands, `space` runs `mise trust`
|
|
357
|
+
in it. Each space also gets a workspace-local `tmp/` — use it instead of `/tmp`.
|
|
228
358
|
|
|
229
|
-
|
|
230
|
-
architect space config set git_clone_protocol https
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
When stdout/stderr are attached to a TTY, long-running repo operations show an
|
|
234
|
-
interactive spinner. Multiple repos passed to `architect space repo add` are fetched
|
|
235
|
-
**concurrently**, up to five at a time, on fibers — no threads, all cooperative. 🧵
|
|
236
|
-
After each repo is in place, `architect` runs `mise trust` in it so local mise config
|
|
237
|
-
is ready to go.
|
|
359
|
+
## Embedding 📚
|
|
238
360
|
|
|
239
|
-
|
|
240
|
-
`/var/tmp`; when using `mktemp`, point it at `tmp/`. 🗑️
|
|
361
|
+
The library is split into three namespaces you can require independently:
|
|
241
362
|
|
|
242
|
-
|
|
363
|
+
- **`Space::Core`** — the foundation: config, state, XDG, terminal, git/mise
|
|
364
|
+
clients, the space store. The `space` CLI runs on this alone.
|
|
365
|
+
- **`Space::Architect`** — project state, the builder harness, dispatch, and the
|
|
366
|
+
research supervisor.
|
|
367
|
+
- **`Space::Src`** — the evergreen engine (tracking, sync, copy-on-write clone).
|
|
243
368
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
fetched.
|
|
249
|
-
|
|
250
|
-
```sh
|
|
251
|
-
architect src repo add github.com/example-org/example-app # tend it 🌲
|
|
252
|
-
architect src sync # run one sync pass
|
|
253
|
-
architect src status # per-repo evergreen status
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
When `architect space repo add` sees a matching evergreen copy, it copy-on-writes
|
|
257
|
-
from it instead of hitting the network — instant provisioning. ⚡
|
|
258
|
-
|
|
259
|
-
The vendored engine and space management share the same layout by design — both use
|
|
260
|
-
`<evergreen_dir>/<host>/<owner>/<repo>` — so they line up with zero configuration:
|
|
261
|
-
|
|
262
|
-
```sh
|
|
263
|
-
architect src repo add github.com/example-org/example-app # tend it: keep it evergreen 🌲
|
|
264
|
-
architect space repo add example-app # copies it instantly ⚡
|
|
369
|
+
```ruby
|
|
370
|
+
require "space_core" # just spaces
|
|
371
|
+
require "space_architect" # the full loop (pulls in core + src)
|
|
372
|
+
require "space_src" # just the evergreen engine
|
|
265
373
|
```
|
|
266
374
|
|
|
267
375
|
## Documentation 📖
|
|
268
376
|
|
|
269
377
|
- **[Command Reference](docs/reference.md)** — every command, flag, and behavior
|
|
270
|
-
- **[Design](docs/
|
|
378
|
+
- **[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
|
|
379
|
+
- **[Changelog](CHANGELOG.md)** — release history
|
|
271
380
|
|
|
272
381
|
## Development 🛠️
|
|
273
382
|
|
data/exe/architect
CHANGED
data/exe/space
CHANGED
data/exe/src
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
source_gemfile = File.expand_path("../Gemfile", __dir__)
|
|
5
|
+
if File.exist?(source_gemfile)
|
|
6
|
+
ENV["BUNDLE_GEMFILE"] ||= source_gemfile
|
|
7
|
+
require "bundler/setup"
|
|
8
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require "space_src"
|
|
12
|
+
|
|
13
|
+
Space::Src::CLI.run(ARGV, $stdout, $stderr)
|