Repository navigation
docs(pm): label writes re-read current labels in the same action — stale snapshots are invalid snapshots (#9226) - #9238
Merged
Conversation
… — stale snapshots are invalid (#9226) In-place, line-neutral rewrite of the issue_write labels whole-set-replace trap line in platform-readings.md: the freshness of the read is now pinned (re-read current values within the same action; a reading from an earlier round/hour is an invalid snapshot). Piggyback per the scope-addendum comment: SKILL.md review section now states that the review seat for clause-1 skill-surface PRs must itself run at the contract-review tier, referenced via the dispatch-gates CONTRACT_REVIEW_TIER constant (no model name). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017TNzEetykdh7ceZGwuAPLq
This was referenced Aug 17, 2026
os-zhuang
marked this pull request as ready for review
August 17, 2026 11:50
This was referenced Aug 17, 2026
os-zhuang
pushed a commit
that referenced
this pull request
Aug 17, 2026
…9395) Implements the maintainer ruling on #9319 decision 2 (2026-08-17): the `ADR maintainer approval` gate's path predicate extends to `.claude/skills/**`, so Prime Directive #14's human-merge reservation is machine-enforced on the lane's own protocol surface rather than declared. - the single ADR prefix becomes a GOVERNED_SURFACES table: identical pass conditions (an APPROVED standing + no armed auto-merge), distinct failure wording, each surface naming its own rule; - the #8012 armed-auto-merge clause reaches the new path class identically, with its own emptiness proof (identical reviews, opposite verdicts); - one path hit governs the whole PR -- a mixed diff is never judged by proportion, pinned by comparing a 1-of-4 verdict with a 1-of-1 one; - the report renderer is pure, so the "each surface names its own rule" requirement is asserted on the text an operator actually reads; - PR #9238 -- the skills-only PR the merge queue landed with zero reviews -- joins the historical replay fixtures as a real capture, pinned RED. The workflow needed no trigger change: it carries no `paths` filter (a path filter would skip the whole workflow and hang the queue on a required context that never reports), and #9238 already produced a completed `ADR maintainer approval` check run through the clean path. No existing check is weakened: every prior assertion still runs, and the self-test goes from 66 to 96 assertions. Fixes #9395
This was referenced Aug 17, 2026
Merged
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 23, 2026
…bjectstack-ai#9395) (objectstack-ai#9407) Implements the maintainer ruling on objectstack-ai#9319 decision 2 (2026-08-17): the `ADR maintainer approval` gate's path predicate extends to `.claude/skills/**`, so Prime Directive objectstack-ai#14's human-merge reservation is machine-enforced on the lane's own protocol surface rather than declared. - the single ADR prefix becomes a GOVERNED_SURFACES table: identical pass conditions (an APPROVED standing + no armed auto-merge), distinct failure wording, each surface naming its own rule; - the objectstack-ai#8012 armed-auto-merge clause reaches the new path class identically, with its own emptiness proof (identical reviews, opposite verdicts); - one path hit governs the whole PR -- a mixed diff is never judged by proportion, pinned by comparing a 1-of-4 verdict with a 1-of-1 one; - the report renderer is pure, so the "each surface names its own rule" requirement is asserted on the text an operator actually reads; - PR objectstack-ai#9238 -- the skills-only PR the merge queue landed with zero reviews -- joins the historical replay fixtures as a real capture, pinned RED. The workflow needed no trigger change: it carries no `paths` filter (a path filter would skip the whole workflow and hang the queue on a required context that never reports), and objectstack-ai#9238 already produced a completed `ADR maintainer approval` check run through the clean path. No existing check is weakened: every prior assertion still runs, and the self-test goes from 66 to 96 assertions. Fixes objectstack-ai#9395 Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 17, 2026
…he pre-ruling landing (objectstack-ai#18148) Fixes objectstack-ai#18083 `scripts/pm/check-governed-queue-guard.mjs` decides on an authorized APPROVED review and has since the 2026-09-04 predicate landed. What had not moved was the text a seat is told to consult: the docblock called a draft awaiting the maintainer's own merge the regime's terminal state, and the printed remedy's preferred option told a seat to take the PR out of the queue "and leave the merge to the maintainer". Since the charter chain landed (PR objectstack-ai#18018 `9489e2c0`, PR objectstack-ai#18038 `c185d087`, PR objectstack-ai#18051 `137eb00e`) the rule is ruling C — issue objectstack-ai#17971, maintainer 2026-09-13, verbatim and untranslated: > C. approve 后不管后续改动都由席位落地: So the narration under-permitted: it told a seat not to do the thing the rule now says it should do once an authorized approval is on record. ## What moved Wording only. ⛔ No decision branch changed — `entrySatisfied`, the approval reduction, the tier split and every exit code are untouched. Anchored by content, not by line number. 1. **Docblock, the "why the PR leg must not redden" paragraph.** The healthy resting state is now a draft *waiting for an authorized approval*, in the landed rule's own words from `.claude/skills/pm-dispatch/references/landing-operations.md`: 「四件套留 draft 等人批,⛔ 不翻正式不入队;获授权批准后认领席落地。」 2. **Docblock, a new paragraph for what happens after the approval** — ruling C, quoted verbatim, plus `SKILL.md`'s operational half: 「席位落地 = 过落地前检、清标、ready、auto-merge,踢出/变基同法。」 The seat's ready → enqueue is now stated as the correct next act there rather than a violation. 3. **Docblock, the "this guard cannot stop a direct merge" paragraph.** The direct merge is now the OTHER landing rather than the only one — `references/core-rules.md`: 「受管面由维护者人合或授权批准后席位落地」. The objectstack-ai#11387 measurement it cites is kept verbatim as history. 4. **The `pull_request` leg's EARLY WARNING rendering.** The ⛔ list (flip ready / enqueue / arm auto-merge) is now explicitly conditional — "while no authorized APPROVED review is on record", with AGENTS.md Prime Directive objectstack-ai#14's own "lift only for that approval" — and a new ✅ line says what a seat DOES do after the approval. 5. **The `merge_group` refusal remedy.** Steps 1 → 2 are now an order rather than a menu: out of the queue first, then the authorized approval, and the CLAIMING SEAT lands it from there. The unapproved direct merge (人工直合) is kept as the landing that PR still has. 6. **Two internal comments** that restated the same pre-ruling shape: the tier-default asymmetry cost (was "costs one hand merge") and the exit-code precedence note. The references tier is untouched and still says the in-seat review of record lands it: remedy option 3 renders byte-for-byte as before, and both of its pins (offered on a references-only refusal, withheld on a rules-layer one) still pass. ## Acceptance readings Taken on `a2e4cd7d9`, in the worktree, against merge base `a90a9f267`. **The two pre-ruling phrases, in the narration and the printed text: N → 0.** | reading | before | after | |---|---|---| | `git grep -c -E 'leave the merge to the maintainer\|human merge IS the review record'` | 2 | 2 | | … of those, hits in narration or printed remedy | 2 | **0** | | … of those, hits inside the self-test pin that FORBIDS them | 0 | 2 | Both remaining hits are the new negative assertion itself — a comment and the regex literal in `⛔ a-refusal-never-tells-a-seat-to-leave-the-merge-to-the-maintainer-nor-calls-that-merge-the-record`. A pin has to name what it forbids; neither is text the guard ever prints. **The landed phrase: 0 → 5** (`git grep -c 'CLAIMING SEAT lands\|claiming seat lands'`). **Every hit of the pre-ruling wording enumerated** (`git grep -n -E 'hand merge|human merge|leave the merge|人工合'`), 6 before → 4 after, and each remaining one accounted for: - `:44` 「人工合并即人工审核」 (docblock) — **moved**. - `:52` "the human merge IS the review record" (docblock) — **moved**. - `:536` "costs one hand merge" (tier-default comment) — **moved**, now "costs one authorized approval". - `:1171` 「人工合并即人工审核」 (EARLY WARNING rendering) — **moved**. - `:1242` "leave the merge to the maintainer. A human merge" (remedy) — **moved**. - `:2010` (was `:1983`) the `objectstack-ai#9319` replay fixture's name, quoting PR objectstack-ai#9238's own body: "a .claude/skills PR whose own body said 'awaiting a human merge'" — **stays**. It is a historical measurement naming what that PR said in 2026; rewriting it would falsify the fixture. - `:2429`, `:2436`, `:2468` — **new**, the three negative pins (two English phrases, one 人工合并即人工审核). **Self-test:** `node scripts/pm/check-governed-queue-guard.mjs --self-test` :: exit 0, **233 cases before → 238 after** (5 added, none removed, no battery floor lowered). **Diff surface:** `git diff --stat a90a9f2` names exactly one file, `scripts/pm/check-governed-queue-guard.mjs`, 104 insertions / 32 deletions. `origin/main` advanced under this worktree during the run (`a90a9f267` → `739ab526d`, a shared-ref hazard AGENTS.md names), so the anchor above is the merge base, not the moving ref. **Governed?** No — `node scripts/pm/check-governed-merges.mjs --test scripts/pm/check-governed-queue-guard.mjs` :: exit 0, "NOT governed — ordinary queue landing applies". This PR is opened as a draft and the seat lands it; nothing here flips ready or arms anything on its own. ## Reverse verification — the new pins can actually fail One-shot, from the committed state, with a `trap … EXIT INT TERM` restoring absolute paths. Predicted direction: **turns red**. - HEAD blob `f7938efe94a20f34a3c1e6f07e2aaca393f16a47`. - Mutation: the remedy's step-2 line rewritten back to the pre-ruling wording. On-disk observation, anchored on both texts: landed anchor 1 → **0**, injected stale phrase 0 → **1**; blob `87b912dbc8acaf5af5d02fb86cc06eb2bcffd986` ≠ HEAD blob, so it reached disk. - Mutated leg: `--self-test` :: **exit 1**, `✗ 2 of 238 case(s) failed` — exactly `a-refusal-orders-the-remedy-DRAFT-then-the-authorized-APPROVAL-then-the-CLAIMING-SEAT-lands-it` and `⛔ a-refusal-never-tells-a-seat-to-leave-the-merge-to-the-maintainer-nor-calls-that-merge-the-record`. - Restore leg: `git checkout HEAD -- FILE` → blob back to `f7938efe…` (byte-identical), `git diff HEAD` empty, `git status --porcelain` empty, anchor restored 1, injected 0. - Restored leg: `--self-test` :: exit 0, 238 cases pass. ## Gates Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths, three-dot against merge base `a90a9f267`) — **33 commands, all run in the foreground, every exit code captured before any pipe, all `exit 0`.** Reconciled: ``` node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran RAN_FILE Run reconciliation — 33 derived, 33 run, 0 NOT-MEASURED, 0 UNRUN. ✓ 33 derived famil(ies) accounted for — a DERIVED zero — all 33 recorded an exit code and none of them is 3. ``` Including `node scripts/pm/check-governed-queue-guard.mjs --self-test` :: exit 0 and `pnpm check:nul-bytes` :: exit 0. `pnpm check:pm-governed-merges` :: exit 0 was run too, though the derivation does **not** place it for this path — it is a `--self-test`-only checker-health family here, so its green grades that checker's fixtures, not this diff. Control characters: `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over the changed file — no hits. No changeset: `scripts/pm/**` ships in no package's `files[]`, so this publishes nothing — the `skip-changeset` label carries it. ## Acceptance notes Two observations outside this card's one-file surface, noted and not filed (this seat's write budget for the round is the branch push, this PR, the label and one report comment): - `scripts/pm/check-governed-merges.mjs` :140 and `scripts/check-required-contexts.mjs` :288 both still say "a human merge IS the review record" for a governed PR. Neither is wrong — it is one of the two terminals the charter names 「终局两条:人工直合即审核记录;授权批准 ⇒ 席位落地。」 — but neither mentions the second one. That is an omission rather than a contradiction, so it is not the class this card is. Issue objectstack-ai#18083 fences the first file off from this PR by name. - `.claude/hooks/guard-governed-enqueue.sh` :548 was checked and is already ruling-C shaped (its steps read draft → wait for the approval → "Then enqueue"), so it needed nothing. _Generated by [Claude Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_ --- _Generated by [Claude Code](https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8)_ Co-authored-by: Claude <noreply@anthropic.com>
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 #9226
Main deliverable —
references/platform-readings.md(in-place, line-neutral)The
issue_writelabels whole-set-replace trap line is rewritten in place (no new lines). Core increment per the card: 写标签前同一动作内重读现值合并 —— 隔轮/隔小时的旧读数视为无效快照. All pre-existing elements are preserved: whole-set replace (not append), the silent-stripping consequence, true append via RESTPOST /issues/{n}/labels, and the post-write read-back. Rationale (from the card): the old wording pinned read-then-union but not the freshness of the read — a reading taken early in a round plus a write 80 minutes later satisfied it literally while bypassing it semantically; post-write read-back cannot catch this class, so the only effective defense is compressing the read-write window to seconds.Piggyback (scope-addendum comment on #9226) — landed, not dropped
SKILL.md review section (the skill-surface ACCEPT 三件套, item ①) now states that the review seat for clause-① skill-surface PRs must itself run at the contract-review tier, referenced via the dispatch-gates constant
CONTRACT_REVIEW_TIER— no model name written, single source preserved. Funded line-neutrally by extending the existing line (long-line precedent in the file: lines up to 492 chars); no re-wrap, no new line.Line budget (ratchet, read on the spot)
.claude/skills/pm-dispatch/references/platform-readings.md.claude/skills/pm-dispatch/SKILL.mdTier derivation (verbatim,
node scripts/pm/dispatch-gates.mjs --tieron the changed paths)Verification — gate union re-run after the final commit, at
0627eed38Gate families re-derived from the actual changed paths (
node scripts/pm/dispatch-gates.mjson the two files): the five families above, matching the dispatch expectation; no additions beyond the derived set..claude/-only change — releases nothing;skip-changesetapplied.This is a skill-surface PR (
.claude/skills/**): draft, awaiting a human merge — never ready/queue/auto-merge.Generated by Claude Code