fix(pm): a retracted claim leaves the governing-claim pool, so a withdrawn claim never governs - #18770
Merged
os-justin merged 3 commits intoSep 17, 2026
Conversation
The pool was every comment matching CLAIM_COMMENT_MARKER, ranked by recency. A retraction carries no `Claim:` line, so it was never in the pool and could not remove the claim it retracts: on #18373 a claim its own author withdrew 84 seconds later kept governing, naming a branch origin does not have, while the seat actually working the card read SUPERSEDED. Membership is now resolved before recency. A claim leaves the pool when a later comment by the same author retracts it, read through the two channels the protocol already writes: the `Release:` directive, and a prose line that opens with the retraction act and names the claim by comment id. A retracted claim is listed RETRACTED with the retracting comment id, never SUPERSEDED and never dropped. Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu Co-authored-by: Claude <noreply@anthropic.com>
…and the #18373 replay The battery replays the #18373 thread offline from its six real comment ids, with each body carrying the load-bearing lines of the real comment rather than a retyped paraphrase. Its BEFORE leg is produced by removing the retraction comment, which is the reading main takes. The measured trap is pinned too: the seat's own report line carries a retraction word and its own claim id, so an `includes` anchor would have read the comment that filed this defect as a withdrawal of the claim it defends. The anchor opens the line instead. Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 17, 2026
os-justin
marked this pull request as ready for review
September 17, 2026 20:29
os-justin
deleted the
claude/issue-18719-retracted-claim-leaves-the-pool
branch
September 17, 2026 20:53
This was referenced Sep 17, 2026
os-tesla
pushed a commit
that referenced
this pull request
Sep 19, 2026
…read the sibling's way Two rulings on the claim arbiter, one region. A retraction is a `Release:` line (batch #156 item 3, letter A): the prose channel PR #18770 taught — a closed verb roster, a comment-id scan and a stripper of this file's own — is deleted, not disabled. The protocol's definition of a decorated ownership line is the shared claim reading (batch #156 item 4, letter A): the `Release:` channel now reads through markerMatches instead of the raw constant, so a bolded or backticked release retracts exactly as a bare one. Measured consequence, replayed in the self-test: two of the twelve cross-author pairs #18862 counted — objectui#7848 (a `**Release:**`) and #7924 (a backticked one) — stood only because the raw constant could not see the holder's release; os-warren's backticked release on #17852 is read the same way. The #18373 specimen is replayed both ways: the prose line retracts nothing (the withdrawn claim stands again, the cost ruling A accepted), the same line in the declared act takes it out, and the sigil-led spelling is named by the sibling's `leading-sigil` near-miss row rather than stripped. The twelve spellings the card compared read the same through the one path on both sides of this file (5 disagreements → 0). Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W5y9kRg1YtYaMQYExVLRc2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #18719
Clause-②: no
The defect
scripts/pm/check-clause2-carriers.mjsbuilt the governing-claim pool fromCLAIM_COMMENT_MARKERalone and then ranked it by recency, so the pool was closed under addition: a claim entered it and nothing ever took one out. A RETRACTION carries noClaim:line of its own, so it was never in the pool and could not remove the claim it retracts — which means the one act the protocol calls explicit (「释放是显式动作」) was the one act the ownership arbiter could not see. The repair is not a re-sort: every ordering of a pool that still holds the withdrawn record picks the withdrawn record, and the next retraction is exactly as invisible. What changes here is MEMBERSHIP — the selector READS the retraction, and membership is resolved before recency.The #18373 counterfactual, re-derived offline
The six comment ids were fetched ONCE through the REST proxy and replayed offline through
claimCarrierSelection/pairInputRecord. #18373 itself isneeds-user-decisionand another seat's; nothing here re-grades it.main)5717315121(os-bill) — withdrawn by its own author 84 seconds later5717143021(os-litant)claude/issue-18373-include-bare-directory-provenance— absent from originclaude/issue-18373-type-source-resolution-bare-dir-include— the one refgit ls-remote origin 'refs/heads/claude/issue-18373*'returns5717333576claim.selectedauthoros-billos-litant— the card's only assigneeThe BEFORE row is produced by REMOVING the retraction comment from the same six rows, so it is a reading rather than a description. The AFTER
claim.selectedline now names the author, which is the point of the last row: the LABEL face (assigneeos-litant) and the SELECTOR face (governing claim's author) are printed where a reader compares them instead of reconstructing the contradiction by hand. The assignee itself is still not read on this path, and the record says so.The routes, on the four axes
Triage ruled A out as the deliverable (「修法是让选择器读到撤回」), so the choice is B, C, or both read as ONE predicate. Recommended: B and C as one predicate, which is what this PR implements.
A — leave it; the selection is an input record.
实际业务需求: fails on measurement. The printed block is a record, but the POOL is not:
cardDeclarationreads the pool for theClause-②declaration, the governing branch is what the liveness rows probe, and the record is what a seat reads to decide who owns a card. 项目长远合理性: a monotone set standing in for a mutable fact (ownership) cannot express a withdrawal at any ordering. 防 AI 写错: the worst axis — an arbiter that answers confidently with the wrong owner is worse than one that declines, which is the triage's 「一个只会做加法的池子,和一个没有池子,危险方向相反但都不安全」. 创业阶段不扩散: cheapest, and that is its only argument.B — the
Release:directive only.需求: real, and already declared:
AGENTS.md:408 andSKILL.md:468 / :470 / :496 makeRelease:the act that takes a card out of a seat's hands, andcheck-half-states.mjsalready exportsRELEASE_COMMENT_MARKERfor H47. 长远: the best-shaped half — one declared spelling, contract-first, nothing inferred. 防 AI 写错: strongest, because it is 声明即强制. 不扩散: adds nothing new at all. ⛔ But measured, B alone does not close the case it was filed for: the #18373 retraction carries NORelease:line — it is a bold opening line 「🚨 撤回上一条认领(5717315121)…」 posted with the assignee cleared. Under B the counterfactual above stays red. B is necessary and not sufficient.C — skip a claim retracted by a later comment of the same author.
需求: closes the measured case. 长远: on its own C has no declared shape — "retracts" still needs a predicate, and an unanchored one is a natural-language matcher inside an ownership arbiter. 防 AI 写错: C without a declared act is the lenient-consumer shape the framework rejects; its measured cost is in the next section. 不扩散: C alone invites the treadmill (#16170's lesson — close one spelling, leave the next exactly as silent).
B ∧ C, as ONE predicate — the recommendation.
需求: closes the measured case AND reads the act the protocol already declares. 长远: one sentence — a claim leaves the pool when a LATER comment BY THE SAME AUTHOR retracts it — read through two channels, which is the shape
check-half-states.mjsalready uses for a block (Blocked-by:directive plusPROSE_BLOCKER_ANCHORS). An in-family reading, ⛔ not a new mechanism. 防 AI 写错: every loosening is refused in the direction that would let one seat void another's ownership — same author, strictly later, the act OPENS the line, the line NAMES the claim by comment id, fail-closed on an unreadable author on either side; under-reading leaves the claim standing, which is today's behaviour. 不扩散: no governed text moves, no new label, no new request, no new field in the record roster, one file.⛔ No protocol text is changed:
Release:is already the act and its marker is IMPORTED rather than restated. Whether the protocol should REQUIRE theRelease:spelling of a retraction — which would let the prose channel be retired — is a governed-text question and is raised in the report'sopen_questions, ⛔ not answered here.The three shapes, each with its control
Release:line from the claim's own author, no idRelease:posted BEFORE the claim retracts nothingRelease:/ retraction from a DIFFERENT authorAlso pinned: a retraction naming some OTHER comment id; an unreadable author on the retractor, and on the claim; the act buried mid-sentence; decoration in front of the act (「-⚠️ 撤回 …」) which is not a difference; bare
releasewhich is not on the anchor roster, because in this repository a "release" is overwhelmingly a VERSION release.The measured trap that shaped the predicate. An⚠️ 但它暴露了一个工具缺陷:… 那条已撤回的
includes-style anchor (the shapePROSE_BLOCKER_ANCHORScorrectly uses, because that reader only NOMINATES candidates it then resolves) fails here, and the proof is on this very thread.os-litant— the seat whose claim the fix has to PROTECT — wrote, inside the dev report that REPORTED this defect (5717738051), a line carrying a retraction word and its own claim id: 「"question": "The governing-claim instrument now names a retracted claim. … marks my dispatch's5717143021as SUPERSEDED …"」. Underincludesthat line retracts the claim it is defending, same author, later timestamp — the comment that filed the card would have silently voided the ownership the card exists to restore. The first run of this branch did exactly that, on the real fixture. ⇒ the act must be what the line is ABOUT, so it OPENS the line after leading decoration is stripped, and the line must NAME the claim by id.os-litant's 5717775707 「5717315121…」 is the same shape from the other direction and is excluded twice over — by the author test and by this one.The RETRACTED listing
A retracted claim is ⛔ never dropped from the listing and ⛔ never called SUPERSEDED. It is rejected with its own sentence naming the retracting comment, its author, its timestamp and the channel —
RETRACTED — comment 5717333576 at 2026-09-17T15:54:48Z, by the same author (os-bill), takes it back via a retraction line OPENING with the act and naming the claim by comment id (5717315121). ⛔ NOT superseded: a withdrawn claim is not a candidate for governance at all, whatever its date. When EVERY claim is retracted the result is a state this file already has and ⛔ never a fabricated carrier:misplacedwhen the withdrawn record left a declaration line on the thread (a C2 row, its value ⛔ not accepted),absentwhen it did not — both pinned, plus the control that the same thread WITHOUT the retraction readsmissing. Theclaim.selectedsentence tells "nobody claimed" apart from "every claim was withdrawn"; the printedCLAIM_SELECTION_RULEnow carries the membership half, so two runs stay comparable on the rule as well as on the selection.The pin the triage asked for, and the ablation
New battery
#18719: a RETRACTED claim leaves the pool — a withdrawn claim never governs, 36 cases, floor pinned at 36;SELF_TEST_BATTERY_FLOOR28 → 29. The #18373 replay carries the REAL ids, stamps and logins, and each body carries the load-bearing LINES of the real comment, extracted from the REST rows rather than retyped.Self-test: 802 cases pass on the base file (read from the shared checkout, unchanged since
a84f61a7c4) → 838 cases pass here, exit 0.Ablation from the committed fix —
claimRetractionsmade to return an empty Map on disk, which is exactlymain's membership rule:The mutation was proven on disk by marker count and by a CHANGED blob hash before the suite ran, not by the editor's exit code; the restore is
git checkout HEAD -- pathunder atrap … EXIT INT TERMwith an absolute repo root, and is proven by the blob hash returning to the HEAD blob AND by an emptygit diff HEADon the path. All 15 reds are cases of the new battery and nothing pre-existing went red (checked by matching each failing case name against the battery's own roster). The⛔ CONTROLcases — the ones that assertmain's reading — stay GREEN under the ablation, which is the asymmetry that makes them controls.Gates
Derived from the worktree with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no hand-fed paths) atee9bf03bd4: 34 commands over a change set of 1 path. Every one was run and its exit code captured with redirect-then-$?, then reconciled with--ran.Repo-wide
pnpm lint(eslint . --no-inline-config): exit 0, run whole rather than narrowed.The derivation also names eight artifact-roster families whose roster sits under a directory one of these paths is in, where silence is evidence in neither direction. Run:
check-published-list-mirrors0 ·check:console-injection0 ·check:engine-double-contract0 ·check:i18n-stale-fill0 ·check:pm-label-desc-cap0 ·check:single-claim-paths0 ·check:dts-closureexit 3 andcheck:published-readme-exportsexit 3 — both PREREQUISITE NOT MET (no build in this worktree), recorded as NOT MEASURED and ⛔ not as a pass: both read builtdist/*.d.ts, which a repo-rootscripts/pm/**diff cannot move, and CI builds.The two queued cards on this file — read, ⛔ neither folded in
#18764 (a decorated
**Claim:**never enters this same pool) is ⛔ NOT folded. It moves the ENTRY side of membership (what makes a comment a claim); this card moves the EXIT side (what takes one out). They are two predicates, and folding it would mean importingmarkerMatchesfrom PR #18756, which is in the merge queue and ⛔ not on this base — a second predicate plus a dependency on an unlanded PR. The boundary, named rather than crossed: shape (2) reads the protocolRelease:through the IMPORTEDRELEASE_COMMENT_MARKER, which on this base is undecorated-only, so a decorated**Release:**is NOT read by the directive channel. The PROSE channel is decoration-tolerant by its own leading-decoration stripper, which is this file's reader and not the sibling's constant. When #18756 lands and this file adoptsmarkerMatches, both ownership markers gain decoration tolerance in one edit — that edit is #18764's.#18683 (the un-paged comment read,
per_page=100with no page ladder) is ⛔ NOT folded: it is about WHICH rows reach the reader, not about what the reader does with them — a different limb, and a truncated thread would truncate this reading exactly as it truncates today's.Generated by Claude Code