Repository navigation
Description
Mechanism
GET /packages/:id/export (assemblePackageManifest, packages/runtime/src/domains/packages.ts:873) assembles a portable manifest whose views: array is getMetaItems('view', packageId). That read returns the registry's view items — which, by the ADR-0017 dual-read design, include the expanded per-view items (viewKind-bearing, registered under dotted names like account.form) alongside the authored container, plus any tenant-authored standalone ViewItems and flattened list/form overlays (branches 1/3/4 of the declared view metadata vocabulary, packages/spec/src/ui/view.zod.ts:3231).
The stack manifest vocabulary (packages/spec/src/stack.zod.ts:251, views: z.array(ViewSchema)) accepts containers only. So the export product is refused by the platform's own declared schema — defineStack / os validate reject it — yet its documented consumer is marketplace-install-local → manifestService.register() → engine.registerApp() (the exporter's own doc comment names this chain), and that install path performs no stack-schema parse (normalizeBundle in packages/cloud-connection/src/marketplace-install-local-plugin.ts:472 only unwraps the bundle envelope). The round trip works today solely because the runtime registration loop (packages/objectql/src/engine.ts:3794, the isAggregatedViewContainer site) accepts more than the schema declares — the exact runtime-wider acceptance #5320 records.
Measured (by execution, not grep)
Registering one minimal schema-valid container through registerApp and reading back listItems('view', pkg) after the export path's clean() (underscore/provenance keys stripped):
name="account" viewKind=undefined | container=true | stack ViewSchema accepts=true | metadata-door accepts=true
name="account.default" viewKind="list" | container=false | stack ViewSchema accepts=false | metadata-door accepts=true
name="account.form" viewKind="form" | container=false | stack ViewSchema accepts=false | metadata-door accepts=true
A standalone ViewItem (metadata vocabulary branch 1) measures: metadata door accepts = true, stack schema accepts = false, and today's runtime loop registers it through views: [...].
So the exported views[] of every views-bearing package contains entries only the runtime-wider loop can ingest — 2 of 3 entries even in the minimal single-container case.
Consequences
- Whichever way
views:数组的三个门形状判断不一致:栈级 schema 只收容器、授权 lint 按记录门映射、运行时注册循环全收 —— declared ≠ enforced 的「运行时更宽」向 #5320's convergence lands, this producer/vocabulary gap needs an explicit decision: runtime-assembled manifests re-aggregate items into containers at the producer, or the portable-manifest vocabulary gains a declared home for non-container view artifacts, or assembled manifests get their own declared registration seam. Tenant-authored standalone items and overlays have NO container to re-aggregate from, so this is a contract question, not a mechanical fix. - Until it is decided, tightening the runtime loop to the declared container-only contract (the
views:数组的三个门形状判断不一致:栈级 schema 只收容器、授权 lint 按记录门映射、运行时注册循环全收 —— declared ≠ enforced 的「运行时更宽」向 #5320 ruling's route) would refuse the platform's own export product on import; the cloud env-artifact boot path documented inpackages/runtime/src/app-plugin.test.ts("cloud artifact-kernel-factory handed artifact.metadata — category arrays with data") ships the same shapes into the same loop.
Blocked-by: #5320 — the fork reported on that card and this issue's fix direction are one decision.
Discovered while measuring #5320's ruling premise; the full measurement record is on that card.
Generated by Claude Code
Activity
hotlong commentedon Aug 12, 2026
Triage:
pm:blockedon the card's ownBlocked-by: #5320line — its fix direction and #5320's convergence ruling are one decision, so it must not dispatch ahead of that card leaving the decision inbox. Deliberately left laneless: the landing surface depends on which way #5320 is ruled (producer-side re-aggregation ⇒packages/runtime/domain:cli; a declared vocabulary home for non-container view artifacts ⇒packages/spec/domain:spec). Routing happens at the unlock re-check, against the merged ref, when the answer exists.Noted for the decision record: this card is new measured input to #5320 (executed round-trip evidence, not grep — 2 of 3 exported entries refused by the stack schema even in the minimal single-container case, and tenant-authored standalone items have no container to re-aggregate from). A pointer comment goes on #5320 so the maintainer sees it when they pick that card up.
本评论来自分诊座位 Routine。
Generated by Claude Code
hotlong commentedon Aug 12, 2026
Answered by the #5320 fork ruling — 2026-08-12 (maintainer sam, live PM chat
session_01GxKQfv3k8b6a2d2QrZU411, verbatim 「接受你的全部建议。」). This card and #5320 are one decision, as its body states.Ruling: option B + A's mechanical half —
packages/specdeclares a portable home for non-container view artifacts in runtime-assembled manifests (spec seat,claude-fable-5clause applies), export/artifact factories re-aggregate into containers where a container exists, and only then does the runtime registration loop tighten to the schema's container-only contract. So the export→import round trip stops depending on the loop's undeclared wider acceptance — which is exactly this card's complaint.Staying
pm:blockeddeliberately, now with a precise unblock condition rather than an open question: #5320's spec-side vocabulary lands first. At that moment this card's landing surface is determined (packages/runtime/export side) and it returns topm:queue— routeddomain:specfor now so it travels with its decision.Blocked-by: #5320stands.Generated by Claude Code