Never give the connector's monitor a timeout
Context
Kitchen card: a connector session armed its request monitor with a 30-minute timeout. At each expiry the model woke, re-armed it, and said another system "is running in the background. Nothing is needed from you." That was about 48 wasted turns a day, and nothing behind the status line had checked that system, which took no work for 15 hours meanwhile.
The skill already said persistent: true. What pushed the session to a timeout is the Monitor tool itself: in current Claude Code builds (2.1.322 here) a feature gate, on by default, drops persistent from the Monitor schema, makes timeout_ms the only knob (default 5 minutes, capped at 30), and the tool's description tells the model to "set timeout_ms to the maximum and re-arm on each expiry". 30 minutes is exactly that cap. So the skill has to say what to do both where persistent exists and where it doesn't.
Change
skills/basecamp-connect/SKILL.md only:
- What this flow needs now names a Monitor tool that takes
persistent, beside Claude Code. Without one, the session goes to Without this session (--orchestrator) before starting anything, which needs no monitor and records each event once. - Step 1 arms the monitor with
persistent: trueand never atimeout_ms, in the arming sentence itself. If it expires, re-arm it once, persistent; if that one expires too (a remote session turnspersistentinto a 30-minute cap), tell the person. An earlier head switched to the orchestrator mode mid-run instead, which needed a stop, a wait for the lock and a drain of requests already marked handed off; the switch went rather than gaining a third patch. - Without this session says why a monitor that always expires can't hold the watch: each re-arm replays the whole output file (
tail -n +1), and a compacted session can't tell requests it handled from new ones. - Keep the terminal quiet now says the session speaks for the connector alone and never says whether anything else here is working.
- The
event_idskip rule names a re-armed monitor's replay beside a restart.
To keep the per-request steps inside the 14,000-character compaction budget (TestTheConnectSkillKeepsEachRequestsStepsInsideTheCompactionCut), the opening paragraph goes: the "Three pieces" list restates it point for point. The per-request part now ends at 13,949 characters, against 13,980 before: 51 characters of headroom, so the next addition here will have to trim something.
For a decision: the Monitor in Claude Code 2.1.322 has no persistent by default (see Context), so on today's builds this sends most sessions to the orchestrator mode rather than a session watch. The alternative is a session that re-arms every 30 minutes with a cursor file the monitor writes so a replay resumes after the last line passed: about 48 turns a day, and a persisted marker to keep right. That is the trade-off to settle; this PR takes the first.
Verification
bin/cigreen on b9fab5d (run on a 32-core host): unit and e2e tests, lint, CLI surface, and skill drift for all four skill files. On 76fd277, which changes only SKILL.md wording, the connector skill tests andmake check-skill-driftpass.TestTheConnectSkillKeepsEachRequestsStepsInsideTheCompactionCutpasses at 13,949 characters; the first head's additions without dropping the opening paragraph measured 14,233 and failed it.- The Monitor schema behavior is read from the Claude Code 2.1.322 bundle: with the gate on, the tool takes no
persistentand capstimeout_msat 30 minutes; with it off,persistent: trueruns with no timeout and ignorestimeout_ms. - Not run:
make -C skill-evals eval-connect(model-graded; no case covers arming the monitor).