create-claude-cabinet 0.35.0 → 0.36.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.35.0",
3
+ "version": "0.36.0",
4
4
  "description": "Claude Cabinet — opinionated process scaffolding for Claude Code projects",
5
5
  "bin": {
6
6
  "create-claude-cabinet": "bin/create-claude-cabinet.js"
@@ -40,6 +40,13 @@ slash commands for CC maintenance.
40
40
 
41
41
  These hold for every SKILL.md regardless of type.
42
42
 
43
+ **Runtime output formatting lives in a sibling doc.** This doc covers
44
+ *write-time* authoring. For *runtime* user-facing output — when a running
45
+ skill should present choices via the native `AskUserQuestion` tool versus
46
+ prose versus a markdown table, plus the AskUserQuestion schema facts
47
+ authors must get right — see `skill-output-conventions.md`. Follow that
48
+ pointer whenever a skill prompts the user to make a decision.
49
+
43
50
  ### Body under 500 lines
44
51
 
45
52
  The SKILL.md **body** — content after the closing `---` of
@@ -0,0 +1,153 @@
1
+ # Skill Output Conventions
2
+
3
+ How skills format **user-facing output** and **interactive prompts** at
4
+ runtime. The companion to `skill-best-practices.md`.
5
+
6
+ ## 1. Purpose & Scope
7
+
8
+ `skill-best-practices.md` governs **write-time** authoring rules — file
9
+ structure, naming, frontmatter, length. This doc governs **runtime**
10
+ interaction: how a skill, while executing, presents choices and
11
+ information to the user. `output-contract.md` is a third, separate
12
+ concern — the JSON cabinet members emit during audits, not user-facing
13
+ output.
14
+
15
+ Stating the boundary keeps the three docs from drifting together: if a
16
+ rule is about *how a SKILL.md is written*, it belongs in
17
+ skill-best-practices; if it's about *what the running skill shows the
18
+ user*, it belongs here.
19
+
20
+ ## 2. When to Use AskUserQuestion
21
+
22
+ `AskUserQuestion` is the native interactive primitive — a structured
23
+ menu of 2-4 options the user picks from. Use it when **all** of these
24
+ hold:
25
+
26
+ - The choice is among **discrete options** (not free text).
27
+ - The answer **branches the skill's behavior** (it's a real decision).
28
+ - There are **2-4 mutually-exclusive choices** (or a small set if
29
+ multiSelect).
30
+ - It is **not an obvious-default confirm** — a yes/no where one answer
31
+ is plainly expected (see §5).
32
+ - The item count is **bounded and small** — not a variable-length loop
33
+ (see §4).
34
+
35
+ If any answer is "no," use prose (§5) or a table (§6) instead.
36
+
37
+ ## 3. Schema Facts Authors Must Get Right
38
+
39
+ Verified against the live schema. Get these wrong and the call fails or
40
+ behaves unexpectedly.
41
+
42
+ - **1-4 questions per call; 2-4 options per question.** Outside this
43
+ range fails validation.
44
+ - **`header` is REQUIRED** — a short chip/tag, **max 12 chars** (e.g.
45
+ `Branch`, `Verdict`, `Decision`). Omitting it fails validation. This
46
+ is the most common authoring mistake.
47
+ - **Cost is per-session, not per-call.** AskUserQuestion is a deferred
48
+ tool: the first use in a session loads its schema (one ToolSearch
49
+ round-trip, ~200 tokens); every call after that is free. Don't
50
+ under-use it to "save" a cost that's already paid.
51
+ - **`multiSelect` is required.** `false` for mutually-exclusive choices
52
+ (the norm — one answer). `true` only when the user may legitimately
53
+ pick more than one.
54
+ - **"Other" is auto-added** by the harness. Never add an "Other" /
55
+ "Something else" option manually — it duplicates.
56
+ - **No reliable preview/comparison field.** The official schema has no
57
+ dependable preview surface; don't build conventions on preview
58
+ behavior or expect side-by-side rendering.
59
+ - **Unavailable in Task-spawned subagents.** Agents launched via the
60
+ Task tool (execute-group worktree agents, Workflow agents,
61
+ `context:fork`) cannot call AskUserQuestion — they must use prose.
62
+ This warning outlives any current wiring: a skill that runs in the
63
+ main session today may be called from a subagent tomorrow.
64
+ - **Pre-specify each call site** in the SKILL.md prose — exact `header`,
65
+ `question`, and option labels/descriptions. In a long skill body the
66
+ model otherwise drifts to a prose question instead of emitting the
67
+ structured call. (This is an authoring practice — `skill-best-practices.md`
68
+ is the write-time home for it — surfaced here because it's what makes a
69
+ runtime AskUserQuestion call fire reliably.)
70
+
71
+ ## 4. Bounded-List Caveat
72
+
73
+ AskUserQuestion is for **decisions**, not **batch processing**. A
74
+ variable-length loop of homogeneous items — reviewing 12 copy edits,
75
+ approving 30 line items — should not become 30 sequential dialogs. Past
76
+ ~5 items, prefer a single batch path (present all, take one combined
77
+ response) over N prompts. The fatigue of N near-identical dialogs
78
+ outweighs the structure they add.
79
+
80
+ The test: are these **genuine, distinct decisions** (→ AskUserQuestion,
81
+ one per item up to a small cap) or **homogeneous review items** (→ batch
82
+ path)?
83
+
84
+ ## 5. When to Use Prose
85
+
86
+ Use plain conversational prose for:
87
+
88
+ - **Free-text gathering** — names, reasons, descriptions, anything not
89
+ a fixed menu.
90
+ - **Clarifications and reasons** — "why did you defer this?"
91
+ - **Obvious-default confirms** — a yes/no where one answer is plainly
92
+ expected and the other is rare. A structured menu over-formalizes it;
93
+ a prose "Want me to X? (I'll skip if not)" is lighter.
94
+
95
+ ## 6. When to Use Markdown Tables
96
+
97
+ Use a table for **rosters, status, or any data with ≥2 columns** —
98
+ where the value is in *comparing rows*, not *choosing one*. The `/menu`
99
+ skill (skills × description) and `/cabinet` (member × domain) are
100
+ canonical examples. A table presents; AskUserQuestion decides. Don't use
101
+ a table to offer a choice, and don't use AskUserQuestion to display a
102
+ list the user isn't picking from.
103
+
104
+ ## 7. Option-Block Format
105
+
106
+ When presenting options as prose (subagent context, or >4 options), the
107
+ canonical format is in `templates/skills/onboard/phases/options.md` —
108
+ name, "what it is," "good for," "trade-off" per option. Do not duplicate
109
+ that format here; reference it.
110
+
111
+ ## 8. Section Structure & Tone
112
+
113
+ `options.md` is also canonical for tone: **present, don't prescribe.**
114
+ "Here are your options" not "I recommend X." Ground choices in the
115
+ user's actual situation. This applies whether the choice is rendered via
116
+ AskUserQuestion or prose — the primitive changes, the posture doesn't.
117
+
118
+ ## 9. Calibration Examples
119
+
120
+ **Before/after — engagement decision items** (the Tier 1 conversion):
121
+
122
+ > Before: "Present the options conversationally and let the client
123
+ > choose."
124
+ > After: For each decision item, one AskUserQuestion call — `header:
125
+ > "Decision"`, `question:` the item's client-facing prompt, `options:`
126
+ > the item's own authored option list, `multiSelect: false`. One call
127
+ > per item; never batched.
128
+
129
+ Why: the items already carry discrete, consultant-authored options, and
130
+ this is the consultant↔client boundary where ambiguity is most expensive
131
+ and the client can't ask for real-time clarification.
132
+
133
+ **Before/after — triage-audit fallback verdict:**
134
+
135
+ > Before: a prose prompt listing "Fix / Defer / Reject / Question" and
136
+ > asking the user to type one.
137
+ > After: AskUserQuestion — `header: "Verdict"`, four options, one per
138
+ > finding, `multiSelect: false`.
139
+
140
+ Why: four discrete mutually-exclusive verdicts that branch behavior —
141
+ this scores well on all five §2 criteria.
142
+
143
+ **EXCLUDED — orient registry-orphan prompt** (do NOT convert):
144
+
145
+ > "Your old project 'deal-v1' seems to have been deleted — want me to
146
+ > remove it from the registry?"
147
+
148
+ This looks like a Remove/Keep choice but is an **obvious-default
149
+ confirm**: the path no longer exists, so removal is plainly expected and
150
+ "keep" is the rare exception. A structured two-option menu over-formalizes
151
+ a routine yes/no. Leave it prose. This is the boundary that stops
152
+ AskUserQuestion from being applied to every binary question in the
153
+ codebase.
@@ -321,6 +321,20 @@ information-design's mock output. This should be sequential: designer
321
321
  produces mock, then usability critiques the interaction model using the
