Commit 7d70612
docs(pm-skills): prescribe the landing-call curl spelling the allow rules match (#19045)
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. The
landing-call allow rules the maintainer is committing read
```text
Bash(curl -sS -X POST https://api.github.com/repos/objectstack-ai/objectstack/pulls/*/ccr/ready_for_review *)
Bash(curl -sS -X PUT https://api.github.com/repos/objectstack-ai/objectstack/pulls/*/ccr/auto_merge *)
```
so the operative literal prefix is everything before the first glob —
`curl -sS -X POST` (or `PUT`)
followed by the bare, unquoted url up to `/pulls/`. A command that puts
a `-H` flag 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/main` at `dbd474431` before the clause was
written
- `.claude/settings.json`: **47 allow entries, of which 21 are
`Bash(curl ...)` rules**, and all 21
match 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.
- The two `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.md` is untouched (held by #19033).
Measured there:
`grep -n rest-channel` → **zero hits**, and `grep -rn 'ccr/'` over
`.claude/` hits only
`platform-readings.md:48` and `rest-channel.md`. So that file neither
points at `rest-channel.md`
nor 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.md`
Ready row (`:48`), 100 B → 120 B:
```text
- - ✓ draft 转 ready `POST .../pulls/{n}/ccr/ready_for_review`,反向 `.../ccr/convert_to_draft`。
+ - ✓ draft 转 ready `curl -sS -X POST .../pulls/{n}/ccr/ready_for_review -d '{}'`,反向 `.../ccr/convert_to_draft`。
```
Auto-merge row (`:52`), 109 B → 120 B:
```text
- - ✓ auto-merge 挂载 `PUT .../pulls/{n}/ccr/auto_merge` 带 `{"merge_method":"SQUASH"}`,`DELETE` 卸载。
+ - ✓ auto-merge 挂载 `curl -sS -X PUT .../pulls/{n}/ccr/auto_merge -d '{"merge_method":"SQUASH"}'`,`DELETE` 卸载。
```
Section heading (`:34`), 32 B → 120 B — it carries the reason in one
clause, and it governs both rows
plus the other 19 write rows of the same section:
```text
- ## 写侧 —— 全部可迁移
+ ## 写侧 —— 全部可迁移;允许规则按首个 glob 前的字面前缀匹配:verb 紧跟裸 url,`-H`/`-d` 后置
```
No other line changed. Every existing fact of both rows is still on its
own row: the `✓`, the
draft-to-ready and auto-merge-mount meanings, the reverse
`.../ccr/convert_to_draft`, the
`{"merge_method":"SQUASH"}` body and the `DELETE` unmount. Both rows
stay grep-able by
`ccr/ready_for_review` (1 hit) and `ccr/auto_merge` (2 hits), which is
how SKILL.md and
`platform-readings.md` reach them.
## Line and byte budget (the ceiling is 82 and the file was at 82)
- Line count: **82 before, 82 after** — line-neutral, nothing folded,
nothing paid, no ceiling touched.
- Bytes of every changed line, measured with `LC_ALL=C awk '{print
length($0)}'` and cross-checked
through the gate's own `classifyLine`: `:34` 120, `:48` 120, `:52` 120.
The cap is 120 B, the file's
own pre-existing maximum (`:3` is 120), and **no line uses a length
exemption**:
`scanLineLengths` reports `offenders: []` with `exempt entries: 0`.
- Ratchet verdict, verbatim:
`✓ 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 and
128 B with the url written out, before any prose or the row's existing
facts. Measured packings:
the ready row with `-H` included and its reverse-endpoint clause dropped
is 119 B — it fits only by
shedding an existing fact, and the auto-merge row with `-H` and its
`SQUASH` body is 137 B, which the
gate classifies `over` (it re-wraps to 2 lines). The fallback in the
dispatch (reason on the ready
row, 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 two
commands 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
`-H` so the reader
knows where it goes.
## Reader test
A seat about to land a PR greps `ccr/ready_for_review`, lands on `:48`,
and types
`curl -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 for
`https://api.github.com/repos/{o}/{r}`, established at `:7` and 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-expressions` answered `exit 3` (PREREQUISITE NOT MET
— nothing measured) until
`@objectstack/formula` and `@objectstack/lint` were built under
`scripts/pm/os-verify-lock.sh`; it is
`exit 0` after the build. `check:pm-settings-deny-roster` was run beyond
the derivation because its
roster lives under `.claude/`, the directory this diff is in — `exit 0`,
17 declared content-write
tools = 17 enforced deny entries. `check:pm-dispatch-gates` exceeds the
foreground cap and was
detached; its verdict is reported in the dev report rather than guessed
here.
Repo-wide `pnpm lint` and 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_merge` grep 到(SKILL.md 与
`platform-readings.md` 靠这两个 token
指过来)。代价是两行与标题都顶到 120 字节上限,下次再往这三行加字就得先折行或搬走一个事实。回滚 =
revert 这一个提交,无迁移、无后续动作。
**席位意见** ——
**你要做的** —— 无需动作;这是事实层(`references/`),按席内契约档复核后进队列。若你更希望「为什么」
那句话落在两行自己身上而不是节标题上,请说一声:那需要把 82 行的天花板抬到 83,而抬天花板要你的裁决。
## Out of scope, noted, not filed
- The dispatch's mechanism assumption 2 is falsified
(`landing-operations.md` points nowhere and
spells no `ccr/` call). Not filed as a card: the file is held by open PR
#19033, whose author is the
next one to touch those rows.
- `.claude/settings.json` carries no `Bash(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](https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 221dabb commit 7d70612
1 file changed
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
| 34 | + | |
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | | - | |
| 48 | + | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
| 52 | + | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
0 commit comments