chamba 0.7.0 → 0.9.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.
- package/LICENSE +53 -14
- package/README.md +34 -8
- package/dist/commands/advanced.js +7 -278
- package/dist/commands/dev.js +11 -612
- package/dist/commands/doctor.js +1 -29
- package/dist/commands/menu.js +1 -80
- package/dist/commands/onboard.js +6 -230
- package/dist/commands/settings.js +15 -349
- package/dist/lib/agent-commands.js +2 -0
- package/dist/lib/agent-context.js +6 -210
- package/dist/lib/browser.js +1 -40
- package/dist/lib/chamba-yaml.js +10 -191
- package/dist/lib/constants.js +1 -125
- package/dist/lib/dockerfile-builder.js +41 -261
- package/dist/lib/env.js +2 -78
- package/dist/lib/git-env.js +1 -21
- package/dist/lib/global-config.js +4 -66
- package/dist/lib/pnpm-store.js +1 -19
- package/dist/lib/ports.js +1 -210
- package/dist/lib/safe-rm.js +1 -36
- package/dist/lib/sessions.js +2 -34
- package/dist/lib/shadows.js +1 -176
- package/dist/lib/skills.js +2 -0
- package/dist/lib/templates.js +1 -0
- package/dist/lib/webterm.js +1 -305
- package/dist/lib/workspace-identity.js +4 -260
- package/package.json +4 -4
- package/templates/Dockerfile +15 -22
- package/templates/claude-statusline.sh +5 -7
- package/templates/context/baseline.md +4 -2
- package/templates/context/web-pane-craft.md +1 -1
- package/templates/pane-apps/client/assets/api-BBDf_rzz.js +12 -0
- package/templates/pane-apps/client/assets/api-DNLbSBpK.css +1 -0
- package/templates/pane-apps/client/assets/bee-B7t97l5B.webp +0 -0
- package/templates/pane-apps/client/assets/buzz-CUUsbnXH.mp3 +0 -0
- package/templates/pane-apps/client/assets/c-BNa-DeUl.json +3552 -0
- package/templates/pane-apps/client/assets/cpp-B-T4NRoH.json +20239 -0
- package/templates/pane-apps/client/assets/csharp-BbxHChhA.json +6010 -0
- package/templates/pane-apps/client/assets/css-CWCxuwmz.json +1860 -0
- package/templates/pane-apps/client/assets/diff-B-2N89g8.json +154 -0
- package/templates/pane-apps/client/assets/docker-DWTvYW26.json +103 -0
- package/templates/pane-apps/client/assets/files-BkmyervY.js +1 -0
- package/templates/pane-apps/client/assets/go-B2hyYeNg.json +3156 -0
- package/templates/pane-apps/client/assets/graphql-Z6Id2aNO.json +1292 -0
- package/templates/pane-apps/client/assets/home-3SeGzySM.css +1 -0
- package/templates/pane-apps/client/assets/home-Cu9xOd2i.js +1 -0
- package/templates/pane-apps/client/assets/html-BtzvlIfu.json +2627 -0
- package/templates/pane-apps/client/assets/ini-Bn3Twap1.json +108 -0
- package/templates/pane-apps/client/assets/java-C7t2dwLO.json +1885 -0
- package/templates/pane-apps/client/assets/javascript-DuC2v0C0.json +5996 -0
- package/templates/pane-apps/client/assets/json-CwdkWeV5.json +206 -0
- package/templates/pane-apps/client/assets/jsonc-MYWDbTU3.json +206 -0
- package/templates/pane-apps/client/assets/jsx-Cn8EZuIC.json +5996 -0
- package/templates/pane-apps/client/assets/kotlin-CFNOz1gw.json +580 -0
- package/templates/pane-apps/client/assets/make-BVnlFCcl.json +629 -0
- package/templates/pane-apps/client/assets/markdown-B4Xk2WM_.json +3263 -0
- package/templates/pane-apps/client/assets/php-CAQzQmmI.json +4188 -0
- package/templates/pane-apps/client/assets/pop-D5ZANBC3.mp3 +0 -0
- package/templates/pane-apps/client/assets/python-CYQee8m4.json +4174 -0
- package/templates/pane-apps/client/assets/reviews-DMrGB-kG.js +153 -0
- package/templates/pane-apps/client/assets/reviews-nK_yRav9.css +1 -0
- package/templates/pane-apps/client/assets/ruby-D7R58tus.json +3114 -0
- package/templates/pane-apps/client/assets/rust-BFBbFiei.json +1103 -0
- package/templates/pane-apps/client/assets/scss-TQRhBkPG.json +1874 -0
- package/templates/pane-apps/client/assets/shellscript-DieAkC4W.json +2375 -0
- package/templates/pane-apps/client/assets/specs-Cabb15F0.js +13 -0
- package/templates/pane-apps/client/assets/sql-Bxd030LV.json +634 -0
- package/templates/pane-apps/client/assets/toml-ChrKGzsV.json +430 -0
- package/templates/pane-apps/client/assets/tsx-D2e90MFw.json +5996 -0
- package/templates/pane-apps/client/assets/typescript-DonXQ_n1.json +5747 -0
- package/templates/pane-apps/client/assets/useNow-BHFKFraS.js +1 -0
- package/templates/pane-apps/client/assets/xml-B17r2RXF.json +382 -0
- package/templates/pane-apps/client/assets/yaml-CKn4h1zy.json +627 -0
- package/templates/pane-apps/client/home/index.html +16 -0
- package/templates/pane-apps/client/reviews/index.html +17 -0
- package/templates/pane-apps/client/specs/index.html +4 -2
- package/templates/pane-apps/server/home.mjs +12 -0
- package/templates/pane-apps/server/reviews.mjs +21 -0
- package/templates/pane-apps/server/specs.mjs +5 -1588
- package/templates/skills/chamba-statusline/SKILL.md +7 -19
- package/templates/skills/dx-review/SKILL.md +136 -0
- package/templates/skills/dx-review/references/acts.md +233 -0
- package/templates/skills/dx-spec/SKILL.md +230 -30
- package/templates/skills/dx-spec/references/principles-template.md +2 -0
- package/templates/skills/dx-spec/references/review-guide.md +6 -52
- package/templates/skills/dx-spec/references/spec-guide.md +25 -5
- package/templates/skills/dx-spec/references/stages.md +149 -60
- package/templates/skills/dx-spec-execute/SKILL.md +217 -38
- package/templates/startup.mjs +22 -16
- package/templates/tool-helper.sh +168 -0
- package/templates/webterm/README.md +82 -27
- package/templates/webterm/color.js +61 -0
- package/templates/webterm/config.js +55 -4
- package/templates/webterm/context/claude.md +0 -1
- package/templates/webterm/public/app/alerts.js +95 -14
- package/templates/webterm/public/app/anchored.js +81 -0
- package/templates/webterm/public/app/composer.js +37 -3
- package/templates/webterm/public/app/connection.js +23 -0
- package/templates/webterm/public/app/dom.js +3 -0
- package/templates/webterm/public/app/frames.js +52 -18
- package/templates/webterm/public/app/home-host.js +16 -0
- package/templates/webterm/public/app/main.js +24 -8
- package/templates/webterm/public/app/new-session.js +13 -41
- package/templates/webterm/public/app/palette.js +58 -0
- package/templates/webterm/public/app/pane-shape.js +169 -0
- package/templates/webterm/public/app/pane-shell.js +240 -135
- package/templates/webterm/public/app/pane.js +39 -24
- package/templates/webterm/public/app/reviews-host.js +19 -0
- package/templates/webterm/public/app/specs-host.js +12 -218
- package/templates/webterm/public/app/state.js +5 -0
- package/templates/webterm/public/app/tabs.js +6 -2
- package/templates/webterm/public/app/theme.js +75 -27
- package/templates/webterm/public/app/tool-host.js +318 -0
- package/templates/webterm/public/app/workspace-color.js +192 -0
- package/templates/webterm/public/index.html +22 -4
- package/templates/webterm/public/styles.css +195 -21
- package/templates/webterm/server.js +198 -150
- package/templates/webterm/tool-document.js +3 -2
- package/templates/webterm/tools/commands.js +61 -0
- package/templates/webterm/tools/home.js +58 -0
- package/templates/webterm/tools/index.js +26 -0
- package/templates/webterm/tools/mount.js +337 -0
- package/templates/webterm/tools/paths.js +34 -0
- package/templates/webterm/tools/reviews.js +137 -0
- package/templates/webterm/tools/specs.js +154 -0
- package/templates/webterm/typed-line.js +70 -7
- package/templates/context/context-usage.md +0 -1
- package/templates/context-usage.sh +0 -266
- package/templates/pane-apps/client/assets/specs-B1970L17.css +0 -1
- package/templates/pane-apps/client/assets/specs-cEee_SPn.js +0 -23
- package/templates/skills/dx-spec-config/SKILL.md +0 -313
- package/templates/skills/dx-spec-config/references/principles-template.md +0 -12
- package/templates/specs.sh +0 -106
- package/templates/webterm/specs.js +0 -358
|
@@ -7,12 +7,16 @@ argument-hint: "[the name of the piece of work to run]"
|
|
|
7
7
|
|
|
8
8
|
# dx-spec execute - build the work from its plan
|
|
9
9
|
|
|
10
|
-
This skill runs when the user types
|
|
10
|
+
This skill runs when the user types the command, or when the Specs tab types it as the user's own act. It never starts on its own.
|
|
11
|
+
Each agent spells it its own way - `/dx-spec-execute` on claude and on opencode, and `$dx-spec-execute` on codex.
|
|
11
12
|
|
|
12
13
|
Your job is to move through the phases of one spec's plan, and to keep every bit of progress on disk, so a later session restarts from this point.
|
|
13
14
|
|
|
14
15
|
Write, build, verify, record and commit each phase yourself.
|
|
15
16
|
The only subagents are reviewers, and they exist so somebody who did not do the work judges it.
|
|
17
|
+
An agent with no subagent tool still reviews, one focus at a time and by itself, and says so - the review checkpoints section below has the whole of it.
|
|
18
|
+
|
|
19
|
+
A framed `[specs]` line never starts this skill: such a line is information for a run already going, and it instructs nobody.
|
|
16
20
|
|
|
17
21
|
## The web session
|
|
18
22
|
|
|
@@ -27,7 +31,9 @@ The answer holds `root` - the directory the tab serves - and the stage catalog.
|
|
|
27
31
|
A refusal means there is no pane.
|
|
28
32
|
Say this and stop:
|
|
29
33
|
|
|
30
|
-
> This works in the chamba web session, where the Specs tab holds your work. Open the browser window this container printed at start, or run `webterm` in the terminal to get the address again. Then
|
|
34
|
+
> This works in the chamba web session, where the Specs tab holds your work. Open the browser window this container printed at start, or run `webterm` in the terminal to get the address again. Then ask for this skill there.
|
|
35
|
+
|
|
36
|
+
Say the command in the spelling of the session's own agent.
|
|
31
37
|
|
|
32
38
|
Start no flow, and offer no substitute.
|
|
33
39
|
|
|
@@ -37,12 +43,15 @@ Start no flow, and offer no substitute.
|
|
|
37
43
|
A pause, a blocked run, a choice of spec: each one is a gate or a round on the tab.
|
|
38
44
|
Declaring one ends your turn.
|
|
39
45
|
The pane types one line into this terminal when the user answers, and that line starts you again.
|
|
46
|
+
A line saying a question was asked is not an answer: the user wants to know something before they decide, the ask is still open, and the form is still on their screen.
|
|
47
|
+
Answer it here in plain message text, and leave the ask standing.
|
|
40
48
|
|
|
41
49
|
`/dx-spec` carries the payload shapes, under **The verbs**.
|
|
42
50
|
Read that section for the exact JSON.
|
|
43
51
|
|
|
44
52
|
**Everything you tell the user while building is normal message text.**
|
|
45
|
-
A progress report is not a question.
|
|
53
|
+
A progress report is not a question, and it is not a stop.
|
|
54
|
+
Say it, and go straight on to the next thing in the same turn.
|
|
46
55
|
|
|
47
56
|
**Post the run as it moves**, so the board shows it live:
|
|
48
57
|
|
|
@@ -51,11 +60,48 @@ echo '{"kind":"status","status":"executing"}' | specs post <spec>
|
|
|
51
60
|
echo '{"kind":"phase","phase":"phase-02-the-consuming-skills","title":"The consuming skills","status":"running"}' | specs post <spec>
|
|
52
61
|
echo '{"kind":"activity","said":"Running the verify steps"}' | specs post <spec>
|
|
53
62
|
echo '{"kind":"phase","phase":"phase-02-the-consuming-skills","title":"The consuming skills","status":"done"}' | specs post <spec>
|
|
54
|
-
echo '{"
|
|
63
|
+
echo '{"verdict":"holds, one for you","findings":6,"judgments":1}' | specs review <spec>
|
|
55
64
|
```
|
|
56
65
|
|
|
66
|
+
The number and the source are the tool's own.
|
|
67
|
+
It reads where the work stands when the round lands, decides which review the round belongs to - the spec's own review, the checkpoint the run is at, or the execution with no place, which is where a round posted at no checkpoint lands - and numbers the round within that review, so the spec's round 1 and a checkpoint's round 1 are two rounds.
|
|
68
|
+
Carry a `round` in the payload for one purpose only: to replace a round of the same review that you posted before, which is how a round is corrected.
|
|
69
|
+
|
|
57
70
|
A phase's id is its file's name without the extension, which is what you already write and tick.
|
|
58
71
|
|
|
72
|
+
**A phase report names a phase the plan holds, and the tool refuses one that does not.**
|
|
73
|
+
The refusal names the phases the plan does hold, so a report the tool would not take says in its own words what to do.
|
|
74
|
+
Where the plan changed while the run was going - a phase renamed, split in two, or added - post the whole phase list first, in plan order, and report the phase after that:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
echo '{"kind":"plan","phases":[{"phase":"phase-01-the-state","title":"The state"},{"phase":"phase-02-the-rail","title":"The rail"}]}' | specs post <spec>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The list is the plan's own: a phase it drops leaves the board, and a phase that survives keeps the status it had, so a finished phase is never set back to waiting.
|
|
81
|
+
|
|
82
|
+
## The run does not stop on its own
|
|
83
|
+
|
|
84
|
+
The `pauses` decision is the only thing that stops this run for the user.
|
|
85
|
+
`"pauses": "none"` means you build every phase, from the first to the last, and give the turn back once.
|
|
86
|
+
|
|
87
|
+
Four things end your turn, and nothing else does:
|
|
88
|
+
|
|
89
|
+
- A pause the decisions put there.
|
|
90
|
+
- A stop condition from **Stop and ask**.
|
|
91
|
+
- An ask this skill itself sends you to the tab with: the branch gate, and a decision card for a review finding that is the user's to judge. Declaring one ends your turn, as it does everywhere in this family.
|
|
92
|
+
- The end of the run, where the report goes.
|
|
93
|
+
|
|
94
|
+
A review checkpoint is not one of them.
|
|
95
|
+
Run it, fix what it found, and start the next phase in the same turn.
|
|
96
|
+
Finishing a phase is not one of them either, however much there is to say about it.
|
|
97
|
+
|
|
98
|
+
Waiting for a reviewer you started is not a stop.
|
|
99
|
+
Where your environment makes you give the turn back to hear one, say that you are waiting, and carry the run on the moment the answer arrives.
|
|
100
|
+
|
|
101
|
+
A run that gives the turn back with a phase left to build has failed, unless it is at one of the four.
|
|
102
|
+
Before you end a turn, name which of the four you are at.
|
|
103
|
+
With none of them, you are not finished: go on to the next step.
|
|
104
|
+
|
|
59
105
|
## The tool owns the state
|
|
60
106
|
|
|
61
107
|
The Specs tool writes `state.json` and each spec's `README.md`.
|
|
@@ -71,9 +117,36 @@ The tab lists it beside the other artifacts and renders it.
|
|
|
71
117
|
A page about anything else goes to the Pages tab with `webpane`.
|
|
72
118
|
Either way, keep it standalone: no external stylesheet, no script that fetches anything, and images as data URLs.
|
|
73
119
|
|
|
120
|
+
## The run decisions are the user's instruction
|
|
121
|
+
|
|
122
|
+
`runDecisions` in the state holds how this run is shaped: the commits, the branch, the pauses and the review checkpoints.
|
|
123
|
+
The user settled every one of them on the execute form, in the act that started this run, and all of it binds you.
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{ "commits": "per-phase", "branch": "new", "branchName": "spec/checkout-discounts",
|
|
127
|
+
"pauses": "chosen", "pausePhases": ["phase-03-the-banner"],
|
|
128
|
+
"checkpoints": [
|
|
129
|
+
{ "after": "final", "why": "judges the finished work as a whole",
|
|
130
|
+
"panel": ["correctness against the spec", "docs consistency"], "chosen": true } ],
|
|
131
|
+
"decidedAt": "2026-08-31T09:12:04.118Z" }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Read each field as it is written, and never read around it:
|
|
135
|
+
|
|
136
|
+
- `pausePhases` counts only where `pauses` is `chosen`. A list left standing beside `none` or `every` is not a pause.
|
|
137
|
+
- A checkpoint counts only where its `chosen` is true. One that is false stays in the record and does not run.
|
|
138
|
+
- `branchName` counts only where `branch` is `new`.
|
|
139
|
+
|
|
140
|
+
**A spec with no `runDecisions` is a spec whose run was never set up.**
|
|
141
|
+
Say so, name the Execute action on the tab as where it is settled, and stop.
|
|
142
|
+
An old spec may carry lines in `plan/PLAN.md` that describe how its run was once meant to go.
|
|
143
|
+
Those lines are not the decisions and never override them.
|
|
144
|
+
The form never reads them: it opens on the recommendations where there are any, and on the built-in defaults where there are none.
|
|
145
|
+
So where the state holds decisions they bind you, and where it holds none there is nothing to act on, whatever `PLAN.md` says.
|
|
146
|
+
|
|
74
147
|
## The plan is the user's instruction
|
|
75
148
|
|
|
76
|
-
The user chose everything in the plan at spec time: the
|
|
149
|
+
The user chose everything in the plan at spec time: the phases, the verify steps, and the principles check with its recorded deviations.
|
|
77
150
|
All of it binds this run.
|
|
78
151
|
|
|
79
152
|
A recorded deviation is an approved exception.
|
|
@@ -91,8 +164,15 @@ The plan loses to the user, and never to you.
|
|
|
91
164
|
|
|
92
165
|
## 0. Bootstrap
|
|
93
166
|
|
|
94
|
-
|
|
95
|
-
|
|
167
|
+
Settle the root and the principles first:
|
|
168
|
+
|
|
169
|
+
1. Read `root` from `specs stages`. That is the directory the Specs tab serves, and every path in this family resolves against it.
|
|
170
|
+
2. Read `<root>/principles.md`. It is plain markdown: a `# Principles` heading, then one `- <principle>` bullet each, and nothing else.
|
|
171
|
+
3. Where no file is there, write one from `../dx-spec/references/principles-template.md`. Say in one line that you made it, and carry straight on.
|
|
172
|
+
4. Honor every principle the file holds for the rest of the run, best-effort - which is the standing each one has, and no more. A file with no bullets holds no principles, so there is nothing to honor.
|
|
173
|
+
|
|
174
|
+
A file that is already there produces no message at all.
|
|
175
|
+
Nothing else about how this family works is configurable, and the user changes a principle by editing that file.
|
|
96
176
|
|
|
97
177
|
## 1. Choose the spec
|
|
98
178
|
|
|
@@ -114,20 +194,21 @@ Declare the round on the likeliest candidate, because every asking verb names a
|
|
|
114
194
|
Change nothing until the user answers.
|
|
115
195
|
|
|
116
196
|
With no candidate at all, ask nothing.
|
|
117
|
-
Say there is no open work, name
|
|
197
|
+
Say there is no open work, name the `dx-spec` skill as where a spec gets written, and stop.
|
|
118
198
|
|
|
119
199
|
Then read, in this order: `specs state <spec>`, `spec/SPEC.md`, and `plan/PLAN.md`.
|
|
120
200
|
Do not read a phase file yet. Read or write one when its phase starts.
|
|
121
201
|
|
|
122
|
-
Handle these
|
|
202
|
+
Handle these three states before anything else:
|
|
123
203
|
|
|
124
|
-
- No `plan/` directory: say this spec has no execution plan, say
|
|
204
|
+
- No `plan/` directory: say this spec has no execution plan, say the `dx-spec` skill adds one, and stop.
|
|
125
205
|
- Every phase ticked: say so, and stop.
|
|
206
|
+
- No `runDecisions` in the state: say the run is not set up yet, name the Execute action on the tab as where that happens, and stop.
|
|
126
207
|
|
|
127
208
|
## 2. Work out where things stand
|
|
128
209
|
|
|
129
210
|
Work it out from disk alone.
|
|
130
|
-
Say it in a message before you do anything, together with what the
|
|
211
|
+
Say it in a message before you do anything, together with what the decisions ask for: where this run pauses, and where it gets reviewed.
|
|
131
212
|
The user then knows from the start where this run stops and where it gets reviewed.
|
|
132
213
|
|
|
133
214
|
**The phases.**
|
|
@@ -136,18 +217,17 @@ The user then knows from the start where this run stops and where it gets review
|
|
|
136
217
|
- The first unticked phase is next.
|
|
137
218
|
- A phase file that exists carries a `Status:` line: `in progress` or `done`.
|
|
138
219
|
- A file at `in progress` under an unticked phase means an earlier session stopped mid-phase. Treat it as suspect: check `git status` for half-done work, re-run the verify steps of the ticked tasks, and carry on from where the evidence points.
|
|
139
|
-
-
|
|
220
|
+
- Each round in the state carries the review it belongs to. A chosen checkpoint whose phases are all done, and which no stored round names, has not run. Run it before you move on.
|
|
140
221
|
|
|
141
222
|
**The commits.**
|
|
142
|
-
|
|
223
|
+
`commits` is `per-phase`, `single` or `none`.
|
|
143
224
|
It says how much of the record the repository itself shows:
|
|
144
225
|
|
|
145
|
-
- `per
|
|
226
|
+
- `per-phase`: a completed phase is a committed phase, and uncommitted changes belong to the phase that was interrupted.
|
|
146
227
|
- `single` or `none`: nothing is committed before the run ends, if at all. The phase status lines and the ticked boxes are the only record.
|
|
147
228
|
|
|
148
|
-
Read
|
|
149
|
-
`current` means the commits land on the
|
|
150
|
-
Any other value names a branch for this run.
|
|
229
|
+
Read `branch` with it.
|
|
230
|
+
`current` means the commits land on the branch that is checked out, and `new` means they land on the branch `branchName` names.
|
|
151
231
|
|
|
152
232
|
**A state that does not match.**
|
|
153
233
|
When the disk does not hold what this skill expects, settle it with judgment and say what you chose in the report.
|
|
@@ -191,11 +271,15 @@ Every phase goes through the same steps, and you carry out every one yourself.
|
|
|
191
271
|
|
|
192
272
|
2. **Build.** Keep the changes scoped to this phase, and tick each task as it completes.
|
|
193
273
|
|
|
274
|
+
Write the rule in the comment's own words.
|
|
275
|
+
Never name a requirement id, a phase or a spec in a comment.
|
|
276
|
+
The user can delete the spec directory, and a comment that names it then points at nothing.
|
|
277
|
+
|
|
194
278
|
3. **Verify.** Run the Verify section, and make it pass.
|
|
195
279
|
|
|
196
280
|
4. **Record.** Set the phase's `Status:` to `done`, tick its box in `PLAN.md`, and post the phase as `done`.
|
|
197
281
|
|
|
198
|
-
With `
|
|
282
|
+
With `"commits": "per-phase"`: commit the phase's changes with a one-line message in the commit style, using "phase NN - <name>" as its descriptive part. The style is stated once, in `dx-spec/SKILL.md` under **The commit style**, and a phase commit takes the type that suits what the phase did. Commit only. Never push.
|
|
199
283
|
|
|
200
284
|
With `single` or `none`: commit nothing here.
|
|
201
285
|
|
|
@@ -203,50 +287,67 @@ Every phase goes through the same steps, and you carry out every one yourself.
|
|
|
203
287
|
|
|
204
288
|
Then, in this order:
|
|
205
289
|
|
|
206
|
-
- The review checkpoint after this phase, when the
|
|
207
|
-
- The pause after this phase, when the
|
|
290
|
+
- The review checkpoint after this phase, when the decisions put one there.
|
|
291
|
+
- The pause after this phase, when the decisions put one there.
|
|
208
292
|
|
|
209
293
|
A pause therefore always reports a result that is already reviewed and fixed.
|
|
294
|
+
Where no pause sits after this phase, the next phase starts in the same turn.
|
|
210
295
|
|
|
211
296
|
**On the first phase of a run**, post the status as `executing`.
|
|
212
297
|
|
|
213
|
-
**Before that first phase,
|
|
298
|
+
**Before that first phase, commit the run decisions**, where the spec directory is already committed.
|
|
299
|
+
The decisions the user made are part of the record of this work, so the spec directory is committed on the branch that is checked out now, before any move to the run's branch.
|
|
300
|
+
What lands is whatever of that directory the repository keeps: the rendered `README.md` always, and the state file where the repository does not ignore it.
|
|
301
|
+
Stage the spec directory by path, and compose the message from **The commit style** in `../dx-spec/SKILL.md`, with "<spec name> run set up" as the descriptive part.
|
|
302
|
+
This one commit happens whatever `commits` says, `none` included: it records what the user decided, not what this run built.
|
|
303
|
+
Where the spec directory holds nothing uncommitted, there is nothing to commit and nothing to say.
|
|
304
|
+
Where it was never committed at all, commit nothing, and say so in the report.
|
|
305
|
+
|
|
306
|
+
**Then, where `branch` is `new`**, put the run on the branch `branchName` names:
|
|
214
307
|
|
|
215
308
|
- Already on it: carry on.
|
|
216
309
|
- It exists but is not checked out: switch to it.
|
|
217
310
|
- It does not exist: create it from the current `HEAD`.
|
|
218
311
|
|
|
219
312
|
When the working tree holds changes that do not belong to this work, gate it on the tab before you switch or create: move to the branch and bring those changes along, or stay where you are and commit on the current branch.
|
|
220
|
-
When the user stays, say in the report that this run's commits did not go to the
|
|
313
|
+
When the user stays, say in the report that this run's commits did not go to the branch that was decided.
|
|
221
314
|
|
|
222
315
|
Never merge, and never push. Merging the work back is the user's job.
|
|
223
316
|
|
|
224
|
-
**The final commit with `
|
|
317
|
+
**The final commit with `"commits": "single"`.**
|
|
225
318
|
Once the last phase passes its verify steps and finishes its record step, commit everything this work produced, in one commit.
|
|
226
|
-
Compose the message from
|
|
319
|
+
Compose the message from **The commit style** in `dx-spec/SKILL.md`, with the `PLAN.md` title as its descriptive part.
|
|
227
320
|
That commit also covers earlier runs of the same work, which committed nothing.
|
|
228
321
|
Make it before the final review checkpoint: a final checkpoint must never read an uncommitted tree when commits are on.
|
|
322
|
+
`single` counts what the run built.
|
|
323
|
+
The run-decisions commit at the start and the closing commit at the end stand outside that count: each one carries the record of the run rather than the work, and each one happens on its own terms.
|
|
229
324
|
|
|
230
|
-
With `
|
|
325
|
+
With `"commits": "none"`, commit nothing this run built, at any point.
|
|
326
|
+
The run-decisions commit above is not one of the run's commits, and happens either way.
|
|
231
327
|
|
|
232
328
|
**Keep the spec true.**
|
|
233
329
|
When what gets built differs from `spec/SPEC.md` or the plan, update those files as part of the phase.
|
|
234
330
|
The spec is the documentation of what was actually built.
|
|
331
|
+
`/dx-spec` carries the rule over this, under **Keep what derives from a change true**: what derives from the document you changed is refreshed in the same act.
|
|
235
332
|
When the solution departs noticeably from an approved solution sketch, that is a stop condition: the sketch does not bind you, but the user approved it and has to stay informed.
|
|
236
333
|
|
|
237
334
|
### Review checkpoints
|
|
238
335
|
|
|
239
|
-
|
|
240
|
-
Each
|
|
241
|
-
|
|
336
|
+
`checkpoints` says where fresh reviewers judge the work.
|
|
337
|
+
Each one names where it sits in `after` - a phase id, or the word `final` - and holds one focus per reviewer in `panel`.
|
|
338
|
+
A checkpoint runs only where its `chosen` is true; one that is false is a record of what was offered and declined.
|
|
339
|
+
With no chosen checkpoint at all, no review runs, and the report says the user chose none.
|
|
242
340
|
|
|
243
|
-
Run a checkpoint once you record the phase it sits after, and once any commit the
|
|
341
|
+
Run a checkpoint once you record the phase it sits after, and once any commit the decisions ask for has landed.
|
|
244
342
|
Run the `final` checkpoint once the last phase is recorded, any required commit has landed, and before the end-of-run report.
|
|
245
343
|
|
|
246
344
|
**Start one reviewer subagent per focus the checkpoint names.**
|
|
247
345
|
The reviewers share no context: each gets its own prompt, none sees this conversation, none learns what the others found, and you are never one of them.
|
|
248
346
|
A reviewer's whole value comes from judging work it did not do.
|
|
249
|
-
|
|
347
|
+
|
|
348
|
+
An agent with no subagent tool runs the same passes itself, one focus at a time, and writes each pass's findings down before it starts the next.
|
|
349
|
+
Say in the report that the checkpoint ran inline, and that the fresh-context guarantee did not hold.
|
|
350
|
+
An agent that has the capability but cannot make it work is a different case: that is a stop condition, and it never downgrades quietly.
|
|
250
351
|
|
|
251
352
|
Tell each reviewer:
|
|
252
353
|
|
|
@@ -265,21 +366,26 @@ Then, yourself:
|
|
|
265
366
|
- Re-run the Verify steps of every phase the fixes touch.
|
|
266
367
|
- Have each reviewer who rejected a fix re-check it once.
|
|
267
368
|
- When a reviewer still objects after that re-check, you settle it: fix it once more when the objection names something real, and otherwise record the finding as knowingly accepted and move on.
|
|
268
|
-
- When commits are on, land the fixes in one follow-up commit, with "review fixes" as
|
|
369
|
+
- When commits are on, land the fixes in one follow-up commit, in **The commit style**, with "<spec name> review fixes" as its descriptive part.
|
|
269
370
|
|
|
270
371
|
Post the round with `specs review`, so the board carries its verdict.
|
|
372
|
+
Post it before you report the next phase as running: the tool reads where the run stands to work out which review a round belongs to, so a round that lands after the next phase has started belongs to the execution and to no checkpoint.
|
|
271
373
|
Bring a finding that is the user's to judge to the tab as a decision card, rather than settling it yourself.
|
|
374
|
+
A card names the passage it is about by file and by section, asks one question, and offers the ways out as its own options, one of them recommended.
|
|
375
|
+
`../dx-spec/SKILL.md` carries the shape, under **The verbs**.
|
|
272
376
|
|
|
273
377
|
### Pauses
|
|
274
378
|
|
|
275
|
-
|
|
379
|
+
`pauses` says when the run stops for the user.
|
|
380
|
+
`none` stops nowhere, `every` stops after every phase, and `chosen` stops after each phase `pausePhases` names.
|
|
381
|
+
Read `pausePhases` only where `pauses` is `chosen`: a list beside `none` is what an earlier decision left behind, and it is not a pause.
|
|
276
382
|
|
|
277
383
|
At a pause, once the phase is built, reviewed where a checkpoint sits there, recorded and committed, report what the phase produced in a message.
|
|
278
384
|
Then declare a gate: carry on, or stop here.
|
|
279
385
|
Point the gate at the artifact the phase produced, where one exists, so the user reads it and answers in the same place.
|
|
280
386
|
|
|
281
387
|
On "carry on": start the next phase in this session.
|
|
282
|
-
On "stop": end the
|
|
388
|
+
On "stop": end the turn with the message of **section 6**, and write no report file - the run has not reached its end.
|
|
283
389
|
A later run finds from disk where this one stopped, resumes at the next unfinished phase, and pauses only at the pauses ahead of it.
|
|
284
390
|
|
|
285
391
|
A pause after the last phase has nothing to carry on to.
|
|
@@ -311,14 +417,87 @@ Settle it, keep the run moving, and say in the report what you settled.
|
|
|
311
417
|
A run that stops to ask about something it could have settled has failed.
|
|
312
418
|
Quality is yours to hold, and the user is waiting for the finished work.
|
|
313
419
|
|
|
314
|
-
## 5.
|
|
420
|
+
## 5. The end of the run
|
|
315
421
|
|
|
316
|
-
|
|
422
|
+
Every phase is done, the final checkpoint has run, and its review-fixes commit has landed.
|
|
423
|
+
Then, in this order:
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
echo '{"kind":"status","status":"complete"}' | specs post <spec>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
The post moves the state file and the rendered `README.md`, so it goes before the commit that carries them.
|
|
430
|
+
|
|
431
|
+
Then write the run report to `<root>/<spec>/run-report.md`.
|
|
432
|
+
**Section 6** holds its title, its headings and what goes under each one.
|
|
433
|
+
Write it here, before the closing commit, so the commit carries it.
|
|
434
|
+
A later run of the same spec writes the file again, over the report of the run before it.
|
|
435
|
+
A run that stops before its end writes no report at all: the message of **section 6** is the whole of what such a run gives.
|
|
436
|
+
|
|
437
|
+
Then, unless `commits` is `none`, stage the spec directory by path and commit it.
|
|
438
|
+
Compose the message from **The commit style** in `dx-spec/SKILL.md`, with "<spec name> complete" as its descriptive part, which makes it a `docs` commit.
|
|
439
|
+
This one commit covers the phase files, the ticked plan, the spec the run kept true, the report and the rendered board.
|
|
440
|
+
Staging by path leaves every other change in the working tree alone, and the tree is clean over the spec directory once it lands.
|
|
441
|
+
Commit only. Never push.
|
|
442
|
+
|
|
443
|
+
With `"commits": "none"`, post the status and commit nothing.
|
|
444
|
+
The report then says the closing status was left uncommitted, so the user knows the state file and the `README.md` are changed and theirs to keep or to drop.
|
|
445
|
+
|
|
446
|
+
Then give the message of section 6, which is what ends the turn and says what the closing commit did.
|
|
447
|
+
|
|
448
|
+
## 6. Report
|
|
449
|
+
|
|
450
|
+
A run that reaches its end has two homes for its report, and they hold the same run.
|
|
451
|
+
A run that stops before its end has one: the message.
|
|
452
|
+
|
|
453
|
+
`run-report.md` at the top of the spec directory is the whole of the report.
|
|
454
|
+
The closing step of section 5 writes it, the Specs tab lists it beside the other artifacts and renders it, and it stays with the work for whoever reads the spec later.
|
|
455
|
+
It is written at the end of the run and nowhere else, so a pause and a stop condition write no file at all.
|
|
456
|
+
|
|
457
|
+
The message in this terminal is the short form.
|
|
458
|
+
It is what ends the turn, and the user reads it now rather than later.
|
|
459
|
+
|
|
460
|
+
### The file
|
|
461
|
+
|
|
462
|
+
Write it as Markdown, with this title and these headings, in this order:
|
|
463
|
+
|
|
464
|
+
```markdown
|
|
465
|
+
# <spec name> - run report
|
|
466
|
+
|
|
467
|
+
## Bottom line
|
|
468
|
+
|
|
469
|
+
## Must know
|
|
470
|
+
|
|
471
|
+
## The details
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
The title names the spec.
|
|
475
|
+
The title and the three headings are fixed word for word.
|
|
476
|
+
Nothing else about the report is fixed.
|
|
477
|
+
The text under each heading is yours to write, so two reports share the headings and differ in their words alone.
|
|
478
|
+
|
|
479
|
+
- **Bottom line**: a few sentences on what landed, and whether the run is complete.
|
|
480
|
+
- **Must know**: the decisions that carry weight, the departures from the plan and from the mocks, and the critical issues a checkpoint found.
|
|
481
|
+
Write this section only where the run holds something the user must know.
|
|
482
|
+
Where it holds none, leave the heading out, and never write the section to fill it.
|
|
483
|
+
- **The details**: the phases finished and the overall progress, every checkpoint with what it found, what was fixed and what was dismissed with the reason, what you settled on your own, the branch and the commits of the run, and the commit mode.
|
|
484
|
+
Say that the report rides in the closing commit, or, with `"commits": "none"`, that it sits uncommitted in the tree.
|
|
485
|
+
|
|
486
|
+
Bottom line and The details are in every report.
|
|
487
|
+
|
|
488
|
+
### The message
|
|
489
|
+
|
|
490
|
+
The message is what ends a turn.
|
|
491
|
+
Give it at the end of the run, at a pause, or at a stop condition, and nowhere else.
|
|
492
|
+
What you say between phases is a progress line: say it and keep building.
|
|
493
|
+
|
|
494
|
+
Say it in normal message text:
|
|
317
495
|
|
|
318
496
|
- The phases finished this run, and the overall progress, such as "5/7 phases done".
|
|
319
|
-
- What the verification showed, and the outcome of every checkpoint this run ran: what the reviewers found, what was fixed, what was dismissed and why. When
|
|
497
|
+
- What the verification showed, and the outcome of every checkpoint this run ran: what the reviewers found, what was fixed, what was dismissed and why. When no checkpoint was chosen, say so.
|
|
320
498
|
- What you settled on your own, where it matters to the user.
|
|
321
499
|
- The branch, when the run committed to one of its own, that it is unmerged, and that merging it back is the user's job.
|
|
500
|
+
- Whether the run decisions were committed, and where they were not, that the spec directory was never committed.
|
|
322
501
|
- Why the run stopped, when it stopped at a pause or a stop condition, and what you need from the user.
|
|
323
|
-
|
|
324
|
-
|
|
502
|
+
- Whether the closing commit landed, and under `"commits": "none"`, that the closing status was left uncommitted.
|
|
503
|
+
- Where the run reached its end, that `run-report.md` in the spec directory holds the whole of the report.
|
package/templates/startup.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// =============================================================================
|
|
3
|
-
// startup.mjs -- Container startup:
|
|
3
|
+
// startup.mjs -- Container startup: agent CLI updates + readiness checks
|
|
4
4
|
// Baked into the container image at /home/devuser/startup.mjs
|
|
5
5
|
// Must run as root (npm global install requires root).
|
|
6
6
|
// Must use only Node.js built-ins -- no external packages available in container.
|
|
@@ -45,15 +45,15 @@ const fail = (label, detail) => {
|
|
|
45
45
|
};
|
|
46
46
|
// Non-fatal notice: always prints (even in summary), but does NOT increment errors, so it never aborts
|
|
47
47
|
// the session. Used for things the user should know about but that must not block connecting (e.g. a
|
|
48
|
-
// transient
|
|
48
|
+
// transient agent CLI update failure -- the existing versions still work).
|
|
49
49
|
const warn = (label, detail) => console.log(`${yellow("!")} ${label.padEnd(24)}${detail ? yellow(detail) : ""}`);
|
|
50
50
|
const section = summary ? () => {} : (title) => console.log(`\n${bold(title)}`);
|
|
51
51
|
|
|
52
52
|
// -- Header -------------------------------------------------------------------
|
|
53
53
|
if (!summary) console.log(`\n${bold("chamba - Sandbox for AI Agents")}\n`);
|
|
54
54
|
|
|
55
|
-
// --
|
|
56
|
-
section("
|
|
55
|
+
// -- Agent CLI update (requires root - skipped when run via 'status' alias as devuser) -
|
|
56
|
+
section("Agent CLI update");
|
|
57
57
|
|
|
58
58
|
const isRoot = process.getuid?.() === 0;
|
|
59
59
|
const TIMESTAMP_FILE = "/home/devuser/.ai-cli-updated";
|
|
@@ -71,7 +71,7 @@ try {
|
|
|
71
71
|
|
|
72
72
|
// -- Context snapshot cleanup (best-effort, silent) ---------------------------
|
|
73
73
|
// claude-statusline.sh writes one small per-session snapshot to this directory on every
|
|
74
|
-
// prompt render
|
|
74
|
+
// prompt render, and the web interface's status strip reads it. Delete week-old entries here -- covers both
|
|
75
75
|
// stale *.json snapshots and orphaned .tmp.* files. Any failure is swallowed so cleanup
|
|
76
76
|
// can never affect readiness checks.
|
|
77
77
|
const SNAPSHOT_DIR = "/home/devuser/.claude/context-usage";
|
|
@@ -148,7 +148,7 @@ const doUpdate = (label) =>
|
|
|
148
148
|
child.on("error", (err) => {
|
|
149
149
|
finish(() => {
|
|
150
150
|
printIndented(String(err?.message ?? err));
|
|
151
|
-
warn("
|
|
151
|
+
warn("agent CLIs", "update failed -- continuing with existing versions");
|
|
152
152
|
});
|
|
153
153
|
});
|
|
154
154
|
child.on("close", (code) => {
|
|
@@ -156,16 +156,17 @@ const doUpdate = (label) =>
|
|
|
156
156
|
if (code === 0) {
|
|
157
157
|
printIndented(out);
|
|
158
158
|
writeFileSync(TIMESTAMP_FILE, `${new Date().toISOString()}\n`);
|
|
159
|
-
ok("
|
|
159
|
+
ok("agent CLIs", "updated");
|
|
160
160
|
} else {
|
|
161
161
|
printIndented(`${out}${errOut}`);
|
|
162
|
-
warn("
|
|
162
|
+
warn("agent CLIs", "update failed -- continuing with existing versions");
|
|
163
163
|
}
|
|
164
164
|
});
|
|
165
165
|
});
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
-
// SPACE within `seconds` -> skip.
|
|
168
|
+
// SPACE within `seconds` -> skip. ENTER -> update now, without waiting out the countdown. Any other input is
|
|
169
|
+
// ignored. Ctrl+C exits 130. Non-TTY -> no skip.
|
|
169
170
|
const promptSkipUpdate = (seconds) =>
|
|
170
171
|
new Promise((resolve) => {
|
|
171
172
|
if (!process.stdin.isTTY) {
|
|
@@ -175,7 +176,7 @@ const promptSkipUpdate = (seconds) =>
|
|
|
175
176
|
let remaining = seconds;
|
|
176
177
|
let tick;
|
|
177
178
|
let timer;
|
|
178
|
-
const line = (s) => `\r\x1b[K${blue("●")} ${dim(`Updating
|
|
179
|
+
const line = (s) => `\r\x1b[K${blue("●")} ${dim(`Updating agent CLIs in ${s}s... SPACE to skip, ENTER to update now`)}`;
|
|
179
180
|
const cleanup = () => {
|
|
180
181
|
clearInterval(tick);
|
|
181
182
|
clearTimeout(timer);
|
|
@@ -195,6 +196,11 @@ const promptSkipUpdate = (seconds) =>
|
|
|
195
196
|
resolve(true);
|
|
196
197
|
return;
|
|
197
198
|
}
|
|
199
|
+
if (byte === 0x0d || byte === 0x0a) {
|
|
200
|
+
cleanup();
|
|
201
|
+
resolve(false);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
198
204
|
}
|
|
199
205
|
};
|
|
200
206
|
process.stdin.setRawMode(true);
|
|
@@ -212,19 +218,19 @@ const promptSkipUpdate = (seconds) =>
|
|
|
212
218
|
});
|
|
213
219
|
|
|
214
220
|
if (Number.isFinite(lastUpdate) && Date.now() - lastUpdate < THROTTLE_MS) {
|
|
215
|
-
ok("
|
|
221
|
+
ok("agent CLIs", "up to date");
|
|
216
222
|
} else if (!isRoot) {
|
|
217
|
-
skip("
|
|
223
|
+
skip("agent CLIs", "update skipped (requires root)");
|
|
218
224
|
} else {
|
|
219
225
|
// About to show update activity (the skip prompt and/or install/update output). In summary mode that is the
|
|
220
226
|
// first thing after the host's "Starting dev container...", so add a blank line to separate it.
|
|
221
227
|
if (summary) console.log("");
|
|
222
228
|
if (!timestampFileExists) {
|
|
223
|
-
await doUpdate("Installing
|
|
224
|
-
} else if (await promptSkipUpdate(
|
|
225
|
-
skip("
|
|
229
|
+
await doUpdate("Installing agent CLIs...");
|
|
230
|
+
} else if (await promptSkipUpdate(5)) {
|
|
231
|
+
skip("agent CLIs", "update skipped by user");
|
|
226
232
|
} else {
|
|
227
|
-
await doUpdate("Updating
|
|
233
|
+
await doUpdate("Updating agent CLIs to latest...");
|
|
228
234
|
}
|
|
229
235
|
}
|
|
230
236
|
|