worclaude 2.7.0 → 2.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,42 @@ All notable changes to worclaude are documented in this file. Format loosely fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.8.0] — 2026-04-24
8
+
9
+ Fixes a long-standing agent worktree correctness bug. Both `claude --worktree` and the `Agent` tool's `isolation: "worktree"` option create their isolated checkout from `origin/HEAD` — which on most worclaude-convention repos resolves to `origin/main`. When the working branch (typically `develop`) is ahead of main (the normal state mid-release-cycle), agent worktrees get a stale checkout that misses recent commits, producing "missing develop files" symptoms easy to misattribute to tooling flakiness. This release ships two complementary fixes: a new `worclaude doctor` check that detects and warns on the at-risk configuration with a local, reversible remedy (`git remote set-head origin <branch>`), and a freshness preamble on the three bundled worktree agents (`bug-fixer`, `verify-app`, `test-writer`) that resets the worktree to match the parent's current branch regardless of `origin/HEAD`. Documentation in `subagent-usage` now correctly describes the harness behavior instead of the previous "creates a worktree from your current branch" claim.
10
+
11
+ ### Added
12
+
13
+ - **`worclaude doctor` Git Integration / `origin/HEAD` divergence check** (PR #121) — warns when the current branch is ahead of `origin/HEAD`'s target, naming the branch and commit count. Suggests `git remote set-head origin <branch>` (local-only, reversible via `--auto` or `main`) as the fix. Skips silently outside a git repo or when `origin/HEAD` is unset. Shared `runGit(cwd, args)` helper added alongside for future checks to reuse the same spawn pattern.
14
+ - **Worktree freshness preamble on `bug-fixer`, `verify-app`, `test-writer` agent templates** (PR #121) — on worktree start the agent runs `git fetch origin`, identifies the parent's current branch from `git worktree list --porcelain` (filtering out auto-named `worktree-agent-*` branches), then `git reset --hard "origin/${PARENT_BRANCH}"`. Protects correctness even when the user hasn't run `set-head`. LLM-driven parsing (no `awk`/`sed` pipelines) for cross-platform portability.
15
+
16
+ ### Changed
17
+
18
+ - **`subagent-usage` skill (both `.claude/skills/subagent-usage/SKILL.md` and `templates/skills/universal/subagent-usage.md`)** (PR #121) — "How it works" item 1 corrected from "creates a worktree from your current branch" to "creates a worktree based on `origin/HEAD` (see gotcha below)". New "Base-branch gotcha" subsection cross-links to `worclaude doctor` and the `git remote set-head` remedy, and notes that the three bundled agents include a freshness preamble while other worktree agents do not.
19
+
20
+ ### Docs
21
+
22
+ - **`docs/spec/SPEC.md` doctor section** (this /sync) — adds a `### Git Integration` subsection documenting both the gitignore coverage check and the new origin/HEAD divergence check.
23
+ - **`docs/spec/PROGRESS.md`** (this /sync) — new v2.8.0 release entry; Stats refreshed (788 → 804 tests, 57 → 58 files).
24
+
25
+ ## [2.7.1] — 2026-04-24
26
+
27
+ 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.
28
+
29
+ ### Fixed
30
+
31
+ - **`/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 `?`.
32
+ - **`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.
33
+
34
+ ### Changed
35
+
36
+ - **`/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.
37
+
38
+ ### Docs
39
+
40
+ - **`docs/spec/SPEC.md` `/setup` section** (this /sync) — reflects the `help`-keyword-only trigger and the CONFIRM_MEDIUM ≤4-option AskUserQuestion path.
41
+ - **`docs/spec/PROGRESS.md`** (this /sync) — new v2.7.1 release entry; Stats refreshed (782 → 788 tests).
42
+
7
43
  ## [2.7.0] — 2026-04-23
8
44
 
9
45
  `/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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worclaude",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "The Workflow Layer for Claude Code — scaffold agents, commands, skills, hooks, and memory into any project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -838,6 +838,73 @@ async function checkGitignore(projectRoot) {
838
838
  return results;
839
839
  }
840
840
 
841
+ function runGit(projectRoot, args) {
842
+ try {
843
+ const r = spawnSync('git', args, { cwd: projectRoot, encoding: 'utf8' });
844
+ if (r.error) return { status: -1, stdout: '', stderr: String(r.error) };
845
+ return {
846
+ status: r.status,
847
+ stdout: (r.stdout || '').trim(),
848
+ stderr: (r.stderr || '').trim(),
849
+ };
850
+ } catch (err) {
851
+ return { status: -1, stdout: '', stderr: String(err) };
852
+ }
853
+ }
854
+
855
+ async function checkOriginHead(projectRoot) {
856
+ const skipped = result(PASS, 'origin/HEAD check skipped', null);
857
+
858
+ const headRef = runGit(projectRoot, ['symbolic-ref', 'refs/remotes/origin/HEAD']);
859
+ if (headRef.status === 128) return skipped;
860
+ if (headRef.status !== 0) {
861
+ return result(
862
+ WARN,
863
+ 'origin/HEAD not set',
864
+ 'Run `git remote set-head origin --auto` (or `git remote set-head origin <branch>`) so worktree agents have a defined base'
865
+ );
866
+ }
867
+
868
+ const defaultBranch = headRef.stdout.replace(/^refs\/remotes\/origin\//, '');
869
+ if (!defaultBranch) {
870
+ return result(WARN, 'origin/HEAD malformed', `Unexpected ref: ${headRef.stdout}`);
871
+ }
872
+
873
+ const currentRef = runGit(projectRoot, ['branch', '--show-current']);
874
+ if (currentRef.status !== 0) return skipped;
875
+
876
+ const currentBranch = currentRef.stdout;
877
+ if (!currentBranch) {
878
+ return result(PASS, `origin/HEAD → ${defaultBranch} (detached HEAD, skipped)`, null);
879
+ }
880
+ if (currentBranch === defaultBranch) {
881
+ return result(PASS, `origin/HEAD → ${defaultBranch} (matches current branch)`, null);
882
+ }
883
+
884
+ const ahead = runGit(projectRoot, [
885
+ 'rev-list',
886
+ '--count',
887
+ `origin/${defaultBranch}..${currentBranch}`,
888
+ ]);
889
+ if (ahead.status !== 0) {
890
+ return result(PASS, `origin/HEAD → ${defaultBranch}`, null);
891
+ }
892
+ const aheadCount = Number.parseInt(ahead.stdout, 10) || 0;
893
+ if (aheadCount === 0) {
894
+ return result(
895
+ PASS,
896
+ `origin/HEAD → ${defaultBranch}, current '${currentBranch}' not ahead`,
897
+ null
898
+ );
899
+ }
900
+
901
+ return result(
902
+ WARN,
903
+ `Current branch '${currentBranch}' is ${aheadCount} commit(s) ahead of origin/${defaultBranch}`,
904
+ `Worktree agents (claude --worktree, Agent isolation:worktree) base off origin/${defaultBranch} and will miss those commits. Fix: \`git remote set-head origin ${currentBranch}\` (local-only, reversible with \`--auto\` or \`main\`)`
905
+ );
906
+ }
907
+
841
908
  async function checkPendingReviewFiles(projectRoot) {
842
909
  const pending = [];
843
910
  try {
@@ -943,6 +1010,7 @@ export async function doctorCommand(options = {}) {
943
1010
  // Git Integration
944
1011
  section('Git Integration');
945
1012
  record('git', await checkGitignore(projectRoot));
1013
+ record('git', await checkOriginHead(projectRoot));
946
1014
  spacer();
947
1015
 
948
1016
  // Integrity
@@ -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: 'confirm',
80
+ type: 'list',
81
81
  name: 'generatePluginJson',
82
82
  message: 'Generate .claude-plugin/plugin.json for marketplace compatibility?',
83
- default: selections.generatePluginJson || false,
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: 'confirm',
90
+ type: 'list',
87
91
  name: 'scaffoldGtdMemory',
88
92
  message: 'Scaffold structured memory files (decisions.md, preferences.md)?',
89
- default: selections.scaffoldGtdMemory || false,
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 };
@@ -6,6 +6,18 @@ isolation: worktree
6
6
  maxTurns: 50
7
7
  ---
8
8
 
9
+ ## Worktree freshness preamble
10
+
11
+ Before making any code changes, synchronize this worktree to the parent checkout's committed state. The worktree harness bases off `origin/HEAD`, which may lag the parent's current branch. Follow these steps and report the result:
12
+
13
+ 1. Run `git fetch origin`.
14
+ 2. Run `git worktree list --porcelain`. Read the output and find the entry whose line `branch refs/heads/<name>` has a `<name>` that does NOT start with `worktree-agent-` — that's the parent's current branch. Strip the `refs/heads/` prefix and use it as `PARENT_BRANCH`.
15
+ 3. Run `git reset --hard "origin/${PARENT_BRANCH}"`.
16
+
17
+ If step 2 yields no match, or step 3 fails, stop and report the issue — do not make changes against an unsynchronized worktree.
18
+
19
+ ---
20
+
9
21
  You are a senior developer who specializes in diagnosing and fixing
10
22
  bugs. You follow a disciplined approach: understand the bug, find the
11
23
  root cause, make a minimal fix, and verify it with a regression test.
@@ -9,6 +9,18 @@ skills:
9
9
  - testing
10
10
  ---
11
11
 
12
+ ## Worktree freshness preamble
13
+
14
+ Before writing tests, synchronize this worktree to the parent checkout's committed state. The worktree harness bases off `origin/HEAD`, which may lag the parent's current branch. Follow these steps and report the result:
15
+
16
+ 1. Run `git fetch origin`.
17
+ 2. Run `git worktree list --porcelain`. Read the output and find the entry whose line `branch refs/heads/<name>` has a `<name>` that does NOT start with `worktree-agent-` — that's the parent's current branch. Strip the `refs/heads/` prefix and use it as `PARENT_BRANCH`.
18
+ 3. Run `git reset --hard "origin/${PARENT_BRANCH}"`.
19
+
20
+ If step 2 yields no match, or step 3 fails, stop and report the issue — tests written against a stale worktree will not cover the code you were asked about.
21
+
22
+ ---
23
+
12
24
  You are a test specialist. You write comprehensive, meaningful tests
13
25
  for recently changed code. You focus on testing behavior (what the code
14
26
  does) not implementation (how it does it). You work in a worktree to
@@ -9,6 +9,18 @@ initialPrompt: "/start"
9
9
  criticalSystemReminder: "CRITICAL: You are verification-only. Do NOT edit or fix code. Report findings with exact reproduction steps."
10
10
  ---
11
11
 
12
+ ## Worktree freshness preamble
13
+
14
+ Before running any verification, synchronize this worktree to the parent checkout's committed state. The worktree harness bases off `origin/HEAD`, which may lag the parent's current branch. Follow these steps and report the result:
15
+
16
+ 1. Run `git fetch origin`.
17
+ 2. Run `git worktree list --porcelain`. Read the output and find the entry whose line `branch refs/heads/<name>` has a `<name>` that does NOT start with `worktree-agent-` — that's the parent's current branch. Strip the `refs/heads/` prefix and use it as `PARENT_BRANCH`.
18
+ 3. Run `git reset --hard "origin/${PARENT_BRANCH}"`.
19
+
20
+ If step 2 yields no match, or step 3 fails, stop and report the issue — verification against a stale worktree is meaningless.
21
+
22
+ ---
23
+
12
24
  You are a verification specialist. You test the actual running
13
25
  application to confirm that implemented features work correctly
14
26
  end-to-end. Unit tests passing is not enough — you verify the real
@@ -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` (INTERVIEW states only, per the
69
- Interaction mode contract `selectable` / `multi-selectable`
70
- questions). Not permitted at CONFIRM_HIGH / CONFIRM_MEDIUM:
71
- those render VERBATIM per rule #7 so the text-parser contract
72
- stays stable.
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 prompt format
96
- with `[x] 1. ...` syntax or other structured output, render it
97
- EXACTLY as specified AND wrap it in a triple-backtick fenced code
98
- block so Markdown rendering does not reformat checkboxes or
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 "?" for help.
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
- - `?` | `help` → render the **Field-help** block for EACH displayed
261
- field (description + target + example) without advancing state. Then
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 `?` for help. To cancel, type
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, render ONE
284
- prompt VERBATIM in a fenced code block. The prompt shape depends on
285
- `item.candidates`:
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
- **Shape A — `candidates === null`** (emitted by `readme`):
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
- **Shape B — `candidates` is a non-empty array** (emitted by
300
- `package-manager` when multiple lockfile groups disagree):
353
+ 1. <renderValue(item)>
354
+ Will be saved as: <target>
355
+ 2. Other (I'll type my own)
301
356
 
302
- ```
303
- <formatField(field)> (detected from <source>):
304
- → Will be saved as: <target>
357
+ Reply with the number of your choice (default: 1), or type `help`:
358
+ ```
305
359
 
306
- 1. <candidates[0]>
307
- 2. <candidates[1]>
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
- Reply with the number of your choice (default: 1), or `?` for help:
313
- ```
364
+ ```
365
+ <formatField(field)> (detected from <source>):
366
+ → Will be saved as: <target>
314
367
 
315
- `<target>` comes from the **Field-help table** below. Render it
316
- verbatim per the table.
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
- `candidates[0]` equals `item.value` default-1 accepts the detected
319
- value.
374
+ Reply with the number of your choice (default: 1), or type `help`:
375
+ ```
320
376
 
321
- **Storage rule:** `mediumResolved[field]` MUST be a string. Store the
322
- exact `renderValue(item)` that was shown to the user on option 1, or
323
- the user's trimmed free-text on "Other", or `candidates[k-1]` (shape
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 (per item):
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 above.
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
- - `?` | `help` → render the **Field-help** block for this field
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 `?` for help. To cancel, type
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 `?` / `help` command (CONFIRM_HIGH, CONFIRM_MEDIUM, and
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 `?` at a CONFIRM or INTERVIEW
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
  ```
@@ -67,7 +67,7 @@ coordination overhead grows.
67
67
  Some agents use `git worktree` to make changes without affecting your working tree:
68
68
 
69
69
  How it works:
70
- 1. Agent creates a worktree from your current branch
70
+ 1. Agent creates a worktree based on `origin/HEAD` (see gotcha below)
71
71
  2. Makes changes in the worktree (isolated from your files)
72
72
  3. Commits changes
73
73
  4. You merge or cherry-pick the results
@@ -75,6 +75,19 @@ How it works:
75
75
  Agents with worktree isolation: code-simplifier, test-writer, verify-app, ci-fixer,
76
76
  bug-fixer, refactorer, doc-writer.
77
77
 
78
+ ### Base-branch gotcha
79
+
80
+ Both `claude --worktree` and the Agent `isolation: "worktree"` option create the
81
+ worktree from `origin/HEAD`, **not** your current branch. If your working branch is
82
+ ahead of whatever `origin/HEAD` points to (typically `origin/main`), the worktree
83
+ will miss those commits.
84
+
85
+ Run `worclaude doctor` to diagnose. Fix locally with `git remote set-head origin
86
+ <your-branch>` (reversible via `--auto` or `main`). The bundled `bug-fixer`,
87
+ `verify-app`, and `test-writer` agents include a freshness preamble that resets
88
+ their worktree to match the parent's current branch automatically; other worktree
89
+ agents do not.
90
+
78
91
  Benefits:
79
92
  - Agent's changes don't conflict with your uncommitted work
80
93
  - You can review agent changes before merging