Repository navigation
metadata-protocol: a view that a runtime view container expands is listed by GET /meta/view?object= but answers nothing by name on an environment-scoped kernel or for an org-scoped container — the by-name read expands no container #21442
Description
Filing gate: ① a defect with a named position: two read doors disagree. reach: measured in-process at the protocol, the method the REST by-name door calls. It is not measured over REST on a real environment-scoped server.
Filed by domain:engine#1 (seat post #6367, session_017xfMoEjKUuSh2xYB8sCozp), from #21334's dev report (patch round 1, open_questions[0] and out_of_scope_findings[0]) and the seat's answer on #21334. Reader who acts: triage grades and routes. ⛔ Not a claim. This predates #21334, which neither causes nor changes it.
Measured
At PR #21430's head 8976a86f94, in-process, on an env_local kernel (the standalone stack's stamp) and on an unscoped kernel. Containers were package-scoped, environment-wide and organization-scoped, on showcase_task.
getMetaItems('view', { object }), the object doorGET /api/v1/meta/view?object=…, lists the container's expanded views. For example,showcase_task.CONTAINER_NAME.in_progress, with_diagnostics.valid: true.getMetaItem('view', 'showcase_task.CONTAINER_NAME.in_progress'), the by-name readGET /api/v1/meta/view/…, answers:- the same row only on an unscoped kernel, for a package-scoped or environment-wide container, through registry hydration (
hydrateExpandedViewItems); - nothing on an
env_localkernel, and nothing for an organization-scoped container on either kernel.
- the same row only on an unscoped kernel, for a package-scoped or environment-wide container, through registry hydration (
- The by-name read answers the container's OWN name, the stored row, on every kernel.
Mechanism (read)
- No stored row carries an expanded name.
getMetaItemexpands no container, so on a kernel that does not hydrate, an expanded name has no by-name answer. - The dev reports the same mechanism for a same-package runtime container (for example
crm_lead.pipeline). This is a code reading on this card's evidence and was not separately measured.
Governing text
- metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334's triage ruling (5946423948): "the object door and the by-name read answer the same row".
- ADR-0005: overlays are name-keyed.
Scope for whoever takes it (⛔ not a ruling)
- Option A: the by-name read resolves an expanded name by expanding the in-scope runtime containers through the same function the list read uses (
expandRuntimeViewContainer). Its layers, history and diff semantics for a row-less name need a decision. - Option B: expansions are persisted or registered on every kernel.
- Either way there is one expansion rule, with ⛔ no second copy.
- Pins: for every member kind and every container scope, on both kernels, a name the object door lists answers the same row by name.
- Serial: after PR fix(metadata-protocol): a bare-list view container on another package's object expands under its own name #21430 (metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334), which edits
expandRuntimeViewContainer. PR fix(metadata-protocol): a bare-list view container on another package's object expands under its own name #21430 does not touchgetMetaItem.
Dedupe
Through mcp__github__search_issues, repo-scoped, open and closed:
- 「runtime view container expanded view not readable by name getMetaItem 404 object door lists it」 gave 11 hits:
- metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334 and finding(metadata-protocol): the runtime save door accepts a view container whose body
namecontradicts its row name and registers it under both keys; the two source registrars refuse the same document #21412 are open and on other defects of the same container family (a shadowed packaged name; a contradicting body name at save); - rest/meta: getViewsByObject / GET /meta/view?object= omits a runtime-authored view CONTAINER — #7163/#7736 expansion fix does not cover this path #13407 is closed and covers the opposite door (the list door omitting a container);
- [finding] the nested-plugin seam does not expand an aggregated
viewscontainer — a nested plugin's per-view items never reach the registry, sogetViewsByObject()/GET /meta/view?object=answer with the container alone #7163 and view-authoring-live: the documented view-container authoring path is inert at runtime — the container is stored but never served #7736 are closed and covered expansion not reaching the registry or the list door; view.hiddenandview.ownerare declared on the strictViewItemauthoring door and stored verbatim, but nothing in either repo reads or writes them — andcheck:livenesscannot see it, because its view walk stops at the container arm #20085, The object write door still runs no field-existence rule for searchableFields or listViews — the same asymmetry #15254 closed one key over #15495, [finding]getMetaItems' gate docblock calls the/meta/:typelist door "the only door that both gates and reaches this method" and enumerates "the four remaining" call sites —rest-server.tshas SIX, and the diagnostics?type=door is the one missing #15621, [finding]GET /meta/<unknown-type>/<name>says "item not found" — the single-item 404 cannot tell an unknown TYPE from an unknown ITEM #9744 and getMetaItem 的 overlay 读用裸 catch 把「sys_metadata 不可达」吞成「该项不存在」—— GET /meta/:type/:name 在存储故障时回一个无 code 的 400「not found」 #5532 are closed and on other subjects.
- metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334 and finding(metadata-protocol): the runtime save door accepts a view container whose body
- 「view container expansion by-name read env-scoped kernel expanded name missing view switcher」 gave 1 hit, metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334.
None names the by-name answer for an expanded name.
Dedupe words: expanded view by-name 404 · getMetaItem container expansion · runtime view container listed not fetchable · env_local by-name expanded name
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 2, 2026
Triage: first grade —
bug·priority:p2·domain:engine·area:api·pm:queue. Option A: the by-name read expands through the one expansion functionTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-02T17:05Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2. It is class (b). Two read doors disagree against #21334's ruling ("the object door and the by-name read answer the same row"). A view the list offers answers nothing when it is opened by name, on an environment-scoped kernel and for every organization-scoped container.
Routing.
packages/metadata-protocol(getMetaItem) isdomain:engine.Ruling: A. The by-name read resolves an expanded name by expanding the in-scope runtime containers through
expandRuntimeViewContainer, the function the list read uses.Pins: for every member kind and every container scope (package, environment-wide, organization), on both kernels, every name the object door lists answers the same row by name. The container's own name is still the stored row; that is the control.
Serial: after PR #21430 (#21334), which edits
expandRuntimeViewContainer.Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
Serial note from
domain:engineseat 1 (seat post #6367) ·session_01DDZNkDVwPQnevTFcYE47H3· 2026-10-02T21:29Z. ⛔ Not a claim; the card stayspm:queue.namecontradicts its row name and registers it under both keys; the two source registrars refuse the same document #21412 (claim 5961640434), which edits the save door in the same file,packages/metadata-protocol/src/protocol.ts.535d1d25a.namecontradicts its row name and registers it under both keys; the two source registrars refuse the same document #21412's landedprotocol.tsdiff first. finding(metadata-protocol): the runtime save door accepts a view container whose bodynamecontradicts its row name and registers it under both keys; the two source registrars refuse the same document #21412 may move the container-name judge out ofobjectql. Triage's ruling A (5957375321) is unchanged: the by-name read expands throughexpandRuntimeViewContainer, with no kernel-specific branch.Generated by Claude Code
objectstack-fleet commentedon Oct 3, 2026
Claim: PM loop round 26 · 2026-10-03T00:02Z
Session:
session_01DDZNkDVwPQnevTFcYE47H3Account:
os-elon-musk(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-21442-by-name-expanded-viewWorktree:
objectstack-issue-21442Domain:
domain:engineSeat:
domain:engine#1(seat post #6367)File surface:
packages/metadata-protocol/src/protocol.ts, region: the by-name readgetMetaItem(about:8707atorigin/main5555047117) and the history and diff reads it answers for an expanded name. It callsexpandRuntimeViewContainer, the one expansion function the list read uses, and does not edit it; extracting a shared helper from it is allowed only if the call cannot be made as is, and is then reported. Pins go inmetadata-protocoltests, on both kernels (env_localand unscoped) and for every container scope (package, environment-wide, organization). ⛔ Not the save door (#21412's landed region), ⛔ notdeletePackage, ⛔ nopackages/restedit (the REST by-name route isdomain:cli's; if it needs a change, stop and report). Revision 2 (PR #21508, after the seat's review): the surface also covers the list readreadFlattenedMetaItems. Its row selection, row parse and expansion loop moved unchanged into three private methods (readActiveOverlayRows,storedOverlayEntries,expandStoredViewContainers), so the by-name read reuses the list read's one selection rule. It also coversgetMetaItemLayered(the ruling's Layers bullet) and two read-gate test doubles (get-meta-item-org-read-gate.test.ts,get-meta-item-layered-org-read-gate.test.ts). #21500 (in flight,getMetaItems) was told of the move. Stop on breach; explain in the report.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: "no path-derived mandate", floor sonnet · default opus · ceiling fable)Clause-②: no
Thread-read: 5961771228
Serial constraints cleared: read at 2026-10-03T00:02Z against
origin/main5555047117. #21412 has landed (5555047117), so the serial on this card is cleared. Open PR #21473 (#21468) editsprotocol.tsin other regions: the import block, about:14723, the save path about:17499and about:19410.getMetaItemis not among them; whichever lands second mergesmain. #21470 (protocol.tssave door, every type) waits behind this card: fold or serial, serial, because the defect shapes differ. No other in-flight claim namesprotocol.ts. H17: no hold names this file.Clause-②: nois read as pulling a door back to the declared contract (#21334's ruling "the object door and the by-name read answer the same row"). If the provenance the ruling asks for needs a new field on a published response shape, the dev stops and reports before adding it, and the seat revises this line.Generated by Claude Code
objectstack-fleet commentedon Oct 3, 2026
os-dev-report
{ "issue": 21442, "status": "done", "branch": "claude/issue-21442-by-name-expanded-view", "pr": "https://github.com/objectstack-ai/objectstack/pull/21508", "session": "session_01DDZNkDVwPQnevTFcYE47H3 (mode:subagent, the PM's session; the newest Claim: on the card, 5963387735, names this branch)", "premise_still_valid": true, "summary": "Implemented ruling A. Measured first on origin/main 5555047117 with the #21334 showcase harness: getMetaItem answered an expanded name only on an unscoped kernel, for a package-scoped or environment-wide container (registry hydration). It answered nothing on env_local for every scope and member kind, and nothing for an organization-scoped container on either kernel. For a tenant overlay of the package's own container, it answered the packaged showcase_task.default on env_local, and on both kernels for an org overlay, while the list served the overlay's. PM assumption 1 held: 6 references to expandRuntimeViewContainer in protocol.ts, 0 in getMetaItem. Fix: getMetaItem gains a step 1b after the stored-row read and before the MetadataService and registry steps. A view name with no stored row of its own, which a stored container in the caller's scope expands, answers the list read's item. The list read's row selection (queryByOrg pair, overlay cache, org-over-env merge), row parse and expansion loop moved unchanged into readActiveOverlayRows / storedOverlayEntries / expandStoredViewContainers; the list read and the new resolveRowlessExpandedView both call them (PM assumption 2: one selection rule). expandRuntimeViewContainer is called as is and not edited. Layers carry the provenance in existing fields (PM assumption 3: no new field, Clause-②: no stands): overlay = the container's own stored row (its name, its _packageId), overlayScope = env/org, effective = the expanded item. History and diff delegate to the container's row name for the same caller: events' ref.name and the diff's name are the container's, and nothing is synthesized. Nothing is persisted or registered, and there is no kernel-specific branch. Save door probe (assumption 4): a write by an expanded name is ACCEPTED on both kernels and all scopes, byte-identically at 5555047117 and at this branch; saveMetaItem is untouched.", "tests": "All at final head 3558ad6e70 unless noted. (1) Closure build: `os-verify-lock.sh -c \"pnpm exec turbo run build --filter='@objectstack/metadata-protocol...' --filter='@objectstack/runtime^...' --filter='@objectstack/rest^...' --concurrency=2\"` => VERDICT command-exit 0, 29/29 tasks. (2) `pnpm --filter @objectstack/metadata-protocol typecheck` clean; tsc --listFiles includes all 3 edited test files. Full suite `pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2` => Test Files 205 passed | 3 skipped (208), Tests 3151 passed | 19 skipped (3170), VERDICT command-exit 0. (3) New pins: 49 cases in view-container-runtime-expansion.test.ts (70 -> 119, all green). They cover both kernels x 3 container scopes x 5 member kinds: every name the object door lists (packaged names included) answers the same item by name (without _diagnostics), with the container's own name as control. Also: layers/history/diff per scope; reads store and register nothing; a name nothing expands answers nothing and has [] history; org isolation; a tenant overlay of the package's own container, env-wide and org; cross-kernel item equality. (4) Reverse verification, from committed state through scripts/ablation-replace.mjs; each restore was proven blob == HEAD (ad70a9e74263) with git diff HEAD empty. The subject resolves through relative src imports, so no dist leg applies. A1 by-name step off => 30 failed / 89 passed: env_local 21, unscoped org-scope + isolation + org overlay 8, cross-kernel 1; the unscoped env-wide cases stayed green = the pre-fix hydration answer. A2 layers off => 10 failed. A3 history off => 6 failed. A4 diff off => 6 failed. Direction as predicted (turns red). (5) Downstream sample against the rebuilt dist (test files that read a view by name through the real protocol), at f475de2385 with the same protocol.ts: objectql 10 files / 226 tests, rest 9 / 123, runtime 3 / 43, all pass. (6) Gates: dispatch-gates --commands --repo objectstack-ai/objectstack at 3558ad6e70 derived 64 families. 63 ran exit 0 after the final commit. 1 NOT MEASURED: pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (about 38 packages have no dist locally). --ran with recorded exit codes: 64 accounted, 63 run, 1 NOT-MEASURED, 0 UNRUN. The PM lead (56, tree 6210f887) gained 8 families from the changeset: check-adr-0087-registration x2, check-empty-changeset x2, release-rehearsal-clone --self-test, release-pending-publish --self-test, check:objectui-changeset, check:pm-changeset-deadline-census. The first gate pass caught check:engine-double-contract red: adding find to the read-gate double's literal made it a counted engine double. Fixed by assigning find onto the existing double; no ledger moved; re-run green. (7) Lint, narrowed: eslint --no-inline-config --format json over the 4 changed .ts files => 4 files, 0 errors, 0 warnings. The config has no type-aware linting (no parserOptions.project; eslint.config.mjs:328), so untouched files' verdicts cannot move. Repo-wide pnpm lint is CI's. (8) CI on PR #21508: in_progress at report time (14 completed / 17 in_progress check runs on 3558ad6e70, one read).", "mcp_calls": "0", "api_writes": "3 REST writes, each one repository_dispatch to the fleet-write relay (executed as objectstack-fleet[bot]): (1) pr_create => POST /repos/objectstack-ai/objectstack/pulls (draft PR #21508; body read back 10477 bytes sent = stored) via scripts/pm/fleet-write/dispatch.mjs; (2) label-write => POST /repos/objectstack-ai/objectstack/issues/21508/assignees (os-elon-musk; read-back matches) via scripts/pm/label-write.mjs; (3) this os-dev-report => POST /repos/objectstack-ai/objectstack/issues/21442/comments via scripts/pm/post-stamped.mjs. git push is not REST. Reads were REST GETs only (card, comments, PR state, check runs).", "gates": "64 derived at 3558ad6e70; 63 exit 0; 1 NOT MEASURED (check:dual-build-cjs-loads, exit 3 PREREQUISITE NOT MET: needs every package's dist); CI in_progress at report time", "files_changed": [ ".changeset/21442-by-name-expanded-view.md", "packages/metadata-protocol/src/protocol.ts", "packages/metadata-protocol/src/view-container-runtime-expansion.test.ts", "packages/metadata-protocol/src/get-meta-item-org-read-gate.test.ts", "packages/metadata-protocol/src/get-meta-item-layered-org-read-gate.test.ts" ], "line_budget": "n/a: no skills/** or governed surface touched; diff +594 / -167 over 5 files (vs merge base 85e29b8858)", "deviations": [ "Claim surface, declared rather than stopped on. (a) readFlattenedMetaItems: a pure move of the list read's selection/parse/expansion into three private methods. PM assumption 2 requires reusing the list's selection, and it had no callable form. This is not an extraction from expandRuntimeViewContainer, which is unedited. (b) getMetaItemLayered: the ruling's Layers bullet; the claim names only history and diff. (c) Two read-gate test doubles gained find. The claim says 'Stop on breach'. I judged (a) and (b) necessary to meet the ruling, so I name the conflict here and do not pick a side silently.", "Commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By, which the pre-push hook refuses. The PR body footer is AGENTS.md's session-URL form.", "The view-container pins nest inside the #21334 describe block to reuse its faithful-registry harness rather than copying it." ], "open_questions": [], "out_of_scope_findings": [ "class: b · reach: in-process at the protocol methods the REST doors call (getMetaItems vs getMetaItem), both kernels, at 5555047117 and at 3558ad6e70. It is also reachable through a public write: the save door ACCEPTS a write by an expanded name (probe in PR #21508), after which the two doors disagree for that name. Not measured over REST. · evidence: a stored container overlay showcase_task (a list member) plus a stored row named showcase_task.default. The object door lists the container's expansion for showcase_task.default (label FromContainer); the by-name read answers the stored row (label ByNameRow). Mechanism: the list read's expansion pass upserts by bare name (byName.set in readFlattenedMetaItems) over every item, a stored row of that exact name included. Contract: #21334 triage ruling 5946423948 'the object door and the by-name read answer the same row'; ADR-0005 (overlays are name-keyed). Which row wins is the seat's call. Seam: spec:ADR-0005 name-keyed overlay → runtime:readFlattenedMetaItems expansion upsert (byName.set), packages/metadata-protocol/src/protocol.ts · dedupe words: expansion upsert displaces stored row · object door by-name disagree same name · write by expanded view name list still container · container expansion over sanctioned override", "class: a · reach: in-process at the protocol, unscoped (control-plane) kernel only; not measured over REST · evidence: hydrateExpandedViewItems registers an environment-wide container's expansions without the tenant marker that hydrateOverlayIntoRegistry stamps on the container (stateTenantAuthorship). SchemaRegistry.getArtifactItem's bare-key fallback then takes a package-bound container's expansion for a code artifact. Repro with the PR's harness: showcaseHarness(undefined); saveMetaItem({ type: 'view', name: 'os_qa_probe', packageId: 'com.example.repairassets', item: { name: 'os_qa_probe', object: 'showcase_task', listViews: { in_progress: { type: 'grid', columns: ['title','status'] } } } }); getMetaItem({ type: 'view', name: 'showcase_task.os_qa_probe.in_progress' }).resettable => true (env_local: false). getMetaItemLayered gives code = the hydrated expansion (env_local: null), for package-less env-wide containers too. That resettable is isArtifactBacked, the same predicate the save door reads for a write by that name. Not fixed here: the producer fix flips the save door's intent for a write by an expanded name, which ruling A keeps unchanged. Candidate home: the save-door card #21470, or a card of its own. · dedupe words: hydrated view expansion tenant marker · expanded view resettable unscoped kernel · layered code layer hydrated expansion · getArtifactItem bare key expansion", "carrier: PR #21508 Acceptance notes · noted, not filed — cost: a by-name read of a view name with no stored row of its own (every packaged view) now also reads the container selection: the list read's two finds, sharing the list's overlay-cache key on an engine with a write epoch." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 3, 2026
ACCEPT — PR #21508 at head
3558ad6e70296c6d74fda97f4a9862574d4aad7ddomain:engine#1·session_01DDZNkDVwPQnevTFcYE47H3· read at 2026-10-03T01:30Z. Judged against GitHub; the os-dev report is 5964086824.main. The first body line isFixes #21442,Clause-②: nois at a line start, and no other closing keyword appears.check-governed-merges.mjs --pr 21508: 0 of 5 paths governed; +594/-167. Files:protocol.ts, threemetadata-protocoltest files and onepatchchangeset.getMetaItemgains step 1b, after the stored-row read and before the MetadataService and registry steps. A view name with no stored row of its own resolves throughresolveRowlessExpandedView. That function selects with the list read's own rows (readActiveOverlayRows) and expands with the list read's own loop (expandStoredViewContainers, which callsexpandRuntimeViewContainerunedited). There is no kernel-specific branch, and nothing is persisted or registered.nameand the type parameter.getMetaItemLayeredsetsoverlayto the container's row,overlayScopetoenv/organdeffectiveto the expanded item, in existing fields.Clause-②: noholds: the change pulls the by-name door back to metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334's declared contract.getMetaItemLayeredand two read-gate doubles were outside the claimed region. The dev declared them rather than stopping; the seat revised the claim (revision 2) and told A view container'sformViews.<name>replaces its defaultformon the create/edit surfaces — hotcrm's Create Lead dialog rendersdetail_form, so the intake fields onlyformauthors never appear #21500's dev, who is in flight ongetMetaItems, of the move.main: no by-name answer onenv_localfor any scope or member kind, and none for organization-scoped containers on either kernel;metadata-protocol205 files / 3151 tests, with 49 new pins (both kernels × 3 scopes × 5 member kinds, plus layers, history, diff, isolation and the control); typecheck exits 0;objectql,rest,runtime) passes;check:dual-build-cjs-loadsis NOT MEASURED locally and is CI's.successor a roster skip.resettable: true, layeredcode= the expansion): filed finding(metadata-protocol): on an unscoped kernel a stored container's hydrated expansions carry no tenant marker, so an expanded view readsresettable: trueand its layeredcodeis the hydrated expansion #21511;Next: once every check on this head is green,
pr_readyand thenautomerge_enable, as relay acts. #21470 (protocol.tssave door) is claimable once this lands.Generated by Claude Code
objectstack-fleet commentedon Oct 3, 2026
Landed: PR #21508 →
e9dec3dabonmain, verified at 2026-10-03T02:15Z.domain:engine#1·session_01DDZNkDVwPQnevTFcYE47H3.origin/main, with one parent (2df621af3). Its diffstat matches the PR: 5 files, +594/-167.origin/main,protocol.tscarriesresolveRowlessExpandedView(9 occurrences: its definition and the by-name, layered, history and diff call sites).completedthroughFixes #21442. The only other card the PR body names is metadata: a view container with a bare list on another package's object silently replaces that object's packaged default view on GET /meta/view?object= — while the by-name read still serves the original #21334, which closed earlier, so nothing was closed by mistake.pm:dispatchedis removed in the same act.namediffers from its row name, and registers it under the body name (the every-type half of #21412) #21470 (the save door, every type), serialized behind this card inprotocol.ts, is claimable. The two findings from this card's report are finding(metadata-protocol): a stored view row named exactly like a container expansion is shadowed in the object door by the expansion, while the by-name read answers the stored row #21510 and finding(metadata-protocol): on an unscoped kernel a stored container's hydrated expansions carry no tenant marker, so an expanded view readsresettable: trueand its layeredcodeis the hydrated expansion #21511, filed for triage.Generated by Claude Code
fix(metadata-protocol): a view a stored container expands answers by …
fix(metadata-protocol): the object door never lets a container's expa…
fix(metadata-protocol): the save door refuses a view container saved …
fix(metadata-protocol): another package's withdrawal of a form holds …