fix(sdlc): resolve reform-complete predicate through the gate shim + test gatherer boundary + repoint timer#3842
Conversation
…test the gatherer boundary + repoint the timer The #3833 reform-complete predicate grepped cc-task-gate.sh for is_cognition_path / escape_grant_allows / _record_retro_grant_obligation / DEPRECATED, but #3832 moved those into cc-task-gate.impl.sh and left cc-task-gate.sh a thin HAPAX-GATE-SHIM. So canonical-gate (INV-5), escape-grant and off-deprecation reported permanent FALSE-NEGATIVE FAILs — they could never enter passed_ever, blinding --regression-only exactly when a silent revert matters (the 3rd merged-vs-realized cycle, in the tool meant to detect them). - Add _resolve_gate_text(): if a gate is a HAPAX-GATE-SHIM, resolve to the real impl mirroring the shim's own order (deployed canonical $HAPAX_CANONICAL_HOOKS first, then co-located cc-task-gate.impl.sh), skipping a candidate that is itself a shim. Wire it into _has_inv5 / gather_escape_grant / gather_off_deprecation. shadow-cutover keeps reading the RAW gate deliberately: the only policy_decide token in the impl is a non-enforcing comment, so resolving would false-positive the genuinely-incomplete 3b cutover. The raw-shim sha (live_matches_repo) is unchanged — it operates on the shim layer, complementary to INV-5 presence on the resolved impl. - Add TestShimResolution: drives the gatherers against a materialized shim+impl pair (the boundary the decider-only tests never exercised); fails if a gatherer reads only the shim. Honest-negative cases (no resolvable impl -> False) asserted too. - Repoint hapax-reform-complete.service ExecStart off the stale primary worktree onto the deploy worktree (%h/.cache/hapax/rebuild/worktree) + ConditionPathExists, fixing the same hardcoded-primary-worktree hazard as #3839. The 6h timer auto-enables on merge via its existing Hapax-Auto-Enable marker; --verify-auto-enable already detects + loudly fails a missing install. Live: canonical-gate, escape-grant, off-deprecation now PASS (resolving through impl/canonical); only coord-verbs remains an honest red. 50 tests, ruff, pyright green. Timer install/enable + scheduled-run watermark population are realized via the deploy chain (reform-deploy-chain-repair, #3840) on merge, mirroring #3839's deferral. Task: reform-complete-predicate-fix-20260601 AuthorityCase: CASE-SDLC-REFORM-001 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR introduces shim-aware gate-file resolution to avoid false negatives when checking for deployment markers in shimmed ChangesShim-aware gate resolution and service integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fdd1704bb4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for candidate in ( | ||
| _canonical_hooks_dir() / "cc-task-gate.sh", | ||
| path.parent / "cc-task-gate.impl.sh", |
There was a problem hiding this comment.
Read repo shims from their colocated impl
When this helper is used for repo_gate (and lane gates), preferring $HAPAX_CANONICAL_HOOKS/cc-task-gate.sh masks regressions in the checkout under test: if the deployed canonical gate still contains is_cognition_path but the current repo's hooks/scripts/cc-task-gate.impl.sh has been reverted or is missing, _has_inv5(repo_gate) still returns true. I checked hooks/scripts/hooks-doctor.sh and the deploy path installs the repo impl as the canonical gate, so the predicate needs to verify the colocated repo impl for repo-source checks rather than the already-deployed copy, otherwise canonical-gate can pass while the source that will be deployed is broken.
Useful? React with 👍 / 👎.
| if SHIM_MARKER not in ctext: | ||
| return ctext |
There was a problem hiding this comment.
Follow canonical shims before falling back locally
When $HAPAX_CANONICAL_HOOKS points at a different shim directory, this skips that canonical shim and falls back to the original checkout's colocated impl, but the real hooks/scripts/cc-task-gate.sh only skips the canonical path when it is the same inode and otherwise execs it. In the misconfigured or partially deployed case where the canonical shim has no colocated impl, the live hook fails open, while this resolver reads the caller's local impl and reports INV-5/escape/off-deprecation as wired, so the regression detector can pass exactly the bad canonical-shim state it is meant to catch.
Useful? React with 👍 / 👎.
| # absent) code — the same hardcoded-primary-worktree hazard fixed for | ||
| # hapax-sdlc-invariants.service in #3839. The rebuild worktree tracks deployed main and | ||
| # is rebuilt idempotently by hapax-post-merge-deploy. | ||
| ExecStart=/home/hapax/.local/bin/uv run --directory %h/.cache/hapax/rebuild/worktree python scripts/hapax-reform-complete --regression-only |
There was a problem hiding this comment.
Keep live/source comparison off the deploy cwd
With the timer now running the script from %h/.cache/hapax/rebuild/worktree, REPO_ROOT inside hapax-reform-complete is the same deploy worktree that the LIVE_GATE constant points to, so gather_canonical_gate() hashes the same hooks/scripts/cc-task-gate.sh file for both live_sha and repo_sha. In the scheduled regression-detector context, a rebuild-worktree gate drift therefore makes live_matches_repo stay true instead of reporting the divergence the canonical-gate check is documented to catch.
Useful? React with 👍 / 👎.
Reform fix — reform-complete predicate false-negatives + uninstalled regression timer
The #3833 mechanical "is the coordination reform realized?" predicate was itself doubly broken — the THIRD merged-vs-realized drift, in the tool meant to detect them.
Root cause (reproduced live before fixing)
scripts/hapax-reform-completegreppedcc-task-gate.shforis_cognition_path,escape_grant_allows,_record_retro_grant_obligation,DEPRECATED. But #3832 collapsed that file into a thinHAPAX-GATE-SHIMand moved every marker intocc-task-gate.impl.sh(deployed canonical at$HAPAX_CANONICAL_HOOKS). So canonical-gate (INV-5), escape-grant, off-deprecation reported permanent FALSE-NEGATIVE FAILs — they could never enterpassed_ever, blinding--regression-onlyexactly when a silent revert matters.Live before:
Live after:
Changes
_resolve_gate_text()— resolves aHAPAX-GATE-SHIMto its real impl, mirroring the shim's own order (deployed canonical first, then co-locatedcc-task-gate.impl.sh), skipping a candidate that is itself a shim. Wired into_has_inv5/gather_escape_grant/gather_off_deprecation. Returns the shim text verbatim when no impl resolves, so a truly-missing impl stays an honest failure.shadow-cutoverdeliberately NOT resolved — the onlypolicy_decidetoken in the impl is a non-enforcing comment (a shadow-replay pointer); resolving would false-positive the genuinely-incomplete 3b cutover. It stays honest, passing onpredicate_reachable. (Inline comment documents this so a future "consistency fix" doesn't reintroduce the false positive.)TestShimResolution(8 tests) — drives the gatherers against a materialized shim+impl pair (the boundary the decider-only tests never exercised); fails if a gatherer reads only the shim. A reverted-resolver simulation confirms the 3 gatherer tests fail (genuine regression guard, not vacuous).hapax-reform-complete.service— ExecStart repointed off the stale primary worktree (%h/projects/hapax-council, which floats on feature branches) onto the deploy worktree (%h/.cache/hapax/rebuild/worktree) +ConditionPathExiststo convert a 203/EXEC crashloop into a clean skip. Same hardcoded-primary-worktree hazard fixed forhapax-sdlc-invariants.servicein fix(sdlc): activate inert INV-1..5 trace-checker + unify auto-mint onto the live escape-grant contract #3839.Acceptance criteria
hapax-reform-complete.timerenabled + scheduled — realized via the deploy chain on merge (the# Hapax-Auto-Enable: truemarker;--verify-auto-enablealready detects it and fails the deploy loudly when not enabled). Mirrors fix(sdlc): activate inert INV-1..5 trace-checker + unify auto-mint onto the live escape-grant contract #3839's deferral; gated onreform-deploy-chain-repair(fix(sdlc): repair severed post-merge-deploy chain — origin/main trigger, cumulative deploy, re-arm + alarms #3840).passed_everrecords canonical-gate + escape-grant — mechanism demonstrated in-session (fixed run records them); durably populated by the first post-deploy scheduled run. The live watermark is left at the deployed-predicate-consistent state to avoid a stale-code false-regression window.Verification
pytest tests/test_reform_complete.py→ 50 passedruff check+pyright→ cleanhapax-reform-completerun → 3 false-negatives now PASS, no new false positivesTask:
reform-complete-predicate-fix-20260601· AuthorityCase: CASE-SDLC-REFORM-001🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Improvements
Tests