worclaude 2.5.0 → 2.6.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 (33) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/package.json +4 -2
  3. package/src/commands/doctor.js +4 -6
  4. package/src/commands/init.js +9 -6
  5. package/src/commands/scan.js +126 -0
  6. package/src/commands/setup-state.js +113 -0
  7. package/src/commands/status.js +6 -4
  8. package/src/commands/upgrade.js +32 -20
  9. package/src/core/drift-checks.js +2 -1
  10. package/src/core/file-categorizer.js +38 -0
  11. package/src/core/merger.js +14 -7
  12. package/src/core/migration.js +77 -1
  13. package/src/core/project-scanner/detectors/ci.js +51 -0
  14. package/src/core/project-scanner/detectors/deployment.js +32 -0
  15. package/src/core/project-scanner/detectors/env-variables.js +78 -0
  16. package/src/core/project-scanner/detectors/external-apis.js +45 -0
  17. package/src/core/project-scanner/detectors/frameworks.js +56 -0
  18. package/src/core/project-scanner/detectors/language.js +131 -0
  19. package/src/core/project-scanner/detectors/linting.js +58 -0
  20. package/src/core/project-scanner/detectors/monorepo.js +93 -0
  21. package/src/core/project-scanner/detectors/orm.js +72 -0
  22. package/src/core/project-scanner/detectors/package-manager.js +57 -0
  23. package/src/core/project-scanner/detectors/readme.js +123 -0
  24. package/src/core/project-scanner/detectors/scripts.js +128 -0
  25. package/src/core/project-scanner/detectors/spec-docs.js +110 -0
  26. package/src/core/project-scanner/detectors/testing.js +88 -0
  27. package/src/core/project-scanner/index.js +126 -0
  28. package/src/core/project-scanner/manifests.js +120 -0
  29. package/src/core/remover.js +6 -3
  30. package/src/core/scaffolder.js +1 -0
  31. package/src/core/setup-state.js +213 -0
  32. package/src/index.js +39 -0
  33. package/templates/commands/setup.md +512 -113
@@ -1,121 +1,520 @@
1
1
  ---
2
- description: "Project setup interview fills in CLAUDE.md, skills, and configuration"
2
+ description: 'Diagnose-first project setup with state machine scans, confirms, interviews, writes.'
3
3
  ---
4
4
 
