agentic-sdlc-wizard 1.47.0 → 1.48.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.
@@ -11,351 +11,259 @@ $ARGUMENTS
11
11
 
12
12
  ## Purpose
13
13
 
14
- You are a guided update assistant. Your job is to check what version the user has, show what changed, and walk them through selectively adopting updates while preserving their customizations. DO NOT blindly overwrite files. Show diffs and let the user decide.
14
+ Guided update assistant. Check what version the user has, show what changed, walk them through selectively adopting updates while preserving their customizations. **DO NOT blindly overwrite files.** Show diffs and let the user decide.
15
15
 
16
16
  ## MANDATORY FIRST ACTION: Read the Wizard Doc
17
17
 
18
- **Before doing ANYTHING else**, use the Read tool to read the `CLAUDE_CODE_SDLC_WIZARD.md` file — specifically the "Staying Updated (Idempotent Wizard)" section near the end. This contains the update URLs, version tracking format, and step registry you need. Do NOT proceed without reading it first.
18
+ **Before doing ANYTHING else**, use Read on `CLAUDE_CODE_SDLC_WIZARD.md` — specifically the "Staying Updated (Idempotent Wizard)" section near the end. This contains update URLs, version tracking format, and step registry. Do NOT proceed without reading it first.
19
19
 
20
20
  ## Execution Checklist
21
21
 
22
- Follow these steps IN ORDER. Do not skip or combine steps.
22
+ Follow steps IN ORDER. Do not skip or combine.
23
23
 
24
24
  ### Step 1: Read Installed Version
25
25
 
26
- Read `SDLC.md` and extract the version from the metadata comment:
26
+ Read `SDLC.md` and extract from the metadata comment:
27
27
  ```
28
28
  <!-- SDLC Wizard Version: X.X.X -->
29
+ <!-- Completed Steps: ... -->
29
30
  ```
30
- If no version comment exists, treat as `0.0.0` (first-time setup — suggest running `/setup-wizard` instead).
31
-
32
- Also note the completed steps from `<!-- Completed Steps: ... -->`.
31
+ No version comment treat as `0.0.0` (suggest `/setup-wizard` instead).
33
32
 
34
33
  ### Step 1.5: Check CLI Version (ROADMAP #232)
35
34
 
36
- The wizard files in the user's project (skills, hooks, settings.json) are one half of the install. The other half is the **npm CLI** (`agentic-sdlc-wizard`) — the binary that powers `npx agentic-sdlc-wizard init`, `check`, and `complexity`. If the user ran `npx agentic-sdlc-wizard init` months ago, their npx cache (or global install) can be stuck on an old version even after `/update-wizard` patches the project files in-session. This step closes that gap: detect the locally installed CLI version, compare to the npm registry latest, and surface a one-shot upgrade BEFORE running drift detection or per-file updates.
37
-
38
- **Detection — try both paths, in order:**
35
+ The wizard files in the user's project are one half of the install. The other half is the **npm CLI** (`agentic-sdlc-wizard`) — the binary powering `npx agentic-sdlc-wizard init`/`check`/`complexity`. If the user ran `init` months ago, their npx cache (or global install) can be stuck on an old version even after `/update-wizard` patches the project files in-session. This step closes that gap.
39
36
 
40
- 1. **Global install** (rare but possible): `npm ls -g agentic-sdlc-wizard --json --depth=0 2>/dev/null | jq -r '.dependencies["agentic-sdlc-wizard"].version // empty'` emits the version if globally installed, empty otherwise.
37
+ **Detectiontry both paths:**
41
38
 
42
- 2. **npx cache** (the common case): find every `package.json` in npx's cache layout, extract `.version`, then pick the largest by semver. Do NOT use `sort -u | tail -1` — that's lexicographic and treats `1.9.0 > 1.10.0`. Use Node's built-in semver-aware compare:
39
+ 1. **Global install** (rare): `npm ls -g agentic-sdlc-wizard --json --depth=0 2>/dev/null | jq -r '.dependencies["agentic-sdlc-wizard"].version // empty'`
43
40
 
44
- ```bash
45
- find ~/.npm/_npx -maxdepth 4 -name 'package.json' -path '*agentic-sdlc-wizard*' 2>/dev/null \
46
- | xargs -I{} jq -r '.version' {} 2>/dev/null \
47
- | node -e "
48
- let max = '';
49
- require('readline').createInterface({input: process.stdin}).on('line', v => {
50
- if (!v) return;
51
- if (!max || cmp(v, max) > 0) max = v;
52
- }).on('close', () => process.stdout.write(max));
53
- function cmp(a, b) {
54
- const [ab, ap] = a.split('-'), [bb, bp] = b.split('-');
55
- const an = ab.split('.').map(Number), bn = bb.split('.').map(Number);
56
- for (let i = 0; i < 3; i++) if (an[i] !== bn[i]) return an[i] - bn[i];
57
- if (ap && !bp) return -1; if (!ap && bp) return 1;
58
- if (ap && bp) return ap < bp ? -1 : ap > bp ? 1 : 0;
59
- return 0;
60
- }
61
- "
62
- ```
41
+ 2. **npx cache** (common): find every `package.json` under `~/.npm/_npx` matching `*agentic-sdlc-wizard*`, extract `.version`, pick the largest **by semver** (do NOT use `sort -u | tail -1` — lexicographic treats `1.9.0 > 1.10.0`). Use a Node `cmp()` helper: split on `-` for prerelease tag, compare numeric `major.minor.patch`, then prerelease ordering (`1.40.0-beta.1 < 1.40.0`). Read each version on its own line via stdin, track max, print at close. Empty input → empty output.
63
42
 
64
- This reads each found version on its own line, compares pairwise with semver semantics (numeric major.minor.patch, plus prerelease tags ordered as `1.40.0-beta.1 < 1.40.0`), and prints the maximum. Empty input prints empty.
65
-
66
- If both paths return empty, the user may be running from a custom install or has never used `npx`. Treat as **undetectable** — note it in your update report but do not block the rest of the flow. Skip the CLI bump prompt, continue to Step 2.
43
+ If both paths return empty, the user may be running from a custom install or never used `npx`. Treat as **undetectable** note in the report but do not block. Skip the CLI bump prompt; continue to Step 2.
67
44
 
68
45
  **Registry comparison:**
69
-
70
46
  ```bash
71
47
  curl -fsS "https://registry.npmjs.org/agentic-sdlc-wizard/latest" | jq -r '.version'
72
48
  ```
49
+ Cache the result (also used in Step 3).
73
50
 
