Skip to content

skills(pm-dispatch): the patrol timer is armed ONCE at seating as a self-bound Routine and deleted at sign-off — a round-end re-arm skipped once idled a seat ~7 h #17728

Description

@claude

Filed by the skills seat (session session_01MCLBsUgfykL74aU716rzVK, GitHub os-sales) at 2026-09-12T00:47Z from the maintainer's question in this seat's chat (2026-09-12T00:3xZ), which quoted a stalled PM seat's own diagnosis. Provenance, verbatim and untranslated:

项目经理:为什么停下来 —— 直接的答案
因为我在上一轮结束时漏挂了唤醒定时器。 没有别的原因:不是等你、不是被阻塞、不是限流。座位协议要求「走之前重新挂唤醒」,前面每一轮我都挂了,最后那轮没挂。没有下一次 fire,循环就停在那儿了。
现在 00:17Z,我最后一次动作在昨天约 17:00Z —— 空转约 7 小时。
这种应该怎么解决

The shape

The protocol arms the next wake-up as a ONE-SHOT at the round's end (SKILL.md 〈入口与角色〉: 「自设定时器只定下一次唤醒」, 「定时器默认在轮末挂、延时 ≤55 分钟」) and separately makes the re-arm the first action of every patrol (〈收集〉 ①: 「定时器重挂是每次巡检的第一动作,先挂后查,链条对中断免疫」). A chain of one-shots has no memory: one skipped link is silence until a human notices. The chain is immune to an interrupted round only if the arm happened BEFORE the work — the two lines point in different directions, and the seat that stalled followed the first.

Measured cost: one seat idle ~7 h (last own output ~2026-09-11T17:00Z, noticed 2026-09-12T00:17Z) with its queue and its in-flight items untouched; nothing on the board said so, because a 🟢 title and a missing timer look identical from GitHub.

Direction (seat reading; veto window in the round report)

  1. At seating, the seat creates ONE self-bound recurring Routine (create_trigger with a cron, firing into the same session, initiation: own_followup) and records its id in the seat post's Notes; the fired text follows the timer-text discipline (re-read state first, key criteria only). The round-end send_later becomes an optional accelerator (≤55 min while anything is in flight), never the only wake-up.
  2. Sign-off checklist item 6 already says list_triggers + clean up every timer — the recurring Routine is deleted there; the dead-session case is already ruled in platform-readings.md 〈断粮〉: a bound session that dies orphans its Routine ⇒ delete and recreate from the new session.
  3. Cadence is unchanged: standby already patrols every 60–70 min, and a self-bound Routine keeps the session's prompt-cache chain (the readings table records self-binding as a performance optimisation, zero-cost to delete and recreate).
  4. ⛔ Not a mechanical patrol row: Routines are account-scoped and the patrol runner cannot read another account's, so the guard is the Routine itself, not a check.

Landing: SKILL.md 〈入口与角色〉 (the two timer lines fold into one stating the seating-time Routine + the optional round-end one-shot) and 〈收集〉 ① (the first-action re-arm becomes «confirm the Routine is enabled; re-arm the accelerator»), the matching core-rules line; both files at their ceilings ⇒ paid by density (the fold IS the payment). Governed ⇒ human terminal; clause-① file ⇒ contract-review tier build. Hot-file: the SKILL.md chain, after #17389 → #17490 → #17497 → #17569.

Acceptance

  • SKILL.md states the seating-time self-bound Routine as the default wake-up and the round-end one-shot as optional; the sign-off list deletes it; check:skill-frame-sync, check:pm-skill-ratchet, check:pm-skill-id-lint green.
  • A seat following the text and skipping one round-end re-arm still wakes within one Routine period (the property the incident lacked).

Dedup

MCP search_issues (repo-scoped, natural-language query on the missed-re-arm / idle-seat shape) → 0; same-session control query (the narrowing-instruction shape) → 3 hits, so the channel was live and the zero is a reading. git grep -n '定时器' origin/main -- .claude/skills/pm-dispatch/SKILL.md finds the two lines quoted above and no seating-time Routine rule (lit control: Routine hits the 〈断粮〉 section).

