agentic-sdlc-wizard 1.83.0 → 1.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -142,11 +142,11 @@ codex exec -c 'model_reasoning_effort="xhigh"' -s danger-full-access \
142
142
 
143
143
  The wizard ships a **default recommendation**, not a mandate. You can swap to any Claude model — newer, older, or sibling tier — at any time. `/model` per session, or pin in `.claude/settings.json`.
144
144
 
145
- **Default: Opus 4.6 at max effort** (`[f] Flagship` in the setup wizard). This is the wizard's recommendation as of v1.80.0 a stronger statement than "this might work." Here's why.
145
+ **Default: Sonnet 5 at `high` effort, escalating to `xhigh`** (Setup A in `AI_SETUP_LANES.md`). Sonnet 5 (launched 2026-06-30) beats Opus 4.6 on every coding benchmark (SWE-bench Verified 85.2% vs 80.8%, Terminal-Bench 2.1 80.4% vs 65.4%) while using ~5x less Max quota per turn. Opus 4.6 remains available as **Setup B — Stability** for proven-consistency workflows; here's why it's no longer the default.
146
146
 
147
- ### Why Opus 4.6 max, not Anthropic's latest
147
+ ### Why Opus 4.6 was the flagship, and why that changed
148
148
 
149
- Two weeks of in-the-wild data after Opus 4.8's launch (2026-05-28) showed a clear pattern:
149
+ Two weeks of in-the-wild data after Opus 4.8's launch (2026-05-28) showed a clear pattern that first made Opus 4.6 the wizard's flagship over Anthropic's own "latest" model:
150
150
 
