agentic-sdlc-wizard 1.46.1 → 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,350 +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.46.1
95
+ Installed: 1.42.0
96
+ Latest: 1.48.0
135
97
 
136
98
  What changed:
137
- - [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.
138
- - [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.
139
- - [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.
140
- - [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.
141
- - [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.
142
- - [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).
143
- - [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.
144
- - [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).
145
- - [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.
146
- - [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.
147
- - [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.
148
- - [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.
149
- - [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.
150
- - [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.
151
- - [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.
152
- - [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`).
153
- - [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.
154
- - [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.
155
- - [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
156
- - [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)
157
- - [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, ...
158
- - [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, ...
159
- - [1.33.0] opus[1m] as SDLC default, dual-channel install drift guardrails, model/effort session-start nudge, ...
160
- - [1.32.0] Opus 4.7 + xhigh support, model/effort upgrade detection, benchmark ceiling audit, ...
161
- - [1.31.0] Hook false-positive fix for non-SDLC dirs, ephemeral marketplace path warning, ...
162
- - [1.30.0] Firmware fixture, model A/B comparison workflow, CC degradation detection, ...
163
- - [1.29.0] Node 24 compliance, autocompact in settings.json, effectiveness scoreboard, ...
164
- - [1.28.0] Autocompact benchmarking methodology, canary fact mechanism, benchmark harness, ...
165
- - [1.27.0] Domain-adaptive testing diamond, 3 domain fixtures, 25 quality tests, ...
166
- - [1.26.0] Codex SDLC Adapter plan, claw-code/OmO/OmX research, CC feature discovery verified, ...
167
- - [1.25.0] Plugin format, 6 distribution channels (curl, Homebrew, gh, GitHub Releases), ...
168
- - [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)
169
106
  ```
170
107
 
171
- **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*:
172
111
 
173
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.
174
- - **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.
175
114
 
176
- **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.
177
116
 
178
117
  ### Step 4: Run Drift Detection
179
118
 
180
- Run the CLI drift checker to see per-file status:
181
119
  ```bash
182
120
  npx agentic-sdlc-wizard check
183
121
  ```
184
-
185
- 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.
186
123
 
187
124
  ### Step 5: Fetch Latest Wizard Doc
188
125
 
189
- Use WebFetch to fetch the latest wizard:
126
+ WebFetch:
190
127
  ```
191
128
  https://raw.githubusercontent.com/BaseInfinity/claude-sdlc-wizard/main/CLAUDE_CODE_SDLC_WIZARD.md
192
129
  ```
130
+ Source of truth for all templates, hooks, skills, step registry.
193
131
 
194
- This is the source of truth for all templates, hooks, skills, and step registry.
195
-
196
- ### Step 6: Present Per-File Update Plan
197
-
198
- For each managed file from the `sdlc-wizard check` output:
132
+ ### Step 6: Per-File Update Plan
199
133
 
200
134
  | Status | Action |
201
135
  |--------|--------|
202
136
  | MATCH | Skip — already current |
203
- | MISSING | Recommend install — show what the file does |
137
+ | MISSING | Recommend install — explain what the file does |
204
138
  | CUSTOMIZED | Show what changed in latest vs user's version. Ask: adopt, skip, or merge? |
205
139
  | DRIFT | Flag the issue (e.g., missing executable permission). Offer to fix |
206
140
 
207
- 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."
208
-
209
- **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.
210
142
 
211
- ### Step 7: Handle settings.json Specially
143
+ **If user passed `force-all`:** skip per-file approval, apply all updates.
212
144
 
213
- NEVER overwrite settings.json. Instead:
145
+ ### Step 7: settings.json (Smart Merge Only)
214
146
 
215
- 1. Read the user's current settings.json
216
- 2. Compare against the latest template's hook definitions
217
- 3. Describe what hooks changed (added, updated, removed)
218
- 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.
219
148
 
220
- 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).
221
150
 
222
151
  ### Step 7.5: Model Pin Migration (Issue #198)
223
152
 
224
- 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.
225
154
 
226
- If the user is upgrading from a pre-#198 version, check their `.claude/settings.json`:
155
+ Check user's `.claude/settings.json`:
227
156
 
228
- 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:
229
-
230
- > Your `.claude/settings.json` pins `model: "opus[1m]"` with `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30`.
231
- > 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).
232
- >
233
- > - **Remove the pin** (recommended for most users) — keeps auto-mode enabled, lets Claude Code pick the model per turn.
234
- > - **Keep the pin** — you want guaranteed Opus 4.7 + 1M context, and you're OK giving up model auto-selection.
235
- >
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
236
161
  > Remove, keep, or decide later? `[r/k/l]`
237
162
 
238
- 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.
239
-
240
- 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'."
241
-
242
- 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.
243
167
 
244
- 5. **If neither field is set** user is already on the new default. No action.
245
-
246
- 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.
247
169
 
248
170
  ### Step 7.6: `allowedTools` → `permissions.allow` Migration (Issue #197)
249
171
 
250
- 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.
251
-
252
- 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"`.
253
173
 
254
- 1. **If only `allowedTools` is present** (no `permissions.allow`) ask:
174
+ If user's `.claude/settings.json` has top-level `allowedTools`, offer migrate:
255
175
 
256
- > 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.
257
- >
258
- > - **Migrate** (recommended): move all entries into `permissions.allow`, remove the old `allowedTools`.
259
- > - **Keep** — you have a specific reason to use the legacy key.
260
- > - **Later** — don't touch it now.
261
- >
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
262
181
  > `[m/k/l]`
263
182
 
264
- 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.
265
184
 
266
- 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.
267
187
 
268
- 4. **If neither is present** no action.
269
-
270
- 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.
271
189
 
272
190
  ### Step 7.7: Dead Plugin Registration Cleanup (Global Settings)
273
191
 
274
- 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.
275
193
 
276
- 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.
277
195
 
278
- **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):
279
197
 
280
198
  - `sdlc-wizard-local`
281
199
  - `sdlc-wizard-wrap`
282
200
 
283
- 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.
284
202
 
285
203
  **Detection:**
286
204
 
287
- 1. Read `~/.claude/settings.json` and parse as JSON.
288
- 2. For each `extraKnownMarketplaces[key]` where `key` is in the allowlist above:
289
- - 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`).
290
- - 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**.
291
209
  3. For every dead marketplace `<name>`, look for `enabledPlugins["sdlc-wizard@<name>"]` — also flag for removal.
292
- 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).
293
211
 
294
- **Cleanup (always ask first, all-or-nothing per user response):**
212
+ **Cleanup (always ask, all-or-nothing per response):**
295
213
 
296
214
  > Your `~/.claude/settings.json` references wizard plugin marketplaces that don't exist on disk:
297
215
  >
298
216
  > - `extraKnownMarketplaces.sdlc-wizard-local.source.path` → `<resolved-path>` (missing)
299
217
  > - `enabledPlugins["sdlc-wizard@sdlc-wizard-local"]` is `true`
300
- > - (list all dead pairs from detection)
218
+ > - (list all dead pairs)
301
219
  >
302
- > 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.
303
221
  >
304
- > Drop the listed entries from `~/.claude/settings.json`? `[y/N]`
222
+ > Drop these entries from `~/.claude/settings.json`? `[y/N]`
305
223
 
306
- If the user says yes:
307
- 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.
308
- 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).
309
- 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.
310
- 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.
311
229
 
312
- 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).
313
231
 
314
- **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.
315
233
 
316
- **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.
317
235
 
318
- **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.
319
237
 
320
- **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.
321
239
 
322
- **`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.
323
241
 
324
242
  ### Step 8: Apply Selected Changes
325
243
 
326
- For each file the user approved:
327
- - Use the Edit tool to update the file content
328
- - For complete replacements (MISSING files), use Write
329
- - 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.
330
245
 
331
246
  ### Step 9: Bump Version Metadata
332
247
 
333
- Update the version in `SDLC.md`:
248
+ Update `SDLC.md`:
334
249
  ```
335
250
  <!-- SDLC Wizard Version: X.X.X -->
336
- ```
337
- Set it to the latest version.
338
-
339
- Also update the completed steps if new steps were applied:
340
- ```
341
251
  <!-- Completed Steps: step-0.1, step-0.2, ..., step-update-wizard -->
342
252
  ```
253
+ Set to latest version. Update completed steps if new ones applied.
343
254
 
344
255
  ### Step 10: Verify
345
256
 
346
- Run drift detection again:
347
257
  ```bash
348
258
  npx agentic-sdlc-wizard check
349
259
  ```
350
-
351
- 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.
352
261
 
353
262
  ## Rules
354
263
 
355
- 1. **NEVER modify CLAUDE.md.** It is fully custom to the user's project. The wizard never touches it.
356
- 2. **NEVER auto-apply without showing what will change first** (unless `force-all` was passed).
357
- 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."
358
- 4. **First-time users:** If SDLC.md doesn't exist or has no version metadata, suggest `/setup-wizard` instead of `/update-wizard`.
359
- 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.
360
- 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.