Uh oh!
There was an error while loading. Please reload this page.
fix(examples): app-multi-package's module is served WITH scope: 'project' — drop the "no scope key" claim - #14804
Conversation
…ackage
`defineStack` parses every `packages[]` entry through `ManifestSchema`, whose
`scope` is `.default('project')`, so the fixture's module is served with
`scope: 'project'` and never was the scope-less row it documented. Measured:
`dist/objectstack.json` carries `has_scope: true, scope: "project"` on both
packages.
State what the fixture actually delivers instead — the server's own
`writable: false` verdict (ADR-0070 D2), which reads `engine.manifests` before
any scope — and pin `scope: 'project'` on both served rows in the dogfood
harness that already boots the fixture, so the corrected docs stay true.
The genuinely scope-less rows exist where a manifest reaches the registry
without a `ManifestSchema` parse (marketplace / offline import; a Studio base
via `POST /api/v1/packages`); that pair is already pinned in
`packages/runtime/src/domains/packages-writable-verdict.test.ts`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Landing ( Pre-landing checks: seat ACCEPT on #14597 (comment 5519582946; clause ② no — no schema, accept/reject or public-surface change; Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#14597
The fixture documented a property its producer never emits. The triage made one question a precondition: does a genuinely scope-less served row exist on any path? It does — just not on this fixture's path, and not on the row the fixture claimed.
Measurement (read-only; all line numbers on
origin/main8f9ef6f7c)H1 — the artifact path materialises
scopeat compile time. CONFIRMED.defineStackparses everypackages[]entry's manifest throughManifestSchema(packages/spec/src/stack.zod.ts:233,ArtifactPackageEntrySchema), whosescopeis.default('project')(packages/spec/src/kernel/manifest.zod.ts:311). Measured:dist/objectstack.jsonafter a real buildhas_scope: true, scope: "project"ManifestSchema.parseof the authored orders bodyhas_scope: falsein,scope: "project"outGET /api/v1/packageson a booted stackscope: "project",writable: falseSo no package of a compiled artifact can be scope-less — the fixture's claim was not merely untrue here, it is unreachable from any
examples/**app.H2 — a raw manifest body CAN reach the registry unparsed. CONFIRMED; H1's "no served row is ever scope-less" is FALSIFIED.
registerApp(packages/objectql/src/engine.ts:4927) hands its argument toinstallPackage(:4956), which storestoRecordManifest(manifest)(packages/objectql/src/registry.ts:3956) — a key-by-key copy (:1229) that applies no defaults and runs no parse. Two production paths reach it without aManifestSchemaparse:manifestService.register(rawBody)atpackages/cloud-connection/src/marketplace-install-local-plugin.ts:291and:827, routed throughpackages/objectql/src/plugin.ts:457. This is the card's own parenthetical ("an installed marketplace package whose manifest bypassesdefineStack?") and the answer is yes.POST /api/v1/packages:const manifest = body.manifest || body(packages/runtime/src/domains/packages.ts:383) reachesprotocol.installPackage(packages/metadata-protocol/src/protocol.ts:21188), which defaultsversionand derivesnamespaceby hand and parses nothing (:21215). The code says so itself: "defineStackenforces it at compile time, but runtime-created packages never take that path".Measured:
SchemaRegistry.installPackageof the unparsed orders body yields a record with noscopekey; of the parsed body,scope: "project".H3 — the fixture's module would not have been the discriminator even if it were scope-less.
isWritablePackage(packages/metadata-protocol/src/package-writability.ts:77) readsengine.manifestsFIRST, so scope is never consulted for a booted package. Measured verdicts:engine.manifestsscopewritablefalsetrue'project'falseThe pair that separates the server verdict from any scope-only rule is rows 1 and 2 — and it is already pinned where it is true, in
packages/runtime/src/domains/packages-writable-verdict.test.ts(Pins 2 + 4) andpackages/metadata-protocol/src/get-meta-items-package-writable.test.ts. Nothing needed to move; the claim needed to come off the fixture.What changed
examples/app-multi-package/src/packages/orders/index.ts— the second "load-bearing property" now states what the fixture delivers (the server's ownwritable: falseverdict), plus a ⛔ note recording why no compiled artifact can carry a scope-less row, so the claim cannot be re-added.examples/app-multi-package/README.md— same correction to the prose under the table.packages/qa/dogfood/test/multi-package-artifact.dogfood.test.ts— the harness that already boots this fixture. Its comment repeated the claim; corrected, and a new pin asserts both served rows carryscope: 'project', on a real boot. That is the assertion the old claim could only ever have been checked by, and never was.No changeset: comment-and-test only, from a
privateexample and aprivateQA package — nothing publishes.skip-changesetapplied at creation.⛔
packages/spec/src/kernel/manifest.zod.tsis untouched, per the triage: the default is correct and load-bearing.Verification — union run at
bff31b601node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack), all run: 29 green, 2 needed the workspace built and are green after it (check:dual-build-cjs-loads,check:type-check-debt— the latter's--re-measurereports 22 ledger entries, 755 raw errors, none above record).scripts/check-test-completeness.mjsreturns its own exit-3 NOT MEASURED branch (it parses a test-run log CI supplies; no local log exists) — recorded as NOT MEASURED, not as a pass.pnpm lint(repo-wideeslint . --no-inline-config) — green. No narrowing claimed.pnpm --filter './examples/*' run typecheck— green; log confirmsexamples/app-multi-package typecheck$ tsc --noEmit ... Done(checked against the zero-match-exits-0 trap).pnpm check:nul-bytesgreen, plus a manual control-character scan over the three edited files.pnpm --filter @objectstack/dogfood exec vitest run test/multi-package-artifact.dogfood.test.ts— 9 passed (was 8).toBeUndefined()) and re-ran: 1 failed | 8 passed,AssertionError: expected 'project' to be undefined— the card's claim, falsified mechanically on a booted stack. Mutation confirmed on disk both ways before the run (injected marker present = 1, removed text = 0, blob1b93be01vs HEAD blobb6a7adf5); restore leg proved bygit diff HEADempty and the worktree blob back tob6a7adf5, marker gone, pin present. Restore ran from anEXIT INT TERMtrap using absolute paths.Out of scope, filed unassigned
The same false attribution is repeated in five platform-side comments and in the objectui console's rationale. Neither is a file this card may touch (the triage fenced the objectui half explicitly, and
packages/metadata-protocol/src/protocol.tsis held by open PR #14767, so that sweep cannot be atomic here anyway).defineStackmaterialisesscope: 'project'#14803 — the fiveobjectstacksites, including the pending.changeset/packages-read-door-writable-verdict.md, which would otherwise ship the false attribution into the release notes.writablefallback's rationale rests on a false premise — a multi-package artifact's module is served WITHscope: 'project', not scope-less objectui#7431 —packages/app-shell/src/views/studio-design/packages-io.ts:14-24and its test's case names. Behaviour there is correct and must not change; only the rationale is misattributed.🤖 Generated with Claude Code
https://claude.ai/code/session_017RbbUMnxkUnWhE4j94v8FE
Generated by Claude Code