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_trigger fires sessions that have no mcp__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 = load mcp__github__list_issues, run one query, post a PROBE RESULT comment → 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_at stayed at 14:02:22Z across both probes.
- ⇒ Unusable for any seat whose work is GitHub reads and writes, which is every PM seat.
-
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_trigger has neither a sources parameter nor a model parameter. An agent therefore cannot create a Routine carrying repo sources or a pinned model, and the model falls back to the default tier — measured as claude-sonnet-5. Agents also cannot edit a UI-created Routine: update_trigger refuses with this 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 pins claude-fable-5 (above the ruling); an agent-created one falls to claude-sonnet-5 (below it). The agent can change neither.
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_01KagCpMYhdWXRf1MQGwWDLB went FAILED on 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
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:cse_0185ehwUiQgstfBYcKBjtF9B): smoke test, "confirm you can get github tools, stop if not" → 25s IDLE, 1114 output tokens, zero writes.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.updated_atstayed at14:02:22Zacross both probes.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.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.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:
trig_01KagCpMYhdWXRf1MQGwWDLBwentFAILEDon 2026-08-23 and lay unnoticed for 6 days;⇒ The rule must carry its recovery path:
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/, notSKILL.mdSKILL.mdcarries 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 ofreferences/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 reachingSKILL.md's protocol-semantic surface would forceclaude-fable-5.Triage-seat notes
.claude/skills/**is a governed surface (human merge). This is filed as an ungradedfindingfor thedomain:skillsseat to grade, dispatch and land through a PR.