Team recap · Diagnostic session · 2026-07-23
Someone ran our automated "ship" workflow on their own laptop and saw a message: falling back to synchronous CI polling. Nothing broke — that fallback is by design. This recap explains why it happens, and answers the follow-up: no, polling does not cost the tokens you'd expect.
This was a diagnostic session, not a coding one — no files in the repository changed. The deliverable is the understanding itself: two things the whole team can now rely on instead of re-deriving. First, the live-update path the workflow prefers only exists in cloud environments, so a laptop correctly uses the polling fallback. Second, that fallback's "waiting" is free in token terms — the cost, when there is one, comes from output volume, not from time spent waiting.
What changed
Both items below document how existing behavior works. Read the color code once and it holds for the rest of the page: local · polling and cloud · subscription.
The workflow's preferred path is to subscribe to pull-request events and react as they arrive. That needs a tool that exists only in remote environments — Claude Code on the web, or a GitHub Action. On a laptop the tool is simply absent, so the workflow does the correct thing: it polls the checks until they finish. The message you saw is that switch happening, not a failure.
"Polling" sounds like the model checking over and over. It isn't. The workflow waits inside a single blocking command, and the model does no thinking — and spends no tokens — while that command waits for CI. Cost appears only from the text the command finally prints, and from any fix-and-recheck loops. Waiting ten minutes costs the same as waiting thirty seconds.
How it works now
Assumption vs. reality
Nothing changed in code, so the useful "before/after" here is the gap between the common assumption and how the workflow really behaves.
| What you might assume | What actually happens |
|---|---|
| The fallback message means something failed | Expected. The cloud-only live-update tool is absent on a laptop, so the safe fallback runs. |
| Polling means checking over and over, burning tokens | The wait is one blocking command. The model is idle and bills nothing while CI runs. |
| A 10-minute CI wait costs more than a 30-second one | Same cost. Waiting is free; only the returned output is billed, once. |
| Subscription mode is always cheaper | Only for chatty PRs. For a quiet PR that goes green once, polling is cheaper — one turn, then done. |
| It keeps handling review comments after merge time, locally | No. Locally it stops after merging. The keep-watching behavior needs subscription mode. |
Decisions
Polling is a complete path to the same outcome — watch CI, fix failures, merge when green. The only local losses are cosmetic (the turn stays busy) and post-merge (no ongoing comment handling).
Rejected · warn or block harder locally
Adds friction to a workflow that already does the right thing.
Rejected · require running remotely
Removes a real capability (local shipping) to solve a non-problem.
The single blocking watch command is the simplest thing that waits until CI settles, and its cost is fine for normal runs.
Rejected · swap in a sleep-then-check loop
It would shrink the printed output but add model turns, and today's output isn't big enough to justify the change. Kept as an option if watch output ever bloats a session — see Open items.
Learnings
Open items
If the watch command's repeated status tables ever noticeably bloat a session's context, replace the single blocking --watch with a short loop that sleeps and then asks for the compact JSON status. Trade-off: a couple more model turns for a much smaller output footprint. Only worth doing if the bloat is actually observed.
Files touched
kit/plugins/git-agent/skills/ship-autonomous/SKILL.md — traced the Step 5 subscribe-or-poll branch and the fix-and-recheck loop.docs/plans/sessions/document-ship-autonomous-ci-polling-session.md — this committed recap record.Glossary
Session d76058d4 · recap generated 2026-07-23 · source: ship-autonomous/SKILL.md