# Mature a hank and version its evidence A hank–a workflow of agent tasks–usually starts out fragile: the prompts carry assumptions only the author knew, the models are whatever worked first, and nobody can say why a particular rule exists. Every run, though, leaves evidence behind–logs, files, outputs, and the places where things succeeded or failed. This page is about using that evidence deliberately. We will let a complete run teach us what to change, remove assumptions from prompts, compare model changes on fresh state, preserve the constraints that earned their place, and version the inputs and accepted outputs alongside the hank itself. The goal is a hank that the next person can run, trust, and improve without rediscovering what you already learned. Before you begin, put the hank, prompt files, and input data under version control, and commit accepted expected artifacts as the run produces them. Keep the execution directory separate from the source project so that run artifacts can be compared without changing the inputs. ## Learn from the first complete run Improvement starts with a run you actually watched to the end. Do not improve a run you stopped before it finished: a partial run tells you where it broke, but not whether the rest of the hank works. Let the run complete, then read the hank and its prompts and inspect the execution directory. Start your review with these questions: 1. **Did we actually look at it?** Record what the run left before proposing a change. 2. **What was re-derived?** Turn deterministic (repeatable) setup into commands, copy required files into the workspace, precompile context where appropriate, and provide scripts the agent would otherwise have to write. Put that setup in a rig–a setup that runs before a codon–when it can be derived reliably. 3. **Are the codons shaped well?** Keep one clear job per codon–an agent task–make prompts self-contained, use `fresh` when a new session is intended, and pass work through files. Put greenfield implementation in a coding-agent phase before asking later codons to refine it. 4. **What could be a feature rather than a hope?** Ask whether a loop would improve reliability, a sentinel (a rule that watches run events) would catch a failure earlier, a context bridge would shorten a handoff, a codon needs a different model, or archiving would help. Treat these as questions to test, not prescriptions. 5. **Would a budget stop the codon with usable work?** Use measured cost to choose a margin. For the anchor workflow, twice the cost of a stable run is a useful starting point, not a guarantee. When Hankweave detects an exceeded budget, it requests interruption of the active model. `onExceeded` then decides how to record the interrupted codon; it does not give the model time to finish. Choose `"complete"` only when partial artifacts are acceptable and you check them explicitly. Choose `"fail"` when unfinished output cannot be trusted. See [budget behavior](/concepts/budgets) for the full contract. The bundled `anchor-hank` shows what this review looks like in practice. It is the `quote-template-unification` workflow: it normalizes eight suppliers across three digitizer dialects and reconciles 40 supplier-part rows. Its first full run was estimated for three suppliers but exercised eight; two hard caps tripped at $1.05 against the $1.00 cap and $0.51 against the $0.50 cap. Those figures are a recorded lesson, not a price forecast. Four live iterations then exposed the execution-path, corpus-shape, budget, and hazard-rule lessons before the final artifacts matched 40 supplier-part rows and the eight planted exception classes. Compare the artifacts that matter to your task, not merely a success status. **Check it.** A completed run has a `RunCompleted` transition, and you can name one observed break and the artifact or prompt responsible for it. The captured run below shows that completion shape–a `codon.completed` event followed by the `RunCompleted` transition. The lesson is to inspect the files the run leaves, not to infer quality from completion alone. ```text {"id": "", "timestamp": "", "type": "codon.completed", "data": {"codonId": "summarize-notes", "success": true, "cost":"", "duration":"", "exitStatus": {"type": "success"}}} {"id": "", "timestamp": "", "type": "state.transition", "data": {"transitionType": "RunCompleted", "runId": "", "transition": {"type": "RunCompleted", "data": {"runId": ""}}, "resultingState": {"currentRunId": null, "runCount": 1, "totalCost":"", "currentRunCost":""}}} ``` ## Find the context gaps your prompt assumes away A “vibed” hank is one assembled from conversation whose author silently supplies missing context. The prompts read fine to the person who wrote them, because that person already knows the conventions, the file layout, and the decision rules. The model does not. Read the hank with fresh eyes, and for each codon mark: * terms that are used but never defined; * files that are named but may not exist in the execution workspace; * domain conventions the prompt assumes you know; and * instructions that assume the agent already knows an API, format, or decision rule. Replace each gap with explicit context in the prompt, a system prompt, or a file the agent can read. We have information the model does not, and a missing API choice or convention can look like a mysterious failure later. Making that information available gives the agent a fairer chance to do the work we intended. Do not fill a gap with a broad instruction such as “use your judgment.” Name the input, the convention, and the expected handoff. Keep the gap list beside the prompt while you make the edits, then rerun the same task and check the resulting artifacts for the failure you were addressing. **Check it.** Every item in your list names the missing term, file, or assumption and points to the prompt, system context, or handoff file that fills it. If you cannot point to that edit, the gap is still open. For prompt ownership and handoff design, see [designing codons and handoffs](/author/designing-codons-and-handoffs). ## Downshift models without breaking the hank Once prompts are sharp and regression checks exist, model cost becomes the next lever. The intended maturity curve is deliberate: use a frontier model for an early run, then test a cheaper model as the hank stabilizes; never make the change automatic. A cheap-model rehearsal belongs to [testing and hardening](/author/testing-and-hardening), where the question is first whether the run can complete with its files, handoffs, and rigs intact. ### Know which model name you are changing Before editing anything, be sure which name you are actually changing. In a Hankweave model string, `pi/` identifies the embedded Pi routing layer; for example, `pi/baseten/deepseek-ai/DeepSeek-V4-Pro` is the Baseten/DeepSeek catalog route to the `DeepSeek-V4-Pro` model. A registry shortcut such as `haiku` is resolved by Hankweave's model registry; the harness is the in-process agent runner that executes the resolved model. See [model resolution](/reference/model-resolution) for the supported catalog rather than treating a recorded internal model name as a universal shortcut. The current anchor hank shows a task split by judgment density: `normalize-aster`, `normalize-beacon`, `normalize-cedar`, `survey-and-extracts`, and `award-brief` use `haiku`, while `validate-and-repair` and `reconcile` use `pi/baseten/deepseek-ai/DeepSeek-V4-Pro`. Mechanical work is cheaper to replace than judgment about aliases, exceptions, and reconciliation. Choose by the cost of a wrong decision, not by codon position. The capture manifest below records one complete execution of that split. Note the fields it pins down–the runtime version, the complete-codon count, the tracked cost, and the input scope–because those are exactly what you need when comparing a candidate run against this baseline later. ```text # Capture manifest - Captured: 2026-09-06T13:07:23.154353+00:00 · runtime: hankweave@0.10.0 - actual_service_output: true - Scope: one complete live execution - Raw execution (path normalized): ~/.hankweave-executions/anchor/1788699352631-qoit-40a58f - Complete codons: 7/7 - Tracked codon cost: $0.88303367 (provider health checks and sentinel calls are separate) ``` ### Compare fresh executions 1. Keep the baseline hank and its prepared data unchanged. Run it in one named execution directory. 2. Change only the candidate codon `model` fields in a working copy of `hank.json`. 3. Run the candidate in a second named execution directory with the same prepared data. 4. Diff checkpointed files, final outputs, exception handling, and the regression assertions. Promote a cheaper model only when the judgment artifacts remain acceptable. The `--model ` option overrides every codon's model for one invocation. It is useful for a rehearsal, not for recording the durable assignment. A durable downshift is an edit to the codon `model` fields followed by a fresh run: a resumed execution keeps its persisted resolved models, so editing the hank or adding `--model` does not re-plan a failed codon. Use explicit paths for both arms: ```sh bunx hankweave@0.10.0 hank.json data/ -e ./runs/baseline --start-new --force bunx hankweave@0.10.0 hank.json data/ -e ./runs/candidate --start-new --force ``` `-e` creates or selects the named execution directory; with `--start-new --force` an existing managed execution is backed up and its old `agentRoot/` is wiped before the fresh run. Add `--no-wipe` only when you intentionally staged verified handoff files in that execution's `agentRoot/` and need to preserve them. Without `--start-new`, an execution with recorded state resumes instead of comparing fresh plans. For an interactive step-by-step run, add `--no-autostart` and press `n` to advance to the next codon. The anchor's re-proven capture assigns the models above and records $0.88303367 of tracked codon cost for one complete execution. Provider health checks and sentinel calls are separate, so this is not a total billing promise. The earlier approximately $2.41 figure belongs to the original Sonnet run and is historical comparison data, not the current anchor cost. A cheap model can fail structurally while reporting success: a recorded one-codon run sealed an empty checkpoint without writing its required file. Make incremental writes and self-verification explicit in the prompt. A judgment failure looks different: the run completes but validated records or exceptions degrade; use the maturity exercise in [tutorial chapter 5](/tutorial/5-break-resume-inspect) for that worked comparison rather than treating a completion event as proof. Here, “the forge” means this documentation project's own recorded internal runs; its dated ladder illustrates evidence-based promotion and demotion. On 2026-09-01, `deepseek-v4-flash` was kept for mechanical work and `glm-5.3` for briefs and reviews; the same day's long-context probe demoted `deepseek-v4-flash` to `DeepSeek-V4-Pro` for that task class. On 2026-09-02, a three-arm comparison returned 5/5 first-review passes for DeepSeek-V4-Pro, 3 passes and 2 repairs for Kimi-K3, and 0 passes and 5 repairs for glm-5.3. The arms were not difficulty-matched, so those results are directional. The resulting forge policy rejected Sonnet-named hanks; that is a recorded local constraint, not a Hankweave default. > **Pitfall** – At 0.10.0, `pi/zai/*` codons report cost 0 in `codon.completed`, and retries can emit that event more than once. Dedupe cost records by codon ID and distrust Zai dollar totals before using them in a downshift decision. See [authentication and models](/operate/authentication-and-models) for provider concerns. **Check it.** The baseline and candidate directories sit side by side, each with its own artifacts, and your comparison records which outputs changed. Do not call a model cheaper or safer from a resumed execution: that execution preserves its resolved plan. ## Version the whole corpus together A hank is more than its program file. Commit the hank from the first useful run and commit every iteration: prompt edits, codon splits, rig additions, fixture changes, and accepted-output changes. A hank version describes the whole corpus, not only the program file. Keep `meta.name` and `meta.version` in `hank.json`; `$schema` identifies the published schema for editor support. | field | type | default | required | constraints | description | | --------- | -------- | ------- | -------- | ----------- | ---------------------------------------- | | `meta` | `object` | | no | | Metadata for sharing/indexing (optional) | | `$schema` | `string` | | no | | JSON Schema URL for editor support | The same rule applies to runtime compatibility. The project's `docs.lock.json` is a compact example: one lock records the runtime version, npm tarball hash, public tag and commit, schema hashes, and behavior surfaces such as the help hash and initialized codon list. On upgrade, read the changelog, snapshot representative inputs and accepted outputs, validate the configuration, run deterministic checks plus a small stochastic sample, compare costs and artifacts, stage the rollout, and keep rollback available. See [upgrading](/start/upgrading) for release-specific breaking changes. Treat expected output as captured evidence, not a promise. The corpus manifest records the generator, checker, data class, and hashes for its files: ```json { "corpus": "quote-template-unification", "spec_version": "corpus-spec.md (merged sol-1/glm-5.3/fable-1, quote-template-unification)", "license": "CC0-1.0", … "generator": "generator/gen-corpus.ts", … "checker": "generator/check-invariants.ts", "entries": [ { "path": "digitized-extracts/aster-quote-qb-1047_rev2.json", "sha256": "4b28baf001186ecaaf9a395f917d90ab7d66a4edda2227a5fe57f019073cf8c6", "media_type": "application/json", "data_class": "synthetic" } ] } ``` A deterministic regeneration should reproduce those hashes byte-for-byte; the manifest is written after the hash walk so it does not hash itself. Captured transcripts are different from a promise: the minimal fixture records a capture date and runtime version, and its documentation output is regenerated from the fixture directory. Do not promise bitwise equality across runtime or model versions. Regression checks should compare behavior, control flow, and artifacts; model output is stochastic. Keep model versions pinned where possible, keep prompts minimal, test after provider updates, and roll out gradually. Codon boundaries make it easier to identify which task changed behavior. Capture manifests also record the runtime, scope, normalized execution path, complete-codon count, tracked cost, and input scope; the anchor capture records 7/7 codons and $0.88303367, while the minimal capture records 1/1 and $0.01394590. **Check it.** Regenerate the corpus and compare its manifest hashes; then verify that each expected transcript carries a capture date and runtime version. A capture manifest must describe one complete live execution and its input scope, not stand in for an oracle result. ## Preserve ugly constraints and their reasons Mature hanks accumulate rules that look arbitrary: a quarantine step, a special case for one supplier, a comment warning against an obvious simplification. Preservation is the default while evidence is missing, not a ban on cleanup. Before changing an inherited hank: 1. read the hank and prompt comments; 2. inspect artifacts from the last successful and failing runs; 3. identify the incident or reason behind the constraint; 4. add or locate a regression case; and 5. change the constraint and compare the result. Put the reason where the constraint lives. Use a rationale comment in the prompt or a design-notes file beside the hank. Hankweave strips HTML comments before sending prompt content to the model, so an HTML rationale can remain available to maintainers without adding tokens to the model's prompt. The anchor records the reason for each codon-boundary decision in a design-notes file beside its hank. The anchor's four hazard rules show why a short constraint can be valuable: quarantine low-confidence records, repair and log page splits, route handwriting to notes, and silently repair prefix splits. Its exception ledger routes eight classes–`EXPIRED_VALIDITY`, `NO_BID`, `DEDUP_CONFLICT`, `PAGE_SPLIT_LINE`, `UNKNOWN_TEMPLATE`, `UNRESOLVED_PRICE`, `LOW_CONFIDENCE`, and `NOTE_ROUTED`–to resolutions. Preserve such rules until a regression case shows that the replacement keeps the same safety boundary. The `exhaustWithPrompt` removal is a useful negative example. In 0.10.0, a provider 429 and an idle timeout during an extension caused the run to fail even though the codon had already sealed. The forge removed that extension from production hanks at v0.1.3. The reason and the upstream design question were recorded, and both incidents remain retrievable as execution records, so a runtime fix can reopen the decision on evidence. The extension mechanics themselves belong in [codon concepts](/concepts/codons); turn any repair into a regression fixture in [testing and hardening](/author/testing-and-hardening). **Check it.** For each surviving awkward rule, you can retrieve its reason from the prompt comment or design notes and point to a regression case or observed failure. If you cannot, preserve the rule and investigate before cleaning it up. ## Turn repeated runs into an appliance A supervised, latency-sensitive run is necessary when you build fresh each time. As preferences, special cases, and fixes accumulate in prompts, rigs, and fixtures, the same task can become cheaper and more reliable to run offline–overnight, locally, or on a low-cost model. The hank is the place where the local operating procedure accumulates; the useful offline agent is the one that already knows that procedure, not necessarily the most capable model. See the [online/offline explanation](https://www.southbridge.ai/blog/no-country-for-old-code) for the distinction. For unattended operation, see [headless operation](/operate/runbook), [budgets](/concepts/budgets), and [sentinels](/reference/sentinel-config). Before handing the hank over, ask whether someone else can run it with the same prepared inputs without rediscovering the fixes. The minimal fixture supplies a pinned command and observable completion shape: ```sh bunx hankweave@0.10.0 hank.json data/ --validate # schema and paths only; no provider health check bunx hankweave@0.10.0 hank.json data/ --headless --start-new -o out ``` The fixture's complete run records a `codon.completed` event with `exitStatus` `success`, followed by a `RunCompleted` transition; its captured transcript's last runtime output is “Listening on”, after which the capture appends its own `exit=0` trailer. That is evidence that an unattended run completed, not evidence that every task is correct. Keep the output where a handoff can inspect it, and make the next operator's command and inputs explicit. **Check it.** Run the pinned command without watching the process and verify the completion event and the output artifact. The handover passes when another operator can repeat it from the versioned hank, prepared data, and documented model assignments.