Repository navigation
Description
Out-of-scope finding measured while closing #7049 / PR #7153. Recorded per Prime Directive #10, unassigned. That card was scoped to which collections the two registration seams enumerate; this is a difference in what the two seams do with a collection they both enumerate, so it was deliberately not folded in — #7049's brief said to file rather than widen, and the seam difference is real behaviour change owing its own verification.
The fact
packages/objectql/src/engine.ts reaches the registration seam from two entry points. Since #7049 both read one METADATA_ARRAY_KEYS, so views is enumerated by both. But only the manifest seam expands an aggregated view container:
if (key === 'views' && isAggregatedViewContainer(toRegister)) {
for (const vi of expandViewContainer(itemName, toRegister)) {
this._registry.registerItem('view', vi, 'name' as any, id);
}
}The nested-plugin loop in registerPlugin() has no equivalent. "Object has-many View" (ADR-0017) says a defineView document aggregates an object's views and must ALSO be expanded into independent ViewItems registered under <object>.<key> — that expansion is what getViewsByObject() and GET /meta/view?object= consume, and it is what carries the per-view package layer the view switcher and Studio read.
The measurement
On PR #7153's branch (the divergence is identical on origin/main @ 3e8e669), one aggregated container registered through each seam, reading registry.listItems('view') back:
container = { list: { data: { object: 'account' }, name: 'all_accounts' },
form: { data: { object: 'account' } } }
via manifest -> [ 'account', 'account.all_accounts', 'account.form' ]
via nested plugin -> [ 'account' ]
Same document, same package id, same collection key — two of the three registry entries simply are not created on the nested path.
Impact
A package shipping its views through manifest.plugins[] registers the container and nothing else. Readers that ask for the container by object name still find it (which is why this is silent); readers that go through the expanded per-view items — the view switcher, Studio's per-view package attribution, GET /meta/view?object= — see an object with no views. No refusal and no diagnostic, the same silent-under-registration shape as #7049 one layer in.
Frequency is not measured and none is claimed: how many published packages ship an aggregated views: container from a nested plugin rather than from the top-level manifest is unknown.
Class
Observation-class with a demonstrated missing value, filed for triage to grade. Two shapes are plausible and they differ in cost:
- Share the loop body, not just the enumeration — extract one
registerMetadataCollections(source, ownerId, opts)both seams call, with the remaining seam differences (the per-keydebugline, the warn-on-nameless-item) as named parameters rather than accidental drift. Closes this and makes the next body-level divergence unrepresentable, the way ObjectQL's two collection-registration copies diverge: jobs / emailTemplates / tools / skills register from a manifest but NOT from a nested plugin — a package shipping them via a nested plugin registers nothing, stamps no ADR-0010 provenance #7049 did for the enumeration. - Add the expansion to the nested loop — small, and it is the one-instance shape ObjectQL's two collection-registration copies diverge: jobs / emailTemplates / tools / skills register from a manifest but NOT from a nested plugin — a package shipping them via a nested plugin registers nothing, stamps no ADR-0010 provenance #7049 explicitly argues against, since it leaves the two loop bodies undiffed exactly as the two lists were.
The other two measured body differences are recorded here so the next reader does not have to re-derive them: the manifest seam emits a per-key debug line and warns on an item with no derivable name; the nested seam does neither, so a nameless nested item is dropped in total silence.
Related
#7049 / PR #7153 (the enumeration half of the same two-seam divergence, and the source of this measurement), #6242 (the enumeration sweep), #5870 (the capabilities precedent for patching one seam at a time), ADR-0017 (Object has-many View), ADR-0010 (provenance envelope).
Activity
docs(objectql): name the filed card for the views-expansion seam diff…
os-zhuang commentedon Aug 10, 2026
Triage:
finding(domain:engine-corestays —packages/objectql/src/engine.ts).origin/main@5d24f4b:expandViewContaineris imported atengine.ts:130and called only atengine.ts:3097(the manifest seam); the nested-plugin loop has no equivalent — matches the card's claim exactly.manifest.plugins[]is named, so nothing a user hits today is established. Held for the findings round; either fix shape the card lists (sharedregisterMetadataCollections()or expansion in the nested loop) looks decision-free when promoted.jobs/emailTemplates/tools/skills— the two registration copies become one enumeration (#7049) #7153 is the collections-enumeration card this was deliberately fenced out of; re-searched "nested plugin views registry" — nothing else.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
claude commentedon Aug 10, 2026
Race re-read: comments re-read, no competing session ID;
assigneesmeasured EMPTY via REST immediately before assigning.pm:queue→pm:dispatchedin the same write.Surface freed by PR #7423's merge (
2ef18070e) —engine.tsserial queue, this card is next; #7373 queues behind it.Generated by Claude Code
claude commentedon Aug 10, 2026
ACCEPT — PR #7452. Ready + queued.
Verified by reading the body and diff:
ViewItems) to the loader, not one entry point; the sibling loader (metadata/src/plugin.tsartifact/HMR path) already expands — with the inline comment inui/view.zod.tssaying the expansion was pushed into spec precisely "so the two loaders cannot drift"; ~51 shipping stacks (crm/todo/showcase/qa) ride the manifest seam's expansion; and zero in-tree nested plugins carry aviewscollection. One direction breaks every shipping consumer, the other breaks nobody — the nested seam catches up. The user-visible mechanism is nailed too: only expanded items carryviewKind,getViewsByObject()filters on it, so an unexpanded container is invisible toGET /meta/view, the view switcher and Studio attribution, with no diagnostic.registerMetadataCollections, extending ObjectQL's two collection-registration copies diverge: jobs / emailTemplates / tools / skills register from a manifest but NOT from a nested plugin — a package shipping them via a nested plugin registers nothing, stamps no ADR-0010 provenance #7049's own reasoning from the list to the body — a divergence that cannot be written down cannot be re-introduced by the next hand patch. What legally varies (object read, package id, debug label) is parameterized.minor, behaviour deltas named; ⛔ nopackages/spectouch — no declaration needed.CI fully green. Auto-merge armed; issue closes on merge. #7373/#7413 queue behind this for
engine.ts.Generated by Claude Code
fix(objectql): a nested plugin registers `jobs` / `emailTemplates` / …
fix(objectql): expand an aggregated `views` container from the nested…
feat(objectql,runtime,lint): tighten views: to the container-only con…
docs(qa): re-point eight checklist items the 17.6.0 release-verificat…