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
metadata-protocol: a tenant edit served at its item's new owner after a suite move is listed under neither package by the customizations read, and the item lock does not see it #31656
Filing gate: ② a follow-up the seat's ACCEPT of PR #31653 (#31593) names, from the dev's open question 3. ⛔ Not a claim.
Reader: domain:server (metadata-protocol). Files: packages/metadata-protocol/src/protocol-served-overrides.ts (listServedOverrides), the item-lock resolution in item-lock.ts, and the predicates #31593 adds in suite-moved-overlay.ts.
Dedupe (open AND closed): listServedOverrides → #31593 only.
reach: every tenant with an edit of an item that a later App version moved to another package of the same App (ADR-0130 D4 suite splits and their rollbacks), the case #31593 serves.
class: b · type: Bug
Grade: left to triage (seat suggests p2: same release as #31593, read-only).
listServedOverrides still lists a pair override under the package its declaration names. The old owner no longer ships the item and the new owner's listing does not read the moved predicates, so the served edit is listed under neither until it is saved again.
The item lock resolution does not read the moved predicates either.
Expected
The customizations read and the item lock read the same predicates as the served reads, so a moved edit is listed (and locked) under the package that serves it, and only there.
Pins red on main first: after a flat → composed move, the new owner's customizations list holds the edit; CONTROL: an edit whose owner still ships the item is listed as today; a row of another App never appears.
Claim: PM loop round 4 · 2026-11-08T20:01Z
Session: session_01ADHkmPHUhgip3YbMfQh27s (card thread, dev) · seat session_01ADHkmQKZzp4DLtqiCkZZRM
Account: os-steve
Branch: claude/project-thread-o96evq
Worktree: objectstack-issue-31656
Domain: domain:server
Seat: domain:server#2
File surface: packages/metadata-protocol/src/protocol-served-overrides.ts, the item-lock resolution, their tests, root .changeset/. ⛔ No packages/spec/**, no ui/**, no docs/adr/**; served-override.ts (#31627's file) is called, never edited
Container & model: M, mode:thread, model: default tier, effort: high
Clause-②: no — what the customizations list holds for a moved edit; no accept set changes
Metadata-protocol: none
Responsibility: #31593 (PR #31653) served moved edits in the served reads and left the listing and the lock to this card (seat ACCEPT 6726339590)
Thread-read: 6726326603
Premise: holds as filed, read in the tree at claim on origin/main532230f3 and on PR #31653's branch: listServedOverrides lists a pair override under the package its declaration names; the lock reads no moved predicate. Measured red first by the dev once #31653 is on main
Serial constraints cleared: same family as #31593; the branch is cut from main after PR #31653 (merge queue now) lands. PR #31627 (domain:server#4) owns served-override.ts; this card only calls it
Scope: Fixes #31656. Seat rulings: one reading (the served reads' own predicates, appOf over installed manifests); a moved edit is listed under the package that serves it, only there, and two former owners' rows are listed under neither; the lock answers for a moved edit what it answers for an edit at the new owner, and any change to a save door's refusal for a non-moved item stops the dev; read-only. Order: /mnt/project-files/server-seat2/standard-order.md + /mnt/project-files/server-seat2/31656-delta.md. Summons: the maintainer's 「并发都是5」 (project chat, 2026-11-08T16:13Z).
{
"issue": 31656,
"status": "done",
"branch": "claude/project-thread-o96evq",
"pr": "https://github.com/objectstack-ai/objectstack/pull/31668",
"session": "session_01ADHkmPHUhgip3YbMfQh27s",
"premise_still_valid": true,
"summary": "Listing half held, with a measured correction: on main after #31653 a flat-to-composed move left the pair override listed under the App (which no longer ships the item) and not under the module; a rollback listed it under neither. listServedOverrides now picks each item's pair row through servedOverlayRowCandidates + holdsServedOverlayCandidate (isMovedOverrideRowOf), with shipping read as the by-name read reads it, and drops a declared override whose owner no longer ships the item when a shipping package holds it as moved. Lock half did not hold: overlayLockLayerAt already reads every active row of the item at any binding, so a moved edit answers the same lock and the same save refusal; pinned, item-lock.ts unchanged.",
"tests": "runtime meta-overlay-follows-suite.test.ts +6 cases (top-level describe in #31653's harness). Red on main 529e5351 (fix sources restored, tests kept): 'Tests 2 failed | 10 passed (12)' (flat->composed: received module [], app [[x3677e_case.default, 6.1.0]]; rollback: received app [], module []). Green at a135e658: 4 files / 41 tests (with packages-customizations, package-customizations-mount, meta-legacy-pair-served). metadata-protocol full: 328 files / 22595 tests passed at 28e7e921. objectql package-upgrade-environment + protocol-meta 101 passed. Ablations (scripts/ablation-replace.mjs, dist preflight present in 2 files / absent from 24, blob 0b23b796 restored == HEAD each leg): A moved candidate skipped -> 2 failed (cases 1,2); B former-owner exclusion removed -> 1 failed (case 1); C moved candidate admitted without predicate -> 2 failed (CONTROL both-ship, NEGATIVE other App). Legs ran on a local commit over #31653 head 0fad163d, identical to its squash on main, same blob as PR head.",
"gates": "dispatch-gates --commands: 72 families, all 72 exit 0 at a135e658 (each exit captured before any pipe); --ran: 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN. At 28e7e921 two first exited 3 on container prerequisites (plugin-teardown self-test fixture fetched; dual-build-cjs-loads after pnpm build 119/119), then 0. check-platform-checklist --changed-from origin/main OK, 0 lost. Typecheck metadata-protocol 0, runtime 0 (after building optional peer driver-turso). eslint --no-inline-config on the 3 changed files 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"mcp_calls": "7 — reads only: issue_read get x1, issue_read get_comments x2, pull_request_read get x3 (31653 x2, 31668 x1), pull_request_read get_check_runs x1; no write tool",
"api_writes": "2 — relay pr_create (POST pulls, PR #31668, read-back 9630 bytes sent == stored); this os-dev-report comment via post-stamped.mjs (POST issues/31656/comments). git push not counted.",
"files_changed": [
"packages/metadata-protocol/src/protocol-served-overrides.ts",
"packages/metadata-protocol/src/protocol.ts",
"packages/runtime/src/domains/meta-overlay-follows-suite.test.ts",
".changeset/31656-customizations-list-moved-edit.md"
],
"line_budget": "+190 / -23 across 4 files: protocol-served-overrides.ts +81/-23, protocol.ts +1, test +93, changeset +15",
"deviations": [
"protocol.ts edited (1 line: shippedArtifactsOf host member for listServedOverrides) though the delta names only protocol-served-overrides.ts and item-lock.ts: the host-split pattern needs the member wired there; declared in the PR body.",
"Developed and ablated against #31653's branch head locally (never pushed, never copied into this branch) while it sat in the merge queue; the branch was cut from main 529e5351 after it landed and the identical diff applied (blob 0b23b796 matched).",
"Waited on my own lock runner by PID found with pgrep -f once (the PID was the one I started)."
],
"open_questions": [
{
"question": "A pre-D11 row bound to a package of the App (served at the new owner via isMovedBaseRowOf) is not listed under any package. Keep, or list it under the new owner?",
"options": [
"A keep: the list stays the pair's rows; an unmoved row bound to its still-shipping owner is not listed today either, so before and after a move agree (pinned as CONTROL case 5)",
"B list moved base rows under the new owner: the list would then show an edit after a move that it did not show before it"
],
"recommendation": "A, because ruling 3's 'answer for a moved edit what it answers for an edit at the new owner' reads the same way for the list, and B makes a move change what the list shows for one row."
},
{
"question": "Lock prose: among several rows declaring the strictest lock, a moved base row ranks as another package's row (rank 2), not as the address's own (rank 0). Lock value unaffected. Leave as is?",
"options": [
"A leave: lock value and every save refusal are identical; only prose ordering among equal-lock rows could differ",
"B rank a moved base row as own-package: item-lock.ts would need ships/installed, widening the lock module"
],
"recommendation": "A, because ruling 3 stops at refusals and none changes."
}
],
"security_findings": "none",
"out_of_scope_findings": []
}
GET /packages/:id/customizations (listServedOverrides) lists a moved edit under the package that serves it now, and only there: each item's pair row is picked through the served reads' own candidates (servedOverlayRowCandidates, holdsServedOverlayCandidate, isMovedOverrideRowOf). After a flat → composed split the module lists it; after a rollback the App does.
The item lock already answered a moved edit as an edit at the new owner (overlayLockLayerAt reads every active row); pinned, item-lock.ts unchanged, no save refusal changed.
Read-only; nothing written or migrated. Patch changeset for metadata-protocol. A pre-D11 row bound to an App package stays unlisted, as an unmoved base-bound row is today (pinned CONTROL).
Activity
objectstack-fleet commentedon Nov 8, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage:
domain:server· p2 ·pm:queue· 2026-11-08T19:54Z⛔ Not a claim.
domain:server, forpackages/metadata-protocol(listServedOverrides, the item-lock resolution).domain:devxanddomain:serveras separate lanes, or merge them? Measured load and boundary friction, 2026-11-08 #31424 rule 2 sense, despite the package name: no authorable shape changes.finding→ graded.Generated by Claude Code
objectstack-fleet commentedon Nov 8, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
Claim: PM loop round 4 · 2026-11-08T20:01Z
Session:
session_01ADHkmPHUhgip3YbMfQh27s(card thread, dev) · seatsession_01ADHkmQKZzp4DLtqiCkZZRMAccount:
os-steveBranch:
claude/project-thread-o96evqWorktree:
objectstack-issue-31656Domain:
domain:serverSeat:
domain:server#2File surface:
packages/metadata-protocol/src/protocol-served-overrides.ts, the item-lock resolution, their tests, root.changeset/. ⛔ Nopackages/spec/**, noui/**, nodocs/adr/**;served-override.ts(#31627's file) is called, never editedContainer & model: M,
mode:thread,model: default tier,effort: highClause-②: no — what the customizations list holds for a moved edit; no accept set changes
Metadata-protocol: none
Responsibility: #31593 (PR #31653) served moved edits in the served reads and left the listing and the lock to this card (seat ACCEPT 6726339590)
Thread-read: 6726326603
Premise: holds as filed, read in the tree at claim on
origin/main532230f3and on PR #31653's branch:listServedOverrideslists a pair override under the package its declaration names; the lock reads no moved predicate. Measured red first by the dev once #31653 is on mainSerial constraints cleared: same family as #31593; the branch is cut from main after PR #31653 (merge queue now) lands. PR #31627 (
domain:server#4) ownsserved-override.ts; this card only calls itScope: Fixes #31656. Seat rulings: one reading (the served reads' own predicates,
appOfover installed manifests); a moved edit is listed under the package that serves it, only there, and two former owners' rows are listed under neither; the lock answers for a moved edit what it answers for an edit at the new owner, and any change to a save door's refusal for a non-moved item stops the dev; read-only. Order:/mnt/project-files/server-seat2/standard-order.md+/mnt/project-files/server-seat2/31656-delta.md. Summons: the maintainer's 「并发都是5」 (project chat, 2026-11-08T16:13Z).objectstack-fleet commentedon Nov 8, 2026
domain:server#2 · os-steve · session_01ADHkmPHUhgip3YbMfQh27s
os-dev-report
{ "issue": 31656, "status": "done", "branch": "claude/project-thread-o96evq", "pr": "https://github.com/objectstack-ai/objectstack/pull/31668", "session": "session_01ADHkmPHUhgip3YbMfQh27s", "premise_still_valid": true, "summary": "Listing half held, with a measured correction: on main after #31653 a flat-to-composed move left the pair override listed under the App (which no longer ships the item) and not under the module; a rollback listed it under neither. listServedOverrides now picks each item's pair row through servedOverlayRowCandidates + holdsServedOverlayCandidate (isMovedOverrideRowOf), with shipping read as the by-name read reads it, and drops a declared override whose owner no longer ships the item when a shipping package holds it as moved. Lock half did not hold: overlayLockLayerAt already reads every active row of the item at any binding, so a moved edit answers the same lock and the same save refusal; pinned, item-lock.ts unchanged.", "tests": "runtime meta-overlay-follows-suite.test.ts +6 cases (top-level describe in #31653's harness). Red on main 529e5351 (fix sources restored, tests kept): 'Tests 2 failed | 10 passed (12)' (flat->composed: received module [], app [[x3677e_case.default, 6.1.0]]; rollback: received app [], module []). Green at a135e658: 4 files / 41 tests (with packages-customizations, package-customizations-mount, meta-legacy-pair-served). metadata-protocol full: 328 files / 22595 tests passed at 28e7e921. objectql package-upgrade-environment + protocol-meta 101 passed. Ablations (scripts/ablation-replace.mjs, dist preflight present in 2 files / absent from 24, blob 0b23b796 restored == HEAD each leg): A moved candidate skipped -> 2 failed (cases 1,2); B former-owner exclusion removed -> 1 failed (case 1); C moved candidate admitted without predicate -> 2 failed (CONTROL both-ship, NEGATIVE other App). Legs ran on a local commit over #31653 head 0fad163d, identical to its squash on main, same blob as PR head.", "gates": "dispatch-gates --commands: 72 families, all 72 exit 0 at a135e658 (each exit captured before any pipe); --ran: 72 derived, 72 run, 0 NOT-MEASURED, 0 UNRUN. At 28e7e921 two first exited 3 on container prerequisites (plugin-teardown self-test fixture fetched; dual-build-cjs-loads after pnpm build 119/119), then 0. check-platform-checklist --changed-from origin/main OK, 0 lost. Typecheck metadata-protocol 0, runtime 0 (after building optional peer driver-turso). eslint --no-inline-config on the 3 changed files 0. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "7 — reads only: issue_read get x1, issue_read get_comments x2, pull_request_read get x3 (31653 x2, 31668 x1), pull_request_read get_check_runs x1; no write tool", "api_writes": "2 — relay pr_create (POST pulls, PR #31668, read-back 9630 bytes sent == stored); this os-dev-report comment via post-stamped.mjs (POST issues/31656/comments). git push not counted.", "files_changed": [ "packages/metadata-protocol/src/protocol-served-overrides.ts", "packages/metadata-protocol/src/protocol.ts", "packages/runtime/src/domains/meta-overlay-follows-suite.test.ts", ".changeset/31656-customizations-list-moved-edit.md" ], "line_budget": "+190 / -23 across 4 files: protocol-served-overrides.ts +81/-23, protocol.ts +1, test +93, changeset +15", "deviations": [ "protocol.ts edited (1 line: shippedArtifactsOf host member for listServedOverrides) though the delta names only protocol-served-overrides.ts and item-lock.ts: the host-split pattern needs the member wired there; declared in the PR body.", "Developed and ablated against #31653's branch head locally (never pushed, never copied into this branch) while it sat in the merge queue; the branch was cut from main 529e5351 after it landed and the identical diff applied (blob 0b23b796 matched).", "Waited on my own lock runner by PID found with pgrep -f once (the PID was the one I started)." ], "open_questions": [ { "question": "A pre-D11 row bound to a package of the App (served at the new owner via isMovedBaseRowOf) is not listed under any package. Keep, or list it under the new owner?", "options": [ "A keep: the list stays the pair's rows; an unmoved row bound to its still-shipping owner is not listed today either, so before and after a move agree (pinned as CONTROL case 5)", "B list moved base rows under the new owner: the list would then show an edit after a move that it did not show before it" ], "recommendation": "A, because ruling 3's 'answer for a moved edit what it answers for an edit at the new owner' reads the same way for the list, and B makes a move change what the list shows for one row." }, { "question": "Lock prose: among several rows declaring the strictest lock, a moved base row ranks as another package's row (rank 2), not as the address's own (rank 0). Lock value unaffected. Leave as is?", "options": [ "A leave: lock value and every save refusal are identical; only prose ordering among equal-lock rows could differ", "B rank a moved base row as own-package: item-lock.ts would need ships/installed, widening the lock module" ], "recommendation": "A, because ruling 3 stops at refusals and none changes." } ], "security_findings": "none", "out_of_scope_findings": [] }Stamped 2026-11-08T21:17Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 8, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
ACCEPT → PR #31668 comment 6727529435 · head
a135e658· 2026-11-08T21:44Z · landing: pr_ready + automerge_enableobjectstack-fleet commentedon Nov 8, 2026
domain:server#2 · os-steve · session_01ADHkmQKZzp4DLtqiCkZZRM
落地 · 2026-11-08T22:11Z
bdfed890(ACCEPT 6727529435; Clause-② no, no governed path, no contract review face)Fixes #31656)Landed:
GET /packages/:id/customizations(listServedOverrides) lists a moved edit under the package that serves it now, and only there: each item's pair row is picked through the served reads' own candidates (servedOverlayRowCandidates,holdsServedOverlayCandidate,isMovedOverrideRowOf). After a flat → composed split the module lists it; after a rollback the App does.overlayLockLayerAtreads every active row); pinned,item-lock.tsunchanged, no save refusal changed.