151
151
  - **[Andon Labs Vending-Bench](https://andonlabs.com/blog/opus-4-8-vending-bench)** — 4.8 finished last vs 4.7 and GPT-5.5; documented "Max reasoning is not the best reasoning effort"; falls for scam suppliers 30× more frequently
152
152
  - **[AI Weekly: 900K cache tokens per turn](https://aiweekly.co/alerts/claude-opus-48-thinking-burns-900k-tokens-per-turn)** — 40-60× jump vs 4.7 at HIGH effort. Burns Max 5-hour limits 2-3× faster
@@ -156,51 +156,41 @@ Two weeks of in-the-wild data after Opus 4.8's launch (2026-05-28) showed a clea
156
156
  - **[BSWEN effort decision guide](https://docs.bswen.com/blog/2026-04-19-claude-code-effort-level-decision-guide/)** — "Max on Opus causes overthinking on routine stuff. xHigh is the sweet spot for autonomous work"
157
157
  - **r/Claudeopus field reports** — one maintainer's literal A/B: "12 hours with 4.8 zero deliverables; plugged in 4.6, spec written + 133 tests green in one session." Top comment: "4.6 had the best overall balance at max"
158
158
 
159
- Six independent sources converging on the same conclusion: **4.6 is the only Opus where `max` effort tolerates without overthinking, and 4.7/4.8's "improvements" come with structural token-burn tradeoffs.** When you're running SDLC discipline workflows that span hours and tens of thousands of tokens, reliability beats benchmarks.
159
+ That research still stands it's why **Opus 4.6 remains Setup B (Stability)** rather than being dropped entirely, and why the wizard escalates to Opus **4.8** (not a blanket "latest") only when Sonnet 5 gets stuck. But Sonnet 5's June 30 launch changed the calculus for the *default*: it beats Opus 4.6 on every benchmark above at a fraction of the quota cost, so it's no longer a tradeoff between "reliable but weaker" and "strong but overthinks" — Sonnet 5 doesn't have Opus 4.8's overthinking problem in the first place.
160
160
 
161
- 4.6 is Anthropic-supported until **≥ Feb 5, 2027** per the [official deprecation page](https://platform.claude.com/docs/en/about-claude/model-deprecations) 8 months minimum runway. The Feb-Apr 2026 quality bugs are fully fixed per Anthropic's [April 23 postmortem](https://www.anthropic.com/engineering/april-23-postmortem) the wizard picks up the post-fix model, not the regression window.
162
-
163
- ### What 4.6 max gives up
164
-
165
- - 4.8's SWE-Bench Pro (69.2% vs 4.7's 64.3%) and Terminal-Bench 2.1 (74.6% vs 66.1%) gains
166
- - Dynamic-workflows and parallel-subagent-swarm features introduced in 4.8
167
- - Anthropic's "latest = best" convention. The wizard is explicitly betting against that convention here.
168
-
169
- ### Latest tier — Opus 4.8 (opt-in)
170
-
171
- If you want the newest benchmarks and you're comfortable with the token-burn tradeoff, pick `[l] Latest` in the setup wizard. Always `max` effort on all Claude models (#395). The [`Latest tier — Opus 4.8`](CLAUDE_CODE_SDLC_WIZARD.md) section has the full opt-in instructions.
161
+ 4.6 remains Anthropic-supported until **≥ Feb 5, 2027** per the [official deprecation page](https://platform.claude.com/docs/en/about-claude/model-deprecations), so Setup B stays a safe long-term choice if you've tuned a workflow to its behavior specifically.
172
162
 
173
163
  ### Switch any time
174
164
 
175
165
  ```bash
176
- /model claude-opus-4-6 # wizard's recommended flagship (default in v1.80.0+)
177
- /model opusplan # Opus plans (Shift+Tab), Sonnet executes both Max-bundled
178
- /model claude-opus-4-8 # Anthropic's latest, opt-in via Latest tier
166
+ /model sonnet # wizard's recommended default (Setup A) — native 1M context
167
+ /model claude-opus-4-6 # Stability lane (Setup B) — proven consistency
168
+ /model opusplan # Opus plans (Shift+Tab), Sonnet executes — both Max-bundled (Setup C)
169
+ /model claude-opus-4-8 # escalation only — don't run as daily driver, burns quota 2-3x faster
179
170
  ```
180
171
 
181
172
  Or pin in `.claude/settings.json`:
182
173
 
183
174
  ```json
184
- { "model": "claude-opus-4-6", "env": { "CLAUDE_CODE_EFFORT_LEVEL": "max" } }
175
+ { "model": "sonnet", "advisorModel": "fable", "effortLevel": "xhigh" }
185
176
  ```
186
177
 
187
- Or sweep all your projects by setting `ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6` in `~/.claude/settings.json`.
188
-
189
- Effort: **always `max`** on all Claude models. Persist it: set `CLAUDE_CODE_EFFORT_LEVEL=max` in your settings env block (CC docs: `effortLevel: "max"` in settings.json is session-only and silently ignored). OpenAI/Codex: `xhigh` (their highest).
178
+ **Effort is model-aware, not blanket `max`.** Sonnet 5: `high` default, `/effort xhigh` for hard tasks. Opus 4.8: `xhigh` (its own `max` overthinks). Opus 4.6: `max` (its one `xhigh`-less sweet spot). Set per-session with `/effort`, not a shell-rc or settings env var — persisting effort that way silently overrides a later `/effort` change after you switch models (see `SDLC.md`'s Lessons Learned for a real incident this caused). OpenAI/Codex reviewer: `xhigh` (its highest).
190
179
 
191
- ### Three Setup Lanes
180
+ ### Four Setup Lanes
192
181
 
193
- The wizard defines three AI coding setups in [`AI_SETUP_LANES.md`](AI_SETUP_LANES.md):
182
+ The wizard defines four AI coding setups in [`AI_SETUP_LANES.md`](AI_SETUP_LANES.md):
194
183
 
195
184
  | Lane | Advisor | Driver | Reviewer | Escalation |
196
185
  |------|---------|--------|----------|------------|
197
- | **A — Premium** | Fable 5 (advisorModel) | Opus 4.6 max | GPT-5.5 xhigh | + Fable review (security/release/architecture) |
198
- | **B — Saver** | Opus 4.6 (advisorModel) | Sonnet | GPT-5.5 xhigh | None |
199
- | **C — Lite** | None | Sonnet | None | None |
186
+ | **A — Recommended** | Fable 5 (advisorModel) | Sonnet 5, `high`→`xhigh` | GPT-5.5 xhigh | Opus 4.8 xhigh or Fable review |
187
+ | **B — Stability** | Fable 5 (advisorModel) | Opus 4.6 max | GPT-5.5 xhigh | None |
188
+ | **C — Saver** | Fable 5 or Opus 4.8 (advisorModel) | Opus 4.8 plans, Sonnet 5 executes | GPT-5.5 xhigh | None |
189
+ | **D — Lite** | None | Sonnet 5, `medium` | None | None |
200
190
 
201
- Setup C's whole point: **the discipline of knowing when NOT to use discipline.** When blast radius is low and you just need fast cheap hands, skip the SDLC overhead.
191
+ Setup D's whole point: **the discipline of knowing when NOT to use discipline.** When blast radius is low and you just need fast cheap hands, skip the SDLC overhead.
202
192
 
203
- **A note on `[1m]` and billing.** The `[1m]` suffix is the 1M-context alias. As of [March 2026](https://claude.com/blog/1m-context-ga), 1M context is GA at standard pricing — **no long-context surcharge, no premium tier, no API-only restriction.** Interactive Claude Code sessions on Max / Team / Enterprise plans include 1M context automatically; whether you set `claude-opus-4-6` or `claude-opus-4-6[1m]`, you're billed against the same per-token Max budget at $5/$25 per million tokens. (Pro users need "Enable usage credits" turned on once.) The [June 15, 2026 billing split](https://codersera.com/blog/anthropic-june-2026-billing-change-claude-code/) moved *headless* surfaces — `claude -p`, Agent SDK, GitHub Actions, third-party apps — off the Max subscription onto a separate metered credit pool. Interactive Claude Code in your terminal stays on Max. Full details in [`AI_SETUP_LANES.md` § How Billing Works](AI_SETUP_LANES.md#how-billing-works--1m-context-max-plan-and-the-june-15-split).
193
+ **A note on `[1m]` and billing.** Sonnet 5 always runs at its native 1M context — no `[1m]` suffix needed, no separate billing tier. For Opus, the `[1m]` suffix is the 1M-context alias; as of [March 2026](https://claude.com/blog/1m-context-ga), 1M context is GA at standard pricing — **no long-context surcharge, no premium tier, no API-only restriction.** Interactive Claude Code sessions on Max / Team / Enterprise plans include 1M context automatically. (Pro users need "Enable usage credits" turned on once.) The [June 15, 2026 billing split](https://codersera.com/blog/anthropic-june-2026-billing-change-claude-code/) moved *headless* surfaces — `claude -p`, Agent SDK, GitHub Actions, third-party apps — off the Max subscription onto a separate metered credit pool. Interactive Claude Code in your terminal stays on Max. Full details in [`AI_SETUP_LANES.md` § How Billing Works](AI_SETUP_LANES.md#how-billing-works--1m-context-max-plan-and-the-june-15-split).
204
194
 
205
195
  ## How It Works
206
196
 
package/cli/init.js CHANGED
@@ -26,6 +26,9 @@ const FILES = [
26
26
  { src: 'hooks/model-effort-check.sh', dest: '.claude/hooks/model-effort-check.sh', executable: true, base: REPO_ROOT },
27
27
  { src: 'hooks/precompact-seam-check.sh', dest: '.claude/hooks/precompact-seam-check.sh', executable: true, base: REPO_ROOT },
28
28
  { src: 'hooks/goal-confidence-check.sh', dest: '.claude/hooks/goal-confidence-check.sh', executable: true, base: REPO_ROOT },
29
+ { src: 'hooks/codex-gate-check.sh', dest: '.claude/hooks/codex-gate-check.sh', executable: true, base: REPO_ROOT },
30
+ { src: 'hooks/token-spike-check.sh', dest: '.claude/hooks/token-spike-check.sh', executable: true, base: REPO_ROOT },
31
+ { src: 'hooks/codex-review-stop-check.sh', dest: '.claude/hooks/codex-review-stop-check.sh', executable: true, base: REPO_ROOT },
29
32
  // #254 Bug 1: shared helper sourced by all hooks above. Must ship — without
30
33
  // it, hooks emit "_find-sdlc-root.sh: No such file or directory" + the
31
34
  // SDLC root walk-up logic is silently dead.
@@ -1,10 +1,10 @@
1
- // Roadmap #233: repo complexity heuristic for mixed-mode tier selection.
1
+ // Roadmap #233: repo complexity heuristic for setup-lane suggestion.
2
2
  //
3
3
  // Output: { tier: 'simple' | 'complex', score: <number>, signals: [...] }
4
- // - 'simple' → setup wizard suggests mixed-mode (Sonnet 4.6 coder + Opus 4.6 max reviewer)
5
- // - 'complex' → setup wizard suggests full flagship (Opus 4.6 max everywhere)
6
- // Cross-model review (Codex / external) always stays at the flagship tier
7
- // regardless of coder selection — see CLAUDE_CODE_SDLC_WIZARD.md.
4
+ // - 'simple' → setup wizard suggests Setup A (Sonnet 5 + Fable) or no pin
5
+ // - 'complex' → setup wizard suggests Setup B (Opus 4.6 Stability) or escalating to Opus 4.8
6
+ // Cross-model review (Codex xhigh) always runs regardless of driver
7
+ // selection — see CLAUDE_CODE_SDLC_WIZARD.md.
8
8
  //
9
9
  // Classification (matches CLAUDE_CODE_SDLC_WIZARD.md → "Mixed-Mode Tier"):
10
10
  // simple = LOC < 10K AND tests < 30 AND hooks < 5 AND workflows < 5 AND no stakes
@@ -25,6 +25,15 @@
25
25
  "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/tdd-pretool-check.sh"
26
26
  }
27
27
  ]
28
+ },
29
+ {
30
+ "matcher": "Bash",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/codex-gate-check.sh"
35
+ }
36
+ ]
28
37
  }
29
38
  ],
30
39
  "InstructionsLoaded": [
@@ -43,6 +52,10 @@
43
52
  {
44
53
  "type": "command",
45
54
  "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/model-effort-check.sh"
55
+ },
56
+ {
57
+ "type": "command",
58
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/token-spike-check.sh"
46
59
  }
47
60
  ]
48
61
  }
@@ -57,6 +70,16 @@
57
70
  }
