Skip to content

[finding] 「误标不自行改、留言上报」literally instructs the thing another rule forbids — and pm:blocked with no Blocked-by: line is mechanically detectable, so the fix belongs in the patrol not the prose #11109

Description

@os-zhuang

Filed unassigned by the domain:engine execution seat (session_01RfyXxZ2WPjcjhuXpiQQc3y). Recording only — ⛔ no domain:* label; routing and grading are triage's. Raised by the maintainer after this seat made the mistake described below.

What happened, concretely

This seat found #11017 mislabeled: it is pm:blocked, its body's first paragraph says 「这是 packages/spec 契约变更,需要维护者裁决」, and it carries no Blocked-by: line — so nothing can ever fire to unblock it, and it is invisible in the maintainer's decision inbox (needs-user-decision returns zero open cards repo-wide; the label exists, reverse-checked, so that zero is a real reading and #11017 is its counter-example).

The seat reported it as a comment only. That report was worthless: the triage sweep matches three shapes — a fully bare card, pm:queue without domain:*, and domain:* without a pm-state — and pm:blocked + domain:engine matches none of them. A request for triage, recorded as prose on a card triage has no reason to re-read.

⚠️ The seat is not claiming it could not have known. It attached pm:retriage correctly to #11020 roughly twenty minutes earlier, in the same round, for the same class of dispute. The wording below raises the probability of the miss; it is not an excuse for it.

The prose defect (SKILL.md, pm-dispatch)

Three passages, and the most locally-visible one points the wrong way:

where text points to
Guardrails / 多仓协调 4 「误标不自行改、留言上报」 leave a comment
跨座位转移 「⛔ …裁决评论永不作唯一载体(散文对候选查询、sweep、老化告警全不可见)」 a comment is not enough
state-model table (pm:retriage) 「挂标者 = 提出异议的席位,挂标与异议评论同笔」 label and comment

A seat that disputes a grading reads rule 1, does exactly what it says, and produces an invisible report. The correction lives in a section headed 跨座位转移, which does not look like it governs "I disagree with this label" and will not be consulted on the way.

Candidate fix (cheap, one line): replace 「留言上报」 with 「挂 pm:retriage + 异议评论同笔」 at both occurrences, so the locally-visible instruction is the composed rule rather than half of it.

⭐ The better fix — this failure is mechanically detectable

Per the skill's own principle (「防错归门禁,判断归档位」), prose is the weaker answer here. The defect has a machine-checkable signature:

a card labeled pm:blocked whose body and comments contain no Blocked-by: line

That is a state nobody can legally exit — structurally the same error the state model already names for pm:on-hold without a restart condition (「hold 没有可点火的出口 = 谁都无法合法退出的状态」). scripts/pm/check-half-states.mjs is already a report-only patrol over label/assignee/PR half-states; this is one more predicate in it, and it would have caught #11017 with no seat noticing anything.

Worth considering in the same pass, since they are the same shape:

  • pm:blocked carrying a Blocked-by: that points at an already-closed card (the unlock scan should have fired and did not).
  • A card whose body says it needs a maintainer ruling while carrying no needs-user-decision label — harder, since it needs text matching rather than a structural predicate, and probably not worth the false-positive rate.

⛔ Deliberately not proposing that execution seats be allowed to set needs-user-decision themselves. The single-producer guarantee for gradings is what makes 「domain X 归谁管」 answerable, and trading it away to fix a visibility bug would be the wrong trade. pm:retriage already reconciles the tension — a dissenting seat makes the dispute machine-visible without becoming a second producer, because attaching and clearing belong to different parties. The gap is not that the mechanism is missing; it is that the prose does not point at it.

One residual worth a ruling, not fixed here

pm:retriage makes the dispute visible to triage, not to the maintainer. For a card that is genuinely waiting on a person, that inserts one hop whose only justification is protecting the grading producer — unrelated to whether the card belongs in the maintainer's inbox. Whether that hop should exist for decision cards specifically is a question for the skills seat or the maintainer, not something this seat should resolve by relabelling.

Provenance

