Skip to content

docs(pm-dispatch): re-key platform-readings' GraphQL-only list now the ccr routes are counted - #18396

Merged
os-elon-musk merged 2 commits into
mainfrom
claude/issue-18361-platform-readings-graphql-only-list
Sep 16, 2026
Merged

os-elon-musk merged 2 commits into
mainfrom
claude/issue-18361-platform-readings-graphql-only-list

Conversation

@os-elon-musk

@os-elon-musk os-elon-musk commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Fixes #18361

references/platform-readings.md only, in place at 466 / 466 lines (ratchet ceiling, headroom 0). Four rows re-keyed by judgment; no row added, none removed, no re-wrap, every rewritten line under the gate's 120-byte cap.

Three rows landed in the first commit (b0c55121). The fourth arrived with the seat's review (comment 5694684277 on #18361), which widened this claim's file surface by one row: a fact table does not carry a row whose job is to say the row above it is false, so the row above is re-keyed in place instead — second commit a7026a35, no force-push, no rebase.

Rows are located by CONTENT, not by the card's line numbers: the card was filed against 1411cf2c and the file has landed twice since (b57671ed #18359 at 04:18Z, 05f1cdd6 #18363 at 06:40Z), so :134 / :143 / :57 have drifted.

Row 1 — the GraphQL-only membership row (line 134 on this branch)

Landing point: the row directly under 「GraphQL 池 5000/时,只留给没有 REST 对应物的几件。」

before (verbatim, 113 B):

- 那几件 = draft 翻转、auto-merge 挂载、语义 `/search/*`、Projects field_values、`issue transfer`。

after (verbatim, 118 B):

- 那几件 = `rest-channel.md`〈不可迁移〉那三件;draft 翻转与 auto-merge 挂载有 ccr 路、不在内。

Row 2 — the queue-repo landing row (line 142), widened into scope by the seat's review

Landing point: the row directly under 「红窗调度:守候只给上面那几件 GraphQL-only 的,⛔ 其余一切不为配额空等。」

before (verbatim, 107 B):

- 走队列的仓落地必经 auto-merge ⇒ 红窗里无退路;直合仓有,合并本身有 REST 端点。

after (verbatim, 118 B):

- 走队列的仓落地仍必经 auto-merge,红窗里照样走 ccr REST 挂载;直合仓合并本身有 REST 端点。

The row's premise — that arming is GraphQL-only — is the same one the card retires, so the row is retired with it. What survives is what is still true: a queue repo's landing still goes through auto-merge (the queue is not bypassed), the mount in a red window rides the ccr REST route, and the direct-merge half keeps its REST endpoint.

Row 3 — the red-window stand-down row (line 143)

Landing point: the row directly under row 2.

before (verbatim, 70 B):

- MCP 侧限流下,draft 翻转与 auto-merge 挂载整窗不可得。

after (verbatim, 89 B):

- 红窗里 draft 翻转与 auto-merge 挂载照常走 ccr REST,⛔ 不为它们守候。

The first commit ended this row with 「⇒ 上条无退路不成立」, a clause whose only job was to void the row above. The review rejected that shape — correctly: a reader of a fact table should not have to hold two rows in mind to get one fact. With row 2 re-keyed, the clause has nothing to do and is gone.

Row 4 — the echo row (line 57), carrying comment 5693336603's mechanism

Landing point: the row directly under 「squash 的 committer date 是入队时刻,快进不改 ⇒ 落地时刻读 merged_at/merged,不读 git log。」

before (verbatim, 114 B):

- 回显两向不可靠,空回显不等于未挂上 ⇒ ⛔ 不拿它当任何方向的证据、不为它空转。

after (verbatim, 115 B):

- 回显两向不可靠:全绿加 `clean` 即吞进队列不存记录 ⇒ 空回显是成功常态,⛔ 不空转。

