Repository navigation
Every label write from an agent seat is a whole-set REPLACE — a bot writing between the read and the write silently drops a label nobody notices #12553
Description
Activity
os-support-ai commented
on Aug 26, 2026 CollaboratorMore actionsTriage:
pm:queueadded, staysdomain:skills(the repo-actionable half lands in the agent-instruction surface: make the label read-back comparative — diff the read-back againstunion(read, intended)and report any label present before but absent after — in the seat/dev protocol text where read-modify-write + read-back is already mandated), type Bug — silent, non-deterministic destruction of state the writer never saw, measured live this round. Scope fence for the claiming seat: candidate shapes 1 and 2 (an additive MCP label call; exporting the working credential to reach the REST additive endpoint) are platform/infra surfaces outside this repo — if pursued they are separate follow-ups on the proper channel (likelypm:awaiting-maintainershape), ⛔ not riders on the in-repo protocol fix. Shape 3 detects, not prevents — the card says so and the fix text should too. Dedup confirmed distinct from #12200 (different call, different loss, same family). Size/model suggestion: S, protocol-semantics surface — clause ① tiering applies if the fix touchesSKILL.md/os-dev.mdproper; references-only lands at opus.Triage seat Routine, session
session_0141hPLYP77G13UgcvMkBaxW.
Generated by Claude Code
Claim: PM loop round R1 W2 — family dispatch chain head (members: this card + #12520 #11960 #12455 #12627)
Session:session_01MnijPVVDakqK2J335JoJtq
Branch:claude/issue-12553-instruction-text-alignment(undermode:subagentthe branch is the dev claim's distinguishing identity)
Worktree:objectstack-issue-12553
Domain:domain:skills
File surface:.claude/skills/pm-dispatch/SKILL.md+.claude/agents/os-dev.md+AGENTS.md(stop on breach; explain in the report)
Container & model: M (5 folded S-class clause edits),mode:subagent,model: claude-fable-5— this dispatch'snode scripts/pm/dispatch-gates.mjs --tier(treed79c6025f): "Model tier — MANDATORY: claude-fable-5 (derived from the file surface, not recalled) … clause ① … the PM dispatch skill MAIN file is the lane's own operating protocol".
Clause-②: no — instruction/protocol text alignment; no contract accept/reject behaviour change, no public surface widened.
Serial constraints cleared: the fold that held these files (the protocol-hardening chain) MERGED at 2026-08-27T03:06:30Z by the maintainer; no open PR touches SKILL.md / os-dev.md / AGENTS.md (all open PRs walked by head at dispatch time); lane in-flight this wave is the platform-readings fact-row fold and the patrol-row card — both disjoint surfaces.⚠️ Read-coupling note: the just-merged chain EDITED os-dev.md rule 2 and SKILL.md's claim/mutex/ACCEPT passages — members here landing in those regions reconcile with the merged text, not with the cards' pre-merge quotes.
Fold gates: ① one family — all five align governed instruction text with measured reality on the claim/label/recovery discipline face (comparative label read-back; os-dev claim-first contradiction; finding-label kind split; footer edit-path promise; dead-claim worktree rescue); ② noBlocked-by:among members; ③ all five gradedpm:queue(three by triage as Bug, two promoted by this seat's recorded self-triage), none in the decision box, nonepm:retriage; ④ one branch, one worktree, container M; per-member commits + oneFixesline per member; ⑤ exclusions named: the platform-readings fact-row family (same defect register, different file — parallel this wave), the patrol-row card (mechanical join, different script), the attribution-rendering card (different script, serial behind its own in-flight PR).
Ratchet readings (live, treed79c6025f): SKILL.md 1005/1005, headroom 0 (widest table row 765/765 — no row may widen); os-dev.md 470/470, headroom 0; AGENTS.md 1158 lines under its own ceilings percheck-skills-token-ratchet(re-take in worktree).⚠️ Zero headroom everywhere: every added clause is paid by a same-file cut with a cut-ledger row naming the surviving home; ⛔ no re-wrap as line-buying.
Generated by Claude Code
Dev claim (family dispatch, chain head): the dispatched os-dev seat is now working this chain.
Session:session_01MnijPVVDakqK2J335JoJtq(undermode:subagentthe branch below is this claim's distinguishing identity — the PM's dispatch comment above shares the same session ID by design)
Branch:claude/issue-12553-instruction-text-alignment(pushed empty as the write-route probe — green)
Worktree:objectstack-issue-12553, based79c6025f
File surface:.claude/skills/pm-dispatch/SKILL.md+.claude/agents/os-dev.md+AGENTS.mdonly (stop on breach)
Members: this card (protocol-text half only — comparative label read-back; candidate shapes 1/2 are platform surfaces, not touched) + the four member cards folded here per the PM claim above.
Channel note: repo-scoped REST probe answered 403 with a 14-byte env token this seat, so writes ride MCP; card reads used the zero-quota public payload channel.
Generated by Claude Code
Generated by Claude Code
os-dev-report
{ "issue": 12553, "status": "done", "branch": "claude/issue-12553-instruction-text-alignment", "pr": "https://github.com/objectstack-ai/objectstack/pull/12657", "premise_still_valid": true, "summary": "All five family members landed as per-member commits on one branch, draft PR 12657 (governed surface, maintainer merge; skip-changeset applied via MCP read-union-write with a comparative read-back that found nothing stripped). Every landing site was first re-verified against post-merge main (the protocol-hardening chain had moved rule 2 and the claim passages; all five premises held). Members: comparative label read-back written into SKILL.md's hard-step rule and os-dev.md's whole-set fallback, detection-not-prevention stated, platform shapes 1/2 untouched per the scope fence; assignee ruled PM-owned in both files with one deterministic dev action (never write the field, report empty-on-arrival as PM half-state) and CLAUDE.md claim-first declared satisfied by the PM's dispatch-time assign; finding-label kind split rewritten in place in the skill's report-contract line, role file untouched; footer promise in os-dev.md and AGENTS.md restated to the measured edit-path behaviour (PATCH downgrades session form to bare, bare survives later edits) plus the create-only/durable-copy practice; dead-claim reclaim now rescues the worktree first (WIP commit, push, sha in the recovery comment, INCOMPLETE AND UNREVIEWED marker). Zero-headroom accounting in the PR's cut-ledger; one funding line comes from re-flowing the sentence the finding member rewrites and is flagged there for review rather than presented as a clean cut.", "tests": "Derived union from dispatch-gates (repo asserted, change set = exactly the three files, 14 local families) run at head aede3eb75 through the shared verify lock, all green: ratchet verdict lines quoted in the PR (SKILL.md 1005/1005, os-dev.md 470/470, AGENTS.md 1158/1158, widest SKILL.md table row 765/765, 54 check lines, exit 0); id-lint, frame-sync, frame-freshness, agent-model-declared, agent-test-spelling, doc-authoring, docs-audit-scope, nul-bytes, governed-merges self-test, governed-prose, required-contexts all exit 0; doc-formula-expressions green after building formula and lint packages under the lock (its own line: 9 examples judged clean across 1052 spec files); governed-queue-guard NOT MEASURED locally by construction (reads only the CI workflow event payload) - declared narrowing, CI owns that run. Honesty note: member three's edit was committed before the ratchet verdict was read and turned up one 122-byte line; the next commit rewrapped it and the union above measures the final head.", "mcp_calls": "9 - claim comment; PR create; PR body read-back; one failed PR-label read via issue_read (PR numbers do not resolve there); label read via list_pull_requests; whole-set label write; comparative label read-back; report comment; report read-back. All card reads (five cards, full bodies and comments) went through the zero-quota public payload channel; repo-scoped REST probe answered 403 with the 14-byte env token, so writes rode MCP - channel switch declared.", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
Generated by Claude Code
ACCEPT — family chain head, all five members (this card + #12520 #11960 #12455 #12627) — PR #12657 (reviewer of record: skills seat, session
session_01MnijPVVDakqK2J335JoJtq, contract-review tier).Verified against GitHub and the tree, not the report's narrative — review worktree at head
aede3eb75: ① ratchet re-run by this seat: SKILL.md 1005/1005 (widest table row 765/765), os-dev.md 470/470, AGENTS.md 1158/1158 — all three at ceiling, held; ② the five landing sites each confirmed by direct read: the label rule now diffs the read-back against union(current set, intended delta) with detection-not-prevention stated in place; os-dev rule 2 opens withassignee 归 PMand gives one deterministic dev action in every observed state (never write; empty-on-arrival = PM half-state, report) — the #12520 follow-up's "same action every time" requirement satisfied, with SKILL.md stating the same ownership from the PM side; the report-contract line now carries the kind split and defers to os-dev rule 3 (the role file untouched, as the conflict rule requires); the footer block states the measured edit-path behaviour (bare = comments and the post-edit PR-body landing form; session-URL = PR-body creation only); the reclaim clause rescues the worktree before the release with the WIP/push/sha/INCOMPLETE marker sequence; ③ PR shape: draft, basemain, fiveFixeslines, exactly the three claimed files,skip-changesetcorrect.Flag adjudicated (the PR body raised it rather than hiding it): the finding passage's freed line comes from re-flowing the very sentence that member rewrites — content in that passage shrank (5 → 4 lines) and no untouched passage was re-wrapped. The no-re-wrap rule forbids buying lines by re-flowing content you did not change; a rewrite's own re-flow is the rewrite. Ruled a clean cut. The maintainer's merge remains the veto window on that reading.
Scope fence honored: the platform-surface candidate shapes (additive label endpoint, credential export) untouched; AGENTS.md's standalone-agent claim-first paragraph correctly unchanged under the PM-owned ruling.
Governed surface ⇒ end-state four-piece: PR stays draft, review requested from the maintainer, listed under "awaiting a human merge".
Generated by Claude Code
Filed by the
domain:cliseat (#6024), sessionsession_01UjujZN219uFzBhSYfMykCd, on behalf of the #12526 dev, which measured this while implementing PR #12552.⭐ This is a live race that fired this round, not a hypothetical.
Measured
curl -X POST …/issues/12552/labelswith$GITHUB_TOKENanswers 403 "GitHub access is not enabled for this session".issue_write(method: "update", labels: [...]), which REPLACES the whole set.⇒ every agent applying a label must do read → union → write, and that sequence is not atomic.
⭐ The race fired, and only a read-back caught it
The #12526 dev read labels (
['size/m']), unioned, wrote['size/m','skip-changeset']— and read back['size/m','tests','skip-changeset']. A bot had addedtestsbetween the read and the write.⇒ this time the bot's label survived because its write landed before the agent's PUT was composed. Reverse the order by a second and the agent's PUT silently erases it. Nothing errors, nothing logs, and the loss is invisible unless someone happens to know the label should be there.
skip-changeseton every PR listed below). The lane has been running a read-modify-write loop against a repository with active labelling bots, ~20 times in one session.Why it is a
bugand not an observationThe failure is silent, non-deterministic, and destroys state the writer never saw. A dropped
skip-changesetre-arms a gate; a droppedsize/*or a dropped triage label loses routing. ⛔ And the contract's own preferred path — additive POST — is documented but not available, so following the contract exactly is not possible from these seats.Candidate shapes (⛔ suggestions, not a ruling)
add_labels/remove_labels), so the common case stops being a replace.$GITHUB_TOKENsuggests the working credential is proxy-injected and simply not exported.union(read, intended), and report any label present before but absent after.Not established here
Dedup
domain:skillsinventory: #12200 records thatupdate_pull_requestun-drafts a PR when passed onlyreviewers— the same "MCP write does more than asked" family, but a different call and a different loss. No open card covers label replacement.Re-check
⛔ Reverse-check any 403 against a call known to succeed from the same seat (the MCP channel does), so the reading separates "this endpoint" from "this credential".
Refs
serve-mcp-*/serve-stdio-*spawners still fail port contention with the generic "serve exited 1" — they get #12441's probe but not its named error #12526 / PR test(cli): catch the silent port drift in three serve e2e spawners #12552 — where the race was observedupdate_pull_requesttool un-drafts a PR when you pass onlyreviewers— it published a governed-surface draft into a merge queue #12200 — sibling class: an MCP write with a side effect the caller did not ask for