322
322
  mock as input."
323
323
 
324
+ **Good (output conventions — prose where AskUserQuestion fits):** "/triage-audit's
325
+ CLI-fallback path prompts the user to type one of Fix / Defer / Reject /
326
+ Question. These are four discrete, mutually-exclusive verdicts that branch
327
+ behavior — the canonical case for the native `AskUserQuestion` tool per
328
+ `skill-output-conventions.md` §2. Rendering them as a prose 'type one of…'
329
+ prompt is a guidance-layer drift. Flag as a finding pointing to that doc."
330
+ Do NOT raise this finding for: free-text gathering (names, reasons), open
331
+ clarifying questions, obvious-default confirms (e.g. orient's "remove the
332
+ deleted project from the registry?" — removal is plainly expected, so prose
333
+ is correct), or variable-length per-item loops of homogeneous items (those
334
+ prefer a batch path, not N dialogs). Match the finding to the doc's §2
335
+ checklist; if any checklist item fails, prose is the right call and there is
336
+ no finding.
337
+
324
338
  **Too narrow (belongs to another cabinet member):** "The deploy script has a
325
339
  race condition." That's technical-debt or architecture territory.
326
340
 
@@ -123,9 +123,25 @@ in `needs_you` was resolved upstream; don't nag about it.)
123
123
  Then split `needs_you` into two groups:
