Skip to content

feat(hydra-gates): gate 122 holds changed units to the SIG 4-star bounds - #871

Merged
rubenvdlinde merged 3 commits into
mainfrom
feat/gate-122-sig-maintainability
Oct 29, 2026
Merged

rubenvdlinde merged 3 commits into
mainfrom
feat/gate-122-sig-maintainability

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What

Gate 122, sig-maintainability, measures what the Software Improvement Group (SIG) rates: unit size, McCabe complexity, parameters and duplication, per language. It runs on PHP, JavaScript, TypeScript, Vue and Python.

  • With a delta base it ratchets. A unit the change adds or makes worse is a finding above NLOC 60, McCabe 10 or 4 parameters. So is a new duplicated fragment of 6 or more code lines. A unit that was already over and did not get worse is inherited, and so is everything the change did not touch.
  • Without a base it reports. It writes the full SIG risk profile against the 4-star limits as sig-profile.json and sig-profile.md: unit size, complexity, interfacing, duplication, module coupling, component independence and the two entanglement inputs. Report-only, it passes with a census line.
  • Duplication in the report follows SIG's line definition: every later copy of 6 code lines equal modulo whitespace. jscpd's pairwise figure is shown beside it. On openregister PHP that is 8.8% against jscpd's 2.7%, because jscpd pairs clones and needs 30 tokens.

It ships as a warning, like every new gate. HYDRA_GATE_SIG_MAINTAINABILITY_BLOCKING=1 makes it block.

Why

Our phpmd runs at its own defaults with baselines, so a green phpmd is not a green SIG profile. On 2026-10-29 openregister kept 16.5% of its PHP in units over 60 lines, against a limit of 8.3%. SIG will assess openregister, opencatalogi, integriq, filinq and anonymiq.

How it measures

  • lizard 1.24.3 and jscpd 4.0.5, pinned. The first run installs them into ~/.cache/hydra-gates/tools (or $HYDRA_GATE_TOOLS_DIR). Any other version is refused. HYDRA_GATE_SIG_NO_INSTALL=1 forbids the install.
  • PHP parameters are counted from the unique $names, because lizard keeps only the last one. Python self and cls do not count.
  • Each file is analysed on its own with a time limit. A file lizard raises on is listed as not measured. openconnector's src/components/LtiPlatformDetails.vue is one.
  • A clone counts the code lines that are literally equal modulo whitespace, as SIG does. jscpd alone reported a docblock-spanning "13-line" clone on openregister #5008 that held five equal code lines.
  • Scope is Sigrid's own default exclude list (vendored), plus test code, js/ and l10n/, plus a sigrid.yaml at the root if there is one.

Verified

  • python3 scripts/lib/test_check_sig_maintainability.py: 23 tests, exit 0. Mutation-checked: breaking the worse-than-base rule, the clone threshold, the clone line filter, the report's line-window duplication, the PHP parameter fix or the Python self rule each turns a test red.
  • bash scripts/lib/test_gate122_sig_maintainability_scope.sh: 6 arms through the real runner (warning, blocking switch, census line, report mode, not applicable, missing tool), exit 0.
  • test-hydra-gates-bin.sh, test_gate_acceptance_matrix.sh, test_gate_errexit_discipline.sh, test_gate_numbers_unique.sh: exit 0. In run-helper-suites.sh locally, test_check_connections_declaration.js fails because Ajv is not installed on this machine, which has nothing to do with this change. ShellCheck at warning level on the runner and the new suite: exit 0.
  • Replayed on a real change: openregister HEAD~5..HEAD names AuditTrailMapper::findAll growing from NLOC 117 to 121 and McCabe 20 to 21 (#5005), and lists 21 inherited findings. Took 177 s, mostly jscpd over the PHP corpus.
  • Report mode on fresh clones of all five SIG apps. openregister takes about 3.5 minutes and 1.6 GB, the others under a minute.

Notes for review

  • lizard 1.24.3 was published on 2026-10-24, five days ago. It was pinned on purpose to match the baseline, but it is younger than the fleet's usual cooldown.
  • Entanglement is reported as density and violation degree. SIG normalises them with benchmark numbers it does not publish, so the 0.077 limit is not checked.
  • The nightly wiring (job summary and artifact on the drift sweep's dispatch) is a separate PR on quality.yml. The skill file is a separate PR in hydra.

🤖 Generated with Claude Code

SIG rates maintainability from risk profiles per language. Our phpmd
runs at its own defaults with baselines, so a green phpmd is not a green
SIG profile: openregister keeps 16.5% of its PHP in units over 60 lines
against a limit of 8.3%.

With a delta base the gate ratchets: a unit the change adds or makes
worse fails above NLOC 60, McCabe 10 or 4 parameters, and so does a new
duplicated fragment of 6+ lines. Findings on untouched or unworsened
units are inherited. Without a base it writes the full SIG risk profile
(unit size, complexity, interfacing, duplication, module coupling,
component independence, entanglement inputs) as sig-profile.json and
sig-profile.md, report-only.

lizard 1.24.3 and jscpd 4.0.5 are pinned and installed into the tool
cache. PHP parameters are counted from the unique $names, Python self
and cls are not parameters, and a file lizard raises on is listed as
not measured. Scope follows Sigrid's default excludes plus sigrid.yaml.

Ships as a warning; HYDRA_GATE_SIG_MAINTAINABILITY_BLOCKING=1 blocks.
… lines

jscpd matches tokens and skips comments, so a fragment it reports can
span a docblock and match its first and last line only in part. Replayed
on openregister #5008 that read as a 13-line clone holding five equal
code lines. SIG counts code lines repeated literally modulo whitespace,
so both fragments' code lines are now paired in order and a clone needs
six equal ones, in the ratchet and in the report.
jscpd reports clones pairwise and needs 30 tokens, so on openregister's
PHP its literally equal lines came to 2.7% of code, where windows of six
equal code lines come to 8.8%. The report now measures duplication the
way SIG defines it, every later copy of six code lines equal modulo
whitespace, and keeps jscpd's figure beside it as duplication_jscpd.
The ratchet still uses jscpd's clones.
@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Related: nightly wiring in #872, skill file in ConductionNL/hydra#759.

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.

1 participant