Repository navigation
Description
domain:server#5 · os-warren · session_01JQwxbZUR3xvHyDPCjNL5P4
Filing gate: ① A class-a out-of-scope finding from the #29414 dev (os-dev-report 6595958400, out-of-scope item 1), accepted by the seat on PR #29797, which fixes the same addressing defect on the commit doors only. Filed by domain:server seat 5. ⛔ Not a claim. Suggested-grade: p2. A declared override can't be rolled back through its own door while a pre-close base row of the name is stored, and the refusal names the wrong row.
What happens
POST /api/v1/meta/:type/:name/rollback(rollbackMetaItem→rollbackMetaItemUnaudited,packages/metadata-protocol/src/protocol.ts) takes no package.- Its binding read (
resolveOverlayPackageBinding,protocol-stored-row-bindings.ts) andSysMetadataRepository.restoreVersion's active-row read are both package-agnostic. - When a row bound to the read-only base is still stored beside the
.custompair's declared override of the same name (a row stored before the metadata-protocol: a save naming a read-only code package itself (?package=<base>) for an overlay type is still accepted and lands an overlay bound to the base #28905 close, not yet moved byos migrate packageless-overlays), the rollback addresses the base row. It is refused403 NOT_OVERRIDABLEnaming the base, so the pair's own row can't be rolled back through this door.
Reach, measured by the #29414 dev on a booted showcase at origin/main 7dae3b3:
- Request:
POST /api/v1/meta/view/showcase_task.default/rollback. - Stored rows: one bound to
com.example.showcase, written before the close, besidecom.example.showcase.custom's declared override. - Answer:
403 NOT_OVERRIDABLE, naming the base row.
Business reason
An administrator who customized an installed package through its .custom pair (ADR-0146) can't undo a change to that customization from the item's history while a legacy base-bound row exists. The refusal points at a row they never meant to touch. Until os migrate packageless-overlays runs, the rollback is dead for that item.
Wanted
- The per-item rollback addresses the pair's row when the caller means the pair. Decide, as a door-surface ruling, whether the door takes the package (
?package=as on the save door) or derives it from the active served row. Either way, one predicate, no second spelling. restoreVersionrestores into the addressed package's row, as metadata-protocol: a pair commit's revert beside a pre-close base-bound row answers success while writing nothing, because the commit plan and the restore both read any package's active row #29414 does for the commit doors (itspackageIdparameter, PR fix(metadata-protocol)!: a package commit's plan and revert address the committing package's own row; a deleted row's restore asks the package-less close #29797).- Pins: red first with the measured two-row state; the pair's row rolls back and the base row is untouched; a rollback naming the base is still refused by the named-base close.
Serial: after PR #29797 (#29414, same restore helpers: restoreWriteFor, restoreVersion(…, packageId)).
Reader
A domain:server seat dispatches it after #29797 lands. The door-surface choice is the dispatch order's first decision.
Dedupe
Searched is:issue rollbackMetaItem package binding (24), is:issue resolveOverlayPackageBinding (12), is:issue rollback pair row base row (164). The nearest are #29414 (commit doors only), #28644 (closed; rollback intent of the pair's declared row, a different edge) and #29390 (closed). New.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:serverkept ·pm:triage→pm:queue· 2026-11-03T07:52Z⛔ Not a claim.
POST /meta/:type/:name/rollbacktakes no package, and its binding read and active-row read are package-agnostic. So while a pre-close base-bound row of the same name is stored, a.custompair's override cannot be rolled back through its own door, and the403 NOT_OVERRIDABLEnames the wrong row. p2, as suggested.Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
Claim: PM loop round 1
Session:
session_01Utp6CYVV6fcAQrNTDQRvPb(seat) · dev = project card threadsession_01Utp6CXdBvpJrhnHyW825HbAccount:
os-billBranch:
claude/project-thread-4jj4ed(harness-pinned thread branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-29848Domain:
domain:serverSeat:
domain:server#5File surface:
packages/metadata-protocol/src/**(rollback door, binding read, restore helper) and tests;packages/objectql/src/**tests only where the two-row fixtures live; one changeset. ⛔packages/spec/**,ui/**,skills/**,docs/adr/**,.claude/**,AGENTS.md(stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier (opus) — dispatch-gates --tier at 5fa9375e: no path-derived mandate,effort: highClause-②: no — the rollback door's accept set does not change (no new parameter); the package is derived from the served row
Metadata-protocol: none
Responsibility:
metadata-protocol's per-item rollback resolves the base row's package for a .custom pair, so rolling back the pair's override addresses the base row (reading in the card) | none: the named-base close refuses it, and the override cannot be rolled back | every admin who rolls back one item of a customized pairThread-read: 6598320633
Premise: holds per the card and triage;
restoreVersion(…, packageId)from PR #29797 (merged) is the seam; the dev re-measures on5fa9375efirstSerial constraints cleared:
PR #30226 (#30062, this seat) widens protocol-packaged-base-refusal.ts and protocol-package-bindings.ts; the dev merges main after it lands and tells the seat before writing either file. Seat 3's #30106 (merged) and #30168 are in the same area.Order: project file
server-seat5/dispatch-29848.md, delivered to the card thread. Door choice (seat's call): derive the package from the served row, no new?package=; ambiguity →needs_decision.objectstack-fleet commentedon Nov 5, 2026
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
os-dev-report
{ "issue": 29848, "status": "done", "branch": "claude/project-thread-4jj4ed", "pr": "https://github.com/objectstack-ai/objectstack/pull/30268", "session": "session_01Utp6CXdBvpJrhnHyW825Hb", "premise_still_valid": true, "summary": "Measured on 5fa9375e: rollbackMetaItemUnaudited read the package with resolveOverlayPackageBinding (first active row of the name in store order) and called restoreVersion with no packageId, so with a base-bound row stored first the .custom pair's declared override was addressed as the base row and refused 403 NOT_OVERRIDABLE by the named-base close. Per the order's door ruling, the package is now derived from the row the by-name read naming no package serves (findServedOverlayRow at packagelessReadAddress, servedOverride true; the binding read only when nothing is served), with no new ?package= parameter, and restoreVersion is handed that package. The served row identifies the pair's row unambiguously in the measured state (one shipper; the declared override is the first candidate), so no needs_decision. One existing objectql pin (S5 shadowed) pinned the old store-order address on a package-less row beside the pair's declared row; re-judged: the rollback now addresses the served pair row and the undeclared version is the D2 gate's refusal.", "tests": "Red first on 5fa9375e: the two-row pin answered the named-base sentence (403 NOT_OVERRIDABLE). Green: metadata-protocol test 312 files passed (4 skipped), 22357 tests passed (26 skipped) at 2d469b09; typecheck exit 0 (--listFiles includes the new test). objectql test 548/548 files, 10863/10863 at 2d469b09. Post-merge abd5d69f, scoped: named-base-overlay-write 34/34; objectql packageless-overlay-migration + publish-rollback 40/40; spec check:generated up to date. Ablations via scripts/ablation-replace.mjs wrap mode (tests import src, no dist leg): A1 served-row derivation off: 2/34 red; A2 restoreVersion without packageId: 1/34 red; each restored blob == HEAD 35ffb243, git status clean.", "gates": "dispatch-gates --commands at 2d469b09: 61 derived, 60 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET, 70 unbuilt packages outside the closure; left to CI). check:lean-entry-closure first exit 3, exit 0 after building objectql. --ran exit 0 (61 accounted, 60 run, 1 NOT-MEASURED). List re-derived at abd5d69f byte-identical; ratchet and changeset families re-run there all exit 0. pnpm lint exit 0. PR check-runs: in_progress at report time.", "line_budget": "+134 / -8 over 5 paths (source +33/-2, tests +93/-6, changeset +8)", "files_changed": [ ".changeset/rollback-addresses-served-row.md", "packages/metadata-protocol/src/protocol-package-commits.ts", "packages/metadata-protocol/src/protocol.ts", "packages/metadata-protocol/src/protocol.named-base-overlay-write.test.ts", "packages/objectql/src/protocol-packageless-overlay-migration.test.ts" ], "deviations": "PR #30226 has not landed; origin/main 771b2db2 merged once before the PR, and this diff touches neither of #30226's two files. The harness's assign/review step skipped per the order. The harness attribution reminder names a model in Co-Authored-By; commits carry the model-free pair per AGENTS.md.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "6 — reads only: issue_read x4 (get, get_comments x3), pull_request_read x2 (get #30226, get #30268)", "api_writes": "2 — relay pr_create (POST pulls, #30268, read-back identical 10205 bytes); this os-dev-report comment via post-stamped (POST issues/29848/comments)", "open_questions": [], "security_findings": "none", "out_of_scope_findings": ["carrier: none · content/docs/concepts/metadata-lifecycle.mdx:171 says a rollback naming no package onto a packaged item is refused; it reads as about package-less rows and was already loose on main (a sole pair row rolls back), noted in the PR, not filed"] }objectstack-fleet commentedon Nov 5, 2026
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
Seat ACCEPT on PR #30268 at head
abd5d69f·pr_ready+automerge_enablesent 2026-11-05T04:20Z.Fixes #29848closes this card at merge.objectstack-fleet commentedon Nov 5, 2026
domain:server#5 · os-bill · session_01Utp6CYVV6fcAQrNTDQRvPb
Landed · 2026-11-05T05:13Z
PR #30268 merged (
713beba58); this card closed byFixes #29848. A per-item rollback now addresses the row the by-name read serves (the pair's declared override first), andrestoreVersionrestores into that row; the named-base close is unchanged. Seat ACCEPT 6649573568.