5
- You are conducting a project setup interview. Your goal is to gather
6
- enough information to fill in all project-specific files with real,
7
- useful content.
8
-
9
- IMPORTANT RULES:
10
- - Before EVERY question, remind the user: "You can type 'skip' to
11
- skip this section or 'back' to return to the previous one."
12
- - Show a persistent section indicator: "Section X of 7: [Name]"
13
- - If the user seems uncertain, reassure them: "No pressure you
14
- can always update these files later. Skip anything you're not
15
- sure about."
16
- - After each section, briefly summarize what you learned before
17
- moving on.
18
- - Be conversational, not robotic. Adapt follow-up questions based
19
- on answers.
20
- - Do NOT use information from previous conversations, memory, or
21
- other projects. This setup is for THIS project only. Only use
22
- information the user provides during this interview. Ask every
23
- question fresh do not pre-fill answers from memory.
24
-
25
- ## Interview Flow
26
-
27
- ### Section 1 of 7: Project Story
28
- Ask: "Do you have an existing project description, PRD, requirements
29
- document, or any file that describes your project? If so, share the
30
- file path and I'll read it first."
31
-
32
- If yes: Read the file. Extract purpose, features, users, constraints.
33
- Use this context for all subsequent questions — skip questions already
34
- answered by the document.
35
-
36
- If no, ask:
37
- - What does this project do in one paragraph?
38
- - Who is it for? (end users, developers, internal team, etc.)
39
- - What problem does it solve?
40
- - Is there a similar product you're modeling this after?
41
-
42
- ### Section 2 of 7: Architecture & Structure
43
- - What's the overall architecture? (monolith, microservices, monorepo, serverless)
44
- - What are the main directories or modules and their purposes?
45
- - What database(s) do you use? What are the main entities/tables?
46
- - Does it integrate with any external services or APIs?
47
- - How is it deployed? (Vercel, Railway, AWS, Docker, etc.)
48
-
49
- ### Section 3 of 7: Tech Stack Details
50
- - Specific frameworks and versions? (e.g., FastAPI 0.100+, Next.js 14)
51
- - Package manager? (npm, yarn, pnpm, bun, pip, poetry)
52
- - ORM or database client? (Prisma, SQLAlchemy, Drizzle, etc.)
53
- - Testing framework? (pytest, vitest, jest, etc.)
54
- - Linting/formatting tools already configured?
55
-
56
- ### Section 4 of 7: Core Features
57
- - What are the main features or modules?
58
- - Which are already built vs planned?
59
- - What's the priority order?
60
- - Any complex business logic Claude should understand?
61
- - Any tricky edge cases or gotchas you've discovered?
62
-
63
- ### Section 5 of 7: Development Workflow
64
- - How do you start the project locally? (exact commands)
65
- - How do you run tests? (exact commands)
66
- - How do you build for production?
67
- - Any environment variables needed? (names only, not values)
68
- - CI/CD pipeline? (GitHub Actions, GitLab CI, etc.)
69
- - Any setup steps for new developers?
70
-
71
- ### Section 6 of 7: Coding Conventions
72
- - Any specific patterns? (repository pattern, service layer, clean architecture, etc.)
73
- - Error handling approach?
74
- - Logging approach?
75
- - API response format conventions?
76
- - Naming conventions for files, functions, variables?
77
- - Any "never do this" rules specific to this project?
78
- - Any "always do this" rules?
79
-
80
- ### Section 7 of 7: Verification Strategy
81
- - How should Claude verify its changes work?
82
- - Are there specific test commands beyond the standard ones?
83
- - Can Claude run the app and test it manually? How?
84
- - Any browser testing needed? How to set up?
85
- - Is there a staging or preview environment?
86
- - Any CI checks that must pass before merging?
87
-
88
- ## After Interview
89
-
90
- Summarize everything learned in a brief overview. Then write/update
91
- these files with real, project-specific content:
92
-
93
- 1. **CLAUDE.md** — Update Tech Stack section with exact tools and
94
- versions. Update Commands section with real project commands.
95
- Add any project-specific critical rules or gotchas.
96
-
97
- 2. **docs/spec/SPEC.md** — Write a comprehensive specification
98
- from the interview answers. Include all features, data models,
99
- architecture decisions, and implementation phases.
100
-
101
- 3. **.claude/skills/backend-conventions/SKILL.md** — Fill with real
102
- backend patterns, framework-specific conventions, database
103
- patterns specific to this project.
104
-
105
- 4. **.claude/skills/frontend-design-system/SKILL.md** Fill with real
106
- design system, component patterns, styling approach if
107
- applicable.
108
-
109
- 5. **.claude/skills/project-patterns/SKILL.md** Fill with real
110
- architectural patterns, directory structure explanation,
111
- module interaction patterns.
112
-
113
- 6. **docs/spec/PROGRESS.md** — Update with actual phases and
114
- features from the interview, marking completed items.
115
-
116
- Show the user what files were updated and offer to review each one.
5
+ ## CRITICAL EXECUTION RULES READ FIRST
6
+
7
+ This command is a state machine. Once `/setup` is invoked, your behavior
8
+ is constrained by the following rules. These rules override contextual
9
+ judgment, helpfulness instincts, and any other instructions you would
10
+ normally apply.
11
+
12
+ 1. **ADVANCE STATES IN ORDER.** States execute in numeric order 0 through
13
+ 11. You MUST NOT skip a state based on your judgment about what seems
14
+ redundant. If a state's work is trivially empty (e.g., no
15
+ medium-confidence items to confirm), enter the state, record the
16
+ empty mutation, and transition immediately but DO enter it.
17
+
18
+ 2. **NO BACKWARD ADVANCE.** Once you leave a state, do not re-enter it
19
+ within this `/setup` invocation. "Invocation" means one continuous
20
+ run from INIT through DONE. Typing `cancel setup` ENDS the current
21
+ invocation; re-running `/setup` later starts a NEW invocation, and
22
+ entering the saved `currentState` is an allowed forward transition
23
+ for the new invocation. If the user wants to correct a prior answer
24
+ mid-run, tell them to finish this run and edit the output files
25
+ afterward.
26
+
27
+ 3. **OFF-TOPIC INPUT DOES NOT ADVANCE.** If the user's response to a
28
+ state's prompt is not valid input for that state, you MUST re-render
29
+ the current state's prompt with this prefix:
30
+
31
+ > "I'm in the middle of project setup (state: `<STATE_NAME>`).
32
+ > I'll help with that after setup completes. To cancel setup, type
33
+ > `cancel setup`."
34
+
35
+ You MUST NOT answer the off-topic question. You MUST NOT run any
36
+ tool to investigate the off-topic question.
37
+
38
+ 4. **CANCEL PRESERVES STATE.** The cancel trigger is the case-
39
+ insensitive regex `/^(cancel|stop|abort)( setup)?[.!?\s]*$/i`
40
+ applied to the trimmed user reply. Accepts the base verb (optionally
41
+ followed by "setup") plus trailing punctuation or whitespace —
42
+ `cancel`, `Cancel!`, `STOP SETUP.`, `abort ` all match. Text beyond
43
+ the matched prefix means "not a cancel" (`cancel please` is a
44
+ question, not a cancel). On match, acknowledge (the state file is
45
+ already saved after every mutation per rule #6), print:
46
+
47
+ > "Setup paused. Run `/setup` again to resume, or
48
+ > `worclaude setup-state reset` to discard."
49
+
50
+ and exit. You MUST NOT write any output files on cancel.
51
+
52
+ 5. **SCOPED TOOL WHITELIST.** Between SCAN ENTRY and WRITE ENTRY you
53
+ may invoke ONLY these tools:
54
+
55
+ - Shell: `worclaude scan --path .` (SCAN only)
56
+ - Shell: `worclaude setup-state show --path .`
57
+ - Shell: `worclaude setup-state save --stdin --path .` (pipe the
58
+ updated state JSON via stdin the ONLY way state is persisted)
59
+ - Shell: `worclaude setup-state reset --path .`
60
+ - Shell: `worclaude setup-state resume-info --path .`
61
+ - Read: `.claude/cache/detection-report.json`
62
+ - Read: `.claude/cache/setup-state.json`
63
+
64
+ At WRITE state the whitelist RELAXES to additionally permit:
65
+
66
+ - Read: each of the six target output files (`CLAUDE.md`,
67
+ `docs/spec/SPEC.md`, three `SKILL.md` files under
68
+ `.claude/skills/`, `docs/spec/PROGRESS.md`). Reads are ONLY to
69
+ preserve user content that the merge does not overwrite. Missing
70
+ files are treated as empty.
71
+ - Read: `.claude/workflow-meta.json` for template-hash lookup.
72
+ - Write: exactly those six files, with merged content per the
73
+ per-file merge rules in the WRITE state section.
74
+
75
+ NO OTHER tool invocation is permitted — not Grep, not Glob, not
76
+ WebFetch, not arbitrary Bash, not reads of files outside the
77
+ whitelist. If you find yourself wanting another tool, you have
78
+ already drifted; restate the current prompt instead.
79
+
80
+ 6. **NO MEMORY PRE-FILL.** Do NOT use information from previous
81
+ conversations, memory, or other projects. This setup is for THIS
82
+ project only. Only use information the user provides during THIS
83
+ interview and the detection report for THIS project.
84
+
85
+ 7. **RENDER PROMPTS VERBATIM.** Where a state specifies a prompt format
86
+ with `[x] 1. ...` syntax or other structured output, render it
87
+ EXACTLY as specified AND wrap it in a triple-backtick fenced code
88
+ block so Markdown rendering does not reformat checkboxes or
89
+ renumber lines. The format is part of the contract with the
90
+ user-response parser paraphrasing or reformatting breaks parsing.
91
+ You MAY add a brief conversational sentence before or after a
92
+ verbatim prompt, but NOT within it.
93
+
94
+ KNOWN FAILURE MODES: reformatting `[x] 1. X: Y` as `- [x] X: Y`
95
+ (loses numbering); paraphrasing labels; collapsing items onto one
96
+ line; rendering outside a fenced block (Markdown may convert `[x]`
97
+ to interactive checkboxes).
98
+
99
+ This rule ALSO applies to state-machine control prose. Render these
100
+ templates with fixed phrasing:
101
+
102
+ - Resume preamble (INTERVIEW\_\* states):
103
+ "Resuming `<STATE_NAME>`. Already have: `<comma-list>`.
104
+ Next: `<next questionId>`."
105
+ - Back rejection (INTERVIEW\_\* states):
106
+ "I can't go back within a single setup run. Finish this run and
107
+ edit the output files afterward."
108
+ - Off-topic restate prefix: exactly the text in rule #3.
109
+ - Cancel acknowledgment: exactly the text in rule #4.
110
+
111
+ If any rule conflicts with contextual judgment, **THE RULE WINS**. This
112
+ command is intentionally rigid — rigidity is the feature.
113
+
114
+ ---
115
+
116
+ ## State machine reference
117
+
118
+ | # | State | ENTRY action | EXIT condition |
119
+ | --- | ---------------------- | ----------------------------------------------------- | -------------------------------------------- |
120
+ | 0 | INIT | Precondition check, then branch to SCAN or RESUME | State loaded OR state absent/stale |
121
+ | 1 | SCAN | Invoke `worclaude scan --path .`, read cache file | Report loaded successfully |
122
+ | 2 | CONFIRM_HIGH | Render high-confidence checklist; parse response | User responds with "ok" or valid number list |
123
+ | 3 | CONFIRM_MEDIUM | Iterate medium-confidence items; one prompt each | All medium items resolved |
124
+ | 4 | INTERVIEW_STORY | Section 1 residual questions | User answered or skipped |
125
+ | 5 | INTERVIEW_ARCH | Section 2 residual questions | User answered or skipped |
126
+ | 6 | INTERVIEW_FEATURES | Section 4 conversational interview | User answered or skipped |
127
+ | 7 | INTERVIEW_WORKFLOW | Section 5 residual questions | User answered or skipped |
128
+ | 8 | INTERVIEW_CONVENTIONS | Section 6 conversational interview | User answered or skipped |
129
+ | 9 | INTERVIEW_VERIFICATION | Section 7 residual questions | User answered or skipped |
130
+ | 10 | WRITE | Merge-write the six output files from collected data | All files written (failures recorded) |
131
+ | 11 | DONE | Clear state file, summarize to user | — (terminal) |
132
+
133
+ ---
134
+
135
+ ## Per-state instructions
136
+
137
+ ### State 0 — INIT
138
+
139
+ ENTRY:
140
+
141
+ - **Precondition check.** Verify `.claude/workflow-meta.json` exists at
142
+ the project root. If absent, print "This project has not been
143
+ scaffolded by Worclaude yet. Run `worclaude init` first, then re-run
144
+ `/setup`." and exit. `/setup` is a post-init command.
145
+ - Invoke `worclaude setup-state show --path .`.
146
+ - If stdout is `no state` → advance to SCAN.
147
+ - If the command exits non-zero (corrupt state file, unsupported
148
+ schema, unreadable project root): print the stderr verbatim, add
149
+ "The setup state file looks broken. Run
150
+ `worclaude setup-state reset` to discard it, then re-run `/setup`.",
151
+ and exit. Do NOT auto-reset.
152
+ - If stdout is a JSON state object:
153
+ - Invoke `worclaude setup-state resume-info --path .` to get the
154
+ pre-formatted `state: ..., age: ..., staleness: ...` line.
155
+ - If `staleness: stale` → prompt: "Found a setup in progress from
156
+ `<age>`. That's old enough I'd rather start fresh. Discard and run
157
+ a new setup? [yes/no]". `yes` → invoke
158
+ `worclaude setup-state reset`, advance to SCAN. `no` → resume at
159
+ the saved `currentState`.
160
+ - Otherwise (`fresh`) → prompt: "Found a setup in progress (state:
161
+ `<STATE>`, started `<age>` ago). Resume from there, or start over?
162
+ [resume/restart]". `resume` → jump to the saved `currentState`.
163
+ `restart` → invoke reset, advance to SCAN.
164
+
165
+ EXIT: SCAN (fresh/reset) or the saved `currentState` (resume).
166
+ Resuming begins a new invocation (rule #2).
167
+
168
+ ### State 1 — SCAN
169
+
170
+ ENTRY:
171
+
172
+ - Invoke `worclaude scan --path .`.
173
+ - Read `.claude/cache/detection-report.json`.
174
+ - If the report has a non-empty `errors` array, render a one-block
175
+ warning verbatim:
176
+
177
+ ```
178
+ The scanner ran but reported <N> detector error(s). I'll proceed
179
+ with what was detected; the error'd fields will be asked in the
180
+ interview.
181
+ Errors:
182
+ - <detector>: <kind> — <message>
183
+ - ...
184
+ ```
185
+
186
+ - State file mutation: write a fresh state with `currentState: "SCAN"`,
187
+ `startedAt` and `updatedAt` set to now, `detectionReportPath:
188
+ ".claude/cache/detection-report.json"`, empty arrays/objects for the
189
+ remaining fields. Persist via `worclaude setup-state save --stdin`.
190
+
191
+ EXIT: advance to CONFIRM_HIGH.
192
+
193
+ ### State 2 — CONFIRM_HIGH
194
+
195
+ ENTRY:
196
+
197
+ - Read the detection report. Gather entries with
198
+ `confidence === "high"`.
199
+ - If there are zero high-confidence items: persist the state with
200
+ `currentState: "CONFIRM_HIGH"`, `highConfirmedAccepted: []`,
201
+ `highConfirmedRejected: []`, and transition to CONFIRM_MEDIUM
202
+ (trivial exit per rule #1).
203
+ - Otherwise render VERBATIM (wrapped in a triple-backtick fenced code
204
+ block):
205
+
206
+ ```
207
+ I scanned your project. Please confirm the high-confidence
208
+ detections below. Reply with the numbers of any items that are
209
+ WRONG (e.g., "2, 5"), or reply "ok" to accept all.
210
+
211
+ [x] 1. <formatField(item1.field)>: <renderValue(item1)> (from <item1.source>)
212
+ [x] 2. ...
213
+
214
+ Your response:
215
+ ```
216
+
217
+ `<formatField>` and `<renderValue>` are defined in the **Field
218
+ rendering table** below.
219
+
220
+ Response parsing (case-insensitive, whitespace trimmed):
221
+
222
+ - `ok` | `yes` | `all good` | `""` → accept all; set
223
+ `highConfirmedAccepted` to all item field names in rendered order;
224
+ `highConfirmedRejected: []`.
225
+ - One or more integers (comma or space separated) in range 1..N →
226
+ those items are rejected; split fields into accepted/rejected
227
+ accordingly (in rendered order).
228
+ - Anything else (including integers out of range) → rule #3 fires:
229
+ restate with "I need either 'ok' or numbers from 1 to `<N>` matching
230
+ the items above (e.g., '2, 5'). To cancel, type `cancel setup`."
231
+
232
+ State file mutation: persist the updated arrays via
233
+ `worclaude setup-state save --stdin`.
234
+
235
+ EXIT: advance to CONFIRM_MEDIUM.
236
+
237
+ ### State 3 — CONFIRM_MEDIUM
238
+
239
+ ENTRY:
240
+
241
+ - Gather entries with `confidence === "medium"` from the detection
242
+ report.
243
+ - If there are zero medium-confidence items: persist
244
+ `mediumResolved: {}`, transition to INTERVIEW_STORY.
245
+ - Otherwise iterate in report order. For each medium item, render ONE
246
+ prompt VERBATIM in a fenced code block. The prompt shape depends on
247
+ `item.candidates`:
248
+
249
+ **Shape A — `candidates === null`** (emitted by `readme`):
250
+
251
+ ```
252
+ <formatField(field)> (detected from <source>):
253
+
254
+ 1. <renderValue(item)>
255
+ 2. Other (I'll type my own)
256
+
257
+ Reply with the number of your choice (default: 1):
258
+ ```
259
+
260
+ **Shape B — `candidates` is a non-empty array** (emitted by
261
+ `package-manager` when multiple lockfile groups disagree):
262
+
263
+ ```
264
+ <formatField(field)> (detected from <source>):
265
+
266
+ 1. <candidates[0]>
267
+ 2. <candidates[1]>
268
+ ...
269
+ N. <candidates[N-1]>
270
+ N+1. Other (I'll type my own)
271
+
272
+ Reply with the number of your choice (default: 1):
273
+ ```
274
+
275
+ `candidates[0]` equals `item.value` — default-1 accepts the detected
276
+ value.
277
+
278
+ Response parsing (per item):
279
+
280
+ - `""` | `1` | `default` → accept item 1 (the detected value).
281
+ - The final "Other" number (`2` in shape A, `N+1` in shape B) →
282
+ follow-up free-text prompt: "Go ahead — what's the value you'd like
283
+ to use?". Record the trimmed reply as the answer.
284
+ - Integer in range `2..N` (shape B only) → accept `candidates[k-1]`.
285
+ - Anything else → restate with "I need a number from 1 to `<max>`, or
286
+ empty for the default. To cancel, type `cancel setup`."
287
+
288
+ State file mutation: after EACH item is resolved (not batched),
289
+ append to `mediumResolved` and persist.
290
+
291
+ EXIT: advance to INTERVIEW_STORY.
292
+
293
+ ### States 4–9 — INTERVIEW\_\*
294
+
295
+ Shared ENTRY protocol for each INTERVIEW state:
296
+
297
+ - Read the state file. Determine this state's question list from the
298
+ **QuestionId enumeration** below plus any rejected fields routed to
299
+ this state from CONFIRM_HIGH (per the **Rejected-field re-ask
300
+ routing** table).
301
+ - Skip any `questionId` already present in `interviewAnswers`.
302
+ - Resume preamble (only if ANY questionId is already answered AND at
303
+ least one remains): "Resuming `<STATE_NAME>`. Already have:
304
+ `<comma-list>`. Next: `<next questionId>`."
305
+ - If ALL `questionId`s for this state are present, trivially-exit:
306
+ persist a state update (only `currentState` and `updatedAt` change)
307
+ and advance.
308
+ - Ask remaining questions conversationally, in enumeration order.
309
+ - `skip` on a question → record `interviewAnswers[<questionId>] =
310
+ "[skipped]"`, advance to the next question in this state.
311
+ - `skip all` → record every remaining `questionId` as `[skipped]`,
312
+ exit the state.
313
+ - `back` → restate the current question with the prefix "I can't go
314
+ back within a single setup run. Finish this run and edit the output
315
+ files afterward." (rule #2).
316
+ - Rule #3 applies within interview states: off-topic replies trigger
317
+ a restatement of the pending question, not an answer to the
318
+ off-topic question.
319
+
320
+ State file mutation: after EACH question is answered or skipped,
321
+ persist via `worclaude setup-state save --stdin` BEFORE rendering the
322
+ next prompt. Resume granularity is per-question.
323
+
324
+ EXIT: advance to the next state; INTERVIEW_VERIFICATION exits to
325
+ WRITE.
326
+
327
+ ### State 10 — WRITE
328
+
329
+ ENTRY:
330
+
331
+ - Per rule #5's WRITE relaxation, read each of the six target files
332
+ (missing → empty) and read `.claude/workflow-meta.json` for template
333
+ hashes.
334
+ - Compose merged contents per the per-file merge rules below.
335
+ - Write each file. Per-file failure is recorded but does not abort
336
+ the remaining writes.
337
+ - State file mutation: record `writeResults: { [file]: "ok" | "error:
338
+ <message>" }` and persist.
339
+
340
+ Per-file merge rules:
341
+
342
+ 1. **`CLAUDE.md`** — ATX-heading-scoped replace. Replace ONLY the body
343
+ of `## Tech Stack` and `## Commands` with generated content.
344
+ Preserve every other section verbatim (user additions, critical
345
+ rules, gotchas). If either target section is absent, append it at
346
+ the end.
347
+ 2. **`docs/spec/SPEC.md`** — full rewrite if empty or template-only;
348
+ otherwise append a `## Additions from /setup (<ISO-date>)` section
349
+ at the end.
350
+ 3. **`.claude/skills/backend-conventions/SKILL.md`** — same rule as
351
+ SPEC.md.
352
+ 4. **`.claude/skills/frontend-design-system/SKILL.md`** — same rule.
353
+ 5. **`.claude/skills/project-patterns/SKILL.md`** — same rule.
354
+ 6. **`docs/spec/PROGRESS.md`** — never overwrite. Append a
355
+ `## Setup notes (<ISO-date>)` section with detected stack summary
356
+ and interview highlights.
357
+
358
+ **Template-hash lookup.** "Template-only" means the file's
359
+ CRLF-normalized SHA-256 matches the hash stored in
360
+ `.claude/workflow-meta.json` for that file. If the meta file is
361
+ missing or lacks the entry, treat the file as authored (safer
362
+ default: append, do not rewrite).
363
+
364
+ EXIT: advance to DONE.
365
+
366
+ ### State 11 — DONE
367
+
368
+ ENTRY:
369
+
370
+ - Invoke `worclaude setup-state reset` to clear the state file.
371
+ - Print: "Setup complete. Wrote `<N>`/6 files. [If any errors: list
372
+ them.] Review what I wrote and edit anything that looks off."
373
+
374
+ EXIT: terminal.
375
+
376
+ ---
377
+
378
+ ## QuestionId enumeration (load-bearing contract)
379
+
380
+ These IDs are the keys for `interviewAnswers`. `saveSetupState`
381
+ rejects keys outside this set (with the `<state>.unchecked.<field>`
382
+ prefix exception — see routing table).
383
+
384
+ **INTERVIEW_STORY** (section 1; residual after README + spec-docs
385
+ detection):
386
+
387
+ - `story.audience` — "Who is it for?"
388
+ - `story.problem` — "What problem does it solve?"
389
+ - `story.analogs` — "Any similar product you're modeling after?"
390
+
391
+ **INTERVIEW_ARCH** (section 2; `monorepo` detector flags presence
392
+ only):
393
+
394
+ - `arch.classification` — monolith / microservices / monorepo /
395
+ serverless
396
+ - `arch.modules` — directory/module purposes. Prompt the user to
397
+ mention in-house libraries and private-registry packages here.
398
+ - `arch.entities` — database entities (detector knows the ORM;
399
+ entities are user knowledge).
400
+ - `arch.external_apis` — external APIs beyond SDK detection.
401
+ - `arch.stack_rationale` — WHY the detected framework/stack choices
402
+ were made.
403
+
404
+ **INTERVIEW_FEATURES** (section 4; detection ~10%):
405
+
406
+ - `features.core` — list of core features.
407
+ - `features.nice_to_have` — nice-to-have features.
408
+ - `features.non_goals` — explicit non-goals.
409
+
410
+ **INTERVIEW_WORKFLOW** (section 5; residual after scripts,
411
+ env-variables, ci detection):
412
+
413
+ - `workflow.new_dev_steps` — setup steps beyond README.
414
+ - `workflow.env_values` — guidance for env variable values (detector
415
+ has names only, not values).
416
+
417
+ **INTERVIEW_CONVENTIONS** (section 6; detection ~21%):
418
+
419
+ - `conventions.patterns` — code patterns the project uses.
420
+ - `conventions.errors` — error handling approach.
421
+ - `conventions.logging` — logging approach.
422
+ - `conventions.api_format` — API response format.
423
+ - `conventions.naming` — naming conventions.
424
+ - `conventions.rules` — never/always rules.
425
+
426
+ **INTERVIEW_VERIFICATION** (section 7; residual after testing + ci
427
+ detection):
428
+
429
+ - `verification.manual` — manual verification steps.
430
+ - `verification.staging` — staging/preview environment.
431
+ - `verification.required_checks` — CI required checks.
432
+
433
+ ### Rejected-field re-ask routing
434
+
435
+ Fields in `highConfirmedRejected` are re-asked as one sub-question
436
+ each in the INTERVIEW state that matches the field's natural section.
437
+
438
+ | Rejected field | Re-asked in | Answer key |
439
+ | ------------------------------------ | ---------------------- | -------------------------------- |
440
+ | `readme`, `specDocs` | INTERVIEW_STORY | `story.unchecked.<field>` |
441
+ | `packageManager`, `language` | INTERVIEW_ARCH | `arch.unchecked.<field>` |
442
+ | `frameworks`, `orm`, `monorepo` | INTERVIEW_ARCH | `arch.unchecked.<field>` |
443
+ | `deployment`, `externalApis` | INTERVIEW_ARCH | `arch.unchecked.<field>` |
444
+ | `scripts`, `envVariables`, `linting` | INTERVIEW_WORKFLOW | `workflow.unchecked.<field>` |
445
+ | `ci` | INTERVIEW_WORKFLOW | `workflow.unchecked.<field>` |
446
+ | `testing` | INTERVIEW_VERIFICATION | `verification.unchecked.<field>` |
447
+
448
+ `<state>.unchecked.<field>` keys are the ONLY keys outside the
449
+ enumeration that `saveSetupState` accepts, matched by prefix. The
450
+ `<field>` segment must exactly match a known detector field name AND
451
+ the routing table must map that field to that state prefix.
452
+
453
+ ---
454
+
455
+ ## Field rendering table
456
+
457
+ Reproduced from the scanner's `summarizeValue` semantics. Used in
458
+ CONFIRM_HIGH and CONFIRM_MEDIUM to render `<renderValue(item)>`.
459
+
460
+ | `field` | `item.value` shape | Rendered as |
461
+ | ---------------- | ---------------------------------------------- | -------------------------------------------------------------------- |
462
+ | `packageManager` | string | `<value>` (shape-B medium → render `candidates` one per line) |
463
+ | `language` | string | `<value>` |
464
+ | `frameworks` | `[{name, version}, ...]` | `Name Version, Name Version` joined by `, ` (missing version → just `Name`) |
465
+ | `testing` | `{framework, configFile, ...}` | `<framework> (<configFile>)` — if `configFile` null: `<framework>` |
466
+ | `linting` | `string[]` | joined by `, ` (empty → omit this item) |
467
+ | `orm` | `{name, schemaFile}` | `<name>` |
468
+ | `deployment` | string | `<value>` |
469
+ | `ci` | `{provider, workflows: string[]}` | `<provider>, <N> workflow(s)` (singular when `N === 1`) |
470
+ | `scripts` | `{dev, test, build, lint, ...}` | `dev=<dev.key> test=<test.key> build=<build.key> lint=<lint.key>` — omit null slots; all null → `(no standard scripts)` |
471
+ | `envVariables` | `{names: string[], inferredServices: [...]}` | `<N> variable(s)` (singular when `N === 1`; 0 → omit) |
472
+ | `externalApis` | `string[]` | joined by `, ` (empty → omit) |
473
+ | `readme` | `{projectDescription, ...}` | `<projectDescription>` truncated to 80 chars with `…` suffix |
474
+ | `specDocs` | `[{path, firstHeading}, ...]` | `<N> doc(s)` (empty → omit) |
475
+ | `monorepo` | `{tool, packagePaths, ...}` | `<tool> (<N> packages)` |
476
+ | fallback scalar | string / number / boolean | `String(value)` |
477
+
478
+ `formatField(field)` inserts a space before each uppercase letter and
479
+ capitalizes the first character — every word ends up Title-Cased:
480
+ `packageManager` → `Package Manager`, `envVariables` →
481
+ `Env Variables`, `externalApis` → `External Apis`, `specDocs` →
482
+ `Spec Docs`. Render exactly what `formatField` produces — do not
483
+ retitle `External Apis` as `External APIs` or similar; the parser
484
+ matches the scanner's output, not natural-language acronym casing.
485
+
486
+ ---
487
+
488
+ ## WRITE composition (which state data flows to which file)
489
+
490
+ For each target file, compose content from detection + `mediumResolved` +
491
+ `interviewAnswers` per this mapping:
492
+
493
+ - **`CLAUDE.md`** Tech Stack ← `packageManager`, `language`,
494
+ `frameworks`, `orm`, `testing`, `linting`. Commands ← `scripts` +
495
+ `workflow.unchecked.scripts`.
496
+ - **`docs/spec/SPEC.md`** ← Overview (`story.*`); Architecture
497
+ (`arch.*`, `frameworks`, `monorepo`, `deployment`); Features
498
+ (`features.*`); Workflow (`workflow.*`, `scripts`, `ci`,
499
+ `envVariables`); Conventions (`conventions.*`); Verification
500
+ (`verification.*`, `testing`, `ci`).
501
+ - **`backend-conventions/SKILL.md`** ← `conventions.errors`,
502
+ `conventions.logging`, `conventions.api_format`, `orm`,
503
+ `externalApis`.
504
+ - **`frontend-design-system/SKILL.md`** ← detected frontend
505
+ frameworks (`react`, `vue`, `svelte`, `next`, `nuxt` — if present in
506
+ `frameworks`) + design-system residuals from interview answers.
507
+ - **`project-patterns/SKILL.md`** ← `conventions.patterns`,
508
+ `conventions.naming`, `conventions.rules`, `arch.classification`,
509
+ `arch.modules`.
510
+ - **`docs/spec/PROGRESS.md`** ← `## Setup notes (<ISO-date>)`
511
+ appended; detected stack summary + interview highlights.
512
+
513
+ ---
117
514
 
118
515
  ## Trigger Phrases
516
+
119
517
  - "set up the project"
120
518
  - "configure this project"
121
519
  - "project interview"
520
+ - "run setup"