124
124
 
125
125
  - **Decisions** — items with a populated `options` list (or
126
- `kind === 'decision'`). These are **never** batch-approved. Walk each
127
- one individually: present the options conversationally, let the client
128
- choose. A real decision always gets explicit engagement.
126
+ `kind === 'decision'`). These are **never** batch-approved walk each
127
+ one individually with exactly **one `AskUserQuestion` call per decision
128
+ item**. Never bundle two decisions into a single call. Pre-specify the
129
+ call this way:
130
+ - `header`: `"Decision"` (within the 12-char cap).
131
+ - `question`: the item's client-facing prompt/title.
132
+ - `options`: the item's own `options` list, one labeled choice each.
133
+ **If an item has more than 4 options**, AskUserQuestion can't hold
134
+ them — fall back to presenting that item's options as prose and let
135
+ the client answer in their own words.
136
+ - `multiSelect: false` — a single verdict per decision.
137
+ - Do **not** add an "Other" choice; the harness adds it automatically.
138
+ If the client picks "Other" or says something off-menu, handle it
139
+ conversationally and map to the right verdict (see the table below).
140
+
141
+ A real decision always gets explicit engagement. (AskUserQuestion is
142
+ available here because `/engagement` runs in the main session, not a
143
+ subagent. See `.claude/cabinet/skill-output-conventions.md` for the
144
+ conventions behind this.)
129
145
  - **Approvals / FYIs** — items with no options. These are eligible for
130
146
  the batch default.
131
147
 
@@ -32,8 +32,16 @@ Access pib-db via [pib-db-access.md](../../cabinet/pib-db-access.md).
32
32
  - "What's the item?" (internal `text`)
33
33
  - "Who should see it?" — map to `audience:<id>` (and, for a delegate,
34
34
  `assignee:<id>` — the **sole** basis for a delegate seeing it).
