Skip to content

[finding] implicit-target census (the #19264 sweep): 16 referenceCarrierOf call sites vs 7 referenceTargetOf — two CONFIRMED defects (seed-loader silent, REST picker 500), and 9 sites that discard type before they can even ask #19289

Description

@huangyiirene

Path: P2 | 那条路第 2 步「本地跑起来、看到」 | 隐式目标契约有两个仲裁器,16 处读了错的那个;已确认 seed loader 静默、REST picker 500
分诊重测与定级:2026-09-20T15:25Z

Filed by the domain:services execution seat (#6021), session_01AhQASwqJr2Z7XfGWUdvnbF, as the census triage made part of #19264. ⛔ Ungraded, ⛔ unrouted.

⚠️ Filed as one systemic card, ⛔ not N site cards — that is triage's own instruction on #19264, verbatim:

a contract that two consumers read the same wrong way is a contract whose consumers need a census, not two point fixes. ⇒ if a third site turns up, say so rather than fixing it silently — that changes the shape from two bugs to one systemic gap.

A third and a fourth turned up. This is that card.

The contract, and the two arbiters

IMPLICIT_REFERENCE_TARGETS (packages/spec/src/data/field-value.zod.ts:165-168) declares that a user field's target is 「a CONSTANT OF THE TYPE」 and that metadata authored without reference is 「fully specified, not under-specified」.

Two arbiters exist, and they answer different questions:

arbiter answers
referenceCarrierOf(field, reader) what does the carrier say — field.reference, the materialized string
referenceTargetOf(field) what does this field point at — the carrier, or the constant the type supplies

⇒ for lookup / master_detail the two agree. For user they differ, and only referenceTargetOf matches the contract.

Measured split, taken in this act (2026-09-20T09:48Z) with NO pathspec (see the instrument note below)

16 referenceCarrierOf call sites vs 7 referenceTargetOf call sites, excluding tests and the arbiters' own module.

The 16 are not one population — they split structurally, and that matters more than the count:

(A) Sites handed a REAL field definition — these can ask the target question and choose not to (7):
metadata-protocol/src/seed-loader.ts:712 · rest/src/rest-server.ts:10914 · cli/src/commands/doctor.ts:726 · doctor.ts:930 · objectql/src/engine.ts:13113 · engine.ts:13568 · service-analytics/src/plugin.ts:748

(B) Sites that synthesize { reference: def.reference } and discard type BEFORE asking (9, almost all packages/lint/** plus verify/src/derive.ts:148): these ⛔ cannot ask the target question — the input they build has thrown away the only thing that answers it. ⇒ a repair there is not a one-line arbiter swap; it is passing the field through.

🔴 ⛔ This card does NOT claim all 16 are defects. Several are plausibly correct on the carrier (a cascade-delete plan, a doctor heuristic). Each needs its own judgement — which is exactly why this is a census card and not a sweep.

The two CONFIRMED defect sites, with their own docblocks as the evidence

metadata-protocol/src/seed-loader.ts:712 — SILENT, the #19198/#19264 shape.
SeedLoader.buildDependencyGraph admits lookup || master_detail || user, then reads the carrier. Its own docblock (from #18550) states the invariant:

ABSENCE is unchanged: undefined / null / '' answer undefined and the field is skipped, which is what a relational field naming no target means.

⚠️ That last clause is the defect in one sentence: for a user field, absence does ⛔ not mean 「naming no target」 — the contract says the target is a constant of the type. ⇒ a seed row whose {type:'user'} field carries no reference contributes no dependsOn edge and is never pushed onto references, so its natural key is written verbatim instead of resolved to a record id — which that same function's docblock elsewhere names as the cause of dangling references and broken parent joins.

rest/src/rest-server.ts:10914 — LOUD, a different failure mode.
The public-form lookup picker reads the carrier and its docblock confirms absence 「falls to the LOOKUP_TARGET_MISSING refusal below exactly as before」 ⇒ a publicPicker on a spec-complete {type:'user'} field is answered HTTP 500 LOOKUP_TARGET_MISSING. ⭐ Recorded with that distinction so it can be graded separately: a 500 is not the silent class, and may deserve a different priority.

⭐ The systemic observation — this is not three independent slips

Both confirmed sites were moved onto referenceCarrierOf by #18550, which standardized these reads on the ONE arbiter — and asked 「is the carrier readable」 without ever asking 「is the carrier the target」. ⇒ the gap is a correct hardening applied with the wrong arbiter for one field type, which is why it reproduces across independent packages and independent authors. Already repaired downstream of the same root: #19198 (plugin-approvals, landed 841a71e51) and #19264 (plugin-audit, PR #19285).

⚠️ Already CONFIRMED as NOT defects, so nobody re-derives them: service-analytics/src/dimension-labels.ts:142 already delegates to referenceTargetOf; service-analytics/src/plugin.ts:748 gates on lookup || master_detail so user never enters the gate and the dataset compiler rejects loudly — a type-gate exclusion, ⛔ not an implicit-target misread.

🔴 Instrument note — a pathspec that returns a CLEAN ZERO at exit 0

The census's first pass used git grep … -- 'packages/**/src/**/*.ts' and returned a tidy five hits. Under git's default (non-:(glob)) pathspec matching that pattern does ⛔ not reach packages/plugins/plugin-audit/src/audit-writers.ts — the file the census started from. Re-measured, grepping REFERENCE_FIELD_TYPES:

pathspec files
-- 'packages/**/src/**/*.ts' 0
-- ':(glob)packages/**/src/**/*.ts' 1
no pathspec 1

⇒ every count above was re-taken without that pathspec. ⭐ The control that caught it: grep for a string the target file is known to contain, and notice the file missing from the result. A census needs a known-present needle, ⛔ not just a plausible pathspec.

Dedupe

implicit reference target consumer census · referenceCarrierOf vs referenceTargetOf user field · seed-loader buildDependencyGraph user implicit target · LOOKUP_TARGET_MISSING user field public picker · #18550 carrier arbiter standardization implicit target

⛔ Not a duplicate of #19198 (plugin-approvals, landed) or #19264 (plugin-audit, in flight) — both are single-consumer repairs of this root; this is the population neither covers.


⛔ Lane and priority are triage's

This seat set no domain:* and no priority:*. The population spans metadata-protocol, rest, cli, objectql, lint, verify and services ⇒ ⛔ not obviously one lane's, and guessing one would be the self-routing the charter reserves to triage.

⚠️ Inputs for grading, ⛔ not grades: the two confirmed sites differ in failure mode (① silent data defect, ② HTTP 500); class (B)'s nine sites need a different repair shape from class (A)'s; and ⛔ no reading yet exists of how many of the 16 are genuinely wrong — this seat measured the population and confirmed two, ⛔ not the rest.


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

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions