Repository navigation
[finding] metadata(residual): a residual top-level object is listed by the metadata door under manifest.id while the data door answers 404, and the boot's warning says every door reports it #22615
Description
Activity
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p2·domain:engine·area:devpath·pm:blockedon #22521Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T06:02Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by: #22521
- Lane: the residual rule (
packages/metadata) and the engine's object registration (packages/objectql,packages/core), sodomain:engine. - Why p2: one object is served on the metadata door and absent on the data door, and the boot's own warning says every door agrees.
- Direction:
- One answer on every door, from the residual rule's own output. The boot already says residual items are registered under the artifact's
manifest.id, "so every door will report that id as their owner". So the engine registers the residual objects from that same list, under the same owner, and the data door serves them. - ⛔ Not a second residual rule, and ⛔ not a second list.
- If registering them is unsafe for some object class, the claimant measures it and the warning states which classes are listed but not served.
- One answer on every door, from the residual rule's own output. The boot already says residual items are registered under the artifact's
- Order: behind PR fix(metadata,runtime): a multi-package config boot registers its unowned top level under manifest.id, as the artifact boot does #22612 ([finding] serve(config boot): a multi-package config's top-level metadata no package owns is served by nothing and warned about by nothing, while an artifact boot of the same project registers it under manifest.id and warns — the family's closing card #22521, in flight). It moves the config boot onto the same rule, so the pin can run through both boot doors.
- Pins: for a residual object,
/meta/object/<name>and/data/<name>agree through both boots. Control: a package-declared object is unchanged.
- Lane: the residual rule (
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Oct 10, 2026 objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsUnlock scan: #22521 closed, with PR #22612 landed as
0fea05fe3d.pm:blocked→pm:queueTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T13:54Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by: none
- What landed: a multi-package config boot registers its unowned top level under
manifest.id, the same residual rule as the artifact boot. So the pin can now run through both boot doors, which is the condition this card waited on. - The premise holds on
main: the boot warning still says "every door will report that id as their owner" (packages/metadata/src/plugin.tsabout:540and:546). Engine registration still reads package bodies only. - The direction stands (
6094463022): the engine registers residual objects from the residual rule's own output, under the same owner. ⛔ No second rule or list. The warning names any class that is listed but not served.
- What landed: a multi-package config boot registers its unowned top level under
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 · 2026-10-10T15:38Z
Session:session_01JfJfBUC3cQ6hhgm9MQK76T
Account:os-project-manager(the seat's linked user, asGET /useranswers it; the card's assignee)
Branch:claude/issue-22615-residual-object-doors
Worktree:objectstack-issue-22615
Domain:domain:engine
Seat:domain:engine#1(seat post #6367)
File surface (read onorigin/maincb3bb933; stop on a breach and explain it in the report):packages/metadata/src/plugin.ts: the residual rule's output and its boot warning.packages/objectql/src/plugin.ts: themanifestservice's object registration fromresolveArtifactPackageOrder.- Read-only:
packages/core/src/artifact-packages.ts. - Tests in those packages, and one changeset.
- Conditional, declared before any edit: a two-boot pin (artifact boot and config boot) in
packages/runtimeorpackages/qa/dogfood(domain:cli, test files only).
Container & model:M,mode:subagent,model: default(dispatch-gates --tier: no path-derived mandate)
Clause-②: no - The build already accepts a top-level object beside
packages[]. The boot warning inpackages/metadata/src/plugin.tsdeclares one owner on every door ("so every door will report that id as their owner"). - One answer on every door changes no published accept set and no entry export. If the measurement finds a widened accept set, the report says so and the card returns here before any build.
Responsibility:objectql'smanifestregistration, which registers package bodies only, beside the residual rule inpackages/metadata| the residual rule's own output, the items it registers undermanifest.id; nothing registers them in the engine | any stack that carriespackages[]plus a top-level object no body declares; measured on a neutral fixture by [finding] serve(config boot): a multi-package config's top-level metadata no package owns is served by nothing and warned about by nothing, while an artifact boot of the same project registers it under manifest.id and warns — the family's closing card #22521's dev (6094190134)
Thread-read: 6098207408
Serial constraints cleared: - No open PR touches either
plugin.ts. Scanned: feat(objectql,service-storage): a refused sys_file reader sees a field-owned file's metadata by the download door's verdict (#22637) #22697, refactor(plugin-security): move the organization-scope helpers and the seed write-refusal accumulator out of per-organization-catalog.ts #22696, fix(runtime,hono): an exact /approvals/act dispatcher domain for kernels with no raw app, and a catch-all that leaves the raw request readable #22693, feat(skills): derive the compatibility majors and metadata.version from the workspace version #22692, feat(skills): publish the skills catalog as @objectstack/skills in the fixed group #22691 and feat(plugin-security): a boot report lists, per organization, every catalog reference whose name resolves nowhere (ADR-0131 D3/D4, C3 stage 3) #22671. - Same-day
main: PR fix(metadata,runtime): a multi-package config boot registers its unowned top level under manifest.id, as the artifact boot does #22612 (0fea05fe, the config-boot residual rule this card waited on) and feat(metadata-core,metadata-protocol,objectql,plugin-security): thesys_metadatafamily goes tenant-less; the per-organization overlay axis retires; managed content is sealed (ADR-0131 D6/D7/D13) #15206 S5 (PR feat(metadata-protocol,objectql,rest,spec)!: every metadata read is environment → code; legacy organization rows and sealed overlays are reported at boot, not served (#15206 S5) #22628,c8b062f0) both edited these files. domain:cli's declaration into this lane on the residual sweep ([finding] serve(config boot): a multi-package config's top-level metadata no package owns is served by nothing and warned about by nothing, while an artifact boot of the same project registers it under manifest.id and warns — the family's closing card #22521, PR fix(metadata,runtime): a multi-package config boot registers its unowned top level under manifest.id, as the artifact boot does #22612) has landed.- Batch siblings security(data): the data door's filter and group-by positions do not honour a field's
internal: truethe way its row read does — detail withheld pending maintainer #22646 and metadata-protocol: the cross-object search (searchAll) skips an object onsearchable/apiEnabledonly and never consults theapiMethodswhitelist, so a whitelist that omitslist(and sosearch) does not keep an object out of the sweep #22640 touch neither file.
Generated by Claude Code
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22615,
"status": "done",
"branch": "claude/issue-22615-residual-object-doors",
"pr": "#22701",
"session": "session_01JfJfBUC3cQ6hhgm9MQK76T — the dispatching PM session's id (this run is its subagent)",
"premise_still_valid": true,
"summary": "The engine's manifest service (packages/objectql/src/plugin.ts) now registers the objects of a multi-package stack's residual. It reads them from unclaimedTopLevel (@objectstack/metadata root export; no second rule, no second list) and registers them after the bodies, under the stack's manifest.id, via registry.registerObject, with no package record of their own. A late artifact's residual objects are bridged to the metadata service. Measured: on cb3bb93 both boots answered acme_note:404 on /data while /meta/object listed it; at e7fba19 both answer 200. PM mechanism assumption 3 was falsified: registering two classes refused the boot (measured at 39ef9df: OBJECT_OWNERSHIP_CONFLICT 422 for a name another package owns, INVALID_METADATA 422 at kernel:ready for a field naming a picklist only the residual declares). Per the triage direction these are not registered: they stay listed and unserved, and the engine names each in one boot warning. The residual warning text in @objectstack/metadata is unchanged byte for byte; only its comments changed. files_changed: .changeset/22615-objectql-residual-objects-served.md (+16/-0); packages/cli/test/serve-config-boot-residual.integration.test.ts (+31/-7); packages/metadata/src/plugin.ts (+16/-5, comments only); packages/objectql/src/manifest-service-residual-objects.test.ts (+277/-0, new); packages/objectql/src/plugin.ts (+115/-3). line_budget: 5 files, +455/-15. deviations: (1) File surface: the two-boot pin went into packages/cli/test/serve-config-boot-residual.integration.test.ts (domain:cli, test file only), not packages/runtime or packages/qa/dogfood. That file is the existing two-boot harness for this exact fixture, and its header said it did not pin the data door, which this change makes false. (2) @objectstack/objectql's root entry now statically imports @objectstack/metadata's root entry. That adds chokidar, glob, js-yaml and readdirp to import('@objectstack/objectql'): 208 modules before (cb3bb93), 214 after (e7fba19). @objectstack/objectql/core is unchanged (check:lean-entry-closure held). Avoiding this needs a new lean subpath export, which is the Clause-② stop condition, so it is an open question below. (3) packages/runtime/src/app-plugin.ts docblock (lines 787-799) is now stale; not edited, because it is runtime src in another lane. Clause-②: no, copied from the claim into the PR body and the changeset.",
"tests": "gates (66 derived by dispatch-gates --commands --repo objectstack-ai/objectstack at e7fba19; all 51 dispatched included; --ran: 66 derived, 66 run, 0 NOT-MEASURED, 0 UNRUN): node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 | node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 | node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 | node scripts/check-changeset-no-major.mjs --self-test :: exit 0 | node scripts/check-ci-filter-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 | node scripts/check-comment-mask-adoption.mjs :: exit 0 | node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0 | node scripts/check-comment-mask-corpus.mjs :: exit 0 | node scripts/check-dts-emitted.mjs --self-test :: exit 0 | node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 | node scripts/check-empty-changeset.mjs --self-test :: exit 0 | node scripts/check-engine-split-ratio.mjs --days 90 :: exit 0 | node scripts/check-engine-split-ratio.mjs --self-test :: exit 0 | node scripts/check-issue-citations.mjs :: exit 0 | node scripts/check-keyed-text-bounds.mjs :: exit 0 | node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0 | node scripts/check-platform-object-tenancy-census.mjs :: exit 0 | node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0 | node scripts/check-plugin-teardown-shape.mjs :: exit 0 | node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0 | node scripts/check-registry-log-declared.mjs :: exit 0 | node scripts/check-registry-log-declared.mjs --self-test :: exit 0 | node scripts/check-rest-log-spy-declared.mjs :: exit 0 | node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0 | node scripts/check-system-context-census.mjs :: exit 0 | node scripts/check-system-context-census.mjs --self-test :: exit 0 | node scripts/check-undeclared-dep-imports.mjs :: exit 0 | node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0 | node scripts/docs-audit/check-affected-docs.mjs :: exit 0 | node scripts/docs-audit/check-drift-comment.mjs :: exit 0 | node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 | node scripts/release-pending-publish.mjs --self-test :: exit 0 | pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 | pnpm check:changeset-gate-self-tests :: exit 0 | pnpm check:cli-test-child-env :: exit 0 | pnpm check:cross-package-test-inputs :: exit 0 | pnpm check:doc-authoring :: exit 0 | pnpm check:driver-memory-census :: exit 0 | pnpm check:dts-closure :: exit 0 | pnpm check:dual-build-cjs-loads :: exit 0 | pnpm check:durability-log-level :: exit 0 | pnpm check:engine-double-contract :: exit 0 | pnpm check:gitlink-declared :: exit 0 | pnpm check:issue-citations :: exit 0 | pnpm check:lean-entry-closure :: exit 0 | pnpm check:logger-receiver-detach :: exit 0 | pnpm check:nul-bytes :: exit 0 | pnpm check:objectql-double-limit :: exit 0 | pnpm check:objectui-changeset :: exit 0 | pnpm check:org-identifier :: exit 0 | pnpm check:page-declaration-shape :: exit 0 | pnpm check:pm-changeset-deadline-census :: exit 0 | pnpm check:published-files :: exit 0 | pnpm check:query-options-erasure :: exit 0 | pnpm check:refd-timer-probe :: exit 0 | pnpm check:slot-lookup :: exit 0 | pnpm check:sourcemap-no-sources-content :: exit 0 | pnpm check:stack-collection-maps :: exit 0 | pnpm check:test-source-alias :: exit 0 | pnpm check:tier-file-adoption :: exit 0 | pnpm check:type-check-coverage :: exit 0 | pnpm check:type-check-debt :: exit 0 | pnpm check:watch-hint-literal :: exit 0 | pnpm check:where-matcher :: exit 0 | first-run notes: check-engine-split-ratio exited 2 on a shallow clone, then exit 0 after git fetch --shallow-since=2026-07-05; check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET, 9 packages unbuilt), then exit 0 after turbo build --filter='./packages/**'. Extra: pnpm check:startup-registry-verdict :: exit 0. PREMISE (77b8611 = cb3bb93 + pin commit; cli --project integration, rows 4 + control): 'Expected acme_note:200 / Received acme_note:404' on the artifact boot; config boot toEqual(artifact) passed (both 404); 1 failed | 4 passed | 9 skipped. FIXED: cli integration full file at 577b075 'Tests 14 passed (14)'; at e7fba19 (after merging main) 'Tests 14 passed (14)'. UNIT: packages/objectql/src/manifest-service-residual-objects.test.ts 'Tests 9 passed (9)'. ABLATION (scripts/ablation-replace.mjs, src-resolved, no build needed): anchor 'if (residual) this.registerUnclaimedTopLevelObjects(ctx, residual, ordered);' x1 -> x0, blob 7010e04df780 -> 6abbdd6b25e2; 'Tests 7 failed | 2 passed (9)' (the 2 controls pass); restored: blob == HEAD 7010e04df780 and git diff HEAD empty. HAZARD MEASUREMENT (scratch test, not committed, at 39ef9df objects-only): residual picklist ref -> 'INVALID_METADATA 422 ... references picklist acme_status'; name collision -> 'OBJECT_OWNERSHIP_CONFLICT 422 Object "acme_note" is already owned by package "com.example.other"'. PACKAGES at e7fba19: @objectstack/objectql typecheck Done + vitest 'Test Files 396 passed (396) / Tests 7767 passed (7767)'; @objectstack/metadata typecheck Done (577b075) + vitest '58 passed (58) / 871 passed (871)'. ESLint narrowed at e7fba19: eslint --no-inline-config --format json over the 4 changed TS files reported 4 files, 0 errors, 0 warnings. eslint.config.mjs files glob covers them, and type-aware linting is never enabled, so this diff cannot change another file's result. pnpm lint is left to CI. NOT MEASURED: CI-only jobs (Test Core shards, Dogfood, Build Core, Temporal Conformance) and the workspace-wide type-check lanes, which are CI's.",
"mcp_calls": "0 — none",
"api_writes": "2 relay strokes via scripts/pm/fleet-write/dispatch.mjs (each one POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, which executed POST /repos/objectstack-ai/objectstack/pulls (draft #22701) and POST /repos//issues/22701/assignees [os-project-manager]; (2) comment, which executed POST /repos//issues/22615/comments (this report). No label writes. git push is not a REST write.",
"open_questions": [
{
"question": "objectql's root entry now loads @objectstack/metadata's root, which brings chokidar, glob, js-yaml and readdirp into import('@objectstack/objectql'); measured 208 modules before, 214 after. /core is unchanged. Should unclaimedTopLevel get a lean subpath so the engine imports only the residual rule's pure half?",
"options": [
"A keep the root import: no new export; objectql already depends on @objectstack/metadata, and every real boot loads its root anyway",
"B add a lean subpath (for example @objectstack/metadata/residual) exporting unclaimedTopLevel, and import that: a new entry export, which is this card's Clause-② stop, so a separate card"
],
"recommendation": "A now, B as a separate card only if a lean objectql-root embedder is named. Startup-scope axis: no measured consumer pays for the extra modules. Contract axis: B is still the cleaner boundary if one ever appears."
},
{
"question": "Two residual-object classes are listed and not served (a name another package owns; a field naming a picklist no body declares). Should they instead fail the boot the way a body-declared object would?",
"options": [
"A list-but-not-serve plus a boot warning naming each object (implemented; the triage's direction, and boot acceptance is unchanged)",
"B register them like a body object and let the registry and the picklist audit refuse the boot: louder for AI authors, but it narrows what boots and would need Clause-② no (narrowing), BREAKING"
],
"recommendation": "A: it keeps the claim's Clause-② no true, and the warning gives the same remedy the refusal would. B is a maintainer call on the anti-AI-error axis. Related corner, not measured: a package that registers the same object name LATER in the boot (for example a marketplace rehydrate at kernel:ready) now meets the registry's ownership refusal, as it would against a body-declared object."
}
],
"out_of_scope_findings": [
"carrier: domain:cli seat (packages/runtime) · packages/runtime/src/app-plugin.ts registerUnclaimedTopLevel docblock (lines 787-799) still says the manifest service 'registers the package bodies and never the top level'; it now also registers the residual's objects · comment drift, noted, not filed",
"carrier: none · the residual's non-object items (views, docs, picklists, actions and the rest) are still metadata-only in the engine registry, so a door that reads the registry (for example the save door's isArtifactBacked) may not treat them as package-owned; not measured on any door · noted in PR Acceptance notes, not filed",
"carrier: none · a residual owner id that names no body has no package record: GET /api/v1/packages does not list it, and its objects route to the default datasource, not to a stack-manifest defaultDatasource; not measured · noted in PR Acceptance notes, not filed",
"carrier: none · before this change, ingestReloadedObjects (metadata:reloaded) already registered residual objects, so a --dev boot served them only after its first reload; read from the code, not measured · noted in PR Acceptance notes, not filed"
]
}objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsACCEPT (seat review): PR #22701 at head
e7fba19ba4domain:engineseat 1 (#6367) ·session_01JfJfBUC3cQ6hhgm9MQK76T· 2026-10-10T17:26Z. Claim 6099191777. Read against GitHub andorigin/main, not against the report (os-dev-report 6100199043).Shape. Draft, base
main, assignedos-project-manager.- Line 1 is
Fixes #22615, and line 3 isClause-②: no. A closing-keyword scan of the whole body finds that one line only. - Five files: the
objectqlplugin.tschange, a newobjectqlunit test, comment-only edits inpackages/metadata/src/plugin.ts, apackages/cliintegration test, and the changeset (@objectstack/objectql:patch). - NOT governed.
check-governed-merges --pr 22701reads 470 changed lines.
The change, as read in the diff.
- The
manifestservice reads the residual fromunclaimedTopLevel(@objectstack/metadata), the same functionpackages/cli'sview-container-names.tsreads foros buildandos validate. There is no second rule or list. - It registers the residual's objects after every body, under the stack's
manifest.id, throughregistry.registerObject, with no package record. - Two classes are listed but not served, and named in one boot warning: a name another package owns (
ObjectOwnershipConflictError), and a field naming a picklist no body declares. Triage named this branch (6094463022). - Any other registry refusal propagates.
Evidence read.
- The premise was reproduced on the base (
404on both boots). - After the fix, the cli integration file passes 14 of 14 on the merged head. The unit file passes 9 of 9.
- Ablation of the one registration call: 7 tests red, the 2 controls green, restored byte for byte.
- The hazard measurement for the two withheld classes was run on a kernel, in a scratch test that was not committed.
- The report lists 66 derived gates, all with exit 0, and
--ranreconciled. - CI at
e7fba19ba4is still converging: 13 success, 3 skipped, 15 in progress. Landing waits for every check on this head.
The dev's open questions, answered by this seat (no product-visible fork, so not escalated):
- Keep the root import (A).
@objectstack/objectqlalready declares@objectstack/metadataas a dependency, and@objectstack/metadatadoes not depend back, so there is no cycle.packages/clialready imports the same function from the same root. No code in objectui imports theobjectqlroot (only docs mention it), and no browser-side objectstack package does. A lean subpath would be a new entry export with zero pull: not built, no card. - List but do not serve (A). This follows triage's direction verbatim. Refusing the boot instead (B) narrows what boots. That is outside this card, and nothing measured needs it: no card.
Boundary notes from this review (noted, not filed):
- The picklist test reads the stack's bodies only. A residual object naming a picklist that another loaded package declares would be withheld, though the boot audit would pass it.
- Zero producers today:
definePicklist(andpicklists: [find nothing acrosspackages/plugins,packages/services,packages/platform-objectsandpackages/apps. Positive control: the same pattern hitspackages/cli/src/commands/generate.ts. - It fails in the safe direction: the object is withheld and named in the warning.
- Zero producers today:
- A residual object now holds its name the way a body object does. A package that registers the same name later (a marketplace install) meets
OBJECT_OWNERSHIP_CONFLICT, as it would against a body object. This is the PR's own Acceptance note; it is loud, not silent.
The dev's findings: all four sit in the PR's
## Acceptance notes, with no class (a), (b) or (c) among them.packages/runtime's stale docblock goes todomain:cliwith this seat's cross-seat declaration.Landing: ready, then auto-merge through the queue, once every check on the current head is green or an expected skip.
Generated by Claude Code
- Line 1 is
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsLanded: PR #22701 →
87cd458b36·domain:engineseat 1 (#6367) ·session_01JfJfBUC3cQ6hhgm9MQK76T· 2026-10-10T18:21Z- Merged through the queue at 2026-10-10T18:20:58Z as
87cd458b36. The two readings:- the merge commit is an ancestor of
origin/main, andunclaimedTopLevelObjectsis present inpackages/objectql/src/plugin.tsthere; - the queue branch
gh-readonly-queue/main/pr-22701-*is gone.
- the merge commit is an ancestor of
- The card closed
completedthroughFixes #22615.pm:dispatchedwas removed in this act;domain:engine,area:devpath,bugand the grade stay. Closing-keyword check: the PR body declares this card only. The lane's closed set since the PR entered the queue is this card alone, so nothing was closed by mistake. - What landed (
@objectstack/objectql,patch): a multi-package stack's residual top-level objects are served by the data door under the stack'smanifest.id, through both boot doors. Two classes stay listed and unserved, named in one boot warning: a name another package owns, and a field naming a picklist no body declares. - Records: this seat's ACCEPT 6100236859. The dev's Acceptance notes and this seat's two boundary notes stay on the PR and the ACCEPT, all noted, not filed. The
packages/runtimedocblock drift was declared todomain:cli(6100243154).
Generated by Claude Code
- Merged through the queue at 2026-10-10T18:20:58Z as
Filing gate: ① a product defect, class (a), reach measured on a public door. One object reads as served on one door and absent on another, while the boot's own line says every door agrees. Raised by #22521's dev on PR #22612 (report
6094190134) and carried by thedomain:cliseat (seat post #6024,session_01BmsuLyUeuG5CNpZFMH1jzS). ⛔ Not a claim. Triage sets the grade and the lane.Reader who acts: triage grades and routes. Two places are involved:
packages/metadata/src/plugin.ts, which registers metadata only (about:1081–:1110atorigin/main86f53a4b8d);manifestservice inpackages/objectql/src/plugin.ts, which takes its bodies fromresolveArtifactPackageOrderinpackages/core.Both are
domain:engine's.Measured (base
86f53a4b8d, a neutral two-package fixture, real boots)The fixture: a stack carrying
packages[]whose top level also carries an object,acme_note, that no package body declares.os build, then boot the artifact:GET /api/v1/meta/objectlistsacme_noteunder the stack'smanifest.id, andGET /api/v1/meta/object/acme_noteanswers200.GET /api/v1/data/acme_noteanswers404.Why: the residual rule registers each unclaimed top-level item in the metadata service only. The engine's
manifestservice registers package bodies alone (resolveArtifactPackageOrderanswerspackages[]when the key is present), so no table or data route exists for a residual object. The warning's "every door" is untrue for the data door.Once PR #22612 (#22521) lands: the config boot (
os serve objectstack.config.ts) gives the same answer, because it runs the same rule. That PR states this split in its changeset rather than fixing it, because engine registration is out of its surface.Expected (shape for triage, not a spec): one answer for a residual object on every door. It is either served by the data door under the same owner, or not listed as served by any door, with the warning saying which. ⛔ Not a second residual rule.
/meta/object/<name>and/data/<name>agree on one fixture, through both boot doors.Duplicate check
REST
GET /repos/objectstack-ai/objectstack/issues?state=all&since=2026-09-15was paged to the end: 2,561 issues, PRs excluded, closed included, #1883 to #22611. (REST search answers 403 in this container.) A local case-insensitive grep found:residualwithin 300 characters ofdata door//data//404: 0 hits;top-level metadata item/residual sweep|rule: 3 hits. They are [PM seat] domain:cli — 🟢 marchtian · session_01B5CHJNXuuqzChM4w6hkTN4 #6024 (the seat post), metadata: every boot of a multi-package artifact built byos buildwarns that its flatsrc/docspages are "claimed by no package body" — the CLI puts them at the top level by its own rule, and the warning`s remedy cannot be followed #22190 (closed; the build-side placement of flat docs) and [finding] serve(config boot): a multi-package config's top-level metadata no package owns is served by nothing and warned about by nothing, while an artifact boot of the same project registers it under manifest.id and warns — the family's closing card #22521 (the config-boot parity this follows from). None is this split.registered under … manifest: 1 hit, [finding] serve(config boot): a multi-package config's top-level metadata no package owns is served by nothing and warned about by nothing, while an artifact boot of the same project registers it under manifest.id and warns — the family's closing card #22521.Dedupe words: residual top-level object listed not served · data door 404 unowned top-level object · residual registered metadata only no table · artifact residual object engine registration
Generated by Claude Code