Skip to content

skills(pm-dispatch): push-notify the maintainer when an item moves into the maintainer's hands - #24488

Draft
objectstack-fleet[bot] wants to merge 1 commit into
mainfrom
claude/issue-24481-push-notify-maintainer-hands
Draft

objectstack-fleet[bot] wants to merge 1 commit into
mainfrom
claude/issue-24481-push-notify-maintainer-hands

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #24481

Clause-②: no

What changed

One rule in .claude/skills/pm-dispatch/SKILL.md, in 升级与决策 beside the card-before-popup and AskUserQuestion bullets (previously :268–:271), as two bullets at :272–:273:

- 推送维护者:受管 PR 待批合、决策卡待字、发版、仅其可解之阻 ⇒ 另发 `PushNotification`。
- 一行 ≤200 字,先写动作与编号;每项恰一次,例行进展、刚问刚答与在场即见的不推。

The maintainer's order, said in the epic seat's chat (session_01Y5583bs2RDd53MH6kM1ca3, 2026-10-19) and quoted on the card verbatim:

「24422 等我合并,你改过之后没给我推送消息,是skills的问题吗」

「长期固定下来,立一张skills卡片」

The rule keeps the card's content: the four triggers (a governed PR awaiting approval and merge, a decision card awaiting a word, a release step, a block only the maintainer can clear), the push sent in addition to chat and the GitHub record (另发), one line, ≤200 characters, the action and the number first, exactly once per item, and no push for routine progress, a question just answered, or a maintainer who is present. The card's "⛔ 不以 GitHub assign 代推送(同上条)" is already the existing :268 bullet (「⛔ 不 assign 推送」), two lines above, so it is not restated.

Line budget: net 0, paid by deleting duplicated content, not by re-wrapping

pnpm check:pm-skill-ratchet pins SKILL.md at 319 lines with headroom 0 and the widest table row at 342 bytes. The two new bullets are paid for by deleting two bullets whose content lives verbatim-equivalent in references/lanes/director.md, which the director seat reads (:56 already pointed there):

  • deleted 「三职 = 契约复核记录事后审计、决裁勤务、维护者动作台账。」 — director.md's three 职责 headers (:29, :45, :60);
  • deleted 「每场召唤把带席内 ACCEPT 的受管草稿呈为一批 ≤5 行决裁;批准与合并仍是维护者的点击。」 — director.md :53–:54, and AGENTS.md Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14 ("ONE batch of at most five rows, and the click stays the maintainer's");
  • the director row of the args table (:56) now reads 「三职与章程见 references/lanes/director.md」 instead of pointing at this section for the three duties.

No neighbouring bullet was folded or re-wrapped: the dev role file names re-wrap as not a legal currency for the line ratchet (「⛔ 不拿 re-wrap(折行合并)当筹行,新增以删减付账」), and every prose bullet in this file is ≤120 bytes, which a two-bullet fold cannot keep. The dispatch's fallback (stop and report candidate folds) was therefore not needed; the alternative folds are listed in the report comment on the card for the record. Result: 319 → 319 lines; 3 insertions, 3 deletions; every changed line ≤120 bytes (56: 117, 272: 118, 273: 112).

The dispatch's measurement points

  • Mirror line: none added. The round-report duty lives in references/seat-lifecycle.md:66–:68 (「轮次报告与节奏」); references/execution-duties.md carries no round-report duty (its only 轮报 mention, :54, is a triage-gap line); seat Routine prompts live in each session's scheduled task, not in the tree. seat-lifecycle.md is outside the claim's surface and was not edited.
  • Issue-id lint: scripts/pm/check-skill-id-lint.mjs refuses /#[0-9]{3,}/ in this file, so the card's example 「docs(adr): ADR-0131 D6 charts sharing_rule under regime C; D7 ledger reading and lines for #24377 and #24435; D14 records the 18.0 scope #24422 ADR 待您合并」 cannot appear in the rule; the rule states the format ("先写动作与编号") and carries no example (an #N example did not fit the 120-byte line norm with the exclusions kept).
  • The PushNotification tool: the name is the card's. No reference to it exists in the tracked tree, in .claude/settings.json, in .claude/hooks/, or in this container's tool list (a ToolSearch for "push notification" returned no such tool), so the card's 「工具回 not sent 即视为在场,不重发」 clause is unsourced here and was not written; 「每项恰一次」 and 「在场即见的不推」 carry the once-only intent without a claim about the tool's return value.
  • Tier: the card and the dispatch call this PR Tier H. The register (GOVERNED_SURFACES in scripts/pm/check-governed-merges.mjs, row claude-tree), AGENTS.md Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14 and SKILL.md :204 all place .claude/** in Tier S. The posture here is the same either way: the PR is opened as draft and stays draft; this agent never readies, queues or arms it; landing waits for the tier's record.
  • Acceptance item 2 (the next item moving into the maintainer's hands gets exactly one push, recorded in a round report) is the seat's post-landing reading, not part of this PR.
  • Changeset: .claude/** publishes nothing, so skip-changeset is applied at PR creation.

Verification (at c4341e35c)

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on the committed diff: 20 runnable families (12 matched by path, 8 declared whole-tree), plus check-governed-queue-guard.mjs which is CI-measured only. All 20 ran locally, exit codes captured before any pipe; --ran reconciliation: 20 derived, 20 run, 0 NOT-MEASURED, 0 UNRUN (every family with an exit code recorded).

  • pnpm check:pm-skill-ratchet exit 0 — 「.claude/skills/pm-dispatch/SKILL.md is 319 lines (ceiling 319; headroom 0)」, 「widest table row is 342 bytes (pin 342; headroom 0)」
  • pnpm check:pm-skill-id-lint exit 0 — 87 files clean
  • pnpm check:pm-governed-prose exit 0; pnpm check:skill-frame-sync exit 0 (one declared copy, coherent, 90 files scanned); pnpm check:pm-expected-skips exit 0
  • pnpm check:doc-authoring, check:agent-test-spelling, check:cross-package-test-inputs, check:pm-governed-merges — exit 0 each
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions — first run exit 3, PREREQUISITE NOT MET (@objectstack/lint and @objectstack/formula unbuilt; nothing measured); built both under the verify lock (VERDICT command-exit 0), rerun exit 0
  • node scripts/pm/check-governed-queue-guard.mjs --self-test, node scripts/pm/check-harness-current.mjs --self-test — exit 0
  • whole-tree: check:driver-memory-census, check:gitlink-declared, check:nul-bytes, check:refd-timer-probe, check:watch-hint-literal, check-closing-keyword-parity.mjs (self-test and run), check-comment-mask-corpus.mjs — exit 0 each
  • local-only (reading reported, not a CI family): pnpm check:skill-frame-freshness exit 0

No package build, test or typecheck is owed: the diff touches no package. The full farm is CI's; the PR's check-runs are the record for every family CI runs.

维护者速读(草稿)

改了什么:在 pm-dispatch 技能的〈升级与决策〉里加了一条规则:事项转入您手上时(受管 PR 等您批准合并、决策卡等您回字、发版步骤、只有您能解的阻塞),席位除了聊天和 GitHub 记录之外,再给您发一条推送通知;一行、先写要做的动作和编号;每项只推一次;例行进展、刚问刚答、您在场看得见的不推。为了不超过文件的行数上限,删掉了两条总监席的细则(三职清单、每场呈批 ≤5 行),它们在 references/lanes/director.md 里原样都有;参数表里 director 一行改为只指向该文件。

为什么改:2026-10-19 PR 24422 已经通过评审、等您合并,席位只在聊天里说了一句,没有推送,您不在那个会话就不知道。您的原话:「24422 等我合并,你改过之后没给我推送消息,是skills的问题吗」「长期固定下来,立一张skills卡片」。

风险与代价(含回滚):只改一个技能文件的文字,不加门禁、不发布任何包。风险一:席位推送过多——规则用「四类触发」「每项恰一次」和三条不推情形来限;风险二:PushNotification 这个工具名来自卡片,本容器里查不到它,席位会话里是否存在未实测,若不存在,席位应在轮次报告里说明。回滚 = revert 本 PR 一个提交,文件回到 319 行原样。

席位意见:(留空,由席位填写)

你要做的:一个动作——审阅后批准并合并本 PR(受管面,席位不代合)。

Acceptance notes

  • The card and the dispatch call this PR Tier H; the register and AGENTS.md Prime Directive feat: Comprehensive CRM example demonstrating all ObjectStack protocol features #14 place .claude/** in Tier S. Not a defect in the tree; noted for the seat (carrier: the dispatching seat), not filed.
  • check-skill-line-ratchet prints a pre-existing info line unrelated to this diff: .claude/skills/spec-property-retirement/SKILL.md max-table-row-bytes headroom is 2 (pin 326, measured 324), which the gate invites a future PR to lower. Observation only; carrier: none; not filed.
  • The round-report duty in references/seat-lifecycle.md:66–:68 does not mention the push; the dispatch ruled no mirror line, so none was added. Observation only.

Generated by Claude Code

…to the maintainer's hands

Add the rule beside the card-before-popup / AskUserQuestion bullets in
升级与决策: when an item moves into the maintainer's hands (a governed PR
awaiting approval and merge, a decision card awaiting a word, a release
step, a block only the maintainer can clear) the seat also sends one
push notification — one line, action and number first, exactly once per
item, never for routine progress, a just-answered question or a
maintainer who is present.

The line ratchet has zero headroom, so the two new bullets are paid for
by deleting two bullets whose content is carried verbatim-equivalent by
references/lanes/director.md (its three duty headers, and :53–:54 for
the ≤5-row batch and the maintainer's click); the director arg row now
points at that file alone. Net 0 lines; no neighbouring bullet was
re-wrapped.

Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 19, 2026
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Oct 19, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: c4341e35cc6fa3ef337916c89f7bfa01a7a8ce0b
Local-runs: none
Scope: .claude/skills/pm-dispatch/SKILL.md + .claude/skills/pm-dispatch/references/lanes/director.md, .claude/skills/pm-dispatch/references/execution-duties.md, .claude/skills/pm-dispatch/references/seat-lifecycle.md, AGENTS.md (Prime Directive 14), scripts/pm/check-governed-merges.mjs (GOVERNED_SURFACES), scripts/pm/check-skill-id-lint.mjs, scripts/pm/check-skill-line-ratchet.mjs, .claude/agents/os-dev.md

① Derived judgments

  • Inputs read: card skills(pm-dispatch): push-notify the maintainer when an item moves into the maintainer's hands (a Tier H PR to merge, a decision card, a release step) #24481 (body, claim comment 6261400779, os-dev-report comment 6261915698), PR skills(pm-dispatch): push-notify the maintainer when an item moves into the maintainer's hands #24488 (body, file list, net diff against main; merge-base fb9c22a, and origin/main at ae6bd1a carries no change under .claude/skills/pm-dispatch/ since that base, so the net diff is the same three-line change), and the 38 check-runs on the head. Face: a governed rules path, so the rules face at CONTRACT_REVIEW_TIER; the diff has no remainder for a TIER_DEFAULT ACCEPT (one file, +3/-3).
  • Accept set and public surface: none moves. The diff is one file under .claude/**; no package, no exports map, no schema, no changeset is touched. Right.
  • Added SKILL.md:272 (the trigger bullet). The four triggers are the card's four: a governed PR awaiting approval and merge, a decision card awaiting the maintainer's word, a release step, a block only the maintainer can clear; the push is sent in addition to chat and the GitHub record (另发), and the tool name is the card's. Judged against the rest of 升级与决策: no contradiction with :268 (card before popup; the assign ban forbids assignment as a nudge, and the push is a separate channel, so the card's restated assign ban is already carried two lines above and is correctly not duplicated), and no overlap with any other push rule in the instruction tree (the only other 推送 rule in SKILL.md is :268). Right.
  • Added SKILL.md:273 (the shape bullet): one line, at most 200 characters, action and number first, exactly once per item, no push for routine progress, a question just answered, or a maintainer who is present. Every clause is the card's. It composes with :270 and :271 rather than colliding: a maintainer with human input in the last ~30 minutes gets the in-session question and no push; an absent maintainer gets the push and no popup. Right.
  • The card's example line with a real PR number is not written: scripts/pm/check-skill-id-lint.mjs:90 sets ID_PATTERN to three-or-more digits after a hash and SKILL.md is in its corpus (:366), so the example cannot appear in this file; the rule states the format instead and the card lets the implementing seat tighten the wording. Right.
  • The card's clause that a tool reply of not-sent means present and no resend is not written: see ③.
  • Deleted bullet on the director's three duties (former :273): the rule is carried at references/lanes/director.md:29, :45 and :60 (the three duty headers), reached from the edited pointer at SKILL.md:56 and from the kept director summon bullet at SKILL.md:274; director.md:18 still names the three duties by that word. Not lost. Right.
  • Deleted bullet on the batch of at most five rows and the maintainer's click (former :274): carried at references/lanes/director.md:52 to :54 (the governed-draft batch, the at-most-five-row presentation of seat-ACCEPTed drafts, and approval and merge staying the maintainer's click, never delegated), and at AGENTS.md Prime Directive 14 ("ONE batch of at most five rows, and the click stays the maintainer's"); the never-approve and never-merge halves are also SKILL.md:26 and :27. Not lost. Right.
  • Pointer change at SKILL.md:56: the director row now sends the reader to director.md alone for the duties and the charter, which is correct once the section no longer carries them. Every other pointer into 升级与决策 (.claude/agents/os-dev.md:356, references/decision-analysis.md:3, references/dispatch-runbook.md:204, references/lanes/hotcrm.md:32, references/lanes/director.md:3) names the four-axis frame, which the diff does not touch. Right.
  • Placement: the card asked for the rule next to :268 to :270; the two bullets sit at :272 and :273, directly after the :268 to :271 card, popup and AskUserQuestion group and before the director bullets. Right. The card forbade a new gate; none is added. Right.
  • Mirror line: the card conditions a one-line mirror on the hourly wake routine's prompt template or references/execution-duties.md carrying the round-report duty. execution-duties.md carries no round-report duty (its only round-report mention, :54, is a triage-gap line); the routine prompt is not in the tree; the duty lives at references/seat-lifecycle.md:66 to :70, which the card does not name. No mirror is owed by the card's text, and none was written. Right. Observation: the round-report content at seat-lifecycle.md:68 to :70 does not list the push, but the card's Acceptance item 2 is a one-time record in the next round report, not a standing duty, so nothing is missing.
  • Line budget: 319 lines at base and 319 at head against the ceiling 319 at scripts/pm/check-skill-line-ratchet.mjs:382; the two added lines are paid by deleting content that is carried elsewhere, not by re-wrap, which is the only currency .claude/agents/os-dev.md:295 and references/lanes/skills.md:20 allow; no neighbouring bullet changed. The changed lines measure 117, 118 and 112 bytes under the 120-byte line norm, and the edited table row is far below the widest-row pin. Right. The gate verdicts are CI's, below.
  • The governed-prose region at SKILL.md:184 to :185 is untouched. Right.
  • Style: one rule spelled as two bullets, the second with an implicit subject, is the same shape the section already uses at :220 to :222 and :262 to :266; acceptable under the 120-byte cap.
  • Check-runs on the head: 38, all completed; 25 success, 13 skipped, 0 failure. Success includes Governed Surface Queue Guard, Lint · PM dispatch-gates (the ratchet, id-lint, governed-prose and frame-sync families), Lint & Repo Gates, Lint · repo & tooling gates, The card this PR closes must claim this branch, both single-writer and same-issue guards. The 13 skips are the expected-skip roster's shapes for a diff outside packages/** and scripts/**: Build Core, Build Docs, Console Pin Gate, Temporal Conformance, Dogfood Verify CLI, the Test Core and Dogfood shard templates, both Packed-tarball runs, both Check Changeset runs (the PR carries skip-changeset), and the second Auto Label and Check PR Size runs on the edited event. The aggregates Test Core and Dogfood Regression Gate are success. Every check is green or an expected skip.

② Semver level

  • The diff publishes nothing: no released package's shipped content is touched. skip-changeset on the PR is the correct declaration, and Check Changeset skipping under that label is the expected reading. Right.
  • Clause-②: no stands at line start in the PR body with no arm: no accept set widens, none narrows, so no (narrowing) arm, no breaking change and no ADR-0087 disposition is owed. The claim comment carries the same value. Right.
  • Served tier: a governed rules path decides the rules face, CONTRACT_REVIEW_TIER; this record is the one owed. Right.

③ Boundary flags

The dev report lists seven deviations and two out-of-scope findings; open_questions is empty. Each, answered:

  • Tier H or Tier S. The card and the claim comment call the PR Tier H; the GOVERNED_SURFACES row for .claude/** at scripts/pm/check-governed-merges.mjs:1178 carries GOVERNED_TIER_S for the whole tree, AGENTS.md Prime Directive 14 says the same ("Tier S: all of .claude/**"), SKILL.md:204 says the same, and the register header quotes the maintainer's 2026-09-18 ruling that .claude/skills/** lands through the queue on an in-seat CONTRACT_REVIEW_TIER PASS. The card's Tier H sentence is the filing seat's reading, not the maintainer's word: the two quoted sentences say nothing about landing. Answer: Tier S. With this PASS record on the current head and every check green or an expected skip, the owning seat lands the PR through the queue; no maintainer approval is owed and the card's "the maintainer reviews and merges it" does not bind. The drafted 维护者速读 in the body is harmless. Carrier: the owning seat, at landing.
  • The not-sent clause omitted. Answer: the once-per-item clause at :273 already forbids a resend whatever the tool returns, so the behaviour the card wanted survives; the dropped sentence asserts the return value of a tool that no file in the tree names (the only PushNotification in the instruction tree is the new :272), and writing unverified tool semantics into a rule is what the file's own third axis at :248 to :250 refuses. Acceptable omission. Residual flag: the tool name itself is the card's and is equally unverified in seat sessions; the PR body discloses this. The card's Acceptance item 2 (one push on the next item that moves into the maintainer's hands, recorded in the next round report) is the live test: if the tool is absent in the seat's session, that round report says so and the name becomes a card, never a silent no-op. Carrier: the owning seat.
  • The real-number example omitted. Answered in ①: the id-lint pattern refuses it in this file; the format is stated. Right.
  • No mirror line. Answered in ①: the card's condition is unmet; none owed. Right.
  • Release-step trigger. The compressed trigger 发版 at :272 sits beside references/seat-lifecycle.md:76 to :77 (the Version Packages PR is never nagged and stays out of the maintainer summary; the one exception is an important fix merged on main and waiting for a release). The card's own wording carries the same tension. Read as the card frames it, an item that has moved into the maintainer's hands, the two do not collide: a standing Version Packages PR is not such an item; a release step becomes one only when it is the maintainer's pending action (a pm:awaiting-maintainer item with its Maintainer-action: line, or seat-lifecycle.md:77's exception), and then exactly one push is owed. No contradiction inside 升级与决策; observation only, for the seat's reading. Carrier: none.
  • Commit trailers. The one commit on the PR carries a session line and a model-free co-author line, which is what .claude/agents/os-dev.md:285 to :286 ask for. No action.
  • Base movement. The merge-base is fb9c22a and origin/main has not touched the skill directory since; the net diff against main is the committed three-line change. Right.
  • Label read-back. The PR carries skip-changeset, documentation and size/xs, assignee os-warren, is draft, and has zero reviews. Right.
  • Out-of-scope finding on the retirement skill's table-row headroom: an observation with no carrier; agreed, not filed.
  • Acceptance item 2 is post-landing seat behaviour and is not judged by this record; the seat's next round report carries it.

Implemented-by: claude/issue-24481-push-notify-maintainer-hands
Reviewed-by: session_01FM29ZqLTrnPNXxijioZwMp

VERDICT: PASS


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skills(pm-dispatch): push-notify the maintainer when an item moves into the maintainer's hands (a Tier H PR to merge, a decision card, a release step)

2 participants