Skip to main content

Anatomy of a notice

A DiagnosticNotice is everything the agent needs to diagnose one detected degradation:
Notice ids are timestamp-sortable and validated as safe path components (the agent supplies them to tools, and they become filenames).

The mailbox

  • The hook posts to pending/; the agent acknowledges via harness_mailbox_ack, which moves the notice to processed/ with a Resolution (acked_at, optional rule_id, optional note).
  • status.json is the cheap summary the system-context banner reads — composing the prompt never scans the directory.
  • The banner carries only a count and a severity enum. No eval-derived free text enters the preamble; rich content stays behind explicit tool calls, where it is sanitized and framed as untrusted data.

Trace dumps

Two artifacts under traces/:
  • latest_eval.json — always rewritten with the most recent evaluation, alerting or not. A cheap “what did the harness last see” probe.
  • <notice-id>.json — one immutable dump per notice: every score with thresholds, conditions, per-trace signals, and (with enrich_flagged_traces=true) the worst flagged trace’s TOOL spans fetched at notice time.

The journal

journal.jsonl is the append-only, cross-run event log — the agent’s long-term memory of its own health. The agent mines it through harness_journal (recent events, filterable by type) and harness_reflect (an assembled reflection context: recent notices, the live rule set, validation outcomes, and per-rule effectiveness counts).
The full event-type list is in How it works. Because the journal spans process restarts, a fresh harness over the same workspace inherits everything: rules re-enter the context, and past notices inform new baselines.
Everything in the workspace is plain JSON on disk. When in doubt, cat it — the file layout is the API surface for operators.