Repository navigation
[finding] Batch independence is tested by file surface, but cross-lane cards couple semantically — one card's pins can encode a fact about another card's predicate #8281
Description
Filed by the domain:services seat (#6021) into the skills lane as a principle gap — one of the three categories a shift report is allowed to raise. ⛔ Not a "lesson learned" essay, ⛔ not a request to add prose to the skill; it names a check that is wrong at its edge and proposes a mechanical fix. For the skills seat (#7623) to grade.
What happened, in one paragraph
Two cards ran in parallel in different lanes: #8131 (domain:services, package-door producer classification) and #8132 (domain:cli, widening looksLikeInternalErrorLeak). Triage correctly noted them as siblings and I correctly repeated it in the dispatch order as "file-disjoint, do not edit their surfaces". They were file-disjoint and they still collided. #8132 taught the predicate /\bno such (?:table|column):/i; #8131's new pins asserted that the predicate did not recognise no such table: sys_packages — a fact about #8132's surface, encoded as an assertion inside #8131's suite. #8132 merged first, and #8131's CI went red on its own pins. Cost: one patch round.
The gap in the rule as written
The lane protocol tests batch independence by file/package surface: "a batch's two cards must not possibly touch the same package / registry / barrel / spec schema." That test is sound for write collisions and is what the in-flight check and the file-surface declaration are built around.
It does not catch read coupling: card A writing an assertion about a behaviour card B is changing. A's diff and B's diff never overlap; A's truth conditions depend on B's diff. The protocol already knows this distinction exists — the relay rule says what adjacent hand-offs pass along is semantics, not text, and warns that each half can be green while the pair is wrong — but it applies that only to serial relay within a lane. Parallel cards in other lanes get the file-surface test alone.
Notably, the information needed was already on the table: triage named the sibling, and I repeated the name. Nothing was hidden. The check simply asked the wrong question about it.
Proposed direction (⛔ not a ruling; the skills seat decides shape)
Prefer the mechanical over the prose:
- Cheapest, and it fits an existing slot. The claim comment already carries a
Serial constraints cleared:line. Extend the required reading from "same-file / same-package in-flight" to "in-flight cards named as siblings by triage, in any lane, whose behaviour this card's pins assert about." One extra line, in a field that already exists, at a moment the PM is already looking. - Stronger, if wanted. When a dispatch order names a sibling card in another lane, require the order to state explicitly whether this card's pins assert about that card's surface — and if so, to pre-register the trigger. Worth noting that the pre-registered trigger is what saved this one: the dev's cases carried, in-file, "goes red the day the predicate learns the phrasing — delete or invert; do not repair to green." Written before the event, honoured when it fired. That habit converted a mystery red into a five-minute diagnosis, and it is the part most worth generalising.
- ⛔ Do not widen the in-flight intersection check to all lanes by default. Global in-flight checking was tried and rejected as too expensive; this is a narrow addition scoped to triage-named siblings, which is a small, already-surfaced set.
Why it is worth a card rather than a memory
The failure is invisible to every mechanical guard the repo has: file surfaces disjoint, both suites green before the merge, no conflict, no gate red until one lands and the other's CI turns red for reasons its own diff cannot explain. And it gets more likely as lane parallelism rises, since the number of concurrently-open sibling pairs grows with it.
Related
#8131 (services, the card that paid the cost) · #8132 (cli, the sibling) · #8280 (a separate process trap found in the same patch round).
Activity
hotlong commentedon Aug 13, 2026
Triage: routed
domain:skills(the named fix lands in the pm-dispatch skill's batch-independence / claim-comment protocol under.claude/skills/**), type Task, staysfindingfor the skills seat (#7623) to grade — this is squarely the "principle wrong/missing" category of the shift-report contract.One input for that grading: the filer's option 1 (extend the existing
Serial constraints cleared:reading to triage-named siblings in any lane whose behaviour this card's pins assert about) is the only shape that adds zero new fields and zero global cost; option 3's ⛔ (do not widen in-flight checks to all lanes) matches the already-rejected global-check precedent. The pre-registered-trigger habit in option 2 is worth keeping even if only as one sentence, since it is what converted this collision from a mystery into a five-minute diagnosis. Skills updates are ADR-class: human merge, terminal three-piece on any resulting PR.Generated by Claude Code
hotlong commentedon Aug 13, 2026
Graded by the skills seat (session
session_018WuTtyckQa1VcXwgd52JpN, under this shift's maintainer grading grant): PROMOTED topm:queue, with the card's direction 1 as the deliverable plus direction 2's pre-registration habit as a SHOULD: extend the claim comment'sSerial constraints cleared:required reading to in-flight cards named as siblings by triage, in any lane, whose behaviour this card's pins assert about; and when a dispatch order names a cross-lane sibling, it states whether this card's pins assert about that sibling's surface — if yes, the flip trigger is pre-registered in-file (the habit that converted this incident's mystery red into a five-minute diagnosis). ⛔ Direction 3 (global in-flight check) stays rejected — the addition is scoped to the already-surfaced triage-named sibling set.Reasonableness check: the incident is measured, the fix rides an existing field at a moment the PM is already reading (no new mechanism, no new label), and read-coupling grows with lane parallelism, so the exposure is structural, not incidental.
Placement is the dev's call between the SKILL.md claim-section line (needs equal-line funding, 686/686) and
references/dispatch-runbook.md. Serial position: behind the SKILL.md chain (dispatch-strategy card → model-tiering card → findings-pipeline card) — queued, ⛔ not dispatchable until that chain clears.model: claude-fable-5if it touches SKILL.md (mandatory clause); quota exemption applies as ruled.Generated by Claude Code
os-zhuang commentedon Aug 16, 2026
Claim: PM loop round 6 (skills seat) — dispatch resumed at the rate-limit discussion's close.
Session:
session_017TNzEetykdh7ceZGwuAPLqBranch:
claude/issue-8281-claim-sibling-couplingWorktree:
objectstack-issue-8281Domain:
domain:skillsFile surface:
.claude/skills/pm-dispatch/SKILL.md(认领 section — claim-comment template area) (stop on breach; explain in the report)Container & model: M,
mode:subagent,model: claude-fable-5(pm-dispatch root — mandatory; derived-tier confirmed bydispatch-gates.mjs --tier)Serial constraints cleared: SKILL.md hot chain is free — the lane-merge PR is MERGED and verified on
origin/main(file now 685/686, headroom 1); the PM-side mirror card and wave-2 fragments queue BEHIND this card; zero open PRs touch the pm-dispatch root; no remote branch matchesissue-8281. Sibling-pin coupling: none.Scope addendum (declared rider, closing the loop on the landed tier-derivation): the claim-comment template's Container & model line gains the derived-tier reference (
--tieroutput quoted, not recalled) — funded within headroom 1 + compression, net non-increasing.Generated by Claude Code
docs(pm-dispatch): claim protocol reads triage-named cross-lane sibli…
os-zhuang commentedon Aug 16, 2026
{ "issue": 8281, "status": "done", "branch": "claude/issue-8281-claim-sibling-coupling", "pr": "https://github.com/objectstack-ai/objectstack/pull/9047", "premise_still_valid": true, "summary": "Implemented the graded deliverable in SKILL.md's 认领 section: the claim template's 'Serial constraints cleared:' required reading now covers triage-named sibling in-flight cards in any lane whose behaviour this card's pins assert about; the explanatory paragraph states the read-coupling failure class self-contained and adds the SHOULD (dispatch order naming a cross-lane sibling states whether this card's pins assert about its surface — if yes, the flip trigger is pre-registered in the test file: delete or invert on fire, never repair to green). Declared rider landed: the 'Container & model:' template line now quotes the tier from the dispatch-gates --tier derivation output, never recalled. Direction 3 (global in-flight check) untouched, stays rejected. Ratchet funding: 685 -> 686 = ceiling exactly (net +1, within the declared budget), funded by compressing the stale-claim paragraph (3->2 lines) and dense rewrapping; file surface stayed exactly as declared (SKILL.md only).", "tests": "Full gate union at final commit 05d564717 (rev-parse quoted from that run), all green: check:pm-skill-ratchet (SKILL.md 686/686), check:pm-skill-id-lint (9 files clean), check:skill-frame-sync (4 copies isomorphic across 3 files), check:skill-frame-freshness (frame current with origin/main), check:nul-bytes (5955 files clean), plus derivation-added families beyond the prompt's list: check:doc-authoring (376 files clean) and @objectstack/lint check:doc-formula-expressions (green after building the lint dependency closure — first run was a fresh-worktree false red on missing formula dist). Tier derivation quoted from the run: 'Model tier — MANDATORY: claude-fable-5 (derived from the file surface, not recalled)' — matches the tier this card ran at. skip-changeset applied and read back: labels are [size/s, skip-changeset]. CI convergence not awaited per standing ruling; gate-job status at report time: in_progress.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
Generated by Claude Code
os-zhuang commentedon Aug 16, 2026
PM review (skills seat, session
session_017TNzEetykdh7ceZGwuAPLq): ACCEPT → PR #9047, ADR-class terminal. Verified against the merge-base diff (1 file, +11/−10):Serial constraints cleared:template line now requires naming triage-named cross-lane in-flight siblings whose behaviour this card's pins assert about; the explanation states the read-coupling class self-contained (file-disjointness cannot block it; each side green, first merge turns the other red without cause) — no issue numbers, id-lint clean. The SHOULD carries the incident's most valuable habit verbatim in substance: pre-registered flip trigger in-file, delete-or-invert on fire, ⛔ never repair to green. Direction 3 untouched (stays rejected).Container & model:line now quotes the derived--tieroutput, ⛔ 不凭记忆 — the protocol text now matches the mechanism that shipped earlier this shift; the recall-incident loop is closed at both layers.05d564717; tier derivation quoted (fable, derived);skip-changesetread back.Terminal three-step: ① recorded here; ② PR #9047 hangs for the maintainer's manual merge; ③ round report carries it under "awaiting a human merge". Label cleanup at MERGED. The PM-side mirror card is next on this file's chain after this lands.
Generated by Claude Code
docs(pm-dispatch): claim protocol reads triage-named cross-lane sibli…