Skip to main content
Rules are the harness’s output: permanent operating constraints the agent writes for itself, learned from its own failures. They live in a structured store, render into the system prompt, and — since v0.6 — carry a full lifecycle and relevance-based injection.

The rule store

rules.jsonl is append-only; the latest record per rule id wins (so retiring or promoting a rule appends an updated record rather than rewriting history). Each rule carries: Guard rails on add:
  • Dedup — a rule whose normalized text matches a live rule returns the existing rule instead of creating a duplicate.
  • Cap — at max_active_rules (default 50, counted over active + candidate) the add fails with a message telling the agent to retire something first. Compaction is agent-driven; nothing is silently evicted.
  • Sanitization — rule text and rationale pass the trust boundary (sanitize_text) before they can ever reach a prompt.

The rendered context

harness_rules.md is a projection, regenerated from the store on every change: the packaged template preamble (the self-healing contract and tool table), then the rules:
Candidates render always — a rule must be in force to be measurable — but under a heading that makes their unproven status unmistakable, and the standing protocol tells the agent to prefer validated rules on conflict.

Task-conditioned retrieval

With more than a handful of rules, injecting all of them dilutes attention and lets a rule learned from one failure mode overfit onto unrelated tasks. With rule_retrieval=true (the default), the context renders:
  1. Every global (untagged) rule — always, exempt from the budget.
  2. The top-rules_context_topk (default 8) tagged rules ranked by lexical relevance to the current query: the pending notices’ signatures and metric names, plus an optional caller-supplied task hint:
  1. A one-line note when rules were trimmed, pointing at harness_rules_search / harness_rules_list — the context stays small while every rule stays reachable.
The scorer is deliberately simple and dependency-free: casefolded word tokens, tag hits weighted double over rule/rationale text hits, normalized by query size, ties broken by recency. breach:agent_reliability tokenizes to breach + agent_reliability, so signatures, metric names, and task words all match naturally. Behavior at the edges:
  • No signal (no pending notices, no hint) → everything renders; retrieval never hides rules without a reason.
  • No overlap → ranking degrades to recency under the same top-k.
  • Candidates never consume top-k slots — retrieval can’t starve a trial.
  • rule_retrieval=false restores render-everything (the pre-v0.6 behavior).
  • The on-disk harness_rules.md is always the full render; retrieval only shapes the composed prompt.

Working with rules programmatically

The agent-facing equivalents are harness_rules_list, harness_rules_search, harness_rule_retire, harness_rule_status, and harness_reflect — see the toolset.