The Venue Cutover

Project13 min · Scope → Isolate → Supervise → Land · Updated 2026-09-15

You end this lesson with: fleet/cutover.md — your fleet moved to its chosen venue with a measured before and after.

Chapters

  1. Brief
    01
  2. The Rule This Lab Tests
    02
  3. Steps
    03
  4. Acceptance
    04
  5. Rubric
    05
  6. Key Takeaways
    06

Project 03. The Venue Cutover

A three-person team at a seed-stage logistics startup had been running their coding agent's overnight jobs on the founding engineer's laptop for four months. One night the laptop's lid drifted half-shut on a desk that wasn't quite level, and the OS put the machine to sleep fifteen minutes later — the default nobody had ever changed. The agent was thirty-eight minutes into a two-hour migration task when the process froze mid-run: no crash, no error, no partial commit, just a status file that stopped updating at 2:47am and never resumed. The team re-ran the whole task from scratch the next morning once someone noticed. Nobody could say how many nights like that one had already happened before this one got caught, because nothing had ever been watching for it.

Illustrative composite. The team, the laptop, and the exact timestamps are a teaching device; the failure mode — an unattended run dying to a laptop's own power settings, with no page and no record of when it happened — is the one this project measures a real fix for.

Your fleet has run on your laptop since module one. Lesson nine had you price two venues and write an exit plan for each in fleet/venues.md; lesson ten gave every agent a working, blocked or done status file and a page when one needs you. This project asks you to actually move: run real work in the venue you chose, not a toy example, and put a number on what changed. Three small tasks, run once on the laptop and once on your chosen venue, with fleet/watch/'s own logs as the source of every number in the sheet you hand over. If the venue is cheaper, faster, or less painful to walk away from, the sheet says so. If it is not, the sheet says that too, and the rollback path is what you reach for next.

Brief

Pick the venue you priced and timed in fleet/venues.md: the remote host from lesson eight, a self-served sandbox, or a vendor's managed cloud agent. If you have not provisioned anything yet, read the fallback at the end of this brief before you start rather than letting provisioning delay the project. Wire fleet/watch/'s writer side (run.sh and the Notification hook) into whichever agent CLI you use in both conditions, laptop and venue, so the same log format backs every number below. You need write access to a repository you are willing to have an agent touch twice with the three tasks that follow, your own project or a disposable clone.

The three benchmark tasks

Run each of these exactly as given, in both conditions, so the two runs of a task differ only in venue.

Task A, "the changelog stub." Goal: add one dated entry to CHANGELOG.md (create the file if it does not exist) summarizing the last five commits in one or two sentences. Files it may touch: CHANGELOG.md only. Interfaces it must not invent: none, this is a content change. Done test: the file has a new top entry dated today, and git diff --stat touches exactly one file. Ceiling: ten minutes. This task is nearly free on its own; its purpose is isolating venue overhead from work.

Task B, "the flaky test fix." Goal: find one test in your suite that depends on wall-clock time or unseeded randomness, or write one deliberately (a test asserting two Date.now() reads a millisecond apart is enough), and make it deterministic without changing what it verifies. Files it may touch: the one test file, plus a fixture or helper file if the fix genuinely needs one. Interfaces it must not invent: no new test framework, no new CI step. Done test: the test passes on ten consecutive runs. Ceiling: thirty minutes.

Task C, "the guarded migration." Goal: write and run a small, reversible data migration (add a column with a default, or rename a config key across a handful of files) that touches a path your containment tier gates behind a permission prompt, such as a database file, a generated lockfile, or anything outside the task's own worktree. Files it may touch: one migration script plus the gated path itself. Interfaces it must not invent: no new migration framework, plain script if the repo has none. Done test: the migration applies cleanly, a reverse migration or rollback script exists, and the gated write produced a Notification-hook event in fleet/watch/. Ceiling: one hour, including the wait for your own permission answer. This task is deliberately built to block at least once, so the wait-time column below is a real measurement and not an assumed zero.

The measurement sheet

