worclaude 2.7.0 → 2.7.1
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/CHANGELOG.md +18 -0
- package/package.json +1 -1
- package/src/commands/init.js +12 -4
- package/templates/commands/setup.md +123 -60
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to worclaude are documented in this file. Format loosely fol
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.7.1] — 2026-04-24
|
|
8
|
+
|
|
9
|
+
Three `/setup` UX follow-ups from v2.7.0 confirmation testing, shipped as a single patch PR. The `?` / `help` trigger introduced in v2.7.0 turned out to collide with Claude Code's built-in keyboard-shortcut overlay (pressing `?` opens the shortcut panel before /setup's parser sees the keystroke); switched to the `help` keyword only. `worclaude init`'s `runOptionalExtras` was the only place in the init flow still using `inquirer type: 'confirm'` (rendered as `(y/N)`) — converted to `type: 'list'` arrow-key menus so every yes/no in init behaves consistently. CONFIRM_MEDIUM now invokes `AskUserQuestion` directly when the per-item option count fits the tool's `maxItems: 4` schema cap, with the consequence info ("Will be saved as") carried inside each option's `description` field; falls back to the verbatim text prompt (using `help` instead of `?`) when the count exceeds 4. CONFIRM_HIGH stays text-parse — detection lists routinely exceed 4 items. No consumer-visible schema or CLI surface additions.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **`/setup` `?` help trigger → `help` keyword** (PR #119) — 9 occurrences across CONFIRM_HIGH + CONFIRM_MEDIUM prompt templates, response-parsing bullets, error restates, and the Field-help table intro. Explanatory notes added so future maintainers don't re-add `?`.
|
|
14
|
+
- **`worclaude init` prompt-type consistency** (PR #119) — `runOptionalExtras` (src/commands/init.js:77-93) converted the plugin.json and gtd-memory prompts from `type: 'confirm'` (the only `(y/N)` text inputs in init) to `type: 'list'` with boolean-valued Yes/No choices. Regression test inspects `inquirer.prompt.mock.calls` directly.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **`/setup` CONFIRM_MEDIUM (≤4 options) uses `AskUserQuestion`** (PR #119) — State 3 split into Path 1 (AskUserQuestion path) and Path 2 (verbatim text fallback, >4 options). Rule #5 widens the AskUserQuestion permit to include CONFIRM_MEDIUM. Rule #7 picks up an explicit EXCEPTION paragraph. Storage rule from v2.6.5 (`mediumResolved[field]` must be a string) applies uniformly across both paths.
|
|
19
|
+
|
|
20
|
+
### Docs
|
|
21
|
+
|
|
22
|
+
- **`docs/spec/SPEC.md` `/setup` section** (this /sync) — reflects the `help`-keyword-only trigger and the CONFIRM_MEDIUM ≤4-option AskUserQuestion path.
|
|
23
|
+
- **`docs/spec/PROGRESS.md`** (this /sync) — new v2.7.1 release entry; Stats refreshed (782 → 788 tests).
|
|
24
|
+
|
|
7
25
|
## [2.7.0] — 2026-04-23
|
|
8
26
|
|
|
9
27
|
`/setup` hardening + UX revamp release. PR #115 closes 8 backend bug clusters surfaced by the v2.6.3 manual test matrix (upgrade-flow correctness, downgrade guard, doctor ghost detection, scaffolder exec bits, Commander routing). PR #116 fixes four `/setup` template failure modes — missing `schemaVersion` in SCAN state, `readme` object-shape mismatch in CONFIRM_MEDIUM, all-22-questions-asked despite detection, accept-off-topic-as-answer — and adds a `--from-file` flag to `worclaude setup-state save` plus `Bash(worclaude:*)` permissions so `/setup` runs without approval-prompt interruption. PR #117 adopts Claude Code's `AskUserQuestion` tool for 10 enumerable interview questions (arrow-key selection instead of free-text), redesigns CONFIRM prompts with a "Will be saved as" consequence sub-line and `?` / `help` command, and drops the 80-char readme truncation so users can read the full description before accepting. Dogfood-relevant: `.claude/commands/setup.md` auto-updates on `worclaude upgrade` to pick up the new template.
|
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -77,16 +77,24 @@ async function runAgents(selections) {
|
|
|
77
77
|
async function runOptionalExtras(selections) {
|
|
78
78
|
const { generatePluginJson, scaffoldGtdMemory } = await inquirer.prompt([
|
|
79
79
|
{
|
|
80
|
-
type: '
|
|
80
|
+
type: 'list',
|
|
81
81
|
name: 'generatePluginJson',
|
|
82
82
|
message: 'Generate .claude-plugin/plugin.json for marketplace compatibility?',
|
|
83
|
-
|
|
83
|
+
choices: [
|
|
84
|
+
{ name: 'Yes', value: true },
|
|
85
|
+
{ name: 'No', value: false },
|
|
86
|
+
],
|
|
87
|
+
default: selections.generatePluginJson === true ? 0 : 1,
|
|
84
88
|
},
|
|
85
89
|
{
|
|
86
|
-
type: '
|
|
90
|
+
type: 'list',
|
|
87
91
|
name: 'scaffoldGtdMemory',
|
|
88
92
|
message: 'Scaffold structured memory files (decisions.md, preferences.md)?',
|
|
89
|
-
|
|
93
|
+
choices: [
|
|
94
|
+
{ name: 'Yes', value: true },
|
|
95
|
+
{ name: 'No', value: false },
|
|
96
|
+
],
|
|
97
|
+
default: selections.scaffoldGtdMemory === true ? 0 : 1,
|
|
90
98
|
},
|
|
91
99
|
]);
|
|
92
100
|
return { ...selections, generatePluginJson, scaffoldGtdMemory };
|
|
@@ -65,11 +65,16 @@ normally apply.
|
|
|
65
65
|
- Read: `.claude/cache/setup-state.json`
|
|
66
66
|
- Write: `.claude/cache/setup-state.draft.json` (state-save staging
|
|
67
67
|
only — overwritten each save).
|
|
68
|
-
- Tool: `AskUserQuestion`
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
- Tool: `AskUserQuestion` permitted at:
|
|
69
|
+
- INTERVIEW states, per the Interaction mode contract
|
|
70
|
+
(`selectable` / `multi-selectable` / `hybrid` questions).
|
|
71
|
+
- CONFIRM_MEDIUM when the per-item option count (candidates + 1
|
|
72
|
+
for "Other") is ≤ 4 — AskUserQuestion's own `maxItems: 4`
|
|
73
|
+
schema cap. When the count exceeds 4, fall back to the verbatim
|
|
74
|
+
text-parse rendering defined in State 3 below.
|
|
75
|
+
Not permitted at CONFIRM_HIGH: the detection list routinely has
|
|
76
|
+
12+ items in real projects, which exceeds the 4-option schema cap.
|
|
77
|
+
CONFIRM_HIGH renders VERBATIM per rule #7.
|
|
73
78
|
|
|
74
79
|
At WRITE state the whitelist RELAXES to additionally permit:
|
|
75
80
|
|
|
@@ -92,15 +97,23 @@ normally apply.
|
|
|
92
97
|
project only. Only use information the user provides during THIS
|
|
93
98
|
interview and the detection report for THIS project.
|
|
94
99
|
|
|
95
|
-
7. **RENDER PROMPTS VERBATIM.** Where a state specifies a
|
|
96
|
-
with `[x] 1. ...` syntax or other structured output,
|
|
97
|
-
EXACTLY as specified AND wrap it in a triple-backtick
|
|
98
|
-
block so Markdown rendering does not reformat checkboxes
|
|
99
|
-
renumber lines. The format is part of the contract with the
|
|
100
|
+
7. **RENDER PROMPTS VERBATIM.** Where a state specifies a text-parse
|
|
101
|
+
prompt format with `[x] 1. ...` syntax or other structured output,
|
|
102
|
+
render it EXACTLY as specified AND wrap it in a triple-backtick
|
|
103
|
+
fenced code block so Markdown rendering does not reformat checkboxes
|
|
104
|
+
or renumber lines. The format is part of the contract with the
|
|
100
105
|
user-response parser — paraphrasing or reformatting breaks parsing.
|
|
101
106
|
You MAY add a brief conversational sentence before or after a
|
|
102
107
|
verbatim prompt, but NOT within it.
|
|
103
108
|
|
|
109
|
+
EXCEPTION — CONFIRM_MEDIUM via AskUserQuestion: when the per-item
|
|
110
|
+
option count is ≤ 4 (candidates + "Other"), State 3 uses the
|
|
111
|
+
`AskUserQuestion` tool path instead of the verbatim text prompt
|
|
112
|
+
(see rule #5 and State 3). The verbatim-rendering requirement does
|
|
113
|
+
not apply to tool invocations. When the count exceeds 4, the text
|
|
114
|
+
fallback kicks in and this rule applies as written. CONFIRM_HIGH
|
|
115
|
+
never uses AskUserQuestion (detection lists routinely exceed 4).
|
|
116
|
+
|
|
104
117
|
KNOWN FAILURE MODES: reformatting `[x] 1. X: Y` as `- [x] X: Y`
|
|
105
118
|
(loses numbering); paraphrasing labels; collapsing items onto one
|
|
106
119
|
line; rendering outside a fenced block (Markdown may convert `[x]`
|
|
@@ -235,7 +248,7 @@ ENTRY:
|
|
|
235
248
|
```
|
|
236
249
|
I scanned your project. Please confirm the high-confidence
|
|
237
250
|
detections below. Reply with the numbers of any items that are
|
|
238
|
-
WRONG (e.g., "2, 5"), or reply "ok" to accept all, or "
|
|
251
|
+
WRONG (e.g., "2, 5"), or reply "ok" to accept all, or type "help".
|
|
239
252
|
|
|
240
253
|
[x] 1. <formatField(item1.field)>: <renderValue(item1)> (from <item1.source>)
|
|
241
254
|
→ Will be saved as: <target1>
|
|
@@ -257,13 +270,15 @@ Response parsing (case-insensitive, whitespace trimmed):
|
|
|
257
270
|
- One or more integers (comma or space separated) in range 1..N →
|
|
258
271
|
those items are rejected; split fields into accepted/rejected
|
|
259
272
|
accordingly (in rendered order).
|
|
260
|
-
-
|
|
261
|
-
|
|
273
|
+
- `help` → render the **Field-help** block for EACH displayed field
|
|
274
|
+
(description + target + example) without advancing state. Then
|
|
262
275
|
restate the prompt above (same text, same items). Do NOT persist a
|
|
263
|
-
mutation for the help render.
|
|
276
|
+
mutation for the help render. (`?` is intentionally NOT a trigger —
|
|
277
|
+
Claude Code binds it to a keyboard-shortcut overlay that intercepts
|
|
278
|
+
the keystroke before /setup sees it.)
|
|
264
279
|
- Anything else (including integers out of range) → rule #3 fires:
|
|
265
280
|
restate with "I need either 'ok', numbers from 1 to `<N>` matching
|
|
266
|
-
the items above (e.g., '2, 5'), or
|
|
281
|
+
the items above (e.g., '2, 5'), or type `help`. To cancel, type
|
|
267
282
|
`cancel setup`."
|
|
268
283
|
|
|
269
284
|
State file mutation: persist the updated arrays via
|
|
@@ -280,69 +295,117 @@ ENTRY:
|
|
|
280
295
|
report.
|
|
281
296
|
- If there are zero medium-confidence items: persist
|
|
282
297
|
`mediumResolved: {}`, transition to INTERVIEW_STORY.
|
|
283
|
-
- Otherwise iterate in report order. For each medium item,
|
|
284
|
-
|
|
285
|
-
`
|
|
298
|
+
- Otherwise iterate in report order. For each medium item, compute the
|
|
299
|
+
total option count:
|
|
300
|
+
- Shape A (`candidates === null`, emitted by `readme`):
|
|
301
|
+
`1 + 1` = 2 (detected value + "Other").
|
|
302
|
+
- Shape B (`candidates` is a non-empty array): `candidates.length + 1`.
|
|
303
|
+
If the total is ≤ 4, use the **AskUserQuestion path** (Path 1).
|
|
304
|
+
Otherwise fall back to the **verbatim text-parse path** (Path 2).
|
|
305
|
+
The threshold is the `maxItems: 4` schema cap of AskUserQuestion.
|
|
306
|
+
|
|
307
|
+
#### Path 1 — AskUserQuestion (option count ≤ 4)
|
|
308
|
+
|
|
309
|
+
Invoke the `AskUserQuestion` tool once per medium item with exactly
|
|
310
|
+
this shape:
|
|
311
|
+
|
|
312
|
+
- `question`: `<formatField(field)> — detected from <source>. Which
|
|
313
|
+
should I use?`
|
|
314
|
+
- `header`: short label for the sidebar (≤ 12 chars) — typically
|
|
315
|
+
`formatField(field)` truncated.
|
|
316
|
+
- `multiSelect`: `false`
|
|
317
|
+
- `options`: built from the Shape above:
|
|
318
|
+
- Shape A: `[{ label: <renderValue(item)>, description: "Will be
|
|
319
|
+
saved as <target>. Accept the detected value." },
|
|
320
|
+
{ label: "Other (I'll type my own)", description: "Supply a
|
|
321
|
+
custom value via free-text follow-up." }]`
|
|
322
|
+
- Shape B: one option per `candidates[k]` with
|
|
323
|
+
`description: "Will be saved as <target>."`; append
|
|
324
|
+
`{ label: "Other (I'll type my own)", description: "Supply a
|
|
325
|
+
custom value via free-text follow-up." }` as the final option.
|
|
326
|
+
|
|
327
|
+
`<target>` comes from the **Field-help table** below. Render it
|
|
328
|
+
verbatim per the table.
|
|
329
|
+
|
|
330
|
+
On response:
|
|
331
|
+
- User selects a candidate label → store that label string in
|
|
332
|
+
`mediumResolved[field]` (Storage rule applies).
|
|
333
|
+
- User selects "Other (I'll type my own)" → follow up with a free-text
|
|
334
|
+
prompt: "Go ahead — what's the value you'd like to use?". Store the
|
|
335
|
+
trimmed reply.
|
|
336
|
+
|
|
337
|
+
`AskUserQuestion` does not expose a `help` trigger; the per-option
|
|
338
|
+
`description` text carries the equivalent content inline. The text
|
|
339
|
+
fallback's `help` keyword is scoped to Path 2 only.
|
|
340
|
+
|
|
341
|
+
#### Path 2 — Verbatim text prompt (option count > 4)
|
|
342
|
+
|
|
343
|
+
Render ONE prompt VERBATIM in a fenced code block. The prompt shape
|
|
344
|
+
depends on `item.candidates`:
|
|
345
|
+
|
|
346
|
+
**Shape A — `candidates === null`** (rare in this path — only 2
|
|
347
|
+
options, typically handled by Path 1 above; included here for
|
|
348
|
+
completeness in case AskUserQuestion is unavailable):
|
|
286
349
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
```
|
|
290
|
-
<formatField(field)> (detected from <source>):
|
|
291
|
-
|
|
292
|
-
1. <renderValue(item)>
|
|
293
|
-
→ Will be saved as: <target>
|
|
294
|
-
2. Other (I'll type my own)
|
|
295
|
-
|
|
296
|
-
Reply with the number of your choice (default: 1), or `?` for help:
|
|
297
|
-
```
|
|
350
|
+
```
|
|
351
|
+
<formatField(field)> (detected from <source>):
|
|
298
352
|
|
|
299
|
-
|
|
300
|
-
|
|
353
|
+
1. <renderValue(item)>
|
|
354
|
+
→ Will be saved as: <target>
|
|
355
|
+
2. Other (I'll type my own)
|
|
301
356
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
→ Will be saved as: <target>
|
|
357
|
+
Reply with the number of your choice (default: 1), or type `help`:
|
|
358
|
+
```
|
|
305
359
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
N. <candidates[N-1]>
|
|
310
|
-
N+1. Other (I'll type my own)
|
|
360
|
+
**Shape B — `candidates` is a non-empty array** (e.g.,
|
|
361
|
+
`package-manager` when multiple lockfile groups disagree and produce
|
|
362
|
+
4+ candidates):
|
|
311
363
|
|
|
312
|
-
|
|
313
|
-
|
|
364
|
+
```
|
|
365
|
+
<formatField(field)> (detected from <source>):
|
|
366
|
+
→ Will be saved as: <target>
|
|
314
367
|
|
|
315
|
-
|
|
316
|
-
|
|
368
|
+
1. <candidates[0]>
|
|
369
|
+
2. <candidates[1]>
|
|
370
|
+
...
|
|
371
|
+
N. <candidates[N-1]>
|
|
372
|
+
N+1. Other (I'll type my own)
|
|
317
373
|
|
|
318
|
-
|
|
319
|
-
|
|
374
|
+
Reply with the number of your choice (default: 1), or type `help`:
|
|
375
|
+
```
|
|
320
376
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
B) for a numbered pick. **NEVER store the raw `item.value` object** —
|
|
325
|
-
for fields like `readme` whose detected value is an object
|
|
326
|
-
(`{projectDescription, setupInstructions, fullPath}`) the validator
|
|
327
|
-
will reject the mutation with `state.mediumResolved.<field> must be a
|
|
328
|
-
string`.
|
|
377
|
+
`<target>` comes from the **Field-help table** below. Render it
|
|
378
|
+
verbatim per the table. `candidates[0]` equals `item.value` —
|
|
379
|
+
default-1 accepts the detected value.
|
|
329
380
|
|
|
330
|
-
Response parsing (
|
|
381
|
+
Response parsing (Path 2 only):
|
|
331
382
|
|
|
332
383
|
- `""` | `1` | `default` → accept item 1; store `renderValue(item)`
|
|
333
|
-
as a string per the Storage rule
|
|
384
|
+
as a string per the Storage rule.
|
|
334
385
|
- The final "Other" number (`2` in shape A, `N+1` in shape B) →
|
|
335
386
|
follow-up free-text prompt: "Go ahead — what's the value you'd like
|
|
336
387
|
to use?". Store the trimmed reply.
|
|
337
388
|
- Integer in range `2..N` (shape B only) → store `candidates[k-1]`.
|
|
338
|
-
-
|
|
389
|
+
- `help` → render the **Field-help** block for this field
|
|
339
390
|
(description + target + example) without advancing state. Then
|
|
340
391
|
restate the prompt above. Do NOT persist a mutation for the help
|
|
341
|
-
render.
|
|
392
|
+
render. (`?` is intentionally NOT a trigger — Claude Code binds it
|
|
393
|
+
to a keyboard-shortcut overlay that intercepts the keystroke.)
|
|
342
394
|
- Anything else → restate with "I need a number from 1 to `<max>`,
|
|
343
|
-
empty for the default, or
|
|
395
|
+
empty for the default, or type `help`. To cancel, type
|
|
344
396
|
`cancel setup`."
|
|
345
397
|
|
|
398
|
+
#### Storage rule (both paths)
|
|
399
|
+
|
|
400
|
+
`mediumResolved[field]` MUST be a string. Store the exact label that
|
|
401
|
+
was shown to the user (Path 1: `AskUserQuestion` `label`; Path 2:
|
|
402
|
+
`renderValue(item)` or `candidates[k-1]`), or the user's trimmed
|
|
403
|
+
free-text on "Other". **NEVER store the raw `item.value` object** —
|
|
404
|
+
for fields like `readme` whose detected value is an object
|
|
405
|
+
(`{projectDescription, setupInstructions, fullPath}`) the validator
|
|
406
|
+
will reject the mutation with `state.mediumResolved.<field> must be a
|
|
407
|
+
string`.
|
|
408
|
+
|
|
346
409
|
State file mutation: after EACH item is resolved (not batched),
|
|
347
410
|
append to `mediumResolved` and persist.
|
|
348
411
|
|
|
@@ -635,7 +698,7 @@ knowledge the detector has no access to).
|
|
|
635
698
|
|
|
636
699
|
### Field-help table
|
|
637
700
|
|
|
638
|
-
Drives the
|
|
701
|
+
Drives the `help` command (CONFIRM_HIGH, CONFIRM_MEDIUM, and
|
|
639
702
|
INTERVIEW states) AND the "→ Will be saved as: `<target>`" line on
|
|
640
703
|
every CONFIRM prompt. Keep the `<target>` column stable — parsers
|
|
641
704
|
downstream don't match on it, but users read it for orientation.
|
|
@@ -686,7 +749,7 @@ Interview questions (used at INTERVIEW states):
|
|
|
686
749
|
| `verification.staging` | Whether there's a staging / preview env | `## Verification` of `docs/spec/SPEC.md` | `yes — Vercel preview per PR` |
|
|
687
750
|
| `verification.required_checks` | CI required checks gating merge | `## Verification` of `docs/spec/SPEC.md` | `tests, lint, type-check` |
|
|
688
751
|
|
|
689
|
-
Help-render format when the user types
|
|
752
|
+
Help-render format when the user types `help` at a CONFIRM or INTERVIEW
|
|
690
753
|
prompt — render in a fenced code block:
|
|
691
754
|
|
|
692
755
|
```
|