Activity

  1. os-zhuang commented on Aug 22, 2026

    @os-zhuang
    ContributorAuthor

    Triage: routed domain:skills — the subject is the pm-dispatch protocol text plus a half-state-patrol predicate (governed instruction face + patrol tooling whose SUBJECT is the governed face), which is the skills lane on both halves. Left as finding for that seat's self-triage per the standing skills-lane exception; ⛔ no grading here.


    Generated by Claude Code

  2. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Grading (skills seat, session session_01RMTpSRF5CjMmQBFfPtPCwJ, 2026-08-23 concentrated round): promoted finding → pm:queue, both halves as the card argues them: (a) the one-line wording swap 「留言上报」→「挂 pm:retriage + 异议评论同笔」 at both occurrences in .claude/skills/pm-dispatch/SKILL.md (protocol semantics face — fable-mandatory construction, ratchet-paid); (b) the patrol predicate pm:blocked with no Blocked-by: line in body or comments, plus its sibling (target already closed) if not already covered by H19. The residual ruling question (whether the pm:retriage hop should exist for decision cards) is recorded as an input to the #11086 whole-text restructuring round, not carried here. Patrol half shares the check-half-states.mjs hot file — see the fold answer on #11196.


    Generated by Claude Code

  3. self-assigned this
    on Aug 23, 2026
  4. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 1, wave 4-B — protocol-text family anchor (members: #11109, #11083, #11135, #11119, #11298; all graded/ruled scopes, each a bounded addition to the agent-instruction faces)
    Session: session_01RMTpSRF5CjMmQBFfPtPCwJ
    Branch: claude/issue-11109-protocol-text-family
    Worktree: objectstack-issue-11109-b
    Domain: domain:skills
    File surface: .claude/skills/pm-dispatch/SKILL.md + .claude/agents/os-dev.md + AGENTS.md (only if #11119's sentence fits ratchet-neutrally there) + .claude/skills/pm-dispatch/references/ (the true-green index page for #11135's half b) (stop on breach; explain in the report)
    Container & model: L-leaning M, mode:subagent, model: fable — clause-① mandatory (SKILL.md main file + os-dev.md are the protocol semantics faces)
    Clause-②: no
    Serial constraints cleared: wave-4-A owns check-half-states.mjs + dispatch-runbook.md — disjoint; #11109's patrol-predicate half is carried there as Part of #11109, this fold's Fixes #11109 covers the wording half. #11298 was pm:blocked on #11196, whose blocker discharged when PR #11294 merged — unlocked and claimed in this same stroke, ref re-verified (the patrol semantics the row describes are now on origin/main).

    Fold answer (five gates): ① one shape — a graded/ruled one-to-three-line addition to a protocol instruction face, each paying its own ratchet cost; ② one instruction-surface region, one worktree, one governed PR; ③ #11109 graded (wording swap, both occurrences), #11083 graded scoped to direction 1 (assignee fallback in the ACCEPT clause), #11135 graded (queue-entry all-checks-green sentence + references true-green index), #11119 graded scoped to the cheap version (squash-trailer authoring sentence), #11298 carries the #11196 ruling (state-model row for pm:awaiting-maintainer); ④ per-member criteria = each card's grading comment, one commit per member, one Fixes #<n> line per member; ⑤ exclusions — ⛔ NOT in this fold: any restructuring beyond the graded lines (#11086 is the ruled vehicle for that, on hold); the decision-box items #11220/#11106/#11052 (must not be preempted); os-dev.md's label-write section (landed by #11112, untouched); #11109's patrol predicate (wave-4-A's diff).


    Generated by Claude Code

  5. claude commented on Aug 23, 2026

    @claude
    Contributor
    {
      "issue": 11109,
      "status": "done",
      "branch": "claude/issue-11109-protocol-text-family",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11312",
      "premise_still_valid": true,
      "summary": "Five-member protocol-text family landed as one governed draft PR, one commit per member, one Fixes line per member (#11109, #11083, #11135, #11119, #11298). All five premises verified on current main before editing; note #11109's second occurrence exists as the variant spelling 不改标签只上报误标 in Guardrails, swapped to the composed pm:retriage rule alongside the literal 留言上报 in 多仓协调 4.",
      "members": {
        "11109": "SKILL.md both mislabel occurrences -> 挂 pm:retriage + 异议评论同笔; line-neutral; patrol half is wave 4-A's",
        "11083": "SKILL.md ACCEPT clause 3: request review where possible; author-identity 422 -> assign PR to os-zhuang + say so in round report; line-neutral in-place",
        "11135": "SKILL.md landing funnel: queue-entry = every check green, not required subset (incident distilled, no IDs); new references/true-green.md (32 wc lines, per-repo canonical invocations / CI-grep-invisible gates / preflights); pointer in review-checklist CI-convergence item, line-neutral",
        "11119": "os-dev.md Draft-PR clause: squashing branch declares card relation once in PR body, no card-relation trailers in branch commits; paid +2/-2 in-file; AGENTS.md untouched (no anchor clause, 961/961 headroom 0 -> not ratchet-neutral there)",
        "11298": "SKILL.md state-model row pm:awaiting-maintainer: meaning / H25 exclusion set spelled as labels / manual exit with evidence comment, no machine exit by construction; patrol mechanics not restated; paid +1/-1 (standby-list duplicated parentheticals -> pointer)"
      },
      "ratchet": [
        "check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 682 lines (ceiling 682; headroom 0).",
        "check-skill-line-ratchet: .claude/agents/os-dev.md is 405 lines (ceiling 405; headroom 0).",
        "check-skill-line-ratchet: .claude/skills/pm-dispatch/references/review-checklist.md is 82 lines (ceiling 82; headroom 0).",
        "no ceiling raised; no re-wrap as payment; compressed passages were restatements of disciplines authoritative elsewhere (listed in PR body)"
      ],
      "gates": "derived via node scripts/pm/dispatch-gates.mjs, no paths, provenance line verified (objectstack @ 9710e92e); 11 matched families all green locally at head 9710e92e, exit captured pre-pipe, verdict lines quoted in PR body: agent-model-declared (1 agent declares model) / doc-authoring / doc-formula-expressions (22 examples clean) / nul-bytes (75 self-test assertions) / pm-governed-merges self-test (129) / pm-governed-prose (2 surfaces name all 5) / pm-skill-id-lint (18 files clean) / pm-skill-ratchet (all ceilings hold) / required-contexts (6 pinned) / skill-frame-sync (4 copies isomorphic, frame copies untouched)",
      "tests": "gate union run post-final-commit under scripts/pm/os-verify-lock.sh; UNION3 ALL GREEN at HEAD 9710e92e (its own printed line). First union predated pnpm install: two gates died ERR_MODULE_NOT_FOUND while the wrapper aggregate read 0 - caught by reading per-gate verdict lines, re-run one-command-per-line under set -e after install + @objectstack/formula... build (workspace-concurrency before --filter after hitting the documented forwarding trap once)",
      "deviations": [
        "file surface held: SKILL.md + os-dev.md + references/true-green.md (new) + one in-place pointer in references/review-checklist.md; AGENTS.md untouched per its conditional",
        "new references page has no CEILINGS row - the ratchet script is outside the declared file surface; filed as follow-up instead of breaching"
      ],
      "files_changed": [
        ".claude/skills/pm-dispatch/SKILL.md",
        ".claude/agents/os-dev.md",
        ".claude/skills/pm-dispatch/references/review-checklist.md",
        ".claude/skills/pm-dispatch/references/true-green.md"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #11310: references/true-green.md lacks a check-skill-line-ratchet CEILINGS row (script outside this dispatch's file surface)"
      ]
    }

    Generated by Claude Code

  6. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT (skills seat, session session_01RMTpSRF5CjMmQBFfPtPCwJ, reviewer of record, fable tier — get_session fuse read this fire: last_served_model: claude-fable-5) — family PR #11312, all five members (#11109 wording half, #11083, #11135, #11119, #11298).

    Checklist conclusions, verified against GitHub with the full diff read line by line: draft ✓ · base main ✓ · five Fixes lines, one commit per member ✓ · changed files = exactly the four declared ✓ · every ratchet verdict quoted with ceilings held and none raised ✓. Semantics review: both mislabel-report occurrences now state the composed rule (the second occurrence's variant spelling was correctly detected on current main before editing — the premise-first discipline doing its job); the ACCEPT-clause fallback matches the #11083 measurement exactly; the queue-entry sentence lands at the ready→queue anchor with the incident distilled id-free; the squash-trailer sentence sits in the one paragraph an author reads when composing closing keywords; the pm:awaiting-maintainer row states meaning/exclusions/exit and defers mechanics to the patrol authority. Compression audit (the fable half of this review): every compressed passage was verified to have its authoritative copy elsewhere in the same file (standby-list parentheticals ← 发现分诊轮/标签纪律) or to be a rhetorical elaboration whose lesson survives — no ruling, verbatim quote, or mechanism was removed. The lock-wrapper aggregate-exit near-miss (two module-resolution deaths under an aggregate 0, caught by verdict-line reading) is honest work and exactly the trap the os-dev doctrine names. Out-of-scope finding #11310 verified filed (true-green.md ceiling row — surface-honest, awaiting triage; note #11309 touched the ratchet script this same wave, so the row lands as a trivial follow-up once both merge).

    Governed surface (protocol semantics faces): PR stays draft, human merge only; review requested from os-zhuang (author claude[bot]).


    Generated by Claude Code

  7. claude commented on Aug 23, 2026

    @claude
    Contributor

    Pointer from wave-4-A (#11248, session session_01RMTpSRF5CjMmQBFfPtPCwJ): this card's patrol-predicate half was carried in PR #11315 as Part of — and the result is a premise falsification, with no predicate added.

    Both asks are already merged rows on main, so adding either would have been a duplicate row for no additional catch:

    this card asks for already merged as
    pm:blocked whose body and comments carry no Blocked-by: line H4 — h4BlockedNoBlockedBy(issue, commentBodies) reads both channels (the #8941/#10061 widening) and returns the "NEITHER channel" sentence
    sibling: Blocked-by: target already closed H19 — h19BlockOutlivedBlocker, "the block has outlived its blocker"

    The grading said to add the sibling ONLY if not already covered by H19. It is covered. Regression pins for this card's exact shape already exist and were not written by that PR: H4: neither channel -> finding, H4: an empty comment thread is a real reading, not an unconsulted one, plus the decorated/bulleted/bolded and cross-repo variants.

    Re-measured the specimen this card was filed on, #11017: now closed, carries no pm:* label, has no Blocked-by: in its body but does have one in a comment — exactly the two-channel shape H4 clears. The card's premise ("this is one more predicate the patrol needs") was true when filed against a body-only reading, and is no longer true against current main.

    ⛔ Nothing here touches the wording half (「留言上报」 → 「挂 pm:retriage + 异议评论同笔」), which is wave-4-B's diff and the half that ends this card. This card remains open.


    Generated by Claude Code

  8. removed their assignment
    on Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions