Repository navigation
skills(pm-dispatch): judge responsibility before dispatch, and stop a PR whose security review keeps reopening #21929
Description
Activity
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsPath: fleet decision — the dispatch loop spends dev effort where it lands value | 缺项 | none
Triage: first grade —
tooling·priority:p2·domain:skills·pm:queue. Three rules forpm-dispatch, on the maintainer's orderTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-06T01:56Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
.claude/skills/pm-dispatch/(the dispatch and review references) ⇒domain:skills; rationale: it changes the instruction set every dispatching seat reads, which is the named surface that admits thistoolingcard to the queue.- Why p2: the measured cost was security(datasource): credential-shaped values in some datasource configurations are stored and served without the platform's secret handling — detail withheld pending maintainer #21840 / PR fix(spec)!: credential-shaped datasource config values are refused at write and redacted on every read door for drivers with no shipped contract #21877 (about 4,000 lines and four review rounds, closed unmerged), and the maintainer asked for it in so many words. It is a process rule, so it is not p1.
- Triage's own share. This amends my
5990389094on security(datasource): credential-shaped values in some datasource configurations are stored and served without the platform's secret handling — detail withheld pending maintainer #21840: I graded itsecurity· p2 and routed it for a code fix without asking whose risk it was. This card's rule 1 binds triage at first grade too. The PR should state that intriage-duties.mdas well, and not only in the dispatch references, so the question is asked before a card ever reachespm:queue. - Keep the rules short and checkable. Each one should be a named line a seat cites in its claim, not prose a seat paraphrases. ⛔ No new CI gate: this is guidance for seats, and the circuit breaker is the seat's own stop, not a workflow.
Generated by Claude Code
- addedpriority:p2Medium: important, M3Medium: important, M3and removed
on Oct 6, 2026 objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_0181E4ZeZmWyknawnauxD2CE
Account:os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)
Branch:claude/issue-21929-judge-responsibility-before-dispatch
Worktree:objectstack-issue-21929
Domain:domain:skills
Seat:domain:skills#2
File surface:.claude/skills/pm-dispatch/SKILL.md(the 〈升级与决策〉 escalation-criteria line and the claim template in 〈模板与表〉),.claude/skills/pm-dispatch/references/execution-duties.md(〈候选与批次〉 / 〈派发〉 / 〈复核〉 — the REWORK-cap line),.claude/skills/pm-dispatch/references/dispatch-runbook.md(〈派发词构造细则〉),.claude/skills/pm-dispatch/references/seat-lifecycle.md(the 〈轮次报告与节奏〉 report line),.claude/skills/pm-dispatch/references/triage-duties.md(the first-grade question),.claude/skills/pm-dispatch/references/filing-gate.md(〈定级判据〉, reach) — region-level; every file is at its ratchet ceiling (headroom 0 atorigin/mainaa09db58c9), each added line paid in place. ⛔.claude/agents/os-dev.md,skills/**,scripts/**,.github/**untouched; stop on breach; explain in the report
Container & model:M,mode:subagent,model: CONTRACT_REVIEW_TIER—dispatch-gates --tier --repo objectstack-ai/objectstack .claude/skills/pm-dispatch/SKILL.md …prints "Model tier — MANDATORY … (derived from the file surface, not recalled)" with the path line ".claude/skills/pm-dispatch/SKILL.md ⇢ '.claude/skills/pm-dispatch/SKILL.md' — clause ① of the model-tiering ruling (narrowed to protocol semantics, 2026-08-20)"; no downgrade exit taken: the card rewrites protocol semantics across six files, not a one-line mechanical edit
Clause-②: no
Thread-read: 6007745609
Serial constraints cleared: none — 4 open PRs at the reading — #21994 · #21991 · #21988 · #21974 — file lists read through REST, none on.claude/**,scripts/pm/**,package.json,.github/workflows/lint.ymlordocs/audits/**;git ls-remoteshows noclaude/issue-21929-*branch; the last touches of the surface onorigin/mainared13df0c6ande27a7c0c(2026-10-05), not same-day; seat 1's hot-file table (#7623 r139) names onlydispatch-gates.mjsFROZEN andcheck-widening-tells.mjs, and its in-flight #21892 is onscripts/pm/**; the sibling claim this round (#21959) touchesreferences/instrument-discipline.mdline 7 only, a file this card does not name; verify lock state: lock is free queue: empty — arrival depth 1 (this dev), belowLOCK_DEPTH_HOLD; shared checkout atorigin/mainaa09db58c9. Readings taken at 2026-10-06T14:09Z.objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 21929, "status": "done", "branch": "claude/issue-21929-judge-responsibility-before-dispatch", "pr": "https://github.com/objectstack-ai/objectstack/pull/21999", "session": "session_0181E4ZeZmWyknawnauxD2CE", "premise_still_valid": true, "summary": "Four rules landed in .claude/skills/pm-dispatch/ (5 files, 8 lines added or rewritten, 8 deleted, every file at its ceiling before and after): the claim template gains a Responsibility: field carrying the three questions (whose code / platform path / who reaches it, used today) and binds the dispatch prompt's ruling section to repeat them; the escalation enumeration in SKILL.md 升级与决策 gains the document-not-defend exit (rule 1 verdict) and the no-heuristic-security-boundary exit (rule 2); the ESCALATE verdict line in execution-duties 复核 now fires on any of three breaker conditions (security review failed 2 rounds in a row / diff past 2x first reviewed size / previous round's fix introduced a new HIGH) with PR paused and no next round until the maintainer answers; seat-lifecycle's round report lists breaker hits per PR; triage asks the three questions at first touch; filing-gate caps a highest-privilege-only, no-current-user finding at p3 regardless of the security label. Premise verified at base 6befe19c: zero hits for the rule vocabulary across the skill with a live control word. Draft PR 21999, Tier S (.claude/** only), awaiting the skills seat's contract-tier review; head 8cdefa6c.", "tests": "No package touched, so no build/test/typecheck owed. Gates derived in the worktree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 8cdefa6c: 21 commands (identical to the dispatch list); all 21 run on head 8cdefa6c with exit captured before any pipe; --ran reconciliation: '21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of them is 3)'. Evidence: check:pm-skill-ratchet 'SKILL.md is 319 lines (ceiling 319; headroom 0)', 'execution-duties.md is 183 lines (ceiling 183; headroom 0)', 'seat-lifecycle.md is 96 lines (ceiling 96; headroom 0)', 'triage-duties.md is 120 lines (ceiling 120; headroom 0)', 'filing-gate.md is 58 lines (ceiling 58; headroom 0)', SKILL.md widest table row pin 342 unchanged; check:pm-skill-id-lint '34 file(s) clean'; check:skill-frame-sync 'the one declared copy of the decision frame is internally coherent'; frame block md5 abff5f852c8fd09b79ec0623439aa4f0 before and after; check:pm-governed-prose '2 instruction surface(s) name all 6 registered governed surfaces'; check:nul-bytes 'no raw ASCII control bytes'; check:doc-authoring '0 pinned site(s)'; check:comment-mask-corpus '8303 files, 0 disagree'. First attempt of pnpm --filter @objectstack/lint run check:doc-formula-expressions exited 3 (PREREQUISITE NOT MET: formula and lint not built) — NOT a measurement; built both with turbo under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 133s, waited 0s) and re-ran: exit 0, '22 record-scoped formula example(s) across 461 files / 1384 TS blocks judged clean'. New/rewritten prose line widths (LC_ALL=C awk bytes): 120, 108, 117, 110, 114, 113, 112; the template field is inside a fence (exempt). No ablation applies (prose only).", "mcp_calls": "0 — no MCP GitHub tool was called; reads went through gh api GET (issue, comments, PR read-back, label existence); writes only through scripts/pm/ (fleet-write relay).", "api_writes": "3 relay dispatches, 4 REST write actions executed by the relay as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (PR 21999, body read back identical, 14901 bytes); (2) label-write.mjs → labels_add POST /repos/objectstack-ai/objectstack/issues/21999/labels (skip-changeset) + assign POST /repos/objectstack-ai/objectstack/issues/21999/assignees (os-steve), read back MATCHES; (3) comment → POST /repos/objectstack-ai/objectstack/issues/21929/comments (this report). Plus 2 git push (not REST): the empty branch probe and commit 8cdefa6c.", "gates": { "derived_at": "8cdefa6c", "derived": 21, "run": 21, "not_measured": 0, "unrun": 0, "all_exit_0": true, "rerun_after_prerequisite": "pnpm --filter @objectstack/lint run check:doc-formula-expressions (first exit 3 PREREQUISITE NOT MET → build under verify lock → exit 0)", "not_in_derived_set_but_relevant": "check:skill-frame-freshness — frame block byte-identical to origin/main (md5 abff5f852c8fd09b79ec0623439aa4f0)", "ci": "in_progress — not awaited, per contract" }, "line_budget": { "budget_rule_lines_max": 8, "spent": "8 (5 new: SKILL.md rule-1 verdict, SKILL.md rule-2 condition, SKILL.md Responsibility template field, execution-duties breaker conditions, filing-gate reach cap; 3 rewritten: execution-duties ESCALATE verdict, seat-lifecycle round-report line, triage-duties first-touch line)", "paid_by_deletions": "5 (SKILL.md reach restatement in 报告契约; SKILL.md 机械守卫索引 rows for git-history.mjs and the two guard hooks — all three survive in AGENTS.md / filing-gate.md / the kept 收口卡 line; execution-duties self-declared Clause-② minor restatement — survives in AGENTS.md Post-Task Checklist 3; filing-gate 判例 example — derivable from lines 12–13 and 20); survivors listed per line in the PR body", "files": { ".claude/skills/pm-dispatch/SKILL.md": "319 → 319 (ceiling 319)", ".claude/skills/pm-dispatch/references/execution-duties.md": "183 → 183 (ceiling 183)", ".claude/skills/pm-dispatch/references/dispatch-runbook.md": "241 → 241 (not edited)", ".claude/skills/pm-dispatch/references/seat-lifecycle.md": "96 → 96 (ceiling 96)", ".claude/skills/pm-dispatch/references/triage-duties.md": "120 → 120 (ceiling 120)", ".claude/skills/pm-dispatch/references/filing-gate.md": "58 → 58 (ceiling 58)" }, "ceilings_changed": false, "rewrap_used": false }, "files_changed": [ ".claude/skills/pm-dispatch/SKILL.md", ".claude/skills/pm-dispatch/references/execution-duties.md", ".claude/skills/pm-dispatch/references/filing-gate.md", ".claude/skills/pm-dispatch/references/seat-lifecycle.md", ".claude/skills/pm-dispatch/references/triage-duties.md" ], "deviations": [ "dispatch-runbook.md 〈派发词构造细则〉 was in the claimed file surface but is not edited: the Responsibility: template field's parenthetical already binds the dispatch prompt's ruling section to repeat the three answers, and a second line there (or a rewrite of execution-duties 候选与批次 line 13) would have cost a deletion for the same reader; reason in the PR body.", "PM mechanism hypothesis falsified by measurement: rule 2 cannot be appended to the 「只在至少一条成立时升级」 line (120 B) nor split into 「或修复需破坏性/难回滚动作」 (117 B); it lands as one 108 B condition line inside the same enumeration, between those two. Rule 3 likewise: the REWORK line is 118 B, so the breaker rides the rewritten ESCALATE verdict line plus one conditions line in 复核; no new section.", "'at most low' is spelled 至多 p3 (the repo's lowest grade, the one triage-duties already gives a reach-less finding); 'third-party or user-authored code' is spelled 他人代码 to fit 120 bytes.", "origin/main advanced aa09db58 → 6befe19c between dispatch and worktree creation; the branch is based on 6befe19c (one commit, fix(metadata-protocol), touching none of the surface).", "The harness attribution reminder names a model in its Co-Authored-By trailer; the commit carries the AGENTS.md model-free pair instead (Claude-Session URL + Co-authored-by: Claude). Reported, not a history rewrite." ], "open_questions": [], "out_of_scope_findings": [ "carrier: none — noted, not filed · references/lanes/hotcrm.md 30 and references/lanes/engine.md 32 carry lane-local 'ask where the producer is' lines for declared≠enforced cards; the new first-touch three-question line generalises them; no conflict, lane files outside this card's surface.", "carrier: none — noted, not filed · 安全/权限边界 was already on the auto-adjudication human floor (triage-duties 95–96, SKILL.md 262) but the escalation enumeration had no security-boundary trigger before this PR; rule 2 is that trigger, narrowed to fixes that decide the boundary by guessing. Observation only." ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 6, 2026 ContributorAuthorMore actionsACCEPT — PR #21999 (
8cdefa6c), Tier S governed text; the contract-review record (PASS) is on the PR thread ·session_0181E4ZeZmWyknawnauxD2CE(domain:skills#2) · 2026-10-06T14:51ZChecklist, read on GitHub: draft, base
main, first lineFixes #21929(the merge should close this card),Clause-②: noat body line 2, assigneeos-steve, labelsskip-changeset·documentation·size/s; files = 5 under.claude/skills/pm-dispatch/, +8 / −8 against merge-base6befe19c, nocontent/docs/releases/, no unrelated file; no package touched ⇒ no changeset owed; 「维护者速读(草稿)」 present; no model id in the body or the commit trailers. Report comment 6018766887 on this card (first lineos-dev-report, 8389 bytes).mcp_calls0;api_writes3 relay dispatches (pr_create, labels + assignee, report) — no write tool, no PATCH of the PR body.Spot-checks: every added line is at most 120 bytes (one exactly 120); no
#NNNappears in the diff; the five deletions each have a verified surviving home (listed in the review ①); the frame block md5 is unchanged; the newResponsibility:claim key is inert to theClaim:/Thread-read:readers incheck-half-states.mjs. Check-runs on the head at this reading: 30 completed (success / expected skip), 3 in progress (Lint & Repo Gates,Type Check · consumer gates,Type Check · debt ledger); the enqueue waits for them, thencheck-expected-skips --pr 21999exit 0 andcheck-governed-merges --pr 21999reading Tier S.Deviations: five, all accepted (review ③). Acceptance notes: 2 items with
carrier: none— Acceptance notes, not filed. Rule 4 (reach caps a highest-privilege-only, no-current-user finding at p3) is the one line that generalises past the verbatim #21921 rulings; it is the card's rule as filed and graded, and the 速读 draft in the PR body is the maintainer's veto window — named in the round report.Landing: Tier S ⇒ this seat lands it through the queue once the three checks complete green (
pr_ready+automerge_enablethrough the relay). Sibling #21992 edits the same two files in other regions and has been told which lines this PR touches.- added 2 commits that reference this issue
on Oct 7, 2026
Requested by the maintainer in Claude Code session
session_018zT8d8NpiQ1ExhuNd5TxY6, 2026-10-06, verbatim: 「以后怎么避免在这类开发上耗资源,创建一张skills卡」.What happened
#21840 (P2, readable only by platform administrators, and affecting only plugin drivers, of which the repository has none) was dispatched as a security fix. PR #21877 tried to decide, from key names and value shapes, which values in a plugin driver's
configare credentials.configis its author's responsibility and that the platform does not guess. security(datasource): credential-shaped values in some datasource configurations are stored and served without the platform's secret handling — detail withheld pending maintainer #21840 was closed as not planned, fix(spec)!: credential-shaped datasource config values are refused at write and redacted on every read door for drivers with no shipped contract #21877 was closed unmerged, and one docs paragraph landed instead (docs(drivers): a plugin driver's config is its author's to keep free of credentials #21927).The cost came before any code was written: nobody asked whose problem it was, and nothing stopped the loop once it started.
Rules to add to
.claude/skills/pm-dispatch/Responsibility check before dispatch. Before dispatching a defect, the seat answers three questions in the claim or the dispatch:
When the risk sits in third-party or user-authored code, a supported path exists, and only the highest privilege reaches it, the default is document, not defend. The seat proposes a docs change or a decision card, and does not dispatch a code fix.
No security boundary built on a heuristic. If the proposed fix decides security by guessing (key names, value shapes, pattern lists), the seat stops and opens a decision card that compares it with a declaration-based approach, before dispatch.
Circuit breaker on a PR. The seat pauses the PR and asks the maintainer, with a short summary and options, when any of these holds:
No further development round is dispatched until the maintainer answers.
Price by reach, not by class. A finding with no current user, reachable only by the highest privilege, is graded at most low and may be recorded without a fix. The "security" label alone does not raise its priority.
Done when
维护者速读
#21840 只影响仓库里不存在的插件驱动,而且只有平台管理员能看到,却被当成安全漏洞派了开发。#21877 靠猜字段名,复审 4 轮都没收住,代码长到 4000 行,最后作废,改成补一句文档。
要在派发规则里加四条:
Generated by Claude Code