58
71
  ]
59
72
  }
73
+ ],
74
+ "Stop": [
75
+ {
76
+ "hooks": [
77
+ {
78
+ "type": "command",
79
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/codex-review-stop-check.sh"
80
+ }
81
+ ]
82
+ }
60
83
  ]
61
84
  }
62
85
  }
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+ # PreToolUse hook — blocks git commit without cross-model review artifact
3
+ # Fires on Bash tool; only acts when the command contains "git commit"
4
+ #
5
+ # #436 fix: exit 2 + stderr is what actually denies the tool call in Claude
6
+ # Code. The original version exited 0 on every path (including the two
7
+ # "CROSS-MODEL REVIEW REQUIRED" branches below), so it printed a warning but
8
+ # never blocked anything — the exact bug class this gate exists to prevent.
9
+ # Matches the proven blocking pattern in precompact-seam-check.sh.
10
+
11
+ set -e
12
+
13
+ # Skip gate if explicitly overridden (emergency bypass with logged justification)
14
+ [ "${CODEX_GATE_SKIP:-}" = "1" ] && exit 0
15
+
16
+ TOOL_INPUT=$(cat)
17
+
18
+ # Codex review findings (hook-enforcement-436):
19
+ # Round 1: extracting the "command" field's value via grep/sed with
20
+ # `[^"]*` broke when an earlier quote appeared in the command (e.g. `cd
21
+ # "$dir" && git commit ...`) — the class stops at the first literal `"`
22
+ # regardless of JSON escaping, truncating the capture before it ever
23
+ # reached "git commit" (false negative — review-less commit slipped
24
+ # through).
25
+ # Round 2: matching "git commit" against the WHOLE raw TOOL_INPUT (the
26
+ # round-1 fix) over-corrected — a non-commit command got blocked if any
27
+ # OTHER field (e.g. the Bash tool's own "description") happened to mention
28
+ # "git commit" in prose (false positive).
29
+ # Fix: extract just the "command" field's value with an escape-aware
30
+ # pattern — `([^"\\]|\\.)*` consumes an escaped quote (`\"`) as one unit
31
+ # instead of treating it as a terminator, so it can't stop early, and it
32
+ # still can't run past the field's true (unescaped) closing quote because
33
+ # neither alternative in the group can match a bare `"`. Scoped to just
34
+ # this field, so unrelated fields containing the phrase can't false-trigger.
35
+ COMMAND_FIELD=$(printf '%s' "$TOOL_INPUT" \
36
+ | grep -oE '"command"[[:space:]]*:[[:space:]]*"([^"\\]|\\.)*"')
37
+
38
+ case "$COMMAND_FIELD" in
39
+ *"git commit"*) ;;
40
+ *) exit 0 ;;
41
+ esac
42
+
43
+ REVIEW_FILE=".reviews/handoff.json"
44
+
45
+ if [ ! -f "$REVIEW_FILE" ]; then
46
+ echo "CROSS-MODEL REVIEW REQUIRED: No .reviews/handoff.json found. Run Codex cross-model review before committing. Set CODEX_GATE_SKIP=1 to bypass with justification." >&2
47
+ exit 2
48
+ fi
49
+
50
+ STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$REVIEW_FILE" \
51
+ | head -1 \
52
+ | sed 's/.*"status"[[:space:]]*:[[:space:]]*"//; s/"$//')
53
+
54
+ case "$STATUS" in
55
+ CERTIFIED|REVIEWED) exit 0 ;;
56
+ *)
57
+ echo "CROSS-MODEL REVIEW REQUIRED: .reviews/handoff.json status is '$STATUS' (need REVIEWED or CERTIFIED). Run Codex cross-model review before committing. Set CODEX_GATE_SKIP=1 to bypass with justification." >&2
58
+ exit 2
59
+ ;;
60
+ esac
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # Stop hook — warns (non-blocking) when the session is about to end with
3
+ # significant uncommitted changes and no REVIEWED/CERTIFIED cross-model
4
+ # review artifact.
5
+ #
6
+ # Gap this closes (Fable self-enforcement audit, #436): a full SDLC workflow
7
+ # can complete — Claude presents "done, here's what I changed" — without
8
+ # ever running `git commit`. codex-gate-check.sh only fires on that one
9
+ # Bash command, so it never triggers and cross-model review is silently
10
+ # skippable. This hook catches the "never committed, walked away" case.
11
+ #
12
+ # Non-blocking by design: Stop fires at the end of every turn, not just at
13
+ # true session end, and it must never prevent the user from getting their
14
+ # response. Fires once per session (sentinel-gated) to avoid nagging on
15
+ # every iterative turn while a feature is still in progress.
16
+
17
+ HOOK_DIR="${BASH_SOURCE[0]%/*}"
18
+ [ "$HOOK_DIR" = "${BASH_SOURCE[0]}" ] && HOOK_DIR="."
19
+ # shellcheck disable=SC1091
20
+ source "$HOOK_DIR/_find-sdlc-root.sh"
21
+ dedupe_plugin_or_project "${BASH_SOURCE[0]}" || { cat > /dev/null; exit 0; }
22
+
23
+ STDIN_JSON=$(cat)
24
+
25
+ git rev-parse --is-inside-work-tree > /dev/null 2>&1 || exit 0
26
+
27
+ # Changed files: staged + unstaged + untracked, excluding review metadata
28
+ # itself (.reviews/ changes describe the review, they aren't the work).
29
+ CHANGED=$(git status --porcelain 2>/dev/null | awk '{print $2}' | grep -v '^\.reviews/')
30
+ [ -z "$CHANGED" ] && exit 0
31
+
32
+ # Doc-only changes don't need cross-model review.
33
+ SIGNIFICANT=$(printf '%s\n' "$CHANGED" | grep -vE '\.md$|\.txt$|^LICENSE|^CHANGELOG|\.gitignore$|\.gitattributes$')
34
+ [ -z "$SIGNIFICANT" ] && exit 0
35
+
36
+ REVIEW_FILE=".reviews/handoff.json"
37
+ if [ -f "$REVIEW_FILE" ]; then
38
+ STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$REVIEW_FILE" \
39
+ | head -1 \
40
+ | sed 's/.*"status"[[:space:]]*:[[:space:]]*"//; s/"$//')
41
+ case "$STATUS" in
42
+ CERTIFIED|REVIEWED) exit 0 ;;
43
+ esac
44
+ fi
45
+
46
+ # Once-per-session sentinel — avoid nagging on every Stop event while a
47
+ # feature is still in progress within the same session.
48
+ SESSION_ID=$(printf '%s' "$STDIN_JSON" \
49
+ | grep -o '"session_id"[[:space:]]*:[[:space:]]*"[^"]*"' \
50
+ | head -1 \
51
+ | sed 's/.*"\([^"]*\)"$/\1/')
52
+ if [ -n "$SESSION_ID" ]; then
53
+ CACHE_DIR="${SDLC_WIZARD_CACHE_DIR:-$HOME/.cache/sdlc-wizard}"
54
+ SAFE_SID=$(printf '%s' "$SESSION_ID" | tr -cd 'A-Za-z0-9._-')
55
+ if [ -n "$SAFE_SID" ]; then
56
+ SENTINEL="$CACHE_DIR/stop-review-warned-${SAFE_SID}"
57
+ mkdir -p "$CACHE_DIR" 2>/dev/null || true
58
+ if [ -f "$SENTINEL" ]; then
59
+ exit 0
60
+ fi
61
+ : > "$SENTINEL" 2>/dev/null || true
62
+ fi
63
+ fi
64
+
65
+ echo "NOTE: uncommitted changes with no REVIEWED/CERTIFIED cross-model review artifact. If this work is heading to a commit, run Codex review before committing." >&2
66
+
67
+ exit 0
package/hooks/hooks.json CHANGED
@@ -25,6 +25,15 @@
25
25
  "command": "${CLAUDE_PLUGIN_ROOT}/hooks/tdd-pretool-check.sh"
