Skip to content

[finding] 9 raw .reference reads still answer undefined silently after #18503 routed the carrier through one arbiter — the measured residue of ruling E item 2 #18550

Description

@os-litant

Split out of #18095 at contract-review time, so the residue keeps a tracker after Fixes #18095 closes that card. ⛔ Not filed by the implementing dev and ⛔ not a defect in PR #18503 — the PR names this residue itself, under "What this PR does not close".

What is left

PR #18503 routed the FieldSchema.reference carrier read through one arbiter (referenceCarrierOf), so a carrier that cannot be read is now refused loudly instead of answering "no target". Ruling letter E item 2 on #18095 asked for that refusal at every reader. The PR delivered it at the arbiter plus the four lint read sites, and left a measured residue of raw reads that still answer undefined silently:

  • packages/objectql/src/engine.ts:13052 and :13491 (cascade delete)
  • packages/rest/src/rest-server.ts:10835
  • packages/metadata-protocol/src/seed-loader.ts:701
  • packages/lint/src/validate-expressions.ts:380
  • packages/lint/src/validate-field-consumers.ts:552
  • packages/lint/src/validate-object-references.ts:297 and :316
  • packages/lint/src/validate-sharing-rule-enforceability.ts:261
  • packages/verify/src/derive.ts:136

⚠️ The count is 9, not the 10 the PR body states. The contract review re-measured it: packages/lint/src/validate-preset-comparands.ts:431 reads verdict.meta?.reference, and meta is the GraphField slice graphFieldOf builds (packages/lint/src/object-graph.ts:307) — so that site is already covered by the arbiter change and is NOT residue. The other ten cited lines were each printed at the merge base and read.

Separately, the review recorded 7 typeof === 'string' narrowing sites (class C1) that produce the same silence spelled differently, neither changed nor listed by the PR under "does not close": plugin-audit/src/audit-writers.ts (×4), rest/src/export-format.ts, cli/src/commands/doctor.ts, spec/src/kernel/functional-completeness.ts. ⚠️ One of those is misclassified in the PR body: spec/src/kernel/functional-completeness.ts:167 is not silence — it reports a non-string reference as an incompleteness finding. Whoever takes this card should re-derive the C1 set rather than inherit it.

The open question this card also carries

⚖️ Does arbiter + lint routing satisfy ruling item 2, or was PR #18503 owed the residue too? The contract review declined to answer this and named it the maintainer's to give. The seat landed #18503 on its PASS with this card filed first, so that whichever way the question goes, the work is tracked rather than lost. If the answer is "the PR was owed it", this card is that work and nothing was lost by landing; ⛔ the seat did not treat landing as the answer.

Why each site needs its own judgement, rather than a sweep

Routing these means touching objectql, rest, metadata-protocol and verify, several on hot runtime paths. Each site needs a decision about absence vs unreadability — the two are deliberately different answers in this design (null, undefined and '' are absence and must never throw; StrictField declares reference nullable). A mechanical sweep that throws on everything falsy would break the absence contract.

⛔ Note for whoever takes it: the schema's own superRefine validators must NOT throw (spec/src/data/field.zod.ts, spec/src/ui/action.zod.ts, spec/src/automation/builtin-node-config.zod.ts) — a throw inside a refinement makes safeParse throw instead of returning {success: false}, which would destroy the loudness at the contract door this whole change leans on.

First step for the dispatched dev

Re-derive the residue on the then-current main before touching anything: the list above was measured at PR #18503's merge base 2f11e2db7, and both the 9 and the C1 set are premises to falsify, not facts to inherit.

Dedupe words: referenceCarrierOf residue, raw .reference read answers undefined, C3 residue 9 sites, absence vs unreadability reference carrier, ruling E item 2 every reader.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions