Harness Search¶
H07: local exploration, no control plane
A harness search proposes, verifies, runs and evaluates harness candidates locally, under a spending envelope, and writes a report. It touches no experiment and claims no durable orchestration: branching a harness proposal into an experiment is refused until harness candidates are durable (ADR-019 M1–M6). The decisions are in ADR-024, accepted on 2026-10-15.
HarnessSearchProvider.select(context) where to search next (a base node), or why not
HarnessMutationProvider.mutate(request, 1) what to change: one typed HarnessPatch, or none
HarnessPlanner.plan: select → request → mutate → apply_patch → verify_harness_proposal → dedupe
run_local_harness_search: compile → run → verify evidence → evaluate → provider feedback → plan
What a search may change¶
A HarnessPatch is a closed, typed list of operations on one pinned base:
the system prompt, the task template (same variables), a defined tool's
description, the enabled tools, the context policy and the stopping limits.
apply_patch refuses a stale base, an operation outside the allowed
surfaces, an undefined tool, a template with other variables, a result over
the experiment's ceilings, an invalid result and a no-op, with every reason.
The enabled set only narrows: child.enabled ⊆ parent.enabled ∩
authorized_tools. A tool the parent defines but has disabled stays
disabled; enabling it is a grant, and a grant is an Action. A prompt that
claims a permission grants nothing.
What a provider may see¶
Only ProviderFeedback (run values after the provider filter, and per-task
execution measurements) and provider-safe comparisons computed from it: H06's
compare() over provider-visible values with no restricted report. A
single-task reference-derived score and any successful-tasks slice never
reach a provider, under either disclosure mode: a comparison on one is
withheld-from-provider, with no number and no verdict.
Authorization and spending¶
A HarnessSearchPolicy must say autonomous_search: authorized; it has no
default. It fixes the authorized tools, the allowed operations, the
ceilings and the spending envelope, and all of them are in its fingerprint.
The envelope limits rounds, candidate evaluations (one per execution replicate: three candidates on three seeds are nine), task attempts, model calls per role and tokens per unit (units are never added together). Every unit of work reserves its worst case before it starts; a unit that could cross a limit never starts. A replicate's evaluation is admitted before any of its task attempts runs, so no task runs for an evaluation that could not start. A cost limit, a unit without a limit, and a harness whose attempts are unbounded all refuse the search before anything runs.
After a unit ends, it is charged what was measured. A judge call is charged
the tokens its provider reported, so a declared judge_prompt_tokens that is
too small is caught: a report above the reservation stops the search with
spending-exceeded. A call whose provider reported no token counts, and a
task attempt that raised, keep their whole reservation charged, and the
report names the error type (never its message).
A provider that breaks its contract, for example by choosing a base the
context lists as exhausted, or raises, ends the search with provider-error.
Any other error (an evaluator or evidence store that raises) ends it with
error, and the unit it interrupted is charged its whole reservation. The
report is written whatever ends the search, then the error is raised.
Replay is planning replay¶
replay_local_harness_search re-plans each recorded round from its
recorded context and checks it gives the same choice, requests, refusals
and proposal. It replays decisions only: no model is called, no task runs
and nothing is evaluated again. It shows that the same evidence, given to
the same bound providers under the same policy, gives the same proposals,
not that the evidence itself would be reproduced.
A worked example¶
runs three rounds on the pinned support suite with the scripted model and prints every decision, comparison and unit of spend, then replays the planning (not the execution) from the report.
apply_patch(base, patch, *, allowed=None, authorized_tools=None, ceilings=None)
¶
The child harness patch describes, applied to base; refused with every reason.
Refuses a stale base, an operation outside allowed, a tool the base does not define (descriptions) or does not enable (the enabled set), a tool outside authorized_tools, a template whose variables are not the base's, a result that is not a valid harness, a result outside ceilings, and a no-op.
Raises:
| Type | Description |
|---|---|
PatchRefusedError
|
With every reason. |
Source code in xaytune/core/domain/harness_search.py
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
verify_harness_proposal(proposal, parent, policy, existing, *, provider_operations=None)
¶
ADR-024 §P7's four checks, and duplicates, against the recorded parent.
- Patch integrity: the patch is for this parent, and applying it gives
exactly
proposal.harness. - No capability escalation:
child.enabled ⊆ parent.enabled ∩ authorized_tools. - Ceilings: the child is within the experiment's ceilings.
- Surfaces: every operation is allowed by the policy (and the provider).
Run in the planner, and again wherever the proposal is acted on.
Raises:
| Type | Description |
|---|---|
HarnessProposalRefusedError
|
With every reason. |
Source code in xaytune/core/domain/harness_search.py
HarnessSearchPolicy
¶
Bases: _Closed
What an experiment authorizes a harness search to do, fixed for the whole search.
autonomous_search has no default: without the experiment saying so
explicitly, no candidate is generated without a human (§P7, Q3). The
permissions (tools, operations, ceilings) and the budget (the envelope)
are part of the fingerprint; changing any of them is a new search.
LocalSearchEnvelope
¶
Bases: _Closed
What the local search may spend, in total (ADR-024 §P12a).
token_limits has one limit per token unit; units are never added
together. cost is refused in v1 -- cost is not metered -- so a search
declaring one refuses to start rather than pretending to bound it.
max_candidate_evaluations = Field(gt=0, strict=True)
class-attribute
instance-attribute
¶
Evaluation runs: one per execution replicate (each seed of each candidate), not one per candidate. Three candidates on three seeds are nine.
max_model_calls = Field(default_factory=FrozenDict)
class-attribute
instance-attribute
¶
{role: calls} for agent, judge and provider; a missing role may make none.
token_limits = Field(default_factory=FrozenDict)
class-attribute
instance-attribute
¶
{unit: tokens}, e.g. {"tokens(whitespace-v1)": 50000}.
judge_prompt_tokens = Field(default=None, gt=0, strict=True)
class-attribute
instance-attribute
¶
The declared bound on one judge call's prompt, in the judge's token unit.
HarnessPlanner(search, mutation, policy)
¶
Orchestrates a search provider and a mutation provider into at most one proposal (§P1).
A Xaytune-owned planner: it builds the mutation request, applies and
verifies every patch (§P7), deduplicates, and retries a refused patch at
most policy.max_retries times. It holds no state between rounds.
Source code in xaytune/harness/search.py
plan(context, harnesses, *, seed, round)
¶
At most one verified proposal from context; harnesses are the recorded nodes'.
Source code in xaytune/harness/search.py
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | |
run_local_harness_search(*, root, planner, objectives, benchmark, evaluation, content, model, toolbox, recording, workspace, comparison_k=2.0)
¶
Run a harness search locally, round by round, under the policy's spending envelope.
Each round runs the current candidate on every seed (compile, run,
assemble and verify evidence), evaluates each replicate, gives the
planner provider feedback and provider-safe comparisons only, and takes
the verified proposal as the next round's candidate. The report is
written to workspace/search-report.json whatever ends the search.
Raises:
| Type | Description |
|---|---|
SpendingUnenforceableError
|
If the envelope cannot be enforced; nothing runs. |
SpendingExceededError
|
If a unit measured more than its reservation (after the report is written). |
HarnessSearchError
|
If a provider broke its contract (after the report
is written, with |
HarnessRunRefusedError
|
If the runner refused a task run (after the
report is written, with |
Exception
|
Whatever else ended a round -- an evaluator or evidence
store that raised -- after the interrupted unit is charged in full
and the report is written, with |
Source code in xaytune/harness/search.py
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 | |
replay_local_harness_search(report, planner)
¶
Planning replay: re-plan every recorded round from its recorded context.
It replays decisions only. Nothing is re-executed: no model is called, no task runs and no evaluation is measured again. The recorded contexts are its input, so it shows that the same evidence, given to the same bound providers under the same policy, gives the same proposals -- not that the evidence itself would be reproduced. Returns how many plans were replayed.
The planner must be bound exactly as recorded, and every round must give the same choice, requests, refusals and proposal.
Raises:
| Type | Description |
|---|---|
ReplayMismatchError
|
Naming every round that does not reproduce. |