26
26
  }
27
27
  ]
28
+ },
29
+ {
30
+ "matcher": "Bash",
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/codex-gate-check.sh"
35
+ }
36
+ ]
28
37
  }
29
38
  ],
30
39
  "InstructionsLoaded": [
@@ -61,6 +70,16 @@
61
70
  }
62
71
  ]
63
72
  }
73
+ ],
74
+ "Stop": [
75
+ {
76
+ "hooks": [
77
+ {
78
+ "type": "command",
79
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/codex-review-stop-check.sh"
80
+ }
81
+ ]
82
+ }
64
83
  ]
65
84
  }
66
85
  }
@@ -1,18 +1,23 @@
1
1
  #!/bin/bash
2
2
  # SessionStart hook — effort/model nudge.
3
3
  #
4
- # Behavior (#395 update):
4
+ # Behavior (v1.84.0 update — model-aware floor):
5
5
  # CLAUDE_CODE_EFFORT_LEVEL env var takes precedence over effortLevel in settings.
6
6
  # CC docs: max is session-only in settings.json — only the env var persists it.
7
- # Opus 4.6 supports: low, medium, high, max (NO xhigh falls back to high).
7
+ # This hook cannot detect the active model (SessionStart payload has no model
8
+ # field, per ROADMAP #180), so it uses a floor that's correct across models:
9
+ # `high` is Sonnet 5's and Fable's tested default (escalate to xhigh for hard
10
+ # tasks); xhigh is Opus 4.8's floor; max remains the sweet spot on Opus 4.6
11
+ # (no xhigh support). Blanket max is WRONG for Sonnet 5/Opus 4.8 (wastes
12
+ # tokens for no quality gain — see AI_SETUP_LANES.md per-model table).
8
13
  #
