docs(pm-skills): prescribe the landing-call curl spelling the allow rules match - #19045
Conversation
…ules match The ready and auto-merge rows in pm-dispatch `references/rest-channel.md` named the endpoint but never the invocation, so a seat typed its habitual shape. A Claude Code `Bash(...)` allow rule matches the literal PREFIX up to its first glob, so the command has to begin with the verb and the bare, unquoted url, with every `-H` / `-d` flag after it. Both rows now carry that command, and the `写侧` section heading carries the reason in one clause. Line-neutral: 82 lines before and after, at the file's ceiling of 82; every changed line measured at or under the 120-byte cap with no exemption used. Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Landing record — every pre-check met, blocked at the channel (skills seat, Every check on Generated by Claude Code |
|
Landing record — landed on the seat's record through the CCR route (skills seat, Channel: the two allow rules of PR #19047 ( Acts: Generated by Claude Code |
Fixes #19025
Clause-②: no — one references-layer file, three lines, line-neutral. No package, export, schema
or generated artifact moves, and nothing published changes.
The finding, and what this PR owes
A Claude Code
Bash(...)permission rule is a literal PREFIX match up to its first glob. Thelanding-call allow rules the maintainer is committing read
so the operative literal prefix is everything before the first glob —
curl -sS -X POST(orPUT)followed by the bare, unquoted url up to
/pulls/. A command that puts a-Hflag before the url,or quotes the url, matches nothing and falls to the session classifier. The two rows named the
endpoint but never the invocation, so nothing in the corpus prescribed the flag order.
Measured on
origin/mainatdbd474431before the clause was written.claude/settings.json: 47 allow entries, of which 21 areBash(curl ...)rules, and all 21match verb-then-bare-url (
Bash(curl -sS -X VERB https://api.github.com/...with the globs after).Zero exceptions. The dispatch calls all 47 curl rules; measured, 47 is the total allow count and
21 of them are curl rules — the shape claim itself holds for every one of the 21.
ccr/landing rules are not yet in.claude/settings.json(grep -n 'ccr/'→ no hit):they are in flight on the maintainer's side. This PR prescribes the spelling those rules match; it
adds no rule, widens none, and says nothing about what the classifier does.
references/landing-operations.mdis untouched (held by feat(pm): a PR over 5,000 changed lines lands only by a human merge — size predicate in check-governed-merges --test, the same reading in dispatch-gates, one rule line in SKILL.md and landing-operations #19033). Measured there:grep -n rest-channel→ zero hits, andgrep -rn 'ccr/'over.claude/hits onlyplatform-readings.md:48andrest-channel.md. So that file neither points atrest-channel.mdnor spells either landing call — the dispatch's mechanism assumption 2 is falsified, reported
rather than acted on.
Before / after — three lines, all in
.claude/skills/pm-dispatch/references/rest-channel.mdReady row (
:48), 100 B → 120 B:Auto-merge row (
:52), 109 B → 120 B:Section heading (
:34), 32 B → 120 B — it carries the reason in one clause, and it governs both rowsplus the other 19 write rows of the same section:
No other line changed. Every existing fact of both rows is still on its own row: the
✓, thedraft-to-ready and auto-merge-mount meanings, the reverse
.../ccr/convert_to_draft, the{"merge_method":"SQUASH"}body and theDELETEunmount. Both rows stay grep-able byccr/ready_for_review(1 hit) andccr/auto_merge(2 hits), which is how SKILL.md andplatform-readings.mdreach them.Line and byte budget (the ceiling is 82 and the file was at 82)
LC_ALL=C awk '{print length($0)}'and cross-checkedthrough the gate's own
classifyLine::34120,:48120,:52120. The cap is 120 B, the file'sown pre-existing maximum (
:3is 120), and no line uses a length exemption:scanLineLengthsreportsoffenders: []withexempt entries: 0.✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/rest-channel.md is 82 lines (ceiling 82; headroom 0).The dispatch's mechanism assumption 1, measured and falsified
A single ≤120 B line cannot carry the verb, the bare url,
-H "Content-Type: application/json",-d '{}'and a reason clause: the command alone is 95 B with the file's...url abbreviation and128 B with the url written out, before any prose or the row's existing facts. Measured packings:
the ready row with
-Hincluded and its reverse-endpoint clause dropped is 119 B — it fits only byshedding an existing fact, and the auto-merge row with
-Hand itsSQUASHbody is 137 B, which thegate classifies
over(it re-wraps to 2 lines). The fallback in the dispatch (reason on the readyrow, a pointer on the auto-merge row) does not fit either — the rows are at 120 B with their own
facts. So the invocation shape stayed on the rows and the reason moved up one level, to the section
heading that governs them, at 120 B.
-H "Content-Type: application/json"is not repeated in the twocommands because the row four lines above the first one already carries it as a rule for every write
(
:44), and this file's own discipline is ⛔ 不在两处各存一份; the heading names-Hso the readerknows where it goes.
Reader test
A seat about to land a PR greps
ccr/ready_for_review, lands on:48, and typescurl -sS -X POST https://api.github.com/repos/objectstack-ai/objectstack/pulls/19033/ccr/ready_for_review -H "Content-Type: application/json" -d '{}'— verb first, bare url next (the
...in the row is this file's abbreviation forhttps://api.github.com/repos/{o}/{r}, established at:7and used by 21 of the file’s rows), header after.That command's first bytes are the allow rule's literal prefix, so it never reaches the classifier.
Reading the heading tells the seat why the order is not a style choice.
Gates
Derived from this worktree with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(the tool takes its own change set from the merge base — 1 path). 17 families derived, 17 run, all
exit 0, exit codes captured redirect-then-
$?; reconciliation:✓ dispatch-gates --ran: 17 derived famil(ies) accounted for — 17 run, 0 NOT-MEASURED.Named in the dispatch and green here:
check:pm-skill-ratchet,check:pm-skill-id-lint,check:nul-bytes,check:skill-frame-sync,check:doc-authoring,check:pm-governed-merges.check:doc-formula-expressionsansweredexit 3(PREREQUISITE NOT MET — nothing measured) until@objectstack/formulaand@objectstack/lintwere built underscripts/pm/os-verify-lock.sh; it isexit 0after the build.check:pm-settings-deny-rosterwas run beyond the derivation because itsroster lives under
.claude/, the directory this diff is in —exit 0, 17 declared content-writetools = 17 enforced deny entries.
check:pm-dispatch-gatesexceeds the foreground cap and wasdetached; its verdict is reported in the dev report rather than guessed here.
Repo-wide
pnpm lintand the rest of the farm are CI's run, not this PR's local scope.维护者速读(草稿)
改了什么 —— PM 技能的
references/rest-channel.md里,「转 ready」和「挂 auto-merge」两行原来只写了 endpoint,现在直接写出席位该敲的那条
curl命令;该节的标题多了一句话,说明为什么命令必须以「动词 + 裸 url」开头(允许规则按首个 glob 前的字面前缀匹配),
-H/-d一律后置。为什么改 —— 维护者正在提交的四条落地允许规则是字面前缀匹配。席位按习惯写法(先
-H、url 加引号)敲出的命令一条规则都不匹配,会落到会话分类器,于是「七个绿 PR 等着人来点」的症状在规则齐备后照样复现。
规则文本不动,本 PR 只补事实层的拼写。
风险与代价(含回滚) —— 风险极低:改的是三行说明文字,不碰任何代码、生成物或发布内容;两行仍可被
ccr/ready_for_review、ccr/auto_mergegrep 到(SKILL.md 与platform-readings.md靠这两个 token指过来)。代价是两行与标题都顶到 120 字节上限,下次再往这三行加字就得先折行或搬走一个事实。回滚 =
revert 这一个提交,无迁移、无后续动作。
席位意见 ——
你要做的 —— 无需动作;这是事实层(
references/),按席内契约档复核后进队列。若你更希望「为什么」那句话落在两行自己身上而不是节标题上,请说一声:那需要把 82 行的天花板抬到 83,而抬天花板要你的裁决。
Out of scope, noted, not filed
landing-operations.mdpoints nowhere andspells no
ccr/call). Not filed as a card: the file is held by open PR feat(pm): a PR over 5,000 changed lines lands only by a human merge — size predicate in check-governed-merges --test, the same reading in dispatch-gates, one rule line in SKILL.md and landing-operations #19033, whose author is thenext one to touch those rows.
.claude/settings.jsoncarries noBash(curl -sS -X POST https://api.github.com/repos/objectstack-ai/objectstack/pulls *)rule, so opening this PR through the REST proxy still reaches the classifier. Observation only —
the allow-rule text is the maintainer's.
Generated by Claude Code