| name | haul-spec |
| description | Phase 1 of long-haul. Turn the user's ask into a well-defined spec โ a located deliverable, a transcript-demonstrable success signal, the toolbox of skills + MCP the haul may use, constraints, and out-of-scope. If the ask is vague, grill it first. Produces .longhaul/SPEC.md. Use as the first phase of a long-haul run, or standalone to harden a fuzzy ask into something buildable before setting a goal. |
haul-spec
Phase 1 of long-haul. The haul will run for many turns; it can only run
straight if it starts from a sharp spec. Your job is to produce
.longhaul/SPEC.md โ and you are not done until it has a success signal whose
proof Claude can show in chat.
Vague ask โ grill first
A spec is sharp enough when you can answer all five sections below without
guessing. If the ask is vague โ no clear deliverable, no notion of "done",
hand-waving at the success signal โ grill it before writing anything. Invoke
the grilling skill (the model-invocable form of /grill-me): interview the
user one question at a time, walking the design tree, until the deficiency and
the target are concrete. Explore the codebase to answer your own questions
wherever you can rather than asking.
Don't grill a spec that's already sharp. Two or three pointed questions can be
enough; a fully-specified ask needs none.
Find the source of truth first
Before any menu, ask the cheapest question there is: "Is there a file, ticket,
PR comment, or person that defines what 'done' means here?" One pointer often
reframes the whole deliverable โ a single file can turn "resolve this PR" into a
concrete change. Let the user hand you that source before you presume an answer
space.
The one thing that matters most
haul-goal (the next phase) needs a transcript-demonstrable success
signal โ because /goal's evaluator only reads the conversation, it can't run
tools. So you are not done until you have a check whose output Claude can show:
a test that exits 0, a benchmark number a script prints, a file count, a lint
result. "Better" or "working" without a number is not a signal โ push until it's
concrete.
Then probe whether it's headlessly demonstrable: can Claude run it and show the
output in a transcript? If the real artifact can't be (an Airflow DAG with no
local airflow, a service needing a live container), record the runnable
proxy โ a committed test that stands in for it (e.g. a static/AST check of the
DAG's task order) โ and prefer the proxy that doubles as a CI regression guard.
Note any live-MCP/container confirmation as belt-and-suspenders, but the proxy is
what the /goal signal rides on.
Two checks, not one โ the ratchet and the acceptance gate
Most real "done"s have two tiers, and conflating them is the most common way
a long-haul spec goes wrong. Separate them explicitly:
- Ratchet check โ cheap, headless, re-runnable every round. A unit suite, a
benchmark script, a lint. This is what the explore/exploit loop optimizes turn
after turn; it must be fast enough to run every round without thought.
- Acceptance gate โ expensive / external / one-shot. A prod job (SageMaker,
a deploy), an integration run against live infra, a manual sign-off. It can cost
hours and real money, so it cannot be re-run every round โ it's fired once,
late, after the ratchet is green and the incumbent is locked, and its output is
pasted into the transcript where it persists for the evaluator.
Pin both in the spec when they differ: which check is the per-round ratchet, and
which (if any) is the terminal acceptance gate, what it costs, how it's run, and
what pasted evidence proves it. If the only check is cheap and headless, say so โ
there's no gate, and the ratchet is the whole signal. If "done" requires the
expensive gate, haul-goal will structure /goal so the ratchet loops and the
gate is a one-time terminal proof โ but it can only do that if the spec names both.
The toolbox โ declare it in the spec
A long run drifts unless its means are bounded. The spec names the toolbox:
the specific skills and MCP servers this haul is allowed to reach for. Settle it
with the user now:
- Skills the haul may use (e.g.
/tdd, /review, check-voids-db).
- MCP servers it may touch (e.g.
voids-db, or none).
If a tool isn't in the toolbox, haul-loop doesn't reach for it.
Process
Explore the target first (read the file/module, recent commits, existing tests
or benchmarks). Verify any locations the source-of-truth cites โ an ADR,
ticket, or PR that names file.py:NNN, a function, or a flag has almost always
drifted; grep the current tree, confirm where the symbol actually lives, and
record the corrected refs in SPEC.md (note the original if it helps the haul
orient). A spec that sends the haul to a stale line number wastes its first
round. Then settle the sections โ but match the instrument to the question:
- Hard gate before the first
AskUserQuestion. Don't open a menu until (a) you've let the user point you at the source of truth, and (b) you've confirmed the deliverable is genuinely enumerable. If either is unmet, ask one open question in plain chat โ a menu presumes the answer space it's meant to discover. And read a rejected menu as a signal: when the user clarifies or rejects your tabs, the deliverable isn't pinned yet โ drop back to open grilling, don't reissue a reworded menu.
- Bounded choice โ
AskUserQuestion tabs. Once the deliverable is known and enumerable, settle the genuinely bounded sub-decisions (which repo, which layer, the threshold, the toolbox) with the tool: one question per call, 2โ4 concrete options as tabs grounded in your exploration (the user can pick Other to free-type).
Never dump the sections as a prose checklist.
- What are we building or changing? The specific deliverable; locate it โ which repo (
target_repo, which may not be cwd), then which file/module/endpoint/behavior.
- What does "done" look like? The success signal โ measurable and transcript-demonstrable, with the runnable proxy if the real artifact isn't headlessly verifiable. Name the ratchet check (cheap, every round) and the acceptance gate (expensive/external/once) separately when they differ. Be stubborn here.
- The toolbox โ which skills + MCP the haul may use (above).
- Constraints โ what must hold throughout (public API, deps, behavior other code relies on).
- Out of scope โ guard against scope creep over a long run; YAGNI.
If the ask bundles several independent deliverables, say so and pick one to haul
now; the rest are separate runs.
Output
Write .longhaul/SPEC.md using the template in
../long-haul/reference/file-formats.md.
Show the user a 5-line recap (deliverable ยท success signal ยท toolbox ยท key
constraint ยท out-of-scope) and confirm it's right. Advance PHASE: goal.
If invoked standalone (not by the orchestrator), end by suggesting:
"Next: haul-goal to turn this into a /goal condition."
Don't
- Don't prescribe the implementation here โ how is the haul's job. Stay on what and how we'll know.
- Don't accept an unmeasurable success signal. If you can't make it transcript-demonstrable, say so explicitly in SPEC.md so haul-goal can flag it.
- Don't leave the toolbox open-ended ("any tool") โ an unbounded long run is exactly the drift the toolbox bounds.