roadmap(#229): P1 precompact hook stale-handoff auto-expire - #227
Merged
Conversation
CI caught a real portability bug: `stat -f %m` on Linux is `--file-system` (dumps FS info to stdout, exit 0), not format. My `||` fallback never fired, $MTIME got garbage, and arithmetic blew up on every PENDING handoff path — regressing the existing PENDING_REVIEW/RECHECK blocks. Fix: try GNU `stat -c %Y` first (BSD errors → falls through). Add numeric case-guard so any junk in $MTIME skips the stale check entirely and falls through to HOLD (safe default). Locally macOS green. Pushing to verify Linux CI passes now.
Contributor
Claude Code Review SummaryStatus: Skipped (trivial changes) This PR only contains documentation or configuration changes. Code review skipped to save API costs. To force a review, add the |
Codex review of PR #227 caught: `SDLC_HANDOFF_STALE_DAYS=foo` leaked `[: foo: integer expression expected` to stderr before the normal HOLD text. A typo in the env var should silently fall back, not emit shell diagnostics. Fix: non-negative-integer case-pattern guard. Empty, non-numeric, negative, or decimal values fall back to default 14. Test: test_precompact_stale_threshold_invalid_falls_back asserts rc=2, PENDING_REVIEW in stderr, and NO `integer expression` noise. 20/20 precompact tests green. Codex score: 8/10 CERTIFIED (this addresses the sole P2 finding).
Live-fire bug 2026-04-23: at session end, /compact was blocked by the precompact-seam hook because .reviews/handoff.json is stuck at PENDING_RECHECK from the review that SHIPPED the hook itself. That original review was written BEFORE the self-heal pr_number feature (#209) existed, so there's no PR to auto-query. Handoff is stuck forever until manually flipped. Every wizard user who did a seam review before #209 has this landmine in their repo. Fix: add stale-handoff auto-expire. PENDING_* + no pr_number + mtime > N days → treat as CERTIFIED with WARN (not HOLD). Rescues stale handoffs without bypassing live reviews. P1 because it silently blocks a core UX (manual /compact) and the user hit it mid-session.
Fix UX landmine where handoff.json reviews predating the #209 pr_number self-heal feature would block manual /compact forever. Hook now heals via two paths: - (a) #209: pr_number + gh says MERGED → silent unblock - (b) #229: no pr_number + mtime > SDLC_HANDOFF_STALE_DAYS (default 14) → unblock with one-line WARN PR-linked handoffs still ignore mtime — an OPEN PR with old mtime is still a live review. Tests: 4 new in test-hooks.sh covering stale-unblocks, fresh-still-blocks, stale-with-pr_number-prefers-self-heal, threshold-override. 19/19 precompact tests green. Caught live-fire 2026-04-23 when session-end /compact blocked on a review that shipped the hook itself.
This was referenced Apr 27, 2026
BaseInfinity
added a commit
that referenced
this pull request
Apr 28, 2026
…pdate (#271) Two `cusum.sh --add` calls in weekly-update.yml (version-test + community- e2e-test jobs) appended scores to tests/e2e/score-history.txt, which is tracked by git. Result: every weekly run opened a PR whose only diff was the legacy side-file append — pure noise (Codex finding PR213-02 on auto- PR #213, 2026-04-23). The canonical history is score-history.jsonl, written via the CI Tier 2 persist step in ci.yml. The PR bodies already cite Phase A / baseline scores directly, so removing the standalone CUSUM update steps loses nothing functional. Per Codex consult this session: prefer "stop writing the .txt" over "close PRs with only that diff" (avoids GitHub API edge cases, simpler). New regression test test_weekly_update_does_not_call_legacy_cusum_add in tests/test-workflow-triggers.sh greps for `cusum.sh --add ` (legacy .txt write) and fails if reintroduced. --add-json (canonical .jsonl) is unaffected. Closes #227
2 tasks
BaseInfinity
added a commit
that referenced
this pull request
Apr 29, 2026
Closes #227 (Codex finding PR213-02). The PR-noise source was the scan-community job appending to legacy score-history.txt via `cusum.sh --add`. #231 Phase 3c (v1.53.0) deleted that whole job, so the noise source is already gone — Test 227 in test-workflow-triggers.sh:2445 is the regression check. Cleanup pass: - Delete empty tests/e2e/score-history.txt from the repo (was a stale runtime artifact, never appended-to since Phase 3c) - Add tests/e2e/score-history.txt to .gitignore (test-cusum.sh recreates it on runs that exercise legacy --add mode) - Drop the stale .txt mention in plans/AUTO_SELF_UPDATE.md (was a Files Structure block listing both .txt and .jsonl; .jsonl is the canonical store now) cusum.sh keeps both modes (--add legacy plain-text + --add-json canonical JSONL) for users who want plain-text mode for ad-hoc CLI work. No interface change. No version bump — zero user-facing change. Tests still 169/169 + 50/50 (cusum) green.
BaseInfinity
added a commit
that referenced
this pull request
May 5, 2026
Codex review of PR #227 caught: `SDLC_HANDOFF_STALE_DAYS=foo` leaked `[: foo: integer expression expected` to stderr before the normal HOLD text. A typo in the env var should silently fall back, not emit shell diagnostics. Fix: non-negative-integer case-pattern guard. Empty, non-numeric, negative, or decimal values fall back to default 14. Test: test_precompact_stale_threshold_invalid_falls_back asserts rc=2, PENDING_REVIEW in stderr, and NO `integer expression` noise. 20/20 precompact tests green. Codex score: 8/10 CERTIFIED (this addresses the sole P2 finding).
BaseInfinity
added a commit
that referenced
this pull request
May 5, 2026
* release: v1.36.0 See CHANGELOG for details. Bumps: - package.json: 1.35.0 -> 1.36.0 - SDLC.md metadata + visible table - CLAUDE_CODE_SDLC_WIZARD.md example version (2 places) - skills/update/SKILL.md example output Latest line - CHANGELOG new section * chore: record E2E score [skip ci] * roadmap(#224-227): follow-ups from Codex review of auto-PRs #210, #213 Four new backlog items surfaced by Codex batch review of the auto-generated PRs (2026-04-23): From PR #210 (CC 2.1.118 auto-update analysis): - #224: runtime test for sdlc-prompt-check.sh double-firing — CC 2.1.118 shipped the fix, we have no assertion it holds. - #225: document cleanupPeriodDays minimum — TodoWrite checklists now fall under that retention sweep (CC 2.1.117). From PR #213 (community patterns, closed): - #226: P1 — weekly-update workflow reports fake 5-trial CI (re-scores one transcript N times, not N simulations). Current STABLE verdicts aren't trustworthy. - #227: stop writing legacy score-history.txt in community PRs. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
BaseInfinity
added a commit
that referenced
this pull request
May 5, 2026
…pdate (#271) Two `cusum.sh --add` calls in weekly-update.yml (version-test + community- e2e-test jobs) appended scores to tests/e2e/score-history.txt, which is tracked by git. Result: every weekly run opened a PR whose only diff was the legacy side-file append — pure noise (Codex finding PR213-02 on auto- PR #213, 2026-04-23). The canonical history is score-history.jsonl, written via the CI Tier 2 persist step in ci.yml. The PR bodies already cite Phase A / baseline scores directly, so removing the standalone CUSUM update steps loses nothing functional. Per Codex consult this session: prefer "stop writing the .txt" over "close PRs with only that diff" (avoids GitHub API edge cases, simpler). New regression test test_weekly_update_does_not_call_legacy_cusum_add in tests/test-workflow-triggers.sh greps for `cusum.sh --add ` (legacy .txt write) and fails if reintroduced. --add-json (canonical .jsonl) is unaffected. Closes #227
BaseInfinity
added a commit
that referenced
this pull request
May 5, 2026
Closes #227 (Codex finding PR213-02). The PR-noise source was the scan-community job appending to legacy score-history.txt via `cusum.sh --add`. #231 Phase 3c (v1.53.0) deleted that whole job, so the noise source is already gone — Test 227 in test-workflow-triggers.sh:2445 is the regression check. Cleanup pass: - Delete empty tests/e2e/score-history.txt from the repo (was a stale runtime artifact, never appended-to since Phase 3c) - Add tests/e2e/score-history.txt to .gitignore (test-cusum.sh recreates it on runs that exercise legacy --add mode) - Drop the stale .txt mention in plans/AUTO_SELF_UPDATE.md (was a Files Structure block listing both .txt and .jsonl; .jsonl is the canonical store now) cusum.sh keeps both modes (--add legacy plain-text + --add-json canonical JSONL) for users who want plain-text mode for ad-hoc CLI work. No interface change. No version bump — zero user-facing change. Tests still 169/169 + 50/50 (cusum) green.
17 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
P1 wizard UX bug found during 2026-04-23 live-fire shepherd session. The precompact-seam-check hook blocked a manual
/compactbecause.reviews/handoff.jsonwas stuck atPENDING_RECHECKfrom the original review that SHIPPED the hook (review_id: precompact-seam-001).That review was written BEFORE the self-heal
pr_numberfeature (ROADMAP #209) existed, so there's no PR to auto-query. The handoff is stuck forever until manually flipped.Every wizard user who did a seam review before #209 has this landmine in their repo.
Fix (shipped in 58d1a86 / d761028)
hooks/precompact-seam-check.shnow has two self-heal paths:pr_numberpresent → querygh pr view, if MERGED treat as implicit CERTIFIED, silent unblockpr_numberAND mtime older thanSDLC_HANDOFF_STALE_DAYS(default 14) → implicit CERTIFIED with one-line WARNPaths are mutually exclusive:
if [ -n "$PR_NUMBER" ] / elsestructure ensures an OPEN PR with an old mtime is still treated as live and blocks.Tests
4 new tests in
tests/test-hooks.sh, all passing (19/19 precompact tests green):test_precompact_unblocks_stale_pending_without_pr_number— stale + no pr → unblock + WARNtest_precompact_still_blocks_fresh_pending_without_pr_number— fresh + no pr → still block (regression guard)test_precompact_stale_with_pr_number_prefers_self_heal— stale + pr OPEN → still block (pr_number wins)test_precompact_stale_threshold_override—SDLC_HANDOFF_STALE_DAYS=0→ all PENDING staleRationale for 14-day default
Power users can tune via
SDLC_HANDOFF_STALE_DAYSenv var.Shepherd loop
test-hooks.sh: 114 passed (1 pre-existing failure on main, unrelated).reviews/latest-review.mdwhen complete)