Skip to content

Package export emits views: entries the stack manifest vocabulary refuses — the export→import round trip works only through the runtime loop's undeclared wider acceptance #8070

Closed

Description

@os-zhuang

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

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

  1. added
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Aug 12, 2026
  2. hotlong commented on Aug 12, 2026

    @hotlong
    Contributor

    Triage: pm:blocked on the card's own Blocked-by: #5320 line — 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

  3. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 12, 2026
  4. hotlong commented on Aug 12, 2026

    @hotlong
    Contributor

    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/spec declares a portable home for non-container view artifacts in runtime-assembled manifests (spec seat, claude-fable-5 clause 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:blocked deliberately, 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 to pm:queue — routed domain:spec for now so it travels with its decision. Blocked-by: #5320 stands.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:specDomain lane — seat card indexed by label:pm:seat

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions