# Follow a task guide A question gets one answer. A typical task — an import dossier, an insurance payout, a measurement uncertainty report — is many questions in the right order, facts from a person between them, and a document at the end. The canon's author publishes that order next to the package as a task guide: which case to pin, which facts to collect, which question cards to ask, where to go on every answer status, and which answers fill which fields of the document. A guide carries no formula, rate or threshold; those stay in the canon, and walking the guide computes nothing by itself. The Guide page [A typical task along a canon's route](/guide/task-guides/) covers discovery; this page covers the walk. The reusable instruction set for an agent that applies a canon by task guides is the `apply-canon` skill, shipped in the examples bundle as [examples/instructions/apply-canon/SKILL.md](/agent-engineering/files/instructions/apply-canon/SKILL.md). It encodes the same contract as this page — no semantics in the agent, a human-named date of law, a stop is not an answer, every document value copied from an answer with its source — so an agent can load it instead of re-deriving the rules from prose. The worked example is the uncertainty-report route, version 0.1.0, of `jcgm.gum` — the Guide to the Expression of Uncertainty in Measurement. It is a scientific methodology, not state law: it standardizes how a measurement result is reported, and nothing here is a legal duty. Route listing (ran locally, `law guide`): ```text Task routes of jcgm.gum — corpus/laws/org/jcgm/gum/analysis/task-guides.json (sha256:d6a5197969966402f585c76a97d7bb7610811d9d8b3da227729acbbeb1db774b) jcgm.gum/uncertainty-report v0.1.0 — Отчёт о неопределённости измерения по GUM: бюджет, степени свободы, расширенная неопределённость и запись результата (25 steps, 13 questions, 6 witness paths) ``` ## The mechanism in four moves Every task guide repeats four moves. Real step names from the route: 1. **Pin and collect.** Fix the case and its date of law, then present the facts the case already holds (`pin-case`, `collect-model`). 2. **Ask a question.** Run the step's question and attach the answer to the journal (`ask-input-count` returns 2: two inputs). 3. **Follow the branch the answer chose.** The route names the next step for every answer status. Here the combined uncertainty derives nothing (`ask-combined` returns an empty answer), so the route sends the agent to a diagnostic step instead of guessing a value (`ask-contribution-count` returns 1: only one input contributes). 4. **Fill part of the document.** An assembly step copies recorded answers into named fields with their sources; a field with no answer stays visibly open (`assemble-budget` shows the combined uncertainty as open, not as zero). The route opens with pinning, continues through collection steps (model, input evaluations, coverage data), question steps (input count, variances, contributions, combined uncertainty, degrees of freedom, coverage factor, expanded uncertainty, report completeness) and closes with assembly steps (case, presented data, budget, coverage, result, boundaries, free fields). ## Branches follow status, never invented values Each step names its cards; the agent asks them in order and follows the handler of each outcome. The route's witness paths pin the expected per-step outcomes for replay. Excerpt, shortened (ran locally, `law guide … --witnesses`): ```text k-chosen: ask-combined single ← scenario "urn:query:gum-route-k-chosen" ask-dof empty ← scenario "urn:query:gum-route-k-chosen" ask-dof-infinite NEITHER ← scenario "urn:query:gum-route-k-chosen" ask-report-complete TRUE_ONLY ← scenario "urn:query:gum-route-k-chosen" ``` An outcome of `empty` or `NEITHER` on a witness path is part of the contract, not a failure: the route says what comes next. How to read each status is the single table in [Read answers](/agent-engineering/handle-answers/). ## A complete pass on the incomplete-input branch Status: ran locally (`law 0.1.1`, local CLI from a full checkout; see the Validation record). The pass walks the route against the case `VkhodBezOtsenki` ("input without evaluation") of the worked-example project `otchet-neopredelennosti` (package `examples.jcgm_gum.otchet_neopredelennosti`): two inputs, only the first evaluated, so the combined uncertainty stays silent and the route takes the diagnostic branch. The journal and the answers live in scratch; the project is only read. `$GUM` below is the directory of the `jcgm.gum` package, `$PROJECT` a scratch copy of the worked-example project. Start the journal with a date of law named by a person: ```bash law guide journal new $GUM jcgm.gum/uncertainty-report \ --legal-time 2026-09-06 --out $SCRATCH/journal.json # journal $SCRATCH/journal.json started: route jcgm.gum/uncertainty-report # v0.1.0 (sha256:d6a51979…), legal time 2026-09-06; first step — pin-case ``` Pin the case and present only what it holds: ```bash law guide journal add $SCRATCH/journal.json --step pin-case \ --bind 'result=urn:example:gum:r' # entry 1: step pin-case (case) — next step collect-model law guide journal add $SCRATCH/journal.json --step collect-model \ --bind 'input=urn:example:gum:x1' --bind 'input=urn:example:gum:x2' \ --present jcgm.gum::input_of --present jcgm.gum::result_unit \ --present jcgm.gum::result_estimate --present jcgm.gum::uncertainty_precision \ --present jcgm.gum::input_unit --present jcgm.gum::unit_sensitivity \ --present jcgm.gum::inputs_uncorrelated # entry 2: step collect-model (collect) — next step collect-evaluations law guide journal add $SCRATCH/journal.json --step collect-evaluations \ --present jcgm.gum::quoted_uncertainty_as_multiple # entry 3: step collect-evaluations (collect) — next step ask-input-count ``` No sensitivity coefficients, no correlated inputs, no Type B degrees of freedom are presented: the case does not hold them. Then each ask step gets one `law ask --out` answer attached to the journal. Observed outcomes (every answer `COMPUTED`, no issues): | Step | Saved query | Outcome | |---|---|---| | ask-input-count | chislo-vkhodov | single: 2 | | ask-input-variance | dispersiya-x1, dispersiya-x2 | single: 144/1; empty | | ask-input-contribution | vklad-x1, vklad-x2 | single: 144/1; empty | | ask-combined | summarnaya | empty | | ask-contribution-count | chislo-vkladov | single: 1 | ```bash law ask $PROJECT --case VkhodBezOtsenki --query-json $PROJECT/queries/chislo-vkhodov.json \ --out $SCRATCH/answers/chislo-vkhodov law guide journal add $SCRATCH/journal.json --step ask-input-count \ --answer $SCRATCH/answers/chislo-vkhodov # entry 4: step ask-input-count (ask) — next step ask-input-variance # … entries 5–8 attach the remaining answers; entry 8 ends at request-free-fields ``` ### Observed gap: route cards missing from the catalog The `next` command prints ready commands with `--card input-count`, but that card does not exist: `ask --card: card "input-count" not found`. The route's ask steps name cards (`jcgm.gum/input-count`, `jcgm.gum/standard-variance-value`, …) that are absent from the package's question catalog (12 entries, none matching). The pass therefore attaches saved-query answers, which the journal accepts. Aligning the route with the catalog is package work for the route owner. Until then the card path is NOT RUN (reason: cards absent; reproduction: `law guide journal next` on the journal above, then the printed `--card` command), and the saved-query path is the repeatable one. ### Human decision and assembly The human fills the report's free fields; the seven assembly steps close the walk: ```bash law guide journal add $SCRATCH/journal.json --step request-free-fields \ --set 'free/compiled-by=Lab N-7, R. Jumagulov' \ --set 'free/instrument=voltmeter V7-28' # entry 9: step request-free-fields (decision) — next step assemble-case law guide journal add $SCRATCH/journal.json --step assemble-case # … through assemble-free # entry 16: step assemble-free (section) — walkthrough complete; document open fields 15 ``` Check, then check with replay — both return the same line: ```text journal $SCRATCH/journal.json matches route jcgm.gum/uncertainty-report: 16 entries, walkthrough complete; document open fields 15 ``` The rendered document builds every section from recorded entries. Budget section excerpt: ```text ## Бюджет: суммарная неопределённость | Число входов | 2 | entry 4, step ask-input-count, resultHash sha256:5258… | | Дисперсия u²(xi) каждого входа | urn:example:gum:x1: 144/1; urn:example:gum:x2: open (empty collection — no value derived, this is not zero) | entry 5, … | | Вклад ui²(y) каждого входа | urn:example:gum:x1: 144/1; urn:example:gum:x2: open (empty collection — no value derived, this is not zero) | entry 6, … | | Суммарная стандартная неопределённость uc(y) | open: empty collection — no value derived, this is not zero | entry 7, … | | Число входов с вкладом | 1 | entry 8, step ask-contribution-count, … | ``` Unasked branches render as `open: question not asked on this path`; the boundaries section lists the route's six boundaries; the free fields carry the human's values with their entry as source. ## The full branch stopped on TYPE_ERROR Status: ran locally (`law ask` with the saved combined-uncertainty query against the k-chosen case). An attempt at the k-chosen branch stopped at the combined-uncertainty question: `evaluationStatus TYPE_ERROR`, because `sqrt_bounds` received a `Number` where the engine expects Integer, Decimal or Rational. That stop is a package/engine type mismatch to be resolved outside the route mechanism, not proof that the route is broken: the incomplete-input branch above walks from the first step to a checked, rendered document. A journal holding a type-error record cannot honestly check clean, so the k-chosen full pass stays untaken until the mismatch is fixed. The agent's correct behavior at such a stop is the same as at any non-`COMPUTED` status: stop the branch, report the status and its message, and invent nothing. ## Human decisions Two steps belong to a person: naming the coverage factor with its conditions, and filling the report's free fields. The journal also starts with a human act — the date of law is named by a person and never defaulted to today; that is a contract obligation of the agent, not advice. The agent stops at these steps, presents what is known, and resumes when the person answers. The route does not choose a disputed reading and does not judge for an authority; where those arise, the rules of [Human decisions, interpretations and scenarios](/agent-engineering/decisions-and-scenarios/) apply. ## Document assembly and open fields Each assembly step builds one section from earlier journal entries: values flow from recorded answers into named fields with their sources. A field with no source stays open; the document shows it as unfilled rather than inventing content. The boundaries section is assembled last, so the reader sees what the report does not claim. ## What "completed" means A completed walkthrough means the selected path was finished: every step on the taken branch visited, the decision recorded at each fork, every section assembled from recorded entries. It does not mean every branch was taken — the pass above completes 16 entries on a 25-step route — and it does not mean the grounds are sufficient: a completed report can still rest on sparse inputs, open fields and silent questions. Sufficiency is a human assessment of the assembled document, not a property of the walk. ## Journal commands The walkthrough journal is a file maintained by `law guide journal`: - `new` starts a journal: pins the route, the catalog-bytes hash and the human-named date of law. - `add` records the next step; an answer is a `law ask … --out` directory, and a document section assembles itself from earlier entries. - `check` verifies the journal against the route, attached answers and sections; `--replay` replays each answer with `law eval`. - `next` shows the coming step with case data and ready commands; `run` walks questions and sections in order and stops at case, collection or human-decision steps. - `render` produces the walkthrough document: sections, values and their sources. Over MCP the same routes are offered as the server's prompts (`prompts/list` names them, `prompts/get` returns the frame with ready `law_ask` calls). Getting a prompt executes nothing and accepts no facts. Status: NOT RUN — the session's MCP server was unreachable; confirm through the server's own prompts listing before scripting against it. ## How to verify List the routes and their witnesses: `law guide` with the package directory, then with the route id and `--witnesses`; `law guide journal --help` for the subcommands. Reproduce the pass on a scratch journal: `new` with date of law 2026-09-06, the three pin/collect records, one `law ask --out` per saved query in the table with `add --answer`, the decision record with two `--set` fields, the seven assembly records, then `check`, `check --replay` and `render`. Reproduce the k-chosen stop with `law ask` and the saved combined-uncertainty query against the k-chosen case. Inputs: a pinned copy of the worked-example project with its queries, cases and vendored dependencies, described in [examples/task-guides/README.md](/agent-engineering/files/task-guides/README.md). The pass needs the `law` CLI from a full checkout; the bundle alone is not enough. ## Validation record | Checked | Result | Version | |---|---|---| | Route listing and route detail with witnesses | as quoted | `law 0.1.1`, `law.core/0.2`, 2026-10-04 | | Journal `new/add/next/check/check --replay/render`, 16-entry pass | check line as quoted | same | | Seven saved-query asks with `--out` | outcomes in the table | same | | k-chosen combined-uncertainty ask | `TYPE_ERROR` (`sqrt_bounds`) | same | | `--card input-count` | `card "input-count" not found` | same | | MCP prompts and route catalog | NOT RUN (server unreachable) | — | Previous: [Human decisions, interpretations and scenarios](/agent-engineering/decisions-and-scenarios/) Next: [Cases and processes](/agent-engineering/case-lifecycle/)