35
- - "Is it a decision the client must make, or a credential they must
36
- provide?" `needs:decision` / `needs:credential` (or neither).
35
+ - Collect item type via `AskUserQuestion`:
36
+ - `header`: `"Item type"`
37
+ - `question`: "What kind of item is this?"
38
+ - `options`:
39
+ - Decision — "Client must choose among options you provide"
40
+ - Credential — "Client must hand over a secret (secure dialog)"
41
+ - Neither — "Informational or approval item, no special handling"
42
+ - `multiSelect: false`
43
+ Map: Decision → tag `needs:decision`. Credential → tag
44
+ `needs:credential`. Neither → no needs tag.
37
45
  - "What scope?" (optional `scope:<scope>`)
38
46
  - To make a **project itself** visible to clients as a roll-up
39
47
  (e.g., "E-signing: Done"), tag the project `client-visible` and author
@@ -50,6 +58,9 @@ Access pib-db via [pib-db-access.md](../../cabinet/pib-db-access.md).
50
58
  - Always include `client-visible` (an item with no `client-visible`
51
59
  tag appears in **no** packet).
52
60
 
61
+ (See `.claude/cabinet/skill-output-conventions.md` for when structured
62
+ choices apply.)
63
+
53
64
  3. **Prompt for the client-facing copy block** (optional — the
54
65
  consultant can write it now or let `/engagement-sync` draft it):
55
66
  - "Want to write the client-facing copy now, or let `/engagement-sync`
@@ -53,14 +53,24 @@ id, name, email, and their role."
53
53
  For each recipient, capture:
54
54
  - **id** — short handle (e.g. `ed`, `sydney`), used in tags
55
55
  - **name**, **email**
56
- - **role** — `principal` (sees everything, gets billing) or `delegate`
57
- (sees only items assigned to them, no billing)
56
+ - **role** — collect via `AskUserQuestion`:
57
+ - `header`: `"Role"`
58
+ - `question`: "What role for [name]?"
59
+ - `options`:
60
+ - Principal — "Sees everything, gets billing, defaults to interactive delivery"
61
+ - Delegate — "Sees only assigned items, no billing, defaults to email"
62
+ - `multiSelect: false`
58
63
  - **scopes** — topical areas they care about (e.g. `[marketing]`); a
59
64
  principal is usually `[all]`
60
- - **has_claude_code** — "Does [name] have Claude Code installed? If yes:
61
- they get the interactive `/engagement` view with rich status updates.
62
- If no: they get a formatted email summary instead. (Principals default
63
- to yes, delegates default to no.)"
65
+ - **has_claude_code** — collect via `AskUserQuestion`:
66
+ - `header`: `"Delivery"`
67
+ - `question`: "Does [name] have Claude Code installed?"
68
+ - `options`:
69
+ - Yes — "Interactive /engagement view with rich status"
70
+ - No — "Formatted email summary instead"
71
+ - `multiSelect: false`
72
+ (Principals default to yes, delegates default to no — use as the
73
+ pre-selected suggestion in the question phrasing.)
64
74
 
65
75
  The default `roles` block is:
66
76
  ```yaml
@@ -86,8 +96,17 @@ confirmation before proceeding.
86
96
  "Do you bill time on this engagement?" If yes:
87
97
  - **timelog** path (default `./timelog.md`)
88
98
  - **rate** (default `190`), **currency** (default `USD`)
89
- - **period** — `engagement` (running total), `month`, or
90
- `since-last-sync` (only since the last packet) — default `engagement`
99
+ - **period** — collect via `AskUserQuestion`:
100
+ - `header`: `"Billing"`
101
+ - `question`: "How should billing be calculated?"
102
+ - `options`:
103
+ - Running total — "Cumulative from engagement start (default)"
104
+ - Monthly — "Reset each calendar month"
105
+ - Since last sync — "Only time since the last packet was sent"
106
+ - `multiSelect: false`
107
+
108
+ (See `.claude/cabinet/skill-output-conventions.md` for when structured
109
+ choices apply.)
91
110
 
92
111
  Billing appears only in `principal`-role packets.
93
112
 
@@ -150,15 +150,33 @@ For every `client-visible` action or project **lacking** a `<!-- client-facing -
150
150
  summary: "N items need new copy (no block). M items have stale copy
