Skip to content

feat(hydra-gates): gate 119 procedure-code ratchet (decision 182) - #838

Merged
rubenvdlinde merged 4 commits into
mainfrom
feat/gate-119-procedure-code
Oct 12, 2026
Merged

rubenvdlinde merged 4 commits into
mainfrom
feat/gate-119-procedure-code

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

DO NOT MERGE before every fleet app has a .procedure-code-baseline.json

The gate reports NOT APPLICABLE (never PASS) for an app without a baseline. Merged early, the fleet would read NOT APPLICABLE for a rule it believes is enforced. The coordinator opens the baseline PRs in the apps once this is approved; the table below is the number each file should carry.

What it is

Gate 119, procedure-code, for decision 182 (Ruben, 10 Oct 2026): procedures are configuration, code is generic.

Per app it counts PHP, JS, TS and Vue files under lib/ and src/ whose repo-relative path, or a class/interface/trait/enum declared inside, carries a Dutch procedure token. It holds the count to .procedure-code-baseline.json ({"count": N}) at the app root, as the custom-widget ratchet (gate 29) does:

State Verdict
no baseline file NOT APPLICABLE, never PASS
count above baseline FAIL, the change added procedure-named code
count below baseline FAIL until the same PR lowers the baseline; the message gives {"count": N}
count equals baseline PASS
baseline raised against --base FAIL, the baseline only goes down
baseline not valid JSON FAIL
checker cannot run or config unreadable SKIPPED (wiring), never a finding

Not a delta gate: the count is of the whole tree against the committed number, so it also judges full-scope runs. A base only adds the baseline-raised check.

One config file

hydra-gates/scripts/lib/procedure_code_tokens.json holds everything configurable: roots, extensions, the 17 tokens, and the allowlist.

  • substringTokens: bezwaar, beschikking, subsid, termijn, besluit, leerplicht, verlof, melding, klacht, jeugd, bijstand, omgevings (matched anywhere in the lowercased path or class name).
  • wordTokens: woo, vth, dso, wmo, leges (whole word only after camelCase/kebab/snake splitting, so WoodService and Dsonar.vue do not count, WOOPublication and woo-publication.vue do).
  • allow.words: zgw, ztc, zrc, drc, stuf, brp, kvk, dso-adapter (a hyphenated entry is a word run, so Dso/Adapter.php is excused but DsoMelding.php is not).
  • allow.pathPrefixes: lib/Adapter, lib/Service/Zgw. This is how an ambiguous token like dso is excused: by where the file lives. lib/Adapters/ is not lib/Adapter/.

Numbering

Next free number is 119. 117 is in #782 and 118 in #836; no other open PR or remote branch claims 119. check_gate_numbers_unique.sh: 97 gates, every number claimed once. This branch is cut from main and does not include #782 or #836, so the runner hunk will need a trivial rebase over whichever lands first (all three append before the "Summary + COVERAGE ACCOUNTING" block).

Files

  • scripts/lib/check_procedure_code.py: the checker. --ref <ref> counts a git ref read-only (ls-tree + git grep); --base, --list, --config.
  • scripts/lib/procedure_code_tokens.json: the config.
  • scripts/run-hydra-gates.sh: the gate 119 block (wiring, census line, a crash is not a finding).
  • scripts/lib/test_check_procedure_code.py: 15 rule-by-rule arms.
  • scripts/lib/test_gate119_procedure_code_scope.sh: 10 runner arms over a real git history.
  • scripts/test-fixtures/gate-acceptance/COVERED-ELSEWHERE.md: row for gate 119.

Tests

  • test_check_procedure_code.py: 15 tests OK (also under -W error).
  • test_gate119_procedure_code_scope.sh: all 10 arms passed (the runner takes about four minutes).
  • check_gate_numbers_unique.sh: pass, 97 gates.
  • shellcheck: clean on the new suite; no new warnings on run-hydra-gates.sh.
  • tests/test-hydra-gates-bin.sh: 70 passed, 0 failed.
  • tests/run-helper-suites.sh: 125 passed, 1 quarantined, 3 failed. The three are test_check_connections_declaration.js, test_gate116_connections_declaration_scope.sh and test_gate_45_to_55_acceptance.sh. All refuse to run because Ajv is not installed in this clone (disk is at 97%, so I did not npm install). They do not touch this change. CI installs Ajv.

Baselines

Measured read-only against origin/development of each clone (check_procedure_code.py <clone> --ref origin/development), after a git fetch of development.

App origin/development Baseline count
openregister 63b5d60733 0
opencatalogi 8d5995f26 25
integriq 15e97f167 35
filinq a7cc7b04 1
thematiq aa96f1aa 0
launchpad 49b24d82 0
stackiq c75dbb2 0
larpinq e7f5eba 0
dossiq 31997d98c 169
pipelinq 6989610c5 3
shillinq 726f29a37 10
learniq 0569fa4 0
portaliq 537771c2 3
decidiq 1a2fe7f8 0
buildiq 374e6cc 0
keepiq a226f5b1 0
hermiq 52c0e9d 0
humaniq 599da7f 0
versioniq 42da90f 0
planninq b92c441 0

Token split, so the sizes can be judged: dossiq 36 bezwaar, 29 termijn, 28 beschikking, 27 woo, 16 vth, 13 dso, 13 besluit, 12 subsid. integriq 35 dso. opencatalogi 25 woo. shillinq 6 subsid, 3 wmo, 1 leges.

Notes for the coordinator:

  • Zeros are mostly real, not a miss: humaniq, learniq and others name their code in English (Leave, not Verlof). A zero baseline still enforces: it fails on the first procedure-named file.
  • integriq's 35 are all Dso* files in lib/Controller, lib/Exception, lib/Notification and so on. If those are the national-standard DSO adapter, they are excused by adding their path prefix to allow.pathPrefixes in the config, not by baselining 35. The two example prefixes (lib/Adapter, lib/Service/Zgw) do not cover them. Decision for Ruben; integriq's baseline would drop accordingly.
  • The one allowlisted file in the fleet today is pipelinq's lib/Service/Zgw/BesluittypeNotInCatalogusException.php.
  • Baseline file content to commit: {"count": N}.

This was referenced Oct 10, 2026
@rubenvdlinde
rubenvdlinde merged commit dca320f into main Oct 12, 2026
47 of 48 checks passed
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