litany 0.0.6

A git-backed agent harness
Documentation
events:
  user_message:
    - dispatch(worker)
  worker_return:
    - deliver_result
  worker_flush:
    - dispatch(compactor)
  compactor_return:
    - land_compaction
  branch_stopped:
    - mark_abandoned
    - notify_ui

# Intermediate compaction checkpoints (ARCH §2.6–§2.7, §6). The executor
# reads this at each step boundary: when the trigger fires it dispatches a
# compactor off the compaction point — the branch tip, or `HEAD~keep_recent`
# when `keep_recent` is set — and the compactor's return lands by
# rebase-forward (the `compactor_return: land_compaction` binding above):
# the span before the point squashes into a compaction base and the live
# tail replays on top, zero downtime. `trigger` is one of
# `every_n_commits`, `every_t_seconds` (both take `n`), or `on_flush` (the
# agent-elected `flush`, no `n`). `keep_recent` (optional, default 0) keeps
# the most recent commits out of the span; it must stay below `n` under
# `every_n_commits`. Omit the whole block and the branch never compacts.
compaction:
  intermediate:
    trigger: every_n_commits
    n: 20

# Harness-owned retry policy for a step's model call (ARCH §2.10, §4.4):
# brazen never retries — the harness re-invokes `bz` on a retryable
# in-band Error, up to max_attempts, with exponential backoff.
retry:
  max_attempts: 3
  backoff: exponential

# Bounded transcript projection of tool output (ARCH §3.3, §6). Each
# stream of a tool result (stdout and stderr independently) is bounded
# to its first head_bytes and last tail_bytes before the result envelope
# is rendered; the omitted middle is replaced by a marker stating the
# original byte/line counts and where the full record lives
# (steps/<agent-id>/<NNN>/tools/<tool-id>/output.json — always complete).
# Counts are bytes, never tokens. Omit the block and tool output reaches
# the transcript unbounded.
tool_output:
  head_bytes: 16384
  tail_bytes: 16384

# Tool control (ARCH §3.3 *Tool control*, §6): an adjudicator binary
# consulted before every granted tool invocation executes — it answers
# pass, refuse, or hold (park for out-of-band review). Deliberately not
# configured here: no control ships, and omitting the block leaves the
# tool window unchanged. To wire one:
# tool_control:
#   command: /path/to/control

# Whole-tree spend limits (ARCH §6 "Budgets (v0.7)"). One frozen ceiling
# for the whole agent tree, not a per-agent allowance: every driver in
# the tree — root or subagent — checks the tree's total against these
# same numbers, and a dispatch inherits no fresh budget. Checked at
# every model-call boundary before the adapter is invoked; spend, wall,
# and depth are derived from disk each check — no stored counter. Omit a
# limit (or the whole block) to leave that axis unbounded.
#
# Deliberately not configured here (operator ruling 2026-08-16): a
# whole-tree ceiling binds far earlier than its number reads, because a
# root and every agent below it spend one shared allowance — an hour of
# accumulated wall across a tree ends a conversation that is working. So
# nothing ships bounded: tokens, wall and depth are all unbounded, and a
# ceiling is config an operator adds. To wire one:
# budgets:
#   max_total_tokens: 2000000
#   max_wall_seconds: 3600
#   max_depth: 4