skills(pm-dispatch): pm:awaiting-maintainer owes a Maintainer-action: entry line, read by H55; 具名不升级类 gains the four bookkeeping classes - #17220
Conversation
…line, read by H55; four bookkeeping classes join 具名不升级类 Half A — the carrier. Every other parked state carried a mandatory machine-readable line (`Blocked-by:`, `Restart-when:`); the awaiting state carried nothing, so a card waiting for a JUDGEMENT was indistinguishable from one waiting for a HAND. `references/state-machine.md` now specifies a line-anchored, case-sensitive `Maintainer-action: <action a seat cannot perform> — done when <checkable evidence>` in either channel, and states the classification test: 写不出即决定待做. The SKILL.md state-model row and its core-rules twin point at it. `check-half-states.mjs` gains H55, a report-only ENTRY predicate (band `state`) with a gated thread read on the shared comment cache; legacy entries — last touched before the pinned `MAINTAINER_ACTION_LINE_SINCE` — render as one summary census line, never as rows, so the landing day is not red on the healthy case. Not a machine exit: the H11 note is reconciled to say the state now has an entry predicate and still no exit; H25's deferral note points at H55. Half B — the floor. 具名不升级类 gains the four bookkeeping classes, each bounded by 无产品可见行为变化, in SKILL.md and its core-rules twin; the 人工地板 lines are untouched. Line-neutral on all three governed files, each at its ratchet ceiling: SKILL.md 812/812 (row extended in place; −2 restated lines, +2), state-machine.md 42/42 (−1 line stated in lanes/hotcrm.md, +1), core-rules.md 151/151 (−1 intra-file duplicate, +1; one line rewritten in place). Self-test 3019 → 3103 cases. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ
维护者速读改了什么 — 给「等您亲手做一件事」的状态( 为什么改 — 您 09-09 的两句话:「5986 这种任务不影响我们的产品质量,不应该让人类决策,项目经理自己当场决定就可以,而且这个应该开技能卡纠正」和「这个不应该是决策卡吗?哪个流程出了问题?」。溯源结果:这个状态只有定义没有载体,谁都能挂、没人能证伪;H8 只查有没有转状态、不查转对没有;巡查只看形状和时间不看含义。卡上当天量到 55 张里约 49 张挂错;派发时板上已剩 7 张(上午有一轮改判),缺陷本身没变。 风险与代价(含回滚) — 三个技能文件都在行数上限,每加一行删一行,删的四行在别处都已成文(本席逐条核对;其中 SKILL.md「先过升级门槛:明显的问题直接修,大多数感觉像决定的不是决定」这一行是判断而非纯重复,请您过目)。H55 判新旧用卡片 席位意见 — 本席以契约复审档复核通过:七条裁决逐条对分支核实,自测 3103 例全过,CI 31 项全绿(含线上巡查实跑),合并无冲突。建议合并;合并后本席另开一张有界的改判工作单处理现存 7 张卡。 你要做的 — 受管面走人工合并:看一眼新增那行的写法与被删的那四行,认可即批准并合并本 PR。是否合并? Generated by Claude Code |
Fixes #17017
Maintainer, 2026-09-09, verbatim and untranslated — the two instructions that opened the card. The first is the authority for Half B, the second for Half A:
Governed surface (
.claude/**) ⇒ draft, human merge;skip-changeset(nothing here publishes:.claude/**andscripts/pm/**ship in no packagefiles[]).Half A —
pm:awaiting-maintainergains a machine carrierThe state had a semantic contract (决定已做, one action a seat cannot perform) and no machine carrier:
pm:blockedowesBlocked-by:,pm:on-holdowesRestart-when:, and this state owed nothing, so a card waiting for a JUDGEMENT was indistinguishable from one waiting for a HAND.references/state-machine.md§pm:awaiting-maintainer与pm:retriagenow specifies the entry line (the two placeholders are spelled as words in this PR body because the platform mutates angle-bracket fragments; the file carries them literally, in the same shape asRestart-when: closed OWNER/REPO#N):awaiting 入态带 Maintainer-action: ACTION — done when EVIDENCE,双通道行锚定。— ACTION = 席位做不了的动作, EVIDENCE = 可查证据; body OR comment; line-anchored and case-sensitive like the two sibling lines.写不出即决定待做;本态无机器出口:维护者完成后由总监席核验摘标 + 证据评论同笔。— the classification test the card asked for (「裁完之后」 is the definition ofneeds-user-decision), folded onto the existing exit line.SKILL.md状态模型 row (pointer form, table row extended in place, 234 B ≤ the 342 B table pin):…;入态恒带行首 Maintainer-action: 行(细则见 references/state-machine.md),无行即半态.references/core-rules.mdtwin (in place):pm:awaiting-maintainer 只剩站外人工动作,恒带 Maintainer-action: 行;pm:blocking ⛔ 不手工挂。scripts/pm/check-half-states.mjs— H55, report-only, bandstate: an open card carrying the label whose body and thread carry no completeMaintainer-action:line. The line is read by the shared decorated-directive reader (directiveValues), so it is line-anchored, case-sensitive, decoration-tolerant, and a mid-sentence mention is prose. Both halves are required: a value without itsdone whenhalf fires as "names an act but never its completion". The thread is bought only for a judged, body-clean card (needsMaintainerActionComments, H9's gate one field over) on the shared comment cache; three input states for the thread (unconsulted / unreadable / read), the unreadable one fires and says so. Remedy text: write the line if the act exists; if the line cannot be written because the card is asking for a RULING, the state isneeds-user-decision(决定待做) and the entry was misfiled; the 台账 reader is the director seat's 职责三 (维护者动作台账). ⛔ Not a machine exit — the state still has none by construction; the row judges the ENTRY only.Maintainer-action:line first (still never prescribing aRestart-when:re-check — the existing pin at :19486 holds). H25's deferral note ("any requirement that the card NAME the awaited action … a protocol face the state-model row has not been written for yet") now says that face exists and H55 reads it; H25 stays the EXCLUSIVITY half, H55 is the ENTRY half, neither widened into the other.Population scoping (ruling 2) — the landing day must not be red on the healthy case
Entries are split at a pinned instant,
MAINTAINER_ACTION_LINE_SINCE = '2026-09-10T00:00:00Z'(the UTC day after the rule was written, in the file's own pinned-date idiom): a card last touched BEFORE it is a legacy entry and renders as ONE summary census clause —Awaiting-maintainer entries (H55): N open pm:awaiting-maintainer card(s) last touched before … — COUNTED here and filed as no row …, oldest #N (last touched YYYY-MM-DD); …— never as rows; a card touched ON/AFTER it is judged and can be a row.The split reads
updated_at, not thelabeledevent — the trade, stated. The entry instant is in no payload the sweep already holds (assumption C, measured: the loop holds the label pages' issue payloads, and the only event reader, H35, consumes the repo-wide stream filtered to gate-semantic labels —pm:awaiting-maintaineris not one), and this file's standing design makes no per-card timeline fetch.updated_atis the cheapest honest proxy and its error runs one way:updated_atis never earlier than the labelling, so a card last touched before the pin certainly entered before it (the census can never hide a post-pin entry); a legacy entry TOUCHED after the pin lands among the judged and can render as a row — an over-read costing one cheap idempotent act (write the line, or reclassify) on a card someone is already handling. An unreadableupdated_atis judged, never counted as legacy.Measurement — the live board at authoring (2026-09-09T17:4xZ; REST list endpoint + per-card
/events; 0 MCP calls)pm:awaiting-maintainerlabeledevent → last touch)needs-user-decision— H25 already fires), #17151 (09-09T13:21 → same)updated_atwithin 3 s of thelabeledevent; 2 were touched after enteringPremise shift, reported rather than pressed: the card measured 55 (37 / 16 / 2) on 2026-09-09 and 55 → 55 across ~14 h. By dispatch the population was 7: the repo-wide events stream (H35's channel, read 30 pages per repo back to 2026-09-09T03:38Z / 2026-09-08T17:07Z) shows a reclassification pass that morning — objectui 15
unlabeled pm:awaiting-maintainerat 02:56–03:04Z, objectstack's named specimens at 02:29–05:12Z (#13636, #16500, #12675, #12884, #15406 unlabeled and closed; #12034 back topm:queue). The three defects the card names (no carrier, H8 blind to the chosen state, the sweep reading shape and time only) are unchanged by the count, so the design stands; what changes is the landing-day shape — with the pin above, all 7 render as the census clause on the first sweep, not as rows. Thesearchendpoint answers 403 from this container, so the control reading is the events stream plus a list-endpoint control on a populous label (pm:dispatched= 26 open).Half B — the floor of what may reach the maintainer
具名不升级类 (SKILL.md 〈升级与决策〉) gains the four bookkeeping classes, each bounded by 「无产品可见行为变化」 so none reads as widening; the 人工地板 lines (SKILL.md :390–:392 after the shift; core-rules :95–:96) are byte-untouched and remain the exclusion set.
具名不升级类(立即行动):…:- 四类记账事同属不升级类,恒以无产品可见行为变化为界:去重与卡片合并;台账与记账整理;(120 B)- 纯文档措辞更正(无契约声明改动);门禁内部参数与扫描器盲区修复(加强,非削弱)。(110 B)具名不升级类:…:- 记账事不升级(无产品可见行为变化):去重并卡、台账整理、纯文档措辞、门禁盲区加强。(119 B; the compressed spelling the 人读摘要 file uses for every twin).Authority: the maintainer's first sentence above — cited here, ⛔ not inside the skill text (the skill states rules;
check:pm-skill-id-lintkeeps citations out).Line budget — every file at its ratchet ceiling, headroom 0, line-neutral
pnpm check:pm-skill-ratchetonaf85c612:SKILL.md is 812 lines (ceiling 812; headroom 0)·widest table row is 342 bytes (pin 342)·state-machine.md is 42 lines (ceiling 42)·core-rules.md is 151 lines (ceiling 151). No re-wrap, no ceiling raise,check-skill-line-ratchet.mjsuntouched.SKILL.md- 机会主义重启条件必须点名触发文件。(:131) — the rule is stated inreferences/state-machine.md:18–:19 (Restart-touch:mechanics) and SKILL.md :124 already points there. (−1)- 先过升级门槛:明显的问题直接修,大多数感觉像决定的不是决定。(:711) — restated by the three lines under it (:712–:713 the two thresholds and 其余归 PM 裁量; :714 具名不升级类(立即行动)); introduced by the rules-only rewrite, not a ruled clause.references/state-machine.md- 标签须五仓存在,首次应用时创建。(:42) — stated inreferences/lanes/hotcrm.md:46 (「pm 状态机词表五仓统一,幂等创建在 scripts/pm/ensure-pm-labels.sh」) and mechanised by that script (it createspm:awaiting-maintaineridempotently, :212).references/core-rules.mdpm:blockingkeeps its ⛔ and loses only the WHY (「是反向索引推导的缓存」), which SKILL.md :112 keeps. (−1)- `pm:dispatched` 与摘 `pm:queue` 恒在同一次标签写入里成对落地。(:30) — an intra-file duplicate of :109 (「认领原子对:一次标签写入完成认领与状态对调…」) and :38 (「转换恒一笔 replace」); SKILL.md :107 and :466 keep the rule, so the twin obligation (SKILL.md :44) is untouched.references/lanes/director.mdMechanism assumptions (派发词 — tested before acting)
check-governed-prosepins the SKILL.md region between**ACCEPT 之后的路径分叉and本段只适用本循环派发的 dev PR;check-half-statespinsRELEASE_RULE_LINE(SKILL.md's 释放是显式动作 line) and the retriage answer line;check-skill-frame-syncpins the four-axis frame;check-clause2-carriers/check-widening-tellspinreferences/contract-review.mdand the claim spelling. None of the deleted or edited lines is in any pinned set — all six gates are green below. Held.pm:awaiting-maintainer跨仓标签是待人工动作的唯一机器载体」 was read as the label being the unique carrier of the STATE (against seat-post prose, :55 「标签即状态」), while the new line is the label's machine half specified instate-machine.md, which :56 already points at (「出口条款见 ../state-machine.md」); :54 「台账与出口归本席」 is what the H55 remedy names. No sentence contradicts the line ⇒ left untouched, per the ruling. Noted in Acceptance notes as the one reading a reviewer may want to overturn.updated_at) taken, trade stated in the header, the row text and the summary clause.SKILL.md:110/:126are :111/:127 ona9550bf8;check-half-states.mjs:2298is :2302 (the note) / :2307 (the remedy); 具名不升级类 :714 and 人工地板 :391–:393 as cited. Worked from the tree.Gates (local, on
af85c612; the list derived bynode scripts/pm/dispatch-gates.mjsona9550bf8— 45 families — and re-derived from the real changeset on the final tree: identical 45;--ranreconciliation below)Every exit captured before any pipe (
cmd > log 2>&1; EXIT=$?).node scripts/pm/check-half-states.mjs --self-test(check:pm-half-states)✓ check-half-states self-test: 3103 cases pass.(baseline ona9550bf8: 3019; +84 H55 cases)pnpm check:pm-skill-ratchetpnpm check:pm-skill-id-lint✓ check-skill-id-lint: 26 file(s) clean (pattern /#[0-9]{3,}/g).pnpm check:skill-frame-sync/check:skill-frame-freshness2 copies of the decision frame are structurally isomorphic across 2 files/the frame itself is unchangedpnpm check:pm-governed-prose2 instruction surface(s) name all 5 registered governed surfaces … and claim no others.pnpm check:pm-clause2-carriers/check:pm-widening-tells(self-tests)pnpm check:nul-bytes+ the control-byte grep over the four filesno raw ASCII control bytes/ emptypnpm --filter @objectstack/lint run check:doc-formula-expressions@objectstack/formula) — NOT a measurement; rebuiltformula+lintunderos-verify-lock.sh(VERDICT command-exit 0 · held the lock 2s) and rerun: exit 0pnpm check:*families (agent-test-spelling, bash32-floor, changeset-gate-self-tests, cli-command-ids, cross-package-test-inputs, doc-authoring, driver-memory-census, entry-guard, parse-guard, partof-closing-keyword, pm-governed-merges, pnpm-filter-targets, ratchet-remedy-authority, refd-timer-probe, watch-hint-literal, pm-half-states)nodefamilies (reference-carrier-shape ×2, changeset-no-major ×2, ci-filter-parity, closing-keyword-parity ×2, comment-mask-corpus, declaration-mirrors ×2, scripts-symbol-anchors ×2 —3094 anchors across 238 scripts resolve, self-test-wired ×2, self-test-workflow-commands ×2, whole-set-label-write ×2, bare-root-worklist --self-test —OK … none stale, none missing, none contradicted, governed-queue-guard --self-test, sweep-closed-cards --self-test, report-test-timings --self-test)pnpm check:pm-dispatch-gates(> 600 s foreground cap; run detached,tail --pidwaited)setsid nohup, waited withtail --pid):✓ dispatch-gates self-test: 1624 cases pass., exit 0.node scripts/pm/dispatch-gates.mjs --ran RAN_FILEon the final tree:45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASUREDcheck-governed-queue-guard.mjs(workflow payload),check-partof-closing-keyword.mjs(env), shard attestation, test completeness, the--format=markdown --provenancesweep runNo package touched ⇒ no build closure owed; no changeset (
skip-changeset:.claude/**andscripts/pm/**publish nothing — no gate demanded one;check-changeset-no-majorexit 0).Reverse verification (one-time ablation, committed state, restore proven by bytes)
Committed first (
af85c612), then mutated under atrap restore EXIT INT TERMwith absolute paths: the first statement ofh55AwaitingWithoutMaintainerActionwas madereturn null(markerABLATION-17017-MARKER). Landing proven on disk before reading any result: marker count 0 → 1 on the anchor line, blobf015273c…≠ HEAD blob0ec90893…. Expected direction: RED (the positive control and every row-text case), the census/registry/summary cases unaffected — observed exactly that:✗ check-half-states self-test: 20 of 3103 case(s) failed., the 20 being the sixH55 fires:cases, the three thread-state cases, the undated case and the tenH55 row:sentence cases; every neighbour (H9, H11, H25, H54, summary clauses, band registry) stayed green. Restore leg:git checkout HEAD -- ABSOLUTE_PATH(never a bare checkout — the index is the mutation), proven bygit diff HEAD --statempty,git status --porcelainempty,git hash-object=0ec90893d36c84e19c8721b755252781b8b8b805=git rev-parse HEAD:scripts/pm/check-half-states.mjs, marker count back to 0; the restored run reads✓ check-half-states self-test: 3103 cases pass.again. Nodist/is involved (the sweep runs from source), so no dist preflight applies; no permanent test file was left behind.Acceptance notes
Maintainer-action:line or moved toneeds-user-decision(决定待做) / closed.objectstack devhas no https mode, so the advertised OAuth path for interactive MCP clients cannot be tried against a local dev server #16804 already carries bothneeds-user-decisionandpm:awaiting-maintainer(H25 fires on it today) — first in that worklist. No live card was touched by this PR.…唯一机器载体,其 Maintainer-action: 行即台账行。— it measures 122 B, 2 over the cap, so it would cost a fold elsewhere in the 72/72 file; not done here.done whenrequired — H55 reads "both parts" literally: aMaintainer-action:value without adone whenhalf fires as half a line (its own sentence). The dash spelling is not the contract (—,-,--all carry it); the KEY is byte-exact.check-half-states.mjs'sdirectiveValuesJSDoc named only two keys; widened to three (comment only). noted, not filed — 承接者: the reclassification worklist above: the awaiting label'sensure-pm-labels.shdescription (:212) still says "no machine exit" — true, and now incomplete (no mention of the entry line); a description string, no reader.GET /search/issuesanswers 403 from this container (so did MCP-free dedup rely on the events stream + list endpoint);Maintainer-actionhad 0 hits onorigin/mainat dispatch and this PR is its first spelling.维护者速读(草稿)
改了什么
给
pm:awaiting-maintainer(等您亲手做一件事的状态)加了一条必填的机器可读行:Maintainer-action: 要做的那件事 — done when 怎么验证做完了。写不出这一行的卡,说明它等的不是您的手而是您的裁决,应当放进决策箱(needs-user-decision)。巡查脚本新增 H55 报"进了这个状态却没写这行"的卡(只报告不改标签);今天之前已在状态里的卡只汇总成一行计数,不逐张报红。另外,四类纯记账事(去重合卡、台账整理、纯文档措辞更正、门禁内部参数与盲区加强)明确列为 PM 当场自决、不上报您。为什么改
您 09-09 的两句话:5986 那种任务不该让人决策、该开技能卡纠正;以及"这不应该是决策卡吗?哪个流程出了问题?"。溯源结果是:这个状态只有定义没有载体,谁都能挂、没人能证伪,H8 只查有没有转状态、不查转对没有,巡查只看形状和时间不看含义。卡上当天量到 55 张里约 49 张挂错;派发时板上已剩 7 张(上午有一轮改判),缺陷本身没变。
风险与代价(含回滚)
三个技能文件都在行数上限,每加一行删一行(删的都是别处已有的重复表述,PR 正文逐行列出)。H55 判"新旧"用的是卡片
updated_at而不是打标签时刻(不做逐卡 timeline 请求),代价是:老卡在 09-10 之后被碰过就会被当新卡报一次,补一行即消;绝不会漏报新卡。回滚 = revert 本 PR,无数据、无标签、无 workflow 变化。席位意见
(留空)
你要做的
读完后人工合并本 PR(受管面,席位不合)。合并后如同意,由席位另开一张有界的改判工作单处理现存 7 张卡;本 PR 不动任何在板卡片。
Generated by Claude Code