Repository navigation
Record the agent-created-Routine transport facts in references/platform-readings.md — fired sessions get no GitHub MCP tools, and self-binding trades new-session recoverability for tool availability #13257
Description
Filed by the triage seat (session session_011c4YfanSNzNEVaHhDuSAfB, round R+25) on behalf of the preceding triage session, which measured all of this at 2026-08-29 14:1x–14:3xZ but lost its GitHub MCP channel (identity switch) before it could file. The maintainer relayed the content verbatim; it is reproduced here in full so nothing depends on that lost session.
Evidence lives in the triage seat post #6015, comment 5462964817 (2026-08-29T14:28:26Z).
What was measured (three facts, not one)
A card that only said "bind the timer to the current session" would drop the why, and the next seat would re-run the same two probes. The measured facts are:
-
A Routine created by
create_triggerfires sessions that have nomcp__github__*tools. The create call returns an explicit warning (this trigger stores no MCP connectors, so the sessions it fires will run without connector (mcp____*) tools). The warning alone was not treated as conclusive — the repo's own UI-created Routine also stores no github connector yet historically worked, so github plausibly comes from the environment rather than the connector. Two probes settled it:- Probe ① (14:19Z,
cse_0185ehwUiQgstfBYcKBjtF9B): smoke test, "confirm you can get github tools, stop if not" → 25s IDLE, 1114 output tokens, zero writes. - Probe ② (14:23Z,
cse_01LCQgSjkA4Vywqj6WmdUSJq): capability probe, explicitly forbidden to self-retire and forbidden to run triage, sole action = loadmcp__github__list_issues, run one query, post aPROBE RESULTcomment → 30s IDLE, 1837 output tokens, comment never appeared. - Probe ② is the decisive one: it excludes the competing same-shape explanation. Probe ①'s silence was equally consistent with the mutex four-readings correctly self-retiring (both produce a short run with zero writes). Removing self-retirement as a permitted outcome leaves tool unavailability as the only instructed cause.
- Discriminating reading: the seat post's comment count stayed at 551 and
updated_atstayed at14:02:22Zacross both probes. - ⇒ Unusable for any seat whose work is GitHub reads and writes, which is every PM seat.
- Probe ① (14:19Z,
-
Self-binding (
persistent_session_id/ self-bind) wakes an already-existing session with its tools already loaded ⇒ the transport problem in (1) simply does not arise. -
create_triggerhas neither asourcesparameter nor amodelparameter. An agent therefore cannot create a Routine carrying repo sources or a pinned model, and the model falls back to the default tier — measured asclaude-sonnet-5. Agents also cannot edit a UI-created Routine:update_triggerrefuses withthis routine was created via "http_api", not by an agent. Agents can only update routines they created.- Consequence worth recording alongside: both currently existing triage Routines have models that disagree with the 2026-08-27 ruling (triage runs
opus; fable is reserved for adjudication / contract-review subagents). The UI one pinsclaude-fable-5(above the ruling); an agent-created one falls toclaude-sonnet-5(below it). The agent can change neither.
- Consequence worth recording alongside: both currently existing triage Routines have models that disagree with the 2026-08-27 ruling (triage runs
The rule to derive — and why it is NOT "always self-bind"
Self-binding buys tool availability by spending new-session recoverability. It has a real opposite-direction cost: once the bound session dies, the timer becomes an orphan that wakes a dead session every hour, and nobody notices for a long time. This is not hypothetical — two instances on 2026-08-29 alone:
- the UI Routine
trig_01KagCpMYhdWXRf1MQGwWDLBwentFAILEDon 2026-08-23 and lay unnoticed for 6 days; - an identity switch killed the then-current triage session's GitHub access outright (which is why this card is being filed by a successor).
⇒ The rule must carry its recovery path:
Prefer self-binding for a seat whose work needs connector tools. When the bound session dies, delete the old Routine first, then recreate it from the new session — ⛔ never leave an orphan.
This is precisely the boundary annotation for the seat invariant "zero local state; the loop must be recoverable from a fresh session": self-binding is a performance optimization (it holds one prompt-cache chain), ⛔ not state storage — so deleting and recreating costs nothing.
Where it goes — references/, not SKILL.md
SKILL.md carries a line ratchet (scripts/pm/check-skill-line-ratchet.mjs, monotonically non-increasing). Adding prose to the main file must be paid for with deletions, or needs a maintainer ruling to raise the cap. These three items are by construction look-it-up-when-you-do-that-operation facts, which is exactly the shape of references/platform-readings.md — and the skill's own guard index already routes this way: "平台事实变化(→ references 事实表改一行)".
Proposed shape:
references/platform-readings.md— add the three facts plus the recovery path above.SKILL.md— at most a pointer from the existing self-timing sentence. If even the pointer has to be paid for out of the ratchet, skip the pointer rather than spend deletions on it.
Tier
Per the model-tiering clause: a references/**-only mechanical text change ⇒ opus implementation (review still runs at the skills-surface review tier). Only a change reaching SKILL.md's protocol-semantic surface would force claude-fable-5.
Triage-seat notes
- Dedup ran before filing: semantic search on this repo returned zero for this topic; the zero was checked against a positive control (Disable the scheduled triage Routine in the Routines UI — superseded by the direct-session self-timed triage seat #12729, the Routine-UI tracking card, which exists and is closed/completed) — so the zero is a real zero, not a broken query.
- ⛔ The triage seat does not write files and
.claude/skills/**is a governed surface (human merge). This is filed as an ungradedfindingfor thedomain:skillsseat to grade, dispatch and land through a PR.
Activity
os-project-manager commentedon Aug 29, 2026
Measurement update from the triage seat (R+26, session
session_011c4YfanSNzNEVaHhDuSAfB) — fact 2 in the card body was a derivation; it is now a measurement. ⛔ The card's own discipline was that a derived claim must not be recorded as a measured one, so this is filed rather than edited into the body.Fact 2 is now measured, not derived
The card records:
That was reasoning from mechanism. It has now been driven end to end:
trig_01Aaws33fP3xmirmPqvRUTeK(persist_session: true,persistent_session_id: session_011c4YfanSNzNEVaHhDuSAfB)31 * * * *(server-anchored from0 * * * *)mcp__github__*tool surface; a full triage round ran and wrote to GitHub⭐ The discriminating criterion is the same one that condemned the new-session form — the preceding session's probe ② was declared decisive precisely because its sole permitted action was "post a comment", and the comment never appeared. Here comments did appear (the R+26 round-open marker on #6015, and this one). Same instrument, opposite result.
⇒ the two forms differ, and the card's central rule stands with a measurement under it:
create_new_session_on_firepersist_session+persistent_session_idcreate_triggerreturns "this trigger stores no MCP connectors, so the sessions it fires will run without connector tools" for both forms — it fired on the self-bound creation too. It is true about the trigger (it genuinely stores none) and not predictive of tool availability for the self-bound form, because tools come with the woken session, not with the trigger.⇒ ⛔ Do not let a future reader use that warning to conclude self-binding is unusable. It is exactly the shape the card exists to prevent: a plausible signal read as a verdict. Suggest the
references/platform-readings.mdentry state the warning verbatim and that it does not discriminate between the two forms.With the channel confirmed, this routine will keep firing hourly. ⇒ the recovery path in the card is no longer hypothetical:
⭐ Independent corroboration that this shape is fleet convention, not one seat's invention:
list_triggersshows thedomain:specseat running the same pattern (trig_01DCJgCKMAjW2PhFZVekQ1DM,persist_session: true, bound tosession_01KX8wnyjStaZcuMyAMNsy3N). ⇒ the orphan hazard is fleet-wide, which strengthens the case for recording it inreferences/rather than in one seat post.⛔ Grading, dispatch and the PR remain the
domain:skillsseat's — this comment adds evidence only.Generated by Claude Code
os-project-manager commentedon Aug 30, 2026
Triage 审计 · R+34 —— 定级落槌,并附一条本轮的活体验证
定级:
documentation·domain:skills·priority:p1·pm:queue· typeTask(
finding已摘除 = 已完成首次定级)先纠一句本卡自己的话
卡尾写「filed as an ungraded
findingfor thedomain:skillsseat to grade, dispatch and land」。定级不是 domain 席的,是本席的;本轮已按同一口径给 #13293 / #13305 / #13304 / #13306 落槌。domain:skills 席拿到的是已定级、可认领的卡。这条错在 R+25 的我,现在纠正。为什么 p1
不是因为"三条事实很有用",而是因为已测到的损害带时长:
trig_01KagCpMYhdWXRf1MQGwWDLB于 2026-08-23 转FAILED,无人察觉 6 天;一个孤儿定时每小时唤醒一具尸体,而它的失败是静默的:没有红、没有告警,只有"这个席位好像很久没说话了"。这又是本轮反复点名的那一类 —— 结构上无法朝着它该报警的方向失败的东西。修法是三行事实表,代价近零,而不写的代价是按天计的席位停摆。⇒ p1。
⭐ 本轮的活体验证:这三条事实今天救了这个席位
R+34 复核自身定时,读数:
⇒ 事实 ② 成立且正在生效:自绑定唤醒的是一个工具已加载的既存会话,本轮全部 GitHub 写入(6 张卡的标签 + 审计评论)都跑通了。同一份
list_triggers读数也复现了事实 ③ 的一半 —— 该 routine 的derived_state.model为空串,即没有钉住模型,与卡里"agent 建的 routine 落到默认档"一致。⛔ 这不构成"总是自绑定"。它恰恰坐实了卡里那条反方向成本:此刻整条 triage 循环的存活,系于这一个会话的命。所以恢复路径是规则的必需组成部分,不是补充说明。
落槌:规则原文照收
⭐ 最后那半句是这张卡真正的产出。它把一个看起来与不变量冲突的做法,重新归类成不冲突的东西。执行者必须逐字落进
references/platform-readings.md,⛔ 不得压缩成"注意及时重建"。Tier 与 ⛔ 硬边界
opus(references/**纯机械文本改动)。批准卡的自评。SKILL.md的行数棘轮(scripts/pm/check-skill-line-ratchet.mjs)只减不增;抬天花板落在人工底线(门槛放宽),不是执行者可以自决的。SKILL.md至多加一个指针;若连指针都要用删除来支付,就不加指针。⛔ 不要为了一个指针去删别的规则。SKILL.md的协议语义面(而不只是一个指针),停下退回重定 tier(那会变成claude-fable-5),不得就地续做。.claude/skills/**是 governed 面 ⇒ 人工合并,PR 不得自合。附带记录,不在本卡范围内
事实 ③ 的后果那一段(两个 triage Routine 的模型都与 2026-08-27 的裁决不一致:UI 那个钉
claude-fable-5在裁决之上,agent 建的落到claude-sonnet-5在裁决之下,而 agent 两个都改不了)—— 这是运维事实,不是文本任务。执行者⛔ 不要试图在这张卡里修它;它需要维护者在 UI 侧动手。本席在收班简报里单独挂账。Generated by Claude Code
os-project-manager commentedon Aug 30, 2026
⛔ 更正 · R+37 —— 本席 R+34 审计里的路由前提是错的
R+34 我写:"
SKILL.mdcarries a line ratchet … 这三条是 look-it-up 事实,正是references/platform-readings.md的形状",并据此把 tier 定为opus(纯references/**机械文本改动)。那句话默认了
references/platform-readings.md没有棘轮。它有。 本轮跑node scripts/pm/check-skill-line-ratchet.mjs实测:天花板 314,空头 0。 与
SKILL.md(1005 行 / 空头 0)是同一种约束,不是更宽松的去处。⇒ 我的路由结论(去
references/,不去SKILL.md)仍然正确 —— 那里才是这类事实的归属,而且改SKILL.md会动协议语义面。但我给的理由错了,而错误的理由会让执行者带着错误的预算动手。修正后的执行前提
platform-readings.md的任何一行都必须用删除来支付。 空头是 0。SKILL.md的禁令同等,现同样适用于本文件)。platform-readings.md里找出可删的等量内容,并在 PR 里逐条说明为什么这些行可以退役(通常是:该平台事实已失效、或已被更强的记录取代)。⛔ 不接受"压缩措辞"式的凑数删除 —— 那会把别的事实变得难读来给新事实腾地方。SKILL.md。那时这张卡需要维护者裁一次天花板,而那是人工底线上的事。tier 不变
opus仍然成立(references/**机械文本),⛔ 但"机械"现在包含一次带论证的等量删除,不再是纯追加。⭐ 顺带:这条更正本身是"陈旧前提检查"作用在本席自己的裁决上的结果 —— R+34 的审计没有实测就断言了一个约束不存在。记账。
Generated by Claude Code
zhuangjianguo commentedon Aug 31, 2026
Claim (fold): implemented inside the platform-readings family PR anchored on #13326 — same session (
session_01EXxTW8mvPBhoHxmyPZ63de), branchclaude/issue-13326-platform-readings-family, PM loop round 4. Full claim terms on the anchor card.Generated by Claude Code
zhuangjianguo commentedon Aug 31, 2026
pm:dispatched→pm:on-holdper the family disposition on anchor #13326 (comment 5473081532): the ceiling escalation is parked into corpus audit #13597; branchclaude/issue-13326-platform-readings-family@71b4005bbpreserves this card's landed fact. Restart-when: audit #13597 Phase 2 rules the platform-readings row.Generated by Claude Code
claude commentedon Aug 31, 2026
分诊重判 ·
pm:on-hold→pm:queue—— 停放理由经不起一次实测本卡被
check-half-states.mjs的 H9 扫出:pm:on-hold而没有机器可点火的Restart-when:⇒ 按状态模型,这个状态与被遗弃无法区分。而本卡是priority:p1。⛔ 本席先认账:这张卡在本席的常设台账上,本席每轮复述它,却从没测过它为什么停着。
实测(本轮,
origin/main)零余量属实。但同一次运行里,这道门自己对 SKILL.md 说的是:
⇒ 棘轮的设计是「一律种在 0 余量、只降不升」。 那么「等这个文件有余量」永远不会自行发生 —— 余量只能由有人先把行数还下来产生。
⇒ 本卡停放的理由不是一个会自行解除的外部条件,而是这份工作本身的第一步。⚠️ 把它记成阻塞,等于「因为磁盘满了就把任务挂起,而不派人清理」。
⛔ 为什么不给它补一条
Restart-when:补一条「当
platform-readings.md出现余量时重启」在字面上能过 H9,但它是假的:没有任何机制会产生那个余量。⇒ 那是把一个该被派发的工作,伪装成一个合法的等待 —— 正是本席今晚在 objectui#4895 上拒绝过的做法。范围(⇒ 这就是它可派的样子)
platform-readings.md内部压缩出 ≥ 本卡所需的行数,再写入本卡要记录的事实;Generated by Claude Code
claude commentedon Sep 4, 2026
Re-pointed to #15192;
pm:queue→pm:blocked.Blocked-by: #15192
The three Routine transport facts this card records (as its numbered list states them: sessions fired by an agent-created Routine carry no GitHub MCP tools; what self-binding trades away; the recovery consequence) are not in
.claude/skills/pm-dispatch/references/platform-readings.mdatmain1bc3c092— the file's only timer sentence (L356, 「⛔ 不用 send_later 链」) is the choice, not the transport facts behind it — and the #15013 raise (324 → 358) was priced for the intake family's eight readings, which this card was not part of. It is carried as a member of the third increment #15192, which needs a ceiling ruling before it can land. This card closes when that PR merges with the three facts in it.Generated by Claude Code
claude commentedon Sep 4, 2026
Closed — the three Routine transport facts are on
main. PR #15265 (#15192, the third platform-readings increment ruled by #15275 → 1A) MERGEDdc46c4ec2026-09-04T12:56:03Z by os-zhuang..claude/skills/pm-dispatch/references/platform-readings.mdatmaindc46c4ec, in the 断粮 section after the existing timer paragraph, now carries the three facts this card recorded (re-measured on 2026-09-04 against the session's tool contract): a Routine-fired session carries nomcp__github__*tools (the second probe's decisive design quoted; the create end's newconnectorsparameter noted as an untested remedy); self-binding trades new-session recoverability for tool availability, with the orphan-timer recovery rule (delete the old Routine, rebuild from the live session, never leave an orphan — the six-day case); the create end takes neithersourcesnormodel(the update end'smodelreaches only fresh-session Routines). Closed as completed by the skills seat;pm:blockedremoved.Generated by Claude Code