74
- This is the same endpoint the registry serves; the response is a single JSON object with `version` set to the published latest tag. Cache the result (it's also used in Step 3 for the wizard version comparison).
75
-
76
- **Compare with semver-aware logic** — `sort -V` does NOT correctly order prereleases (it places `1.40.0-beta.1` *after* `1.40.0`, but semver requires the opposite). Use the same Node `cmp()` helper from the npx-cache step:
77
-
78
- ```bash
79
- node -e "
80
- const a = process.argv[1], b = process.argv[2];
81
- function cmp(a, b) { /* same body as above */ }
82
- process.exit(cmp(a, b) < 0 ? 0 : cmp(a, b) > 0 ? 1 : 2);
83
- " "$INSTALLED" "$LATEST"
84
- # Exit 0 = installed < latest (behind); 1 = installed > latest; 2 = equal
85
- ```
51
+ **Compare with semver-aware logic** `sort -V` does NOT correctly order prereleases. Reuse the Node `cmp()` helper to produce exit `0` (installed < latest), `1` (installed > latest), `2` (equal).
86
52
 
87
- **Surface based on the result:**
53
+ **Surface the result:**
54
+ - `installed == latest` → silent, continue.
55
+ - `installed < latest` → show the gap with the upgrade options below.
56
+ - `installed > latest` (rare — pre-release/local dev) → silent, continue.
88
57
 
89
- - `installed == latest` → silent, continue to Step 2.
90
- - `installed < latest` → surface the gap with the upgrade options below.
91
- - `installed > latest` (rare — pre-release or local dev install) → silent, continue.
58
+ **Upgrade options when behind:**
92
59
 
93
- **Upgrade options when behind:** be honest about what each does. Recommend the safer path by default.
94
-
95
- > Your locally installed `agentic-sdlc-wizard` CLI is at **{installed}**, but npm has **{latest}**. The in-session `/update-wizard` will refresh this project's files via Step 6's per-file plan, but your `npx` cache will keep the old CLI on disk for `npx agentic-sdlc-wizard check`/`init`/`complexity` calls.
96
- >
97
- > Pick one:
98
- >
99
- > **A. Refresh just the CLI cache (recommended).** Doesn't touch your project files. Then `/update-wizard`'s per-file plan handles the rest with diffs:
100
- > ```bash
101
- > npx -y agentic-sdlc-wizard@latest --version
102
- > ```
103
- >
104
- > **B. One-shot CLI + project re-init.** Refreshes the CLI AND overwrites *non-settings* managed files (skills, hooks, templates) with the latest versions. `settings.json` is smart-merged (custom hooks + permissions preserved); other managed files are NOT smart-merged — local edits to them are lost unless committed to git or backed up. Use this if you don't have local skill/hook customizations:
105
- > ```bash
106
- > npx -y agentic-sdlc-wizard@latest init --force
107
- > ```
108
- >
109
- > **C. Skip the CLI bump entirely.** Keep the stale CLI; this session's file updates apply but `npx agentic-sdlc-wizard check` will keep using the old drift logic.
110
- >
111
- > Pick A, B, or C: `[A/B/C]`
60
+ > Your `agentic-sdlc-wizard` CLI is at **{installed}**, npm has **{latest}**. The in-session `/update-wizard` will refresh project files via Step 6, but your `npx` cache will keep the old CLI on disk for `npx agentic-sdlc-wizard check`/`init`/`complexity`.
61
+ >
62
+ > **A. Refresh just the CLI cache (recommended).** No project changes; Step 6 handles the rest with diffs:
63
+ > ```bash
64
+ > npx -y agentic-sdlc-wizard@latest --version
65
+ > ```
66
+ >
67
+ > **B. One-shot CLI + project re-init.** Refreshes CLI AND overwrites *non-settings* managed files (skills, hooks, templates) with latest. `settings.json` is smart-merged (custom hooks + permissions preserved); other managed files are NOT smart-merged — local edits are lost unless committed. Use only if no local skill/hook customizations:
68
+ > ```bash
69
+ > npx -y agentic-sdlc-wizard@latest init --force
70
+ > ```
71
+ >
72
+ > **C. Skip the CLI bump.** Keep stale CLI; this session's file updates apply but `npx ... check` keeps using old drift logic.
73
+ >
74
+ > Pick A, B, or C: `[A/B/C]` (default A)
112
75
 
113
- If A: prompt the user to run the one-liner in their shell, then re-invoke `/update-wizard`. If B: same, with the warning about non-settings overwrite. If C: log the choice and continue with in-session file updates only. Default (no response) → A.
76
+ If A: prompt the user to run the one-liner, then re-invoke `/update-wizard`. If B: same with the warning. If C: log the choice and continue.
114
77
 
115
- **`check-only` precedence:** if the user passed `check-only`, Step 1.5 runs in report-only mode — print the gap if found, but do NOT prompt and do NOT run `init --force`. The check-only contract is "tell me what's drifted, don't change anything," and that supersedes the CLI bump path.
78
+ **`check-only` precedence:** if the user passed `check-only`, Step 1.5 runs in report-only mode — print the gap if found, but do NOT prompt and do NOT run `init --force`. The check-only contract is "tell me what's drifted, don't change anything," and that supersedes the CLI bump path. **Graceful fallback** when CLI undetectable: skip the bump prompt, surface the unknown-state in the report, continue to Step 2.
116
79
 
117
- **Why this lives at Step 1.5, not later:** subsequent steps shell out to `npx agentic-sdlc-wizard check` (Step 4) and rely on the CLI's drift heuristics. If the CLI is stale, Step 4 reports based on the OLD definition of "managed files" and may miss new templates entirely. Detecting + surfacing CLI staleness up front lets the user choose whether to refresh first.
80
+ **Why Step 1.5, not later:** subsequent steps shell out to `npx agentic-sdlc-wizard check` (Step 4). If the CLI is stale, Step 4 reports based on the OLD definition of managed files and may miss new templates entirely.
118
81
 
119
82
  ### Step 2: Fetch Latest CHANGELOG
120
83
 
121
- Use WebFetch to fetch the CHANGELOG:
84
+ WebFetch:
122
85
  ```
123
86
  https://raw.githubusercontent.com/BaseInfinity/claude-sdlc-wizard/main/CHANGELOG.md
124
87
  ```
125
-
126
- Extract the latest version from the first `## [X.X.X]` line.
88
+ Extract latest version from the first `## [X.X.X]` line.
127
89
 
128
90
  ### Step 3: Compare Versions and Show What Changed
129
91
 
130
- Parse all CHANGELOG entries between the user's installed version and the latest. Present a clear summary:
92
+ Parse CHANGELOG entries between the user's installed version and latest. Present a clear summary:
131
93
 
132
94
  ```
133
- Installed: 1.24.0
134
- Latest: 1.47.0
95
+ Installed: 1.42.0
96
+ Latest: 1.48.0
135
97
 
136
98
  What changed:
137
- - [1.47.0] Codex review progress wrapper closes #259. New `scripts/codex-review-with-progress.sh` wraps `codex exec` with a heartbeat (every 10s by default) showing elapsed time + output file growth. Distinguishes "still thinking" from "crashed silently" during long xhigh reviews. Signal-safe: SIGTERM/INT/HUP cleanly kills the child codex within ~1s (uses interruptible `sleep & wait` pattern instead of plain `sleep`); preflight check on the binary so missing `codex` exits 127 with a clear error; loop rechecks liveness after sleep so a fast-exit codex doesn't print spurious heartbeats. 11 quality tests using a stub codex (no real API calls). Codex round 3 CERTIFIED 10/10.
138
- - [1.46.1] `npx check` surfaces dangling+enabled plugin state — closes #266. Consumer disabled the wizard plugin via directory rename without flipping `enabledPlugins[sdlc-wizard@sdlc-wizard-local]` in `~/.claude/settings.json`. CC's plugin loader tried to resolve the missing path and crashed UserPromptSubmit on every prompt for **3 days** before the consumer noticed. The wizard's `check` subcommand now cross-references `enabledPlugins` against DANGLING marketplace paths: when both hold (path missing AND plugin enabled), prints a loud `CRASH RISK` block with the exact remediation (flip the boolean to false OR run `/plugin uninstall`). 3 new tests, Codex round 1 CERTIFIED 10/10.
139
- - [1.46.0] PreCompact dry-run env vars closes #240. Smoke-testing PreCompact previously required cp'ing real `.reviews/handoff.json` and `.git/` aside, fabricating fake state, restoring — error-prone (consumer clobbered real handoff.json mid-test). Two new env vars: `SDLC_DRY_RUN_HANDOFF_STATUS=PENDING_RECHECK|CERTIFIED|...` simulates handoff status (overrides the real file read); `SDLC_DRY_RUN_GIT_STATE=rebase|merge|cherry-pick` simulates an in-flight git op (no real .git/ needed). Empty/unset → real-state checks (no behavior change). Unknown values (typos) → fall back to real check, NOT silent bypass — Codex round 1 caught the bypass risk and we fixed it with a DRY_RUN_GIT_HANDLED flag. 7 new test-hooks tests. Codex round 2 CERTIFIED 10/10.
140
- - [1.45.0] PreCompact path (c) — SHA-ancestry self-heal — closes #257. Solo-developer pattern: write fixes, commit them, run targeted Codex recheck, see CERTIFIED in `.reviews/latest-review.md`, ship the feature. Forgetting to bump `handoff.json status` from `PENDING_RECHECK` → `CERTIFIED` is realistic — the file is buried and the visible signals (commits + review file) already say "done". PreCompact hook now self-heals silently when: (a) handoff is `PENDING_*` with no `pr_number`, (b) every SHA cited in `fixes_applied[]` is reachable from HEAD via `git merge-base --is-ancestor`, AND (c) `.reviews/latest-review.md` contains CERTIFIED without `NOT CERTIFIED`. Bracket extraction is escape-aware (depth counter + JSON `\\\"` handling) so `]` inside string literals doesn't terminate the array early. UUIDs (8-4-4-4-12 hex) stripped before SHA extraction so ticket IDs in fixes_applied don't false-block the heal. 9 new tests, Codex round 3 CERTIFIED 10/10.
141
- - [1.44.1] Autocompact compound-misconfig detection — closes #207. Consumer reported autocompact firing at 12% context on a fresh opus[1m] session because they set BOTH `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30` AND `CLAUDE_CODE_AUTO_COMPACT_WINDOW=400000` (a natural misreading of the "or"-joined override cell). The two compound: 30% × 400K = 120K trigger ≈ 12% of 1M. Three-pronged fix: (a) wizard doc clarifies alternatives with a `> ⚠ Do NOT set both` callout that shows the compound math; (b) `instructions-loaded-check.sh` (InstructionsLoaded hook) detects when both env vars are set in `.claude/settings.json`, computes the effective trigger, and warns with the math; (c) shipped `skills/sdlc/SKILL.md` was still calling opus[1m] the "default" (stale post-#198) AND repeating the same ambiguous wording — both fixed. 4 new hook tests + 3 new doc-consistency tests + size-cap fixture extended. Codex round 2 CERTIFIED 9/10.
142
- - [1.44.0] Install-path & cache hygiene — closes #254, #239, #238 filed by consumer codeguesser after upgrading 1.32.0 → 1.42.1. (1) `cli/init.js` FILES list now ships `hooks/_find-sdlc-root.sh` the helper sourced by all 5 hooks was missing from npm install path, so every session emitted `_find-sdlc-root.sh: No such file or directory` + `dedupe_plugin_or_project: command not found` and the SDLC walk-up logic was silently dead. (2) `init --force` now invalidates `~/.cache/sdlc-wizard/latest-version` so post-upgrade hooks re-fetch fresh values from npm instead of serving the pre-upgrade cache for 24h (which produced reverse "1.42.1 → 1.41.1" nudges). (3) instructions-loaded-check.sh now uses semver-direction comparison via new `semver_lt` function: nudge only fires when installed < latest, equality is silent, reverse direction is silent. Cache sanity-check rejects poisoned values (cached "latest" < installed → force refetch). (4) When `npm view` fails AND cache empty, hook now surfaces a one-line warning instead of going silent. (5) Dual-channel install nudge gains an opt-in silence sentinel — set via `mkdir -p $SDLC_WIZARD_CACHE_DIR && touch $SDLC_WIZARD_CACHE_DIR/dual-channel-acknowledged` (printed inside the nudge itself for discoverability). 8 new tests across test-cli.sh + test-hooks.sh, Codex CERTIFIED 10/10 round 2.
143
- - [1.43.0] Token-spike anomaly detection — ROADMAP #220 closure. New `hooks/token-spike-check.sh` (SessionStart, opt-in via `.metrics/`) ingests CC transcript usage (`input_tokens` / `output_tokens` / `cache_creation_input_tokens` / `cache_read_input_tokens`) into `.metrics/token-history.jsonl`, then warns when the last session's `costly_tokens` (input + cache_creation + output, excluding the cheap cache_read tier) exceeds median + 2σ over a rolling baseline. Catches silent CC-side caching regressions (per Anthropic's 2026-04-23 post-mortem) before they surface on the invoice. Uses MAD-based spread for the median metric so a single baseline outlier doesn't mask the next spike. 14 quality tests in `tests/test-token-spike.sh` (incl. malicious-transcript privacy probe, flat-baseline floor, median-vs-mean contrast, concurrent-ingest mkdir lock).
144
- - [1.42.2] PreCompact self-heal documented — ROADMAP #209 closure. Added `pr_number` opt-in to all 3 handoff template schemas (skill Step 1; wizard Round 1 + cross-model section). Self-heal logic shipped earlier with #229 but was undocumented, leaving the dead-code path. New `test_handoff_template_documents_pr_number` enforces template/doc parity. Together with #229 (mtime auto-expire) closes the "stuck PENDING handoff blocks /compact forever" footgun from both directions.
145
- - [1.42.1] CI hygiene fix — skip Claude PR review on wizard self-PRs. 7 self-PRs (v1.39.0–v1.42.0) had shipped with red `review` job (API canary firing on dead credit balance). Treated as "expected" but red normalizes red. Workflow `if:` now skips review on `BaseInfinity/claude-sdlc-wizard` repo only; consumer projects unaffected. 7 quality tests, mutation-verified (== inversion fails).
146
- - [1.42.0] AGENTS.md interop detection — ROADMAP #205 phase (a). Setup wizard auto-scan now lists AGENTS.md (cross-tool agent-instructions standard, CC issue #6235); new Step 4.5 surfaces a 3-way decision (dual-maintain / merge / skip) when AGENTS.md is detected. Phase (b) write-fresh and phase (d) drift-test deferred. 7 quality tests.
147
- - [1.41.1] MCP-tool hooks audit — ROADMAP #218. Audited all 5 wizard hooks against CC 2.1.118's `type: "mcp_tool"` migration option; conclusion: all stay bash (portability to Codex/OpenCode siblings + exit-code gating semantics rule out MCP). Per-hook rationale documented under "Known CC Gotchas → MCP-tool hooks audit". 7 quality tests.
148
- - [1.41.0] Post-mortem 2026-04-23 lessons folded into wizard — ROADMAP #221. New "Known CC Gotchas" section documents extended-thinking + caching + idle-session failure mode. Recommended Effort section cites the post-mortem as third-party evidence ("don't rely on CC default — set effort yourself"). Brevity-cap audit clean, regression guard added. 7 quality tests.
149
- - [1.40.1] cleanupPeriodDays: 30 pinned in template — ROADMAP #225. CC 2.1.117 expanded `cleanupPeriodDays` to also cover `~/.claude/tasks/`. Aggressive defaults could prune in-progress TodoWrite checklists for paused long-running features. Wizard now ships a 30-day floor + documented gotcha. 7 quality tests.
150
- - [1.40.0] CLI version detection in /update-wizard — ROADMAP #232. New Step 1.5 detects locally installed `agentic-sdlc-wizard` CLI version (npm ls + npx cache inspection, both with semver-aware ordering), compares to `registry.npmjs.org/agentic-sdlc-wizard/latest`, and surfaces a 3-way upgrade choice BEFORE drift detection: A) refresh CLI cache only (default, safest), B) `init --force` re-init with explicit non-settings overwrite warning, C) skip. Closes the gap where in-session file updates landed but the user's stale npx cache kept running an old CLI. Mirrors `claude update` UX. 8 quality tests, mutation-verified.
151
- - [1.39.1] Step 7.7 hoist — dead-plugin cleanup now runs even when wizard versions match. Previously `/update-wizard` exited at "you're up to date" before reaching Step 7.7, so users on the latest wizard with a stale `~/.claude/settings.json` plugin registration were never offered cleanup. New `tests/test-update-skill-step-7-7.sh` (8 quality tests) guards the ordering.
152
- - [1.39.0] Community feature-discovery scanner — ROADMAP #207. `tests/e2e/scan-community.sh` extracts unknown `/slash-command` mentions from transcript text (Reddit / HN / Discord exports), dedupes against `tests/e2e/known-slash-commands.txt` allowlist, emits JSON digest of candidates with count + sample. Replaces the deleted CI scan-community job (per #231 Phase 3) with a maintainer-runnable offline scan. 14 quality tests.
153
- - [1.38.0] Mixed-mode tier (Sonnet 4.6 coder + Opus 4.7 reviewer) for simple repos — ROADMAP #233. New `cli/lib/repo-complexity.js` heuristic + `npx agentic-sdlc-wizard complexity .` CLI command. Setup Step 9.5 expanded from binary y/N to 3-way (no-pin / mixed / flagship). Cross-model review always stays at flagship regardless of coder pin. Reconciles with #198: mixed-mode is opt-in per-project; no-pin remains the default. Plus ROADMAP #224 prompt-hook-fires-once instrumentation (opt-in `SDLC_HOOK_FIRE_LOG`).
154
- - [1.37.1] Token-bloat fix: dedupe 2× SDLC BASELINE print when both project + plugin register the same hook (~300 tokens doubled per prompt). 5 hooks gain `dedupe_plugin_or_project()` helper. Codex 2-round 100/100.
155
- - [1.37.0] `monthly-research.yml` workflow deleted (ROADMAP #231 Phase 1) — 0 merged artifacts in 30d while burning $11-23/month; research happens inline now. `model-effort-check.sh` loud WARNING below xhigh (#217) — max preferred, xhigh floor; duplicate effort nudge in `instructions-loaded-check.sh` removed; single source of truth. Both changes Codex-certified.
156
- - [1.36.1] Repo renamed `agentic-ai-sdlc-wizard` → `claude-sdlc-wizard` (matches sibling pattern; npm package unchanged); `npm pkg fix` metadata cleanup; slug migration across docs/tests/configs
157
- - [1.36.0] CC 2.1.118 `/usage` canonical + aliases, Tier 2 dead-gate fix (#215), score-history max_score correctness (#211), setup-bun regression guard (#210), post-mortem learnings (#220-222), GPT-5.5 adoption plan (#223), MCP-tool hooks + #198 re-verify in backlog (#218/#219)
158
- - [1.35.0] PreCompact seam gate + self-heal (#208/#209), effort auto-bump on LOW/FAILED/CONFUSED (#195), wizard staleness nudge (#196), Codex CI-log audit pattern, ...
159
- - [1.34.0] API feature detection shepherd for Claude releases, Memory Audit Protocol with 7 verified lessons (+2 caught-and-retracted), /less-permission-prompts surfaced, ...
160
- - [1.33.0] opus[1m] as SDLC default, dual-channel install drift guardrails, model/effort session-start nudge, ...
161
- - [1.32.0] Opus 4.7 + xhigh support, model/effort upgrade detection, benchmark ceiling audit, ...
162
- - [1.31.0] Hook false-positive fix for non-SDLC dirs, ephemeral marketplace path warning, ...
163
- - [1.30.0] Firmware fixture, model A/B comparison workflow, CC degradation detection, ...
164
- - [1.29.0] Node 24 compliance, autocompact in settings.json, effectiveness scoreboard, ...
165
- - [1.28.0] Autocompact benchmarking methodology, canary fact mechanism, benchmark harness, ...
166
- - [1.27.0] Domain-adaptive testing diamond, 3 domain fixtures, 25 quality tests, ...
167
- - [1.26.0] Codex SDLC Adapter plan, claw-code/OmO/OmX research, CC feature discovery verified, ...
168
- - [1.25.0] Plugin format, 6 distribution channels (curl, Homebrew, gh, GitHub Releases), ...
169
- - [1.24.0] Hook if conditionals, autocompact tuning + 1M/200K guidance, tdd_red fix, ...
99
+ - [1.48.0] SKILL.md trimtoken bloat audit phase 2 follow-up
100
+ - [1.47.0] Codex review progress wrapper (#259)
101
+ - [1.46.1] npx check surfaces dangling+enabled plugin state (#266)
102
+ - [1.46.0] PreCompact dry-run env vars (#240)
103
+ - [1.45.0] PreCompact path (c) SHA-ancestry self-heal (#257)
104
+ - [1.44.1] Autocompact compound-misconfig detection (#207)
105
+ ... (full entries from fetched CHANGELOG)
170
106
  ```
171
107
 
172
- **If versions match:** Step 7.7 (global plugin-registration cleanup) is independent of wizard file versions — it must run even when the user is already up-to-date. The `check-only` flag still gates whether cleanup is *applied*:
108
+ Read the actual entries from the fetched CHANGELOG; don't paraphrase. The user wants to see exactly what shipped.
109
+
110
+ **If versions match:** Step 7.7 (global plugin-registration cleanup) is independent of wizard file versions — it must run even when the user is up-to-date. The `check-only` flag still gates whether cleanup is *applied*:
173
111
 
174
112
  - **Without `check-only`**: Run Step 7.7 in normal mode (detect, prompt, apply) before stopping. Then say "You're up to date! (version X.X.X)" and stop. Do not run Steps 4–10; only Step 7.7 fires on match.
175
- - **With `check-only`**: Run Step 7.7 in detection-only mode — report any dead plugin registrations found, but do NOT prompt the user and do NOT mutate `~/.claude/settings.json`. Then say "You're up to date! (version X.X.X)" and stop.
113
+ - **With `check-only`**: Run Step 7.7 in detection-only mode — report any dead plugin registrations, but do NOT prompt and do NOT mutate `~/.claude/settings.json`. Then say "You're up to date! (version X.X.X)" and stop.
176
114
 
177
- **If user passed `check-only` and versions don't match:** Stop after showing what changed. Do not apply anything (file updates, settings cleanup, version bumps).
115
+ **If user passed `check-only` and versions don't match:** Stop after showing what changed. Do not apply anything.
178
116
 
179
117
  ### Step 4: Run Drift Detection
180
118
 
181
- Run the CLI drift checker to see per-file status:
182
119
  ```bash
183
120
  npx agentic-sdlc-wizard check
184
121
  ```
185
-
186
- This reports each managed file as MATCH, CUSTOMIZED, MISSING, or DRIFT. Present the results.
122
+ Reports each managed file as MATCH, CUSTOMIZED, MISSING, or DRIFT.
187
123
 
188
124
  ### Step 5: Fetch Latest Wizard Doc
189
125
 
190
- Use WebFetch to fetch the latest wizard:
126
+ WebFetch:
191
127
  ```
192
128
  https://raw.githubusercontent.com/BaseInfinity/claude-sdlc-wizard/main/CLAUDE_CODE_SDLC_WIZARD.md
193
129
  ```
130
+ Source of truth for all templates, hooks, skills, step registry.
194
131
 
195
- This is the source of truth for all templates, hooks, skills, and step registry.
196
-
197
- ### Step 6: Present Per-File Update Plan
198
-
199
- For each managed file from the `sdlc-wizard check` output:
132
+ ### Step 6: Per-File Update Plan
200
133
 
201
134
  | Status | Action |
202
135
  |--------|--------|
203
136
  | MATCH | Skip — already current |
204
- | MISSING | Recommend install — show what the file does |
137
+ | MISSING | Recommend install — explain what the file does |
205
138
  | CUSTOMIZED | Show what changed in latest vs user's version. Ask: adopt, skip, or merge? |
206
139
  | DRIFT | Flag the issue (e.g., missing executable permission). Offer to fix |
207
140
 
208
- Read both the installed file and the latest template content. Present a human-readable summary of differences — not a raw diff, but "what was added/changed/removed and why."
209
-
210
- **If user passed `force-all`:** Skip per-file approval and apply all updates.
141
+ Read both the installed file and the latest template. Present a human-readable summary of differences — what was added/changed/removed and why, NOT a raw diff.
211
142
 
212
- ### Step 7: Handle settings.json Specially
143
+ **If user passed `force-all`:** skip per-file approval, apply all updates.
213
144
 
214
- NEVER overwrite settings.json. Instead:
145
+ ### Step 7: settings.json (Smart Merge Only)
215
146
 
216
- 1. Read the user's current settings.json
217
- 2. Compare against the latest template's hook definitions
218
- 3. Describe what hooks changed (added, updated, removed)
219
- 4. Offer to merge: update wizard hooks while preserving all custom hooks, permissions, and other settings
147
+ NEVER overwrite. Read user's current settings.json, compare to latest template's hook definitions, describe what changed (added/updated/removed), offer to merge: update wizard hooks while preserving all custom hooks, permissions, and other settings.
220
148
 
221
- The CLI's `init --force` already has smart merge logic for settings.json. If the manual merge gets complicated, suggest: `npx agentic-sdlc-wizard init --force` (it preserves custom hooks).
149
+ CLI's `init --force` already has smart-merge logic. If manual merge gets complicated, suggest: `npx agentic-sdlc-wizard init --force` (preserves custom hooks).
222
150
 
223
151
  ### Step 7.5: Model Pin Migration (Issue #198)
224
152
 
225
- Wizard versions 1.31.0–1.33.x unconditionally wrote `"model": "opus[1m]"` and `"env": { "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "30" }` to `.claude/settings.json`. Issue #198 flipped that to opt-in because a top-level `model` disables Claude Code's auto-mode for the session.
153
+ Wizard 1.31.0–1.33.x unconditionally wrote `"model": "opus[1m]"` and `"env": { "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "30" }` to `.claude/settings.json`. Issue #198 flipped that to opt-in because a top-level `model` disables Claude Code's auto-mode.
226
154
 
227
- If the user is upgrading from a pre-#198 version, check their `.claude/settings.json`:
155
+ Check user's `.claude/settings.json`:
228
156
 
229
- 1. **If `model` is `"opus[1m]"` and `env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` is `"30"`** — this is likely the old wizard-installed pair, not an intentional user choice. Ask:
230
-
231
- > Your `.claude/settings.json` pins `model: "opus[1m]"` with `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30`.
232
- > This pair was the SDLC wizard default in 1.31.0–1.33.x, but it disables Claude Code's auto-mode (see issue #198).
233
- >
234
- > - **Remove the pin** (recommended for most users) — keeps auto-mode enabled, lets Claude Code pick the model per turn.
235
- > - **Keep the pin** — you want guaranteed Opus 4.7 + 1M context, and you're OK giving up model auto-selection.
236
- >
157
+ 1. **`model: "opus[1m]"` AND `env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "30"`** — likely the old wizard-installed pair, not an intentional choice. Ask:
158
+ > Your `.claude/settings.json` pins `model: "opus[1m]"` with `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30`. This pair was the wizard default in 1.31.0–1.33.x, but it disables Claude Code's auto-mode (issue #198).
159
+ > - **Remove the pin** (recommended) keeps auto-mode enabled
160
+ > - **Keep the pin** guaranteed Opus 4.7 + 1M, OK with no auto-selection
237
161
  > Remove, keep, or decide later? `[r/k/l]`
238
162
 
239
- 2. **If only one of the two fields matches** (e.g. `model: "opus[1m]"` but custom autocompact, or vice versa) — treat as intentional customization. Do not prompt.
240
-
241
- 3. **If `model` is `"sonnet[1m]"` (mixed-mode tier, roadmap #233, v1.38.0+)**treat as user's explicit mixed-mode choice. Do not prompt; this is the supported mixed-mode pin. Mention in the upgrade summary: "Detected mixed-mode tier (Sonnet coder + flagship reviewer). Cross-model review still uses Opus / gpt-5.5 — see CLAUDE_CODE_SDLC_WIZARD.md → 'Mixed-Mode Tier'."
242
-
243
- 4. **If `model` is some other value** (e.g. `"sonnet"`, `"opus"`) — treat as user's explicit choice. Do not touch.
163
+ 2. **Only one of the two fields matches** — treat as intentional customization. Do not prompt.
164
+ 3. **`model: "sonnet[1m]"`** (mixed-mode tier, #233, v1.38.0+) — explicit user choice. Mention in summary: "Detected mixed-mode tier (Sonnet coder + flagship reviewer). Cross-model review still uses Opus / gpt-5.5."
165
+ 4. **Other `model` value** (`sonnet`, `opus`) — explicit user choice. Do not touch.
166
+ 5. **Neither field set** — already on new default.
244
167
 
245
- 5. **If neither field is set** user is already on the new default. No action.
246
-
247
- When removing: edit the file in place, drop the `model` key (and the `env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` key if nothing else is in `env`, otherwise leave `env` alone). Never touch other keys the user added.
168
+ When removing: drop `model` (and `env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` if `env` becomes empty). Never touch other keys.
248
169
 
249
170
  ### Step 7.6: `allowedTools` → `permissions.allow` Migration (Issue #197)
250
171
 
251
- Wizard versions before #197 guided users to write a top-level `allowedTools` array in `.claude/settings.json`. Claude Code silently disables its auto-mode classifier when that key is present, even with `defaultMode: "auto"` set globally.
252
-
253
- If the user's `.claude/settings.json` has a top-level `allowedTools` array, offer to migrate:
172
+ Pre-#197 wizard guided users to write a top-level `allowedTools` array. Claude Code silently disables auto-mode when that key is present, even with `defaultMode: "auto"`.
254
173
 
255
- 1. **If only `allowedTools` is present** (no `permissions.allow`) ask:
174
+ If user's `.claude/settings.json` has top-level `allowedTools`, offer migrate:
256
175
 
257
- > Your `.claude/settings.json` has a top-level `allowedTools` array. This silently disables Claude Code auto-mode (see issue #197). The supported successor is `permissions.allow`, which accepts the same patterns but doesn't trip the auto-mode gate.
258
- >
259
- > - **Migrate** (recommended): move all entries into `permissions.allow`, remove the old `allowedTools`.
260
- > - **Keep** — you have a specific reason to use the legacy key.
261
- > - **Later** — don't touch it now.
262
- >
176
+ 1. **Only `allowedTools`** (no `permissions.allow`) ask:
177
+ > Your `.claude/settings.json` has top-level `allowedTools` (silently disables auto-mode, issue #197). Successor: `permissions.allow`.
178
+ > - **Migrate** (recommended): move all entries into `permissions.allow`, remove the legacy key
179
+ > - **Keep** — specific reason for legacy key
180
+ > - **Later** — don't touch now
263
181
  > `[m/k/l]`
264
182
 
265
- 2. **If both `allowedTools` and `permissions.allow` are present** — flag it: the two lists may have diverged. Show both arrays to the user. On migrate, append every entry from `allowedTools` to the end of `permissions.allow` (preserving order within each list), then drop the legacy `allowedTools` key. **Do NOT dedup.** If the same string appears in both lists, it stays in both positions Claude Code treats duplicate entries as a no-op, but dedup would silently remove user data that the user might have intended. If the user explicitly asks to dedup, do that as a separate follow-up edit.
183
+ 2. **Both `allowedTools` AND `permissions.allow` present** — flag: lists may have diverged. Show both arrays. On migrate, **append every entry from `allowedTools` to the end of `permissions.allow`** byte-for-byte (preserve order within each list), then drop `allowedTools`. **Do NOT dedup.** Same string in both lists stays in both — CC treats duplicates as no-op, but dedup would silently remove user data the user might have intended. If user explicitly asks to dedup, that's a separate follow-up edit.
266
184
 
267
- 3. **If only `permissions.allow` is present** user is already on the new shape. No action.
185
+ 3. **Only `permissions.allow`** — already on new shape.
186
+ 4. **Neither** — no action.
268
187
 
269
- 4. **If neither is present** no action.
270
-
271
- When migrating: preserve every entry byte-for-byte; only the container key changes. Do not reorder, dedup, or expand wildcards. Other top-level keys (hooks, env, model, custom user fields) are never touched.
188
+ Preserve every entry byte-for-byte; only the container key changes. Do not reorder, dedup, or expand wildcards. Other top-level keys never touched.
272
189
 
273
190
  ### Step 7.7: Dead Plugin Registration Cleanup (Global Settings)
274
191
 
275
- Wizard installs sometimes leave dead plugin registrations in the user's **global** `~/.claude/settings.json` after the underlying plugin directory is renamed, disabled, or removed. Symptom: every Claude Code session emits `UserPromptSubmit hook error: Failed to run: Plugin directory does not exist: <path> ... run /plugin to reinstall`. The error is harmless but bleeds into every prompt across every project until cleaned up.
192
+ Wizard installs sometimes leave dead plugin registrations in **global** `~/.claude/settings.json` after the underlying plugin directory is renamed/disabled/removed. Symptom: every CC session emits `UserPromptSubmit hook error: Failed to run: Plugin directory does not exist: <path> ... run /plugin to reinstall`. Harmless but bleeds into every prompt across every project until cleaned up.
276
193
 
277
- This step is **global-settings-only** (`~/.claude/settings.json`, not the project's `.claude/settings.json`). The update skill normally avoids global settings; this is the one exception, and only when the plugin marketplace name matches an exact wizard-owned identifier.
194
+ This step is **global-settings-only** (`~/.claude/settings.json`, not project's). Update normally avoids global; this is the one exception, only when the marketplace name matches an exact wizard-owned identifier.
278
195
 
279
- **Wizard-owned marketplace allowlist** (exact match, no wildcard — wildcards risk eating third-party plugins like `sdlc-wizard-tools` if such a thing ever ships):
196
+ **Wizard-owned marketplace allowlist** (exact match — wildcards risk eating third-party `sdlc-wizard-tools` if such a thing ships):
280
197
 
281
198
  - `sdlc-wizard-local`
282
199
  - `sdlc-wizard-wrap`
283
200
 
284
- If `cli/init.js` later registers additional wizard marketplace names, append them to this list verbatim.
201
+ If `cli/init.js` later adds wizard marketplace names, append verbatim.
285
202
 
286
203
  **Detection:**
287
204
 
288
- 1. Read `~/.claude/settings.json` and parse as JSON.
289
- 2. For each `extraKnownMarketplaces[key]` where `key` is in the allowlist above:
290
- - Verify `entry.source.source === "directory"` AND `typeof entry.source.path === "string"`. If either guard fails, skip not the shape the wizard installs (matches the type-check at `cli/init.js`).
291
- - Resolve the `source.path` (expand `~` if literal). If the resolved path **does not exist** on disk, mark the marketplace **dead**.
205
+ 1. Read `~/.claude/settings.json`, parse as JSON.
206
+ 2. For each `extraKnownMarketplaces[key]` where `key` is in the allowlist:
207
+ - Verify `entry.source.source === "directory"` AND `typeof entry.source.path === "string"`. Either guard fails skip (not the wizard's shape).
208
+ - Resolve `source.path` (expand `~`). If the resolved path **does not exist**, mark **dead**.
292
209
  3. For every dead marketplace `<name>`, look for `enabledPlugins["sdlc-wizard@<name>"]` — also flag for removal.
293
- 4. Repeat for **all** allowlist entries; collect the full set of dead `(marketplace, enabledPlugins)` pairs before prompting. Multiple dead registrations are common (e.g. both `sdlc-wizard-local` and `sdlc-wizard-wrap` if the user reinstalled twice).
210
+ 4. Repeat for **all** allowlist entries; collect the full set of dead pairs before prompting (multiple are common).
294
211
 
295
- **Cleanup (always ask first, all-or-nothing per user response):**
212
+ **Cleanup (always ask, all-or-nothing per response):**
296
213
 
297
214
  > Your `~/.claude/settings.json` references wizard plugin marketplaces that don't exist on disk:
298
215
  >
299
216
  > - `extraKnownMarketplaces.sdlc-wizard-local.source.path` → `<resolved-path>` (missing)
300
217
  > - `enabledPlugins["sdlc-wizard@sdlc-wizard-local"]` is `true`
301
- > - (list all dead pairs from detection)
218
+ > - (list all dead pairs)
302
219
  >
303
- > This causes `Plugin directory does not exist` errors on every prompt in every Claude Code session until cleaned up.
220
+ > Causes `Plugin directory does not exist` on every prompt in every CC session.
304
221
  >
305
- > Drop the listed entries from `~/.claude/settings.json`? `[y/N]`
222
+ > Drop these entries from `~/.claude/settings.json`? `[y/N]`
306
223
 
307
- If the user says yes:
308
- 1. **Back up with timestamp**: `cp ~/.claude/settings.json ~/.claude/settings.json.bak.$(date +%Y%m%dT%H%M%S)` so two cleanups on the same day don't overwrite each other's backups.
309
- 2. **Build a single `jq` filter** that drops every dead marketplace and every dead `enabledPlugins` key in one pass: `jq 'del(.enabledPlugins["sdlc-wizard@sdlc-wizard-local"]) | del(.extraKnownMarketplaces["sdlc-wizard-local"]) | del(.enabledPlugins["sdlc-wizard@sdlc-wizard-wrap"]) | del(.extraKnownMarketplaces["sdlc-wizard-wrap"])'` (include only the keys actually marked dead in detection).
310
- 3. Write to a temp file, validate with `jq empty` (round-trip parse), only then replace `~/.claude/settings.json` with `mv`. If validation fails, restore from the backup.
311
- 4. **Formatting note**: `jq` rewrites the whole file and normalizes formatting. The wizard does NOT preserve comments, trailing commas, or other JSONC features — Claude Code's `settings.json` is strict JSON, so this is safe today, but say so to the user. If they care about preserving the exact diff, give them the manual `del()` filter and let them decide whether to apply it.
224
+ If yes:
225
+ 1. **Backup with timestamp**: `cp ~/.claude/settings.json ~/.claude/settings.json.bak.$(date +%Y%m%dT%H%M%S)` (two cleanups same day don't overwrite each other).
226
+ 2. **Single `jq` filter** dropping every dead marketplace + every dead `enabledPlugins` key in one pass: `jq 'del(.enabledPlugins["sdlc-wizard@sdlc-wizard-local"]) | del(.extraKnownMarketplaces["sdlc-wizard-local"]) | del(.enabledPlugins["sdlc-wizard@sdlc-wizard-wrap"]) | del(.extraKnownMarketplaces["sdlc-wizard-wrap"])'` include only keys actually marked dead.
227
+ 3. Write to a temp file, validate with `jq empty` (round-trip parse), then `mv`. Validation fails restore from backup.
228
+ 4. **Formatting note**: `jq` rewrites the whole file. Wizard does NOT preserve comments/trailing commas (CC's settings.json is strict JSON, so safe today). Tell the user.
312
229
 
313
- If the user says no: skip silently. Some users have a recovery plan (re-enable the renamed dir, reinstall, etc.).
230
+ If no: skip silently. Some users have a recovery plan (re-enable, reinstall).
314
231
 
315
- **Idempotency:** Re-running Step 7.7 after a successful cleanup must be a no-op. Detection only flags marketplaces whose `source.path` is missing AND whose name is in the allowlist; both must be true, so a clean settings.json reports zero dead pairs.
232
+ **Idempotency:** rerunning Step 7.7 after a clean must be a no-op. Only marketplaces with allowlist match AND missing path qualify.
316
233
 
317
- **Scope guard:** only touch entries whose marketplace name matches the exact allowlist. Third-party plugin registrations (`legal@knowledge-work-plugins`, `claude-md-management@claude-plugins-official`, etc.) and unrelated `sdlc`-prefixed marketplaces (e.g. `danielscholl/claude-sdlc`) are never the wizard's business. Path-existence alone never qualifies a marketplace for cleanup — only allowlist + missing-path together do.
234
+ **Scope guard:** only entries whose marketplace name matches the exact allowlist. Third-party plugin registrations (`legal@knowledge-work-plugins`, etc.) and unrelated `sdlc`-prefixed marketplaces (e.g. `danielscholl/claude-sdlc`) are never the wizard's business.
318
235
 
319
- **Why this lives in the update skill, not setup:** setup runs once at install time, when the plugin paths are valid by definition. Dead registrations only appear later, when something disables/renames/deletes the plugin directory. Update is the natural seam to detect drift and offer cleanup.
236
+ **Why update, not setup:** setup runs once at install; plugin paths are valid by definition. Dead registrations only appear later, when something disables/renames/deletes the plugin directory. Update is the natural seam.
320
237
 
321
- **Runs regardless of version match:** Step 7.7 is global-settings hygiene, not file-update logic. It must run even when the wizard version on disk matches npm latest (per Step 3's match-branch instruction). A user can be on the latest wizard and still have a stale plugin registration from a previous install; gating Step 7.7 on version mismatch would silently leave that error firing on every prompt forever. If a future edit to Step 3 changes the match-branch flow, it must continue to invoke Step 7.7 before stopping.
238
+ **Runs regardless of version match:** Step 7.7 is global-settings hygiene, not file-update logic. Must run even when wizard version matches latest (per Step 3 match-branch). Gating Step 7.7 on version mismatch would silently leave the error firing forever.
322
239
 
323
- **`check-only` precedence:** If the user passed `check-only` (whether versions match or not), Step 7.7 runs in detection-only mode: report dead plugin registrations if found, do NOT prompt the user, do NOT execute the jq cleanup, do NOT touch `~/.claude/settings.json`. The check-only contract takes precedence over the cleanup contract — a `check-only` invocation must never mutate state.
240
+ **`check-only` precedence:** if `check-only` is set (whether versions match or not), Step 7.7 runs in detection-only mode: report dead registrations, do NOT prompt, do NOT execute `jq`, do NOT touch `~/.claude/settings.json`. Check-only must never mutate state.
324
241
 
325
242
  ### Step 8: Apply Selected Changes
326
243
 
327
- For each file the user approved:
328
- - Use the Edit tool to update the file content
329
- - For complete replacements (MISSING files), use Write
330
- - For settings.json, apply the merge from Step 7
244
+ For each approved file: Edit (existing) or Write (MISSING). For settings.json, apply the merge from Step 7.
331
245
 
332
246
  ### Step 9: Bump Version Metadata
333
247
 
334
- Update the version in `SDLC.md`:
248
+ Update `SDLC.md`:
335
249
  ```
336
250
  <!-- SDLC Wizard Version: X.X.X -->
337
- ```
338
- Set it to the latest version.
339
-
340
- Also update the completed steps if new steps were applied:
341
- ```
342
251
  <!-- Completed Steps: step-0.1, step-0.2, ..., step-update-wizard -->
343
252
  ```
253
+ Set to latest version. Update completed steps if new ones applied.
344
254
 
345
255
  ### Step 10: Verify
346
256
 
347
- Run drift detection again:
348
257
  ```bash
349
258
  npx agentic-sdlc-wizard check
350
259
  ```
351
-
352
- Report final status. All updated files should show MATCH. Files the user chose to skip will still show CUSTOMIZED — that's fine, it's their choice.
260
+ All updated files should show MATCH. User-skipped files still show CUSTOMIZED — that's fine.
353
261
 
354
262
  ## Rules
355
263
 
356
- 1. **NEVER modify CLAUDE.md.** It is fully custom to the user's project. The wizard never touches it.
357
- 2. **NEVER auto-apply without showing what will change first** (unless `force-all` was passed).
358
- 3. **Offline fallback:** If WebFetch fails (network unavailable), tell the user: "Cannot reach GitHub. Run `npx agentic-sdlc-wizard init --force` to update from your locally installed CLI version instead."
359
- 4. **First-time users:** If SDLC.md doesn't exist or has no version metadata, suggest `/setup-wizard` instead of `/update-wizard`.
360
- 5. **Respect customizations.** When a file is CUSTOMIZED, the user made intentional changes. Show what's different and let them decide — don't pressure them to adopt the latest.
361
- 6. **Reference the wizard doc** for full protocol details (step registry, URLs, version tracking) rather than hardcoding values in this skill.
264
+ 1. **NEVER modify CLAUDE.md.** Fully custom to user's project. Wizard never touches it.
265
+ 2. **NEVER auto-apply without showing what will change first** (unless `force-all`).
266
+ 3. **Offline fallback:** WebFetch fails tell user "Cannot reach GitHub. Run `npx agentic-sdlc-wizard init --force` to update from your locally installed CLI."
267
+ 4. **First-time users:** SDLC.md missing or no version metadata suggest `/setup-wizard`.
268
+ 5. **Respect customizations.** CUSTOMIZED files are intentional show what's different, let them decide. Don't pressure.
269
+ 6. **Reference the wizard doc** for full protocol details (step registry, URLs, version tracking) rather than hardcoding.