151
151
  (status changed). Total: N+M items to review."
152
152
 
153
- **Batch option for large sets.** If more than 5 items need review, offer:
154
- "Review each individually, or review as a batch? (Batch shows all drafts
155
- at once — you confirm, edit by number, or skip any.)"
153
+ **Batch option for large sets.** If more than 5 items need review,
154
+ collect the choice via `AskUserQuestion`:
155
+ - `header`: `"Review"`
156
+ - `question`: "N items need copy review. How to proceed?"
157
+ - `options`:
158
+ - Individual — "One at a time, decide each separately"
159
+ - Batch — "Show all drafts at once, confirm/edit by number"
160
+ - `multiSelect: false`
156
161
 
157
162
  **Skip if block exists.** An existing block (hand-written or previously approved) is authoritative. Never overwrite it. Check: `parseClientCopy(notes) !== null → skip`.
158
163
 
159
164
  **Draft from structured data.** Call `buildGenerationSource(item)` (from `engagement.mjs`) to get the structured metadata — status, completion, needs, options. For projects, pre-compute `child_summary` via `computeChildSummary(actions, project.fid)` and attach it to the project object before calling. Claude drafts a `client_title` + `client_why` from this metadata. The internal `text` field is NEVER an input to generation.
160
165
 
161
- **Per-item review loop (not batch approve).** For each generated draft, show the consultant: the structured source data and the generated title + why. Consultant chooses **Accept / Edit / Skip** per item. Accepted or edited copy proceeds to write-back. Skipped items remain without copy (the dispatch gate drops them).
166
+ **Per-item review loop (not batch approve).** For each generated draft,
167
+ show the consultant the structured source data and the generated title +
168
+ why, then collect the verdict via `AskUserQuestion`:
169
+ - `header`: `"Copy"`
170
+ - `question`: "[item title] — accept this draft?"
171
+ - `options`:
172
+ - Accept — "Use this copy as-is"
173
+ - Edit — "I'll provide revised text"
174
+ - Skip — "Leave without copy (dispatch gate will drop it)"
175
+ - `multiSelect: false`
176
+
177
+ Accepted or edited copy proceeds to write-back. Skipped items remain
178
+ without copy (the dispatch gate drops them). If "Edit" is chosen, ask
179
+ for the revised text conversationally, then write back.
162
180
 
163
181
  **Write-back.** On approval, call `spliceClientCopy(notes, newBlock, markerLine)` (from `engagement.mjs`) to produce the updated notes. `newBlock` is the `<!-- client-facing ... -->` block. `markerLine` is `<!-- cc-generated:<ISO timestamp> status:<current status> -->` — placed OUTSIDE the copy block (never inside, or `parseClientCopy` would include it in `client_why`). Write via `pib_update_action({ fid, notes: splicedNotes })` or `pib_update_project({ fid, notes: splicedNotes })`.
164
182
 
@@ -218,14 +236,23 @@ For project roll-ups, show: `E-signing (roll-up: 3 done, 1 in progress)`
218
236
  vs action items: `DNS cutover (action, needs:decision)`. For projects
219
237
  with individually-visible children, note the count.
220
238
 
221
- Then ask: **"Send these updates now, or review a recipient's packet in
222
- detail first?"**
223
-
224
- - **"Send"** → proceed to archive + dispatch (steps 7–9).
225
- - **"Show me Ed's"** render Ed's full packet (needs_you titles, in_flight,
226
- shipped, messages, billing) so the consultant can read exactly what Ed will
227
- see. Then re-ask.
228
- - **"Cancel"** → abort the sync, nothing sent.
239
+ Then collect the dispatch decision via `AskUserQuestion`:
240
+ - `header`: `"Dispatch"`
241
+ - `question`: "Ready to send to N recipients?"
242
+ - `options`:
243
+ - Send "Archive and dispatch all packets now"
244
+ - Review "Show me a recipient's packet in detail first"
245
+ - Cancel — "Abort this sync, nothing sent"
246
+ - `multiSelect: false`
247
+
248
+ - **Send** → proceed to archive + dispatch (steps 7–9).
249
+ - **Review** → ask which recipient, render their full packet (needs_you,
250
+ in_flight, shipped, messages, billing), then re-present this same
251
+ AskUserQuestion (loop until Send or Cancel).
252
+ - **Cancel** → abort, nothing sent.
253
+
254
+ (See `.claude/cabinet/skill-output-conventions.md` for when structured
255
+ choices apply.)
229
256
 
