# Run record `runbook-run/v0.1` One run of one native pack, stored as JSON in `/.local/runbook-runs/.json` (git-ignored). Non-secret only. | Field | Meaning | | --- | --- | | `run_id` | Timestamp plus random suffix | | `pack_id`, `pack_path` | The pack run | | `operator` | One word: the person who ran it | | `params` | Resolved parameter values (validated, never secret) | | `steps..state` | `todo`, `running`, `done`, `failed`, `skipped` | | `steps..verification` | `kind`, `passed`, and for commands `exit_code`, `output_bytes`, `seconds`. Output text is never stored | | `steps..evidence` | The facts the step declared, supplied by the operator | ## Rules - Steps run in order; a step starts only after its predecessors are done or skipped. - A step completes only with a passing verification and its declared evidence. - A verify command runs only when the operator confirms (`--yes`), with a 60 s timeout. - Only read-only steps may be skipped, and a run with skips never exercises a pack. - Values matching the secret markers are refused everywhere they could be recorded. - The engine never edits `pack.yaml`. `rtut run finish` shows the exercise-status diff; `--apply` writes it, and only for a run in which every step is done. CLI: `rtut run new|list|status|cmd|start|verify|done|fail|retry|skip|finish ...` ## Outcome, score and exercise status A run is unfinished (**stalled**) until finalized. `rtut run finalize` (or the UI's *Close this run*) records an `outcome`: | Outcome | Rule | | --- | --- | | `succeeded` | every step is `done` (skipped steps do not count) | | `failed` | at least one step has failed; otherwise abandon | | `abandoned` | any time. An unfinished run untouched for 7 days also counts as abandoned in the score | A finished run is read-only, except for feedback. The **score** of a runbook is derived from its run records: tried, succeeded, failed, abandoned, stalled (unfinished), plus a tally of feedback ratings (`rtut score `; shown in the UI). Run records live in `.local/` of the machine that ran them, so the score is per machine until run histories are shared. Finalizing never edits the pack by itself. For a `succeeded` run the UI offers **Record pack as exercised**, which shows what will be written, and on click sets `exercise_status: exercised by ` in `pack.yaml` (`rtut run finalize ... --outcome succeeded --apply` does the same). The change is an ordinary edit in the owning repository, to be reviewed and committed there. ## Feedback `feedback` entries (`rating` good|neutral|poor, `comment`, `at`) are added after a run; history is kept and the latest counts. `rtut feedback ` lists them. ## Captures A step may carry optional `captures`: the command actually run, and the output that came back, as documentation or for inspection when the engine cannot reach the system itself. Limits: 20 000 characters of output, 2 000 of command. Obvious secret markers are refused; the engine cannot detect every secret, so the operator stays responsible. For `output-contains` steps the output can be **pasted for verification** (`source: pasted-for-verification`), which checks the `contains` text without running anything. Exit-code checks cannot be verified from pasted output. ## Run record `runbook-run/v0.2` (packs of `runbook-pack/v0.2`) Implemented in `rtut/run2.py` (graph in `rtut/flow.py`). It adds to the v0.1 record: | Field | Meaning | | --- | --- | | `mode` | `manual` or `auto-confirm` | | `datapoints.` | `state` nil, set, err, ok or pushed; `value`, `how` (initial, manual, produced, check, manual confirmation), `error` | | `steps.` | as v0.1 (`pushed` is an additional state), plus `alternative` (chosen `one_of` branch), `authorized_by` | | `gates.` | `state` open, passed, failed, waived or pushed; per-check `results`; `waiver` or `pushed` | | `deviations[]` | every override, waiver and push-through (see `docs/pack-spec-v0.2.md`) | | `auto-confirm` | `preauthorized` irreversible steps, `authorized_by`, and `stopped` if a timeout stopped the run | Rules the engine enforces: - **Preconditions** of an item are its `requires` (and those of enclosing stages), the `set`/`ok` state of the datapoints it `uses`, and, for a gate, completion of the steps of its stage. - **Recommended next action**: the running item first, else the first ready item in the pack's canonical order. `next_actions(run)` returns the recommended item, all ready items (parallel work) and the blocked ones with what they wait for. - **Alternatives**: a `one_of` step is started with an alternative (default: the first whose `recommended_when` matches the datapoints). - **Datapoints**: invalid input leaves the datapoint `err` and is never stored; a step's `produces` become `set` when it completes; `confirmed_by` promotes them to `ok` when that step or gate passes. - **Override** (manual mode only): starting an item with unmet preconditions needs a reason and an acknowledged downstream risk; it is recorded as a deviation. - **Waiver**: only for gates that declare `waivable`, with a reason; recorded as a deviation. - **Confirmation**: irreversible steps need the exact confirmation phrase at start. In auto-confirm they run only if the run pre-authorized them, and never if the step is `auto_confirm: manual-only`. - **Auto-confirm** (`auto-confirm_tick`): the engine applies confirmation when preconditions are met: it starts the recommended item, runs its checks (manual checks are auto-confirmed and marked so) and completes it. It never runs a step's own command; the work is done by the operator or, later, by opt-in execution. A step with `evidence` waits for the operator. If checks keep failing until the item's `timeout` (or the pack default), the run stops, or with `on_timeout: push-through` the item is marked done with state `pushed` and a deviation is recorded. - **Deviations and exercise**: a run with any deviation or pushed-through step can be finalized but never exercises a pack. `finalize(succeeded)` also needs every gate passed or waived. - **Pushed is its own state.** A step, gate or datapoint passed over by push-through is `pushed`: not `done`, not `set`, not `err`. Dependents may proceed (that is the point of pushing through), but a pushed datapoint has no value, so a command that needs it fails its check instead of running with nothing. A run with pushed items can be finished as `failed` (never `succeeded`) and never exercises a pack. - **Stalled**: an unfinished run is counted as `stalled` in the score, and as `abandoned` after a week. - **Modes** are `manual` and `auto-confirm`. Auto-confirm applies confirmation only; running the step's own command is a separate, later level ("auto-pilot with execution", RBT-WP-0006).