9
- # effort=max -> silent (only acceptable level)
10
- # anything else -> LOUD WARNING
14
+ # effort=high, xhigh, or max -> silent (all acceptable — model-dependent)
15
+ # anything else -> LOUD WARNING
11
16
  #
12
17
  # Non-blocking: always exits 0.
13
18
 
14
- # Multiple wizard-blessed models — don't nudge to a single one (#403)
15
- RECOMMENDED_MODELS="claude-opus-4-6, opusplan, or fable (run: /model)"
19
+ # Multiple wizard-blessed models — don't nudge to a single one (#403, #434)
20
+ RECOMMENDED_MODELS="sonnet, opus, opusplan, or fable (run: /model)"
16
21
 
17
22
  HOOK_DIR="${BASH_SOURCE[0]%/*}"
18
23
  [ "$HOOK_DIR" = "${BASH_SOURCE[0]}" ] && HOOK_DIR="."
@@ -44,7 +49,12 @@ if [ -z "$effort" ]; then
44
49
  done
45
50
  fi
46
51
 
47
- # Only env-var max is truly silent.
52
+ # high/xhigh are always silent (persist fine via settings.json, no CC quirk).
53
+ # max is silent EXCEPT when it's settings-only — CC docs: max is session-only
54
+ # in settings.json, only the env var actually persists it.
55
+ if [ "$effort" = "high" ] || [ "$effort" = "xhigh" ]; then
56
+ exit 0
57
+ fi
48
58
  if [ "$effort" = "max" ] && [ "$settings_max" -eq 0 ]; then
49
59
  exit 0
50
60
  fi
@@ -58,11 +68,11 @@ else
58
68
  fi
59
69
 
60
70
  echo "=============================================================================="
61
- echo " WARNING: effort '$effort_display' — SDLC requires max."
62
- echo " Below max = degraded reasoning, shallow TDD, weak self-review."
71
+ echo " WARNING: effort '$effort_display' — SDLC requires high, xhigh, or max."
72
+ echo " Below high = degraded reasoning, shallow TDD, weak self-review."
63
73
  echo ""
64
- echo " Run: /effort max"
65
- echo " Persist: set CLAUDE_CODE_EFFORT_LEVEL=max in settings env block"
74
+ echo " Run: /effort xhigh (or /effort high — see AI_SETUP_LANES.md)"
75
+ echo " Avoid shell-rc env var persistence silently overrides model switches."
66
76
  echo ""
67
77
  echo " recommended models: $RECOMMENDED_MODELS"
68
78
  echo "=============================================================================="
@@ -1,6 +1,15 @@
1
1
  #!/bin/bash
2
2
  # PreToolUse hook - TDD enforcement before editing source files
3
3
  # Fires before Write/Edit/MultiEdit tools
4
+ #
5
+ # #436 fix: this hook printed a TDD reminder but never exited 2 — pure prose
6
+ # despite tdd_red being CRITICAL in the SDLC scoring rubric. It now blocks
7
+ # (exit 2) writes to src/** unless a test file was touched earlier this
8
+ # session. This is an edit-ordering proxy, not full "does a failing test
9
+ # exist" verification — a bash hook can't run the suite and confirm RED.
10
+ # Session-scoped (degrades to allow when session_id is absent — no cross-call
11
+ # state to track without it, matching the back-compat stance already taken
12
+ # for the nudge below).
4
13
 
5
14
  # Token-bloat fix: when both project + plugin register this hook, plugin yields.
6
15
  # Parameter-expansion-safe (no `dirname` dep): `%/*` strips trailing `/file`.
@@ -25,9 +34,39 @@ SESSION_ID=$(printf '%s' "$TOOL_INPUT" \
25
34
  | head -1 \
26
35
  | sed 's/.*"\([^"]*\)"$/\1/')
27
36
 