230
257
  This confirmation step is the human-in-the-loop gate — the safety checks
231
258
  (assertPacketInvariants) catch structural violations, but only the
@@ -282,7 +282,19 @@ items are returned, skip silently. Otherwise:
282
282
  (`triggered | still-waiting | needs-info | condition-obsolete`)
283
283
  and brief reasoning in notes.
284
284
  4. Include any items that evaluated to `triggered` in the briefing's
285
- **Attention Items** section. Do not auto-reopen the user decides.
285
+ **Attention Items** section. For each, collect the user's decision
286
+ via `AskUserQuestion`:
287
+ - `header`: `"Triggered"`
288
+ - `question`: "[fid] appears triggered — [trigger summary]. What to do?"
289
+ - `options`:
290
+ - Reopen — "Change status back to open, ready to work"
291
+ - Leave deferred — "Keep it deferred, not ready yet"
292
+ - Mark obsolete — "Trigger condition no longer relevant"
293
+ - `multiSelect: false`
294
+
295
+ Map: Reopen → status to open; Leave deferred → no-op; Mark obsolete
296
+ → `pib_mark_trigger_checked` with `condition-obsolete`.
297
+ (See `skill-output-conventions.md`.)
286
298
 
287
299
  **Cost control:** Cap this phase at 30 seconds total. If N > 10 items,
288
300
  evaluate only the 5 least-recently-checked.
@@ -344,9 +356,18 @@ done
344
356
  Also check `git worktree list` for active worktrees whose branches
345
357
  have diverged from main.
346
358
 
347
- Surface as advisory:
348
- > Branch `feature-x` has N commits ahead of main (last touched
349
- > [date]). Merge, continue working, or discard?
359
+ Surface as advisory, then collect the decision via `AskUserQuestion`:
360
+ - `header`: `"Branch"`
361
+ - `question`: "Branch `[name]` has N commits ahead of main. What to do?"
362
+ - `options`:
363
+ - Merge — "Merge into main now"
364
+ - Continue — "Leave it, still working on it"
365
+ - Discard — "Delete the branch (destructive)"
366
+ - `multiSelect: false`
367
+
368
+ Map: Merge → `git merge [branch]` (surface conflicts if any). Continue →
369
+ no-op. Discard → warn "permanently deletes N commits" and require
370
+ explicit second confirmation before `git branch -D`.
350
371
 
351
372
  **Known platform limitation:** The Claude Code Agent tool with
352
373
  `isolation: "worktree"` branches from the remote tracking ref, not
@@ -136,8 +136,23 @@ assumption, evidence, question, and your commentary. The user needs to
136
136
  see everything to make good decisions.
137
137
 
138
138
  **Fallback (no browser available):** Present findings in the conversation
139
- grouped by cabinet member, severity-ordered within each group. Ask for
140
- verdicts one group at a time to avoid overwhelming.
139
+ grouped by cabinet member, severity-ordered within each group. For each
140
+ finding, show its full context (title, description, assumption, evidence,
141
+ question, and your commentary), then collect the verdict via one
142
+ `AskUserQuestion` call:
143
+
144
+ - `header`: `"Verdict"`
145
+ - `question`: the finding's title
146
+ - `options`:
147
+ - Fix — "Real finding, approve for action"
148
+ - Defer — "Real but not now — revisit later"
149
+ - Reject — "Not a real problem for this project"
150
+ - Question — "Need more information before deciding"
151
+ - `multiSelect: false`
152
+
153
+ One call per finding, walked individually within each group. (See
154
+ `.claude/cabinet/skill-output-conventions.md` for when this pattern
155
+ applies.)
141
156
 
142
157
  ### 3. Apply Verdicts (core)
143
158