The byte WAS there, so the note is carried here rather than left on the card: the mechanism (all checks green plus mergeable_state: clean is consumed straight into the queue and stores no record, so an empty echo is the normal echo of SUCCESS) replaces two clauses the row no longer has to spend bytes on. 空回显不等于未挂上 is subsumed by the stronger 空回显是成功常态, and ⛔ 不拿它当任何方向的证据 follows from 回显两向不可靠 in the same sentence. The note's third half — never re-arm on a NULL alone — is NOT restated: the file already carries it at 「⛔ 永不据它判没挂上而重挂 —— 重挂踢队重排。」, and a second copy is what this card exists to remove.

The card's question: mirror rest-channel's 「不可迁移 —— 只有这三件」, or point at it

Point at it. Three reasons, in descending authority:

  1. A maintainer ruling already assigns ownership. The 2026-09-01 batch (总监批 chore(ci)(deps): bump actions/upload-artifact from 4 to 6 #22, quoted in scripts/pm/check-skill-line-ratchet.mjs's ceiling comment for rest-channel.md) reads, verbatim and untranslated: 「C 同批:退役 L58 对红窗常设规则的复述 —— 内容归属裁定:红窗规则由 platform-readings.md 配额段独家持有,rest-channel.md 只留指路」. The split it draws is symmetric: red-window POLICY is this file's, per-operation CHANNEL MAPPING is rest-channel's. Which operations have no REST twin is channel mapping.
  2. This file already says so in its own voice, one row below the one being re-keyed: 「逐操作通道归属、写侧配方与队列路由三读法见 rest-channel.md,⛔ 不在本表复述。」 The row this PR re-keys was the one row in breach of its own neighbour.
  3. The drift is the evidence. rest-channel's list stayed correct across lock 1; the mirror here went stale and stood a seat down for two operations that had a route the whole time. A mirror re-opens exactly that channel. rest-channel's heading already carries the return pointer (「红窗守候规则住 platform-readings.md 配额段」), so after this PR each fact has exactly one home and each home points at the other.

What is NOT delegated is the JUDGMENT the card asked for: the two operations that left the list are named here, in the negative, because a seat that remembers the old list needs the deletion stated, not merely absent. The three that stay are not re-listed.

rest-channel.md is not touched by this PR. Its rows 46 and 50 are already correct.

Acceptance notes

  • Adjacent rows read and left standing because they stay TRUE under the re-key: 「红窗调度:守候只给上面那几件 GraphQL-only 的…」 (line 141) becomes automatically correct once line 134 points at the three; and 「被挡住的翻转是在等窗口,不是关于该 PR 的信号…」 (line 144) survives, because a flip can still be blocked by the session gate (GitHub access is not enabled for this session) or by REST core, so its prohibition still has a referent.
  • noted, not filed: 「走队列的仓落地仍必经 auto-merge」 still reads as if arming were the only landing path. It is, on this repo, under Prime Directive 14's governed-surface carve-out and the queue rules — but the row does not say which of those makes it so. 承接者: none; recorded here so the next author of this block knows it was read and judged, not missed.
  • Out-of-scope finding reported to the seat (class b, contract violation): the spec seat's 2026-09-16T06:19Z measurement (seat post [PM seat] domain:spec — 🟢 REOPENED by the maintainer (fix them all, THEN merge, THEN off) · 5 landed (+#18942 cleared main's OSV red) · #18889 at-tier PASS + enqueued · #18688 and #18638 UNPARKED — both rulings had already landed #6017, comment 5692971090) — no enqueued event on this repo's /issues/N/timeline, the queue ref answering BUILD rather than membership, and auto_merge cleared on enqueue — conflicts with rows 10–12 of this same file, which make the timeline event the decisive membership reading. Out of this card's scope, untouched here. Row 4's rewrite was written to be consistent with it (a consumed request stores no record), not against it.

Gates