37
+ # Test-file detection: always allowed, and marks "a test was touched" for
38
+ # this session so the src/ gate below can unlock. Priority over the src/
39
+ # check since many conventions nest tests inside src/ (e.g. src/__tests__/).
40
+ if [[ "$FILE_PATH" =~ (\.test\.|\.spec\.|/__tests__/|/tests?/|/test_|^test_) ]]; then
41
+ if [ -n "$SESSION_ID" ]; then
42
+ CACHE_DIR="${SDLC_WIZARD_CACHE_DIR:-$HOME/.cache/sdlc-wizard}"
43
+ SAFE_SID=$(printf '%s' "$SESSION_ID" | tr -cd 'A-Za-z0-9._-')
44
+ if [ -n "$SAFE_SID" ]; then
45
+ mkdir -p "$CACHE_DIR" 2>/dev/null || true
46
+ : > "$CACHE_DIR/tdd-test-touched-${SAFE_SID}" 2>/dev/null || true
47
+ fi
48
+ fi
49
+ exit 0
50
+ fi
51
+
28
52
  # CUSTOMIZE: Change this pattern to match YOUR source directory
29
53
  # Examples: "/src/", "/app/", "/lib/", "/packages/", "/server/"
30
- if [[ "$FILE_PATH" == *"/src/"* ]]; then
54
+ # Codex review finding (hook-enforcement-436, round 1): "*/src/*" requires a
55
+ # slash BEFORE "src", so a cwd-relative file_path like "src/app.js" (no
56
+ # leading slash) never matched and the whole gate silently no-op'd. Second
57
+ # clause catches the relative form.
58
+ if [[ "$FILE_PATH" == *"/src/"* || "$FILE_PATH" == "src/"* ]]; then
59
+ # #436 gate: block implementation-first edits when no test file has been
60
+ # touched yet this session. Degrades to allow without session_id.
61
+ if [ -n "$SESSION_ID" ]; then
62
+ CACHE_DIR="${SDLC_WIZARD_CACHE_DIR:-$HOME/.cache/sdlc-wizard}"
63
+ SAFE_SID=$(printf '%s' "$SESSION_ID" | tr -cd 'A-Za-z0-9._-')
64
+ if [ -n "$SAFE_SID" ] && [ ! -f "$CACHE_DIR/tdd-test-touched-${SAFE_SID}" ]; then
65
+ echo "TDD RED REQUIRED: no test file touched yet this session. Write or edit a failing test before implementing in src/." >&2
66
+ exit 2
67
+ fi
68
+ fi
69
+
31
70
  # Token-bloat fix (v1.70.0): nudge fires once per CC session. Once Claude
32
71
  # has the SDLC skill auto-invoked (covers TDD RED/GREEN), the per-Edit
33
72
  # nudge becomes duplicate context — typical session has 10-30 src Edits
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-wizard",
3
- "version": "1.83.0",
3
+ "version": "1.84.0",
4
4
  "description": "SDLC enforcement for Claude Code — hooks, skills, and wizard setup in one command",
