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
packages: the base export carries a published dashboard or report override from its .custom pair, where ADR-0146 D8 item 3 says the base export is unchanged #29563
Filing gate: ① a measured contract break, found by the #28579 slice 3 run (run record #29560, PR #29559FOLLOW-UPS.md §15b item 1). The run reproduced it through Studio and over the API. The seat has not re-measured it.
Reader: domain:server (the export read in packages/runtime / packages/metadata-protocol).
Dedupe (open AND closed): export override, ADR-0146 D8 export. #28409 (closed) built the one effective read, and #28914 (open) is the whole-ontology export. Neither covers a base export that serves the pair's item.
reach: any read-only base whose .custom pair has published a dashboard or report override. Measured on com.example.showcase with showcase_ops_dashboard and showcase_hours_by_status.
type: Bug
What happens
After a published override of showcase_ops_dashboard (or the report showcase_hours_by_status) in com.example.showcase.custom, GET /api/v1/packages/com.example.showcase/export carries the item with the edited label and the overrides key. A published view override does not show up in the base export, so the types disagree with each other.
Why it is wrong
ADR-0146 D8 item 3: "GET /packages/hotcrm.custom/export carries the overriding item with its overrides block; GET /packages/hotcrm/export carries the base unchanged." An export of the base that carries the customer's override cannot be redeployed as the vendor's package, and it stamps a .custom item into the base's file.
D8 item 2 also lists "the export of X's app surface" among the reads that serve the override. The fix should say which export that phrase means, so that it is not read as GET /packages/X/export. If it does mean that route, the ADR contradicts itself, and the owner should rule before the code changes.
Wanted
GET /packages/<base>/export carries the base's own documents for every type, the same as it already does for views. The pair's export keeps the override with its overrides block. Add a pin per type (view, dashboard, report at least), and fix studio-authoring.package-customize-restore-display acceptance[4] when it passes.
Read fresh. Reproduced through Studio and the API: the base export carries a published dashboard or report override from its .custom pair, where ADR-0146 D8 item 3 says the base export is unchanged. A contract break, p2.
Claim: PM loop round 3 · 2026-11-02T19:41Z
Session: session_01JQwxbacSXJQqAztgt4UMrS (seat); dev = card thread session_01JQwxbXd7sSh6S5XDDEd7Ei
Account: os-warren
Branch: claude/project-thread-1ikc5d (a project card thread pushes only its assigned branch; measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-29563
Domain: domain:server
Seat: domain:server#4
File surface: packages/runtime/src/domains/packages.ts (the export path: GET /packages/:id/export at ~L2543 and assemblePackageManifest at ~L3299, NOT the CUSTOMISE_BESIDE_REMEDY region that #29568 holds), tests beside it, one @objectstack/runtime.changeset/*.md (stop on breach; explain in the report). ⛔ No packages/spec/**, no packages/metadata-protocol/src/protocol.ts (seat 5 freeze until 2026-11-03 06:00Z).
Container & model: M, mode:thread (the os-dev agent type is not loaded in seat sessions), model: TIER_DEFAULT (no path-derived mandate), effort: project default (the maintainer sets effort)
Clause-②: no
Metadata-protocol: none
Responsibility: n/a — contract break against ADR-0146 D8 item 3, reproduced red first by the dev
Thread-read: 6585691015
Premise: to measure (dev reproduces red per type: view, dashboard, report); if ADR-0146 D8 item 2 means GET /packages/X/export, the dev stops and reports needs_decision
Serial constraints cleared: #29568 (server#1, claim 6586610006) shares packages.ts, other region; the dev merges main before the PR
{
"issue": 29563,
"status": "done",
"branch": "claude/project-thread-1ikc5d",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29597",
"session": "session_01JQwxbXd7sSh6S5XDDEd7Ei",
"premise_still_valid": true,
"summary": "Reproduced red first over the real protocol and engine: after a published .custom override, GET /packages/BASE/export carried two items for dashboard and for report (the base's own and the override with its overrides block); view was already clean. Cause, read off the registry: the publish write-through registers the pair's row in the SchemaRegistry bare slot wearing the base's artifact envelope (lookupArtifactItem falls back to the base's code artifact), so the per-package layer lists it under the base; the #22057 guard that spares views is view-only. Fix at the claimed door: assemblePackageManifest drops, from a package's own per-package export, any item whose overrides.package names that same package; the pair's export is unchanged and a protocol with no per-package layer is read as before. ADR-0146 D8 item 2 read as the pair's export, not GET /packages/X/export (item 3 names that route with the opposite rule), so no needs_decision; protocol.ts not touched.",
"tests": "New packages/runtime/src/domains/packages-export-base-unchanged-per-type.integration.test.ts (real HttpDispatcher door, real ObjectStackProtocolImplementation + ObjectQL on SQLite, pair installed through the package door, draft save + per-item publish per type). Before the fix: Tests 2 failed | 1 passed, 'the base's dashboard export: expected [ Shipped label, Edited label ] to deeply equal [ Shipped label ]' and the same for report. After: the three export test files Test Files 3 passed (3), Tests 9 passed (9). Ablation via scripts/ablation-replace.mjs (anchor 1 to 0, blob f472e256 to 5958b472; the test resolves packages.ts from source, no dist in the path): dashboard and report red with the same messages, view green; restore blob == HEAD, git diff HEAD empty. Full pnpm --filter @objectstack/runtime test at e81217fe: Test Files 526 passed (526), Tests 8489 passed | 19 skipped, lock VERDICT command-exit 0. pnpm --filter @objectstack/runtime typecheck at e81217fe: exit 0.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack: 60 derived; ran on 4a7b14f4 (the only later commit, e81217fe, deletes one unused const in the new test): 58 exit 0; NOT MEASURED exit 3 prerequisite: node scripts/check-plugin-teardown-shape.mjs --self-test (fixture commit outside the shallow clone, checker-health only) and pnpm check:dual-build-cjs-loads (needs every package dist; only the runtime closure built). dispatch-gates --ran: '60 derived famil(ies) accounted for, 58 run, 2 NOT-MEASURED', exit 0. pnpm lint: exit 0. PR check-runs: in_progress at report time (not awaited, per os-dev).",
"dogfood_battery": "n/a, no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2: fleet-write relay pr_create (POST repos/objectstack-ai/objectstack/dispatches, run 41521675795, PR #29597, 7509 bytes sent and stored identical); this os-dev-report comment via post-stamped.mjs (POST issues/29563/comments through the relay). git push is not counted.",
"open_questions": [
{
"question": "ADR-0146 D8 item 2 lists 'the export of X's app surface' among the reads that serve the override. This PR reads it as the pair's export (GET /packages/X.custom/export), consistent with item 3 and the getMetaItemsPerPackage docblock. Should the ADR say so in words, as the card asks?",
"options": [
"A: a one-line docs/adr edit in its own docs-only PR: replace 'and the export of X's app surface' with 'and the export of X's pair (GET /packages/X.custom/export, item 3)'",
"B: leave the ADR text; the per-type pin and item 3 already state the rule"
],
"recommendation": "A, because the card names the ambiguity as a defect of its own and the edit is outside this claim's file surface; it is a seat-filed docs-only change."
}
],
"security_findings": "none",
"out_of_scope_findings": [
"class: b · upstream of this card, in packages/metadata-protocol/src/protocol.ts (frozen, outside the claim) · Seam: runtime:hydrateOverlayIntoRegistry (protocol.ts) then registry.registerItem bare slot then readFlattenedMetaItems per-package layer · a published .custom row of a name the base ships is registered in the bare slot under the base's envelope (_packageId the base's, _provenance package, so isCodeArtifactBody true) for every type but view; measured in the new pin's harness by reading engine.registry for dashboard and report. Minimal change once the freeze lifts: widen the #22057 guard in hydrateOverlayIntoRegistry (anotherPackageShips for a row bound to another package) beyond canonicalType view, or pass the row's own package to the envelope so no other package's artifact is lent; then the export filter becomes a second line of defence. reach: the export door measured (fixed here); other readers of the per-package layer (the anonymous form doors' withdrawal judgement) not measured · dedupe words: hydrateOverlayIntoRegistry envelope pair, bare slot override provenance, 22057 view-only guard · carrier: domain:server seat, after the protocol.ts freeze lifts",
"carrier: seat · studio-authoring.package-customize-restore-display acceptance[4] (docs/qa/platform-checklist/areas/studio-authoring.json) is a live-run record outside this claim; mark it once a live run reads the base export clean · noted, not filed"
],
"body_amendments": "none",
"deviations": "The final gate union ran on 4a7b14f4, one commit before head; the head commit only deletes an unused const in the new test file, and runtime typecheck, the full runtime suite and pnpm lint ran at head e81217fe. main moved 11 commits after the merge (none touch this PR's files); not re-merged."
}
Release: claim 6586728875 (session_01JQwxbacSXJQqAztgt4UMrS, card thread session_01JQwxbXd7sSh6S5XDDEd7Ei, branch claude/project-thread-1ikc5d) · full landing
Produce: PR #29597 merged as 81cd9eb0 at 2026-11-02T21:20Z (a package's own export leaves out any item that declares it overrides that package, so the base export carries the base unchanged per ADR-0146 D8 item 3; ACCEPT 6588421387). Fixes #29563 closed this card as completed.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
pm:queue· 2026-11-02T18:57Z⛔ Not a claim.
.custompair, where ADR-0146 D8 item 3 says the base export is unchanged. A contract break, p2.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS
Claim: PM loop round 3 · 2026-11-02T19:41Z
Session:
session_01JQwxbacSXJQqAztgt4UMrS(seat); dev = card threadsession_01JQwxbXd7sSh6S5XDDEd7EiAccount:
os-warrenBranch:
claude/project-thread-1ikc5d(a project card thread pushes only its assigned branch; measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-29563Domain:
domain:serverSeat:
domain:server#4File surface:
packages/runtime/src/domains/packages.ts(the export path:GET /packages/:id/exportat ~L2543 andassemblePackageManifestat ~L3299, NOT theCUSTOMISE_BESIDE_REMEDYregion that #29568 holds), tests beside it, one@objectstack/runtime.changeset/*.md(stop on breach; explain in the report). ⛔ Nopackages/spec/**, nopackages/metadata-protocol/src/protocol.ts(seat 5 freeze until 2026-11-03 06:00Z).Container & model:
M,mode:thread(the os-dev agent type is not loaded in seat sessions),model: TIER_DEFAULT (no path-derived mandate),effort: project default (the maintainer sets effort)Clause-②: no
Metadata-protocol: none
Responsibility:
n/a — contract break against ADR-0146 D8 item 3, reproduced red first by the devThread-read: 6585691015
Premise: to measure (dev reproduces red per type: view, dashboard, report); if ADR-0146 D8 item 2 means
GET /packages/X/export, the dev stops and reportsneeds_decisionSerial constraints cleared: #29568 (server#1, claim 6586610006) shares
packages.ts, other region; the dev mergesmainbefore the PRobjectstack-fleet commentedon Nov 2, 2026
domain:server#4 · os-warren · session_01JQwxbXd7sSh6S5XDDEd7Ei
os-dev-report
{ "issue": 29563, "status": "done", "branch": "claude/project-thread-1ikc5d", "pr": "https://github.com/objectstack-ai/objectstack/pull/29597", "session": "session_01JQwxbXd7sSh6S5XDDEd7Ei", "premise_still_valid": true, "summary": "Reproduced red first over the real protocol and engine: after a published .custom override, GET /packages/BASE/export carried two items for dashboard and for report (the base's own and the override with its overrides block); view was already clean. Cause, read off the registry: the publish write-through registers the pair's row in the SchemaRegistry bare slot wearing the base's artifact envelope (lookupArtifactItem falls back to the base's code artifact), so the per-package layer lists it under the base; the #22057 guard that spares views is view-only. Fix at the claimed door: assemblePackageManifest drops, from a package's own per-package export, any item whose overrides.package names that same package; the pair's export is unchanged and a protocol with no per-package layer is read as before. ADR-0146 D8 item 2 read as the pair's export, not GET /packages/X/export (item 3 names that route with the opposite rule), so no needs_decision; protocol.ts not touched.", "tests": "New packages/runtime/src/domains/packages-export-base-unchanged-per-type.integration.test.ts (real HttpDispatcher door, real ObjectStackProtocolImplementation + ObjectQL on SQLite, pair installed through the package door, draft save + per-item publish per type). Before the fix: Tests 2 failed | 1 passed, 'the base's dashboard export: expected [ Shipped label, Edited label ] to deeply equal [ Shipped label ]' and the same for report. After: the three export test files Test Files 3 passed (3), Tests 9 passed (9). Ablation via scripts/ablation-replace.mjs (anchor 1 to 0, blob f472e256 to 5958b472; the test resolves packages.ts from source, no dist in the path): dashboard and report red with the same messages, view green; restore blob == HEAD, git diff HEAD empty. Full pnpm --filter @objectstack/runtime test at e81217fe: Test Files 526 passed (526), Tests 8489 passed | 19 skipped, lock VERDICT command-exit 0. pnpm --filter @objectstack/runtime typecheck at e81217fe: exit 0.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack: 60 derived; ran on 4a7b14f4 (the only later commit, e81217fe, deletes one unused const in the new test): 58 exit 0; NOT MEASURED exit 3 prerequisite: node scripts/check-plugin-teardown-shape.mjs --self-test (fixture commit outside the shallow clone, checker-health only) and pnpm check:dual-build-cjs-loads (needs every package dist; only the runtime closure built). dispatch-gates --ran: '60 derived famil(ies) accounted for, 58 run, 2 NOT-MEASURED', exit 0. pnpm lint: exit 0. PR check-runs: in_progress at report time (not awaited, per os-dev).", "dogfood_battery": "n/a, no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2: fleet-write relay pr_create (POST repos/objectstack-ai/objectstack/dispatches, run 41521675795, PR #29597, 7509 bytes sent and stored identical); this os-dev-report comment via post-stamped.mjs (POST issues/29563/comments through the relay). git push is not counted.", "open_questions": [ { "question": "ADR-0146 D8 item 2 lists 'the export of X's app surface' among the reads that serve the override. This PR reads it as the pair's export (GET /packages/X.custom/export), consistent with item 3 and the getMetaItemsPerPackage docblock. Should the ADR say so in words, as the card asks?", "options": [ "A: a one-line docs/adr edit in its own docs-only PR: replace 'and the export of X's app surface' with 'and the export of X's pair (GET /packages/X.custom/export, item 3)'", "B: leave the ADR text; the per-type pin and item 3 already state the rule" ], "recommendation": "A, because the card names the ambiguity as a defect of its own and the edit is outside this claim's file surface; it is a seat-filed docs-only change." } ], "security_findings": "none", "out_of_scope_findings": [ "class: b · upstream of this card, in packages/metadata-protocol/src/protocol.ts (frozen, outside the claim) · Seam: runtime:hydrateOverlayIntoRegistry (protocol.ts) then registry.registerItem bare slot then readFlattenedMetaItems per-package layer · a published .custom row of a name the base ships is registered in the bare slot under the base's envelope (_packageId the base's, _provenance package, so isCodeArtifactBody true) for every type but view; measured in the new pin's harness by reading engine.registry for dashboard and report. Minimal change once the freeze lifts: widen the #22057 guard in hydrateOverlayIntoRegistry (anotherPackageShips for a row bound to another package) beyond canonicalType view, or pass the row's own package to the envelope so no other package's artifact is lent; then the export filter becomes a second line of defence. reach: the export door measured (fixed here); other readers of the per-package layer (the anonymous form doors' withdrawal judgement) not measured · dedupe words: hydrateOverlayIntoRegistry envelope pair, bare slot override provenance, 22057 view-only guard · carrier: domain:server seat, after the protocol.ts freeze lifts", "carrier: seat · studio-authoring.package-customize-restore-display acceptance[4] (docs/qa/platform-checklist/areas/studio-authoring.json) is a live-run record outside this claim; mark it once a live run reads the base export clean · noted, not filed" ], "body_amendments": "none", "deviations": "The final gate union ran on 4a7b14f4, one commit before head; the head commit only deletes an unused const in the new test file, and runtime typecheck, the full runtime suite and pnpm lint ran at head e81217fe. main moved 11 commits after the merge (none touch this PR's files); not re-merged." }Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#4 · os-warren · session_01JQwxbacSXJQqAztgt4UMrS
Landing record · #29563 · PR #29597 · 2026-11-02T21:21Z
git ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-29597-*'git merge-base --is-ancestor 81cd9eb0 origin/maingit grep -n "function declaresOverrideOf" origin/main -- packages/runtime/src/domains/packages.tsRelease: claim
6586728875(session_01JQwxbacSXJQqAztgt4UMrS, card threadsession_01JQwxbXd7sSh6S5XDDEd7Ei, branchclaude/project-thread-1ikc5d) · full landingProduce: PR #29597 merged as
81cd9eb0at 2026-11-02T21:20Z (a package's own export leaves out any item that declares it overrides that package, so the base export carries the base unchanged per ADR-0146 D8 item 3; ACCEPT 6588421387).Fixes #29563closed this card as completed.protocol.ts: the hydrator lends the base's envelope to a.customrow for every non-view type), docs(adr-0146): D8 item 2's "the export of X's app surface" can be read as GET /packages/X/export, which item 3 says carries the base unchanged; name the export it means #29601 (ADR-0146 D8 item 2 wording).pm:dispatchedremoved; the card is closed.