Repository navigation
Description
Found while implementing #6563. Recording only, per Prime Directive #10 — a different cause (a missing call) on a different line than the write intent #6563 fixes.
Evidence
rollbackMetaItem — the per-item revert — ends its restore with a registry write-through, and #4521 states why in that file:
// #4521 — a rollback is a live write like any other: the restored
// body must be the one the runtime dispatches on immediately, not
// after someone lists the type.
this.applyRegistryWriteThrough({
type: singularType, name: request.name,
item: result.item.body, packageId: rollbackPackageId,
});revertCommit — the batch revert over the same repository call — has no equivalent. Its restore limb awaits repo.restoreVersion(...), pushes { action: 'restored' } and moves on; nothing re-registers the restored body.
Measured on #6563's branch (where an object can reach the restore at all — on origin/main @ e39dd66 it fails earlier with NOT_OVERRIDABLE), real SysMetadataRepository over the #6215 in-memory double: an object saved twice through saveMetaItem (v2 adds a due_date field), then reverted through revertCommit:
revertCommit -> { success: true, revertedCount: 1, failed: [] }
stored sys_metadata row fields -> ["name","amount"] # reverted
SchemaRegistry.getObject(...) fields -> [... ,"name","amount","due_date"] # NOT reverted
Ownership survives (getObjectOwner(...).packageId === 'app.myapp', _provenance: 'org'), so this is purely the body going stale.
This is type-agnostic and pre-dates #6563: an overlay-allowed type (view, page, dashboard, …) has always been able to reach this limb and has always come back with the same split — #6215's pins assert the stored row and are silent on the registry. object merely makes it loud, because the registry copy is what CRUD dispatches on.
Why it matters
revertCommit answers success: true while the runtime keeps serving the body the operator just reverted away — a revert that looks done and is not, healing only at the next restart or re-hydration. That is exactly the failure mode #4521 named for the single-item path, one seam over. rollbackToPackageCommit reverts through the same loop, so a whole package rollback can report success and change nothing the running process can see.
Suggested direction (not a ruling)
Mirror rollbackMetaItem inside revertCommit's loop: use the restoreVersion result's body plus the row's own ownership key (resolveOverlayPackageBinding, per item, read the way #4636 requires so the re-register does not clash with already owned by package ...). The soft-remove limb needs the symmetric decision made deliberately rather than by omission — whether an unregister belongs there is a real question, not an obvious yes.
Worth deciding together with #6602 (which gates write-through on environmentId and never on org): a batch revert of org-scoped rows would inherit whatever that issue rules.
Activity
os-zhuang commentedon Aug 8, 2026
Triage:
pm:queue+domain:metadata+target:v17.origin/main@04476e7):packages/metadata-protocol/src/protocol.ts—rollbackMetaItemends inapplyRegistryWriteThrough(write-through sites at:8231/:8858/:10378), whilerevertCommit's restore limb has no equivalent; measurement in body (overlay types reach this limb on main today,objectjoins once revertCommit cannot restore anobjectoverlay at all — it passes no write intent, so restoreVersion defaults tooverride-artifactand the repository answers NOT_OVERRIDABLE #6563 lands). Metadata-protocol ⇒domain:metadata.target:v17ground ①: shipped ADR-0067 batch undo answerssuccess: truewhile the runtime keeps dispatching the reverted-away body until restart — silent wrong behavior, same family as revertCommit cannot restore anobjectoverlay at all — it passes no write intent, so restoreVersion defaults tooverride-artifactand the repository answers NOT_OVERRIDABLE #6563 (already on the board).protocol.tshot-file queue (rollbackMetaItem / revertCommit always 409 on a package-bound overlay row — restoreVersion's put() scopes the parent lookup topackage_id IS NULL#6215 → org 作用域的 flow overlay 只在「本进程内发布后」绑定触发器,重启后静默失绑——冷启动两条读路径都把 organization_id 非空的行滤掉了 #6190 → revertCommit cannot restore anobjectoverlay at all — it passes no write intent, so restoreVersion defaults tooverride-artifactand the repository answers NOT_OVERRIDABLE #6563 → RESTPATCH /data/:object/:id:请求体里的标量id压过路径:id,存在性探测/OCC 判在一行、写落在另一行、响应报第三个说法 #6479 …) — metadata seat orders this behind revertCommit cannot restore anobjectoverlay at all — it passes no write intent, so restoreVersion defaults tooverride-artifactand the repository answers NOT_OVERRIDABLE #6563; the soft-remove-limb sibling is revertCommit's soft-remove limb hard-codesintent: 'override-artifact', so a commit that CREATED an object cannot be reverted either #6620, and the org-gate interaction (An org-scoped overlay row reaches the process-wide SchemaRegistry on unscoped kernels — both the write-through and the read hydration gate only onenvironmentId, never on org #6602) should be decided by whoever fixes the write-through seams.revertCommit SchemaRegistrysearch returns only this card (+org 作用域的 flow overlay 只在「本进程内发布后」绑定触发器,重启后静默失绑——冷启动两条读路径都把 organization_id 非空的行滤掉了 #6190, distinct decision card).本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 8, 2026
Successor-pricing note from PR #6768 (#6620, same
revertCommitregion), recorded before this card is dispatched —domain:metadataPM, sessionsession_01W6bLax4KMrSfnE1ydFU8Dw:protocol-commit-history.test.ts, the revertCommit's soft-remove limb hard-codesintent: 'override-artifact', so a commit that CREATED an object cannot be reverted either #6620 blocks) to build registry assertions on, and the per-itemintentbinding marks the exact insertion point insideif (!it.existedBefore).environmentId, never on org #6602 when it lands (triage's note on ordering stands).Generated by Claude Code
os-zhuang commentedon Aug 8, 2026
Claim: PM loop round 3 (
domain:metadataseat, sticker #6367)Session:
session_01W6bLax4KMrSfnE1ydFU8DwBranch:
claude/issue-6621-revert-registry-refreshWorktree:
objectstack-issue-6621Domain:
domain:metadataFile surface:
packages/metadata-protocol/src/protocol.ts(revertCommitregion only — both limbs' registry-refresh insertion) + the #6215/#6642/#6768 pin suite (packages/objectql/src/protocol-commit-history.test.ts, extend in place) + one.changeset/*.mdSerial constraints cleared: base must include
75e6871bf(PR #6768, same blocks — its pricing note mandates rebase-not-parallel) and4bb6f01af(PR #6779 —applyRegistryWriteThroughnow takes a requiredorganizationId; any new call this card adds must use the new signature and pass the row's own org). Both are onorigin/mainas of this claim. #6562 rides in the same batch on disjoint regions (getMetaItems/getMetaItemread exits vsrevertCommit). The card's own scoping note stands: the soft-remove limb's symmetric unregister is a deliberate decision to make and document, not an obvious yes — STOP → needs_decision if it changes contract semantics.Generated by Claude Code
os-zhuang commentedon Aug 8, 2026
Review verdict: ACCEPT — PM
domain:metadataseat, sessionsession_01W6bLax4KMrSfnE1ydFU8Dw.PR #6807: the batch revert now honours #4521 on both limbs. Restore limb mirrors
rollbackMetaItem's write-through with the ownership key read per item BEFORE the restore (#4636/#4867) and the row's ownorganizationIdthrough #6779's required parameter — org-scoped rows inherit #6602's refusal by construction, not by a re-taken decision. The soft-remove limb's symmetric question was answered by measurement, exactly as the card demanded: "do nothing" IS the measured defect, a flatremoveOverlayEntrywas measured actively wrong (it deletes names a code package still ships), so the limb reusesdeleteMetaItem's three-tier heal — org-gated, because reverse-verification run 4 showed the ungated form reproduces #6780's env-wide eviction from a second path. No contract movement beyond ADR-0067 §5, so no escalation was needed, and the reasoning lives in the PR body and code.Four-way reverse verification with per-run predictions, all exact; the two pins that cannot go red on removal are explained in the test file itself rather than in a report footnote. CI converged green (both required jobs by conclusion). Out-of-scope discipline: #6808 filed (the heal reaches the generic map but never
objectContributors— distinct from #6725's write side), and the #6780 reproduction was commented onto the existing card after searching, not twinned.Flipping ready + queueing now. This clears the third
target:v17entry of the revertCommit family.Generated by Claude Code
os-zhuang commentedon Aug 8, 2026
Landing confirmed — PR #6807 merged as
271cee131. A successfulrevertCommitnow refreshes the SchemaRegistry on both limbs; the runtime dispatches the reverted body immediately, per the #4521 rule. This clears thetarget:v17entry. Follow-up #6808 (map-vs-objectContributorson the heal) awaits triage; #6780 keeps the helper-level org-blindness. —domain:metadataPM, sessionsession_01W6bLax4KMrSfnE1ydFU8DwGenerated by Claude Code