5
5
  "bin": {
6
6
  "sdlc-wizard": "cli/bin/sdlc-wizard.js"
@@ -2,7 +2,6 @@
2
2
  name: sdlc
3
3
  description: Full SDLC workflow for implementing features, fixing bugs, refactoring code, testing, releasing, publishing, and deploying. Use this skill when implementing, fixing, refactoring, testing, adding features, building new code, or releasing/publishing/deploying.
4
4
  argument-hint: [task description]
5
- effort: max
6
5
  ---
7
6
  # SDLC Skill - Full Development Workflow
8
7
 
@@ -17,6 +16,8 @@ $ARGUMENTS
17
16
 
18
17
  Operational checklist. Full protocol lives in `CLAUDE_CODE_SDLC_WIZARD.md` — read it for depth.
19
18
 
19
+ **If the user requests /sdlc, ALWAYS run the full workflow — even for mechanical tasks.** Never silently skip; if overkill, say so and ask.
20
+
20
21
  ## Full SDLC Checklist
21
22
 
22
23
  Your FIRST action must be a TodoWrite covering every phase below. Compact form (omit `activeForm` to use the subject as the spinner label):
@@ -96,13 +97,17 @@ State your confidence before presenting an approach:
96
97
 
97
98
  | Level | Meaning | Action | Effort |
98
99
  |-------|---------|--------|--------|
99
- | HIGH (90%+) | Know exactly what to do | Present, proceed after approval | `max` (default) |
100
- | MEDIUM (60-89%) | Solid approach, some uncertainty | Present, highlight uncertainties | `max` (default) |
101
- | LOW (<60%) | Not sure | Research or try Codex; if still LOW, ASK USER | **`/effort max` now** |
102
- | FAILED 2x | Something's wrong | Codex for fresh perspective; if still stuck, STOP | **`/effort max` now** |
103
- | CONFUSED | Can't diagnose | Codex; if still confused, STOP and describe | **`/effort max` now** |
100
+ | HIGH (90%+) | Know exactly what to do | Present, proceed after approval | Model default |
101
+ | MEDIUM (60-89%) | Solid approach, some uncertainty | Present, highlight uncertainties | Model default |
102
+ | LOW (<60%) | Not sure | Research or try Codex; if still LOW, ASK USER | **escalate now** (per model, see above) |
103
+ | FAILED 2x | Something's wrong | Codex for fresh perspective; if still stuck, STOP | **escalate now** |
104
+ | CONFUSED | Can't diagnose | Codex; if still confused, STOP and describe | **escalate now** |
105
+
106
+ **Effort bumping is NOT optional.** Bump BEFORE the next attempt, not after a third failure.
107
+
108
+ **Confidence ramp:** Opus researches → Fable batch review → 95% list → /goal TDD → Codex check.
104
109
 
105
- **Dynamic effort bumping is NOT optional.** "Consider max effort" is the same as "ignore this." Bump BEFORE the next attempt, not after a third failure.
110
+ **Advisor:** `advisor()` before plans; if down, spawn Fable subagent.
106
111
 
107
112
  ## Plan Mode
108
113
 
@@ -114,11 +119,11 @@ Native `/goal <condition>` (**v2.1.143+**). Haiku evaluator re-checks transcript
114
119
 
115
120
  ## Recommended Model
116
121
 
117
- **Recommended: `claude-opus-4-6` or `opusplan` (Opus 4.6 max wizard's flagship).** Pin in settings or `/model claude-opus-4-6` at session start. `opusplan` uses Opus for Plan Mode (Shift+Tab) + Sonnet for execution — both Max-bundled. Persist effort: `CLAUDE_CODE_EFFORT_LEVEL=max` in settings env block.
122
+ **Recommended: Sonnet 5 `high`→`xhigh`** — beats Opus 4.6, ~5x less quota. Escalate to **Opus 4.8 `xhigh`** when stuck. **Opus 4.6 `max`** valid for consistency. See `AI_SETUP_LANES.md`.
118
123
 
119
- **If pinning `claude-opus-4-6`:** pair with `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30`default compacts too early at ~76K on 1M. **Do not set this for `opusplan`**200K context, 30% = 60K too aggressive.
124
+ **Effort is model-aware, not blanket `max`**`max` overthinks on Sonnet 5/Opus 4.8. Set via `/effort` per session, not a shell-rc env var (overrides post-switch see SDLC.md). `/model` persists; picker `s` does not.
120
125
 
121
- **Advisor (v2.1.170+):** Flagship → `advisorModel: "fable"`. OpusPlan `advisorModel: "claude-opus-4-6"`. Set during `/setup-wizard` Step 9.5.
126
+ **Pinning `claude-opus-4-6`:** pair with `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=30` (1M) — do not set this for `opusplan` (200K, too aggressive). **Advisor (v2.1.170+):** `advisorModel: "fable"` works with all drivers above; set in `/setup-wizard` Step 9.5.
122
127
 
123
128
  ## Self-Review Loop
124
129
 
@@ -132,20 +137,20 @@ The loop goes back to PLANNING, not TDD RED. Run `/code-review`; issues at confi
132
137
 
133
138
  ## Cross-Model Review (REQUIRED for High-Stakes)
134
139
 
135
- **When to run:** high-stakes changes (auth, payments, data), releases/publishes, complex refactors. **When to skip (log justification):** trivial, hotfixes, risk < review cost. **Prerequisites:** Codex CLI (`npm i -g @openai/codex`) + OpenAI API key. **Reviewer at flagship tier (#233):** even on `opusplan` (Sonnet driver), reviewer runs `gpt-5.5` xhigh — adversarial diversity is the point.
140
+ **When to run:** high-stakes changes (auth, payments, data), releases/publishes, complex refactors. **When to skip (log justification):** trivial, hotfixes, risk < review cost. **Prerequisites:** Codex CLI + OpenAI API key. **Reviewer:** `gpt-5.5` xhigh — adversarial diversity.
136
141
 
137
142
  PROTOCOL is universal across domains; only `review_instructions` and `verification_checklist` change.
138
143
 
139
144
  1. **Preflight** (`.reviews/preflight-{review_id}.md`) — what you already checked: `/code-review` passed, tests passing, manual verifications, known limits. Reduces reviewer findings to 0-1/round.
140
- 2. **Mission-first handoff** (`.reviews/handoff.json`) — required keys: `"review_id"`, `"status": "PENDING_REVIEW"`, `"round": 1`, `"mission"`/`"success"`/`"failure"` (without them you get "looks good"), `"files_changed"`, `"verification_checklist"` (verification checklist with file:line refs — NOT generic), `"review_instructions"`, `"preflight_path"`. Optional `"pr_number":` opts into PreCompact self-heal (#209: PR MERGED → implicit CERTIFIED).
141
- 3. **Run reviewer:** `codex exec -c 'model_reasoning_effort="xhigh"' -s danger-full-access -o .reviews/latest-review.md "<prompt>" < /dev/null`. Always `xhigh`. Bash tool requires `run_in_background: true` + `dangerouslyDisableSandbox: true`; append `< /dev/null` always. **Why:** `< /dev/null` prevents codex stdin-hang at S/0% CPU; `run_in_background: true` avoids the Bash 10-min (`600000` ms) `timeout` cap that force-kills foreground codex (multi-artifact bundles take 5–30 min). xhigh 1–30 min; wrapper's `STALL_SECONDS=1800` is the real control. Heartbeat: `scripts/codex-review-with-progress.sh`. Foreground burned 70 min on a 7-min review (#364).
142
- 4. **Dialogue loop:** per-finding response (`{"finding": "1", "action": "FIXED|DISPUTED|ACCEPTED", "summary": "..."}` in `.reviews/response.json`). Bump round, set status `PENDING_RECHECK`, add `fixes_applied` (numbered, file:line). Recheck prompt: "TARGETED RECHECK. FIXED → verify certify condition. DISPUTED → ACCEPT if sound, REJECT with reasoning. ACCEPTED → verify applied. No new findings unless P0."
145
+ 2. **Mission-first handoff** (`.reviews/handoff.json`) — required keys: `"review_id"`, `"status": "PENDING_REVIEW"`, `"round": 1`, `"mission"`/`"success"`/`"failure"` (without them you get "looks good"), `"files_changed"`, `"verification_checklist"` (verification checklist with file:line refs — NOT generic), `"review_instructions"`, `"preflight_path"`. Optional `"pr_number":` opts into PreCompact self-heal (#209: MERGED → implicit CERTIFIED).
146
+ 3. **Run reviewer:** `codex exec -c 'model_reasoning_effort="xhigh"' -s danger-full-access -o .reviews/latest-review.md "<prompt>" < /dev/null`. Always `xhigh`. Bash tool requires `run_in_background: true` + `dangerouslyDisableSandbox: true`; always append `< /dev/null`. **Why:** `< /dev/null` prevents codex stdin-hang at S/0% CPU; `run_in_background: true` avoids the Bash 10-min (`600000` ms) `timeout` cap that force-kills foreground codex (multi-artifact bundles take 5–30 min). xhigh 1–30 min; wrapper's `STALL_SECONDS=1800` controls it. Heartbeat: `scripts/codex-review-with-progress.sh`. Foreground burned 70 min on a 7-min review (#364).
147
+ 4. **Dialogue loop:** per-finding response (`{"finding": "1", "action": "FIXED|DISPUTED|ACCEPTED", "summary": "..."}` in `.reviews/response.json`). Bump round, set status `PENDING_RECHECK`, add `fixes_applied` (numbered, file:line). Recheck prompt: "TARGETED RECHECK. FIXED → verify certify condition. DISPUTED → ACCEPT if sound, REJECT with reasoning. ACCEPTED → verify applied. No new findings unless P0." **NEVER unilaterally dismiss** — always run the recheck. It's a conversation: the reviewer may accept your dispute or counter with evidence you missed.
143
148
 
144
- **Convergence:** 2 rounds sweet spot, 3 max. After 3 NOT CERTIFIED escalate.
149
+ **Convergence:** 2 rounds sweet spot, 3 max, escalate after except large migrations: judge by finding trend, not count.
145
150
 
146
151
  **Enforcement:** `hooks/goal-confidence-check.sh` warns when `/goal` skips the 95%-confidence or DLC-binding gates (#360).
147
152
 
148
- **Multi-reviewer:** respond to each reviewer independently (no shared anchoring). **Non-code domains:** add `"audience"`/`"stakes"` keys to handoff.
153
+ **Multi-reviewer:** respond to each independently (no shared anchoring). **Non-code domains:** add `"audience"`/`"stakes"` keys.
149
154
 
150
155
  ### Release Review Focus
151
156
 
@@ -165,7 +170,7 @@ Standard pattern: `*_DOCS.md` — living documents that grow with the feature (`
165
170
  4. No `*_DOCS.md` exists and feature touches 3+ files → create one
166
171
  5. Project has `ROADMAP.md` → mark items done, add new items (ROADMAP feeds CHANGELOG)
167
172
 
168
- `/claude-md-improver` audits CLAUDE.md structure. Run it periodically. It does NOT cover feature docs — the SDLC workflow handles those.
173
+ `/claude-md-improver` audits CLAUDE.md structure periodically. Does NOT cover feature docs.
169
174
 
170
175
  ## CI Feedback Loop — Local Shepherd
171
176
 
@@ -175,7 +180,7 @@ Mandatory steps:
175
180
  1. Push to remote
176
181
  2. `gh pr checks --watch`
177
182
  3. **Read CI logs whether pass or fail** (`gh run view <RUN_ID> --log`, not just `--log-failed`). Passing CI hides warnings, skipped steps, degraded scores
178
- 4. **Cross-model audit the CI logs** — pipe to a tmp file, run `codex exec -c 'model_reasoning_effort="xhigh"' -s danger-full-access "<audit prompt>" < /dev/null` (always append `< /dev/null` — stdin-hang fix) with *"Audit for silent failures, skipped tests, degraded metrics, warnings-that-should-be-errors."* Tier 1 + Tier 2 separately
183
+ 4. **Cross-model audit the CI logs** — same `codex exec` pattern (see Cross-Model Review §3). Prompt: *"Audit for silent failures, skipped tests, degraded metrics, warnings-that-should-be-errors."* Tier 1 + Tier 2 separately
179
184
  5. CI fails → diagnose, fix, push (max 2 attempts)
180
185
  6. CI passes → `gh api repos/OWNER/REPO/pulls/PR/comments` for review feedback
181
186
  7. Implement valid suggestions (bugs, perf, missing error handling, dedup, coverage). Skip opinions/style. Max 3 iterations
@@ -192,7 +197,7 @@ Mandatory steps:
192
197
 
193
198
  ## Debugging Workflow (Systematic)
194
199
 
195
- Reproduce → Isolate → Root Cause → Fix → Regression Test. This is the systematic debugging methodology — do not skip steps. Regressions: `git bisect`. Env-specific: check env vars/OS/deps/permissions, reproduce locally, log at the failure point. 2 failed attempts → STOP and ASK USER.
200
+ Reproduce → Isolate → Root Cause → Fix → Regression Test. Do not skip steps. `git bisect` for regressions. 2 failed attempts → STOP and ASK USER.
196
201
 
197
202
  ## Release Planning (Task Ships a Release)
198
203
 
@@ -249,7 +254,7 @@ Per-user memory at `~/.claude/projects/<proj>/memory/` accumulates private learn
249
254
  - `type: project` → manual review (mixed state + portable lesson)
250
255
  - `type: feedback` → manual review (mixed personal preference + portable rule)
251
256
 
252
- **Destinations for promote entries** (no new files): tool/platform gotchas → `SDLC.md` `## Lessons Learned`. Testing → `TESTING.md`. Tool quirks tied to a skill → that `SKILL.md`. Process rules → `CLAUDE.md`.
257
+ **Destinations** (no new files): gotchas → `SDLC.md`. Testing → `TESTING.md`. Skill quirks → that `SKILL.md`. Process rules → `/sdlc`. **Memory that's a process rule = /sdlc gap — use /feedback.**
253
258
 
254
259
  **Tracking:** `promoted_to: <path>` in the memory file's YAML frontmatter; later audits skip already-promoted entries.
255
260