Skip to content

guard: wire 4 orphaned gate tools into CI + document 9th hook check - #712

Open
matt82198 wants to merge 3 commits into
mainfrom
guard/wire-orphan-gates
Open

guard: wire 4 orphaned gate tools into CI + document 9th hook check#712
matt82198 wants to merge 3 commits into
mainfrom
guard/wire-orphan-gates

Conversation

@matt82198

Copy link
Copy Markdown
Owner

What

Gate inventory (PR #709) confirmed four guardrail tools on main invoked by nothing — unit-tested, documented in tools/CLAUDE.md, grading zero real code. This wires the three that are semantically applicable to this repo's CI, and records the fourth as deliberately unwired rather than softening it.

Per-tool verdict (run against a clean origin/main worktree)

Tool Local exit Output Disposition
sibling_import_check.py --check 0 Sibling import check: CLEAN Wired — shard-0 CI gate
fixture_intent_check.py --root . 0 OK: 4 fixtures tracked and valid Wired — shard-0 CI gate
port_fidelity_check.py --check --root . 0 port-fidelity-check: PASS (143 files, 0 findings) Wired — shard-0 CI gate
git_identity_check.py --repo . 2 Error: Must provide --expect-name/--expect-email or --config NOT wired — see below

Why git_identity_check.py stays unwired

It is neither bitrot nor a real finding — it is inapplicable to this repo's CI, the same class as tracker_guard (which lives in the pre-push hook, not CI, for the analogous reason).

  • The tool validates a repo's --local user.name/user.email (git config --local, plus a physical .git/config read).
  • There is no aesop.config.json in the repo and aesop.config.example.json has no identity block, so there is nothing for --config to read; expectations would have to be hardcoded into the workflow.
  • A GitHub Actions runner clone sets only a --global identity (ci.yml step "Configure git" sets --global user.name "CI Runner"). Verified against a simulated CI-style repo with global-only identity:
$ python tools/git_identity_check.py --repo . --expect-name "CI Runner" --expect-email "ci@example.com" --mode fail
EXIT=1
Git identity validation failed for .:
  - user.name mismatch: expected 'CI Runner' but git has 'None'
  - user.email mismatch: expected 'ci@example.com' but git has 'None'

Wiring it would be permanently red. The two ways to make it green — --mode warn (exit 0 unconditionally) or continue-on-error: true — both recreate the exact decoration this sweep exists to remove, and ci_gate_runability.py already rejects continue-on-error on required gates. Its real enforcement point is an aesop-managed target repo, not aesop's own CI. Left unwired, recorded in DELIBERATELY_UNWIRED with the reason, and asserted by the inventory test so it cannot be forgotten.

Doc fix

hooks/CLAUDE.md documented 8 pre-push checks; hooks/pre-push-policy.sh main() gates 9. check_test_suite_count() (runs verify_test_suite_count.py --check between check_metrics and check_encoding_lint) was undocumented. Added as item 8 with its fail-open conditions (test_suite_count_skipped_tool_missing, test_suite_count_skipped_no_python); subsequent items renumbered.

Tests

tests/test_ci_workflow_lint.py::GuardrailGateWiringTest extended:

  • the three invocations added to CI_GATE_INVOCATIONS (covered by the existing "wired" + "uncommented run command" assertions);
  • test_orphan_sweep_steps_exist_with_expected_invocations — each step exists by name and runs exactly its check command;
  • test_orphan_sweep_steps_are_real_enforcement — shard-0 scoped (the checks are shard-invariant) and never continue-on-error;
  • test_orphan_inventory_fully_accounted_for — each of the four inventory tools is either wired or explicitly excepted, never both.

Verification

python tools/verify_gates_wired.py        -> 0  OK: All documented CI gates are wired
python tools/ci_gate_runability.py        -> 0  [OK] All CI gates are runnable on PR events
python tools/workflow_model_linter.py     -> 0
python tools/ci_workflow_lint.py          -> 0  OK: All workflow checks passed
python tools/claudemd_lint.py --root .    -> 0  [OK] No issues found
python tools/claudemd_sync_gate.py --check-> 0  [OK] No changes detected
python tools/verify_test_coverage.py      -> 0  All test files are covered by CI runners
python tools/verify_test_suite_count.py   -> 0  [OK] Test suite counts match
python -m unittest tests.test_ci_workflow_lint -> Ran 32 tests, OK
python tools/secret_scan.py --staged      -> 0  CLEAN

Pre-push hook battery passed on push (no bypass flags used).

🤖 Generated with Claude Code

Gate inventory (PR #709) found four guardrail tools on main invoked by
nothing -- unit-tested, documented, grading nothing. Three are wired as
real shard-0 CI gates; the fourth is recorded as deliberately unwired.

- sibling_import_check.py --check
- fixture_intent_check.py --root .
- port_fidelity_check.py --check --root .

git_identity_check.py stays unwired: its subject is a managed target
repo's *local* git identity, and a GitHub Actions runner clone sets only
a --global one, so it reports mismatch on every CI run (verified exit 1).
Softening it with --mode warn or continue-on-error would recreate the
decoration this sweep removes.

hooks/CLAUDE.md documented 8 pre-push checks while pre-push-policy.sh
runs 9 -- check_test_suite_count() was undocumented. Added and renumbered.

tests/test_ci_workflow_lint.py gains four assertions: the steps exist
with exact invocations, they are shard-0 scoped and never
continue-on-error, and every tool in the orphan inventory is either
wired or explicitly excepted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@matt82198

Copy link
Copy Markdown
Owner Author

Evicted from the merge queue: batch #736 (integrate/q-1785730980) red with every member individually green

@matt82198

Copy link
Copy Markdown
Owner Author

Holding as queue-rejected until #724 lands. Root cause of the merge-queue stall (batches #727/#729/#730/#731/#732/#733/#736/#737 all dissolved): this PR adds the 'Sibling import guard' step to .github/workflows/ci.yml, wiring import_resolution_check as a hard gate. On main that checker does not yet recognize the sanctioned sys.path idiom, so it reports 2 violations in tools/merge_queue.py (lines 68-69, from merge_train import gh, git / from common import get_state_dir) and fails ci (0) on every integration branch. This PR's own green check predates tools/merge_queue.py landing on main, so it reads individually-green while poisoning every batch it joins. #724 (guard/import-check-syspath-idiom) teaches the checker that idiom -- land it first, then re-admit this one.

@matt82198 matt82198 added the merge-queue Queued for the merge-queue advancer daemon label Aug 3, 2026
@matt82198 matt82198 removed the queue-rejected Evicted from the merge queue (red or culprit) label Aug 4, 2026
@matt82198 matt82198 added queue-rejected Evicted from the merge queue (red or culprit) and removed merge-queue Queued for the merge-queue advancer daemon labels Aug 4, 2026
@matt82198

Copy link
Copy Markdown
Owner Author

Evicted from the merge queue: batch #766 (integrate/q-1785803317) red with every member individually green

@matt82198 matt82198 added merge-queue Queued for the merge-queue advancer daemon and removed queue-rejected Evicted from the merge queue (red or culprit) labels Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-queue Queued for the merge-queue advancer daemon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant