# Arbiter and completion

Millrace does not treat backlog drain as automatic completion. Completion is a separate runtime-governed path.

## What triggers Arbiter

The shipped completion model for `default_codex` uses a frozen planning-loop `completion_behavior`.

The shipped baseline is:

- trigger: `backlog_drained`
- readiness rule: `no_open_lineage_work`
- stage: `arbiter`
- request kind: `closure_target`
- target selector: `active_closure_target`
- blocked-work policy: `suppress`

That means Arbiter only runs when:

- no planning work is claimable
- no execution work is claimable
- one open closure target exists
- no queued, active, or blocked lineage work remains for that target

## Root-lineage model

Closure behavior is keyed by explicit root-lineage fields carried through work documents:

- `root_spec_id`
- `root_idea_id`

Arbiter uses root lineage so it does not have to guess which spec family it is judging after remediation churn.

## Canonical contract copies

Arbiter judges against canonical copies under its own workspace subtree:

- `millrace-agents/arbiter/contracts/ideas/<root_idea_id>.md`
- `millrace-agents/arbiter/contracts/root-specs/<root_spec_id>.md`

The runtime snapshots those copies when the root spec first enters the managed lineage so Arbiter is not searching mutable operator-authored files later.

## Closure-target state

The runtime owns one closure-target state file per root spec:

- `millrace-agents/arbiter/targets/<root_spec_id>.json`

The shipped v1 policy is one open closure target per workspace.

The target file records:

- root lineage ids
- canonical contract paths
- rubric path
- latest verdict and report paths
- whether closure is still open
- whether remaining lineage work still blocks closure
- the last Arbiter run id

## Runtime behavior when backlog drains

When no claimable work remains, the runtime:

1. claims planning work if available
2. claims execution work if available
3. if neither is available, inspects frozen completion behavior
4. locates the single open closure target
5. if no open target exists, tries to backfill one from the latest root spec that already carries root-lineage ids
6. scans queued, active, and blocked work for matching `root_spec_id`
7. suppresses Arbiter if lineage work still remains
8. dispatches Arbiter when the target is eligible

If no open target exists and the latest root spec is still missing root-lineage metadata, the runtime marks planning blocked and emits a diagnosable runtime event rather than silently idling through required closure behavior.

## Arbiter request contract

Arbiter is a real planning-stage run. It does not receive a fake queue item.

Its stage request uses `request_kind = closure_target` and includes fields such as:

- `closure_target_path`
- `closure_target_root_spec_id`
- `closure_target_root_idea_id`
- `canonical_root_spec_path`
- `canonical_seed_idea_path`
- `preferred_rubric_path`
- `preferred_verdict_path`
- `preferred_report_path`

The normalized stage result still projects onto `work_item_kind = spec` and `work_item_id = <root_spec_id>` so the result envelope stays typed and stable.

## Arbiter artifact layout

Arbiter-owned durable artifacts live under:

- `millrace-agents/arbiter/rubrics/<root_spec_id>.md`
- `millrace-agents/arbiter/verdicts/<root_spec_id>.json`
- `millrace-agents/arbiter/reports/<run_id>.md`

The runtime result-application path copies the per-run report into the durable Arbiter reports directory so the final report path stays stable.

## Runtime-owned outcomes

Arbiter may emit only:

- `ARBITER_COMPLETE`
- `REMEDIATION_NEEDED`
- `BLOCKED`

The runtime owns the workflow consequences:

### `ARBITER_COMPLETE`

The runtime closes the target, stamps `closed_at`, persists the latest verdict and report paths, and returns to idle.

### `REMEDIATION_NEEDED`

The runtime keeps the target open, persists the latest verdict and report paths, and enqueues a planning incident under `millrace-agents/incidents/incoming/`.

### `BLOCKED`

The runtime keeps the target open, persists the latest run and report context, and leaves the planning status blocked without fabricating queue work.

Arbiter does not directly mutate closure-target workflow authority. It produces artifacts and a terminal result. The runtime applies the authoritative state change.

## Operator inspection surfaces

Current operator-facing surfaces that expose this behavior include:

- `millrace compile show`
- `millrace status`
- `millrace runs show <run_id>`

Use those first before opening raw JSON files unless the full artifact payload is needed.

See also:

- `/ai/modes-and-loops.md`
- `/ai/architecture.md`
- `/ai/faq.md`
