worclaude 2.10.1 → 2.10.3
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 +36 -0
- package/package.json +1 -1
- package/src/commands/delete.js +6 -6
- package/src/commands/init.js +7 -7
- package/src/commands/restore.js +3 -3
- package/src/commands/upgrade.js +4 -4
- package/src/core/scaffolder.js +1 -0
- package/src/prompts/claude-md-merge.js +2 -2
- package/src/prompts/conflict-resolution.js +1 -1
- package/src/prompts/project-type.js +1 -1
- package/src/prompts/tech-stack.js +1 -1
- package/templates/skills/universal/subagent-usage.md +8 -0
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.10.3] — 2026-04-30
|
|
8
|
+
|
|
9
|
+
Fixes a user-reported breakage where every arrow-selectable prompt across `worclaude init` / `upgrade` / `restore` / `delete` accepted typed text instead of arrow-key navigation. Root cause: PR #169 (v2.10.0) bumped `inquirer` 12 → 13 with no code changes, but inquirer 13 renamed its legacy `list` prompt type to `select` and ships a runner that silently falls back to `type: 'input'` (free-text) for unknown types — so every `type: 'list'` site degraded silently. The "Everything look right?" prompt looped because typed `y`/`yes` did not strictly equal the choice value `'yes'`. Renames all 20 sites, migrates 4 index-based defaults to value-based (inquirer 13's `select` matches by value, not index), aligns the CLAUDE.md tech-stack metadata that had drifted behind `package.json` for three deps (Inquirer / Ora / Commander), and closes the test-suite blind spot — the prior `vi.mock('inquirer')` setup never inspected `spec.type`.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Arrow-selectable prompts work again across init / upgrade / restore / delete** (PR #177) — renamed all 20 `type: 'list'` sites to `type: 'select'` across `src/commands/{init,upgrade,restore,delete}.js` and `src/prompts/{claude-md-merge,conflict-resolution,project-type,tech-stack}.js`. Migrated 4 index-based `default:` values to value-based: `init.js:93,111`, `restore.js:51`, `delete.js:113,156`. Without this, "Generate plugin.json?", "Scaffold memory files?", "Install GitHub Action?", "Everything look right?", "Which step do you want to adjust?", restore and delete confirmations, and the standalone hook-conflict / project-type / claude-md-merge prompts all rendered as silent free-text inputs.
|
|
14
|
+
|
|
15
|
+
### Tests
|
|
16
|
+
|
|
17
|
+
- **Structural regression coverage for prompt types** (PR #177) — new `tests/utils/prompt-types.js` exposes `VALID_INQUIRER_TYPES` (the 10 v13 built-in prompt names) plus `expectAllValidPromptTypes(inquirer, label)` which inspects every captured `inquirer.prompt.mock.calls` spec and fails when any `type` is not a v13 built-in. New `tests/prompts/prompt-types.test.js` exercises the four standalone prompt modules + agent-selection. Single-line assertions added to `tests/commands/{init,upgrade,restore,delete}.test.js` so the ~30 sites in command files are also covered. Three stale `expect(spec.type).toBe('list')` assertions in `init.test.js` updated to `'select'`. Test counts: 992 → 999.
|
|
18
|
+
|
|
19
|
+
### Docs
|
|
20
|
+
|
|
21
|
+
- **CLAUDE.md tech-stack metadata aligned with package.json** (PR #177) — Inquirer ^12.5.0 → ^13.4.2, Ora ^8.2.0 → ^9.4.0, Commander ^13.1.0 → ^14.0.3 (all three were drifted; CLAUDE.md's own "watch for breaking changes between majors" warning had not been acted on at the time of PR #169's bump). Two new Gotchas added: (1) the silent `type` → `input` fallback in inquirer 13's legacy runner (`node_modules/inquirer/dist/ui/prompt.js`), and (2) inquirer 13 `select` defaults take the choice value, not its index — `default: 1` (second choice) becomes `default: <that-choice's-value>`.
|
|
22
|
+
|
|
23
|
+
Release group: 1 PR (patch). v2.10.2 → v2.10.3. No missing declarations.
|
|
24
|
+
|
|
25
|
+
## [2.10.2] — 2026-04-30
|
|
26
|
+
|
|
27
|
+
Bundles a dogfood catch-up of this repo's own `.claude/` (skipping from v2.8.0 to v2.10.1 in one upgrade run) with a real scaffold bug fix surfaced during that upgrade — `.claude/workflow-ref/` (transient upgrade-time conflict references) was missing from the scaffolder's `updateGitignore` entries, so every user running `worclaude upgrade` had those files pollute their git status. Also closes the BACKLOG "claude --worktree command visibility" item via a docs-only fix: investigation confirmed Claude Code does not create a "minimal `.claude/`" (the worktree's `.claude/` is a normal git checkout from `origin/HEAD`); the perceived missing-commands symptom was caused by main lagging develop, and the existing `subagent-usage` skill already documented the mechanism. The gap was direct `claude --worktree` users with no agent-mediated freshness preamble — filled with a one-paragraph copy-paste reset block.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **`.claude/workflow-ref/` now scaffolded into `.gitignore`** (PR #174) — `src/core/scaffolder.js` `updateGitignore` entries list now includes `.claude/workflow-ref/`. Existing users pick up the fix on the next scaffold or upgrade pass that runs `updateGitignore`. Two existing tests updated (`is idempotent` seed input + `writes exactly N entries` count 10 → 11 + expected array).
|
|
32
|
+
|
|
33
|
+
### Docs
|
|
34
|
+
|
|
35
|
+
- **Manual freshness reset for direct `claude --worktree`** (PR #175) — added a copy-paste workaround block (`cd .claude/worktrees/<name> && git fetch origin && git reset --hard origin/<your-branch>`) to the existing "Base-branch gotcha" section of the `subagent-usage` skill, in both `templates/skills/universal/subagent-usage.md` and the dogfood mirror. Closes BACKLOG "claude --worktree command visibility" (the entry's "minimal `.claude/`" framing was wrong; investigation captured in the session summary).
|
|
36
|
+
|
|
37
|
+
### Internal
|
|
38
|
+
|
|
39
|
+
- **Dogfood catch-up v2.8.0 → v2.10.1** (PR #174) — applied 3 release groups' worth of template evolution to this repo's own `.claude/`: sandbox.network block in settings.json (self-testing the v2.10.1 feature), observability hooks for UserPromptSubmit / InstructionsLoaded / SubagentStart / SubagentStop, 3 obs-\*.cjs hook scripts, 3 helper scripts under `.claude/scripts/`, and template-current versions of 5 slash commands plus the git-conventions skill that had drifted behind their templates.
|
|
40
|
+
|
|
41
|
+
Release group: 2 PRs (1 patch, 1 none). v2.10.1 → v2.10.2.
|
|
42
|
+
|
|
7
43
|
## [2.10.1] — 2026-04-29
|
|
8
44
|
|
|
9
45
|
Adds opt-in scaffolding for Claude Code 2.1.113's `sandbox.network` deny/allow lists. Worclaude is a scaffolder, so the new `templates/settings/base.json` ships empty `deniedDomains` and `allowedDomains` stubs rather than an opinionated default list — project owners decide their own network policy. The merge paths for both fresh init (Scenario A) and existing-project init/upgrade (Scenarios B/C) union-merge the new arrays preserving any user-added domains, and a new `worclaude doctor` check warns when the block is missing or malformed (with `worclaude upgrade` as the remediation hint). Also bundles a Dependabot major bump to `commander` 14, which is now Node-20+-only and was unblocked by the v2.10.0 Node 18 drop.
|
package/package.json
CHANGED
package/src/commands/delete.js
CHANGED
|
@@ -32,7 +32,7 @@ export async function deleteCommand() {
|
|
|
32
32
|
// Step 1: Mode selection
|
|
33
33
|
const { mode } = await inquirer.prompt([
|
|
34
34
|
{
|
|
35
|
-
type: '
|
|
35
|
+
type: 'select',
|
|
36
36
|
name: 'mode',
|
|
37
37
|
message: 'What would you like to do?',
|
|
38
38
|
choices: [
|
|
@@ -82,7 +82,7 @@ export async function deleteCommand() {
|
|
|
82
82
|
display.newline();
|
|
83
83
|
const { modifiedAction } = await inquirer.prompt([
|
|
84
84
|
{
|
|
85
|
-
type: '
|
|
85
|
+
type: 'select',
|
|
86
86
|
name: 'modifiedAction',
|
|
87
87
|
message: `${classification.modified.length} file(s) have been customized. What should we do?`,
|
|
88
88
|
choices: [
|
|
@@ -110,7 +110,7 @@ export async function deleteCommand() {
|
|
|
110
110
|
|
|
111
111
|
const { rootAction } = await inquirer.prompt([
|
|
112
112
|
{
|
|
113
|
-
type: '
|
|
113
|
+
type: 'select',
|
|
114
114
|
name: 'rootAction',
|
|
115
115
|
message: 'What would you like to do with these files?',
|
|
116
116
|
choices: [
|
|
@@ -118,7 +118,7 @@ export async function deleteCommand() {
|
|
|
118
118
|
{ name: 'Let me choose which to remove', value: 'choose' },
|
|
119
119
|
{ name: 'Remove all', value: 'remove' },
|
|
120
120
|
],
|
|
121
|
-
default:
|
|
121
|
+
default: 'keep',
|
|
122
122
|
},
|
|
123
123
|
]);
|
|
124
124
|
|
|
@@ -153,14 +153,14 @@ export async function deleteCommand() {
|
|
|
153
153
|
|
|
154
154
|
const { confirm } = await inquirer.prompt([
|
|
155
155
|
{
|
|
156
|
-
type: '
|
|
156
|
+
type: 'select',
|
|
157
157
|
name: 'confirm',
|
|
158
158
|
message: 'Confirm deletion?',
|
|
159
159
|
choices: [
|
|
160
160
|
{ name: 'Yes, delete', value: true },
|
|
161
161
|
{ name: 'No, cancel', value: false },
|
|
162
162
|
],
|
|
163
|
-
default:
|
|
163
|
+
default: false,
|
|
164
164
|
},
|
|
165
165
|
]);
|
|
166
166
|
|
package/src/commands/init.js
CHANGED
|
@@ -83,14 +83,14 @@ async function runAgents(selections) {
|
|
|
83
83
|
async function runOptionalExtras(selections) {
|
|
84
84
|
const previouslySelected = new Set(selections.optionalFeatures || []);
|
|
85
85
|
const questions = OPTIONAL_FEATURES.map((feature) => ({
|
|
86
|
-
type: '
|
|
86
|
+
type: 'select',
|
|
87
87
|
name: feature.id,
|
|
88
88
|
message: feature.label,
|
|
89
89
|
choices: [
|
|
90
90
|
{ name: 'Yes', value: true },
|
|
91
91
|
{ name: 'No', value: false },
|
|
92
92
|
],
|
|
93
|
-
default: previouslySelected.has(feature.id)
|
|
93
|
+
default: previouslySelected.has(feature.id),
|
|
94
94
|
}));
|
|
95
95
|
const answers = await inquirer.prompt(questions);
|
|
96
96
|
const optionalFeatures = OPTIONAL_FEATURES.filter((f) => answers[f.id]).map((f) => f.id);
|
|
@@ -100,7 +100,7 @@ async function runOptionalExtras(selections) {
|
|
|
100
100
|
// at it. Phase 7 T7.3.
|
|
101
101
|
const { installGithubAction } = await inquirer.prompt([
|
|
102
102
|
{
|
|
103
|
-
type: '
|
|
103
|
+
type: 'select',
|
|
104
104
|
name: 'installGithubAction',
|
|
105
105
|
message:
|
|
106
106
|
'Install Claude Code\'s GitHub Action for the @claude "compounding engineering" workflow?',
|
|
@@ -108,7 +108,7 @@ async function runOptionalExtras(selections) {
|
|
|
108
108
|
{ name: 'Yes — show me the install instructions now', value: true },
|
|
109
109
|
{ name: "No — I'll do it later", value: false },
|
|
110
110
|
],
|
|
111
|
-
default:
|
|
111
|
+
default: false,
|
|
112
112
|
},
|
|
113
113
|
]);
|
|
114
114
|
|
|
@@ -179,7 +179,7 @@ async function showConfirmation(selections) {
|
|
|
179
179
|
|
|
180
180
|
const { confirmation } = await inquirer.prompt([
|
|
181
181
|
{
|
|
182
|
-
type: '
|
|
182
|
+
type: 'select',
|
|
183
183
|
name: 'confirmation',
|
|
184
184
|
message: 'Everything look right?',
|
|
185
185
|
choices: [
|
|
@@ -241,7 +241,7 @@ async function runInteractivePrompts(projectRoot) {
|
|
|
241
241
|
} else if (confirmation === 'adjust') {
|
|
242
242
|
const { step } = await inquirer.prompt([
|
|
243
243
|
{
|
|
244
|
-
type: '
|
|
244
|
+
type: 'select',
|
|
245
245
|
name: 'step',
|
|
246
246
|
message: 'Which step do you want to adjust?',
|
|
247
247
|
choices: CONFIRMATION_STEPS,
|
|
@@ -772,7 +772,7 @@ export async function initCommand() {
|
|
|
772
772
|
|
|
773
773
|
const { proceed } = await inquirer.prompt([
|
|
774
774
|
{
|
|
775
|
-
type: '
|
|
775
|
+
type: 'select',
|
|
776
776
|
name: 'proceed',
|
|
777
777
|
message: 'Proceed with workflow installation?',
|
|
778
778
|
choices: [
|
package/src/commands/restore.js
CHANGED
|
@@ -27,7 +27,7 @@ export async function restoreCommand() {
|
|
|
27
27
|
|
|
28
28
|
const { selected } = await inquirer.prompt([
|
|
29
29
|
{
|
|
30
|
-
type: '
|
|
30
|
+
type: 'select',
|
|
31
31
|
name: 'selected',
|
|
32
32
|
message: 'Select backup to restore:',
|
|
33
33
|
choices,
|
|
@@ -48,14 +48,14 @@ export async function restoreCommand() {
|
|
|
48
48
|
|
|
49
49
|
const { confirm } = await inquirer.prompt([
|
|
50
50
|
{
|
|
51
|
-
type: '
|
|
51
|
+
type: 'select',
|
|
52
52
|
name: 'confirm',
|
|
53
53
|
message: 'Confirm restore?',
|
|
54
54
|
choices: [
|
|
55
55
|
{ name: 'Yes', value: true },
|
|
56
56
|
{ name: 'No', value: false },
|
|
57
57
|
],
|
|
58
|
-
default:
|
|
58
|
+
default: false,
|
|
59
59
|
},
|
|
60
60
|
]);
|
|
61
61
|
|
package/src/commands/upgrade.js
CHANGED
|
@@ -233,7 +233,7 @@ async function applyRepairPass(projectRoot, plan, variables) {
|
|
|
233
233
|
async function promptProceed(message) {
|
|
234
234
|
const { proceed } = await inquirer.prompt([
|
|
235
235
|
{
|
|
236
|
-
type: '
|
|
236
|
+
type: 'select',
|
|
237
237
|
name: 'proceed',
|
|
238
238
|
message,
|
|
239
239
|
choices: [
|
|
@@ -357,7 +357,7 @@ async function promptAndScaffoldOptionalFeatures(projectRoot, meta, { yes, dryRu
|
|
|
357
357
|
for (const feature of available) {
|
|
358
358
|
const { accept } = await inquirer.prompt([
|
|
359
359
|
{
|
|
360
|
-
type: '
|
|
360
|
+
type: 'select',
|
|
361
361
|
name: 'accept',
|
|
362
362
|
message: feature.label,
|
|
363
363
|
choices: [
|
|
@@ -397,7 +397,7 @@ export async function upgradeCommand(options = {}) {
|
|
|
397
397
|
);
|
|
398
398
|
const { doUpdate } = await inquirer.prompt([
|
|
399
399
|
{
|
|
400
|
-
type: '
|
|
400
|
+
type: 'select',
|
|
401
401
|
name: 'doUpdate',
|
|
402
402
|
message: 'Update worclaude CLI?',
|
|
403
403
|
choices: [
|
|
@@ -533,7 +533,7 @@ export async function upgradeCommand(options = {}) {
|
|
|
533
533
|
agentReport = await patchAgentDescriptions(projectRoot, meta, async (agentName) => {
|
|
534
534
|
const { patch } = await inquirer.prompt([
|
|
535
535
|
{
|
|
536
|
-
type: '
|
|
536
|
+
type: 'select',
|
|
537
537
|
name: 'patch',
|
|
538
538
|
message: `Agent "${agentName}" has been customized. Add missing description field?`,
|
|
539
539
|
choices: [
|
package/src/core/scaffolder.js
CHANGED
|
@@ -107,7 +107,7 @@ export async function promptClaudeMdMerge(existingContent, missingSections) {
|
|
|
107
107
|
|
|
108
108
|
const { choice } = await inquirer.prompt([
|
|
109
109
|
{
|
|
110
|
-
type: '
|
|
110
|
+
type: 'select',
|
|
111
111
|
name: 'choice',
|
|
112
112
|
message: 'How would you like to handle CLAUDE.md?',
|
|
113
113
|
choices: [
|
|
@@ -139,7 +139,7 @@ export async function interactiveSectionMerge(existingContent, renderedTemplate,
|
|
|
139
139
|
|
|
140
140
|
const { addSection } = await inquirer.prompt([
|
|
141
141
|
{
|
|
142
|
-
type: '
|
|
142
|
+
type: 'select',
|
|
143
143
|
name: 'addSection',
|
|
144
144
|
message: `Add "${sectionName}" to your CLAUDE.md?`,
|
|
145
145
|
choices: [
|
|
@@ -16,7 +16,7 @@ export async function promptHookConflict(hookCategory, existingHook, workflowHoo
|
|
|
16
16
|
|
|
17
17
|
const { resolution } = await inquirer.prompt([
|
|
18
18
|
{
|
|
19
|
-
type: '
|
|
19
|
+
type: 'select',
|
|
20
20
|
name: 'resolution',
|
|
21
21
|
message: 'How would you like to resolve this?',
|
|
22
22
|
choices: [
|
|
@@ -88,6 +88,14 @@ Run `worclaude doctor` to diagnose. Fix locally with `git remote set-head origin
|
|
|
88
88
|
their worktree to match the parent's current branch automatically; other worktree
|
|
89
89
|
agents do not.
|
|
90
90
|
|
|
91
|
+
If you invoke `claude --worktree` directly (not via an agent), no preamble runs
|
|
92
|
+
— sync the worktree manually before doing real work:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cd .claude/worktrees/<name>
|
|
96
|
+
git fetch origin && git reset --hard origin/<your-working-branch>
|
|
97
|
+
```
|
|
98
|
+
|
|
91
99
|
Benefits:
|
|
92
100
|
- Agent's changes don't conflict with your uncommitted work
|
|
93
101
|
- You can review agent changes before merging
|