loadouts 0.2.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/bundled/embedded/pi/loadouts-runtime.ts +19677 -0
  2. package/bundled/extensions/loadouts-runtime/index.ts +19677 -0
  3. package/bundled/extensions/loadouts-runtime/package.json +6 -0
  4. package/bundled/loadouts/opencode-runtime.yaml +5 -0
  5. package/bundled/loadouts/pi-runtime.yaml +5 -0
  6. package/bundled/opencode/plugins/loadouts/index.js +39198 -0
  7. package/bundled/opencode/plugins/loadouts/package.json +9 -0
  8. package/bundled/opencode/plugins/loadouts/tui.js +16913 -0
  9. package/dist/builtins/agent-transforms.d.ts.map +1 -1
  10. package/dist/builtins/agent-transforms.js +31 -9
  11. package/dist/builtins/agent-transforms.js.map +1 -1
  12. package/dist/builtins/index.d.ts.map +1 -1
  13. package/dist/builtins/index.js +18 -3
  14. package/dist/builtins/index.js.map +1 -1
  15. package/dist/builtins/kinds/extension-dir.d.ts +3 -0
  16. package/dist/builtins/kinds/extension-dir.d.ts.map +1 -0
  17. package/dist/builtins/kinds/extension-dir.js +8 -0
  18. package/dist/builtins/kinds/extension-dir.js.map +1 -0
  19. package/dist/builtins/kinds/opencode-cli-config.d.ts +3 -0
  20. package/dist/builtins/kinds/opencode-cli-config.d.ts.map +1 -0
  21. package/dist/builtins/kinds/opencode-cli-config.js +10 -0
  22. package/dist/builtins/kinds/opencode-cli-config.js.map +1 -0
  23. package/dist/builtins/kinds/opencode-command.d.ts +3 -0
  24. package/dist/builtins/kinds/opencode-command.d.ts.map +1 -0
  25. package/dist/builtins/kinds/opencode-command.js +8 -0
  26. package/dist/builtins/kinds/opencode-command.js.map +1 -0
  27. package/dist/builtins/kinds/opencode-plugin-dir.d.ts +3 -0
  28. package/dist/builtins/kinds/opencode-plugin-dir.d.ts.map +1 -0
  29. package/dist/builtins/kinds/opencode-plugin-dir.js +11 -0
  30. package/dist/builtins/kinds/opencode-plugin-dir.js.map +1 -0
  31. package/dist/builtins/kinds/opencode-plugin.js +1 -1
  32. package/dist/builtins/kinds/opencode-plugin.js.map +1 -1
  33. package/dist/builtins/tools/opencode.d.ts.map +1 -1
  34. package/dist/builtins/tools/opencode.js +13 -1
  35. package/dist/builtins/tools/opencode.js.map +1 -1
  36. package/dist/builtins/tools/pi.d.ts.map +1 -1
  37. package/dist/builtins/tools/pi.js +2 -1
  38. package/dist/builtins/tools/pi.js.map +1 -1
  39. package/dist/cli/commands/diff.d.ts +10 -0
  40. package/dist/cli/commands/diff.d.ts.map +1 -1
  41. package/dist/cli/commands/diff.js +71 -30
  42. package/dist/cli/commands/diff.js.map +1 -1
  43. package/dist/cli/commands/info.d.ts +10 -0
  44. package/dist/cli/commands/info.d.ts.map +1 -1
  45. package/dist/cli/commands/info.js +45 -1
  46. package/dist/cli/commands/info.js.map +1 -1
  47. package/dist/cli/commands/list.d.ts +18 -0
  48. package/dist/cli/commands/list.d.ts.map +1 -1
  49. package/dist/cli/commands/list.js +27 -0
  50. package/dist/cli/commands/list.js.map +1 -1
  51. package/dist/cli/commands/session.d.ts +3 -0
  52. package/dist/cli/commands/session.d.ts.map +1 -0
  53. package/dist/cli/commands/session.js +68 -0
  54. package/dist/cli/commands/session.js.map +1 -0
  55. package/dist/cli/commands/status.d.ts +10 -0
  56. package/dist/cli/commands/status.d.ts.map +1 -1
  57. package/dist/cli/commands/status.js +100 -2
  58. package/dist/cli/commands/status.js.map +1 -1
  59. package/dist/cli/commands/sync.d.ts.map +1 -1
  60. package/dist/cli/commands/sync.js +6 -0
  61. package/dist/cli/commands/sync.js.map +1 -1
  62. package/dist/cli/commands/tui.d.ts +3 -0
  63. package/dist/cli/commands/tui.d.ts.map +1 -0
  64. package/dist/cli/commands/tui.js +20 -0
  65. package/dist/cli/commands/tui.js.map +1 -0
  66. package/dist/cli/index.d.ts.map +1 -1
  67. package/dist/cli/index.js +4 -0
  68. package/dist/cli/index.js.map +1 -1
  69. package/dist/core/discovery.js +1 -1
  70. package/dist/core/discovery.js.map +1 -1
  71. package/dist/core/import-discovery.d.ts.map +1 -1
  72. package/dist/core/import-discovery.js +2 -0
  73. package/dist/core/import-discovery.js.map +1 -1
  74. package/dist/core/registry.d.ts +5 -0
  75. package/dist/core/registry.d.ts.map +1 -1
  76. package/dist/core/registry.js.map +1 -1
  77. package/dist/core/render.d.ts.map +1 -1
  78. package/dist/core/render.js +77 -8
  79. package/dist/core/render.js.map +1 -1
  80. package/dist/core/resolve.d.ts +1 -1
  81. package/dist/core/resolve.d.ts.map +1 -1
  82. package/dist/core/resolve.js +3 -2
  83. package/dist/core/resolve.js.map +1 -1
  84. package/dist/core/runtime.d.ts +4 -0
  85. package/dist/core/runtime.d.ts.map +1 -1
  86. package/dist/core/runtime.js +10 -3
  87. package/dist/core/runtime.js.map +1 -1
  88. package/dist/core/schema.d.ts +59 -0
  89. package/dist/core/schema.d.ts.map +1 -1
  90. package/dist/core/schema.js +5 -0
  91. package/dist/core/schema.js.map +1 -1
  92. package/dist/core/types.d.ts +13 -0
  93. package/dist/core/types.d.ts.map +1 -1
  94. package/dist/integrations/opencode/advertisement.d.ts +7 -0
  95. package/dist/integrations/opencode/advertisement.d.ts.map +1 -0
  96. package/dist/integrations/opencode/advertisement.js +17 -0
  97. package/dist/integrations/opencode/advertisement.js.map +1 -0
  98. package/dist/integrations/opencode/client.d.ts +12 -0
  99. package/dist/integrations/opencode/client.d.ts.map +1 -0
  100. package/dist/integrations/opencode/client.js +48 -0
  101. package/dist/integrations/opencode/client.js.map +1 -0
  102. package/dist/integrations/opencode/command.d.ts +11 -0
  103. package/dist/integrations/opencode/command.d.ts.map +1 -0
  104. package/dist/integrations/opencode/command.js +19 -0
  105. package/dist/integrations/opencode/command.js.map +1 -0
  106. package/dist/integrations/opencode/delta.d.ts +15 -0
  107. package/dist/integrations/opencode/delta.d.ts.map +1 -0
  108. package/dist/integrations/opencode/delta.js +75 -0
  109. package/dist/integrations/opencode/delta.js.map +1 -0
  110. package/dist/integrations/opencode/session.d.ts +207 -0
  111. package/dist/integrations/opencode/session.d.ts.map +1 -0
  112. package/dist/integrations/opencode/session.js +201 -0
  113. package/dist/integrations/opencode/session.js.map +1 -0
  114. package/dist/lib/gitignore.d.ts +7 -3
  115. package/dist/lib/gitignore.d.ts.map +1 -1
  116. package/dist/lib/gitignore.js +16 -6
  117. package/dist/lib/gitignore.js.map +1 -1
  118. package/dist/tui/core/actions.d.ts +8 -0
  119. package/dist/tui/core/actions.d.ts.map +1 -0
  120. package/dist/tui/core/actions.js +76 -0
  121. package/dist/tui/core/actions.js.map +1 -0
  122. package/dist/tui/core/controller.d.ts +28 -0
  123. package/dist/tui/core/controller.d.ts.map +1 -0
  124. package/dist/tui/core/controller.js +78 -0
  125. package/dist/tui/core/controller.js.map +1 -0
  126. package/dist/tui/core/data.d.ts +43 -0
  127. package/dist/tui/core/data.d.ts.map +1 -0
  128. package/dist/tui/core/data.js +161 -0
  129. package/dist/tui/core/data.js.map +1 -0
  130. package/dist/tui/core/host.d.ts +15 -0
  131. package/dist/tui/core/host.d.ts.map +1 -0
  132. package/dist/tui/core/host.js +2 -0
  133. package/dist/tui/core/host.js.map +1 -0
  134. package/dist/tui/core/intent.d.ts +95 -0
  135. package/dist/tui/core/intent.d.ts.map +1 -0
  136. package/dist/tui/core/intent.js +2 -0
  137. package/dist/tui/core/intent.js.map +1 -0
  138. package/dist/tui/core/keymap.d.ts +16 -0
  139. package/dist/tui/core/keymap.d.ts.map +1 -0
  140. package/dist/tui/core/keymap.js +68 -0
  141. package/dist/tui/core/keymap.js.map +1 -0
  142. package/dist/tui/core/model.d.ts +65 -0
  143. package/dist/tui/core/model.d.ts.map +1 -0
  144. package/dist/tui/core/model.js +34 -0
  145. package/dist/tui/core/model.js.map +1 -0
  146. package/dist/tui/core/selection.d.ts +12 -0
  147. package/dist/tui/core/selection.d.ts.map +1 -0
  148. package/dist/tui/core/selection.js +42 -0
  149. package/dist/tui/core/selection.js.map +1 -0
  150. package/dist/tui/core/theme.d.ts +15 -0
  151. package/dist/tui/core/theme.d.ts.map +1 -0
  152. package/dist/tui/core/theme.js +11 -0
  153. package/dist/tui/core/theme.js.map +1 -0
  154. package/dist/tui/core/update.d.ts +8 -0
  155. package/dist/tui/core/update.d.ts.map +1 -0
  156. package/dist/tui/core/update.js +206 -0
  157. package/dist/tui/core/update.js.map +1 -0
  158. package/dist/tui/core/view.d.ts +4 -0
  159. package/dist/tui/core/view.d.ts.map +1 -0
  160. package/dist/tui/core/view.js +162 -0
  161. package/dist/tui/core/view.js.map +1 -0
  162. package/dist/tui/core/viewport.d.ts +5 -0
  163. package/dist/tui/core/viewport.d.ts.map +1 -0
  164. package/dist/tui/core/viewport.js +33 -0
  165. package/dist/tui/core/viewport.js.map +1 -0
  166. package/dist/tui/core/viewspec.d.ts +49 -0
  167. package/dist/tui/core/viewspec.d.ts.map +1 -0
  168. package/dist/tui/core/viewspec.js +2 -0
  169. package/dist/tui/core/viewspec.js.map +1 -0
  170. package/dist/tui/hosts/pi/embed-entry.d.ts +3 -0
  171. package/dist/tui/hosts/pi/embed-entry.d.ts.map +1 -0
  172. package/dist/tui/hosts/pi/embed-entry.js +96 -0
  173. package/dist/tui/hosts/pi/embed-entry.js.map +1 -0
  174. package/dist/tui/hosts/pi/inject.d.ts +49 -0
  175. package/dist/tui/hosts/pi/inject.d.ts.map +1 -0
  176. package/dist/tui/hosts/pi/inject.js +31 -0
  177. package/dist/tui/hosts/pi/inject.js.map +1 -0
  178. package/dist/tui/hosts/standalone.d.ts +2 -0
  179. package/dist/tui/hosts/standalone.d.ts.map +1 -0
  180. package/dist/tui/hosts/standalone.js +109 -0
  181. package/dist/tui/hosts/standalone.js.map +1 -0
  182. package/dist/tui/skins/pi-tui/input.d.ts +5 -0
  183. package/dist/tui/skins/pi-tui/input.d.ts.map +1 -0
  184. package/dist/tui/skins/pi-tui/input.js +42 -0
  185. package/dist/tui/skins/pi-tui/input.js.map +1 -0
  186. package/dist/tui/skins/pi-tui/pi-theme-adapter.d.ts +4 -0
  187. package/dist/tui/skins/pi-tui/pi-theme-adapter.d.ts.map +1 -0
  188. package/dist/tui/skins/pi-tui/pi-theme-adapter.js +27 -0
  189. package/dist/tui/skins/pi-tui/pi-theme-adapter.js.map +1 -0
  190. package/dist/tui/skins/pi-tui/render.d.ts +38 -0
  191. package/dist/tui/skins/pi-tui/render.d.ts.map +1 -0
  192. package/dist/tui/skins/pi-tui/render.js +162 -0
  193. package/dist/tui/skins/pi-tui/render.js.map +1 -0
  194. package/dist/tui/skins/pi-tui/theme.d.ts +10 -0
  195. package/dist/tui/skins/pi-tui/theme.d.ts.map +1 -0
  196. package/dist/tui/skins/pi-tui/theme.js +58 -0
  197. package/dist/tui/skins/pi-tui/theme.js.map +1 -0
  198. package/docs/archive/opencode-v2-runtime-beta-18707.md +813 -0
  199. package/docs/authoring.md +69 -14
  200. package/docs/commands.md +24 -0
  201. package/docs/compatibility.md +8 -8
  202. package/docs/concepts.md +4 -2
  203. package/docs/opencode-v2-probes.md +253 -0
  204. package/docs/opencode-v2-runtime.md +129 -0
  205. package/docs/registry.md +1366 -0
  206. package/docs/runtime.md +115 -50
  207. package/docs/troubleshooting.md +20 -1
  208. package/docs/tui-architecture.md +503 -0
  209. package/package.json +17 -3
