Skip to content

finding(pm): open+pm:queue+assignee 双向撒谎态,三仓 17 张——四条机器门修法(新 H 规则/配对写入补 assignee/巡查跨仓/H22 窗口),外加一个需裁决的「等人工动作」状态 #11196

Closed

Description

@os-zhuang

Finding,只记录不认领(skills 席 session 757f0dc0-5dae-51d7-9053-c15c57ebfe3b,2026-08-23)。排查主体是另一 PM 席位(维护者转达其报告),本席独立补全了普查并采信其根因链;证据引文见该报告,本卡以可机判修法为主。

精确普查(本席,2026-08-23,REST 全翻页,权威)

open + pm:queue + assignee 非空 = 17 张(此前两份报告分别说 22 与 15,均不准——22 混入了无 pm 状态的卡,15 漏了 objectui 两张):

仓 open+pm:queue 已 assign 卡号
objectstack 135 6 #10757 #10667 #10638 #9483 #9298 #7276
objectui 146 10 #5574 #5451 #5034 #4806 #4535 #3965 #2890 #2762 #2731 #2628
cloud 19 1 #1548

矛盾:队列视图按 pm:queue 说「可派发」,认领规则按 assignee 说「已被占,永不碰」。两条规则同时生效,卡谁都动不了。

根因(采信排查席,四条,均有实测证据)

  1. 主因:状态回退只翻标签不摘 assignee——落地回标(H8)、解锁扫描(pm:blocked→pm:queue)、死认领回收三条路径里只有回收明写摘 assignee;前两条协议根本没提这个字段(objectstack#10638、QA wave R0: provision the shared QA tree and take the machine-lane baseline at e4e5c6e3 #9298、objectui#2731 各是一条路径的活标本)。
  2. 巡查结构性盲区:H2 抓「有 assignee 无 Claim 评论」、H3 抓双状态共存,「有 Claim + pm:queue + assignee」落在两规则之间;且 half-state-patrol.yml 用 ${{ github.repository }} 只跑 objectstack——objectui 10 张、cloud 1 张从未被机器扫过。
  3. 缺「等维护者人工动作」的合法状态(objectstack#7276 活标本:剩余动作是维护者在 Routines UI 里的手工操作,needs-user-decision 与 pm:on-hold 的 Restart-when: 机器判据都不合身,卡来回摆)。
  4. assignee 字段双语义:本席普查实锤——objectui 已 assign 的 10 张里,yinlianghui ×3、qq9340100 ×2、os-sales ×1 是非派发循环身份的真所有权,与 agent 死认领残留(os-zhuang/os-elon/os-project-manager)混在同一字段。

另采信排查席的伴生量级读数:巡查本轮 94 条 findings 里 H22(已关闭卡残留 pm:*)独占 31 条;epic 子树(#9465 的 4 张 8-18 关闭子单)整批超出 H22 的 200-张窗口(~130 合并/天 ≈ 1.5 天),巡查报告零命中。

修法(1–4 可机判,进 scripts/pm/check-half-states.mjs 与 patrol workflow;5 需裁决)

  1. 新 H 规则:open ∧ pm:queue ∧ assignee 非空 ⇒ 红。零判断纯交集,17 张的唯一机器读法。⚠️ 与根因 4 的例外交互:规则先落,例外(若裁出真所有权语义)以显式标记豁免,不反过来。
  2. 配对写入补半条:落地回标与解锁扫描的配对定义加「同笔摘 assignee」(现仅死认领回收有);或 H8/H19 的 remedy 文案直接点名这一笔。
  3. 巡查跨仓:workflow 参数化仓名,objectui/cloud 各跑——单这条覆盖 17 张里的 11 张。
  4. H22 窗口按合并速率重定(200 张 ≈1.5 天,epic 批量收尾必超窗)。
  5. ⛔ 需维护者裁决:「等人工动作」状态怎么给(扩 pm:on-hold 的 Restart-when 接受人工判据+定期点名 / 新标签 / 维持现状)。裁决另行请示,不阻塞 1–4。

与 #11179 的关系

同族不同形:#11179 是「已判未转」(判断做了标签没写),其两条 H 规则(pm:queue∧needs-user-decision 共存、pm:queue 零活动超期)不覆盖本卡 17 张;本卡规则 1 补上。两卡宜同一 PR 落(同文件同自测),派发时可并单。

存量 17 张的清理

不在本卡范围(本卡只落门)。清理需逐张判「死认领 vs 真所有权」:agent 身份残留(≈11 张)可按各自证据清;人类/他席身份(≈6 张)⛔ agent 不得代摘。

Activity

  1. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    维护者裁决,2026-08-23(AskUserQuestion,原文逐字):

    修法 5(「等维护者人工动作」状态):「可以新标签,最好 pm: 开头」
    存量 17 张清理:「A:本席清 agent 残留(推荐)」

    执行注记:新标签拼写建议 pm:awaiting-maintainer(实现 PR 里定稿,须进各循环的状态互斥表与巡查规则);存量清理由 skills 席按逐张证据执行——仅清 agent 身份(os-*)的死认领残留,yinlianghui/qq9340100 等人类身份的 ≈5 张 ⛔ 不动。每张清理留一行证据评论,清理不在本卡范围内展开,结果回贴于此。


    Generated by Claude Code

  2. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    存量清理执行完毕 + 读回复核(skills 席,2026-08-23,承上条裁决记录):

    双向撒谎态即刻止损;修法 1–4 + 新标签实现仍由本卡携带,待派发。


    Generated by Claude Code

  3. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Triage: labeled finding + routed domain:skills — PM-protocol machinery (queue+assignee half-state, proposed H-rules); skills-lane findings are self-triaged by that seat. The "等人工动作" state question it raises is a ruling input — the skills seat should carry it to the maintainer with its grading, not decide it.


    Generated by Claude Code

  4. 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. The maintainer ruling of 2026-08-23 (new pm:-prefixed label for fix 5; spelling pm:awaiting-maintainer to be finalized in the PR) plus the completed legacy cleanup leave fixes 1–5 fully specified — nothing left to ask. Scope = fixes 1–5 as written. Hot-file note (fold-or-serial, answered): scripts/pm/check-half-states.mjs is shared with #11219/#11218/#11217/#11118/#11248 — these will be dispatched as one serialized family or a fold per the five-gate test at dispatch time, never in parallel. #11179 (named in this card as a pair candidate) is still untriaged/unlabeled and is NOT foldable until routed.


    Generated by Claude Code

  5. self-assigned this
    on Aug 23, 2026
  6. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 1, wave 3 — family dispatch anchor (members: #11196, #11217, #11219, #11118; all graded this round, one graded scope overlap resolved here: #11196's fix 3 ≡ #11217's objectstack half, #11196's fix 4 ≡ #11118's H22 leg — one dev resolves them coherently)
    Session: session_01RMTpSRF5CjMmQBFfPtPCwJ
    Branch: claude/issue-11196-half-state-patrol-family (shared; member cards carry no own branch by design)
    Worktree: objectstack-issue-11196
    Domain: domain:skills
    File surface: scripts/pm/check-half-states.mjs (+ embedded self-test) + .github/workflows/half-state-patrol.yml + scripts/pm/ensure-pm-labels.sh (the new label's vocabulary entry) (stop on breach; explain in the report)
    Container & model: L-leaning M, mode:subagent, model: opus — dispatch-gates --tier at wave 1 for this file: no path-derived mandate; patrol predicate + workflow logic = judgment work
    Clause-②: no
    Serial constraints cleared: this is THE hot-file family the fold-or-serial answer on this card's grading comment named — dispatched as one fold, nothing else in flight touches these files (#11084 = check-governed-merges.mjs, #11079 = AGENTS.md, disjoint). #11179 remains untriaged and is NOT folded; #11109's predicate half and #11248's predicate are deliberately NOT folded either (their cards carry non-patrol halves; they dispatch later and will serialize behind this PR on the same file).

    Fold answer (five gates): ① one defect shape — the patrol's input set / predicate vocabulary is narrower than the states the board actually produces; fix = widen inputs/predicates + selftest pins. ② one script + its workflow + the label vocabulary, one worktree, one PR. ③ all four graded this round; #11196 additionally carries the maintainer ruling of 2026-08-23 (new pm:-prefixed label). ④ per-member criteria in the dispatch brief. ⑤ exclusions: #11248's dead-claim predicate and #11109's no-Blocked-by-line predicate (same file, NOT here — later serialized dispatch); the SKILL.md state-model table row for the new label (protocol face, fable-mandatory — explicitly deferred, declared not dropped); sibling-repo workflow installs (consumer cards filed at ACCEPT); any cross-repo token machinery (refused at grading, #11218's loudness half covers honesty).


    Generated by Claude Code

  7. claude commented on Aug 23, 2026

    @claude
    Contributor
    {
      "issue": 11196,
      "status": "done",
      "branch": "claude/issue-11196-half-state-patrol-family",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11294",
      "premise_still_valid": true,
      "summary": "Family of four landed as one draft PR, one commit per member, four `Fixes` lines: #11196 (H24 open+pm:queue+assignee as a pure two-field intersection; H8/H19 remedy texts now name 「同笔摘 assignee」; `pm:awaiting-maintainer` implemented as a first-class state — vocabulary entry, H25 exclusivity, and membership in H11/H13/H22 plus its own label page in the sweep listing), #11217 (repo resolved PM_SWEEP_REPO -> GITHUB_REPOSITORY -> default with a malformed value refused at exit 2; anchor moved to the repository variable HALF_STATE_ANCHOR_ISSUE with 9857 kept as a fallback GUARDED by repo name, and a step that fails loudly rather than writing an unconfigured anchor), #11219 (H26: an open pm:blocked card whose open target carries pm:on-hold/needs-user-decision can never be released, plus the transitive flag when the target is itself pm:blocked — quota-neutral, the labels ride on payloads H19 already paid for), #11118 (H8 2->4 pages, H22 2->4 pages, H23 unchanged at 3, all re-derived against a freshly measured ~137.5 merges/day with the derivation made executable). Two premise refinements, neither fatal: #11217's body says the workflow runs the sweeper `against ${{ github.repository }}` — it did not pass a sweep target at ALL, and the script's hardcoded literal was doing the work, so the conclusion (objectstack only) and the fix are unchanged but the mechanism is one layer down; and #11118's ~132/day re-measures to ~137.5/day, i.e. the card understated rather than overstated. PM note, not a question: the sibling-repo installs this PR enables need a repository VARIABLE set per repo, which is a manual maintainer action — the consuming cards filed at ACCEPT should say so.",
      "tests": "All runs at HEAD 02e28386 (merge-base 050d8d868), each exit code captured before any pipe, each verdict quoted from the gate's own output. (1) SELF-TEST, the file's own gate `check:pm-half-states`: baseline `879 cases pass` at BASE -> `✓ check-half-states self-test: 997 cases pass.` at HEAD (+118: 52 for #11196, 20 for #11217, 26 for #11219, 20 for #11118), run under scripts/pm/os-verify-lock.sh, `VERDICT command-exit 0`. Both directions pinned for every new predicate, every vocabulary membership (H11/H13/H22 clean AND firing), the H19/H26 disjointness (a closed target is H19's row; an unresolved target is H19's sentence and H26 stays silent), and the degenerate window inputs that must answer null rather than Infinity. ONE pre-existing pin failed deliberately and was updated with its reason: H22's 'the measured residue set is the five from the census' (the new label is the one non-census member). (2) PARAMETERISATION PROOF for the objectstack leg, measured not asserted: with globalThis.fetch stubbed, the real CLI issues `GET https://api.github.com/repos/objectstack-ai/objectstack` under GITHUB_REPOSITORY=objectstack-ai/objectstack (byte-identical to the literal it replaced), `/repos/objectstack-ai/objectui` under the sibling shape, `/repos/objectstack-ai/cloud` when PM_SWEEP_REPO overrides, and NO request at all with PM_SWEEP_REPO=objectui (`EXIT=2`, refusal printed). Anchor: vars unset + repo==objectstack-ai/objectstack resolves to '9857', the pre-change literal. YAML re-parsed after the folded-scalar fix — ANCHOR_ISSUE is a single-line expression (a more-indented continuation in a `>-` block was measured keeping its newline). (3) WINDOW MEASUREMENTS, live REST via curl at 2026-08-23T08:42:15Z, windows pinned as full ISO instants: 300 commits 2026-08-21T04:00:19Z..2026-08-23T08:22:47Z = 2.18d -> ~137.5/day, 300/300 carrying the squash marker; H8 2 pages = 200 rows/197 merged, oldest merge 2026-08-21T14:00:28Z = 1.78d, 4 pages = 400/397, oldest 2026-08-20T09:41:02Z = 2.96d; H22 2 pages = 0.65d of update-recency (~15.6h, ~2.6 sweeps), 4 pages = 1.70d; H23 3 pages = 2.18d, ~8.7 sweeps. (4) GATES derived with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` on the actual change set (script's own three-dot derivation, `--repo` assertion held) — 20 families named, all run: cross-package-test-inputs EXIT=0, entry-guard EXIT=0 ('138 scripts/ file(s) — every entry guard goes through invoked-as.mjs'), node-version EXIT=0, parse-guard EXIT=0, pm-half-states EXIT=0, pm-label-desc-cap EXIT=0 ('21 label descriptions ... all ≤100 characters'; the new -d is 88), pnpm-filter-targets EXIT=0, required-contexts EXIT=0, shard-attestation EXIT=0, workflow-status-functions EXIT=0, aggregator-roster EXIT=0, ci-filter-parity EXIT=0, closing-keyword-parity EXIT=0 ('3 parsers agree on all 9 keywords'), step-collectors EXIT=0, check-nul-bytes EXIT=0 ('no raw ASCII control bytes'), partof-closing-keyword run with PR_BODY set to the real body EXIT=0 ('this PR carries no Part-of/closing-keyword contradiction'). (5) REPO-WIDE LINT, not a narrowed subset: `pnpm lint` (`eslint . --no-inline-config`) EXIT=0, no output, 78s under the lock. (6) LIVE SWEEP NOT RUN and cannot be here — `--probe` returns the classified PREREQUISITE NOT MET, EXIT=3 ('the token in the environment is not a valid GitHub credential', prox… len 14, anonymous quota spent), exactly as the file header documents; the workflow's pull_request trigger runs the real sweep on this PR on a runner. No ablation was performed: nothing here is a build artifact, so there is no dist/ leg to state.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #11296: `scripts/pm/ci-failure.mjs:300` carries the same hardcoded `PM_SWEEP_REPO ?? 'objectstack-ai/objectstack'` default this PR removed from the sweeper — a copy in a sibling repo would report on objectstack's CI and read as correct. Unassigned, unlabeled, out of the declared file surface (dispatch said stop on breach), dedup-searched against #11217/#11218/#10971."
      ],
      "deviations": [
        "DECLARED DEFERRALS (per dispatch, not dropped): the SKILL.md state-model table row for `pm:awaiting-maintainer` (protocol face, fable-mandatory, separate landing) and applying the label to specimen card #7276 (the seat's write at ACCEPT). Both are stated in the PR body and in the code's own docblock.",
        "WIDER THAN A LITERAL READING of #11196 fix 5's 'mutual exclusions': the new state also joins H11's parked inventory, H13's PM_STATE_LABELS and H22's PM_RESIDUE_LABELS, and gets its own label page in the sweep's listing loop (one request per sweep, four sweeps a day). Reason: the fold's stated defect shape ① is 'the patrol's vocabulary is narrower than the states the board produces', and a new state invisible to four readers would be that defect on arrival — H13 in particular would have fired a false row on every carrier two hours in. Every membership is pinned in both directions.",
        "H22's page cap was WIDENED (2->4) rather than only restated, against an anti-drowning argument already in the file. The argument refuses the 500+ historical carriers spanning months; 1.70d is not that population, and the measured 0.65d/15.6h reach was not what the argument thought it was buying. Evidence in the docblock, both readings quoted.",
        "`skip-changeset` applied to PR #11294 via the additive endpoint (add_status=200) and READ BACK after the size labeler settled: ['size/xl', 'skip-changeset'] — survived. No changeset written: scripts/pm/** tooling plus one workflow, nothing published.",
        "NOT TOUCHED, as instructed: scripts/pm/bare-root-worklist.mjs, scripts/pm/check-governed-merges.mjs, any .claude/** file, any sibling repo. #11248's dead-claim predicate and #11109's no-Blocked-by-line predicate are not in this diff and will serialize behind it on the same file; #11218 is not addressed here."
      ],
      "files_changed": [
        "scripts/pm/check-half-states.mjs (+982/-33)",
        ".github/workflows/half-state-patrol.yml (+88/-2)",
        "scripts/pm/ensure-pm-labels.sh (+23/-0)"
      ],
      "commits": [
        "6bc3e478 — #11196: H24, pm:awaiting-maintainer + H25, H8/H19 paired-write remedies",
        "5d86dc61 — #11217: repo + anchor parameterised for verbatim sibling adoption",
        "16046238 — #11219: H26 indefinite block + transitive-wait flag",
        "02e28386 — #11118: H8/H22/H23 window arithmetic re-derived"
      ],
      "per_member_criteria": {
        "11196": "fix 1 H24 (open ∧ pm:queue ∧ assignee, zero judgement, rule-first ordering, login named, asymmetric remedy) ✓; fix 2 H8 full-delivery + H19 release texts name 「同笔摘 assignee」, half-delivered branch deliberately silent ✓; fix 5 pm:awaiting-maintainer spelling finalized, vocabulary entry with named consumers, exclusions vs pm:queue/pm:dispatched/pm:blocked/pm:on-hold/needs-user-decision pinned ✓; deferrals declared ✓",
        "11217": "script + workflow take repo and anchor as inputs, sibling adopts verbatim ✓; objectstack leg unchanged, proven by fetch-trace URL equality + 20 self-test pins, not asserted ✓; no cross-repo token machinery ✓",
        "11219": "report-only predicate (open pm:blocked, resolvable target open AND pm:on-hold/needs-user-decision) names the block with no releasing mechanism ✓; cheap chain flag (target itself pm:blocked) ✓; quota-neutral — zero added requests ✓; both directions pinned ✓",
        "11118": "window arithmetic re-derived for H8, H22 AND H23 against the measured rate ✓; H8 and H22 widened to restore their stated boundaries, H23 restated as measured and unchanged ✓; evidence in the docblocks ✓; every measurement window pinned as full ISO instants per the card's approxidate warning ✓"
      },
      "selftest_counts": { "before": 879, "after": 997 }
    }

    Generated by Claude Code

  8. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT (skills seat, session session_01RMTpSRF5CjMmQBFfPtPCwJ, reviewer of record) — family PR #11294, all four members (#11196, #11217, #11219, #11118).

    Checklist conclusions, verified against GitHub: draft ✓ · base main ✓ · four Fixes lines, one commit per member ✓ · changed files = exactly the three declared ✓ · skip-changeset read back surviving the size-labeler ✓. Per-member criteria all met (report on this thread; PR body cross-read): H24 is the pure two-field intersection with rule-first ordering and the asymmetric remedy per the 2026-08-23 ruling; the paired-write remedy texts land on exactly the two rollback paths and deliberately NOT on H8's half-delivered branch (correct — that drop is the #10468 harm); pm:awaiting-maintainer lands as a first-class state with H25 exclusivity and the four vocabulary memberships — the wider-than-literal reading is accepted as the fold's own defect shape applied to itself (a new state invisible to four readers would be the defect on arrival), every membership pinned; the parameterisation is proven by fetch-trace URL equality plus the fail-loud guards (malformed repo refused, unconfigured anchor fails after the sweep); the window re-derivation is now executable so cap and justification cannot drift apart, and the H22 widening is well-evidenced against the anti-drowning argument's own measured reach. Both premise refinements and the deliberate pin update are honest work, recorded. Self-test 879→997 with direction-pairs throughout; live sweep correctly declared unrunnable in-container, with the workflow's own PR-trigger as the on-runner leg.

    Landing class: scripts + workflow + label vocabulary — NOT governed by register; ordinary queue landing once the PR's full check set is green (the seat flips ready + queues on that signal). Deferral carriers filed at this ACCEPT: the SKILL.md state-model row card (fable-mandatory, blocked on this landing) and three sibling-repo install cards (objectui/cloud/objectos, each noting the manual repository-variable step HALF_STATE_ANCHOR_ISSUE — a maintainer action). Post-merge seat duties recorded: run ensure-pm-labels.sh (or the API equivalent) so the label object exists in all five repos, then apply pm:awaiting-maintainer to specimen #7276 with the evidence comment. Out-of-scope finding #11296 verified filed (ci-failure.mjs same-default trap — awaiting triage routing).


    Generated by Claude Code

  9. 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