Most integrations need two edits: drop
task_hint from your system_context() call, and add settle=True to your turn scope. Everything else migrates itself.Why it changed
Three findings from a measured run, each of which is a breaking change below:- The trigger fired on everything.
agent_reliability/agent_consistencyare worst-case rollups that floor near~0.2for essentially every real session, so “score below 0.5” was true almost always. - Promotion was close to random. Candidate rules were scored on that same non-discriminating metric, so the promote/retire decision carried little information.
- The agent operated the harness instead of doing the task. Handed 14 tools, its whole rule corpus in every prompt, and a check-your-mailbox-every-turn mandate, 9 of the 13 rules it wrote were about gaming its own diagnostic protocol.
trend_min_samples was never reachable.
1. The trigger is trace-level
What changed.trigger_mode defaults to "trace". Instead of two session composites per turn, the harness scores trace-level metrics in three tiers and Tier 1 breaches on the trajectory — a stall or a regression — never on an absolute floor.
What you do. Nothing, to get the new behavior. But two things are worth knowing:
- Your thresholds carry different meaning now.
HARNESS_RELIABILITY_THRESHOLDandHARNESS_CONSISTENCY_THRESHOLDonly apply in session mode. What matters in trace mode isgate_window(the primary knob),gate_target,gate_drop, and the Tier-2 thresholds. Re-calibrate. - Notices look different. Each metric now carries
trace_idandtier, the notice carries ascope_hint, and the condition vocabulary gainedstallandregression. If you parse notices or signatures downstream, update those consumers.
2. Turn boundaries need a barrier
What changed.Harness.settle(session_id) and harness.turn(session_id, settle=True) are new. This is the fix for the inert-trend bug: without a per-turn barrier, an agent runs several turns ahead of its own diagnosis and a session can end before its first notice arrives.
What you do.
barrier_timeout_s (default 180s), separate from drain_timeout_s. On expiry the work continues detached and SettleResult.timed_out is set.
3. The rules workspace is agent-owned
What changed.harness_rules.md is now a skill root — protocol, tool table, and a generated References index, with no rule text. Rules live in rules/global.md, rules/scoped.md, and any <topic>.md the agent creates. The system context injects no rule bodies; the agent pulls them with the new harness_rules_read.
What you do.
PandaHarnessHook.startup_context() and compose_system_preamble() lost the same parameter.
Your existing rules migrate themselves. rules.jsonl records are migrated on read, preserving v0.6’s meaning:
No migration command and no rewrite pass; the first render regenerates the
rules/ subtree. If you have a customized harness_rules.md, note that provisioning never overwrites an existing root — but the References section below the generated marker is regenerated.
Retrieval is now keyed on
scope, not on whether a rule happens to carry tags. In v0.6 any rule added without a source notice had no tags and therefore became a permanent global by accident. tags still exist, for ranking.4. Four tools were removed
What changed. 14 tools → 10.
Added:
harness_rules_read. And harness_rule_add gained a scope argument, defaulting to the source notice’s scope_hint.
What you do. If you enumerate tool names, or assert a tool count, update it. HarnessToolset no longer accepts history= or evalset= — nothing left in it reads them.
New in v0.7, opt-in
- Outcome verifier —
Harness.create(..., verifier=...). A(session_id, end_state) -> float | bool | Noneoracle becomes theoutcome_correctmetric and, when present, decides promotion instead of a judged proxy. Prefer a continuous score: a pass/fail flag that is almost always0discriminates no better than the metrics this release replaces. - Tier 3 —
enable_tier3=trueaddsplan_adherence,plan_quality,step_efficiencyto explain a confirmed Tier-2 breach. Never a breach source of its own. hook.pending_sessions— a read-only view for host-side phase barriers, so callers no longer need the private task map.
Behavior fixes worth knowing
These need no action, but they change what you’ll observe:- Validation and regression re-score on trace metrics (Tier 1 + Tier 2, against the replay’s last trace), not the session composites. Deltas in a regression report will name different metrics than they did in v0.6.
- Promotion target is chosen per case from the deltas that actually arrived, in trust order:
outcome_correct→ the rule’smetric→ the triggering signature. A wired verifier with no verdict for a particular task no longer vetoes promotion. - Severity mapping is deliberate. A Tier-1-only fire is advisory
trendand captures no eval case; only a Tier-2-confirmed breach is abreachand becomes a promotable case. Expect a smaller, cleaner eval set. - One platform run per turn for Tier 1, over every new trace, and one history write per trace instead of two per metric.
- Trace listings no longer burn the retry budget on a warm session — an empty listing is only retried while the session has never yet produced a trace.
--signal-weightsis session-only. It is a validation error on the trace path, so the harness omits it there.
A quick checklist
1
Drop task_hint
harness.system_context() — no arguments.2
Add the barrier
harness.turn(session_id, settle=True), or an explicit await harness.settle(session_id).3
Confirm turn granularity
One
on_turn_end per agent turn, not per task. Verify it: after a multi-turn session, state/score_history.json should hold more than one sample per (session, metric).4
Update tool-name lists and notice parsers
10 tools;
harness_rules_read is new; notices carry trace_id, tier, scope_hint; signatures can say stall: / regression:.5
Re-calibrate
Tune
gate_window to your task horizon, and re-measure the Tier-2 thresholds against your traffic.6
Consider a verifier
If you have any ground truth, wire it — it is the strongest promotion signal available and costs nothing per turn.

