Skip to content

fix(gates): a real server↔JS leaf parity check — gate-24 was verifying nothing - #158

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/gate-24-integration-parity
Aug 5, 2026
Merged

fix(gates): a real server↔JS leaf parity check — gate-24 was verifying nothing#158
rubenvdlinde merged 1 commit into
developmentfrom
fix/gate-24-integration-parity

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What

hermiq registers its hermiq-agent leaf on both faces — the LeafDescriptor contributed through RegisterLeafProvidersEvent (lib/Listener/RegisterAgentLeafListener.php) and the registerIntegration({ id: 'hermiq-agent' }) mount pair (src/integration-leaf.js) — but shipped no scripts/check-integration-parity.sh. So hydra gate-24 said, at the v1.3.0 pin:

[gate-24] integration-parity: SKIPPED (structural) — no scripts/check-integration-parity.sh,
but this repo DOES register integration leaves (lib/ LeafDescriptor: 1, src/ registerIntegration: 1).
server↔JS leaf parity (ADR-066 Decisions 4/7 …) is UNVERIFIED

The listener's own comment says the surfaces list is spelled out on both halves "so the cross-layer parity gate (gate-24) has two explicit sets to compare". Nothing was comparing them.

Why it is self-contained

The obvious move — copy openregister's wrapper, which resolves the canonical check out of @conduction/nextcloud-vue — produces a dead gate:

  • the published npm package does not ship its scripts/ dir, and the hydra-gates job never runs npm ci, so the resolution always misses in CI;
  • the historic wrapper answers a miss with exit 0 and a friendly message → gate-24 reports PASS having correlated nothing;
  • even when resolved, the library check validates its own built-ins, and its ADR-066 cross-reference is WARN-only.

So this checker reads only this repo's sources, needs no node_modules, and every way it can fail to check something exits non-zero with a named reason.

Rules (all hard — ADR-019 AD-11/AD-13, ADR-066 decisions 4 and 7)

R1 complete render pair for the declared renderMode (mount+unmount / tab+widget)
R2 server↔JS id correlation both ways — phantom leaf / orphan registration
R3 renderMode agreement across layers under a shared id
R4 metadata agreement: label, icon, group, requiredApp, referenceType, surfaces
R5 a spread-inherited identity must come from the leaf-owning package
R6 an offlineConfig must name schemas/properties the repo actually declares

Output on this repo:

✓ integration parity: 1 server leaf face(s), 1 JS registration(s), 1 OpenRegister schema
  declaration file(s) — all rules pass (assertions run per rule: R1:1 R2:2 R3:1 R4:5 R5:0 R6:0)

The per-rule counts are printed so "verified" and "there was nothing to verify" are distinguishable. A run where every rule has zero subject matter exits 1, so this cannot become the thing it was written to replace.

Positive control — it has been seen to FAIL

break result
PHP renderMode: RENDER_MODE_MOUNTRENDER_MODE_COMPONENT exit 1 — [R3 renderMode] leaf "hermiq-agent" declares renderMode "component" server-side … but "mount" in its JS registration
dropped single-entity from the PHP SURFACES const exit 1 — [R4 metadata] leaf "hermiq-agent" field \surfaces` mismatch across layers`

Both restored; the check passes on the unmodified tree.

gate-24, measured with the v1.3.0 script

before [gate-24] integration-parity: SKIPPED (structural) — … is UNVERIFIED
after [gate-24] integration-parity: PASS

and the coverage line moves 61 of 62 applicable gates ran62 of 62, with gate-24 leaving the "GATES THAT DID NOT RUN" list. It passes because the checker ran and returned 0 — the gate only reaches _pass 24 inside if [ -f scripts/check-integration-parity.sh ], after executing it.

No shipped code changes: two new files under scripts/ (not linted by eslint src, not loaded at runtime).

hermiq registers an integration leaf on BOTH faces — the `hermiq-agent`
`LeafDescriptor` contributed through `RegisterLeafProvidersEvent`, and the
`registerIntegration({ id: 'hermiq-agent' })` mount pair in
`src/integration-leaf.js` — but shipped no `scripts/check-integration-parity.sh`,
so hydra gate-24 reported:

  [gate-24] integration-parity: SKIPPED (structural) — ... server↔JS leaf
  parity (ADR-066 Decisions 4/7 ...) is UNVERIFIED

Nothing correlated the two halves. The listener's own comment says the
`surfaces` list is written out on both halves "so the cross-layer parity gate
(gate-24) has two explicit sets to compare" — there was no gate comparing them.

This adds the checker gate-24 invokes. It is SELF-CONTAINED on purpose: the
canonical Node check in @conduction/nextcloud-vue validates that library's own
built-ins, its ADR-066 cross-reference is WARN-only, and its `scripts/` dir is
not published to npm — so the historic wrapper shape resolves nothing in CI and
exits 0 having checked nothing. Every way this one can fail to check exits
non-zero with a named reason instead.

Rules, all hard (ADR-019 AD-11/AD-13, ADR-066 decisions 4 and 7):
  R1 complete render pair for the declared renderMode (mount+unmount / tab+widget)
  R2 server↔JS id correlation, both ways (phantom leaf / orphan registration)
  R3 renderMode agreement across layers under a shared id
  R4 metadata agreement (label, icon, group, requiredApp, referenceType, surfaces)
  R5 a spread-inherited identity must come from the leaf-owning package
  R6 an offlineConfig must name schemas/properties the repo actually declares

hermiq exercises R1 (1), R2 (2), R3 (1) and R4 (5) — the counts are printed, so
"verified" and "nothing to verify" are distinguishable in the log. A run where
every rule has zero subject matter fails rather than passes.

Positive control (proved it can fail, then restored):
  * renderMode drift — PHP RENDER_MODE_MOUNT -> RENDER_MODE_COMPONENT
    => exit 1, "[R3 renderMode] leaf "hermiq-agent" declares renderMode
       "component" server-side ... but "mount" in its JS registration"
  * surfaces drift — dropped 'single-entity' from the PHP SURFACES const
    => exit 1, "[R4 metadata] leaf "hermiq-agent" field `surfaces` mismatch
       across layers"
Both restored; the check passes on the unmodified tree.
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/hermiq @ 16e5f14

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
test-l10n
composer ✅ 117/117
npm ✅ 744/744
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-05 19:02 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit da02737 into development Aug 5, 2026
39 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