Skip to content

feat(hydra-gates): gate 123, a per-app SIG score floor checked on every change - #891

Merged
rubenvdlinde merged 3 commits into
mainfrom
feat/gate-123-sig-floor
Nov 2, 2026
Merged

rubenvdlinde merged 3 commits into
mainfrom
feat/gate-123-sig-floor

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What

Gate 123 (sig-floor): a per-app SIG score floor, checked on every change. Openspec change: openspec/changes/gate-123-sig-floor/.

  • .github/sig-floor.json in an app lists the SIG 4-star checks it meets, under gate 122's check names (php unit_size >30, vue duplication, php component_independence, ...). check_sig_floor.py write . generates it.
  • On a change, the gate measures the head and the merge base with gate 122's report (same scope, same sigrid.yaml excludes, lizard 1.24.3). The floor is the file read at the base plus every check the base meets, so a change cannot lower its own floor and cannot lose a check development reaches before the file lists it.
  • A floored check the head misses fails and is named with its share and limit. A check development already misses is inherited unless the change makes it worse.
  • The 5-star checks (half of each 4-star limit) go to the step summary and never block.
  • sig-floor-raise: after a push to development that meets more checks, a job opens a pull request that changes only the floor file. The org ruleset refuses a direct push, so a pull request is the route. The job declares no permissions and inherits the caller's grant (humaniq grants no pull-requests write, so there it pushes the branch and warns).
  • Unit cache keyed by file content, restored with actions/cache/restore; only pushes save, so pull requests read development's cache.
  • No-op for an app without a floor file (NOT APPLICABLE).

build_report in gate 122 gains an optional unit reader and can skip the jscpd cross-check; its output is unchanged.

Verified locally

  • test_check_sig_floor.py: 15 tests OK. Capped mutants on the verdict logic (base-met guard, inherited vs worse, lowered file, floor read from the base, proposal only on a pass): all killed; no-op control survives.
  • test_gate123_sig_floor_scope.sh through the real runner: all 4 arms pass (planted FAIL naming the check, refactor PASS with census and sig-floor.md, no floor NOT APPLICABLE, missing tools SKIPPED wiring).
  • test_check_sig_maintainability.py (30 OK) and test_gate122_sig_maintainability_scope.sh (all arms) still pass.
  • Shared-workflow guards run locally on the new quality.yml: run-step size, report needs, producer-deletes-verdict, seed, sibling token, shard partition, test counts, e2e trigger, consolidated legs all pass. test-changed-path-filter.py is 12/14 on main too (inherited; test(quality): give the changed-path filter suite the push env #881 reads #884 addresses it).
  • On a real app (larpinq, local branches only): sixteen new 44-line units pass gate 122 (no unit over 60) and fail gate 123 on php unit_size >30: 24.3% > limit 23.1%; met at the base (16.5%).

AI-assisted: written with Claude Code (claude-opus-5-5).

… reports 5-star

check_sig_floor.py measures the head and the merge base with gate 122's report and fails when a check in the floor is lost. The floor is .github/sig-floor.json read at the base plus every check the base meets, so it only rises. 5-star misses go to the step summary and never block. Units are cached by content; a sig-floor-raise job offers the raised floor as a pull request after a push to development.

Assisted-by: ClaudeCode:claude-opus-5-5
class Raise(FloorCase):
def setUp(self):
super().setUp()
self.proposed = tempfile.mktemp(suffix=".json")
… leave only through sigrid.yaml

An app without a floor file is NOT APPLICABLE before any tool is loaded or base resolved. A floored check the head no longer measures fails unless the change edits sigrid.yaml, or the base no longer measured it either. The raise proposal keeps committed checks the head misses. Tests pin the 4-star boundaries, equal shares as not worse, and the scope rule. ShellCheck SC2016 is disabled on the PHP template line.

Assisted-by: ClaudeCode:claude-opus-5-5
@rubenvdlinde
rubenvdlinde merged commit 30d6ed0 into main Nov 2, 2026
46 of 50 checks passed
This was referenced Nov 2, 2026
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.

2 participants