All Recipes

ExecPlan: an agent on 7–25-hour tasks (Phase 2)

Phase 2 of the Harness Engineering series: ExecPlan is a living plan in the repo that keeps an agent on a long autonomous task (7–25 hours, dozens of files) without losing context. When to use it and when to skip, which sections the human writes before the start (Context, Goal, Out of scope, Approach) and which the agent fills as it goes (Progress, Decisions, Surprises). A copyable ExecPlan template, a 30-minute readiness diagnostic, and the live-update discipline. Stack-agnostic.

IntermediateAI DevOps20 minExecPlan, Claude Code, Plan mode
1

Why an ExecPlan: long autonomy without losing the thread

An ExecPlan is a living plan in the repo (a single markdown file) that lets an agent carry one task across many hours and many files without losing the thread. The series hub (see the 'Harness Engineering' recipe) shows a task travelling through four phases; the ExecPlan is the design-phase artifact that holds context across the longest of them. The problem it solves is simple. On a task that runs 7–25 hours and touches dozens of files, the agent (and the human) forgets what's already done, which decisions were made and why, and what surprises turned up along the way. The chat scrolls, context gets evicted, and an hour in the agent 'doesn't remember' that an hour ago it already rejected one of the approaches. The ExecPlan moves this out of the ephemeral chat into a file: a single source of truth for this one task that survives a session restart. None of this is tied to a stack or a specific agent — it's a process artifact: it works the same for a Go refactor, a Python DB migration, or a new TypeScript feature.

Without an ExecPlan

  • Context lives in the chat — evicted on a long task
  • An hour in, the agent 'forgets' rejected approaches
  • A session restart ≈ starting almost from scratch
  • Decisions and their reasons are recorded nowhere

With an ExecPlan

  • One source-of-truth file for this one task
  • Progress / Decisions / Surprises survive a restart
  • Stack-agnostic: Go, Python, TS — all the same
  • The human reviews against the plan, not the chat log
An ExecPlan is neither a ticket nor an ADR. A ticket says 'what we want', an ADR records one architectural decision forever; an ExecPlan is the working memory of one long task, alive exactly while that task is in flight.
2

When to use it — the threshold

An ExecPlan isn't free: writing and maintaining it costs time, so it isn't for every task. The threshold from the rollout plan: a task bigger than one working day and/or touching more than 5 files — then an ExecPlan is justified. Anything smaller runs through the normal loop without a separate plan: a one-line bugfix, a local edit to a single function, adding a couple of tests need no plan. Typical candidates for an ExecPlan are non-trivial work: large refactors, new features bigger than a working day, migrations. What they share is that the task doesn't fit in one span of attention and must be broken into milestones, each with its own Definition of Done. When unsure, look not at difficulty but at horizon: a task the agent will carry for hours across session restarts falls apart without a written plan; a short one doesn't.

Does this task need an ExecPlan?

Task bigger than one working day
Touches more than 5 files
Large refactor, new feature, migration
Splits into milestones, each with its own DoD
A one-line bugfix — needs no plan
A local edit to one function — no plan
The '>1 day / >5 files' threshold is a filter, not a mandate. The goal isn't 'write more plans' but 'don't carry a long task without written memory'. If a short task suddenly balloons, start an ExecPlan mid-flight — that's fine.
3

Template structure: section / who writes it / when

