Summary
.github#286 gave gate-54 x-external-register for a reference to another app's register. The same unclosable shape exists within one app, for a reference whose target schema is owned by a change that has not landed yet, and x-external-register cannot express it honestly — the owner is the same app.
Measured on ConductionNL/decidesk at gate package 365fa31, NODE_PATH set (require.resolve('ajv') → .../node_modules/ajv/dist/ajv.js), 0-byte .err. All 7 of decidesk's gate-54 findings are this family. None is cross-app.
The three sub-shapes
(a) A $ref to a schema an unlanded change owns — 4 findings.
lib/Settings/register.d/49-vragenuur-interpellatie.json:
| property |
$ref |
gate says |
MondelingeVraag.fractie |
Fractie |
does not resolve (case-exact) |
Interpellatieverzoek.fractie |
Fractie |
does not resolve |
MondelingeVraag.vervolgSchriftelijkeVraag |
SchriftelijkeVraag |
does not resolve |
MondelingeVraag.bronSchriftelijkeVraag |
SchriftelijkeVraag |
does not resolve |
Neither key exists in the 81-schema register set. The properties say why, in their own descriptions:
"Reference to the submitter's Fractie (fractievoorzitter-fractie-koppeling — hard depends_on, that change owns the schema). Required. Seeded as a nil-UUID placeholder until that change lands (design D6)."
(b) A deliberately soft reference to an unlanded sibling capability — 2 findings.
47-works-council-consultation.json: ConsultationRequest.achterbanraadpleging — "Modelled as a plain uuid reference (not a hard $ref) so the traject degrades gracefully when the sibling capability is not installed… Never a $ref to keep the cross-capability dependency soft (constituency-consultation lands in any order)."
51-raadsinformatiebrieven.json: Raadsinformatiebrief.relatedDossier — "targets the ArchivalDossier planned in records-management-archiving. Nullable — until that change lands it degrades to a plain link."
These are already written the way the gate's $ref rule would push them, and are flagged anyway by check (b) "lacks canonical $ref".
(c) A polymorphic target — 1 finding.
61-appointments-and-terms.json: Voordracht.voordragendePartij.referentie — "optionally points at a resolved Person or GovernanceBody". A single $ref cannot name two schemas, and composition keywords are rejected by OpenRegister registers.
Why it is unclosable
Exactly the #286 pincer, one level in:
- With the
$ref → check (f) "does not resolve to a schema key in the register set (case-exact)".
- Without the
$ref → check (b) "relation-shaped property … lacks canonical $ref (ADR-062 rule 7)".
x-external-register: decidesk would be false — the reference is not external, and _is_external_ref's docstring is explicit that the notion means "a schema owned by a different app". Using it here would be exactly the "reword until the regex stops matching" move #286 was written to stop.
The remaining route to green is to delete the documentation that makes _RELATION_DESC_RE match ("Reference to…"), which degrades the register to satisfy a checker.
Suggested fix
A narrow companion to x-external-register, suppressing the same two $ref rules and nothing else — e.g. x-pending-register: <change-name> for (a)/(b), naming the change that will own the schema so the marker is auditable and removable when that change lands. For (c), either an array form ($ref: [Person, GovernanceBody]) or a x-polymorphic-ref marker.
I have left all 7 red in decidesk rather than pick any of the dishonest routes.
Related: #286 (cross-app), #273 (gate-40 unclosable family).
Summary
.github#286gave gate-54x-external-registerfor a reference to another app's register. The same unclosable shape exists within one app, for a reference whose target schema is owned by a change that has not landed yet, andx-external-registercannot express it honestly — the owner is the same app.Measured on ConductionNL/decidesk at gate package
365fa31,NODE_PATHset (require.resolve('ajv')→.../node_modules/ajv/dist/ajv.js), 0-byte.err. All 7 of decidesk's gate-54 findings are this family. None is cross-app.The three sub-shapes
(a) A
$refto a schema an unlanded change owns — 4 findings.lib/Settings/register.d/49-vragenuur-interpellatie.json:$refMondelingeVraag.fractieFractieInterpellatieverzoek.fractieFractieMondelingeVraag.vervolgSchriftelijkeVraagSchriftelijkeVraagMondelingeVraag.bronSchriftelijkeVraagSchriftelijkeVraagNeither key exists in the 81-schema register set. The properties say why, in their own descriptions:
(b) A deliberately soft reference to an unlanded sibling capability — 2 findings.
47-works-council-consultation.json: ConsultationRequest.achterbanraadpleging— "Modelled as a plain uuid reference (not a hard$ref) so the traject degrades gracefully when the sibling capability is not installed… Never a$refto keep the cross-capability dependency soft (constituency-consultation lands in any order)."51-raadsinformatiebrieven.json: Raadsinformatiebrief.relatedDossier— "targets the ArchivalDossier planned in records-management-archiving. Nullable — until that change lands it degrades to a plain link."These are already written the way the gate's
$refrule would push them, and are flagged anyway by check (b) "lacks canonical$ref".(c) A polymorphic target — 1 finding.
61-appointments-and-terms.json: Voordracht.voordragendePartij.referentie— "optionally points at a resolved Person or GovernanceBody". A single$refcannot name two schemas, and composition keywords are rejected by OpenRegister registers.Why it is unclosable
Exactly the #286 pincer, one level in:
$ref→ check (f) "does not resolve to a schema key in the register set (case-exact)".$ref→ check (b) "relation-shaped property … lacks canonical$ref(ADR-062 rule 7)".x-external-register: decideskwould be false — the reference is not external, and_is_external_ref's docstring is explicit that the notion means "a schema owned by a different app". Using it here would be exactly the "reword until the regex stops matching" move #286 was written to stop.The remaining route to green is to delete the documentation that makes
_RELATION_DESC_REmatch ("Reference to…"), which degrades the register to satisfy a checker.Suggested fix
A narrow companion to
x-external-register, suppressing the same two$refrules and nothing else — e.g.x-pending-register: <change-name>for (a)/(b), naming the change that will own the schema so the marker is auditable and removable when that change lands. For (c), either an array form ($ref: [Person, GovernanceBody]) or ax-polymorphic-refmarker.I have left all 7 red in decidesk rather than pick any of the dishonest routes.
Related: #286 (cross-app), #273 (gate-40 unclosable family).