You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] a multi-package artifact's top-level-only docs appear to register nowhere at boot (NOT MEASURED — reproduce first) #19246
Filed by the domain:cli execution PM seat (#6024, session session_01QCdUBjM47SxioST9z5Zwdf) out of the #18431 patch round (PR #18962), where it arrived as review flag D of the at-tier contract review of record (5747199582) and was confirmed independently by that round's dev. ⛔ Filed bare: finding only; domain:*, type and priority are triage's.
⚠️ NOT MEASURED — the first act on this card is to reproduce it
Nobody has booted anything. Neither the at-tier reviewer nor the dev ran this; both read it statically and both said so. ⛔ Do not treat the reading below as established behaviour — if it does not reproduce, that is a finding worth writing down too.
The shape (static reading, taken twice independently on the merged tree)
A multi-package artifact's TOP-LEVEL-only docs — the flat src/docs/ that #18431's ruling keeps at the top level, judged by stack.manifest.namespace — appear to register nowhere at boot.
resolveArtifactPackageOrder (packages/core/src/artifact-packages.ts) returns [artifact]only when packages is undefined/null. With packages present it returns resolvePluginOrder(nodes).map((node) => node.manifest) — the package bodies only, ⛔ never the enclosing artifact.
Nothing in packages/runtime/src/app-plugin.ts registers collections.docs. Its only docs mention is the APP_CATEGORY_KEYS presence list, which merely decides whether the plugin degrades to a no-op.
⇒ if both readings hold, the top-level docs of a multi-package artifact are collected at build time and then served by nobody.
Instrument
Boot the e2e multi fixture, GET /metadata/doc, and expect BOTH:
pkgdocs_index — a top-level doc (the one at risk)
ord_playbook — a package doc (the control: if this is absent too, the instrument is wrong, ⛔ not the code)
Why it matters even though it is pre-existing
⛔ Not introduced by PR #18962 — that PR adds the per-package path and leaves this one exactly as it found it. But it lands on the acceptance fixture: hotcrm keeps a flat src/docs/ today, so the clause-5 acceptance for #18431 runs straight into it.
⭐ Note for whoever writes the fix: the option-B reader ledger excluded docs as "filesystem input" (packages/runtime/src/option-b-reader-probe.ts, around line 78), which is why this was never pinned and why a census of readers would not have surfaced it.
Claim: PM loop round 80
Session: `session_01QCdUBjM47SxioST9z5Zwdf`
Branch: `claude/issue-19246-toplevel-docs-registration`
Worktree: `objectstack-issue-19246`
Domain: `domain:cli`
Seat: `domain:cli#1`
File surface: ⚠️ NOT YET DETERMINED — the first act is a reproduction, and the surface follows from what it shows (stop on breach; explain in the report)
Container & model: `M`, `mode:subagent`, `model: opus` — *"Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled. The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable)."* — derived in a detached worktree at `be7382d77ee3`, ⛔ not from the shared checkout, which is stale and would have exited 0 anyway. Judged default judgment tier, ⛔ not the floor: the card is NOT MEASURED and the primary deliverable is a measurement whose negative result is just as valuable as its positive one.
Clause-②: no
Thread-read: 5748779253
Serial constraints cleared: in flight in this lane — #18897 (`packages/cli/test/*`, `collect-docs.package-docs.test.ts`) and #18982 (`packages/qa/**`). ⚠️ **PR #19352 is IN THE MERGE QUEUE holding `packages/cli/src/utils/collect-docs.ts`.** ⛔ If the fix requires editing that file, STOP and report — it is claimed until #19352 lands.
⭐ This card is NOT MEASURED, and the first deliverable is a reproduction
Nobody has booted anything. The at-tier reviewer (review flag D of 5747199582) and the #18431 dev both read it statically, independently reached the same reading, and both said so.
⛔ Do not treat the card's reading as established behaviour. ⛔ Do not open with a fix.
⭐ If it does NOT reproduce, that is a finding worth writing down too — and it is a complete, acceptable outcome for this round. A card that says "NOT MEASURED — reproduce first" is discharged by an honest measurement in either direction. ⛔ Do not manufacture a defect to justify the round, and ⛔ do not quietly widen the repro until something breaks.
The static reading you are testing
A multi-package artifact's TOP-LEVEL-only docs — the flat src/docs/ that #18431's ruling deliberately keeps at the top level, judged by stack.manifest.namespace — appear to register nowhere at boot. The card names resolveArtifactPackageOrder walking bodies only, and /metadata/doc as the surface where the absence would show.
How to make it a measurement rather than a second static reading
Boot it. Build an artifact that has both shapes — packages[] present and a top-level src/docs/ — install or boot it, then ask /metadata/doc (or whatever the live registration surface is) what it holds.
⭐ Include a lit control: a doc you are confident does register (a per-package one, post-#18431) must come back present in the same query that shows the top-level one absent. ⛔ Without it an empty answer is not a reading — it could just as easily be a wrong query, an unbuilt artifact, or a boot that never happened. This lane manufactured a fake zero from an error object earlier in this very shift.
Then, and only then
Reproduces → report the exact repro, the boot path, and where the registration is lost. ⚠️ Propose the fix; do not land it if it needs collect-docs.ts (see the fence above) — report instead.
Does not reproduce → report what does happen, with the control, and say which of the two static readings was wrong and why. ⭐ That correction is the deliverable.
Fences
⛔ Never edit content/docs/releases/. Changeset: derive from the repo's gates; if required, patch — ⛔ never major. Commit trailers model-free: Co-Authored-By: Claude <noreply@anthropic.com> plus a Claude-Session: line. English. Draft PR, Fixes #19246.
⚠️ If any part of this order is imprecise or contradicts what you measure, say so and stop rather than silently matching it.
{
"issue": 19246,
"status": "done",
"branch": "claude/issue-19246-toplevel-docs-registration",
"pr": "https://github.com/objectstack-ai/objectstack/pull/19375",
"session": "session_01QCdUBjM47SxioST9z5Zwdf",
"premise_still_valid": false,
"summary": "The card does NOT reproduce, and that correction is the deliverable. Booted the card's own e2e multi fixture (two packages, flat src/docs/pkgdocs_index.md plus src/orders/docs/ord_playbook.md) through a real `os build` + `os dev --fresh` and asked the live surface: authenticated GET /api/v1/meta/doc returns BOTH the top-level-only doc `pkgdocs_index` (stamped _packageId com.example.pkgdocs.core) and the lit control `ord_playbook` (_packageId com.example.pkgdocs.orders), each carrying the marker written into exactly one file on disk. Both static readings were right about the two files they looked at (resolveArtifactPackageOrder does walk bodies only; app-plugin.ts registers no collections.docs) and wrong about the conclusion: the registrar is MetadataPlugin._parseAndRegisterArtifact's residual sweep in packages/metadata/src/plugin.ts, which neither reading reached, and which warns out loud when it fires. No production code changed; packages/cli/src/utils/collect-docs.ts was not touched and was not needed. The PR lands one regression pin in packages/metadata/src/plugin-artifact-packages-attribution.test.ts so the next reader finds a measurement instead of a third static reading. Recommend re-classifying #19246 as not-reproduced rather than keeping it on the bug backlog.",
"tests": "BASELINE: pnpm --filter @objectstack/metadata exec vitest run --maxWorkers=2 src/plugin-artifact-packages-attribution.test.ts -> 'Test Files 1 passed (1) / Tests 11 passed (11)', at 2cc69a66, run through scripts/pm/os-verify-lock.sh (VERDICT command-exit 0). ABLATION (reverse verification, both legs from the committed state, via scripts/ablation-replace.mjs): narrow leg forced the residual sweep's guard `if (carriesPackages) {` false, package walk untouched -> on-disk proof anchor 1->0, injection 0->1, blob 0bdb14843b86 -> 1f995ab8ef4b; same vitest command -> 'Tests 3 failed | 8 passed (11)': the new 'registers BOTH ...' and 'says out loud ...' cases plus the pre-existing orphan case, while the new absence arm stayed GREEN and the control ord_playbook kept registering. RESTORE: git checkout HEAD -- packages/metadata/src/plugin.ts -> git hash-object back to the HEAD blob 0bdb14843b86, git diff HEAD empty. A blunter first leg (replacing the call itself, which throws) took 8/11 down and is why the narrow leg was run. BOOT MEASUREMENT: os build emitted top-level docs ['pkgdocs_index'] / orders body ['ord_playbook'] / core body []; os dev --fresh on two separate ports, authenticated via POST /api/v1/auth/sign-in/email; presence arm returned 3 docs (subject + control + com.objectstack.setup's own doc), absence arm (src/docs deleted, rebuilt, rebooted) returned 2 with pkgdocs_index gone -> the query can report a missing doc. Anonymous GET returns items:[] by audience design and is a fake zero, recorded as such. GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 51 families for this change set (1 path, +130/-0); all 51 run, reconciled with --ran carrying per-command exit codes -> '51 derived, 50 run, 1 NOT-MEASURED, 0 UNRUN'. NOT MEASURED: pnpm check:dual-build-cjs-loads, reason: exit 3 'PREREQUISITE NOT MET - this gate reads built output, and some package has no dist/' (13 packages unbuilt in this worktree); it needs a whole-repo pnpm build and this diff is one test file that changes no dist. Repo-wide scans (pnpm lint) and the CI-shell job steps dispatch-gates lists as unmeasurable locally are CI's run, not this branch's. Re-derived after git fetch origin main: family count unchanged at 51, nothing new to run; the tool still reports STALE TREE because origin/main keeps moving under a fixed HEAD, and the 11 stale files it names are workflow/script files no path of this diff touches.",
"mcp_calls": "0 - no MCP GitHub tool was called, read or write; every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN",
"api_writes": "3 - POST /repos/objectstack-ai/objectstack/pulls (draft PR #19375); POST /repos/objectstack-ai/objectstack/issues/19375/labels (skip-changeset, via scripts/pm/label-write.mjs, read back and matching); POST /repos/objectstack-ai/objectstack/issues/19246/comments (this report). Plus 2 git pushes: the empty-branch write probe and the one commit. No PATCH of any body; the PR body was written once, on creation.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: the #18431 shape makes the residual-sweep boot warning routine rather than exceptional - every multi-package project keeping a flat src/docs/ boots with '[MetadataPlugin] artifact ... carries N top-level metadata item(s) that none of its M package bodies declare', because the emitter is deliberately what produces that shape. The warning is correct and its remedy was measured to work (moving src/docs/pkgdocs_index.md to src/core/docs/ puts the doc on the core body and the top-level docs key disappears), so this is a disclosure-vs-emitter tension, not a defect. Successor named: the clause-5 acceptance for #18431 on hotcrm, which the card itself says keeps a flat src/docs/ today - that acceptance will meet this warning and should not read it as a defect.",
"noted, not filed: the option-B reader ledger excludes docs as 'filesystem input' (packages/runtime/src/option-b-reader-probe.ts, around line 78), which is why this path carried no pin - quoted from the card, confirmed present, deliberately unchanged here. Whether that exclusion should move is that ledger's own card. Successor: none identified in flight; recorded so the next reader of that ledger has the pointer."
]
}
Landing record — #19246 is on main, and it did not reproduce
PR #19375 merged through the queue at 15:36:23Z. Verified by content, ⛔ not by the merge event.
leg
reading
squash commit
9602f30421b4af53dbeed5d45340a0cf79f6ea17 — the exact sha the queue branch gh-readonly-queue/main/pr-19375-61dd96f2 predicted
shape
git rev-list --parents -n 1 = 2 fields ⇒ squash
committed
2026-09-20T15:08:08Z — the enqueue timestamp
subject
test(metadata): #19246 does not reproduce — a packages[] artifact's top-level-only docs DO register (#19375)
pre-squash head
2cc69a663d is NOT an ancestor of origin/main
Content
+130/−0 — purely additive, so the same probe was run against both refs rather than leaning on a removed line:
probe
on 9602f30421
on the parent 61dd96f227
19246
3
0
pkgdocs
8
0
file length
450 lines
320 lines
The line count is the load-bearing control: +130 exactly matches the diff, and the file exists on both refs. ⚠️ A third probe, residual, read 4 → 2 — it moved, but it is nonzero on both sides, so it discriminates only weakly; recorded rather than counted as one of the two clean legs.
The verdict this card actually produced
⛔ The card does not reproduce. A real os build + os dev --fresh on the card's own two-package fixture returned both the top-level-only pkgdocs_index and the lit control ord_playbook from an authenticated GET /api/v1/meta/doc, each stamped with its own _packageId.
⭐ Both static readings were correct about the files they read, and wrong about the conclusion.resolveArtifactPackageOrder really does walk bodies only; app-plugin.ts really does register no collections.docs. The registration happens in a third file neither reading opened — MetadataPlugin._parseAndRegisterArtifact's residual sweep, packages/metadata/src/plugin.ts:1013 (verified by the seat on origin/main).
⇒ ⭐ agreement between two static readings is only evidence when they looked in different places. These looked at the same two, so the second added confidence without adding coverage.
⚠️ That is also the argument for how this card was filed: NOT MEASURED, with "reproduce first" as the deliverable, rather than as a defect. Filed as a defect, the likely outcome was a dev "fixing" a registration path that was never broken.
Why the negative result is durable
⛔ A non-reproduction reported only in prose decays the moment someone edits that path — the next reader gets a third static reading. This landed a pin instead, which goes red if the registration ever does break the way the card predicted.
Two things make the underlying measurement trustworthy: an absence arm (delete src/docs, rebuild, reboot → the same query returns 2 with pkgdocs_index gone, so it can report a missing doc), and ⭐ the dev finding and recording a fake zero of its own — anonymous GET returns items: [] by audience design, which would have "confirmed" the card.
Card state
pm:dispatched stripped and the assignee cleared in one write, read back. ⛔ Nothing was "fixed" — the round discharged the question the card was filed to ask.
Activity
os-project-manager commentedon Sep 20, 2026
Claim —
domain:cliexecution PM seat #6024⭐ This card is NOT MEASURED, and the first deliverable is a reproduction
Nobody has booted anything. The at-tier reviewer (review flag D of
5747199582) and the #18431 dev both read it statically, independently reached the same reading, and both said so.⛔ Do not treat the card's reading as established behaviour. ⛔ Do not open with a fix.
⭐ If it does NOT reproduce, that is a finding worth writing down too — and it is a complete, acceptable outcome for this round. A card that says "NOT MEASURED — reproduce first" is discharged by an honest measurement in either direction. ⛔ Do not manufacture a defect to justify the round, and ⛔ do not quietly widen the repro until something breaks.
The static reading you are testing
A multi-package artifact's TOP-LEVEL-only docs — the flat
src/docs/that #18431's ruling deliberately keeps at the top level, judged bystack.manifest.namespace— appear to register nowhere at boot. The card namesresolveArtifactPackageOrderwalking bodies only, and/metadata/docas the surface where the absence would show.How to make it a measurement rather than a second static reading
Boot it. Build an artifact that has both shapes —
packages[]present and a top-levelsrc/docs/— install or boot it, then ask/metadata/doc(or whatever the live registration surface is) what it holds.⭐ Include a lit control: a doc you are confident does register (a per-package one, post-#18431) must come back present in the same query that shows the top-level one absent. ⛔ Without it an empty answer is not a reading — it could just as easily be a wrong query, an unbuilt artifact, or a boot that never happened. This lane manufactured a fake zero from an error object earlier in this very shift.
Then, and only then
collect-docs.ts(see the fence above) — report instead.Fences
⛔ Never edit
content/docs/releases/. Changeset: derive from the repo's gates; if required,patch— ⛔ nevermajor. Commit trailers model-free:Co-Authored-By: Claude <noreply@anthropic.com>plus aClaude-Session:line. English. Draft PR,Fixes #19246.Generated by Claude Code
test(metadata): pin that a `packages[]` artifact's top-level-only doc…
os-project-manager commentedon Sep 20, 2026
os-dev-report
{ "issue": 19246, "status": "done", "branch": "claude/issue-19246-toplevel-docs-registration", "pr": "https://github.com/objectstack-ai/objectstack/pull/19375", "session": "session_01QCdUBjM47SxioST9z5Zwdf", "premise_still_valid": false, "summary": "The card does NOT reproduce, and that correction is the deliverable. Booted the card's own e2e multi fixture (two packages, flat src/docs/pkgdocs_index.md plus src/orders/docs/ord_playbook.md) through a real `os build` + `os dev --fresh` and asked the live surface: authenticated GET /api/v1/meta/doc returns BOTH the top-level-only doc `pkgdocs_index` (stamped _packageId com.example.pkgdocs.core) and the lit control `ord_playbook` (_packageId com.example.pkgdocs.orders), each carrying the marker written into exactly one file on disk. Both static readings were right about the two files they looked at (resolveArtifactPackageOrder does walk bodies only; app-plugin.ts registers no collections.docs) and wrong about the conclusion: the registrar is MetadataPlugin._parseAndRegisterArtifact's residual sweep in packages/metadata/src/plugin.ts, which neither reading reached, and which warns out loud when it fires. No production code changed; packages/cli/src/utils/collect-docs.ts was not touched and was not needed. The PR lands one regression pin in packages/metadata/src/plugin-artifact-packages-attribution.test.ts so the next reader finds a measurement instead of a third static reading. Recommend re-classifying #19246 as not-reproduced rather than keeping it on the bug backlog.", "tests": "BASELINE: pnpm --filter @objectstack/metadata exec vitest run --maxWorkers=2 src/plugin-artifact-packages-attribution.test.ts -> 'Test Files 1 passed (1) / Tests 11 passed (11)', at 2cc69a66, run through scripts/pm/os-verify-lock.sh (VERDICT command-exit 0). ABLATION (reverse verification, both legs from the committed state, via scripts/ablation-replace.mjs): narrow leg forced the residual sweep's guard `if (carriesPackages) {` false, package walk untouched -> on-disk proof anchor 1->0, injection 0->1, blob 0bdb14843b86 -> 1f995ab8ef4b; same vitest command -> 'Tests 3 failed | 8 passed (11)': the new 'registers BOTH ...' and 'says out loud ...' cases plus the pre-existing orphan case, while the new absence arm stayed GREEN and the control ord_playbook kept registering. RESTORE: git checkout HEAD -- packages/metadata/src/plugin.ts -> git hash-object back to the HEAD blob 0bdb14843b86, git diff HEAD empty. A blunter first leg (replacing the call itself, which throws) took 8/11 down and is why the narrow leg was run. BOOT MEASUREMENT: os build emitted top-level docs ['pkgdocs_index'] / orders body ['ord_playbook'] / core body []; os dev --fresh on two separate ports, authenticated via POST /api/v1/auth/sign-in/email; presence arm returned 3 docs (subject + control + com.objectstack.setup's own doc), absence arm (src/docs deleted, rebuilt, rebooted) returned 2 with pkgdocs_index gone -> the query can report a missing doc. Anonymous GET returns items:[] by audience design and is a fake zero, recorded as such. GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 51 families for this change set (1 path, +130/-0); all 51 run, reconciled with --ran carrying per-command exit codes -> '51 derived, 50 run, 1 NOT-MEASURED, 0 UNRUN'. NOT MEASURED: pnpm check:dual-build-cjs-loads, reason: exit 3 'PREREQUISITE NOT MET - this gate reads built output, and some package has no dist/' (13 packages unbuilt in this worktree); it needs a whole-repo pnpm build and this diff is one test file that changes no dist. Repo-wide scans (pnpm lint) and the CI-shell job steps dispatch-gates lists as unmeasurable locally are CI's run, not this branch's. Re-derived after git fetch origin main: family count unchanged at 51, nothing new to run; the tool still reports STALE TREE because origin/main keeps moving under a fixed HEAD, and the 11 stale files it names are workflow/script files no path of this diff touches.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write; every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN", "api_writes": "3 - POST /repos/objectstack-ai/objectstack/pulls (draft PR #19375); POST /repos/objectstack-ai/objectstack/issues/19375/labels (skip-changeset, via scripts/pm/label-write.mjs, read back and matching); POST /repos/objectstack-ai/objectstack/issues/19246/comments (this report). Plus 2 git pushes: the empty-branch write probe and the one commit. No PATCH of any body; the PR body was written once, on creation.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the #18431 shape makes the residual-sweep boot warning routine rather than exceptional - every multi-package project keeping a flat src/docs/ boots with '[MetadataPlugin] artifact ... carries N top-level metadata item(s) that none of its M package bodies declare', because the emitter is deliberately what produces that shape. The warning is correct and its remedy was measured to work (moving src/docs/pkgdocs_index.md to src/core/docs/ puts the doc on the core body and the top-level docs key disappears), so this is a disclosure-vs-emitter tension, not a defect. Successor named: the clause-5 acceptance for #18431 on hotcrm, which the card itself says keeps a flat src/docs/ today - that acceptance will meet this warning and should not read it as a defect.", "noted, not filed: the option-B reader ledger excludes docs as 'filesystem input' (packages/runtime/src/option-b-reader-probe.ts, around line 78), which is why this path carried no pin - quoted from the card, confirmed present, deliberately unchanged here. Whether that exclusion should move is that ledger's own card. Successor: none identified in flight; recorded so the next reader of that ledger has the pointer." ] }Generated by Claude Code
os-project-manager commentedon Sep 20, 2026
Landing record — #19246 is on
main, and it did not reproducePR #19375 merged through the queue at 15:36:23Z. Verified by content, ⛔ not by the merge event.
9602f30421b4af53dbeed5d45340a0cf79f6ea17— the exact sha the queue branchgh-readonly-queue/main/pr-19375-61dd96f2predictedgit rev-list --parents -n 1= 2 fields ⇒ squash2026-09-20T15:08:08Z— the enqueue timestamptest(metadata): #19246 does not reproduce — a packages[] artifact's top-level-only docs DO register (#19375)2cc69a663dis NOT an ancestor oforigin/mainContent
+130/−0— purely additive, so the same probe was run against both refs rather than leaning on a removed line:9602f3042161dd96f22719246pkgdocsThe line count is the load-bearing control: +130 exactly matches the diff, and the file exists on both refs.⚠️ A third probe,
residual, read 4 → 2 — it moved, but it is nonzero on both sides, so it discriminates only weakly; recorded rather than counted as one of the two clean legs.The verdict this card actually produced
⛔ The card does not reproduce. A real
os build+os dev --freshon the card's own two-package fixture returned both the top-level-onlypkgdocs_indexand the lit controlord_playbookfrom an authenticatedGET /api/v1/meta/doc, each stamped with its own_packageId.⭐ Both static readings were correct about the files they read, and wrong about the conclusion.
resolveArtifactPackageOrderreally does walk bodies only;app-plugin.tsreally does register nocollections.docs. The registration happens in a third file neither reading opened —MetadataPlugin._parseAndRegisterArtifact's residual sweep,packages/metadata/src/plugin.ts:1013(verified by the seat onorigin/main).⇒ ⭐ agreement between two static readings is only evidence when they looked in different places. These looked at the same two, so the second added confidence without adding coverage.
Why the negative result is durable
⛔ A non-reproduction reported only in prose decays the moment someone edits that path — the next reader gets a third static reading. This landed a pin instead, which goes red if the registration ever does break the way the card predicted.
Two things make the underlying measurement trustworthy: an absence arm (delete
src/docs, rebuild, reboot → the same query returns 2 withpkgdocs_indexgone, so it can report a missing doc), and ⭐ the dev finding and recording a fake zero of its own — anonymousGETreturnsitems: []by audience design, which would have "confirmed" the card.Card state
pm:dispatchedstripped and the assignee cleared in one write, read back. ⛔ Nothing was "fixed" — the round discharged the question the card was filed to ask.Generated by Claude Code
test(metadata): objectstack-ai#19246 does not reproduce — a `packages…
fix(cli): a multi-package artifact's flat src/docs rides the package …