Targeted set for a .claude/skills/** docs-only diff, re-derived from the actual change at the new head with node scripts/pm/dispatch-gates.mjs --commands (no paths) and reconciled with --ran: 16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN, the same 16 as the first round. Exit codes captured to a file before reading, never across a pipe. Ratchet at the new head: 466 lines, ceiling 466, headroom 0. Per-command results are in the report comments on #18361.

skip-changeset: nothing published moves — .claude/** is not in any package's files[], it is the fast track, not a measurement.

维护者速读(草稿)

改了什么 —— 只动 references/platform-readings.md 四行,行数 466 → 466。一是 GraphQL-only 清单那行:不再自己列五件,改成指向 rest-channel.md〈不可迁移〉的三件,并写明 draft 翻转与 auto-merge 挂载有 ccr 路、不在其内。二是「走队列的仓落地必经 auto-merge ⇒ 红窗里无退路」那行:改成落地仍必经 auto-merge、红窗里照样走 ccr REST 挂载,直合仓那半保留。三是红窗那行:两件在限流窗里照常走 ccr REST,别为它们守候。四是回显那行:补进「全绿加 clean 即被吞进队列、不存记录,所以空回显是成功的常态」这条机制。

为什么改 —— 锁 1 之后 ccr 路是这两件操作的唯一通道,而清单还把它们记作没有 REST 对应物。后果不是措辞问题:读到红窗那几行的席位会白等一个根本不用等的窗口。清单归属有 2026-09-01 的裁定在先(红窗规则归本表独家,通道归属归 rest-channel.md),所以这次是把重复的那份退役成指路,不是再抄一遍。第二行是席位复核时扩进来的:原先我只在下一行写「上条无退路不成立」,事实表不该有一行专门宣布上一行为假,现在把上一行本身改对了。

风险与代价(含回滚) —— 风险有两处。① 席位要判某个操作是不是 GraphQL-only 时,多读一个文件(rest-channel.md,82 行、零配额);换来的是清单只有一份、不会再各自漂移。② 这四行都在同一段里,措辞收紧后相邻行的语气略有重叠(红窗里走 ccr REST 这件事在两行都出现一次),是刻意的:一行讲落地路径,一行讲要不要守候。回滚代价极低:四行就地改写,两个提交都可 git revert,棘轮读数不变。

席位意见 ——

你要做的 —— 若同意「指路而不镜像」这一判断,按 references 档在席复核后落地即可;若更希望本表继续自列三件(以红窗里少读一个文件换一份可能再漂的副本),请在此说明,我改回列举形。


Generated by Claude Code

…e counted

The draft flip and the auto-merge mount both have live ccr REST routes
(rest-channel.md rows 46 and 50, and this file's own undraft row), so
neither belongs on the GraphQL-only list and neither is a reason to stand
a seat down in a rate-limit window. Point the membership row at
rest-channel.md's 不可迁移 section, which the 2026-09-01 content-ownership
ruling already makes the single holder of per-operation channel mapping,
and re-key the red-window row to say the two go through all window.

The same three lines fold in the measured mechanism behind an empty
auto_merge echo: all checks green plus mergeable_state clean is consumed
straight into the queue with no record stored, so NULL is the normal echo
of success.

466 / 466 lines, in place, each rewritten line under the 120-byte cap.

Claude-Session: https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt
Co-authored-by: Claude <noreply@anthropic.com>
…ring it false

A fact table does not carry a row whose job is to say the row above it is
false. The red-window landing row is retired by the same ccr fact this
branch lands, so it is re-keyed in place: a queue repo's landing still
goes through auto-merge, and in a red window that mount goes over the ccr
REST route; its direct-merge half stays. The row below drops its
「⇒ 上条无退路不成立」 tail and keeps the rest.

466 / 466 lines, in place, both rewritten rows at 118 and 89 bytes.

Claude-Session: https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt
Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a7026a359e35326d6c33ded1a4754e331c10b898

① Derived judgments

  • Accept set / public surface: none — references/platform-readings.md only (this skill's fact layer); no runtime code, no published package.
  • Diff read whole by this seat across both rounds (merge-base → head, +4 / −4, one file, 466 → 466): the GraphQL-only membership row now points at rest-channel.md's 〈不可迁移〉 three and names the draft flip and auto-merge mount as ccr-routed; the queue-repo landing row states that a queue repo's landing still goes through auto-merge and that the red window is served by the ccr REST mount (the direct-merge half kept); the red-window row keeps 「⛔ 不为它们守候」 and drops the 「上条无退路不成立」 tail (0 occurrences on the head; 「整窗不可得」 0); the echo row carries the consumed-into-the-queue mechanism (green + clean ⇒ no record stored ⇒ an empty echo is the normal echo of success) with 「⛔ 永不据它判没挂上而重挂」 left as the single home of the never-re-arm rule. Round-2 delta is exactly the two rows the REWORK named (+2 / −2).
  • Re-run by this seat on the head: check-skill-line-ratchet.mjs exit 0 — 466 lines, ceiling 466, headroom 0; the four rewritten rows 115 / 118 / 118 / 89 B; check-clause2-carriers.mjs --pair 18396 exit 0; path face GOVERNED, wholly under references/ (fact layer ⇒ in-seat landing).
  • The card's question answered POINT AT (not mirror) — adopted, with the 2026-09-01 content-ownership ruling the dev quotes from the ratchet script's ceiling comment as the authority.

② Semver level

skip-changeset — nothing published moves.

③ Boundary flags

  • Round 1's adjacent-row deviation: resolved by widening the surface to that row (REWORK 5694684277), now re-keyed in place.
  • The lint.yml wiring that landed on main during the round (Wire check-harness-current.mjs and check:pm-expected-skips self-tests into lint.yml #18388): the dev ran both newly wired self-tests on this branch instead of merging main (exit 0 / 0) — accepted; the queue rebuilds on the current base.
  • Out-of-scope class (b) relayed by the dev: platform-readings' opening queue-membership rows (the timeline event as the decisive reading) against the spec seat's 06:19Z measurement (/issues/N/timeline carries no enqueued row here; the queue ref answers BUILD; auto_merge clears on enqueue). The seat files it as this lane's card.

Implemented-by: claude/issue-18361-platform-readings-graphql-only-list
Reviewed-by: session_01Bz6hxDBqK62NP2W1LATvnt

VERDICT: PASS


Generated by Claude Code

@os-elon-musk
os-elon-musk marked this pull request as ready for review September 16, 2026 09:11
@os-elon-musk
os-elon-musk added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 4a2c88a Sep 16, 2026
35 checks passed
@os-elon-musk
os-elon-musk deleted the claude/issue-18361-platform-readings-graphql-only-list branch September 16, 2026 09:35
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
…bjectstack-ai#18405)

Fixes objectstack-ai#18362

One row of `.claude/skills/pm-dispatch/references/platform-readings.md`,
re-keyed in place. No other row is touched.

## The row, before and after

before — 119 bytes:

```
- `check:pm-dispatch-gates` 单机 430–450 秒贴调用方容器上限 ⇒ detach 加 `tail --pid`;超时非读数。
```

after — 113 bytes:

```
- `check:pm-dispatch-gates` 单机 430–450 秒贴容器上限 ⇒ detach 加 `tail --pid=$!`;超时非读数。
```

The pid's source is now IN the prescription, in the spelling a reader
copies: `tail --pid=$!`. The three parts the card protects are
byte-identical — `430–450 秒`, `detach`, `超时非读数`. The one word paid to
the byte cap is `调用方` in `贴调用方容器上限`; `容器上限` still names what the seconds
bump against. That trim is the route the dispatching seat proposed, and
it is what buys the `=$!`.

Located by content, never by line number (the card's own correction,
comment 5692424694): `grep -n 'tail --pid'` matched exactly one row on
`origin/main` at `9a566305e` before the edit and matches exactly one
after.

## Line budget — the whole edit had to fit an existing line

`pnpm check:pm-skill-ratchet` holds this file at **466 / 466 lines,
headroom 0**, and caps every line at **120 bytes**
(`scripts/pm/check-skill-line-ratchet.mjs`, section "Why 120 bytes"). So
the edit is an in-place re-key: **466 → 466 lines**, the row **119 → 113
bytes**, 7 bytes under the cap. Nothing was re-wrapped to buy room, and
no line was added.

## Acceptance item 2 (the starred half) is NOT written here — the
measurement, then the reason

The card's item 1 (name the pid source) is a hard requirement and is
landed. Item 2 (⭐ explain why `pgrep -f` self-matches) is starred, and
every spelling of it was measured against the 120-byte cap:

| candidate row | bytes | verdict |
|---|---|---|
| landed, item 1 only | 113 | fits |
| item 1 + `⛔ pgrep 自匹配`, qualifiers kept | 133 | 13 over |
| item 1 + `⛔ 不用 pgrep`, qualifiers kept | 130 | 10 over |
| item 1 + `⛔ pgrep 自匹配`, minus `单机` | 126 | 6 over |
| item 1 + `⛔ pgrep 自匹配`, minus `单机` and `容器` | 120 | fits, zero margin
|
| item 1 + terse `⛔ 非 pgrep`, minus `单机` | 120 | fits, zero margin |

So both items fit on one row only by deleting measured qualifiers out of
the half the card forbids disturbing (`单机` says the 430–450 seconds is a
single-box reading, `容器` says which limit it bumps against), and the two
that do fit sit exactly at the cap with no margin for the next author.
Against that, the starred half is already written down twice in this
repo, both times with more room than a 120-byte row has:

- `AGENTS.md:534` (Multi-agent discipline §8) — "⛔ One process table per
container: **kill only a PID you recorded, and wait only on one, never a
name** — `pgrep -f` matches the asking shell (`guard-process-kill.sh`)."
- `.claude/hooks/guard-process-kill.sh` header, lines 72–76 — the
measured mechanism itself, including the deadlock it produced on this
container.

And the re-derivation the card names as the natural wrong completion has
no occasion left: a reader who copies `tail --pid=$!` has the pid
already. Trading a measured qualifier for a duplicate of a rule two
other files carry is the trade this PR declines; the seat can overturn
it with one number from the table above.

## Verification

Gate families derived from the real change set, not from a hand-written
list — `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (1 path vs merge base `f04be62aa`), then
reconciled with `--ran`:

```
Run reconciliation — 16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED
  (a DERIVED zero — all 16 recorded an exit code and none of them is 3).
```

All 16 exited 0 on the merged head `7674f7ce7`: `check:pm-skill-ratchet`
· `check:pm-skill-id-lint` · `check:skill-frame-sync` ·
`check:required-contexts` · `check-governed-queue-guard.mjs --self-test`
· `check-closing-keyword-parity.mjs` (+ `--self-test`) ·
`check-comment-mask-corpus.mjs` · `@objectstack/lint
check:doc-formula-expressions` · `check:agent-test-spelling` ·
`check:doc-authoring` · `check:driver-memory-census` · `check:nul-bytes`
· `check:pm-governed-merges` · `check:refd-timer-probe` ·
`check:watch-hint-literal`.

The ratchet's own verdict line for this file:

```
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md
  is 466 lines (ceiling 466; headroom 0).
```

`check:doc-formula-expressions` exited **3 on its first run** —
`PREREQUISITE NOT MET`, `@objectstack/formula` and `@objectstack/lint`
not built — which is not a finding and not a measurement. Cleared by the
fix the gate itself prints (`turbo run build
--filter=@objectstack/formula --filter=@objectstack/lint`, run through
`scripts/pm/os-verify-lock.sh`), then re-run to exit 0.

Three gates run beyond the derived 16, each for a stated reason:

- `pnpm check:pm-settings-deny-roster` — exit 0. The derivation flags
its roster as living under `.claude/`, where one of my paths is, so its
silence is evidence in neither direction and it was read rather than
assumed.
- `node scripts/pm/check-governed-merges.mjs --test
.claude/skills/pm-dispatch/references/platform-readings.md` — exit **3,
GOVERNED**, as expected: `.claude/** ×1`. This PR stays draft; no seat
flips it ready, enqueues it or arms auto-merge.
- `node scripts/check-skills-token-ratchet.mjs` — exit 0. It ratchets
the published `skills/` catalog, which this diff does not touch; run to
prove that, not because it covers this file.

**Repo-wide lint is CI's, and the local narrowing is declared with its
three readings.** ① The population comes from eslint's own config, not a
guess: every `files:` glob in `eslint.config.mjs` is
`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` or a TypeScript subset of it —
markdown is in no configured population. ② Counted from `--format json`:
eslint over the one changed file returns `errorCount: 0` with `"File
ignored because no matching configuration was supplied."`, i.e. 0 linted
files in this diff. ③ Invariance: there is no `parserOptions.project`
and no typed `@typescript-eslint` rule anywhere in that config, so
nothing in this diff can move the verdict of a file it does not contain
— and this diff contains no JS or TS at all.

Not run and not owed: no workspace package is in the change set, so
there is no dependency closure to build and no package test or typecheck
to run. `@objectstack/formula` and `@objectstack/lint` were built only
as the named prerequisite above.

## Acceptance notes

- `.claude/agents/os-dev.md:342` also names `tail --pid` without a pid
source — noted, not filed, and deliberately not edited: it is one hop
from `AGENTS.md:534`, which bans the `pgrep -f` derivation by name, and
the card's item 4 keeps a sweep of other prescriptions out of this PR as
a separate card with its own evidence. Successor: whoever files that
sweep.
- Region-parallel on this file with PR objectstack-ai#18396 — that PR's three rows are
a different card's and are untouched here; objectstack-ai#18396 is not addressed by
this PR. `git merge origin/main` was run once before opening this PR;
`origin/main` at `f04be62aa` did not carry objectstack-ai#18396 yet, and the merge
touched no `.claude/` path.
- `skip-changeset`: the diff publishes nothing. `.claude/**` ships in no
package's `files[]` — it is repo-internal agent instruction text.

## 维护者速读(草稿)

**改了什么** —— `platform-readings.md` 里那条讲 `check:pm-dispatch-gates` 太慢要
detach 的读数,原来只说了「detach 加 `tail --pid`」,没说这个 pid 从哪来。现在它自己带上了可照抄的写法
`tail --pid=$!`。全文只动这一行,行数 466 → 466。

**为什么改** —— 处方缺了一半,而最自然的补法是错的:用 `pgrep -f 模式` 反推 pid 时,跑 pgrep 的那层 shell
自己的命令行里就带着那个模式,于是监视器等的是它自己,永远等不到。代价量过:一个 dev 在一张卡上踩了三次,每次都把一次干净跑完、exit
0、日志完整的测量,报成了挂死的后台任务。

**风险与代价(含回滚)** —— 风险极低:改的是给 agent 读的一行说明文字,不进任何产物、不发布、无
changeset。代价是一个词:`调用方容器上限` 压成 `容器上限`,为 `=$!` 腾出字节(该文件行数上限 466 已零余量,每行上限
120 字节)。卡面 ⭐ 的第二件(解释 `pgrep -f` 为什么自匹配)没写进这一行 —— 量过:要写下它,就得删掉 `单机` 或
`容器` 这些量过的限定词,而这条规则 `AGENTS.md:534` 与 `guard-process-kill.sh`
文件头已经各写了一遍。回滚 = revert 本 PR 的单行 diff,无后续依赖。

**席位意见** ——

**你要做的** —— 这是受管面(`.claude/**`),合并权不在任何 agent 席位手里。按 references 层的分级,它走
skills 席的 contract-tier 复核后由本席落地;若你想自己看一眼,只需看上面 before/after 那两行,和「要不要为
`pgrep` 那句话删掉 `单机`」这一个取舍。

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt)_

Co-authored-by: Claude <noreply@anthropic.com>
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

2 participants