Fill this from fleet/watch/runs/<run-id>/status.json, log.jsonl and done.json, never from memory or a stopwatch you eyeballed.

TaskVenueWall-clock (start → done)CostBlocked waitOutcome
ALaptopdone.json.finished_at − first log.jsonl linetokens × your runtime's rate, per lesson three's unitn/apass/fail
AVenuesame fieldssamen/apass/fail
BLaptop……n/a…
BVenue……n/a…
CLaptop……blocked-event timestamp → next transition…
CVenue……blocked-event timestamp → next transition…

Illustrative composite. A filled row might read: Task C, Venue, wall-clock 41 minutes, cost $0.62, blocked wait 6 minutes, outcome pass. The exact numbers are yours; the shape and the source (your own run logs) are not.

Price every run per the cost-per-landed-change unit from lesson three, not cost per agent-hour: a run that blocks and never finishes belongs in the sheet as a failed, unlanded attempt with its own cost, not as a zero.

A task's round trip through the venue uses the same watch hook and the same rollback path every other lesson in this module already relies on; the cutover sheet just puts numbers on how long each leg takes.

diagram
drawing
A task enters the venue through the same watch hook that pages you when it blocks, and a breached rollback trigger sends it home by the exit plan already written in fleet/venues.md, not an improvised one.

If you cannot provision a remote host this week

Run the venue condition in a local container instead: Docker Desktop, Podman, or any container runtime already on your machine, one container per benchmark task, with the same egress and credential policy from module two applied inside it. It is still a boundary your laptop's bare shell does not have, and the same measurement sheet applies without modification. This substitution is a full stand-in for a remote host, not a lesser attempt at one, and the rubric scores it identically as long as fleet/cutover.md says plainly which condition you actually ran.

The Rule This Lab Tests

Route a task to the venue when its measured cost-per-landed-change or blocked-wait handling beats the laptop's by more than the venue's own start-up latency can erase from that task's ceiling; keep the task on the laptop otherwise. Y — whether the venue's number actually beats the laptop's, net of start-up latency — is observable directly in fleet/cutover.md's measurement sheet, not asserted from a general feeling that venues are "better."

Task shapeWhat the sheet is likely to showWhere it runs
Tiny, sub-ceiling (Task A: one dated changelog line)Venue start-up latency alone can exceed the whole task's runtimeLaptop
Moderate, no blocking (Task B: a deterministic test fix)Cost-per-landed-change and wall-clock come out close; the tie-breaker is whichever axis the task's own brief cares aboutWhichever the sheet shows wins, task by task
Gated, blocks on a permission prompt (Task C: the guarded migration)The venue's paging (Notification hook) reaches you even with a closed laptop lid; the laptop needed no such hook because you were already thereVenue, if unattended survival matters more than the wall-clock gap

This is not a blanket verdict. The sheet's job, per the acceptance checklist below, is to let each task's own numbers decide, not to justify a single fleet-wide venue preference chosen in advance.

Steps

Step 1 below is fully worked, with a filled command and its confirmation output to copy. Step 4 is yours to work out: decide what a disagreement between two rows of the sheet actually means before checking your reasoning against the fence beneath it. The rest of the steps are open — the rollback trigger in step 5 has to come from your own fleet's numbers and your own tolerance for risk, and there is no filled-in answer for it here.

  1. Confirm your venue and wire the writer side. Point fleet/watch/run.sh and the Notification hook at whichever agent CLI you use, in both the laptop condition and the venue condition (or its local-container substitute). A filled example, laptop condition first:

    bash
    $ fleet/watch/run.sh laptop-smoke-01 claude-code --task tasks/smoke.md
    $ cat fleet/watch/runs/laptop-smoke-01/status.json
    {"run_id":"laptop-smoke-01","state":"done","updated_at":"2026-09-14T09:41:03Z","note":""}
    

    And the same wrapper, unchanged, against the venue:

    bash
    $ ssh venue-host 'fleet/watch/run.sh venue-smoke-01 claude-code --task tasks/smoke.md'
    $ cat fleet/watch/runs/venue-smoke-01/status.json
    {"run_id":"venue-smoke-01","state":"done","updated_at":"2026-09-14T09:52:47Z","note":""}
    

    Output: a working hook wired in both places, verified by both throwaway runs reaching done before any benchmark task depends on them.

  2. Run all three tasks on the laptop. Output: three run directories under fleet/watch/runs/, each with status.json, log.jsonl and done.json.

  3. Run all three tasks on the venue. Same tasks, same acceptance bar. Output: three more run directories.

  4. Fill the measurement sheet in fleet/cutover.md from the six run directories, computing cost per lesson three's unit. Output: fleet/cutover.md, section one. Before copying numbers into cells mechanically, work out what it means when two rows disagree:

  5. Write the rollback path. Name the specific condition that sends you back to the laptop (a cost ceiling breached, a startup-latency budget missed, a failed recovery drill from lesson eight) and the exact steps, referencing the exit plan already written in fleet/venues.md. Output: fleet/cutover.md, section two.

