agentic-sdlc-wizard 1.85.0 → 1.86.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.
@@ -13,7 +13,7 @@
13
13
  "name": "sdlc-wizard",
14
14
  "source": ".",
15
15
  "description": "SDLC enforcement for AI agents — TDD, planning, self-review, CI shepherd",
16
- "version": "1.85.0",
16
+ "version": "1.86.0",
17
17
  "author": {
18
18
  "name": "Stefan Ayala"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdlc-wizard",
3
- "version": "1.85.0",
3
+ "version": "1.86.0",
4
4
  "description": "SDLC enforcement for AI agents — TDD, planning, self-review, CI shepherd",
5
5
  "author": {
6
6
  "name": "Stefan Ayala",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ All notable changes to the SDLC Wizard.
4
4
 
5
5
  > **Note:** This changelog is for humans to read. Don't manually apply these changes - just run the wizard ("Check for SDLC wizard updates") and it handles everything automatically.
6
6
 
7
+ ## [1.86.0] - 2026-07-05
8
+
9
+ ### Fixed
10
+ - **#437: `codex-gate-check.sh` stale-certification loophole.** A CERTIFIED/REVIEWED `handoff.json` status was checked as a literal string with no freshness check — any number of commits made after certification would sail through the gate on the same stale status forever. Proven live during the v1.84.0 release: 2 real post-certification commits both passed the gate on a round-11 CERTIFIED handoff that was never re-issued. Fixed: certification now records `commit_sha` (HEAD at cert time) in `handoff.json`; the gate compares it to current HEAD and treats a mismatch — or a missing field, e.g. an old-format handoff.json predating this fix — as stale (exit 2, same as an uncertified commit). This allows exactly one commit after certification and blocks the next one until re-cert. `CODEX_GATE_SKIP=1` remains the logged-justification escape hatch. TDD: 2 new tests (`test_codex_gate_blocks_stale_certification_after_new_commit`, `test_codex_gate_blocks_missing_commit_sha_as_stale`) proven RED against the unmodified hook, GREEN after; 2 existing tests updated to real git-repo fixtures with a matching `commit_sha` (191/191 hook tests green, up from 189).
11
+ - **The protocol docs needed updating in 3 separate places, not 1 — Codex cross-model review caught 2 of them.** `CLAUDE_CODE_SDLC_WIZARD.md` documents the cross-model review protocol twice (a condensed summary section and a fuller tutorial section), each with its own prose instruction *and* its own ASCII flow diagram — 7 total "reached CERTIFIED, now what" decision points. Round 1 caught a missed prose instruction in the tutorial section; round 2's mutation testing proved my first regression test (a whole-file count comparison) had real slack and, while investigating that, surfaced a 3rd, entirely separate miss: the condensed section's own flow diagram, never touched by anything. All 7 decision points (3 prose instructions + 4 diagram exits across both sections) now write `"commit_sha"` on the same line. `skills/sdlc/SKILL.md` updated too. Replaced the count-based regression test with a per-line proximity check (`test_wizard_doc_certified_paths_all_mention_commit_sha` in `tests/test-doc-consistency.sh`) that can't be fooled by aggregate slack — proved it independently by mutating each of the 3 known-fragile spots one at a time and confirming each is individually caught (53/53 at baseline).
12
+ - **Latent bug in `tests/test-self-update.sh`'s multi-reviewer checks**, exposed (not caused) while trimming `skills/sdlc/SKILL.md` back under its 20K-char cap: 3 test functions used an unescaped `?` as a quantifier (`multi.?review`) inside plain `grep -qi`, which runs basic regex where a bare `?` is a literal character, not "0 or 1 of the preceding." The check had only ever passed via an incidental phrase collision elsewhere in the file ("parallel tasks... `sdlc-reviewer`" in an unrelated Context Management bullet, not actual multi-reviewer guidance) — trimming that unrelated bullet removed the accidental match and surfaced the real bug. Fixed by adding `-E` (extended regex) so `?` behaves as intended; verified it now matches the genuine `**Multi-reviewer:**` guidance directly (153/153 tests green).
13
+
14
+ ### Why
15
+ Post-ship retrospective on v1.84.0 (2026-07-05) independently re-confirmed a gap already tracked as ROADMAP #437 (filed 2026-07-04 while shipping #436). Design settled with Fable's input in the same retrospective, implemented as a standalone TDD PR per that plan — kept separate from the doc-only v1.85.0 release since this one changes actual hook behavior on a security-relevant gate.
16
+
7
17
  ## [1.85.0] - 2026-07-05
8
18
 
9
19
  ### Fixed
@@ -2453,7 +2453,7 @@ PLANNING → DOCS → TDD RED → TDD GREEN → Tests Pass → Self-Review
2453
2453
 
2454
2454
  > **Always launch codex via `run_in_background: true` on the Bash tool.** The Bash tool clamps `timeout` to 600000 ms (10 min) regardless of the value passed, and force-kills the foreground process at that wall. Multi-artifact bundle reviews (release reviews per the checklist below, multi-finding rechecks, etc.) routinely run 6–30 minutes — they need background mode to complete. The wrapper `scripts/codex-review.sh` already has a 30-min stall watchdog (`STALL_SECONDS=1800`) as the real timeout control. A foreground call killed mid-review plus the Stop-hook re-invocation loop can burn 60+ minutes of session compute on what should be a single 7-minute run (issue #364, 2026-05-27 incident). The general rule: **any long-running wrapper invoked through the CC Bash tool — codex, slow builds, long test suites — should use `run_in_background: true` unconditionally and let the wrapper's own stall watchdog be the timeout authority.**
2455
2455
 
2456
- 3. If CERTIFIED → proceed to CI. If NOT CERTIFIED → go to Round 2.
2456
+ 3. If CERTIFIED → **write `"commit_sha": "<git rev-parse HEAD>"` into `handoff.json` before proceeding to CI.** `hooks/codex-gate-check.sh` compares this SHA to current HEAD at commit time and treats a mismatch (or a missing field) as a stale certification (ROADMAP #437) — a CERTIFIED status string alone doesn't prove the certification still covers what's about to be committed. If NOT CERTIFIED → go to Round 2.
2457
2457
 
2458
2458
  ### Round 2+: Dialogue Loop
2459
2459
 
@@ -2497,7 +2497,7 @@ When the reviewer finds issues, respond per-finding instead of silently fixing e
2497
2497
  < /dev/null
2498
2498
  ```
2499
2499
 
2500
- 4. If CERTIFIED → done. If NOT CERTIFIED (rejected disputes or failed fixes) → fix rejected items and repeat.
2500
+ 4. If CERTIFIED → **write/update `"commit_sha"` in `handoff.json` to current HEAD** (same reason as Round 1 step 3 — the gate hook checks it). If NOT CERTIFIED (rejected disputes or failed fixes) → fix rejected items and repeat.
2501
2501
 
2502
2502
  ### Convergence
2503
2503
 
@@ -2512,7 +2512,7 @@ Self-review passes → handoff.json (round 1, PENDING_REVIEW)
2512
2512
  |
2513
2513
  Reviewer: FULL REVIEW (structured findings)
2514
2514
  |
2515
- CERTIFIED? → YES → CI feedback loop
2515
+ CERTIFIED? → YES → write commit_sha → CI feedback loop
2516
2516
  |
2517
2517
  NO (findings with IDs + certify conditions)
2518
2518
  |
@@ -2523,7 +2523,7 @@ Self-review passes → handoff.json (round 1, PENDING_REVIEW)
2523
2523
  |
2524
2524
  Reviewer: TARGETED RECHECK (previous findings only)
2525
2525
  |
2526
- All resolved? → YES → CERTIFIED
2526
+ All resolved? → YES → CERTIFIED (write commit_sha)
2527
2527
  |
2528
2528
  NO → fix rejected items, repeat
2529
2529
  (max 3 rechecks, then escalate to user)
@@ -3075,7 +3075,7 @@ If deployment fails or post-deploy verification catches issues:
3075
3075
 
3076
3076
  **SDLC.md:**
3077
3077
  ```markdown
3078
- <!-- SDLC Wizard Version: 1.85.0 -->
3078
+ <!-- SDLC Wizard Version: 1.86.0 -->
3079
3079
  <!-- Setup Date: [DATE] -->
3080
3080
  <!-- Completed Steps: step-0.1, step-0.2, step-0.4, step-1, step-2, step-3, step-4, step-5, step-6, step-7, step-8, step-9 -->
3081
3081
  <!-- Git Workflow: [PRs or Solo] -->
@@ -3909,7 +3909,7 @@ codex exec \
3909
3909
 
3910
3910
  > **Always launch via `run_in_background: true` on the Bash tool.** Same reason as the parallel callout in the Cross-Model Review Loop section above — Bash tool clamps `timeout` to 600000 ms (10 min) regardless of the value passed and force-kills foreground at the wall. Multi-artifact bundle reviews need background mode to complete. See issue #364 (2026-05-27 incident: 70 min session compute on a 7-min review).
3911
3911
 
3912
- 4. If CERTIFIED → done. If NOT CERTIFIED → enter the dialogue loop.
3912
+ 4. If CERTIFIED → **write `"commit_sha": "<git rev-parse HEAD>"` into `handoff.json`** — `hooks/codex-gate-check.sh` (ROADMAP #437) blocks a commit if this is missing or doesn't match current HEAD, so a bare `CERTIFIED` status isn't enough. Then done. If NOT CERTIFIED → enter the dialogue loop.
3913
3913
 
3914
3914
  **The Dialogue Loop (Round 2+):**
3915
3915
 
@@ -3979,7 +3979,7 @@ Claude writes code → self-review passes → handoff.json (round 1)
3979
3979
  | Reviewer: FULL REVIEW
3980
3980
  | (structured findings with IDs)
3981
3981
  | |
3982
- | CERTIFIED? -+→ YES → Done
3982
+ | CERTIFIED? -+→ YES → write commit_sha → Done
3983
3983
  | |
3984
3984
  | +→ NO (findings)
3985
3985
  | |
@@ -3989,12 +3989,14 @@ Claude writes code → self-review passes → handoff.json (round 1)
3989
3989
  | Reviewer: TARGETED RECHECK
3990
3990
  | (previous findings only, no new P1/P2)
3991
3991
  | |
3992
- | All resolved? → YES → CERTIFIED
3992
+ | All resolved? → YES → CERTIFIED (write commit_sha)
3993
3993
  | |
3994
3994
  └────────── Fix rejected items ←───────────┘
3995
3995
  (max 3 rechecks, then escalate to user)
3996
3996
  ```
3997
3997
 
3998
+ **Every CERTIFIED path above writes `"commit_sha": "<git rev-parse HEAD>"` into `handoff.json`** — `hooks/codex-gate-check.sh` (ROADMAP #437) treats a missing or mismatched SHA as a stale certification, so a bare `CERTIFIED` status string is never enough on its own.
3999
+
3998
4000
  **Key flags:**
3999
4001
  - `-c 'model_reasoning_effort="xhigh"'` — Maximum reasoning depth. This is where you get the most value. Testing showed `xhigh` caught 3 findings that `high` missed on the same content.
4000
4002
  - `-s danger-full-access` — Full filesystem read/write so the reviewer can read your actual code.
@@ -52,7 +52,26 @@ STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$REVIEW_FILE" \
52
52
  | sed 's/.*"status"[[:space:]]*:[[:space:]]*"//; s/"$//')
53
53
 
54
54
  case "$STATUS" in
55
- CERTIFIED|REVIEWED) exit 0 ;;
55
+ CERTIFIED|REVIEWED)
56
+ # #437: a CERTIFIED/REVIEWED status string alone doesn't mean the
57
+ # certification is still current — commits made after it was issued
58
+ # would otherwise sail through on the same stale status forever.
59
+ # commit_sha records HEAD at cert time; a mismatch (or a missing
60
+ # field, e.g. an old-format handoff.json predating this fix) means
61
+ # new commits landed since certification, so treat it as stale. This
62
+ # allows exactly one commit after certification (HEAD still equals
63
+ # the recorded SHA at that commit's PreToolUse check) and blocks the
64
+ # next one until re-cert. No legacy-compat fallback for missing SHA.
65
+ COMMIT_SHA=$(grep -o '"commit_sha"[[:space:]]*:[[:space:]]*"[^"]*"' "$REVIEW_FILE" \
66
+ | head -1 \
67
+ | sed 's/.*"commit_sha"[[:space:]]*:[[:space:]]*"//; s/"$//')
68
+ CURRENT_HEAD=$(git rev-parse HEAD 2>/dev/null) || CURRENT_HEAD=""
69
+ if [ -z "$COMMIT_SHA" ] || [ "$COMMIT_SHA" != "$CURRENT_HEAD" ]; then
70
+ echo "CROSS-MODEL REVIEW REQUIRED: .reviews/handoff.json certification is stale (commit_sha does not match current HEAD — new commits landed since certification). Re-run Codex cross-model review. Set CODEX_GATE_SKIP=1 to bypass with justification." >&2
71
+ exit 2
72
+ fi
73
+ exit 0
74
+ ;;
56
75
  *)
57
76
  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
77
  exit 2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-wizard",
3
- "version": "1.85.0",
3
+ "version": "1.86.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"
@@ -9,7 +9,7 @@ argument-hint: [task description]
9
9
 
10
10
  This skill is loaded from **`.claude/skills/sdlc/SKILL.md`** in the active repo (symlinked to `skills/sdlc/SKILL.md` in the wizard's source tree). Claude Code prefers repo-local skills over global (`~/.claude/skills/sdlc/SKILL.md`) when both exist with the same name — the repo-local copy is the project's authoritative workflow contract. Use global skills only for cross-repo personal tooling (e.g. `feedback`, `revise-claude-md`); use repo-local for implementation, tests, release, and verification in this repo.
11
11
 
12
- If unsure which copy is active, compare `head -5 .claude/skills/sdlc/SKILL.md` against `head -5 ~/.claude/skills/sdlc/SKILL.md`. The repo-local copy wins. Don't mix guidance from both — pick the source for this repo and stay there.
12
+ If unsure which copy is active, compare `head -5` of both the repo-local copy wins. Don't mix guidance from both.
13
13
 
14
14
  ## Task
15
15
  $ARGUMENTS
@@ -143,14 +143,14 @@ PROTOCOL is universal across domains; only `review_instructions` and `verificati
143
143
 
144
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.
145
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.
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. 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. **On CERTIFIED, write `"commit_sha": "<git rev-parse HEAD>"` into `handoff.json`** — the gate hook (#437) treats a missing/mismatched SHA as stale, not just the status string.
148
148
 
149
149
  **Convergence:** 2 rounds sweet spot, 3 max, escalate after — except large migrations: judge by finding trend, not count.
150
150
 
151
151
  **Enforcement:** `hooks/goal-confidence-check.sh` warns when `/goal` skips the 95%-confidence or DLC-binding gates (#360).
152
152
 
153
- **Multi-reviewer:** respond to each independently (no shared anchoring). **Non-code domains:** add `"audience"`/`"stakes"` keys.
153
+ **Multi-reviewer:** respond to each independently. **Non-code domains:** add `"audience"`/`"stakes"` keys.
154
154
 
155
155
  ### Release Review Focus
156
156
 
@@ -275,7 +275,7 @@ Don't fix only the symptom. Add a gate so it can't happen again. Example: PR #14
275
275
  - Auto-compact fires at ~95%; `/usage` shows what's driving token spend
276
276
  - After committing a PR, `/clear` before next feature
277
277
  - `--bare` mode (v2.1.81+) skips ALL hooks/skills/LSP/plugins. Scripted headless only — never normal development.
278
- - Custom subagents (`.claude/agents/`) run autonomously and return results. Skills guide behavior; agents do work. Use for parallel tasks or fresh context. Examples: `sdlc-reviewer`, `ci-debug`, `test-writer`.
278
+ - Custom subagents (`.claude/agents/`) run autonomously and return results. Skills guide behavior; agents do work. Use for parallel tasks or fresh context.
279
279
 
280
280
  ## Design System Check (UI Changes Only)
281
281
 
@@ -95,16 +95,16 @@ Parse CHANGELOG entries between the user's installed version and the resolved la
95
95
 
96
96
  ```
97
97
  Installed: 1.42.0
98
- Latest: 1.85.0
98
+ Latest: 1.86.0
99
99
 
100
100
  What changed:
101
- - [1.85.0] Post-ship retrospective fixes: CI Feedback Loop synced to SKILL.md's stronger version (NEVER AUTO-MERGE, read-logs-even-when-green, cross-model CI audit), CERTIFIED≠CI lesson, Policy Migration Inventory checklist, stale round-count correction (#437 hook-staleness fix follows separately).
101
+ - [1.86.0] Fix #437: codex-gate-check.sh now blocks stale certifications a CERTIFIED handoff.json no longer sails through forever; it records commit_sha at cert time and blocks once HEAD moves past it without a re-cert.
102
+ - [1.85.0] Post-ship retrospective: CI Feedback Loop synced to SKILL.md's stronger version, CERTIFIED≠CI lesson, Policy Migration Inventory checklist, stale round-count correction.
102
103
  - [1.84.0] Hook enforcement fix: cross-model review gate + TDD RED gate now actually block (#436); model-aware effort docs replace blanket max recommendation.
103
104
  - [1.83.0] Model config batch: multi-model hook recommendation (#403), global [1m] pin detection (#391), version race fix (#405), effort config check (#384).
104
105
  - [1.82.0] Usage diagnostics: fix /usage row, Reading Usage Signals guide, advisor fallback procedure, Fable effort guidance, autocompact cross-reference.
105
106
  - [1.81.0] Native `advisorModel` support: Setup A gets Fable advisor, Setup B gets Opus advisor. Replaces manual subagent spawning. Requires CC v2.1.170+.
106
107
  - [1.80.0] Flip default: Opus 4.6 max becomes recommended flagship; Opus 4.8 demoted to opt-in `[l] Latest` tier.
107
- - [1.77.0] release-dry-run.yml + cc-version-drift.yml (#350) + /goal SDLC gates (95% + DLC binding).
108
108
  - [1.75.1] release-workflow fix — Node 22 → 24 (ships npm 11.x), dropped flaky `npm install -g` self-upgrade (hit MODULE_NOT_FOUND on v1.75.0 publish). Explicit npm-version guard.
109
109
  - [1.75.0] npm Trusted Publishing — `release.yml` swapped from `NPM_TOKEN` to OIDC. No more token rotation. Requires one-time publisher config on the npm package page.
110
110
  - [1.74.0] v1.43 salvage: #338 precedence preamble; #235ab `/insights`; codex `< /dev/null` stdin-hang fix; test env-isolation.