@@ -0,0 +1,1366 @@
1
+ # The Loadout Registry: Tracking Session Effectiveness, with Embedded Arena Trials
2
+
3
+ Status: **Design / RFC** (no implementation yet)
4
+ Author: design pass, August–September 2026
5
+ Research grounding: Shorehouse Library, `R. Evaluating Personal AI Coding Agent Configurations`
6
+
7
+ **The registry is the product.** A system for recording and tracking the
8
+ effectiveness of AI-assisted work — every session, every day — as loadout
9
+ configurations and models change underneath it. Blind paired trials
10
+ (**arenas**) are embedded in the flow whenever a comparison deserves causal
11
+ certainty; they are the registry's precision instrument, not the system.
12
+ Note the structural consequence: the top-level object of optimization is
13
+ the interactive main session, and the arena *cannot* pair interactive
14
+ sessions (§6.1) — only the registry reaches the headline metric. Build
15
+ order follows.
16
+
17
+ The architecture is a **registry with embedded trials** (the shape
18
+ epidemiology settled on decades ago): a continuous observational registry
19
+ over the whole population of sessions — main sessions, subagents, nested
20
+ orchestrator trees — with randomized comparisons run *inside* it when the
21
+ cost of rigor is worth paying. The registry is the base case; the arena is
22
+ the scalpel. "Arena" names the highest-validity **protocol** the system
23
+ supports, not the system itself.
24
+
25
+ **Design center: excellent work, less corrective steering, sound judgment,
26
+ then greater efficiency.** Quality, time, and cost are the optimization
27
+ axes. Main sessions usually succeed eventually because the user steers
28
+ them there; the registry must reveal how much the user compensated for the
29
+ harness. Appropriate consultation is part of excellent work: changes to
30
+ the vision, material new information, and consequential choices with weak
31
+ grounds should still come back to the user. Their attention and experience
32
+ are first-class outcomes alongside the result.
33
+
34
+ For routine work, the aim is excellence with little overhead. Demanding
35
+ work can justify longer investigation and greater cost when that effort
36
+ improves the result. Subagents have a different test: **how good was the
37
+ handoff, before the parent repaired it?** Their narrower assignments and
38
+ normally unattended execution make direct artifact assessment useful.
39
+
40
+ Ergonomic capture must produce actionable insight quickly. Large config
41
+ deltas may resolve in a handful of blind paired verdicts; smaller ones may
42
+ remain unclear at personal volumes. Records and notes are useful either
43
+ way. The system's job is to **protect each judgment** and **remember it** —
44
+ never to demand sample sizes before the user may act. A lab notebook with
45
+ a referee, not a gatekeeper.
46
+
47
+ ---
48
+
49
+ ## 0. The minimum landable system
50
+
51
+ The first usable system must measure quality and corrective steering as
52
+ well as cost. Its pieces are:
53
+
54
+ 1. **Render-time loadout hashing** — `loadouts` records lineage,
55
+ name@version, and rendered hash at activation/render.
56
+ 2. **Brief references + session records** — link the request or approved
57
+ plan, preserve revisions, and record the session tree and local usage.
58
+ Preserve subagent handoffs before parent edits.
59
+ 3. **Lightweight main-session review** — “Did it land your vision?” and
60
+ “How much correction did it need?”, with feel and a note available.
61
+ Store these as attributed assessments, separate from recorded facts.
62
+ 4. **CLI record view** — quality, correction burden, cost/time, and
63
+ experience together, with links back to the work. Handoff assessment
64
+ and comparison views are the next increment (§11).
65
+
66
+ Hashing, ledger storage, manual capture, and CLI views need no V2 plugin
67
+ API. Automatic capture needs probes for review timing, usage extraction,
68
+ and handoff preservation (§11). Missing data stays unknown. The manual
69
+ `loadouts arena record` escape hatch can record comparisons before arena
70
+ automation exists, with their actual validity flags.
71
+
72
+ Automated steering analysis, worktree arenas, phase profiling, and ranking
73
+ models follow once the everyday record helps answer real config questions.
74
+
75
+ ---
76
+
77
+ ## 1. Goals & non-goals
78
+
79
+ ### Goals
80
+
81
+ - **Record and track the effectiveness of all work** — main sessions,
82
+ dispatched subagents, nested orchestration trees — longitudinally, as
83
+ loadouts and models change. N=1 assessment is the **base case**, not a
84
+ degraded mode; paired trials are the precision instrument layered on top.
85
+ - **Main-session effectiveness is the top-level metric** — final quality,
86
+ corrective steering, consultation judgment, total cost/time, and
87
+ experience. Successful completion alone hides the user's rescue work.
88
+ The panel includes attributed judgments and computed facts, never
89
+ collapsed to a scalar (§4).
90
+ - **Subagents are assessed at handoff** against their dispatch brief,
91
+ before repair. Quality, usability, blocker reporting, and cost/time to
92
+ handoff stay visible even when the parent later makes the work succeed.
93
+ - **Appropriate autonomy:** reduce avoidable correction while preserving
94
+ valuable consultation. Changed requirements are recorded separately;
95
+ fewer user messages is not an objective.
96
+ - **Experience is a first-class outcome.** Enjoyment, trust, confidence,
97
+ attentiveness across the working day are terminal outcomes the configs
98
+ directly produce — measured as themselves (§3, honesty rule 6), never as
99
+ proxies for output quality.
100
+ - **Config velocity is sacred.** The user edits loadouts constantly;
101
+ measurement must never create pressure to freeze a config. Votes and
102
+ trends pool by **lineage**, not by hash (§6.5), so editing never resets a
103
+ record.
104
+ - **Actionable at low n.** Trend lines, matchup records, and one-line notes
105
+ are the primary output; the user acts on a 3–1 record with legible notes.
106
+ Statistics appear only when volume supports them (§8) and never gate
107
+ action.
108
+ - **Model is a first-class factor**, not a nuisance variable. First target
109
+ experiment: capability-map which task types each model handles under the
110
+ default loadout.
111
+ - **Unified instrumentation.** Briefs, session records, and preserved
112
+ handoffs feed one assessment envelope with distinct main-session,
113
+ handoff, and comparison outputs (§2). Every judgment identifies its
114
+ author, evidence, and time; facts and judgments remain separable.
115
+ - **Machinery minimalism.** Every component beyond the spine must earn
116
+ entry against observed behavior (§11). A limited system that runs is
117
+ worth more than a complete system that doesn't.
118
+ - Arena protocol: blind, position-randomized, merge-gated paired
119
+ comparison on **new, real tasks**; default **N=2**, up to loadout × model
120
+ matrices for deliberate experiments; winner merges back so real work
121
+ proceeds — embedded in the workstream, not beside it.
122
+
123
+ ### Non-goals (v1)
124
+
125
+ - Replay/benchmark suites over historical tasks (explicitly rejected: the
126
+ user works forward, not backward).
127
+ - Automatic config optimization (GEPA-style loops). The ledger should
128
+ *inform* human config edits; closing the loop automatically is future
129
+ work — and known to regress on holdouts when unsupervised (Stet, May 2026).
130
+ - A composite "config score." Quality-per-dollar scalars and weighted
131
+ indices hide exactly the information needed at decision time; the panel
132
+ stays a panel.
133
+ - Persistence churn as a headline metric. At personal config velocity,
134
+ churn conflates "the work was bad" with "the project moved." Demoted to
135
+ an on-demand post-hoc analysis tool (§8.5).
136
+ - Mid-run steering of arena candidates. The arena measures **pure
137
+ autonomous** performance; that is the estimand, stated up front.
138
+ - Deliberately orchestrated dual interactive main sessions. When an
139
+ abort-and-redispatch happens *naturally*, it is recorded as a
140
+ revealed-preference comparison (§2); the system never asks the user to
141
+ interact with two main sessions on purpose.
142
+ - Treating sentiment, message counts, or inactivity as ground truth about
143
+ quality, correction burden, trust, or abandonment. Later transcript
144
+ analysis proposes cited, correctable judgments (§4); it does not infer
145
+ the user's private intent as fact.
146
+ - Cross-tool support. OpenCode V2 first; the loadouts-side artifacts are
147
+ tool-agnostic by construction.
148
+
149
+ ---
150
+
151
+ ## 2. Architecture: a registry with embedded trials
152
+
153
+ ### Briefs: what work was intended
154
+
155
+ A **work brief** links the assignment and acceptance criteria to the
156
+ original request, dispatch, or approved plan. Expected difficulty is
157
+ `routine | demanding | uncertain`; `uncertain` means unknown, not a third
158
+ ordered difficulty level. Record it before execution when available, with
159
+ who supplied it and when. Do not reconstruct it from how expensive the run
160
+ turned out to be.
161
+
162
+ Start with one brief per main session and one per subagent assignment.
163
+ A subagent brief links to the parent's brief; continuations, repairs, and
164
+ retries can link to the same work. Arena candidates share the same frozen
165
+ brief revision. The brief can be just source references initially — no
166
+ mandatory form or separate planning ceremony. Model-written summaries are
167
+ proposals, not newly agreed requirements.
168
+
169
+ When the vision or material requirements change, append a revision with
170
+ its source and effective message/time. Earlier decisions are assessed
171
+ against what was known then; final quality uses the latest agreed brief
172
+ within the reviewed work. Correcting an agent's failure to follow an
173
+ existing requirement does not create a new requirement. Source references
174
+ are authoritative when a summary is disputed. Multi-task session splitting
175
+ is deferred until one brief per session becomes a practical limitation.
176
+
177
+ ### The spine: sessions and preserved handoffs
178
+
179
+ ```
180
+ Work brief + revisions
181
+ ├── Sessions and subagent tree
182
+ │ config/model, message refs, artifacts, local usage, timing
183
+ │ └── Preserved handoffs → linked repairs or retries
184
+ └── Assessments
185
+ main-session review | handoff review | arena comparison
186
+ ```
187
+
188
+ Every session — main, subagent, nested orchestrator, arena candidate —
189
+ uses the same factual record:
190
+
191
+ - **Provenance:** lineage, loadout name@version, rendered hash, model/build,
192
+ and session tags (§8.4). Capture the configuration actually used, not the
193
+ current configuration when the session is reviewed. Known mid-session
194
+ changes retain their message/time boundaries; mixed runs are labeled.
195
+ - **Structure:** parent-session, work/brief revision, and optional
196
+ continuation/retry/repair links. Parentage supports tree views; usage
197
+ accounting follows §4.3, not simple addition of every displayed total.
198
+ - **Execution:** message and artifact references, timestamps, local usage,
199
+ test results, commit refs, and merge events. Runtime state is distinct
200
+ from a human judgment that the work is completed or abandoned.
201
+ - **Handoffs:** preserve each subagent's returned artifact/report before
202
+ parent edits, with brief revision, session record, message, and time.
203
+ A mutable file path alone is not a snapshot. Later repair is linked to
204
+ this handoff; it never replaces the evidence of the first result.
205
+
206
+ Facts land independently of review. Assessment can happen immediately or
207
+ later, including after a session resumes. Each review targets a recorded
208
+ session boundary and specific artifacts; an earlier assessment never
209
+ silently becomes a judgment about subsequent work. Append-only revisions
210
+ and stable IDs make this possible without copying the whole transcript
211
+ into the ledger (§9).
212
+
213
+ ### The assessment object: shared envelope, different review paths
214
+
215
+ ```
216
+ assessment
217
+ ├── arity: 1 | 2 | k
218
+ ├── protocol: review | arena | field | revealed
219
+ ├── review_kind: main | handoff | process | comparison
220
+ ├── validity: { paired?, blind?, position_swapped?, interactive? }
221
+ ├── subjects: [session-record + brief-revision + artifact/handoff refs, …]
222
+ ├── author: user | parent_agent | judge (with model/rubric provenance)
223
+ ├── recorded_at, evidence_refs, supersedes?
224
+ └── outputs: main review / handoff review / comparison / process findings
225
+ ```
226
+
227
+ - **Arity 1, `review`** — the base case, with separate payloads for
228
+ main-session quality/steering/consultation (§4.1), handoff quality and
229
+ usability (§4.2), or later process analysis. Feel is a user report here,
230
+ not a field inferred from the factual session record.
231
+ - **Arity 2, `arena`** — the embedded trial: paired, blind,
232
+ position-swapped, merge-gated (§6).
233
+ - **Arity k, `field`** — blind field ranking of 3–4 candidates with ties.
234
+ - **Arity 2, `revealed`** — naturally occurring implicit votes: the user
235
+ aborts a session and redispatches the same task under a different
236
+ config. Logged as a comparison link with low validity flags; aborting
237
+ one of two attempts mid-stream is a strong signal, but unblinded and
238
+ unpaired-in-inputs, and the record says so.
239
+
240
+ User, parent, and independent judge assessments are separate records. A
241
+ parent accepting a handoff is useful operational feedback, not independent
242
+ proof of quality. Corrections append an assessment with `supersedes`;
243
+ disagreement between authors stays visible rather than overwriting one
244
+ another. Skipped questions and unknown values are distinct from favorable
245
+ answers or zero correction.
246
+
247
+ **Consumption rules — nothing is silently promoted:**
248
+
249
+ | Analysis | Eats |
250
+ |---|---|
251
+ | Bradley-Terry rankings (§8.1) | blind, paired, arity ≥ 2 only |
252
+ | Main-session trends (§8.0) | main reviews, linked usage, and separately labeled process findings |
253
+ | Handoff trends / capability grid | handoff assessments, separated by author and first/repaired result |
254
+ | Experience lane | user-reported feel and notes only |
255
+
256
+ ### The two loops
257
+
258
+ The registry closes the **measurement loop** (config → sessions →
259
+ outcomes/experience). A `/reflect`-style integration closes the
260
+ **improvement loop** (session → durable learnings → config edits). Wired
261
+ together at review time (§5), they form the full cycle: *measure → reflect
262
+ → edit → measure the edit*. When a reflect-produced learning becomes a
263
+ loadout edit, the spine records the provenance (`origin: reflect@<session>`)
264
+ — so the record view can eventually answer "do my reflection-driven edits
265
+ actually move the trend lines?"
266
+
267
+ ---
268
+
269
+ ## 3. Estimands (what the numbers mean)
270
+
271
+ | Stream | Question answered | Validity claim |
272
+ |---|---|---|
273
+ | **Main-session trends** | Does this config land the user's vision with less correction, appropriate consultation, and better cost/time? | Observational: the result belongs to a human–agent collaboration. Brief revisions, expected difficulty, task mix, and config/model changes provide context. Before/after trends suggest questions; they do not isolate a config's causal effect. |
274
+ | **Subagent handoffs** | How good and usable is the first returned work against its dispatch brief, and what did it cost? | Normally unattended, bounded assignments. Preserve first-handoff evidence and label author and any steering; repaired outcomes are separate. Ordinary handoffs remain observational, even when independently judged. |
275
+ | **Arena** | Which (loadout, model) produces better *unattended* work? | Internally valid per comparison (same task, same base commit, blind verdict). Generalizes only to "tasks I chose to arena" while manual mode dominates — the ledger records mode so strata stay separable. |
276
+ | **Capability grid** | Which task types can each model handle under a given loadout? | First-handoff usability × task type and expected difficulty. Descriptive; parent acceptance, independent review, and repaired results are distinguished. |
277
+ | **Experience** | What is each config like to *live in*? | Self-reported outcome (the patient-reported-outcome model): unblindable by nature and valid as itself; trended with novelty settling windows; never used as evidence of output quality. |
278
+
279
+ For plan-arenas on side-effectful tasks (§6.3), the estimand is **planning
280
+ quality**, not execution quality — stated in the record.
281
+
282
+ Key statistical honesty rules, baked into the design rather than left to
283
+ discipline:
284
+
285
+ 1. **Internal validity comes from pairing**, not from random task
286
+ selection. Arena candidates always receive the identical task, prompt,
287
+ and base commit.
288
+ 2. **A/A probes** (§8.3) measure the noise floor. Without them, no verdict
289
+ margin is interpretable.
290
+ 3. **Every run counts.** No discarding bad runs, no silently testing five
291
+ variants and keeping the best (the Leaderboard Illusion at personal
292
+ scale).
293
+ 4. Vetoes and `off` windows are logged with a one-word reason — selection
294
+ behavior is itself data.
295
+ 5. **Recording ≠ gating.** The ledger informs; it never blocks a config
296
+ switch or demands more data before the user acts. Statistical readouts
297
+ appear when volume supports them and stay silent otherwise — a blind
298
+ paired verdict on a big-delta comparison is decision-grade on its own.
299
+ 6. **Experience is an outcome, never a proxy.** Felt-sense gets its own
300
+ first-class lane — structured capture, trend lines, changepoint
301
+ analysis, the same dignity as any metric. It is never used as evidence
302
+ of *output* quality (that comes from explicit artifact/vision assessments
303
+ and verification evidence), and output metrics never overrule experience
304
+ ("the numbers say it's fine" does not beat "I hate working this way").
305
+
306
+ ---
307
+
308
+ ## 4. What gets measured
309
+
310
+ Two review paths share recorded facts. Quality, time, and cost appear
311
+ together; corrective burden, consultation judgment, and experience explain
312
+ what it took to get there. Completion is useful context, not a sufficient
313
+ quality measure.
314
+
315
+ ### 4.1 Main sessions: the result and the help required
316
+
317
+ | Dimension | Everyday capture | Later detail |
318
+ |---|---|---|
319
+ | **Final quality / vision fit** | User: `excellent \| acceptable \| fell_short`, or unknown | Artifact review against the agreed brief, with evidence |
320
+ | **Corrective steering** | User: `none \| a_little \| substantial`, or unknown | Cited correction episodes, impact, and repair/retry links |
321
+ | **Consultation judgment** | Optional user note or flagged example; otherwise unknown | Useful consultation, unnecessary escalation, and missed consultation, each with evidence |
322
+ | **Efficiency** | Total cost and observed timing (§4.3) alongside correction burden | Attributable repair costs and process breakdowns |
323
+ | **Experience** | User: `drag \| fine \| flow`, optional note | Optional trust/confidence check-in (§4.4) |
324
+
325
+ These are lightweight, attributed human judgments, not objective scores or
326
+ inputs to the arena ranking model. A user can report an excellent outcome
327
+ and substantial correction: preserving that combination is the point.
328
+ Work disposition (`completed | abandoned | redone`, or unknown) is recorded
329
+ with the review, but never substitutes for vision fit. A resumed or
330
+ unfinished session can be reviewed at a checkpoint, with final quality
331
+ left unknown until the relevant work is ready.
332
+
333
+ **Steering classification uses the requirements known at the time:**
334
+
335
+ | Event | Interpretation |
336
+ |---|---|
337
+ | User repeats an ignored requirement or rescues an avoidable mistake | Corrective steering |
338
+ | Agent surfaces material new information or a consequential choice it cannot confidently resolve | Useful consultation |
339
+ | User changes the intended result or scope | Requirement revision, not agent failure |
340
+ | Agent asks about a choice already settled or clearly delegated | Potential unnecessary escalation |
341
+ | Agent silently commits to a consequential, insufficiently grounded choice | Potential missed consultation |
342
+
343
+ Autonomous decisions within the brief are expected. “Taken silently” alone
344
+ is not a defect, and fewer user messages is not evidence of improvement.
345
+ Assess whether consultation was appropriate given materiality, uncertainty,
346
+ and delegated authority — not whether the agent claimed to feel confident.
347
+
348
+ A later process judge proposes episode labels with message references,
349
+ the applicable brief revision, rationale, and an `unclear` option. Group
350
+ related messages into episodes rather than counting each message as a new
351
+ correction. The user can correct labels; intent changes are not reliably
352
+ recoverable from a transcript alone. A one-line user note is often better
353
+ evidence than a classifier. Do not turn unreviewed episodes into zero events.
354
+
355
+ ### 4.2 Subagents: quality at handoff
356
+
357
+ Judge the preserved artifact and final report against the dispatch brief:
358
+
359
+ - **Quality and completeness:** did it fulfill the assignment well?
360
+ Record evidence against the acceptance criteria; use a blind comparative
361
+ vote when an arena is warranted.
362
+ - **Usability:** `usable_as_is | needs_repair | needs_replacement`, or
363
+ unknown. This is distinct from excellence: usable work can still admit
364
+ a substantially better solution.
365
+ - **Uncertainty and blockers:** did it surface genuine blockers and
366
+ consequential unresolved choices appropriately?
367
+ - **Cost/time to handoff:** cost includes its subtree; elapsed time uses
368
+ the handoff boundary, following §4.3.
369
+ - **Downstream fate:** accepted, repaired, retried, or discarded, with
370
+ links to the subsequent work and a reason when known.
371
+
372
+ Preserve each handoff before the parent edits it. First-handoff quality and
373
+ the eventual repaired result are separate assessment targets. A repair
374
+ inside the parent session can reference a message span; a separate retry
375
+ can reference another session. If the repair's cost cannot be isolated,
376
+ leave that attribution unknown while retaining the full parent-work cost.
377
+ Routine integration is not automatically a repair of a defective handoff.
378
+
379
+ Parent acceptance is one assessment source; a user or independent judge
380
+ provides another. Display them separately. An occasional steered subagent
381
+ is labeled with the steering reference and is not treated as unattended
382
+ evidence. A subagent orchestrator is itself judged on its delivered work,
383
+ even though it may repair its own children's handoffs along the way.
384
+
385
+ ### 4.3 Shared facts: cost, time, diff, and verification
386
+
387
+ Mechanicals are computed, never LLM-opined: tokens, calls, cost,
388
+ timestamps, diff stats, tests/lint where applicable, subagent count, and
389
+ tree depth. Rollups follow explicit rules:
390
+
391
+ - **Cost/tokens:** store local usage with stable source references; sum
392
+ each unique usage event once across the relevant tree and linked
393
+ attempts. Never sum already rolled-up parent totals with child totals,
394
+ or count a replayed/imported usage event again.
395
+ - **Failures count:** include unsuccessful, aborted, repaired, and retried
396
+ attempts when showing the cost of reaching the result. First-handoff
397
+ cost remains separately visible. Arena candidate costs and the total
398
+ experimental spend (both candidates plus judging) are distinct views;
399
+ judge spend is measurement overhead, not worker usage.
400
+ - **Elapsed time:** measure actual start-to-handoff/review duration for
401
+ the work being shown. Parallel child durations are not added. Across
402
+ linked attempts, distinguish end-to-end elapsed time from the union of
403
+ recorded execution intervals; long gaps can include user or external
404
+ waits. Show known waits separately, and leave missing timing unknown.
405
+ - **Human attention:** initially the reported correction burden and
406
+ notes. Message timestamps do not measure minutes spent thinking,
407
+ reading, or reviewing. Any later self-reported duration is labeled as
408
+ such rather than presented as a mechanical.
409
+ - **Diff:** files touched and lines added/removed, with base/end refs or
410
+ captured snapshots and an attribution status. Shared working trees and
411
+ unrelated edits can make session attribution unknown. Derive an optional
412
+ `diff_size: S | M | L` band using recorded threshold settings; absent
413
+ evidence is null, not zero. Compute a work's net diff from its endpoints,
414
+ not by summing overlapping parent/child diffs.
415
+ - **Verification:** test/lint results reference the artifact version they
416
+ checked. Passing tests is evidence of tested behavior, not proof of
417
+ excellence or complete alignment with the vision.
418
+
419
+ **Expected difficulty is a separate, pre-execution descriptor (§2).** A
420
+ two-line fix may be demanding; a large routine edit may be easy. Diff size
421
+ and the phase mix observed afterward do not establish task difficulty and
422
+ are not productivity scores or cost denominators. Compare efficiency in
423
+ similar work, with quality and burden visible. Greater effort on demanding
424
+ work can be the right investment; reduced cost is an improvement only in
425
+ the context of the resulting work and the user's preferences.
426
+
427
+ **Phase profile** (later, §11): a small-model estimate across
428
+ `planning/research | implementation | running | debugging | validation`,
429
+ stored as a process assessment with model/rubric version, evidence,
430
+ coverage, and the chosen unit (turns or token spans). The unit must be
431
+ specified before percentages are compared. These are estimates of observed
432
+ activity, not measured time or a causal diagnosis. They can suggest why
433
+ costs differ; debugging-heavy work is not necessarily worse work. Validate
434
+ phase labels and aggregate shares separately before trusting trends (§12).
435
+
436
+ ### 4.4 Experience: self-reported, first-class
437
+
438
+ `drag | fine | flow` and notes remain available beside quality and burden.
439
+ Trust and confidence come from explicit reports, not inferred sentiment or
440
+ a decline in questions. Behavioral patterns can prompt a useful question
441
+ (“you report more trust but still check constantly”), not settle it.
442
+
443
+ Skip rate measures capture friction/missingness first, not attentiveness
444
+ or trust. Show review coverage with every trend. Mark config changepoints
445
+ and initial exposure/novelty windows; those annotations do not eliminate
446
+ novelty or task-mix confounding. A monthly two-minute trust/confidence
447
+ check-in is an option if feel and notes prove insufficient.
448
+
449
+ ### 4.5 The two effectiveness views
450
+
451
+ - **Main:** vision fit, corrective burden, consultation findings, total
452
+ cost/time, and experience. “On demanding work, does this config deliver
453
+ excellent results with less correction and appropriate consultation?”
454
+ - **Handoff:** quality/completeness, usability, blocker reporting, cost/time
455
+ to first handoff, and linked repair/retry burden. “For this assignment,
456
+ which config returns the strongest usable work fastest and cheapest?”
457
+
458
+ Filter both by task type and expected difficulty, with unknown visible.
459
+ Show individual records, notes, source of judgment, and coverage alongside
460
+ summaries. Keep the components together and never collapse them into a
461
+ single score. An absence of detected quality difference is not proof of
462
+ equal quality; cost/time trade-offs remain the user's decision.
463
+
464
+ ### 4.6 Orchestration: a facet, not a category
465
+
466
+ Orchestration is a *style of execution* that occurs in any work domain —
467
+ you orchestrate a code refactor or a research sweep. It is captured as:
468
+
469
+ - a boolean session facet (`orchestrated`, auto-detected from whether the
470
+ session dispatched subagents),
471
+ - tree views (subagent count, depth, per-subtree cost, and observed elapsed
472
+ intervals under §4.3),
473
+ - assessment sub-verdicts (delegation effectiveness, plan quality — §7),
474
+ - and lineage matchups between orchestration configs (e.g.
475
+ `orchestration/mine` vs `orchestration/superpowers`), filterable to
476
+ `orchestrated` sessions.
477
+
478
+ "Which orchestration skill delegates better" is a lineage matchup plus a
479
+ facet filter — more data than a dedicated category, same question.
480
+
481
+ ---
482
+
483
+ ## 5. Capture and review
484
+
485
+ ### 5.1 Capture facts as work happens
486
+
487
+ Link the initial request/dispatch to a brief, record provenance and local
488
+ usage, and preserve subagent handoffs as they return. Append known brief
489
+ revisions and retry/repair links. This write path does not wait for a
490
+ human review or depend on a judge succeeding. Subagents do not each trigger
491
+ a user questionnaire.
492
+
493
+ Capture-on-return must preserve the artifact/report before parent edits;
494
+ if a host hook cannot provide that boundary, the dispatch wrapper must
495
+ snapshot before releasing the result. CLI/manual snapshot capture is the
496
+ fallback. If a first handoff was missed, record it as unavailable rather
497
+ than passing off the parent's repaired version as the original.
498
+
499
+ ### 5.2 A short main-session review
500
+
501
+ Two primary questions, each with a quick choice and skip:
502
+
503
+ 1. **Did it land your vision?** `excellent | acceptable | fell_short`.
504
+ 2. **How much correction did it need?** `none | a_little | substantial`.
505
+
506
+ Feel (`drag | fine | flow`), a one-line note, disposition, and a flagged
507
+ consultation example are available in the same compact review. All fields
508
+ allow unknown; an unfinished session can record burden/feel without a
509
+ final-quality judgment. Target a few seconds for the two primary choices,
510
+ with the actual burden tested in dogfooding. Do not add an obligatory
511
+ questionnaire to every turn or silently default unanswered questions.
512
+
513
+ **Review timing remains a probe, not an assumed host feature.** The current
514
+ runtime notes do not verify a session-close/idle-final hook. Test:
515
+
516
+ - **Next-session-start:** offer “Review your previous work?” with the
517
+ actual session identified. Opening another session does not imply that
518
+ the earlier one ended or was abandoned; the user can defer or skip.
519
+ - **Explicit/sidebar capture:** review at a meaningful checkpoint or when
520
+ the work is ready, including before leaving a long-running session.
521
+ - **Close/idle:** use only if the host exposes a useful boundary and
522
+ dogfooding shows that prompting there fits the workflow.
523
+
524
+ The assessment references the reviewed session record, message boundary,
525
+ brief revision, and artifact snapshot. Resuming work produces a new
526
+ boundary; corrections to a prior review append a superseding assessment.
527
+ Missing and skipped reviews remain visible in coverage figures.
528
+
529
+ ### 5.3 Handoff review and later enrichment
530
+
531
+ The parent can record acceptance, repair, retry, or discard against a
532
+ preserved handoff; user/independent artifact review is separately sourced.
533
+ Stage 1 adds these assessments and simple comparison views (§11).
534
+
535
+ Later background passes can propose steering/consultation episodes, phase
536
+ profiles, or `/reflect`-style learnings (memory entries, skill drafts, rule
537
+ candidates). Reflect-driven config edits carry `origin: reflect@<session>`
538
+ back into the spine. Failed enrichment leaves recorded facts and human
539
+ assessments intact, with missing enrichment marked unknown.
540
+
541
+ Deeper `/review-session` analysis and weekly digests are on-demand until
542
+ their findings justify ongoing judge cost. Basic human quality/burden
543
+ capture ships in Stage 0; only the detailed automation waits.
544
+
545
+ ---
546
+
547
+ ## 6. The arena protocol
548
+
549
+ ### 6.1 Modes
550
+
551
+ Factual capture is always-on; reviews are lightweight and skippable. Arena modes:
552
+
553
+ | Mode | Trigger | Candidate selection | v1? |
554
+ |---|---|---|---|
555
+ | `manual` | user, from TUI or CLI, typically at subagent-dispatch time | user picks loadouts × models in the picker | **yes — default** |
556
+ | `off` | user, optionally with duration (`arena off 4h`) | — | **yes** |
557
+ | `auto` | dice roll at configured rate on eligible dispatches | current pick + random challenger | later |
558
+ | `shadow` | dice roll; current pick's result merges immediately unreviewed, challenger + observer run in background | pick + challenger | later |
559
+
560
+ `manual` is expected to dominate. `auto`/`shadow` exist to widen the
561
+ sampled task population when the user wants stronger generalization
562
+ claims; they are rigor boosters, not prerequisites.
563
+
564
+ **Scope rule:** the arena covers anything *dispatched* — including an
565
+ orchestrator subagent with its own nested subagent tree, which is pairable
566
+ natively because it is autonomous from the dispatch point. The one thing
567
+ the arena cannot cover is the **interactive main session**: pairing
568
+ requires identical inputs, and an interactive session's inputs include the
569
+ user — the moment candidate A asks a question and B doesn't, there is no
570
+ "same task" anymore, and the user cannot be blinded to a conversation they
571
+ are in. Main sessions are assessed by the registry + session review
572
+ (arity-1) instead. No mechanism fixes this; it is structural, and the
573
+ system is honest about it.
574
+
575
+ ### 6.2 The flow
576
+
577
+ ```
578
+ 1. TRIGGER user dispatches a task via /arena (or intercepted subagent dispatch)
579
+ 2. PICK TUI picker: loadouts (multi-select) × models (multi-select)
580
+ → N candidates; cost estimate shown; task tag auto-suggested
581
+ 3. FREEZE snapshot brief revision, prompt/context + base commit;
582
+ record expected difficulty before results; render each loadout
583
+ into its own worktree under .worktrees/arena/<comparison-id>/<n>/
584
+ (filesystem activation — each worktree is its own OpenCode
585
+ location, so ALL artifact kinds incl. skills bind natively,
586
+ and a nested orchestrator tree inherits the candidate
587
+ loadout wholesale); record loadout hash = hash of rendered
588
+ artifact set
589
+ 4. RUN dispatch identical autonomous sessions (same prompt, same
590
+ params) under a standing instruction: "no user is available —
591
+ surface questions, blockers, and deferred decisions in your
592
+ final report." Collect mechanical metrics from session data;
593
+ mechanicals are NEVER asked of an LLM.
594
+ 5. JUDGE preserve returned artifacts/reports as handoffs, before
595
+ parent edits; shadow observer: blind verdict + sub-verdicts +
596
+ usability flags, logged — deciding nothing in early stages
597
+ 6. REVIEW two-stage verdict flow (§6.4): blind quality vote with costs
598
+ hidden → reveal metrics → all-things-considered pick
599
+ 7. MERGE the ATC pick squash-merged onto the originating worktree with
600
+ trailers (Arena-Id, Loadout-Hash, Model); user proceeds.
601
+ Losers preserved as refs under refs/arena/<comparison-id>/<n>
602
+ 8. LEDGER link brief, session records, handoffs, separate human/judge
603
+ assessments, and merge fate (§9); earlier facts land as captured
604
+ ```
605
+
606
+ **The merge is the forcing function.** To get the winner into real work —
607
+ which the user needs, it is their actual task — they must pick it blind.
608
+ Vote → note → reveal → merge, self-enforcing, no discipline required.
609
+ Target: under 60 seconds of flow.
610
+
611
+ Step 3 is load-bearing: rendering into separate worktrees sidesteps V2's
612
+ discovery-time/location-wide skill constraint (see
613
+ `docs/opencode-v2-runtime.md` §1, §7.1) *and* exercises loadouts exactly
614
+ as filesystem activation does in normal use. No runtime injection is
615
+ required for candidates.
616
+
617
+ Each candidate's review targets its preserved handoff under the shared
618
+ brief revision. A later repair in the originating session links back to
619
+ that handoff without rewriting its original assessment. Any exceptional
620
+ mid-run steering is recorded and makes the run ineligible for an
621
+ unattended arena comparison.
622
+
623
+ The "no user available" instruction makes autonomy calibration *partially*
624
+ measurable: the escalation content of the final report (what the candidate
625
+ chose to surface vs decide silently) is judged as a sub-verdict (§7). This
626
+ is a proxy for interactive escalation behavior, not the thing itself — the
627
+ gap is stated, and main-session consultation is assessed from user reports
628
+ and later cited process findings (§4.1).
629
+
630
+ ### 6.3 Side-effectful tasks: the plan-arena
631
+
632
+ Admin-category work (searching Slack, making posts, reservations) produces
633
+ side effects in external systems — two candidates cannot both execute.
634
+ Plan-arena: candidates run with side-effect tools permission-denied
635
+ (read/research tools open), and *propose* actions instead of executing.
636
+ The user blind-judges the proposals; the winner executes for real, once.
637
+ Pairing preserved, no double-booking. Estimand: planning quality (§3).
638
+
639
+ ### 6.4 The two-stage verdict
640
+
641
+ Efficiency toward a good outcome is a real preference (a 95% result at 3x
642
+ tokens/time can lose to a 94% result at 1x) — but collapsing it into a
643
+ quality-per-dollar scalar hides the trade. Instead:
644
+
645
+ - **Verdict stage 1 — blind quality vote, costs hidden.** The user (and observer)
646
+ judge artifacts with *no cost/time information* so cost anchoring cannot
647
+ contaminate the quality signal. This vote feeds BT.
648
+ - **Verdict stage 2 — metrics revealed → all-things-considered pick.** The ATC
649
+ pick is what actually merges. Both votes are recorded; divergences
650
+ ("A was better, B was 3x cheaper, I took B") accumulate into the user's
651
+ *revealed* cost-quality tradeoff — data that eventually answers "how
652
+ much do I actually pay for a quality step" without hard-coding a utility
653
+ function.
654
+ - **Keystroke economy: agreement is free.** The ATC pick defaults to the
655
+ blind vote; a single confirm keystroke merges. Overriding takes one
656
+ extra keystroke and gets the note nudge — divergence is the interesting
657
+ datum, so it can afford the friction; agreement cannot. Keeps the <60s
658
+ flow target honest at four logical steps but ~two keystrokes in the
659
+ common case.
660
+
661
+ ### 6.5 Multi-way, lineage, and scope
662
+
663
+ - N=2 is the default and the primary UX. N up to ~6 (e.g., 3 loadouts ×
664
+ 2 models) supported for deliberate experiments.
665
+ - **Review modes**, chosen at picker time:
666
+ - `pair` (default): the observer runs position-swapped pairwise rounds
667
+ down to two finalists; the user blind-reviews only the final pair.
668
+ Every observer round is still logged as a pairwise vote, so a 4-way
669
+ arena yields ~3–5 BT observations instead of 1.
670
+ - `field`: the user blind-reviews the full field (up to 3, maybe 4)
671
+ side-by-side and produces a **ranking with ties allowed**
672
+ (e.g., `A > B = C`), positions randomized. Heavier review burden,
673
+ richer vote — used when the user cares enough about the task to see
674
+ every candidate. The observer still runs (verdict logged for κ
675
+ calibration) but the human ranking is authoritative.
676
+ - **Additive factor model:** fit Bradley-Terry with
677
+ `strength(candidate) = loadout_effect + model_effect` rather than
678
+ ranking opaque (loadout, model) cells. Per-cell rankings will not
679
+ converge at personal sample sizes (sparse-BT instability); additive
680
+ marginals share strength across every vote. Loadout × model
681
+ *interactions* are recorded in the ledger but not reported until data
682
+ volume permits (~4x what marginals need).
683
+ - **Competitor identity = lineage, not hash.** A competitor is a *named
684
+ alternative* (e.g., `orchestration/mine` vs `orchestration/superpowers`),
685
+ stable while its content evolves. Every vote records the exact rendered
686
+ hash for provenance, but records pool by lineage — so constantly editing
687
+ a loadout never resets its record and measurement never pressures the
688
+ user to freeze a config. The user declares a **major-version boundary**
689
+ when a change is big enough that old votes shouldn't count (the plugin
690
+ can warn on a large rendered diff); that starts a fresh record — and a
691
+ changepoint on the trend lines (§8.1) — with the old one archived and
692
+ still queryable.
693
+ - **Assessment scope follows loadout scope.** A global loadout's record
694
+ pools across every project and work category it is used in — config
695
+ effects are assumed to transfer until the data says otherwise. A project
696
+ loadout's record pools within its project. Session tags (§8.4) let any
697
+ record be *sliced* by project or category on demand; slicing is
698
+ diagnostic ("does this win hold in shorehouse too?"), never a default
699
+ wall. One layering wrinkle: inside a project the rendered candidate is
700
+ *global loadout ∘ project overlay*, so a comparison records which layer
701
+ varied (`varied_layer` in the ledger) — usually the overlay with global
702
+ held constant, or vice versa.
703
+ - **"Current pick," not champion.** In manual-dominant use there is no
704
+ defended champion: the user's current pick per scope (one global, one
705
+ per project where overridden) is a declaration, informed by the record.
706
+ Champion/challenger semantics return only with the deferred
707
+ `auto`/`shadow` modes.
708
+
709
+ ---
710
+
711
+ ## 7. The observer
712
+
713
+ Two phases with an enforced information boundary; the plugin (not the
714
+ observer's goodwill) controls what each phase can see.
715
+
716
+ **Initial arena observer: the shadow judge.** From Stage 2 (§11) it runs on
717
+ every arena and produces verdicts, sub-verdicts, and rationale — but
718
+ *decides nothing*. The user votes first (merge-gated, mandatory), then
719
+ sees the observer's verdict alongside their own; κ accumulates from day
720
+ one at zero validity risk. Trust is earned into authority: κ ≥ 0.7 unlocks
721
+ skip-review for routine arenas, and sampling continues forever (judges
722
+ drift).
723
+
724
+ ### Phase 1 — blind, produces the score
725
+
726
+ - Input: frozen brief/acceptance criteria, per-candidate **preserved
727
+ handoff artifact + final report**
728
+ (anonymized as Candidate 1/2), test/lint results. Artifacts: diff for
729
+ code/shorehouse work, report for research, proposed-action plan for
730
+ plan-arenas (where the plan *is* the artifact). **No loadout identity,
731
+ no config content, no cost/time metrics** (§6.4 stage 1), and — by
732
+ design — **no raw trajectory**: trajectories leak identity through skill
733
+ names, model phrasing tells, and system-prompt echoes that position
734
+ swapping cannot fix. Blinding what cannot be redacted is theater; the
735
+ boundary is drawn where redaction is real.
736
+ - Output per pair: overall `clear win | narrow win | tie` + blind-safe
737
+ **sub-verdicts** (each `A | B | tie`, never scales): execution quality,
738
+ task adherence, escalation quality (judged from the final report's
739
+ surfaced questions/blockers/deferred decisions) + per-candidate
740
+ **usability flag** (`usable_as_is | needs_repair | needs_replacement`,
741
+ shared with ordinary handoff reviews) + rationale with
742
+ **required citations into the artifact** for every claim + `unknown`
743
+ escape hatch.
744
+ - Rubrics are **per-category**: code weighs tests/lint and mergeability;
745
+ shorehouse weighs claim citation, structure, and MOC routing; plan-arena
746
+ weighs feasibility, coverage, and risk surfacing.
747
+ - Run **twice with positions swapped**; disagreement between orderings →
748
+ tie.
749
+ - Arena quality uses pairwise judgments plus the descriptive usability
750
+ flag, not numeric scales. The user's coarse main-session vision-fit and
751
+ correction-burden reports (§4.1) are a different instrument and never
752
+ converted into pairwise votes.
753
+ - **Only the overall verdict feeds BT.** Sub-verdicts are recorded
754
+ diagnostics that make verdict notes richer ("mine won on execution, lost
755
+ on escalation quality").
756
+ - Observer model is **pinned and from a different family** than the
757
+ workers where possible (self-preference bias is a perplexity effect — a
758
+ judge sharing the workers' family systematically inflates them).
759
+
760
+ ### Phase 2 — unblinded, diagnostic only
761
+
762
+ - Input: everything — full trajectories, rendered loadout content,
763
+ per-artifact adherence rubrics (rules → verifiable assertions; skills →
764
+ expected trigger conditions, checked both directions: under- and
765
+ over-triggering), cost/time metrics.
766
+ - Output per candidate: **trajectory-derived sub-verdicts** (plan quality,
767
+ delegation effectiveness for orchestrated candidates), grounding counts
768
+ (citations-to-code vs web-fetches per plan), and the adherence report —
769
+ *why* a loadout lost, which rules were violated/ignored, which skills
770
+ fired.
771
+ - **Never feeds the score.** Adherence ≠ quality (ETH Zurich: agents
772
+ followed AGENTS.md faithfully while scoring no better at +20% cost).
773
+ Diagnostics explain outcomes; outcomes are the only score.
774
+ - For a main session, the **process-review judge** produces cited
775
+ steering/consultation episodes using the applicable brief revisions
776
+ (§4.1). It cannot infer private intent or replace the user's quality and
777
+ burden reports. This automation enters at Stage 2 (§11).
778
+ - For an ordinary handoff, an independent artifact review can use the
779
+ brief and preserved output without the trajectory; parent acceptance
780
+ remains separately sourced. This simpler review path enters at Stage 1.
781
+
782
+ ### Placement
783
+
784
+ - **loadouts ships the definitions:** observer agent definition + rubrics
785
+ as versioned artifacts. The observer's own hash goes in each of its
786
+ assessments — otherwise "loadout B improved" and "the judge drifted" are
787
+ indistinguishable. Per-artifact adherence rubrics are emitted at render
788
+ time by the artifact kinds themselves.
789
+ - **The OpenCode plugin/dispatch wrapper ships the integration:** brief
790
+ and session capture, handoff snapshots, worktrees, dispatch, blinding,
791
+ metric extraction, observer invocation, ledger writes, merge trailers,
792
+ and review prompts. Host capabilities are probed before implementation.
793
+ - Escape hatch (v2): observer invocable as an external CLI (`codex exec`,
794
+ `gemini`) so the judge's *harness* is also independent of the harness
795
+ being judged.
796
+
797
+ ### Calibration
798
+
799
+ - In early stages every arena vote is human (merge-gated), so κ
800
+ accumulates for free. Once κ ≥ 0.7, skip-review unlocks and the human
801
+ blind-votes **before** seeing the observer verdict every kth comparison
802
+ (default k=5) forever.
803
+ - Calibration is specific to the review task. Agreement on arena artifact
804
+ choices does not establish reliability at interpreting main-session
805
+ corrections or requirement changes. Validate those findings against
806
+ user-labeled examples; unknown intent stays unknown. User and judge
807
+ assessments of the same artifact are linked, not counted as independent
808
+ task trials.
809
+
810
+ ---
811
+
812
+ ## 8. Records & statistics
813
+
814
+ Reporting is tiered by data volume. Tier 0 is the everyday product; Tier 1
815
+ comes online as votes accumulate and is where **subtle effects become
816
+ detectable** — the same votes that settled big matchups in days keep
817
+ compounding under lineage pooling until 60:40 differences separate from
818
+ noise. Nothing in any tier gates action, and no tier requires a dedicated
819
+ testing campaign: sensitivity is a byproduct of use.
820
+
821
+ ### 8.0 Tier 0 — trend lines and matchup records (always shown)
822
+
823
+ - **Main-session view** (§4.5): vision fit, correction burden, consultation
824
+ findings, cost/time, and experience per lineage. Individual records and
825
+ notes are useful from day one; show trends with **declared changepoints**
826
+ (major-version boundaries, model switches), task type, and expected
827
+ difficulty. Before/after comparisons remain observational. User reports
828
+ and judge findings are labeled separately; missing reviews show as
829
+ missing, and superseded reviews do not add observations.
830
+ - **Handoff view** (§4.5): quality/completeness, first-handoff usability,
831
+ blocker reporting, cost/time, and linked repair/retry burden. Parent
832
+ acceptance and independent reviews are distinct. First and repaired
833
+ results are separately visible, so a parent fixing weak work does not
834
+ inflate the subagent's first-handoff performance.
835
+ - **Whole-work accounting:** linked continuations/retries and descendants
836
+ can be viewed together using §4.3. Show reviewed boundaries and latest
837
+ assessments with coverage; multiple checkpoints on one work item are
838
+ not independent completed tasks. Disposition remains contextual.
839
+ - **Matchup records** per lineage pair: **W–L–T record**, dates, task
840
+ tags, verdict notes, and links back to each comparison (artifacts,
841
+ observer rationale, metrics). Example: `orchestration/mine vs
842
+ orchestration/superpowers: 3–1–1, last 2026-09-12` with one-line notes
843
+ per vote. Decision-grade at expected volumes — a legible 3–1 record with
844
+ notes is exactly the "how am I feeling about these two, and why" answer,
845
+ blind-protected and written down. Revealed-preference comparisons
846
+ display in the record with their validity flags visible, never pooled
847
+ into the W–L–T line silently.
848
+ - Per-candidate **first-handoff usability × task type/difficulty** (the
849
+ capability grid, §3) also lives at this tier. Each assessed candidate
850
+ contributes regardless of who wins, with author, sample count, and
851
+ unassessed coverage visible. Main-session completion rates do not enter
852
+ this grid as evidence of unattended capability.
853
+
854
+ ### 8.1 Tier 1 — ranking model (appears only at volume)
855
+
856
+ Shown for a matchup/factor only once it crosses a vote threshold (default:
857
+ ~15 votes); below that the record view stands alone rather than displaying
858
+ an unstable ranking.
859
+
860
+ - **Custom Bayesian Bradley-Terry, implemented in TypeScript** (~200
861
+ lines: BT is logistic regression on a ±1 design matrix). Weak normal
862
+ priors on factor effects. Chosen over depending on `arena-rank`
863
+ (LMArena's package) after assessment (Sep 2026), because arena-rank
864
+ fails our regime on four counts: (a) competitors are atomic — no
865
+ additive `loadout_effect + model_effect` API (its style-control
866
+ covariates exist only as an example notebook); (b) pure MLE built for
867
+ millions of votes — at personal n, an undefeated loadout causes
868
+ separation (strength → ∞), where a prior yields "strong, wide CI"
869
+ instead; (c) static CIs are not peek-safe, while a posterior can be
870
+ checked daily without inflating false positives — the "statistically
871
+ supported" label (§8.2) is literally `P(A > B | data) ≥ 0.75`; (d) it is
872
+ Python in a TypeScript toolchain.
873
+ - **arena-rank's role: validation oracle, not dependency.** Golden tests
874
+ require our implementation to reproduce its ratings/CIs on shared
875
+ pairwise fixtures (priors relaxed, tolerance-bounded). We inherit its
876
+ correctness without its regime mismatch.
877
+ - **K-way rankings** (from `field` review mode) use a **Plackett-Luce**
878
+ likelihood on the same factor skeleton (PL is BT's ranking
879
+ generalization). Do NOT decompose a 3-way ranking into three independent
880
+ pairwise votes: the derived pairs are correlated and silently inflate n.
881
+ If decomposition is used as a v1 shortcut, downweight — a k-way ranking
882
+ counts as k−1 effective observations, not k(k−1)/2.
883
+ - **Only blind, paired, arity ≥ 2 comparisons of unattended candidates
884
+ enter.** Main-session quality/burden, ordinary handoff reviews, process
885
+ findings, and revealed-preference links inform their respective views,
886
+ never BT. Human and shadow-judge votes on one comparison are linked;
887
+ use the authoritative vote for ranking, not two independent trials.
888
+ - Report CIs (posterior intervals) always; point rankings never stand
889
+ alone.
890
+
891
+ ### 8.2 Confidence labels (advisory, never blocking)
892
+
893
+ - `P(A > B | data) ≥ 0.75` (Cursor's router threshold; configurable) earns
894
+ a matchup a **"statistically supported"** label in the record view. It
895
+ is a display state, not a precondition — the user switches configs
896
+ whenever convinced, and the ledger simply records what the evidence was
897
+ at switch time. Peek-safety comes from the Bayesian posterior (§8.1); no
898
+ separate sequential-testing machinery needed.
899
+ - Rule-of-thumb sample sizes surfaced alongside: a 70:30 edge resolves in
900
+ a few dozen paired votes; 55:45 needs hundreds and will realistically
901
+ never resolve at personal scale — **"within noise" is itself
902
+ actionable** (pick the cheaper/faster one, per the mechanicals and the
903
+ two-stage verdict's revealed tradeoff).
904
+
905
+ ### 8.3 A/A probes
906
+
907
+ - Occasionally the arena silently runs the **same loadout twice**. The
908
+ verdict-margin distribution on A/A runs is the noise floor; if the
909
+ observer (or the user) confidently picks winners in A/A runs, narrow
910
+ verdicts elsewhere get discounted. In manual-dominant usage, the plugin
911
+ occasionally requests an A/A ("calibration run") — user can decline;
912
+ declines are logged. Enters with Stage 2 arenas (§11), before the first narrow
913
+ margin is trusted.
914
+
915
+ ### 8.4 Strata and session tags
916
+
917
+ - **Hard strata** (never silently pooled): `mode` (`manual|auto|shadow`),
918
+ `protocol` (`arena|field|revealed|review`), and `is_aa_probe`. Reviews also
919
+ distinguish main/handoff/process, author, first/repaired result, and
920
+ steered/unattended execution. Main and handoff outcomes never share a
921
+ generic “success rate.” Headline rankings are computed per eligible
922
+ stratum and combined with explicit labeling.
923
+ - **Session tags** (slicing dimensions, pooled by default): every session
924
+ carries `scope` (`global|project`), `project` (when applicable),
925
+ `category`, task type when known, the `orchestrated` facet, and optional
926
+ `diff_size` (`S|M|L`, computed where attribution is available, §4.3).
927
+ Expected difficulty comes from the brief, with source/time and unknown
928
+ retained; it is not derived from the finished diff or phase mix.
929
+ Categories are a fixed, tiny set: `code` (day-to-day software),
930
+ `shorehouse` (research,
931
+ knowledge base, life, reflection), and probably `admin` (task automation
932
+ — searching Slack, making posts, reservations). Multi-valued where work
933
+ genuinely overlaps. Records pool across tags at the loadout's assessment
934
+ scope (§6.5) and can be sliced by any tag — transfer across categories
935
+ is the default assumption, and a sliced record diverging from the pooled
936
+ one is exactly how a transfer failure would surface.
937
+ - Start with cwd/loadout-scope tags and existing request/dispatch metadata,
938
+ with quick manual correction. Small-model category/task tagging enters
939
+ at Stage 3 (§11). Retrospective labels are marked as such; do not
940
+ backfill an allegedly pre-execution difficulty judgment after seeing
941
+ the result. Diff size and phase mix are post-run diagnostic slices,
942
+ not substitutes for expected difficulty or task type.
943
+
944
+ ### 8.5 Post-hoc tools (not metrics)
945
+
946
+ - **Churn analysis**: on-demand ("how much of the arena-merged work from
947
+ lineage X survived?"). Demoted from headline metric: at personal config
948
+ velocity, churn conflates "the work was bad" with "the project moved."
949
+ Useful occasionally as color; never on the panel.
950
+
951
+ ---
952
+
953
+ ## 9. Ledger
954
+
955
+ Append-only JSONL, global location (`~/.local/share/loadouts/registry/`).
956
+ Four row families: `work`, `session`, `handoff`, and `assessment`. They
957
+ separate the intended work, recorded execution, preserved output, and
958
+ interpretation. This is a small file-backed record system; full transcript
959
+ storage and a general-purpose event platform are not required.
960
+
961
+ Every row has a `schema_version`, unique `record_id`, and `recorded_at`.
962
+ Work/session revisions and assessment corrections append with `supersedes`.
963
+ Readers select the current revision for a current view; historical reviews
964
+ retain their exact record references. Re-importing the same source event
965
+ is idempotent. Never sum cumulative session revisions or count corrected
966
+ assessments as additional trials. Cross-author disagreement creates a new
967
+ assessment, not a superseding correction to someone else's judgment.
968
+
969
+ Examples are illustrative; referenced child sessions, brief revisions,
970
+ and usage events are omitted for brevity. Null means unknown/unavailable,
971
+ not zero, failure, or an implied favorable answer.
972
+
973
+ ### Work row: the brief and its revision
974
+
975
+ ```jsonc
976
+ {
977
+ "schema_version": 1, "type": "work", "record_id": "work_main:r1",
978
+ "recorded_at": "2026-09-14T10:00:00Z", "supersedes": null,
979
+ "work_id": "work_main", "parent_work_id": null, "revision": 1,
980
+ "source_refs": ["ses_main/msg_request"],
981
+ "acceptance_refs": ["ses_main/msg_approved_plan"],
982
+ "effective_from": { "session_id": "ses_main", "message_id": "msg_approved_plan" },
983
+ "expected_difficulty": {
984
+ "value": "demanding", // routine | demanding | uncertain
985
+ "source": "user", "source_ref": "ses_main/msg_request",
986
+ "recorded_at": "2026-09-14T10:00:00Z", "before_execution": true
987
+ },
988
+ "task_type": "refactor", "revision_reason": null
989
+ }
990
+ ```
991
+
992
+ A later requirement change appends `work_main:r2` with the new source and
993
+ effective boundary. A summary added after execution cannot masquerade as
994
+ an earlier agreed brief or pre-execution difficulty label.
995
+
996
+ ### Session row: facts local to this session, at a known boundary
997
+
998
+ ```jsonc
999
+ {
1000
+ "schema_version": 1, "type": "session", "record_id": "ses_main:r1",
1001
+ "recorded_at": "2026-09-14T10:20:00Z", "supersedes": null,
1002
+ "session_id": "ses_main", "parent_session": null, "role": "main",
1003
+ "work_id": "work_main", "brief_revision_refs": ["work_main:r1"],
1004
+ "boundary_ref": "ses_main/msg_final",
1005
+ "lineage": "default", "loadout": "default@v12", "loadout_hash": "…",
1006
+ "model": "…", "model_build": null, "config_changes": [],
1007
+ "varied_layer": null,
1008
+ "tags": {
1009
+ "scope": "project", "project": "loadout", "category": ["code"],
1010
+ "orchestrated": true, "diff_size": null
1011
+ },
1012
+ "mechanicals": {
1013
+ "local": { "tokens": 80000, "calls": 20, "cost_usd": 1.20 },
1014
+ "usage_source_refs": ["usage_main_1", "usage_main_2"],
1015
+ "coverage": "complete", // local usage through boundary_ref only
1016
+ "started_at": "2026-09-14T10:00:00Z",
1017
+ "observed_through": "2026-09-14T10:20:00Z",
1018
+ "execution_intervals": null, "known_wait_intervals": null,
1019
+ "diff": { "base_ref": "…", "end_ref": "…", "stats": null, "attribution": "unknown" },
1020
+ "verification_refs": []
1021
+ },
1022
+ "artifact_refs": ["artifact_final"], "merge_refs": [],
1023
+ "links": { "continuation_of": null, "retry_of": null, "repairs_handoff": null },
1024
+ "steering_refs": [],
1025
+ "origin": null, // e.g. reflect@<session>
1026
+ "arena": null // or comparison_id + candidate index
1027
+ }
1028
+ ```
1029
+
1030
+ Child usage is stored on child records. Tree and whole-work totals are
1031
+ derived using §4.3, with coverage carried through. Any config/model change
1032
+ includes its effective boundary; mixed-session aggregates are labeled
1033
+ rather than attributed entirely to the final model/config.
1034
+
1035
+ ### Handoff row: immutable evidence before repair
1036
+
1037
+ ```jsonc
1038
+ {
1039
+ "schema_version": 1, "type": "handoff", "record_id": "handoff_child_1",
1040
+ "recorded_at": "2026-09-14T10:10:00Z",
1041
+ "session_record_id": "ses_child:r1", "brief_revision_ref": "work_child:r1",
1042
+ "sequence": 1, "returned_at": "2026-09-14T10:10:00Z",
1043
+ "message_ref": "ses_child/msg_returned", "previous_handoff_ref": null,
1044
+ "artifact_snapshot": { "ref": "artifact_child_1", "hash": "…" },
1045
+ "report_ref": "report_child_1", "capture_status": "preserved"
1046
+ }
1047
+ ```
1048
+
1049
+ Artifacts/reports are immutable copies or content-addressed refs retained
1050
+ for review. A hash alone cannot recover an overwritten artifact. Missing
1051
+ snapshots are explicitly unavailable. Subsequent repairs/retries link from
1052
+ session records or assessment evidence to this handoff; a later return gets
1053
+ its own handoff record.
1054
+
1055
+ ### Assessment rows: same envelope, role-specific outputs
1056
+
1057
+ **Main-session user review:**
1058
+
1059
+ ```jsonc
1060
+ {
1061
+ "schema_version": 1, "type": "assessment", "record_id": "review_main:r1",
1062
+ "recorded_at": "2026-09-14T10:21:00Z", "supersedes": null,
1063
+ "assessment_id": "review_main", "arity": 1, "protocol": "review", "review_kind": "main",
1064
+ "author": { "kind": "user" },
1065
+ "validity": { "paired": false, "blind": false, "position_swapped": false, "interactive": true },
1066
+ "subjects": [{ "session_record_id": "ses_main:r1", "brief_revision_ref": "work_main:r1", "artifact_ref": "artifact_final" }],
1067
+ "evidence_refs": ["ses_main/msg_correction"],
1068
+ "outputs": {
1069
+ "main": {
1070
+ "vision_fit": "excellent", "correction_burden": "substantial",
1071
+ "consultation": null, "disposition": "completed",
1072
+ "feel": "fine", "note": "Excellent result after I restated the constraint twice."
1073
+ }
1074
+ },
1075
+ "capture": { "skipped_fields": ["consultation"] }
1076
+ }
1077
+ ```
1078
+
1079
+ **Parent handoff review:** an operational judgment, separately sourced from
1080
+ any independent assessment of the same handoff.
1081
+
1082
+ ```jsonc
1083
+ {
1084
+ "schema_version": 1, "type": "assessment", "record_id": "review_handoff:r1",
1085
+ "recorded_at": "2026-09-14T10:12:00Z", "supersedes": null,
1086
+ "assessment_id": "review_handoff", "arity": 1, "protocol": "review", "review_kind": "handoff",
1087
+ "author": { "kind": "parent_agent", "session_id": "ses_main", "model": "…", "agent_hash": "…" },
1088
+ "validity": { "paired": false, "blind": false, "position_swapped": false, "interactive": false },
1089
+ "subjects": [{ "session_record_id": "ses_child:r1", "brief_revision_ref": "work_child:r1", "handoff_ref": "handoff_child_1" }],
1090
+ "evidence_refs": ["artifact_child_1", "ses_main/msg_repair"],
1091
+ "outputs": {
1092
+ "handoff": {
1093
+ "quality_findings": ["Missed the backward-compatibility requirement."],
1094
+ "usability": "needs_repair", "blocker_reporting": null,
1095
+ "downstream_fate": "repaired", "repair_refs": ["ses_main/msg_repair"],
1096
+ "attributed_repair_cost_usd": null
1097
+ }
1098
+ }
1099
+ }
1100
+ ```
1101
+
1102
+ **Human arena comparison:** the shadow judge writes a separate assessment
1103
+ with the same `comparison_id`, its own model/agent/rubric hashes, evidence,
1104
+ and outputs. Process analysis is a separate `review_kind: process` record.
1105
+
1106
+ ```jsonc
1107
+ {
1108
+ "schema_version": 1, "type": "assessment", "record_id": "review_arena:r1",
1109
+ "recorded_at": "2026-09-14T11:00:00Z", "supersedes": null,
1110
+ "assessment_id": "review_arena", "comparison_id": "arena_1",
1111
+ "arity": 2, "protocol": "arena", "review_kind": "comparison", "mode": "manual",
1112
+ "author": { "kind": "user" },
1113
+ "validity": { "paired": true, "blind": true, "position_swapped": false, "interactive": false },
1114
+ "subjects": [
1115
+ { "session_record_id": "ses_a:r1", "brief_revision_ref": "work_arena:r1", "handoff_ref": "handoff_a" },
1116
+ { "session_record_id": "ses_b:r1", "brief_revision_ref": "work_arena:r1", "handoff_ref": "handoff_b" }
1117
+ ],
1118
+ "evidence_refs": ["artifact_a", "artifact_b"],
1119
+ "task_prompt_hash": "…", "base_commit": "…", "is_aa_probe": false,
1120
+ "presentation_order": [1, 0], // randomized; positions swapped in judge's own assessment
1121
+ "outputs": {
1122
+ "comparison": {
1123
+ "review_mode": "pair", "blind_quality_vote": 0,
1124
+ "atc_pick": 1, // after reveal; validity.blind applies to quality vote only
1125
+ "note": "A was stronger, but B was good enough and much faster.",
1126
+ "usability": { "0": "usable_as_is", "1": "usable_as_is" }
1127
+ }
1128
+ },
1129
+ "observer_assessment_ref": "review_observer:r1", "merge_ref": null
1130
+ }
1131
+ ```
1132
+
1133
+ Store blind-vote and reveal timestamps when implementing the arena flow.
1134
+ Later merge fate appends a linked session revision; it does not mutate a
1135
+ blind vote. Only the authoritative quality vote enters rankings (§8.1).
1136
+ Vetoes/off windows remain recorded arena-control metadata with reasons.
1137
+
1138
+ Loser refs: `refs/arena/<comparison-id>/<n>` — invisible, free, recoverable
1139
+ for later "actually B's approach was right" re-votes (recorded as
1140
+ `revealed` assessments).
1141
+
1142
+ ---
1143
+
1144
+ ## 10. TUI surface (OpenCode V2)
1145
+
1146
+ Per `docs/tui-architecture.md`, OpenCode gets a thin `@opentui/solid`
1147
+ skin. The registry + arena adds six flows, in build order (§11):
1148
+
1149
+ 1. **Main-session review** (§5.2): two quick choices — vision fit and
1150
+ correction burden — with feel, note, disposition, and consultation
1151
+ example available alongside them. Skip/unknown is explicit. Review
1152
+ targets a named work/session checkpoint, offered at the dogfooded
1153
+ trigger or opened directly; resumed work is not silently included.
1154
+ 2. **Brief/handoff detail**: links to the original request or dispatch,
1155
+ approved plan, expected difficulty, and brief revisions. A subagent
1156
+ return opens its preserved artifact/report, with parent acceptance,
1157
+ repair/retry links, and independent review shown as separate sources.
1158
+ Creating a brief or preserving a handoff requires no form by default.
1159
+ 3. **Record view**: main and handoff views (§4.5, §8.0), filterable by task
1160
+ type and expected difficulty. Show quality, burden, time, and cost
1161
+ together; distinguish first and repaired handoffs, author, reviewed
1162
+ boundary, and coverage. Add matchup W–L–T records and the capability
1163
+ grid as comparisons arrive. Intervals/rankings appear only at volume.
1164
+ Reuse the shared output conventions (`docs/visual-language.md`);
1165
+ unknown and insufficient data are first-class display states.
1166
+ 4. **Picker** (at `/arena` or intercepted dispatch): multi-select
1167
+ loadouts, multi-select models, N-permutation preview with cost
1168
+ estimate, brief revision and task-tag confirmation, go/veto. Veto
1169
+ prompts for a one-word reason.
1170
+ 5. **Status panel** (sidebar): running candidates, elapsed, token burn,
1171
+ per-candidate test status. No identities hidden here — blinding applies
1172
+ to *artifact review*, not to the fact that an arena is running. On
1173
+ *every* session (arena or not), the sidebar also shows the session tags
1174
+ (§8.4) with a one-keystroke popup to correct them — the registry's only
1175
+ always-on UI. The same popup opens the main-session review at any time
1176
+ (§5.2) and links to the current brief and known difficulty source.
1177
+ 6. **Verdict flow**: blind side-by-side artifact review (anonymized,
1178
+ position-randomized, **costs hidden**). In `pair` mode: the final pair,
1179
+ vote keys (`1`/`2`/`t`). In `field` mode: tabbed/cycled view of up to
1180
+ 3–4 candidates, rank entry with ties (`1>2=3`). Vote → **one-line note
1181
+ prompt** (skippable but nudged) → reveal: identities, observer verdict
1182
+ + rationale with citations, metrics table → **all-things-considered
1183
+ pick** (defaults to the blind vote — enter merges; overriding takes one
1184
+ extra keystroke, §6.4) → merge confirmation.
1185
+
1186
+ CLI parity: every flow scriptable (proposed surface:
1187
+ `loadouts registry log|brief|handoff|review|panel`,
1188
+ `loadouts arena run|record|status|vote|stats`) per the TUI-is-additive
1189
+ principle. CLI capture/views land before the host-specific UI. These are
1190
+ planned commands, not claims of existing functionality.
1191
+
1192
+ ---
1193
+
1194
+ ## 11. Staging: build order and entry criteria
1195
+
1196
+ The machinery budget is a standing constraint: one maintainer, a beta host
1197
+ API, and a design whose value depends on the loop *actually closing* every
1198
+ day. Each stage must prove its premise before the next is built; each
1199
+ deferred component has a named entry criterion, and components that never
1200
+ meet their criterion never get built.
1201
+
1202
+ ### Stage 0 — facts plus main-session quality and burden
1203
+
1204
+ Render-time loadout hashing → brief/source references and session records
1205
+ → local usage/timing with honest tree rollups → preserved subagent handoffs
1206
+ → lightweight main-session quality/burden review → CLI main-session view.
1207
+ Feel and notes are available from the start. Unknown difficulty or missing
1208
+ automated extraction does not prevent a record; manual references/capture
1209
+ can establish the same schema first.
1210
+
1211
+ *Proves:* the review habit sticks, source attribution works, and records
1212
+ distinguish “excellent with little help” from “excellent after rescue.”
1213
+ Basic quality and correction capture are required here, not deferred until
1214
+ cost trends look interesting. Coverage/skip rates measure capture burden.
1215
+
1216
+ *Entry probes for automatic integration (before committing to a host API):*
1217
+
1218
+ 1. **Review timing and boundaries:** test next-session-start, explicit
1219
+ checkpoint/sidebar capture, and close/idle only if available. Does the
1220
+ prompt refer to the intended work, including concurrent/resumed
1221
+ sessions? A throwaway probe per `docs/opencode-v2-runtime.md` §8 tests
1222
+ the API; dogfooding tests the human burden.
1223
+ 2. **Facts and usage extraction:** inspect real main/subagent session data
1224
+ for message IDs, configuration provenance, local usage events,
1225
+ timestamps, and parentage. Start with session API inspection, then
1226
+ verify message/usage sources and deduplication against known totals.
1227
+ Confirm intervals/coverage rather than promising attention measurement
1228
+ or deriving wall-clock by summing children. Diff attribution needs its
1229
+ own base/end evidence; session metadata alone does not establish it.
1230
+ 3. **Handoff preservation:** can the integration capture the returned
1231
+ artifact/report before parent edits? Verify a preserved first handoff
1232
+ remains retrievable after the parent repairs it. Use a dispatch wrapper
1233
+ or manual snapshot if necessary; mark missed evidence unavailable.
1234
+
1235
+ *Unblocked now:* hashing, ledger storage, manual brief/handoff/review
1236
+ capture, CLI record views, and `arena record` need no V2 plugin API.
1237
+
1238
+ *Escape hatch:* `loadouts arena record` accepts **manually-run
1239
+ comparisons** — the user dispatches two subagents themselves and records a
1240
+ vote via CLI. Unblinded, low validity flags, honest about both — but it
1241
+ exercises the schema and starts matchup records (e.g. orchestration/mine
1242
+ vs superpowers) before Stage 2 arena automation exists.
1243
+
1244
+ ### Stage 1 — handoff assessments and simple comparisons
1245
+
1246
+ Parent acceptance/repair/retry records → user or independent handoff review
1247
+ → CLI handoff view and capability grid, with first and repaired outputs
1248
+ separate. Compare ordinary records by task type and expected difficulty,
1249
+ with source and coverage visible. They remain observational comparisons.
1250
+
1251
+ *Proves:* a parent repairing weak subagent work no longer hides that
1252
+ weakness, and the records inform a real delegation/model/config choice.
1253
+
1254
+ ### Stage 2 — targeted process analysis and paired arenas
1255
+
1256
+ Two additions can earn entry independently:
1257
+
1258
+ - **Steering/consultation analysis:** on-demand judge proposals with
1259
+ evidence and user-correctable labels. Enters when coarse burden reports
1260
+ raise a recurring question about corrections or consultation. Validate
1261
+ against user-labeled episodes and brief revisions before showing rates.
1262
+ - **Manual paired arena:** enters when a concrete config/model choice
1263
+ warrants running the same assignment twice. Uses the existing brief and
1264
+ preserved-handoff machinery, N=2, code + shorehouse categories, worktree
1265
+ render, identical dispatch, two-stage merge-gated verdict, and a shadow
1266
+ observer (§7). A/A calibration is available before trusting narrow wins.
1267
+
1268
+ *Proves:* process findings explain actionable sources of corrective burden;
1269
+ paired comparisons close under real use and improve a specific choice.
1270
+ Neither addition is required to keep ordinary sessions useful.
1271
+
1272
+ ### Stage 3 — further earned machinery
1273
+
1274
+ | Component | Entry criterion |
1275
+ |---|---|
1276
+ | BT posteriors (§8.1) | first matchup crosses ~15 votes |
1277
+ | Small-model auto-tagging (§8.4) | first wanted slice that cwd-derived tags can't provide |
1278
+ | Phase profiling (§4.3) | a recurring quality/burden/cost question needs an activity breakdown |
1279
+ | Plan-arena (§6.3) | first real admin comparison worth running |
1280
+ | `field` review mode / multi-way | first deliberate experiment needing N>2 |
1281
+ | Observer skip-review authority | κ ≥ 0.7 sustained |
1282
+ | `auto`/`shadow` modes | user wants generalization beyond arena-chosen tasks |
1283
+ | `/reflect` writes provenance to spine | reflection integration is in use and its edits need attribution |
1284
+ | Weekly digest / scheduled reviews | user asks for the same manual review twice in one week |
1285
+
1286
+ ---
1287
+
1288
+ ## 12. Open questions
1289
+
1290
+ 1. **Task-tag taxonomy** — categories are settled at 2–3 (`code`,
1291
+ `shorehouse`, maybe `admin`); still open: the final fixed set of
1292
+ *task_tags* within them, and which small model does the auto-tagging
1293
+ (cheap local classifier vs one-shot LLM call). Keep expected difficulty
1294
+ separate from post-run diff size and phase mix. Which brief-derived
1295
+ labels provide useful slices without becoming another form to fill in?
1296
+ 2. **Process and phase-profile reliability** — validate correction,
1297
+ useful/unnecessary consultation, missed consultation, and requirement
1298
+ revision labels against user-labeled episodes, including ambiguous
1299
+ intent. Arena-vote agreement is not calibration for these tasks. For
1300
+ phases, settle the unit (token spans vs turns), coverage, and taxonomy
1301
+ across categories; assess agreement on span labels and error in
1302
+ aggregate shares separately. Validate before promoting outputs to trends.
1303
+ 3. **Novelty settling window** — how long after a changepoint before the
1304
+ experience trend counts (fixed days vs session count vs fitted).
1305
+ 4. **Work and repair linking** — when can a continuation/retry/repair be
1306
+ linked from explicit dispatch metadata, and when is user confirmation
1307
+ needed? How should a parent-session repair span distinguish necessary
1308
+ integration from correcting a defective handoff? Uncertain links and
1309
+ unisolatable repair costs remain unknown.
1310
+ 5. **Review ergonomics** — do the two primary questions capture vision fit
1311
+ and burden well, with feel/note available? Does trust/confidence need a
1312
+ monthly explicit check-in? Which review timing works for resumed and
1313
+ concurrent sessions without equating inactivity with abandonment?
1314
+ 6. **Ledger format versioning** — location is settled (global; sessions
1315
+ cross projects); how rows migrate when the schema evolves.
1316
+ 7. **Observer context budget** — large artifacts may exceed the observer's
1317
+ window; chunked review vs file-level sampling vs summary-then-drill.
1318
+ 8. **Merge conflicts on winner pull-back** — the primary worktree may have
1319
+ advanced during the arena; rebase policy needed.
1320
+ 9. **Cost governor** — weekly arena budget config; whether multi-way
1321
+ arenas draw from a separate deliberate-experiment budget; judge-cost
1322
+ governance once automated process reviews exist.
1323
+ 10. **Eligibility rules for auto mode** — subagent-style dispatches only,
1324
+ or an explicit `#arena-ok` opt-in? (Deferred with auto mode itself.)
1325
+ 11. **V2 API drift** — §5 and §10 wait on the V2 plugin surface settling;
1326
+ re-verify against `docs/opencode-v2-runtime.md` probes before
1327
+ implementation.
1328
+
1329
+ ## 13. Research grounding (selected)
1330
+
1331
+ The full evidence base with citations lives in the Shorehouse Library
1332
+ (`R. Evaluating Personal AI Coding Agent Configurations`). Load-bearing
1333
+ results for this design:
1334
+
1335
+ - Paired same-task comparison ≈ 10x sample efficiency vs between-task A/B
1336
+ (interleaving literature; Copilot Arena's in-flow pairing).
1337
+ - Perception fails **as a proxy**: METR RCT's 40-point believed-vs-measured
1338
+ gap motivates measuring time/cost directly rather than inferring them
1339
+ from felt productivity. Main-session vision fit and correction burden
1340
+ are explicitly user judgments, not measurements of objective speed or
1341
+ autonomous quality. Experience follows the patient-reported-outcome model
1342
+ (subjective endpoints measured as themselves; honesty rule 6).
1343
+ - Agent-as-a-Judge: trajectory-grading observer agents reach 90%
1344
+ human-consensus agreement (vs 70% for chat-grading); judges need tools,
1345
+ calibration, and a different model family (self-preference bias).
1346
+ - Pairwise > pointwise for selection decisions (~61% vs ~21% signal
1347
+ recovery) — why arena selection uses comparative artifact votes and
1348
+ `A|B|tie` sub-verdicts. Everyday vision-fit/burden labels describe the
1349
+ user's collaboration with the harness; they are not a substitute for
1350
+ blind comparative evidence and never enter BT.
1351
+ - Adherence ≠ quality (ETH Zurich AGENTS.md study) — hence the phase 1 /
1352
+ phase 2 information boundary.
1353
+ - Config effects are large but non-transferable across users (Arize +5–11%
1354
+ vs ETH null-to-negative; per-user rankings ρ≈0.04 vs global
1355
+ leaderboards) — the reason this system exists at all. Within one user's
1356
+ contexts, transfer is the default assumption, subject to tag-sliced
1357
+ disconfirmation (§8.4).
1358
+ - Acceptance tracks perception, not reality (Ziegler et al.) — why
1359
+ parent acceptance and completed disposition do not establish excellent
1360
+ work. Preserve the first handoff for artifact assessment, and keep later
1361
+ repair visible. Churn-based persistence remains a post-hoc tool rather
1362
+ than ground truth at personal config velocity.
1363
+ - Design frames borrowed from clinical research: **registry with embedded
1364
+ trials** (observational spine + nested randomized comparisons),
1365
+ **interrupted time-series** for N=1 changepoint analysis, and
1366
+ **patient-reported outcomes** for the experience lane.