An ExecPlan's power is a clean split of responsibility: some sections are input from the human BEFORE the start, others the agent fills AS IT GOES, and the last one the human writes AT THE END. A missing required section is a sign of a bad plan. Before the start the human writes four sections: Context (the task, motivation, constraints), Goal — one sentence for what counts as success, Out of scope (what we deliberately do NOT do), and Approach — 5–10 bullets on how we'll move, the split into milestones with a Definition of Done for each. These are the boundaries the agent then works inside autonomously. As it goes, the agent keeps three sections: Progress (what's done, updated after every phase), Decisions — each decision made and its reason, and Surprises — what went wrong, with short proofs (test output is ideal). At the end the human writes the Definition of Done as achieved: what actually came out, a retrospective. Keep every section's examples stack-agnostic — the plan shouldn't read as bound to one framework.
SectionWho writes itWhen
Context — task, motivation, constraintsHumanBefore the start
Goal — one sentence for successHumanBefore the start
Out of scope — what we do NOT doHumanBefore the start
Approach — 5–10 bullets, milestones + DoDHumanBefore the start
Progress — what is doneAgentAs it goes, after each phase
Decisions — decision and reasonAgentAs it goes
Surprises — what went wrong + proofAgentAs it goes
Definition of Done — outcome, retrospectiveHumanAt the end
Goal is exactly one sentence. If success doesn't fit in one phrase, the task is either fuzzy or it's two tasks. Out of scope matters as much as Goal: it explicitly cuts off what the agent would otherwise improvise and do 'while it's at it'.
4

A copyable ExecPlan template

Here's the template itself — drop it into the repo as docs/templates/ExecPlan.md, and save each concrete plan as docs/plans/YYYY-MM-DD-short-name.md. Copy the block below as is; its examples are stack-agnostic, swap them for your task. Note the Surprises example: a short proof, not 'feels off'. The ideal proof is the output of a test or command. And about tests, honestly: a failing test in Surprises is worth more than a green dashboard — the agent must not edit or delete existing tests just to 'make the phase pass'.
# ExecPlan: <short task name>

## Context
Why this task exists, the motivation, and the constraints.
e.g. Search endpoint p95 latency is ~1.8s; product needs < 500ms.
Constraint: public API response shape must not change.

## Goal
ONE sentence describing success.
e.g. Search p95 latency under 500ms with the same response shape.

## Out of scope
What we deliberately will NOT do in this task.
e.g. No new caching layer; no schema migration; no UI changes.

## Approach
5–10 bullets. Split into milestones, each with a Definition of Done.
- M1: add a benchmark that reproduces the slow path. DoD: a failing
      perf test that prints current p95.
- M2: profile and isolate the hot query. DoD: profile saved, top
      cost identified.
- M3: fix the hot path. DoD: perf test passes, existing tests stay
      green (do NOT weaken tests to pass).
- M4: document the change. DoD: short note + plan retrospective.

## Progress            # filled by the agent, AFTER EACH milestone
- [x] M1 done — benchmark added, baseline p95 = 1.82s.
- [ ] M2 in progress.

## Decisions           # filled by the agent, as it goes
- Reuse the existing query builder instead of raw SQL — keeps the
  module boundary; raw SQL would cross it.

## Surprises           # filled by the agent, with a SHORT proof
- N+1 query in the list path. Proof:
    $ run perf-test
    queries executed: 142 (expected ~3)

## Definition of Done  # filled by the HUMAN, at the end
What actually shipped, and a short retrospective. Left empty until
the task closes.
Keep the template's examples realistic and stack-agnostic, not 'lorem ipsum'. An empty template gets filled by guesswork; a template with a live example shows the expected density and tone — especially the Surprises section with its proof.
5

Live-update: Progress / Decisions / Surprises as you go

The core ExecPlan discipline is to update it AS YOU GO, not at the end. This rule is straight from the rollout plan: the agent updates Progress and the Decision Log along the way, not at the end. The temptation to 'write it all up when I'm done' kills the plan's point: if context gets evicted or the session dies before the agent writes up, the working memory is lost and must be rebuilt from the chat log (which may no longer exist). The rhythm is simple: finish a milestone → mark it in Progress immediately; make a forked decision → record it in Decisions with the reason; hit a surprise → log it in Surprises with a short proof. Each entry is a separate edit to the file, not a batch. Then at any moment the plan is a current snapshot of the task's state, and a new session (or a human reviewing) starts from it instead of reverse-engineering what's going on. Tests here are a health signal: a failing test's output in Surprises shows a real problem; masking it by weakening the test is forbidden.
Closed a milestone
Marked in Progress
Plan = current snapshot
Fork → Decisions + reason
Surprise → Surprises + proof
Batch rule: one file edit per event, not 'I'll write it all up at the end'. If you catch yourself thinking 'I'll update Progress when the phase is done', that's deferred context loss already. Update right away.
6

The 30-minute readiness diagnostic + what next

Before launching an agent on a long task, run the readiness diagnostic: can you write the first four sections — Context, Goal (one sentence), Out of scope, Approach (5–10 bullets) — in 30 minutes? If half an hour isn't enough, the task isn't ready to launch. That doesn't mean 'think longer': it means the task is underunderstood, fuzzy in its goal, or secretly several tasks — and an agent launched on it will spend hours of autonomy in the wrong place. The diagnostic is cheap and honest: 30 minutes of writing catch the problem before the agent burns 10 hours on a misread task. If the first four sections come easily, the boundaries are clear and you can launch: from there the agent keeps Progress / Decisions / Surprises itself, and you plug in for review and write the Definition of Done at the end. Where to go next in the series. This recipe is Phase 2 (the ExecPlan template and protocol). The map of the whole series is in the Harness Engineering hub. The next phase is architectural constraints: how to turn 'must not break' from your Approach into deterministic machine checks, so an agent on a long task can't drift out of bounds unnoticed. What an ExecPlan honestly does NOT do: it doesn't validate functional correctness (whether the code does what the user needs stays with the human and product tests) and doesn't replace human review. It holds the thread and structure of a long task — but you still set the meaning.

The 30-minute diagnostic: is the task ready to launch?

Context writes in minutes — task and constraints are clear
Goal fits in one sentence
Out of scope is explicitly drawn
Approach — 5–10 bullets with milestones and DoD
Can't write the 4 sections in 30 min → task isn't ready
Launching the agent on a fuzzy goal to 'figure it out as it goes'
Can't write the first four sections in 30 minutes — that's not a signal to 'spend longer on the plan' but a signal that 'the task isn't ripe'. Reframe or split it, then launch the agent — otherwise the autonomy is wasted.

Result

You understand an ExecPlan as a living plan file in the repo that keeps an agent on a long autonomous task (7–25 hours, dozens of files) without losing the thread. You know the threshold (>1 working day and/or >5 files — otherwise skip), who writes each section and when (the human — Context / Goal / Out of scope / Approach before the start; the agent — Progress / Decisions / Surprises as it goes; the human — Definition of Done at the end), and you hold two rules: live-update after every phase (not batched at the end) and the 30-minute readiness diagnostic before launch. You have a copyable ExecPlan template. It's all stack-agnostic; tests are a health signal, not a KPI. Next in the series — architectural constraints.