Acceptance

  • All three benchmark tasks are defined exactly as given, with unmodified goals and ceilings.
  • fleet/watch/run.sh and the Notification hook are wired identically in both conditions.
  • Six run directories exist under fleet/watch/runs/ (three tasks × two conditions), each with status.json, log.jsonl and done.json.
  • Task C's log.jsonl shows at least one blocked transition in both conditions.
  • fleet/cutover.md's measurement sheet has all six rows filled from the run logs, not estimated after the fact.
  • Cost figures use the cost-per-landed-change unit from lesson three.
  • fleet/cutover.md states plainly which venue was used, including if it is the local-container fallback.
  • The rollback path names a specific trigger condition and the exact steps back to the laptop, referencing fleet/venues.md.
  • The written verdict (worth the cutover or not) follows from the sheet's numbers, not from preference stated first and justified after.

Rubric

CriterionWeakStrong
Measurement sourcingNumbers estimated from memory or a single glance at a clockEvery number traces to a specific line in a log.jsonl or done.json file, checkable by a reviewer
Task fidelityTask C simplified until it no longer touches a genuinely gated pathTask C produced a real Notification-hook event in both conditions, with a measured, non-zero blocked wait
Fallback honestyVenue skipped, with projected numbers written as if measuredThe substitute local-container venue run in full, and named as a substitute, when a remote host was not available
Rollback path"We would go back to the laptop" with no trigger and no stepsA specific trigger condition and exact steps, tied to the exit plan already written in fleet/venues.md
Verdict disciplineA preference stated first, defended after the fact by cherry-picked rowsThe written verdict follows from the full sheet, naming which column decided it

Key Takeaways

  • Source every number in the cutover sheet from fleet/watch/'s own run logs, never from memory.
  • Design at least one benchmark task to trigger a real blocked event, not an assumed zero.
  • Price every run per landed change, and count a failed, unlanded attempt as its own cost.
  • Treat a local container as a full substitute venue, not a lesser one, when named honestly.
  • Write a rollback path with a named trigger, not a general intention to go back.

What You Have Now

fleet/cutover.md — your fleet moved to its chosen venue with a measured before and after, and the rollback path if the venue fails. It sits beside fleet/venues.md and reads directly from the run logs fleet/watch/ produces, closing the Supervise stage's move off the laptop with numbers instead of an impression. Both benchmark runs still go through the same fleet/watch/run.sh and fleet/watch/hooks/on-notification.sh you wired in Lesson 10; the lab's checker looks for them at those paths again here. The next module reads this same run-log format again: the headless gates in lesson twelve need per-run isolation you have now exercised twice, and the audit record in lesson fourteen borrows the same three-file layout for a different purpose.


NO-QUIZ

Quiz coming to this lesson

This lesson doesn't have a graded quiz yet — completion is still tracked, just not verified against questions.

Reading is free — your progress isn't being saved

Nothing you did on this page is recorded. Paid students get saved progress and verified completions, recorded quiz answers, the spaced-repetition review queue, labs, and a certificate for each course they finish.

30-day money-back guarantee. One-time payment — lifetime access and updates.