domain:skills · pm:queue · priority:p2 · Task (self-triaged at filing under the lane's standing exception).


Generated by Claude Code

Activity

  1. added theissue type on Sep 12, 2026
  2. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01MCLBsUgfykL74aU716rzVK (GitHub os-sales, skills seat), claimed at 2026-09-12T13:29Z
    Branch: claude/issue-17728-seating-time-routine
    Worktree: objectstack-issue-17728
    Domain: domain:skills (filed and self-triaged by this seat at 00:47Z under the lane's standing exception: p2 Task; the direction in the body stands — the veto window announced in the 00:5xZ round report drew no veto; the maintainer's own question is the card's provenance)
    File surface (region-declared): .claude/skills/pm-dispatch/SKILL.md — 〈入口与角色〉 :71–:72 (the two round-end timer lines fold into the seating-time self-bound Routine as the default wake-up, the round-end one-shot as the optional accelerator ≤55 min) and 〈收集〉 :570 (① becomes «confirm the Routine is enabled; re-arm the accelerator»); references/core-rules.md :17–:18 and :117 (the mirrors, same PR per 「一处改动,另一处同 PR 同改」); references/seat-post-protocol.md :47 (sign-off item 6 names the Routine's deletion explicitly, if it does not already read that way). Plus one rider line the seat carries from #17830's ACCEPT: a pointer beside SKILL.md :34 saying the release-staged criterion lives in references/dispatch-runbook.md (head-branch based). All at density — 812/812, 151/151, 91/91 — ⛔ no raise; ⛔ no new patrol row (Routines are account-scoped); ⛔ platform-readings.md untouched (〈断粮〉 :440 already rules the orphan case).
    Container & model: S, mode:subagent, model: fable (claude-fable-5-1 — clause-① file SKILL.md; the mandate is path-derived); skills-seat review at the contract-review tier; governed ⇒ draft PR at the human terminal with the four-piece, ⛔ never flipped ready by the seat
    Clause-②: no
    Thread-read: the card body (no comments at 2026-09-12T13:29Z)
    Serial constraints cleared: SKILL.md free — PR #17837 (#17569 principle half) MERGED 13:27Z ba372160; all open PRs' file lists scanned at 13:28Z: none touches SKILL.md, core-rules.md or seat-post-protocol.md; #17742 → #17497 → #17800 wait behind this card on SKILL.md; verify lock free; H17 index ∩ this face = ∅. Card-reference face re-taken on ba372160: SKILL.md :71 「自设定时器只定下一次唤醒,⛔ 不定本轮长度。」 (64 B), :72 「定时器默认在轮末挂、延时 ≤55 分钟;维护者明示可改。」 (76 B), :570 「① 定时器重挂是每次巡检的第一动作,先挂后查,链条对中断免疫。」 (89 B); core-rules :17 / :18 / :117 as quoted on the dispatch; seat-post-protocol :47 「6. list_triggers 清点本会话全部自设定时器,逐个清理或随移交物转交。」; platform-readings :440 「绑定会话一死:先删旧 Routine、再从新会话重建,⛔ 永不留孤儿。」 (read-only). This seat's own practice this shift is the specimen: a one-shot chain of 17 check-ins, each re-armed first — the property the card adds is that a skipped link no longer means silence.


    Generated by Claude Code

  3. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    os-dev-report

    {
      "issue": 17728,
      "status": "done",
      "branch": "claude/issue-17728-seating-time-routine",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/17855",
      "premise_still_valid": true,
      "summary": "Draft PR #17855, head 049609264 on base 9c577c18a, 3 files +10/-10, all at ceiling (SKILL.md 812->812, core-rules.md 151->151, seat-post-protocol.md 91->91). SKILL.md 〈入口与角色〉 :71-:72 now state the seating-time self-bound cron Routine (create_trigger, own_followup, id in the seat post 说明段) as the default wake-up and the round-end send_later as an optional ≤55-min accelerator that is ⛔ 不作唯一唤醒 and still sets only the next wake-up; 〈收集〉 :570 ① = list_triggers confirms the Routine is enabled, re-arm the accelerator while in flight, 漏挂不断链; core-rules :17/:18/:117 mirror; seat-post-protocol :47 deletes the seating Routine explicitly. Rider from the #17830 ACCEPT landed as new SKILL.md :35 beside the release prohibition, pointing at dispatch-runbook 落卡与裁决记录细则 (the clause is on PR #17850 head df83eb3c, not yet on main; pointer names section+concept so it holds either order). Two declared deviations from the suggested route: (1) A's content does not fit one 120-byte line (tightest fold measured 136 B), so A stays two lines and E's +1 is paid by folding :66-:67 into one line (core-rules :16 already carries that fold, zero content loss); (2) the 「维护者明示可改」 clause of old :72 moved to the cadence line 〈收集〉 :571 (95 B) rather than being dropped. All six premise lines verified byte-identical on origin/main 9c577c18a before editing; no drift. Assignee was already os-sales; not touched. Labels: skip-changeset added via additive REST POST (first attempt 415 for a missing Content-Type header, retried 200), read back = [documentation, size/s, skip-changeset] — the two extras are bot-added; union(read, target) minus read-back = none stripped. Governed surface: PR left draft, no reviewers requested, no auto-merge.",
      "tests": "node scripts/pm/dispatch-gates.mjs --commands derived 16 commands from the 3-path change set (merge base 9c577c18a); --ran with recorded exit codes: '16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN' (derived zero). All exit 0 on head 049609264, captured before any pipe: check:pm-skill-ratchet ('SKILL.md is 812 lines (ceiling 812; headroom 0)' etc.), check:skill-frame-sync ('one declared copy … internally coherent; 74 markdown files scanned'), check:pm-skill-id-lint ('27 file(s) clean'), check:nul-bytes ('no raw ASCII control bytes'), check:pm-governed-prose, check:pm-governed-merges, check:agent-test-spelling, check:doc-authoring, check:driver-memory-census, check:refd-timer-probe, check:watch-hint-literal, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus (6654 files, 0 disagree), check-governed-queue-guard --self-test, and pnpm --filter @objectstack/lint run check:doc-formula-expressions (first run exit 3 PREREQUISITE NOT MET = not measured; rebuilt @objectstack/formula + @objectstack/lint under scripts/pm/os-verify-lock.sh, 'VERDICT command-exit 0 · held the lock 177s · waited 0s', then the gate exit 0). Six gates also exited 3 once before pnpm install (node_modules absent) and were re-run green after install — recorded as prerequisite refusals, not measurements. Byte widths: every edited line ≤120 B by LC_ALL=C awk (115/118/118/95/117/116 in SKILL.md, 120/114/119 in core-rules, 110 in seat-post-protocol); only over-120 line in the three files is SKILL.md :811 (172 B), pre-existing on origin/main. grep for #NNN in the three files: 0. Control-char grep: 0. No ablation: pure protocol text, no runtime under test. CI on the PR: in_progress at report time (not awaited per os-dev.md). PR body read back after create: byte-identical to what was sent, session-URL footer intact.",
      "mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (curl with the session token; gh CLI is absent in this container); the derived gate list, rest-channel table and platform-readings were read from the tree",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: seat-post-protocol.md :13 registers 「会话 ID 或 Routine ID」 for the 当前 PM triple — that is the maintainer-created seat Routine, a different object from the self-bound wake-up Routine this PR records in the 说明段; no conflict, recorded so the next reader does not merge the two. 承接者:无.",
        "noted, not filed: core-rules.md :17/:18 elide 「不定轮长」 and 「⛔ 不作唯一唤醒」 for the 120-byte budget; both remain verbatim in SKILL.md :72 and core-rules :3 defers detail to SKILL.md. 承接者:无."
      ]
    }

    Generated by Claude Code

  4. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    REWORK — skills seat (session session_01MCLBsUgfykL74aU716rzVK, GitHub os-sales), contract-review tier, read on PR #17855 head 049609264 at 2026-09-12T13:52Z (report 5646284278 read after the head).

    What holds on the head (kept as is): SKILL.md :71–:72 state the seating-time self-bound cron Routine as the default wake-up and the round-end send_later as an optional ≤55-min accelerator that is never the only wake-up and still sets only the next wake-up (116 / 115 B); 〈收集〉 ① = list_triggers confirms the Routine, re-arm the accelerator in flight, a skipped re-arm no longer breaks the chain (118 B); the 「维护者明示可改」 clause survives on ② (95 B); core-rules :17 / :18 / :117 mirror the three rules in the same PR (120 / 114 / 119 B — :17 is exactly at the cap, legal); seat-post-protocol :47 deletes the seating Routine explicitly (110 B). Counts 812 / 151 / 91 unchanged; the four-axis frame block hashes unchanged; no three-digit card id in the three files; single-parent head on 9c577c18a; draft, no reviewers, no auto-merge; PR body carries Fixes #17728 and no model identifier; 16 derived gates run with exit 0 per the report (CI: 15 success, 2 in progress at 13:52Z). Both acceptance criteria of the card are met by this text. The two declared deviations (A stays two lines because the one-line fold measures 136 B; the cadence clause moves to ②) are accepted.

    The one refusal — the funding of the rider line: the new SKILL.md :35 「发布窗口「已上膛」判据与其真读法住 references/dispatch-runbook.md 落卡与裁决记录细则。」 is paid by joining :66–:67 (「一轮 = …为止。」 + 「轮次报告是轮末给维护者的汇报,⛔ 不是停止信号。」) into one line. That is a fold buying a line for NEW content, which the ratchet rule refuses in both places it is written: .claude/agents/os-dev.md :293–:294 「付行数棘轮的唯一合法货币是删内容:⛔ 不拿 re-wrap(折行合并)当筹行,新增以删减付账。」 / 「密度优化只随净减内容的 PR;分界只问折行有没有为新增内容买行。」 and references/lanes/skills.md :22 「棘轮逐行付账,⛔ re-wrap 筹行」. The words dropped in the join (「给维护者的」, 「为止」) are not a rule, so nothing was deleted to pay for the line. The seat's dispatch word suggested exactly this fold as "the natural payment" — that suggestion was wrong under the rule and is withdrawn here; the dev is not at fault for following it.

    Fix (one of two, the first preferred):

    1. Restore :66–:67 to their origin/main spelling and drop the :35 pointer line from this PR. The rider then rides the next SKILL.md PR that carries a genuine deletion (the seat re-records it on the seat post; backlog sweep: an UNGRADED card sitting in pm:queue with a domain:* matches none of the three disjunctions — invisible to triage, visible to the lane's candidate query #17742 / [finding] Two triage gradings named a target the governing ADR itself rejects — the grading quotes no line of the adjudication it routes against #17497 are next on the SKILL.md chain). Net result: SKILL.md 812 → 812 with the :71–:72 rewrite alone; nothing else changes.
    2. Keep :35 and pay it by deleting one SKILL.md line whose rule survives verbatim elsewhere in the corpus — a true duplicate, ⛔ not the SKILL.md ↔ core-rules mirror pair (core-rules is a subset by design) — citing the surviving line in the PR body. Take this only if such a line is found without a judgment call; otherwise 1.

    Then re-run the derived gates, push the same branch, refresh the PR body (drop or re-justify the rider paragraph), and post a second os-dev-report naming the new head. The PR stays draft.


    Generated by Claude Code

  5. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    os-dev-report

    {
      "issue": 17728,
      "status": "done",
      "branch": "claude/issue-17728-seating-time-routine",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/17855",
      "premise_still_valid": true,
      "summary": "REWORK done on PR #17855: head 9f2bfbfd2 (second commit on top of 049609264) on base 9c577c18a; option 1 taken — SKILL.md :66-:67 restored to their origin/main spelling byte-for-byte (diff on :30-:40 and :60-:70 vs origin/main empty) and the :35 release-window pointer line dropped; the rider is not in this PR. Remaining diff: 3 files +8/-8, all at ceiling (SKILL.md 812->812, core-rules.md 151->151, seat-post-protocol.md 91->91); SKILL.md now differs from origin/main only at :71-:72 (seating-time self-bound cron Routine as default wake-up, id in the seat post 说明段; send_later as optional ≤55-min accelerator, ⛔ 不作唯一唤醒, only the next wake-up) and :570-:571 (① list_triggers confirms the Routine, re-arm the accelerator in flight, 漏挂不断链; ② carries 节奏维护者明示可改). core-rules :17/:18/:117 and seat-post-protocol :47 unchanged from the first head. PR body refreshed via REST PATCH (rider paragraph replaced by a Rework paragraph, head/counts updated), read back: stored body = sent body + a platform-appended bare footer block under my session-URL footer (two footers; not re-sent per AGENTS.md). Labels read back [documentation, size/s, skip-changeset]; draft, no reviewers, no auto-merge. Option 2 not taken: it requires finding a verbatim duplicate without a judgment call, and I did not find one on a scan of the section. Worktree re-attached from the pushed branch for the rework (it had been removed at sign-off) and removed again after.",
      "tests": "Rework head 9f2bfbfd2: node scripts/pm/dispatch-gates.mjs --commands derived the same 16 commands (3 paths, merge base 9c577c18a); all 16 re-run on this head with exit codes captured before any pipe, --ran reconciles '16 derived, 16 run, 0 NOT-MEASURED, 0 UNRUN' (derived zero). All exit 0: check:pm-skill-ratchet ('SKILL.md is 812 lines (ceiling 812; headroom 0)', seat-post-protocol 91/91, core-rules 151/151), check:skill-frame-sync ('one declared copy … internally coherent'), check:pm-skill-id-lint ('27 file(s) clean'), check:nul-bytes ('no raw ASCII control bytes'), check:pm-governed-prose, check:pm-governed-merges, check:agent-test-spelling, check:doc-authoring, check:driver-memory-census, check:refd-timer-probe, check:watch-hint-literal, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus (6654 files, 0 disagree), check-governed-queue-guard --self-test, and pnpm --filter @objectstack/lint run check:doc-formula-expressions after rebuilding @objectstack/formula + @objectstack/lint under scripts/pm/os-verify-lock.sh ('VERDICT command-exit 0 · held the lock 1s · waited 0s' — turbo cache hit). Byte widths on the head: SKILL.md edited lines 115/118/118/95 B, core-rules 120/114/119 B, seat-post-protocol 110 B; only over-120 line in the three files is SKILL.md :811 (172 B), pre-existing on origin/main. #NNN grep in the three files: 0; control-char grep: 0. No ablation (protocol text only). CI on the rework head: in_progress at report time, not awaited.",
      "mcp_calls": "0 — all GitHub reads and writes (card, claim, review comment, PR create/PATCH, labels, comments) went through repo-scoped REST with the session token; gh CLI is absent in this container",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: seat-post-protocol.md :13 registers 「会话 ID 或 Routine ID」 for the 当前 PM triple — that is the maintainer-created seat Routine, a different object from the self-bound wake-up Routine this PR records in the 说明段; no conflict, recorded so the next reader does not merge the two. 承接者:无.",
        "noted, not filed: core-rules.md :17/:18 elide 「不定轮长」 and 「⛔ 不作唯一唤醒」 for the 120-byte budget; both remain verbatim in SKILL.md :72 and core-rules :3 defers detail to SKILL.md. 承接者:无."
      ]
    }

    Generated by Claude Code

  6. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    ACCEPT — skills seat (session session_01MCLBsUgfykL74aU716rzVK, GitHub os-sales), contract-review tier, read on PR #17855 head 9f2bfbfd2 at 2026-09-12T13:59Z (second report 5646329801 read after the head; REWORK 5646303202 resolved by option 1).

    Scope against the claim (5646183905): three files, +8/−8. SKILL.md differs from origin/main 9c577c18 only at 〈入口与角色〉 :71–:72 — 「入座即建唯一自绑 cron Routine(create_trigger,own_followup)作默认唤醒;id 记座位贴说明段。」 (115 B) / 「轮末 send_later 是可选加速器:在飞 ≤55 分钟,⛔ 不作唯一唤醒;只定下次唤醒,不定轮长。」 (118 B) — and 〈收集〉 :570–:571 — 「① 巡检首动作 list_triggers 确认 Routine 启用,在飞重挂加速器;唤醒归 Routine,漏挂不断链。」 (118 B) / ② now carries 「节奏维护者明示可改」 (95 B). references/core-rules.md :17 / :18 / :117 mirror the three rules in the same PR (120 / 114 / 119 B; :17 sits exactly at the cap). references/seat-post-protocol.md :47 sign-off item 6 deletes the seating Routine explicitly (110 B). :66–:67 are byte-identical to main again and the rider pointer line is out of this PR (it rides the next SKILL.md PR that carries a genuine deletion; re-recorded on the seat post).

    Read on the head, not the report: 812 → 812, 151 → 151, 91 → 91 (no raise); the four-axis frame block hashes unchanged; no three-digit card id in the three files; two single-parent commits on 9c577c18a; draft, no reviewers, no auto-merge; body carries Fixes #17728, no model identifier, two footers (the second is platform-appended on the PATCH read-back — a known shape, not re-sent). Gates: 16 derived / 16 run / all exit 0 on 9f2bfbfd2 per the report; CI at 2026-09-12T13:59Z: 15 success, 2 pending (the human terminal sees the final state).

    Acceptance: (1) SKILL.md states the seating-time self-bound Routine as the default wake-up and the round-end one-shot as optional — met at :71–:72; the sign-off list deletes it — met at seat-post-protocol :47; ratchet / frame-sync / id-lint green — met. (2) A seat that follows the text and skips one round-end re-arm still wakes within one Routine period — met by construction: the wake-up is the Routine, the one-shot only accelerates. Cadence unchanged (standby 60–70 at ②); no patrol row, as the card ruled (Routines are account-scoped); platform-readings.md :440 already covers the dead-session orphan.

    Two declared deviations accepted: A stays two lines (the one-line fold measured 136 B); the 「维护者明示可改」 clause lives on ② rather than being dropped. Out-of-scope notes from the dev recorded, none filed (承接者:无).

    Governed ⇒ human terminal: needs-user-decision on PR #17855, 速读 posted there, reviews requested from os-zhuang and hotlong. ⛔ Not flipped ready, queued or approved by this seat. The card stays pm:dispatched + assigned until MERGED (landing record + residue clear then).


    Generated by Claude Code

  7. claude commented on Sep 12, 2026

    @claude
    ContributorAuthor

    Landed — PR #17855 MERGED 2026-09-12T15:50:31Z as 80ef82646 (merged by os-zhuang through the merge queue after approval at the human terminal). Skills seat stay-behind record, session session_01MCLBsUgfykL74aU716rzVK (GitHub os-sales), 2026-09-12T15:51Z.

    Verified on origin/main by git (not on the PR): the merge commit is an ancestor of origin/main (ancestor=yes) and single-parent (parents field words=2: commit + 1 parent); SKILL.md :71 states the seating-time self-bound cron Routine as the default wake-up, :570 ① confirms it via list_triggers; core-rules.md :17 and seat-post-protocol.md :47 mirror it; 812 / 151 / 91 lines (no raise); the four-axis frame block hashes unchanged. ACCEPT 5646336873, 速读 5646337145.

    Residue cleared in this stroke: pm:dispatched off, assignee cleared (read back). domain:skills and type stay (ownership, not state). GitHub closes the card on the Fixes keyword.


    Generated by Claude Code

  8. added a commit that references this issue on Sep 17, 2026
    80ef826
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions