Skip to content

Structure

A writ is a YAML file. This page gives each field of the file.

writ: bug-fixer
holder: default
mandate: "The failing test {failing_test} passes without breaking other tests."
grants:
- read: { paths: ["**/*"] }
- shell: { commands: ["pytest *", "git diff"] }
- edit: { paths: ["src/**"] }
- open_pr: { requires: assent }
bounds:
iterations: 40
cost: $2.50
wall_clock: 20m
edits: { max_files: 5, max_changed_lines: 200 }
invariants:
- { layer: letter, no_edits_outside: ["src/**"] }
- { layer: judgment, clause: "Changes stay minimal.", checkpoint: each_edit }
obligations:
- { on: satisfaction, require: { run: "pytest -x -q", exit: 0 } }
satisfaction:
all:
- { layer: letter, run: "pytest {failing_test} -x -q", exit: 0 }
- { layer: judgment, clause: "The diff addresses the cause, not the symptom." }
remedies:
on_bound_breach: { do: halt, inform: issuer }
on_invariant_breach: { do: inform, inform: holder, strikes: 3 }
Field Necessary Purpose
writ Yes The name of the writ.
mandate Yes The goal, as a condition on the world.
grants Yes The actions that the agent can do.
holder No The name of the holder in the engagement configuration.
bounds No The quantity that the agent can spend.
invariants No The conditions that must stay true during the run.
obligations No The checks that must pass before satisfaction.
satisfaction No The proof that the work is complete.
remedies No The response to a breach.

A writ file must contain writ, mandate, and grants. A writ file must not contain other fields, because the schema refuses an unknown field.

The name of the writ. The record uses this name, and the writ review command uses this name.

The name must start with a lowercase letter. After the first letter, the name can contain lowercase letters, numbers, and single hyphens.

writ: bug-fixer

The name of the holder in the engagement configuration. The default value is default.

holder: default

If you do not write a bound, the writ is authored-unbounded for that value. The omitted value is not a clause.

The managed writ issue adapter adds these operational limits to its model loop when the writ omits them:

Bound Managed operational default
bounds.iterations 25
bounds.cost $1.00
bounds.wall_clock 15m

These values do not become authored clauses. There is no managed default for bounds.edits.

Use --explain to see the authored terms:

Terminal window
writ check bug-fixer.yaml --explain

Use writ plan to check whether one adapter can enforce each authored term.

Do not put secrets in a writ document. An attached activation stores the bound document in Writ state.

The schema accepts these four fields, but this runtime cannot run a writ that contains them:

  • issued_by
  • requires
  • yields
  • holder_must

These fields belong to delegation, which is the procedure that lets a writ issue a weaker writ. Delegation ships in version 2.

The writ check command gives a warning for these fields. The writ issue command stops with an error.

The schema is https://writ.build/schema/writ-v0.schema.json. To get editor completion and editor validation, name the schema in the file:

$schema: https://writ.build/schema/writ-v0.schema.json
writ: bug-fixer

The writ check command validates the file against the same schema. The command needs no network connection.