Skip to content

refactor(hooks): consolidate hooks.json description into ssot.json registry - #1223

Merged
tvna merged 3 commits into
mainfrom
claude/issue-1222-hooks-json-ssot-consolidation
Aug 19, 2026
Merged

refactor(hooks): consolidate hooks.json description into ssot.json registry#1223
tvna merged 3 commits into
mainfrom
claude/issue-1222-hooks-json-ssot-consolidation

Conversation

@tvna

@tvna tvna commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Summary

Shrinks hooks/hooks.json's top-level description field to a pointer at
.gitapex/ssot.json's gates[] registry (the already-established single
source of truth for gate rationale), and registers the one hook script the
registry was missing: hooks/check-merge-pull-request-block.sh (issue
#637), so no rationale is lost in the consolidation.

Facts

Assumptions

  • None outstanding -- this is a mechanical registry/documentation
    consolidation with no behavior change; every claim above was independently
    verified against live repo state, not assumed.

Risk / blast radius

Confined to two prose fields (hooks/hooks.json's description,
.github/scripts/gitapex_detect_changed_gate_scripts.py's docstring) and
one new, schema-valid .gitapex/ssot.json registry entry for an
already-active, unchanged hook script. No command, matcher, timeout,
or detection-logic value changed anywhere in this diff. Worst case if the
new registry entry were somehow wrong: hooks/check-merge-pull-request-block.sh
itself is untouched and keeps denying mcp__github__merge_pull_request
exactly as before -- only the registry's own bookkeeping about it could be
affected, not runtime behavior.

Rollback

git revert this PR's merge commit. No schema change, no data migration,
nothing else depends on the new registry entry existing.

Verification

Restated from the Acceptance Criteria Map in issue #1222, criterion ->
proof method -> result:

Criterion Proof method Result
hooks/hooks.json's description stops duplicating per-gate rationale No gate/test asserts on this field's content (verified); gitapex_detect_changed_gate_scripts.py still flags the diff correctly (path-based, unchanged behavior) Done.
Every wired hook script has a .gitapex/ssot.json entry tests/test_gitapex_scan_ssot_schema.py passing on the new entry Done.

Full local verification: uv run pytest (5162 passed; 2 pre-existing,
environment-only failures individually confirmed as flakes via a one-time
re-run each and deselected from the full-suite pass --
test_repository_workflows_are_drift_free needs full git history this
shallow clone lacks; test_does_not_dirty_the_real_checkouts_settings_json
failed only on a byte-level trailing-newline difference in
.claude/settings.json, produced by the sandbox's own plugin-registration
side effects and confirmed clean, with no dirtying, on immediate re-run in
isolation -- both unrelated to this diff), uv run ruff check . (clean),
mypy (the tests/.github/scripts-covering group, clean, 217 source
files). tests/test_gitapex_scan_ssot_schema.py and
tests/test_gitapex_detect_changed_gate_scripts.py specifically re-run and
green. One drift-check (test_no_prose_count_contradicts_the_registry)
correctly caught its own staleness from the new registry entry (26 -> 27
exclusions) and was fixed in the same commit as the entry itself.

Post-merge update: origin/main (PR #1215, issue #1197's own new
pr-duplicate-issue gate) merged into this branch, producing a real
content conflict in hooks/hooks.json's description field. Resolved by
keeping this PR's short pointer text -- still fully accurate, since it
names no gate-specific content and .gitapex/ssot.json auto-merged
cleanly with both PRs' new entries intact. The same drift-check caught a
second, real staleness from that merged-in entry (27 -> 28 exclusions),
fixed in a follow-up commit. Re-verified after both commits: full local
suite (5255 passed, only the shallow-clone-only
test_repository_workflows_are_drift_free deselected), uv run ruff check . (clean), the same CI mypy group (clean, 223 source files),
and the two most directly relevant test files re-run individually
(253 passed). CI's own pytest job separately hit the known
test_installs_the_prek_hook_for_a_real_checkout session-start.sh
15s-timeout flake (already independently confirmed flaky on PR #1215);
re-run via rerun_failed_jobs rather than a code change.

Skill audit evidence

One deterministic gate registration (.gitapex/ssot.json) and one
deterministic checker-script docstring fix
(.github/scripts/gitapex_detect_changed_gate_scripts.py, prose-only, zero
detection-logic lines changed) are in this diff; no skills/*/SKILL.md or
docs/superpowers/specs/*.md design doc is touched. The post-merge
follow-up commit touches only tests/test_gitapex_gate_local_preflight.py
(a drift-check's own docstring count), outside every named trigger scope
below -- no new disclosure obligation (independently confirmed by running
.github/scripts/gitapex_compute_skill_audit_flags.py --base-ref origin/main --head-ref HEAD locally: identical changed-checker-scripts/
changed-gate-scripts sets as the original commit).

  • deterministic-gate-quality: RAN (dispatched a fresh, independent audit
    against this diff's .gitapex/ssot.json registration, hooks/hooks.json
    description edit, and hooks/check-merge-pull-request-block.sh itself as
    newly brought into registry visibility, read against
    skills/evaluating-deterministic-gate-quality/references/dimensions.md).
    Verdict: well-formed and well-placed. Live-verified via direct script
    execution (deny/pass-through/malformed-stdin cases), a live
    gitapex_scan_ssot_schema.py run, and the full local test suite. Found
    and fixed one real, live-verified defect in the same commit: gitapex_detect_changed_gate_scripts.py's
    own docstring still claimed this hook was "unregistered today" -- false
    as of this PR's own registration, corrected to past tense with an issue
    citation. Two additional low-severity, pre-existing (not
    diff-introduced) maturity gaps disclosed, not fixed, since the hook
    script's own logic is unchanged here: dimension 15 (malformed/empty
    stdin exits 0 rather than deny, steel-manned as low-severity since stdin
    here is harness-controlled, not attacker-reachable) and an undisclosed
    cross-reference gap between this hook and the platform's own
    .github/rulesets/main.json branch-protection floor (a real,
    independently-confirmed complementary layer neither document names).
    Dispatch-isolation caveat, disclosed by the dispatch itself: this
    sandboxed environment could not exclude this repository's own CLAUDE.md
    from the dispatched agent's own context -- a hygiene deviation judged
    unlikely to have biased the verdict (generic process instruction, not
    opinion about this specific diff) but flagged rather than silently
    accepted.
  • checker-script-adversarial-review: NOT-RUN -- this diff's only touch to
    a .github/scripts/*.py file is a one-line docstring correction (a
    previously-accurate claim about check-merge-pull-request-block.sh's
    registration status, now stale after this same PR registers it); zero
    lines of gitapex_detect_changed_gate_scripts.py's actual detection
    logic changed (confirmed via git diff), so there is no logic here for
    an adversarial review round to meaningfully target.
  • defeat-test-disclosure: NOT-RUN -- required via its union with
    deterministic-gate-quality's own scope, but hooks/check-merge-pull-request-block.sh's
    own detection logic is unchanged by this diff (only its
    .gitapex/ssot.json registration is new); per this check's own
    documented design intent, a docstring-or-registration-only edit with no
    new/changed detection logic has nothing for a defeat test to
    meaningfully target.

Execution log

Checklist

  • Tests pass locally
  • Docs updated if behavior changed
  • Issue number cited in every commit
  • If this PR adds/modifies a skills/*/SKILL.md, a docs/superpowers/specs/*.md design doc, a security-relevant skill, or a deterministic checker script (skills/*/scripts/*.py, evals/scripts/*.py, .github/scripts/*.py), a ## Skill audit evidence section discloses the required verdicts/waivers (see .github/scripts/gitapex_gate_skill_audit_disclosure.py)
  • If this PR adds a new Kept-edit-log entry to any evals/*/split.md, that entry discloses a Transfer check line -- not applicable, no evals/*/split.md change
  • If this PR adds or increases a skills/*/SKILL.md's Stop-boundary bullets or named dispatch branches, evals/<skill>/tasks/*.yaml gained at least as many new fixtures -- not applicable, no SKILL.md change

Related Issue

Closes #1222

…gistry

hooks/hooks.json's top-level description field had grown into a
duplicative changelog citing every gate's own issue number, content
already tracked structurally in .gitapex/ssot.json's gates[] registry.
Shrink it to a pointer at that registry, and close the one real gap a
plain shrink would have hidden: hooks/check-merge-pull-request-block.sh
(issue #637) had no ssot.json entry at all. A deterministic-gate-quality
audit of this diff found one real defect, fixed in the same commit: a
stale "unregistered today" claim about this same script in
gitapex_detect_changed_gate_scripts.py's own docstring.

Refs #1222
@tvna
tvna deployed to ruleset-verify August 19, 2026 09:35 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 027daf8e-0e99-4275-b76d-74dfe298355d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 94612ea6-ae48-45a1-9f50-06bab331aac2

📥 Commits

Reviewing files that changed from the base of the PR and between 3e40388 and dd199da.

📒 Files selected for processing (4)
  • .gitapex/ssot.json
  • .github/scripts/gitapex_detect_changed_gate_scripts.py
  • hooks/hooks.json
  • tests/test_gitapex_gate_local_preflight.py

Included review availability: Your plan provides up to 3 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The pull request adds the merge-pull-request-block gate to the registry. It points hook metadata documentation to .gitapex/ssot.json and updates related preflight documentation.

Changes

Gate registry consolidation

Layer / File(s) Summary
Register merge pull request gate
.gitapex/ssot.json
Adds the active gate definition for denying mcp__github__merge_pull_request during PreToolUse.
Align gate metadata documentation
hooks/hooks.json, .github/scripts/..., tests/test_gitapex_gate_local_preflight.py
Points gate metadata to .gitapex/ssot.json, documents the resolved registration gap, and updates the exclusion count to 27.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to dd199

This PR consolidates registry documentation without changing hook runtime behavior, and the required audit disclosure is present. No actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement the requested registry entry, description pointer, stale documentation update, and preservation of hook runtime behavior for issue [#1222].
Out of Scope Changes check ✅ Passed All changes support issue [#1222] and do not modify hook commands, matchers, timeouts, or unrelated functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 30.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: consolidating the hooks.json description into the ssot.json registry.

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.49%. Comparing base (3f73cc4) to head (e65ddf0).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1223   +/-   ##
=======================================
  Coverage   99.49%   99.49%           
=======================================
  Files         111      111           
  Lines       20104    20104           
  Branches     2361     2361           
=======================================
  Hits        20003    20003           
  Misses        101      101           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

claude added 2 commits August 19, 2026 09:53
…ks-json-ssot-consolidation

# Conflicts:
#	hooks/hooks.json
Merging origin/main (PR #1215, issue #1197's pr-duplicate-issue gate)
into this branch raised .gitapex/ssot.json's excluded-gate count from
27 to 28. test_no_prose_count_contradicts_the_registry correctly
caught test_every_unwired_gate_records_why's now-stale docstring claim.

Issue #1222.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(hooks): consolidate hooks.json description into ssot.json gate registry

2 participants