chamba 0.6.1 → 0.8.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 (118) hide show
  1. package/LICENSE +53 -14
  2. package/README.md +38 -11
  3. package/dist/commands/advanced.js +7 -278
  4. package/dist/commands/dev.js +11 -612
  5. package/dist/commands/doctor.js +1 -29
  6. package/dist/commands/menu.js +1 -80
  7. package/dist/commands/onboard.js +6 -230
  8. package/dist/commands/settings.js +15 -349
  9. package/dist/lib/agent-commands.js +2 -0
  10. package/dist/lib/agent-context.js +6 -184
  11. package/dist/lib/browser.js +1 -40
  12. package/dist/lib/chamba-yaml.js +10 -191
  13. package/dist/lib/constants.js +1 -125
  14. package/dist/lib/dockerfile-builder.js +41 -260
  15. package/dist/lib/env.js +2 -78
  16. package/dist/lib/git-env.js +1 -21
  17. package/dist/lib/global-config.js +4 -66
  18. package/dist/lib/pnpm-store.js +1 -19
  19. package/dist/lib/ports.js +1 -210
  20. package/dist/lib/safe-rm.js +1 -26
  21. package/dist/lib/sessions.js +2 -34
  22. package/dist/lib/shadows.js +1 -176
  23. package/dist/lib/skills.js +2 -0
  24. package/dist/lib/templates.js +1 -0
  25. package/dist/lib/webterm.js +1 -305
  26. package/dist/lib/workspace-identity.js +4 -260
  27. package/package.json +6 -6
  28. package/templates/Dockerfile +24 -12
  29. package/templates/claude-statusline.sh +5 -7
  30. package/templates/context/baseline.md +2 -0
  31. package/templates/pane-apps/client/assets/c-BNa-DeUl.json +3552 -0
  32. package/templates/pane-apps/client/assets/cpp-B-T4NRoH.json +20239 -0
  33. package/templates/pane-apps/client/assets/csharp-BbxHChhA.json +6010 -0
  34. package/templates/pane-apps/client/assets/css-CWCxuwmz.json +1860 -0
  35. package/templates/pane-apps/client/assets/diff-B-2N89g8.json +154 -0
  36. package/templates/pane-apps/client/assets/docker-DWTvYW26.json +103 -0
  37. package/templates/pane-apps/client/assets/files-D0nJgFAA.js +12 -0
  38. package/templates/pane-apps/client/assets/files-h0K1vZyQ.css +1 -0
  39. package/templates/pane-apps/client/assets/go-B2hyYeNg.json +3156 -0
  40. package/templates/pane-apps/client/assets/graphql-Z6Id2aNO.json +1292 -0
  41. package/templates/pane-apps/client/assets/html-BtzvlIfu.json +2627 -0
  42. package/templates/pane-apps/client/assets/ini-Bn3Twap1.json +108 -0
  43. package/templates/pane-apps/client/assets/java-C7t2dwLO.json +1885 -0
  44. package/templates/pane-apps/client/assets/javascript-DuC2v0C0.json +5996 -0
  45. package/templates/pane-apps/client/assets/json-CwdkWeV5.json +206 -0
  46. package/templates/pane-apps/client/assets/jsonc-MYWDbTU3.json +206 -0
  47. package/templates/pane-apps/client/assets/jsx-Cn8EZuIC.json +5996 -0
  48. package/templates/pane-apps/client/assets/kotlin-CFNOz1gw.json +580 -0
  49. package/templates/pane-apps/client/assets/make-BVnlFCcl.json +629 -0
  50. package/templates/pane-apps/client/assets/markdown-B4Xk2WM_.json +3263 -0
  51. package/templates/pane-apps/client/assets/php-CAQzQmmI.json +4188 -0
  52. package/templates/pane-apps/client/assets/python-CYQee8m4.json +4174 -0
  53. package/templates/pane-apps/client/assets/reviews-BsoGZ35r.css +1 -0
  54. package/templates/pane-apps/client/assets/reviews-iW0Mbn4e.js +153 -0
  55. package/templates/pane-apps/client/assets/ruby-D7R58tus.json +3114 -0
  56. package/templates/pane-apps/client/assets/rust-BFBbFiei.json +1103 -0
  57. package/templates/pane-apps/client/assets/scss-TQRhBkPG.json +1874 -0
  58. package/templates/pane-apps/client/assets/shellscript-DieAkC4W.json +2375 -0
  59. package/templates/pane-apps/client/assets/specs-D9z3neR-.js +13 -0
  60. package/templates/pane-apps/client/assets/sql-Bxd030LV.json +634 -0
  61. package/templates/pane-apps/client/assets/toml-ChrKGzsV.json +430 -0
  62. package/templates/pane-apps/client/assets/tsx-D2e90MFw.json +5996 -0
  63. package/templates/pane-apps/client/assets/typescript-DonXQ_n1.json +5747 -0
  64. package/templates/pane-apps/client/assets/xml-B17r2RXF.json +382 -0
  65. package/templates/pane-apps/client/assets/yaml-CKn4h1zy.json +627 -0
  66. package/templates/pane-apps/client/reviews/index.html +15 -0
  67. package/templates/pane-apps/client/specs/index.html +14 -0
  68. package/templates/pane-apps/server/reviews.mjs +20 -0
  69. package/templates/pane-apps/server/specs.mjs +5 -0
  70. package/templates/skills/chamba-statusline/SKILL.md +7 -19
  71. package/templates/skills/dx-review/SKILL.md +123 -0
  72. package/templates/skills/dx-review/references/acts.md +162 -0
  73. package/templates/skills/dx-spec/SKILL.md +561 -0
  74. package/templates/skills/dx-spec/references/imagination-guide.md +140 -0
  75. package/templates/skills/dx-spec/references/principles-template.md +2 -0
  76. package/templates/skills/dx-spec/references/review-guide.md +127 -0
  77. package/templates/skills/dx-spec/references/spec-guide.md +145 -0
  78. package/templates/skills/dx-spec/references/stages.md +484 -0
  79. package/templates/skills/dx-spec-execute/SKILL.md +437 -0
  80. package/templates/startup.mjs +10 -4
  81. package/templates/tool-helper.sh +166 -0
  82. package/templates/webterm/README.md +79 -9
  83. package/templates/webterm/color.js +61 -0
  84. package/templates/webterm/config.js +74 -0
  85. package/templates/webterm/context/claude.md +0 -1
  86. package/templates/webterm/public/app/alerts.js +4 -4
  87. package/templates/webterm/public/app/anchored.js +81 -0
  88. package/templates/webterm/public/app/composer.js +4 -1
  89. package/templates/webterm/public/app/connection.js +9 -0
  90. package/templates/webterm/public/app/dom.js +15 -5
  91. package/templates/webterm/public/app/frames.js +51 -10
  92. package/templates/webterm/public/app/main.js +26 -6
  93. package/templates/webterm/public/app/new-session.js +13 -41
  94. package/templates/webterm/public/app/palette.js +58 -0
  95. package/templates/webterm/public/app/pane-shape.js +167 -0
  96. package/templates/webterm/public/app/pane-shell.js +380 -0
  97. package/templates/webterm/public/app/pane.js +77 -193
  98. package/templates/webterm/public/app/reviews-host.js +15 -0
  99. package/templates/webterm/public/app/specs-host.js +16 -0
  100. package/templates/webterm/public/app/state.js +5 -0
  101. package/templates/webterm/public/app/tabs.js +6 -2
  102. package/templates/webterm/public/app/terminal.js +8 -0
  103. package/templates/webterm/public/app/theme.js +75 -27
  104. package/templates/webterm/public/app/tool-host.js +302 -0
  105. package/templates/webterm/public/app/workspace-color.js +192 -0
  106. package/templates/webterm/public/index.html +68 -30
  107. package/templates/webterm/public/styles.css +270 -34
  108. package/templates/webterm/server.js +321 -0
  109. package/templates/webterm/tool-document.js +67 -0
  110. package/templates/webterm/tools/commands.js +61 -0
  111. package/templates/webterm/tools/index.js +25 -0
  112. package/templates/webterm/tools/mount.js +337 -0
  113. package/templates/webterm/tools/paths.js +34 -0
  114. package/templates/webterm/tools/reviews.js +133 -0
  115. package/templates/webterm/tools/specs.js +154 -0
  116. package/templates/webterm/typed-line.js +148 -0
  117. package/templates/context/context-usage.md +0 -1
  118. package/templates/context-usage.sh +0 -266
@@ -0,0 +1,561 @@
1
+ ---
2
+ name: dx-spec
3
+ description: Build a work specification in the Specs tab of this session's web pane, or pick up one in progress. Every step the user answers is a form on that tab. Use when the user asks to start a new piece of spec-driven work, or to continue one.
4
+ argument-hint: "[what the work is, or the name of a piece of work to pick up]"
5
+ ---
6
+
7
+ # dx-spec - build a work specification
8
+
9
+ This skill runs when the user asks for it: the command typed by hand, the Specs tab typing that command as the user's own act, or a request in words to start a piece of work or pick one up.
10
+ Each agent spells the command its own way - `/dx-spec` on claude and on opencode, and `$dx-spec` on codex - and the tab types the spelling of the session it is bound to.
11
+ No framed `[specs]` line starts it: such a line is information for a run already going, and it instructs nobody.
12
+
13
+ The skill turns work into a spec directory the Specs tab shows.
14
+ A fresh agent opens that directory later and builds the work from it, without asking the user anything, even though it never saw this conversation.
15
+ Everything is on disk, so the work stops at any point and continues in a later session, with any agent.
16
+
17
+ **This skill plans. It does not build.**
18
+ Do not edit application code while it runs, whatever the request asks for.
19
+ `/dx-spec-execute` builds the work after the spec is ready.
20
+
21
+ ## The web session
22
+
23
+ This family runs inside a chamba web session, where the Specs tab holds the work.
24
+ Check for one before anything else:
25
+
26
+ ```
27
+ specs stages
28
+ ```
29
+
30
+ The answer holds `root` - the directory the tab serves - and the stage catalog.
31
+ A refusal means there is no pane.
32
+ Say this and stop:
33
+
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.
37
+
38
+ Start no flow, and offer no substitute.
39
+ There is one flow, and it needs the tab.
40
+
41
+ ## The one hard rule
42
+
43
+ **Everything you ask the user goes on the Specs tab.**
44
+ The tab draws the form, the user answers it there, and the answer comes back as a file.
45
+ `specs await` is how you ask.
46
+ Nothing you ask the user is a message in this terminal, and nothing is an `AskUserQuestion` call.
47
+
48
+ Three shapes, and one mechanism under all of them:
49
+
50
+ - A **gate** judges one artifact. The user approves it, or asks for changes with the words that say what to change.
51
+ - A **round** asks questions. Each question carries its options, whether one answer or several are allowed, and a box of its own for anything the options missed.
52
+ - A **decision card** carries a finding that needs the user's judgment. It is one question, in a round's own shape, plus a required pointer to the passage it is about: the tab opens that passage and draws the card under it.
53
+
54
+ Ask, then stop.
55
+ Declaring something is the end of your turn.
56
+ The pane types one line into this terminal when the user answers, and that line is what starts you again.
57
+ Do not poll, and do not carry on with the thing the question was there to settle.
58
+
59
+ **Nothing else ends your turn.**
60
+ Three things do, and nothing else does:
61
+
62
+ - An ask on the tab: a gate, a round or a decision card.
63
+ - The collect invitation, which waits for the user to say what the work is.
64
+ - The closing line that ends the run.
65
+
66
+ `specs post` is not one of them.
67
+ Posting a stage as running, posting an activity, and finishing a stage that has no gate all tell the board something and ask nobody anything, so the turn carries straight on into the work the post announced.
68
+ Saying a line to the user is not one of them either: say it, and go straight on in the same turn.
69
+
70
+ A stage posted as running with nothing after it is the failure this rule exists to stop.
71
+ The board then tells the user that work is happening while the run is standing still, and no line ever comes back to start it again.
72
+
73
+ **A line that comes back is not always an answer.**
74
+ The user may ask you about the ask instead, from the same form, and the line says a question was asked and that nothing was answered.
75
+ The ask is still open, and the form is still on their screen.
76
+ Answer the question here, in plain message text, and leave the ask alone: do not declare it again, do not withdraw it, and do not treat the question as the decision.
77
+ The user answers it in the pane when your answer has told them what they needed.
78
+
79
+ You write to the user in plain messages in exactly four places:
80
+
81
+ - The **collect invitation** - one short line that asks what the work is.
82
+ - The **exploration stage** - thinking out loud is its whole point.
83
+ - A **line of fact** the user needs before a form makes sense, sent in the same turn as the form.
84
+ - The **closing line** that ends the run.
85
+
86
+ **Raise a doubt. Never guess at it.**
87
+ Do not settle a doubt on your own while a spec is being built, however small it looks.
88
+ A fresh agent builds from this spec without asking anything, so a doubt this session swallows becomes a wrong build later.
89
+
90
+ Raise a doubt in one of three ways, by where it comes up:
91
+
92
+ - Outside a stage that writes `SPEC.md`: ask it in the next round.
93
+ - Inside a stage that writes `SPEC.md`: queue it in place as a `[NEEDS CLARIFICATION: ...]` marker, and ask it at the next round or gate, once it clears the bar in `references/spec-guide.md`.
94
+ - Below that bar: write it to disk as a labeled assumption, naming the guess you made.
95
+
96
+ The same rule covers any other guess that has to stand: label it on disk, so no choice stays silent.
97
+
98
+ ## When the steps change under you
99
+
100
+ The user changes the confirmed protocol from the tab, at any moment, including while you are in the middle of a stage.
101
+ The pane types one line into this terminal when they do, saying what moved.
102
+
103
+ That line is work, not a status report.
104
+ Read `specs state <spec>` and act on the difference:
105
+
106
+ - A stage added: run it when its turn comes in catalog order, and run it next where its turn has passed.
107
+ - A stage removed: it was still waiting, so there is nothing to undo. Stop planning for it.
108
+ - Nothing else changed: the protocol is the same, and there is nothing to do.
109
+
110
+ Finish what you are in the middle of first, unless the change makes that work pointless.
111
+ Say in one line what you are going to do about it, and carry on.
112
+ Never ask the user to confirm a change they just made.
113
+
114
+ ## The tool owns the state
115
+
116
+ The Specs tool writes `state.json` and the `README.md` of each spec directory.
117
+ **Never edit either one.**
118
+ Never write a protocol list, a stage checkbox, a status line or a log line by hand.
119
+ You move the work with the verbs below, and the tool writes both files in the same act, so the board in the pane and the file in git cannot disagree.
120
+
121
+ Everything else in the spec directory is yours: `spec/SPEC.md`, the research, the mocks, the plan, the review, and the visuals beside them.
122
+
123
+ ## The verbs
124
+
125
+ `specs <verb> [<spec>]` takes JSON on stdin where a verb needs a payload, and answers JSON on stdout.
126
+ `<spec>` is the directory name the tab shows.
127
+
128
+ ```
129
+ specs stages where the specs live, and the stage catalog
130
+ specs state <spec> where the work stands, and what awaits the user
131
+ echo '<json>' | specs intake file a new piece of work
132
+ echo '<json>' | specs propose <spec> recommend a protocol, and put it to the user
133
+ echo '<json>' | specs recommend <spec> recommend how the run is shaped, for the execute form
134
+ echo '<json>' | specs await <spec> declare a gate, a round or a decision card
135
+ echo '<json>' | specs withdraw <spec> take back an ask nobody needs to answer
136
+ echo '<json>' | specs post <spec> say what is happening
137
+ echo '<json>' | specs review <spec> post one round of quality review
138
+ echo '{"id":"<id>"}' | specs answers <spec> read back what the user answered
139
+ ```
140
+
141
+ **Filing an intake:**
142
+
143
+ ```json
144
+ { "name": "Checkout discounts", "text": "everything the user said, in their words", "attachments": [] }
145
+ ```
146
+
147
+ The answer is `{ "entry": "checkout-discounts", "path": "checkout-discounts/intake.md" }`.
148
+ An attachment is `{ "name": "sketch.png", "type": "image/png", "data": "<base64>" }`.
149
+ An intake may also carry `"wish": { "imagination": true }`, which is what the form's own flavour box files.
150
+ The wish shapes what you recommend, and settles nothing: the steps are where the mode is confirmed.
151
+
152
+ **Recommending a protocol:**
153
+
154
+ ```json
155
+ { "stages": [{ "id": "interview", "recommended": true, "why": "the scope has open edges" }], "note": "" }
156
+ ```
157
+
158
+ Name every stage you have an opinion about.
159
+ The form shows the whole catalog either way, so the user sees what you did not recommend.
160
+
161
+ **Recommending how the run is shaped:**
162
+
163
+ ```json
164
+ { "commits": "per-phase", "branch": "new", "branchName": "spec/checkout-discounts",
165
+ "pauses": "chosen", "pausePhases": ["phase-03-the-banner"],
166
+ "pauseReasons": { "phase-03-the-banner": "the checkout total reads the banner's rules, so a rule you would have written differently sends the next phase wrong" },
167
+ "noPauseReason": "",
168
+ "checkpoints": [
169
+ { "after": "phase-03-the-banner", "why": "later phases build on this one", "panel": ["correctness against the spec", "state and merge safety"] },
170
+ { "after": "final", "why": "judges the finished work as a whole", "panel": ["correctness against the spec", "docs consistency", "better ways to do this"] } ] }
171
+ ```
172
+
173
+ `commits` is `per-phase`, `single` or `none`, and `branch` is `current` or `new`.
174
+ `pauses` is `none`, `chosen` or `every`, and `pausePhases` names the phases for `chosen`.
175
+ `pauseReasons` holds one line for each pause you recommend, keyed by the phase it sits after.
176
+ `noPauseReason` holds the one line for a recommendation of `none`.
177
+ A recommendation of `chosen` fills `pauseReasons` and leaves `noPauseReason` empty.
178
+ A recommendation of `none` fills `noPauseReason` and leaves `pauseReasons` empty.
179
+ A recommendation of `every` carries neither.
180
+ Both are addressed to the user, and the form shows them under the Pauses field.
181
+ A checkpoint's `after` is a phase id or the word `final`, and its `panel` holds one focus per reviewer.
182
+ A phase id is the name of the phase's own file, without the extension.
183
+
184
+ It lands in the state as `runRecommendations`, beside the `runDecisions` the form writes.
185
+ This is a recommendation and nothing more.
186
+ The execute form opens on it, the user decides it there, and what they decide is what binds the run.
187
+ Give every panel one focus at least: a checkpoint with nobody on its panel has nobody to run, and is recorded as one that does not run.
188
+ Post it once the plan is written and its phases are posted, and post it again where a later change to the plan makes it wrong.
189
+
190
+ **Declaring a round:**
191
+
192
+ ```json
193
+ { "id": "interview-1", "kind": "round", "title": "A few things about the checkout", "file": "",
194
+ "payload": { "kind": "round", "questions": [
195
+ { "id": "scope", "ask": "Which orders can be partly cancelled?", "multi": false,
196
+ "invite": "Where the options are wrong, say so",
197
+ "options": [
198
+ { "id": "any", "said": "Any order, at any time", "recommended": true },
199
+ { "id": "unshipped", "said": "Only an order nothing has shipped from" } ] } ] } }
200
+ ```
201
+
202
+ **Declaring a gate:**
203
+
204
+ ```json
205
+ { "id": "spec-gate", "kind": "gate", "title": "Does the spec look right?", "file": "spec/SPEC.md",
206
+ "payload": { "kind": "gate", "asks": "Approve it, or say what to change." } }
207
+ ```
208
+
209
+ `file` is the artifact the gate judges, relative to the spec directory.
210
+ The tab opens that artifact and puts the gate under it.
211
+
212
+ A gate may carry one box beside its approval, for one more thing that goes with approving:
213
+
214
+ ```json
215
+ { "payload": { "kind": "gate", "asks": "Approve it, or say what to change.",
216
+ "offer": { "said": "also commit the spec", "preset": true } } }
217
+ ```
218
+
219
+ The box rides with the approval, so a gate that offers something is not followed by a gate of its own.
220
+ The answer says `"accepted": true` where the user approved with the box ticked, and `false` for every other answer.
221
+ An offer is for a small act that goes with the approval, and never for a second question.
222
+
223
+ **Declaring a decision card:**
224
+
225
+ ```json
226
+ { "id": "rv-04", "kind": "gate", "title": "The plan leans on one mechanism", "file": "plan/PLAN.md",
227
+ "payload": { "kind": "decision", "heading": "Phase 05 - the half-width button",
228
+ "questions": [
229
+ { "id": "half", "multi": false,
230
+ "ask": "Phase 05 stores a pixel width when the button is pressed, so a window resized afterwards leaves the pane at that width and no longer at half.\n\n**Trade-off.** A fraction keeps the button true after a resize and adds one more shape a width can take. Pixels keep one kind of width and let the button drift.",
231
+ "options": [
232
+ { "id": "fraction", "said": "Store half as a fraction, so the pane stays at half after a resize", "recommended": true },
233
+ { "id": "pixels", "said": "Keep the pixel width the button computed, as the plan says" } ] } ] } }
234
+ ```
235
+
236
+ Both parts of the pointer are required, and a declaration missing either one is refused.
237
+ `file` is the artifact, relative to the spec directory, and it has to name a file the spec directory holds.
238
+ `heading` is the `##` section inside it, as written; the tab opens the artifact at that section and draws the card under it.
239
+ A heading no section matches lands on the top of the file, and where two sections share a heading the first one wins.
240
+
241
+ The card asks exactly one question, with two options at least, and a declaration that holds fewer is refused.
242
+ Mark one of them recommended, which is yours to get right: the door does not count the recommendations, and a card that offers none still opens.
243
+ Write the passage's own words into the `ask`: what was found, and what each way costs.
244
+ Say the proposed change as one option, in exact words, and the alternative as another, each in that finding's own terms.
245
+
246
+ **Withdrawing an ask:**
247
+
248
+ ```json
249
+ { "id": "review-gate-1", "reason": "superseded by the second review gate" }
250
+ ```
251
+
252
+ The awaiting list is what the user is told is open, so it must hold only what is genuinely open.
253
+ An ask you supersede is withdrawn in the same act that supersedes it: when you declare a replacement, and when the answer reaches you anywhere else, the terminal included.
254
+ One case the tool does for you: a gate declared on an artifact takes back any open gate on that same artifact, with the reason `superseded by <id>`, because one artifact holds one open judgment.
255
+ A decision card is not a gate in this sense, so cards on one file stack, and a gate takes none of them back.
256
+ Every other replacement is yours to withdraw: a round asked again with a new id, a gate moved to another artifact, and an ask the terminal answered.
257
+ The round file stays on disk as the record of what was asked, and the log carries the reason.
258
+ Withdrawing is your act, not the user's, so it adds nothing to the approvals.
259
+
260
+ **Posting progress:**
261
+
262
+ ```json
263
+ { "kind": "activity", "said": "Reading the checkout code" }
264
+ { "kind": "stage", "stage": "codebase-analysis", "status": "done", "artifacts": ["spec/SPEC.md"] }
265
+ { "kind": "status", "status": "ready" }
266
+ { "kind": "note", "said": "one dated line for the log" }
267
+ ```
268
+
269
+ Post an activity when you start something that takes a while, so the board says what is happening.
270
+ An activity needs no clearing, and there is no verb to clear one with.
271
+ The board shows it while it is current, and stops the moment anything else is posted, or half an hour after it was said.
272
+ So post one for a step that is under way, and post the next thing when that step ends.
273
+
274
+ Post a stage as `running` when it starts, and as `done` with its artifacts when it ends.
275
+
276
+ **Reading an answer back:**
277
+
278
+ ```json
279
+ { "answer": { "outcome": "approved", "said": "", "accepted": true, "questions": [] } }
280
+ ```
281
+
282
+ An outcome is `approved` or `changes` for a gate, and `answered` for a round and for a decision card.
283
+ `accepted` says what the gate's own box came back as, and is `false` where the gate offered none.
284
+ A round's answer carries one line per question, and a question the user left alone is there too, marked `"answered": false`.
285
+ Treat such a question as skipped. It is not a "no".
286
+ A decision card's answer carries one line of the same kind, for its one question: the option the user chose, and what they wrote.
287
+ `{ "answer": null }` means the user has not answered yet.
288
+
289
+ ## Writing a question
290
+
291
+ The pane's form has no limit on questions or options, so ask the whole round at once rather than in a chain of small ones.
292
+ Every question still follows these rules:
293
+
294
+ - Write for someone who has never used these skills.
295
+ - Do not use internal terms - directory layout, phase files, stage names - unless the option explains them in the same breath.
296
+ - Put the option you would choose first, and mark it `"recommended": true`.
297
+ - Keep an option's `said` short. Put the reasoning and the trade-off in the question's `ask`.
298
+ - Where a real trade-off exists, lay it out and let the user decide. Never decide it silently.
299
+ - Give a round's question an `invite` when a typed answer would be worth more than a choice. A question with none gets the plain *Your words*, so write an invite only where it says something that word does not. A decision card is the exception: its one box always says *Your words*, so an `invite` on a card's question is never shown.
300
+
301
+ Give each round and each gate an id that says what it is: `interview-1`, `spec-gate`, `mocks-gate`.
302
+ An id is answered once. Ask again with a new id.
303
+ An answered ask has already left the "Needs you" list, so there is nothing to take back.
304
+ Withdraw the earlier ask only where the new one replaces an ask the user never answered.
305
+ `references/stages.md` says it in full, under **Asking again**.
306
+
307
+ ## Two rules over everything on disk
308
+
309
+ These two hold in every stage of this skill and in every phase of `/dx-spec-execute`.
310
+ They are stated here once, and pointed at from the flows that need them.
311
+
312
+ **Keep what derives from a change true.**
313
+ A change to `spec/SPEC.md` or to `plan/PLAN.md` can make something else wrong: a phase that covers a requirement nobody kept, a review report about a document that moved, a recommendation of how to shape the run that names a phase the plan lost.
314
+ Where you change either document, work out what derives from what you changed, and refresh it in the same act.
315
+ The run recommendations are the easiest one to forget: a change to the phase list makes a pause or a checkpoint that names a phase stale, so post the recommendation again.
316
+ Never leave a derived thing to be found later.
317
+
318
+ **Cross-check a stored answer against the code.**
319
+ An answer the user gave a form, or gave a round in an earlier stage, gets the check a fresh interview answer gets.
320
+ When you first read the code this work touches, read each stored answer against it, and raise a contradiction to the user rather than building on it:
321
+
322
+ - "You said both themes, and this app has a dark theme alone."
323
+ - "You said desktop only, and every screen in this app is responsive."
324
+ - "You asked for broad research, and this work touches one function of your own code."
325
+
326
+ The first two are the interview's answers, in the `Themes and devices` section of `SPEC.md`; the third is the research scope, on the confirmation form.
327
+
328
+ Raise it the way you raise any doubt, and let the user settle it.
329
+ Never change a stored answer on your own.
330
+
331
+ ## The commit style
332
+
333
+ Every commit this family makes is written the same way: a type, a colon, then what the commit did.
334
+
335
+ ```
336
+ docs: user-preferences spec ready
337
+ feat: phase 02 - the consuming skills
338
+ fix: user-preferences review fixes
339
+ ```
340
+
341
+ The type says what the commit did to the code, and the list is open - `feat`, `fix`, `docs`, `chore` and `refactor` are the usual ones.
342
+ A commit that touches spec files alone is a `docs` commit.
343
+ A phase commit of a run takes the type that suits what that phase did, and names the phase in its description, as the second line above does.
344
+
345
+ This is built-in behaviour, and nothing exposes it as a setting, a form field or a run decision.
346
+ A project that wants another shape writes a principle in `principles.md`, which every run reads at start and honors best-effort - the standing every other principle has, and no more.
347
+
348
+ `/dx-spec-execute` states no style of its own: every commit it makes is written from this one.
349
+
350
+ ## What a finished spec is
351
+
352
+ A complete spec lets a fresh agent open the directory with no other context and know what to build.
353
+ That agent learns where the edges are, how to tell the work is done, and roughly where the code goes.
354
+ No question for the user is left.
355
+ Aim for a production-grade spec every time.
356
+
357
+ ## What is on disk
358
+
359
+ The tab serves one root, and each piece of work is one directory under it.
360
+
361
+ ```
362
+ <root>/
363
+ principles.md the engineering principles every run honors, and the user's to edit
364
+ <slug>/
365
+ README.md written by the tool, from the state - never by you
366
+ intake.md what the work started as
367
+ spec/
368
+ SPEC.md the specification
369
+ *.md, *.svg what the user shared, and visuals written beside the spec
370
+ research/RESEARCH.md written by the research stage
371
+ mocks/<mock-id>.html one standalone page per screen
372
+ plan/PLAN.md the execution plan, plus one file per phase during the run
373
+ review/REVIEW.md the quality review report
374
+ archive/
375
+ YYYY-MM-DD-<slug>/ work that is finished and signed off
376
+ ```
377
+
378
+ A stage directory appears when its stage writes something. Nothing is created empty.
379
+
380
+ ## A page you make during this work
381
+
382
+ You may draw a page to explain something - a flow, a comparison, a diagram.
383
+ During spec work, that page belongs to the spec, so save it into the spec directory under a lowercase name.
384
+ The tab lists it beside the other artifacts and renders it, and the user comments on it there.
385
+ Do not publish it to the Pages tab: a page on Pages belongs to this conversation, and this one belongs to the work.
386
+
387
+ Outside spec work, `webpane` and the Pages tab are the right home for a page.
388
+
389
+ Keep a page standalone: no external stylesheet, no script that fetches anything, and images as data URLs.
390
+
391
+ ## The bootstrap
392
+
393
+ Settle the root and the principles before step 1, and before the first step of `/dx-spec-execute`.
394
+
395
+ 1. Read `root` from `specs stages`. That is the directory the Specs tab serves, and every path in this family resolves against it.
396
+ 2. Read `<root>/principles.md`. It is plain markdown: a `# Principles` heading, then one `- <principle>` bullet each, and nothing else.
397
+ 3. Where no file is there, write one from `references/principles-template.md` beside this file. Say in one line that you made it, and carry straight on.
398
+ 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.
399
+
400
+ A file that is already there produces no message at all.
401
+ Nothing else about how this family works is configurable, and the user changes a principle by editing that file.
402
+
403
+ ## Flow
404
+
405
+ ### 1. Start
406
+
407
+ Every start is this skill's own command, in the spelling of the session's agent.
408
+ The user types it by hand, or the Specs tab types it for them: the New-spec form files the intake and then types the command with the fresh directory's name, and the pick-up action types it with the name of the work to continue.
409
+ The argument decides where to begin.
410
+
411
+ **It names a piece of work that exists.** Read `specs state <spec>`. Where the directory holds nothing but its intake - no confirmed protocol, no stage artifacts - read `intake.md` and go to step 4. Where the work is further along, go to step 3.
412
+
413
+ **It is anything else.** Treat it as the user's opening input, and go to step 2.
414
+
415
+ **There is no argument.** Read the root with `specs stages`.
416
+ With one piece of work or more there, declare a round that asks which one, with one option per directory and one for something new.
417
+ Declare it on the piece of work that changed last.
418
+ Every asking verb names a spec, and there is no spec for "which spec" - so the round sits on a real one, and the tab shows it wherever the user is.
419
+ Never name a spec that is not there: the verb refuses it, and the question is not asked at all.
420
+ Never name an empty directory either - the verb accepts one, so this rule is yours to keep.
421
+ With nothing there, go straight to the collect invitation in step 2.
422
+
423
+ ### 2. Collect
424
+
425
+ Let the user say everything they have before you ask anything.
426
+
427
+ Send this invitation as one short message, in these words:
428
+
429
+ > Tell me about the work. Paste everything you have - notes, links, screenshots, file paths, snippets, examples, prior art - in one go, and I'll take it from there.
430
+
431
+ Then end your turn and wait.
432
+ Skip the invitation when their opening input already covers it.
433
+
434
+ With their input in, file it:
435
+
436
+ ```
437
+ echo '{"name":"<a working name>","text":"<everything they said>","attachments":[]}' | specs intake
438
+ ```
439
+
440
+ The tool makes the directory, writes `intake.md`, and starts the state file.
441
+ The tab opens on it.
442
+
443
+ ### 3. Pick up work in progress
444
+
445
+ Read `specs state <spec>` and every artifact in the directory.
446
+ The state says which stages were confirmed, where each one stands, and what is waiting for the user.
447
+
448
+ `.specs/user-feedback.json` in the directory holds annotations the user sent that nobody has applied.
449
+ Apply them as `references/stages.md` defines, before anything else.
450
+
451
+ Then declare a round: what the work is, where it stands, and what happens next - continue, redo something, or change the steps.
452
+
453
+ ### 4. Choose the protocol
454
+
455
+ Read what the input points to in the codebase, enough to judge the shape and the size of the work.
456
+
457
+ Then recommend the stages this work needs:
458
+
459
+ ```
460
+ echo '{"stages":[...],"note":""}' | specs propose <spec>
461
+ ```
462
+
463
+ Give every stage you recommend a `why` of one sentence, in the user's terms.
464
+ The form shows the whole catalog, recommended or not, so the user sees the choice whole.
465
+ Confirming writes the protocol into the state, in catalog order.
466
+
467
+ Rough rules for what to recommend:
468
+
469
+ - A bug fix: codebase analysis and an execution plan.
470
+ - A small feature or a chore: interview, codebase analysis, execution plan.
471
+ - A new user-facing feature: exploration, interview, codebase analysis, technical specs, UI mocks, execution plan.
472
+ - Work in a subject you or the user do not know well: add research.
473
+ - Pure thinking, or one decision to make: exploration, maybe research, and no plan.
474
+ - Large or risky work: add the quality review. Many phases, several stages feeding one spec, or anything that touches security, data or money.
475
+
476
+ **The wish.**
477
+ `wish.imagination` in the state says the intake asked for imagination mode.
478
+ Where it is set, recommend high-level exploration, and recommend UI mocks for work that has a user interface.
479
+ Those two stages are what the mode changes, so a protocol without either one cannot honor the wish.
480
+ Say in the stage's `why` that the user asked to imagine this freely first.
481
+ Recommend neither one against your judgment: where the work plainly needs neither, say so in the `note`, and let the user decide at the form.
482
+
483
+ The pane offers imagination mode when the confirmed protocol holds exploration or UI mocks, and the form opens with the line ticked where the wish is set.
484
+ Read `references/imagination-guide.md` when the state comes back with `modes.imagination` true, when the user asks for the mode by name, and at no other time.
485
+
486
+ Save what the user shared into `spec/` under lowercase names of their own.
487
+
488
+ ### 5. Run the stages
489
+
490
+ Run the stages in the order the confirmed protocol lists.
491
+ `references/stages.md` defines each one.
492
+ Read a stage's section when the stage starts, and run the stage from that definition: it carries gates and rules the stage name alone does not state.
493
+
494
+ Every stage that writes into `SPEC.md` also uses `references/spec-guide.md`.
495
+
496
+ Post the stage as `running` when it starts.
497
+ Post it as `done` with its artifacts when its gate is approved.
498
+ Every stage ends at a gate, except codebase analysis, which feeds the next stage and has none.
499
+
500
+ Every gate also clears the open markers.
501
+ Before you declare a gate, read `SPEC.md` for open `[NEEDS CLARIFICATION: ...]` markers.
502
+ Put them in the same round as the gate, in the priority order in `references/spec-guide.md`.
503
+ Each answer replaces its marker in `SPEC.md` in the same round.
504
+ This is what makes every marker reach the user.
505
+ Codebase analysis has no gate, so what it opens is asked at the gate of the stage after it.
506
+ The interview asks its own markers in its own rounds.
507
+
508
+ ### 6. The coherence rewrite
509
+
510
+ Before the finalize gate, rewrite what the work changed after it was first written.
511
+ `references/spec-guide.md` defines this step: when it runs, what it produces, and the one round of review that follows it.
512
+
513
+ ### 7. Finalize
514
+
515
+ Read every file in the spec directory from start to end, and check:
516
+
517
+ - Every assumption and open question is labeled.
518
+ - No two files disagree.
519
+ - Each requirement carries its own acceptance criterion, where the spec carries requirement IDs.
520
+ - Every ID appears in some phase's `Covers` line, where the protocol includes the execution plan.
521
+
522
+ Skip `mocks/candidates/`: it holds directions nobody chose.
523
+
524
+ When `review/REVIEW.md` is there, this read covers less ground.
525
+ Read the parts no reviewer saw: the fixes the stage made, and the edits that came from the user's decisions at the review gate.
526
+ Treat the rest as covered, because the review stage ran the deeper version of this check over it.
527
+
528
+ Ask any marker still open in `SPEC.md` before the gate.
529
+ The gate does not pass while a marker stays open.
530
+
531
+ Then declare the finalize gate on `spec/SPEC.md`, saying what the spec covers in a sentence or two.
532
+ Carry the commit with it, as the gate's own offer:
533
+
534
+ ```json
535
+ { "id": "finalize-gate", "kind": "gate", "title": "Is the spec ready to build from?", "file": "spec/SPEC.md",
536
+ "payload": { "kind": "gate", "asks": "Approve it, or say what to change.",
537
+ "offer": { "said": "also commit the spec", "preset": true } } }
538
+ ```
539
+
540
+ On changes: revise, and declare a new gate.
541
+ Loop until the user approves it.
542
+
543
+ After they approve, post both lines before you commit anything:
544
+
545
+ ```
546
+ echo '{"kind":"status","status":"ready"}' | specs post <spec>
547
+ echo '{"kind":"note","said":"Spec ready: partial cancellation of a shipped order, with three mocks and a five-phase plan"}' | specs post <spec>
548
+ ```
549
+
550
+ The note is one line saying what the spec holds, in the words a reader who was not here would want.
551
+ It names no commit and no hash: the commit is made after it, so a hash written here would be one the state cannot have yet.
552
+ Both posts move the state file and the rendered `README.md`, which is why they go first - a commit made before them leaves those two changed in the working tree with nothing left to carry them.
553
+
554
+ Where the answer says `"accepted": true`, stage the spec directory by path and commit it with a one-line message.
555
+ Compose the message from **The commit style** above, with "<spec name> spec ready" as its descriptive part.
556
+ Commit only. Never push.
557
+ Staging by path leaves every other change in the working tree alone.
558
+ The tree is clean over the spec directory once that commit lands, which is the whole point of the order: post, then commit.
559
+ Where it says `false`, commit nothing, and ask nothing more: the user answered this at the gate.
560
+
561
+ Close with one short message: what the spec covers, where it is, whether it was committed, and, when a plan exists, that `/dx-spec-execute` runs it.