@oneharness/sdk 0.6.14 → 0.6.15

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 (47) hide show
  1. package/README.md +1 -1
  2. package/dist/generated/capabilities.d.ts +1010 -0
  3. package/dist/generated/capabilities.js +1162 -0
  4. package/dist/generated/config-options.d.ts +8 -0
  5. package/dist/generated/config-options.js +2 -0
  6. package/dist/generated/config-report.d.ts +283 -0
  7. package/dist/generated/config-report.js +2 -0
  8. package/dist/generated/detect-options.d.ts +19 -0
  9. package/dist/generated/detect-options.js +2 -0
  10. package/dist/generated/detection.d.ts +6 -0
  11. package/dist/generated/gate-options.d.ts +17 -0
  12. package/dist/generated/gate-options.js +2 -0
  13. package/dist/generated/history-clear-options.d.ts +15 -0
  14. package/dist/generated/history-clear-options.js +2 -0
  15. package/dist/generated/history-clear-report.d.ts +39 -0
  16. package/dist/generated/history-clear-report.js +2 -0
  17. package/dist/generated/history-list-options.d.ts +13 -0
  18. package/dist/generated/history-lookup.d.ts +26 -0
  19. package/dist/generated/history-migrate-options.d.ts +8 -0
  20. package/dist/generated/history-migrate-options.js +2 -0
  21. package/dist/generated/history-migrate-report.d.ts +31 -0
  22. package/dist/generated/history-migrate-report.js +2 -0
  23. package/dist/generated/history-watch-options.d.ts +13 -0
  24. package/dist/generated/init-options.d.ts +11 -0
  25. package/dist/generated/init-options.js +2 -0
  26. package/dist/generated/interrupt-options.d.ts +12 -0
  27. package/dist/generated/interrupt-options.js +2 -0
  28. package/dist/generated/interrupt-response.d.ts +40 -0
  29. package/dist/generated/interrupt-response.js +2 -0
  30. package/dist/generated/mock-options.d.ts +12 -0
  31. package/dist/generated/mock-options.js +2 -0
  32. package/dist/generated/options.d.ts +108 -0
  33. package/dist/generated/registry.d.ts +14 -4
  34. package/dist/generated/schemas.json +3245 -15
  35. package/dist/generated/sync-options.d.ts +14 -0
  36. package/dist/generated/sync-options.js +2 -0
  37. package/dist/generated/sync-report.d.ts +64 -0
  38. package/dist/generated/sync-report.js +2 -0
  39. package/dist/generated/usage-options.d.ts +15 -0
  40. package/dist/generated/usage-options.js +2 -0
  41. package/dist/generated/usage-report.d.ts +241 -0
  42. package/dist/generated/usage-report.js +2 -0
  43. package/dist/generated/zod.d.ts +70 -2
  44. package/dist/generated/zod.js +444 -0
  45. package/dist/index.d.ts +91 -1
  46. package/dist/index.js +271 -102
  47. package/package.json +2 -2
@@ -1,4 +1,1232 @@
1
1
  {
2
+ "capabilities": [
3
+ {
4
+ "method": "run",
5
+ "argv": [
6
+ "run"
7
+ ],
8
+ "options": "run_options",
9
+ "output": "run_report",
10
+ "stdout": "json",
11
+ "stdin": false,
12
+ "rust": "oneharness_core::io::run::run",
13
+ "always": [
14
+ "--compact",
15
+ "--no-stream"
16
+ ],
17
+ "bindings": [
18
+ {
19
+ "option": "prompt",
20
+ "flag": "--prompt",
21
+ "kind": "value",
22
+ "unless": null
23
+ },
24
+ {
25
+ "option": "batchPrompts",
26
+ "flag": "--prompt",
27
+ "kind": "repeated",
28
+ "unless": null
29
+ },
30
+ {
31
+ "option": "promptFiles",
32
+ "flag": "--prompt-file",
33
+ "kind": "repeated",
34
+ "unless": null
35
+ },
36
+ {
37
+ "option": "harnesses",
38
+ "flag": "--harness",
39
+ "kind": "repeated",
40
+ "unless": null
41
+ },
42
+ {
43
+ "option": "mockHarnesses",
44
+ "flag": "--mock-harness",
45
+ "kind": "repeated",
46
+ "unless": null
47
+ },
48
+ {
49
+ "option": "all",
50
+ "flag": "--all",
51
+ "kind": "switch",
52
+ "unless": "harnesses"
53
+ },
54
+ {
55
+ "option": "exclude",
56
+ "flag": "--exclude",
57
+ "kind": "repeated",
58
+ "unless": null
59
+ },
60
+ {
61
+ "option": "models",
62
+ "flag": "--model",
63
+ "kind": "repeated",
64
+ "unless": null
65
+ },
66
+ {
67
+ "option": "system",
68
+ "flag": "--system",
69
+ "kind": "value",
70
+ "unless": null
71
+ },
72
+ {
73
+ "option": "systemFile",
74
+ "flag": "--system-file",
75
+ "kind": "value",
76
+ "unless": "system"
77
+ },
78
+ {
79
+ "option": "reasoning",
80
+ "flag": "--reasoning",
81
+ "kind": "value",
82
+ "unless": null
83
+ },
84
+ {
85
+ "option": "resume",
86
+ "flag": "--resume",
87
+ "kind": "value",
88
+ "unless": null
89
+ },
90
+ {
91
+ "option": "fork",
92
+ "flag": "--fork",
93
+ "kind": "switch",
94
+ "unless": null
95
+ },
96
+ {
97
+ "option": "session",
98
+ "flag": "--session",
99
+ "kind": "value",
100
+ "unless": null
101
+ },
102
+ {
103
+ "option": "sessionDir",
104
+ "flag": "--session-dir",
105
+ "kind": "value",
106
+ "unless": null
107
+ },
108
+ {
109
+ "option": "control",
110
+ "flag": "--control",
111
+ "kind": "switch",
112
+ "unless": null
113
+ },
114
+ {
115
+ "option": "outputFormat",
116
+ "flag": "--output-format",
117
+ "kind": "value",
118
+ "unless": null
119
+ },
120
+ {
121
+ "option": "events",
122
+ "flag": "--events",
123
+ "kind": "switch",
124
+ "unless": null
125
+ },
126
+ {
127
+ "option": "mockRules",
128
+ "flag": "--mock-rules",
129
+ "kind": "value",
130
+ "unless": null
131
+ },
132
+ {
133
+ "option": "spyFile",
134
+ "flag": "--spy-file",
135
+ "kind": "value",
136
+ "unless": null
137
+ },
138
+ {
139
+ "option": "schema",
140
+ "flag": "--schema",
141
+ "kind": "value",
142
+ "unless": null
143
+ },
144
+ {
145
+ "option": "schemaMaxRetries",
146
+ "flag": "--schema-max-retries",
147
+ "kind": "value",
148
+ "unless": null
149
+ },
150
+ {
151
+ "option": "outputDir",
152
+ "flag": "--output-dir",
153
+ "kind": "value",
154
+ "unless": null
155
+ },
156
+ {
157
+ "option": "timeoutSeconds",
158
+ "flag": "--timeout",
159
+ "kind": "value",
160
+ "unless": null
161
+ },
162
+ {
163
+ "option": "cwd",
164
+ "flag": "--cwd",
165
+ "kind": "value",
166
+ "unless": null
167
+ },
168
+ {
169
+ "option": "env",
170
+ "flag": "--env",
171
+ "kind": "key-value",
172
+ "unless": null
173
+ },
174
+ {
175
+ "option": "mode",
176
+ "flag": "--mode",
177
+ "kind": "value",
178
+ "unless": null
179
+ },
180
+ {
181
+ "option": "permitPrompts",
182
+ "flag": "--permit-prompts",
183
+ "kind": "switch",
184
+ "unless": null
185
+ },
186
+ {
187
+ "option": "config",
188
+ "flag": "--config",
189
+ "kind": "value",
190
+ "unless": "noConfig"
191
+ },
192
+ {
193
+ "option": "noConfig",
194
+ "flag": "--no-config",
195
+ "kind": "switch",
196
+ "unless": null
197
+ },
198
+ {
199
+ "option": "maxParallel",
200
+ "flag": "--max-parallel",
201
+ "kind": "value",
202
+ "unless": null
203
+ },
204
+ {
205
+ "option": "batchStrategy",
206
+ "flag": "--batch-strategy",
207
+ "kind": "value",
208
+ "unless": null
209
+ },
210
+ {
211
+ "option": "runMode",
212
+ "flag": "--run-mode",
213
+ "kind": "value",
214
+ "unless": null
215
+ },
216
+ {
217
+ "option": "printCommand",
218
+ "flag": "--print-command",
219
+ "kind": "switch",
220
+ "unless": null
221
+ },
222
+ {
223
+ "option": "bins",
224
+ "flag": "--bin",
225
+ "kind": "key-value",
226
+ "unless": null
227
+ },
228
+ {
229
+ "option": "requireAvailable",
230
+ "flag": "--require-available",
231
+ "kind": "switch",
232
+ "unless": null
233
+ },
234
+ {
235
+ "option": "history",
236
+ "flag": "--history",
237
+ "kind": "switch",
238
+ "unless": "noHistory"
239
+ },
240
+ {
241
+ "option": "noHistory",
242
+ "flag": "--no-history",
243
+ "kind": "switch",
244
+ "unless": null
245
+ },
246
+ {
247
+ "option": "historyDir",
248
+ "flag": "--history-dir",
249
+ "kind": "value",
250
+ "unless": null
251
+ },
252
+ {
253
+ "option": "historyName",
254
+ "flag": "--history-name",
255
+ "kind": "value",
256
+ "unless": null
257
+ },
258
+ {
259
+ "option": "historyLabels",
260
+ "flag": "--history-label",
261
+ "kind": "key-value",
262
+ "unless": null
263
+ },
264
+ {
265
+ "option": "passthrough",
266
+ "flag": "",
267
+ "kind": "trailing",
268
+ "unless": null
269
+ }
270
+ ],
271
+ "uncovered": [
272
+ {
273
+ "flag": "--bypass",
274
+ "reason": "`mode: \"bypass\"` is the same request"
275
+ },
276
+ {
277
+ "flag": "--no-bypass",
278
+ "reason": "`mode: \"default\"` is the same request"
279
+ },
280
+ {
281
+ "flag": "--stream",
282
+ "reason": "`runStream()` is the streaming method; this one returns one report"
283
+ }
284
+ ]
285
+ },
286
+ {
287
+ "method": "runStream",
288
+ "argv": [
289
+ "run"
290
+ ],
291
+ "options": "run_options",
292
+ "output": "run_stream_envelope",
293
+ "stdout": "jsonl",
294
+ "stdin": false,
295
+ "rust": "oneharness_core::io::run::run",
296
+ "always": [
297
+ "--compact",
298
+ "--stream"
299
+ ],
300
+ "bindings": [
301
+ {
302
+ "option": "prompt",
303
+ "flag": "--prompt",
304
+ "kind": "value",
305
+ "unless": null
306
+ },
307
+ {
308
+ "option": "batchPrompts",
309
+ "flag": "--prompt",
310
+ "kind": "repeated",
311
+ "unless": null
312
+ },
313
+ {
314
+ "option": "promptFiles",
315
+ "flag": "--prompt-file",
316
+ "kind": "repeated",
317
+ "unless": null
318
+ },
319
+ {
320
+ "option": "harnesses",
321
+ "flag": "--harness",
322
+ "kind": "repeated",
323
+ "unless": null
324
+ },
325
+ {
326
+ "option": "mockHarnesses",
327
+ "flag": "--mock-harness",
328
+ "kind": "repeated",
329
+ "unless": null
330
+ },
331
+ {
332
+ "option": "all",
333
+ "flag": "--all",
334
+ "kind": "switch",
335
+ "unless": "harnesses"
336
+ },
337
+ {
338
+ "option": "exclude",
339
+ "flag": "--exclude",
340
+ "kind": "repeated",
341
+ "unless": null
342
+ },
343
+ {
344
+ "option": "models",
345
+ "flag": "--model",
346
+ "kind": "repeated",
347
+ "unless": null
348
+ },
349
+ {
350
+ "option": "system",
351
+ "flag": "--system",
352
+ "kind": "value",
353
+ "unless": null
354
+ },
355
+ {
356
+ "option": "systemFile",
357
+ "flag": "--system-file",
358
+ "kind": "value",
359
+ "unless": "system"
360
+ },
361
+ {
362
+ "option": "reasoning",
363
+ "flag": "--reasoning",
364
+ "kind": "value",
365
+ "unless": null
366
+ },
367
+ {
368
+ "option": "resume",
369
+ "flag": "--resume",
370
+ "kind": "value",
371
+ "unless": null
372
+ },
373
+ {
374
+ "option": "fork",
375
+ "flag": "--fork",
376
+ "kind": "switch",
377
+ "unless": null
378
+ },
379
+ {
380
+ "option": "session",
381
+ "flag": "--session",
382
+ "kind": "value",
383
+ "unless": null
384
+ },
385
+ {
386
+ "option": "sessionDir",
387
+ "flag": "--session-dir",
388
+ "kind": "value",
389
+ "unless": null
390
+ },
391
+ {
392
+ "option": "control",
393
+ "flag": "--control",
394
+ "kind": "switch",
395
+ "unless": null
396
+ },
397
+ {
398
+ "option": "outputFormat",
399
+ "flag": "--output-format",
400
+ "kind": "value",
401
+ "unless": null
402
+ },
403
+ {
404
+ "option": "events",
405
+ "flag": "--events",
406
+ "kind": "switch",
407
+ "unless": null
408
+ },
409
+ {
410
+ "option": "mockRules",
411
+ "flag": "--mock-rules",
412
+ "kind": "value",
413
+ "unless": null
414
+ },
415
+ {
416
+ "option": "spyFile",
417
+ "flag": "--spy-file",
418
+ "kind": "value",
419
+ "unless": null
420
+ },
421
+ {
422
+ "option": "schema",
423
+ "flag": "--schema",
424
+ "kind": "value",
425
+ "unless": null
426
+ },
427
+ {
428
+ "option": "schemaMaxRetries",
429
+ "flag": "--schema-max-retries",
430
+ "kind": "value",
431
+ "unless": null
432
+ },
433
+ {
434
+ "option": "outputDir",
435
+ "flag": "--output-dir",
436
+ "kind": "value",
437
+ "unless": null
438
+ },
439
+ {
440
+ "option": "timeoutSeconds",
441
+ "flag": "--timeout",
442
+ "kind": "value",
443
+ "unless": null
444
+ },
445
+ {
446
+ "option": "cwd",
447
+ "flag": "--cwd",
448
+ "kind": "value",
449
+ "unless": null
450
+ },
451
+ {
452
+ "option": "env",
453
+ "flag": "--env",
454
+ "kind": "key-value",
455
+ "unless": null
456
+ },
457
+ {
458
+ "option": "mode",
459
+ "flag": "--mode",
460
+ "kind": "value",
461
+ "unless": null
462
+ },
463
+ {
464
+ "option": "permitPrompts",
465
+ "flag": "--permit-prompts",
466
+ "kind": "switch",
467
+ "unless": null
468
+ },
469
+ {
470
+ "option": "config",
471
+ "flag": "--config",
472
+ "kind": "value",
473
+ "unless": "noConfig"
474
+ },
475
+ {
476
+ "option": "noConfig",
477
+ "flag": "--no-config",
478
+ "kind": "switch",
479
+ "unless": null
480
+ },
481
+ {
482
+ "option": "maxParallel",
483
+ "flag": "--max-parallel",
484
+ "kind": "value",
485
+ "unless": null
486
+ },
487
+ {
488
+ "option": "batchStrategy",
489
+ "flag": "--batch-strategy",
490
+ "kind": "value",
491
+ "unless": null
492
+ },
493
+ {
494
+ "option": "runMode",
495
+ "flag": "--run-mode",
496
+ "kind": "value",
497
+ "unless": null
498
+ },
499
+ {
500
+ "option": "printCommand",
501
+ "flag": "--print-command",
502
+ "kind": "switch",
503
+ "unless": null
504
+ },
505
+ {
506
+ "option": "bins",
507
+ "flag": "--bin",
508
+ "kind": "key-value",
509
+ "unless": null
510
+ },
511
+ {
512
+ "option": "requireAvailable",
513
+ "flag": "--require-available",
514
+ "kind": "switch",
515
+ "unless": null
516
+ },
517
+ {
518
+ "option": "history",
519
+ "flag": "--history",
520
+ "kind": "switch",
521
+ "unless": "noHistory"
522
+ },
523
+ {
524
+ "option": "noHistory",
525
+ "flag": "--no-history",
526
+ "kind": "switch",
527
+ "unless": null
528
+ },
529
+ {
530
+ "option": "historyDir",
531
+ "flag": "--history-dir",
532
+ "kind": "value",
533
+ "unless": null
534
+ },
535
+ {
536
+ "option": "historyName",
537
+ "flag": "--history-name",
538
+ "kind": "value",
539
+ "unless": null
540
+ },
541
+ {
542
+ "option": "historyLabels",
543
+ "flag": "--history-label",
544
+ "kind": "key-value",
545
+ "unless": null
546
+ },
547
+ {
548
+ "option": "passthrough",
549
+ "flag": "",
550
+ "kind": "trailing",
551
+ "unless": null
552
+ }
553
+ ],
554
+ "uncovered": [
555
+ {
556
+ "flag": "--bypass",
557
+ "reason": "`mode: \"bypass\"` is the same request"
558
+ },
559
+ {
560
+ "flag": "--no-bypass",
561
+ "reason": "`mode: \"default\"` is the same request"
562
+ },
563
+ {
564
+ "flag": "--no-stream",
565
+ "reason": "this method streams by definition, so the negative half cannot apply"
566
+ }
567
+ ]
568
+ },
569
+ {
570
+ "method": "list",
571
+ "argv": [
572
+ "list"
573
+ ],
574
+ "options": null,
575
+ "output": "list_report",
576
+ "stdout": "json",
577
+ "stdin": false,
578
+ "rust": "oneharness_core::io::registry::list",
579
+ "always": [
580
+ "--compact"
581
+ ],
582
+ "bindings": [],
583
+ "uncovered": []
584
+ },
585
+ {
586
+ "method": "detect",
587
+ "argv": [
588
+ "detect"
589
+ ],
590
+ "options": "detect_options",
591
+ "output": "detect_report",
592
+ "stdout": "json",
593
+ "stdin": false,
594
+ "rust": "oneharness_core::io::detect::detect",
595
+ "always": [
596
+ "--compact"
597
+ ],
598
+ "bindings": [
599
+ {
600
+ "option": "harnesses",
601
+ "flag": "--harness",
602
+ "kind": "repeated",
603
+ "unless": null
604
+ },
605
+ {
606
+ "option": "all",
607
+ "flag": "--all",
608
+ "kind": "switch",
609
+ "unless": "harnesses"
610
+ },
611
+ {
612
+ "option": "exclude",
613
+ "flag": "--exclude",
614
+ "kind": "repeated",
615
+ "unless": null
616
+ },
617
+ {
618
+ "option": "bins",
619
+ "flag": "--bin",
620
+ "kind": "key-value",
621
+ "unless": null
622
+ },
623
+ {
624
+ "option": "config",
625
+ "flag": "--config",
626
+ "kind": "value",
627
+ "unless": "noConfig"
628
+ },
629
+ {
630
+ "option": "noConfig",
631
+ "flag": "--no-config",
632
+ "kind": "switch",
633
+ "unless": null
634
+ },
635
+ {
636
+ "option": "requireAvailable",
637
+ "flag": "--require-available",
638
+ "kind": "switch",
639
+ "unless": null
640
+ }
641
+ ],
642
+ "uncovered": []
643
+ },
644
+ {
645
+ "method": "config",
646
+ "argv": [
647
+ "config"
648
+ ],
649
+ "options": "config_options",
650
+ "output": "config_report",
651
+ "stdout": "json",
652
+ "stdin": false,
653
+ "rust": "oneharness_core::domain::config::explain",
654
+ "always": [
655
+ "--compact"
656
+ ],
657
+ "bindings": [
658
+ {
659
+ "option": "cwd",
660
+ "flag": "--cwd",
661
+ "kind": "value",
662
+ "unless": null
663
+ },
664
+ {
665
+ "option": "config",
666
+ "flag": "--config",
667
+ "kind": "value",
668
+ "unless": "noConfig"
669
+ },
670
+ {
671
+ "option": "noConfig",
672
+ "flag": "--no-config",
673
+ "kind": "switch",
674
+ "unless": null
675
+ }
676
+ ],
677
+ "uncovered": []
678
+ },
679
+ {
680
+ "method": "sync",
681
+ "argv": [
682
+ "sync"
683
+ ],
684
+ "options": "sync_options",
685
+ "output": "sync_report",
686
+ "stdout": "json",
687
+ "stdin": false,
688
+ "rust": "oneharness_core::io::sync::sync",
689
+ "always": [
690
+ "--compact"
691
+ ],
692
+ "bindings": [
693
+ {
694
+ "option": "cwd",
695
+ "flag": "--cwd",
696
+ "kind": "value",
697
+ "unless": null
698
+ },
699
+ {
700
+ "option": "harnesses",
701
+ "flag": "--harness",
702
+ "kind": "repeated",
703
+ "unless": null
704
+ },
705
+ {
706
+ "option": "check",
707
+ "flag": "--check",
708
+ "kind": "switch",
709
+ "unless": null
710
+ },
711
+ {
712
+ "option": "global",
713
+ "flag": "--global",
714
+ "kind": "switch",
715
+ "unless": null
716
+ },
717
+ {
718
+ "option": "config",
719
+ "flag": "--config",
720
+ "kind": "value",
721
+ "unless": "noConfig"
722
+ },
723
+ {
724
+ "option": "noConfig",
725
+ "flag": "--no-config",
726
+ "kind": "switch",
727
+ "unless": null
728
+ }
729
+ ],
730
+ "uncovered": []
731
+ },
732
+ {
733
+ "method": "init",
734
+ "argv": [
735
+ "init"
736
+ ],
737
+ "options": "init_options",
738
+ "output": null,
739
+ "stdout": "text",
740
+ "stdin": false,
741
+ "rust": "oneharness_core::io::init::init",
742
+ "always": [],
743
+ "bindings": [
744
+ {
745
+ "option": "path",
746
+ "flag": "",
747
+ "kind": "positional",
748
+ "unless": null
749
+ },
750
+ {
751
+ "option": "force",
752
+ "flag": "--force",
753
+ "kind": "switch",
754
+ "unless": null
755
+ }
756
+ ],
757
+ "uncovered": []
758
+ },
759
+ {
760
+ "method": "usage",
761
+ "argv": [
762
+ "usage"
763
+ ],
764
+ "options": "usage_options",
765
+ "output": "usage_report",
766
+ "stdout": "json",
767
+ "stdin": false,
768
+ "rust": "oneharness_core::io::usage::report",
769
+ "always": [
770
+ "--compact"
771
+ ],
772
+ "bindings": [
773
+ {
774
+ "option": "harnesses",
775
+ "flag": "--harness",
776
+ "kind": "repeated",
777
+ "unless": null
778
+ },
779
+ {
780
+ "option": "all",
781
+ "flag": "--all",
782
+ "kind": "switch",
783
+ "unless": "harnesses"
784
+ },
785
+ {
786
+ "option": "exclude",
787
+ "flag": "--exclude",
788
+ "kind": "repeated",
789
+ "unless": null
790
+ },
791
+ {
792
+ "option": "bins",
793
+ "flag": "--bin",
794
+ "kind": "key-value",
795
+ "unless": null
796
+ },
797
+ {
798
+ "option": "cwd",
799
+ "flag": "--cwd",
800
+ "kind": "value",
801
+ "unless": null
802
+ },
803
+ {
804
+ "option": "timeoutSeconds",
805
+ "flag": "--timeout",
806
+ "kind": "value",
807
+ "unless": null
808
+ },
809
+ {
810
+ "option": "config",
811
+ "flag": "--config",
812
+ "kind": "value",
813
+ "unless": "noConfig"
814
+ },
815
+ {
816
+ "option": "noConfig",
817
+ "flag": "--no-config",
818
+ "kind": "switch",
819
+ "unless": null
820
+ }
821
+ ],
822
+ "uncovered": [
823
+ {
824
+ "flag": "--format",
825
+ "reason": "the SDKs consume the JSON contract; `--format text` is the human-readable view of the same data, carrying nothing the JSON does not"
826
+ }
827
+ ]
828
+ },
829
+ {
830
+ "method": "gate",
831
+ "argv": [
832
+ "gate"
833
+ ],
834
+ "options": "gate_options",
835
+ "output": null,
836
+ "stdout": "text",
837
+ "stdin": true,
838
+ "rust": "oneharness_core::domain::gate::render_deny",
839
+ "always": [],
840
+ "bindings": [
841
+ {
842
+ "option": "harness",
843
+ "flag": "",
844
+ "kind": "positional",
845
+ "unless": null
846
+ },
847
+ {
848
+ "option": "denyIfContains",
849
+ "flag": "--deny-if-contains",
850
+ "kind": "value",
851
+ "unless": null
852
+ },
853
+ {
854
+ "option": "reason",
855
+ "flag": "--reason",
856
+ "kind": "value",
857
+ "unless": null
858
+ }
859
+ ],
860
+ "uncovered": []
861
+ },
862
+ {
863
+ "method": "mock",
864
+ "argv": [
865
+ "mock"
866
+ ],
867
+ "options": "mock_options",
868
+ "output": null,
869
+ "stdout": "text",
870
+ "stdin": true,
871
+ "rust": "oneharness_core::domain::mock::decide",
872
+ "always": [],
873
+ "bindings": [
874
+ {
875
+ "option": "harness",
876
+ "flag": "",
877
+ "kind": "positional",
878
+ "unless": null
879
+ },
880
+ {
881
+ "option": "rules",
882
+ "flag": "--rules",
883
+ "kind": "value",
884
+ "unless": null
885
+ },
886
+ {
887
+ "option": "spyFile",
888
+ "flag": "--spy-file",
889
+ "kind": "value",
890
+ "unless": null
891
+ }
892
+ ],
893
+ "uncovered": []
894
+ },
895
+ {
896
+ "method": "interrupt",
897
+ "argv": [
898
+ "interrupt"
899
+ ],
900
+ "options": "interrupt_options",
901
+ "output": "interrupt_response",
902
+ "stdout": "json",
903
+ "stdin": false,
904
+ "rust": "oneharness_core::io::control::send",
905
+ "always": [
906
+ "--compact"
907
+ ],
908
+ "bindings": [
909
+ {
910
+ "option": "session",
911
+ "flag": "--session",
912
+ "kind": "value",
913
+ "unless": null
914
+ },
915
+ {
916
+ "option": "input",
917
+ "flag": "--input",
918
+ "kind": "value",
919
+ "unless": null
920
+ },
921
+ {
922
+ "option": "sessionDir",
923
+ "flag": "--session-dir",
924
+ "kind": "value",
925
+ "unless": null
926
+ },
927
+ {
928
+ "option": "cwd",
929
+ "flag": "--cwd",
930
+ "kind": "value",
931
+ "unless": null
932
+ }
933
+ ],
934
+ "uncovered": []
935
+ },
936
+ {
937
+ "method": "history",
938
+ "argv": [
939
+ "history",
940
+ "show"
941
+ ],
942
+ "options": "history_lookup",
943
+ "output": "history_records",
944
+ "stdout": "json",
945
+ "stdin": false,
946
+ "rust": "oneharness_core::io::history::read_session",
947
+ "always": [
948
+ "--compact"
949
+ ],
950
+ "bindings": [
951
+ {
952
+ "option": "session",
953
+ "flag": "",
954
+ "kind": "positional",
955
+ "unless": "last"
956
+ },
957
+ {
958
+ "option": "last",
959
+ "flag": "--last",
960
+ "kind": "switch",
961
+ "unless": null
962
+ },
963
+ {
964
+ "option": "all",
965
+ "flag": "--all",
966
+ "kind": "switch",
967
+ "unless": null
968
+ },
969
+ {
970
+ "option": "project",
971
+ "flag": "--project",
972
+ "kind": "value",
973
+ "unless": "allProjects"
974
+ },
975
+ {
976
+ "option": "allProjects",
977
+ "flag": "--all-projects",
978
+ "kind": "switch",
979
+ "unless": null
980
+ },
981
+ {
982
+ "option": "historyDir",
983
+ "flag": "--history-dir",
984
+ "kind": "value",
985
+ "unless": null
986
+ },
987
+ {
988
+ "option": "config",
989
+ "flag": "--config",
990
+ "kind": "value",
991
+ "unless": "noConfig"
992
+ },
993
+ {
994
+ "option": "noConfig",
995
+ "flag": "--no-config",
996
+ "kind": "switch",
997
+ "unless": null
998
+ }
999
+ ],
1000
+ "uncovered": [
1001
+ {
1002
+ "flag": "--format",
1003
+ "reason": "the SDKs consume the JSON contract; `--format text` is the human-readable view of the same data, carrying nothing the JSON does not"
1004
+ }
1005
+ ]
1006
+ },
1007
+ {
1008
+ "method": "historyList",
1009
+ "argv": [
1010
+ "history",
1011
+ "list"
1012
+ ],
1013
+ "options": "history_list_options",
1014
+ "output": "history_list",
1015
+ "stdout": "json",
1016
+ "stdin": false,
1017
+ "rust": "oneharness_core::io::history::list_sessions",
1018
+ "always": [
1019
+ "--compact"
1020
+ ],
1021
+ "bindings": [
1022
+ {
1023
+ "option": "variant",
1024
+ "flag": "--variant",
1025
+ "kind": "value",
1026
+ "unless": null
1027
+ },
1028
+ {
1029
+ "option": "project",
1030
+ "flag": "--project",
1031
+ "kind": "value",
1032
+ "unless": "allProjects"
1033
+ },
1034
+ {
1035
+ "option": "allProjects",
1036
+ "flag": "--all-projects",
1037
+ "kind": "switch",
1038
+ "unless": null
1039
+ },
1040
+ {
1041
+ "option": "historyDir",
1042
+ "flag": "--history-dir",
1043
+ "kind": "value",
1044
+ "unless": null
1045
+ },
1046
+ {
1047
+ "option": "config",
1048
+ "flag": "--config",
1049
+ "kind": "value",
1050
+ "unless": "noConfig"
1051
+ },
1052
+ {
1053
+ "option": "noConfig",
1054
+ "flag": "--no-config",
1055
+ "kind": "switch",
1056
+ "unless": null
1057
+ }
1058
+ ],
1059
+ "uncovered": [
1060
+ {
1061
+ "flag": "--format",
1062
+ "reason": "the SDKs consume the JSON contract; `--format text` is the human-readable view of the same data, carrying nothing the JSON does not"
1063
+ }
1064
+ ]
1065
+ },
1066
+ {
1067
+ "method": "historyWatch",
1068
+ "argv": [
1069
+ "history",
1070
+ "watch"
1071
+ ],
1072
+ "options": "history_watch_options",
1073
+ "output": "history_stream_envelope",
1074
+ "stdout": "jsonl",
1075
+ "stdin": false,
1076
+ "rust": "oneharness_core::io::history::HistoryWatcher",
1077
+ "always": [
1078
+ "--format",
1079
+ "jsonl"
1080
+ ],
1081
+ "bindings": [
1082
+ {
1083
+ "option": "after",
1084
+ "flag": "--after",
1085
+ "kind": "value",
1086
+ "unless": null
1087
+ },
1088
+ {
1089
+ "option": "labels",
1090
+ "flag": "--label",
1091
+ "kind": "key-value",
1092
+ "unless": null
1093
+ },
1094
+ {
1095
+ "option": "variant",
1096
+ "flag": "--variant",
1097
+ "kind": "value",
1098
+ "unless": null
1099
+ },
1100
+ {
1101
+ "option": "project",
1102
+ "flag": "--project",
1103
+ "kind": "value",
1104
+ "unless": "allProjects"
1105
+ },
1106
+ {
1107
+ "option": "allProjects",
1108
+ "flag": "--all-projects",
1109
+ "kind": "switch",
1110
+ "unless": null
1111
+ },
1112
+ {
1113
+ "option": "historyDir",
1114
+ "flag": "--history-dir",
1115
+ "kind": "value",
1116
+ "unless": null
1117
+ },
1118
+ {
1119
+ "option": "events",
1120
+ "flag": "--events",
1121
+ "kind": "switch",
1122
+ "unless": null
1123
+ },
1124
+ {
1125
+ "option": "config",
1126
+ "flag": "--config",
1127
+ "kind": "value",
1128
+ "unless": "noConfig"
1129
+ },
1130
+ {
1131
+ "option": "noConfig",
1132
+ "flag": "--no-config",
1133
+ "kind": "switch",
1134
+ "unless": null
1135
+ }
1136
+ ],
1137
+ "uncovered": []
1138
+ },
1139
+ {
1140
+ "method": "historyClear",
1141
+ "argv": [
1142
+ "history",
1143
+ "clear"
1144
+ ],
1145
+ "options": "history_clear_options",
1146
+ "output": "history_clear_report",
1147
+ "stdout": "json",
1148
+ "stdin": false,
1149
+ "rust": "oneharness_core::io::history::remove_sessions",
1150
+ "always": [
1151
+ "--compact"
1152
+ ],
1153
+ "bindings": [
1154
+ {
1155
+ "option": "project",
1156
+ "flag": "--project",
1157
+ "kind": "value",
1158
+ "unless": "allProjects"
1159
+ },
1160
+ {
1161
+ "option": "allProjects",
1162
+ "flag": "--all-projects",
1163
+ "kind": "switch",
1164
+ "unless": null
1165
+ },
1166
+ {
1167
+ "option": "yes",
1168
+ "flag": "--yes",
1169
+ "kind": "switch",
1170
+ "unless": null
1171
+ },
1172
+ {
1173
+ "option": "historyDir",
1174
+ "flag": "--history-dir",
1175
+ "kind": "value",
1176
+ "unless": null
1177
+ },
1178
+ {
1179
+ "option": "config",
1180
+ "flag": "--config",
1181
+ "kind": "value",
1182
+ "unless": "noConfig"
1183
+ },
1184
+ {
1185
+ "option": "noConfig",
1186
+ "flag": "--no-config",
1187
+ "kind": "switch",
1188
+ "unless": null
1189
+ }
1190
+ ],
1191
+ "uncovered": []
1192
+ },
1193
+ {
1194
+ "method": "historyMigrate",
1195
+ "argv": [
1196
+ "history",
1197
+ "migrate"
1198
+ ],
1199
+ "options": "history_migrate_options",
1200
+ "output": "history_migrate_report",
1201
+ "stdout": "json",
1202
+ "stdin": false,
1203
+ "rust": "oneharness_core::io::history::migrate",
1204
+ "always": [
1205
+ "--compact"
1206
+ ],
1207
+ "bindings": [
1208
+ {
1209
+ "option": "historyDir",
1210
+ "flag": "--history-dir",
1211
+ "kind": "value",
1212
+ "unless": null
1213
+ },
1214
+ {
1215
+ "option": "config",
1216
+ "flag": "--config",
1217
+ "kind": "value",
1218
+ "unless": "noConfig"
1219
+ },
1220
+ {
1221
+ "option": "noConfig",
1222
+ "flag": "--no-config",
1223
+ "kind": "switch",
1224
+ "unless": null
1225
+ }
1226
+ ],
1227
+ "uncovered": []
1228
+ }
1229
+ ],
2
1230
  "run_report": {
3
1231
  "$schema": "https://json-schema.org/draft/2020-12/schema",
4
1232
  "title": "RunReport",
@@ -2196,12 +3424,33 @@
2196
3424
  "description": "Options accepted by `OneHarness.run()` in the published Node SDK.\n\nUnknown fields are rejected because the SDK cannot forward an option it does\nnot understand. This differs deliberately from output contracts, whose Zod\nschemas preserve unknown fields for forward compatibility.",
2197
3425
  "type": "object",
2198
3426
  "properties": {
3427
+ "all": {
3428
+ "description": "Run against every supported harness.",
3429
+ "type": "boolean"
3430
+ },
3431
+ "batchPrompts": {
3432
+ "description": "Further prompts, making this a **batch**: one harness fanned over each\nprompt, sharing the cacheable `system`/model prefix. Combined order is\n`prompt`, then these, then `promptFiles` — the CLI's own order.",
3433
+ "type": "array",
3434
+ "items": {
3435
+ "type": "string"
3436
+ }
3437
+ },
3438
+ "batchStrategy": {
3439
+ "$ref": "#/$defs/BatchStrategy"
3440
+ },
2199
3441
  "bins": {
2200
3442
  "type": "object",
2201
3443
  "additionalProperties": {
2202
3444
  "type": "string"
2203
3445
  }
2204
3446
  },
3447
+ "config": {
3448
+ "type": "string"
3449
+ },
3450
+ "control": {
3451
+ "description": "Open the out-of-band turn-control socket, so a separate `interrupt()`\ncan abort the in-flight turn without killing this run.",
3452
+ "type": "boolean"
3453
+ },
2205
3454
  "cwd": {
2206
3455
  "type": "string"
2207
3456
  },
@@ -2214,6 +3463,13 @@
2214
3463
  "events": {
2215
3464
  "type": "boolean"
2216
3465
  },
3466
+ "exclude": {
3467
+ "description": "Harness id(s) to drop from an all-harness run.",
3468
+ "type": "array",
3469
+ "items": {
3470
+ "type": "string"
3471
+ }
3472
+ },
2217
3473
  "fork": {
2218
3474
  "type": "boolean"
2219
3475
  },
@@ -2235,6 +3491,23 @@
2235
3491
  "historyName": {
2236
3492
  "type": "string"
2237
3493
  },
3494
+ "maxParallel": {
3495
+ "description": "Maximum harnesses (or, in a batch, prompts) to run concurrently.",
3496
+ "type": "integer",
3497
+ "format": "uint32",
3498
+ "minimum": 0
3499
+ },
3500
+ "mockHarnesses": {
3501
+ "description": "Replace these selected harnesses' provider processes with oneharness's\ndeterministic `MOCK_*`-scripted responder.",
3502
+ "type": "array",
3503
+ "items": {
3504
+ "type": "string"
3505
+ }
3506
+ },
3507
+ "mockRules": {
3508
+ "description": "Mock/spy the selected harnesses' tool calls for this run only.",
3509
+ "type": "string"
3510
+ },
2238
3511
  "mode": {
2239
3512
  "$ref": "#/$defs/PermissionMode"
2240
3513
  },
@@ -2244,23 +3517,88 @@
2244
3517
  "type": "string"
2245
3518
  }
2246
3519
  },
3520
+ "noConfig": {
3521
+ "type": "boolean"
3522
+ },
3523
+ "noHistory": {
3524
+ "description": "Do NOT record history for this run, overriding config or the\n`ONEHARNESS_HISTORY` environment override.",
3525
+ "type": "boolean"
3526
+ },
3527
+ "outputDir": {
3528
+ "description": "Write each harness's raw stdout/stderr under this directory.",
3529
+ "type": "string"
3530
+ },
3531
+ "outputFormat": {
3532
+ "$ref": "#/$defs/OutputFormat"
3533
+ },
3534
+ "passthrough": {
3535
+ "description": "Extra arguments appended verbatim to each harness command, after `--`.",
3536
+ "type": "array",
3537
+ "items": {
3538
+ "type": "string"
3539
+ }
3540
+ },
3541
+ "permitPrompts": {
3542
+ "description": "Silence the warning that the chosen mode may block on an approval prompt.",
3543
+ "type": "boolean"
3544
+ },
3545
+ "printCommand": {
3546
+ "description": "Build and report each command without executing it.",
3547
+ "type": "boolean"
3548
+ },
2247
3549
  "prompt": {
2248
3550
  "description": "The user message sent to the selected harnesses.",
2249
3551
  "type": "string",
2250
3552
  "minLength": 1
2251
3553
  },
3554
+ "promptFiles": {
3555
+ "description": "Files each holding one whole prompt, or `-` for stdin.",
3556
+ "type": "array",
3557
+ "items": {
3558
+ "type": "string"
3559
+ }
3560
+ },
2252
3561
  "reasoning": {
2253
3562
  "type": "string"
2254
3563
  },
3564
+ "requireAvailable": {
3565
+ "description": "Treat a not-installed harness as a failure.",
3566
+ "type": "boolean"
3567
+ },
2255
3568
  "resume": {
2256
3569
  "type": "string"
2257
3570
  },
3571
+ "runMode": {
3572
+ "$ref": "#/$defs/RunMode"
3573
+ },
3574
+ "schema": {
3575
+ "description": "Constrain each harness's final answer to this JSON Schema file.",
3576
+ "type": "string"
3577
+ },
3578
+ "schemaMaxRetries": {
3579
+ "description": "Max retries when a response fails schema validation.",
3580
+ "type": "integer",
3581
+ "format": "uint32",
3582
+ "minimum": 0
3583
+ },
2258
3584
  "session": {
2259
3585
  "type": "string"
2260
3586
  },
3587
+ "sessionDir": {
3588
+ "description": "Directory the `session` store lives in.",
3589
+ "type": "string"
3590
+ },
3591
+ "spyFile": {
3592
+ "description": "Append one JSONL record per observed tool call to this file.",
3593
+ "type": "string"
3594
+ },
2261
3595
  "system": {
2262
3596
  "type": "string"
2263
3597
  },
3598
+ "systemFile": {
3599
+ "description": "Read the system prompt from a file — the counterpart to `system` for a\nvalue too large to pass on the argv.",
3600
+ "type": "string"
3601
+ },
2264
3602
  "timeoutSeconds": {
2265
3603
  "type": "integer",
2266
3604
  "format": "uint64",
@@ -2272,25 +3610,60 @@
2272
3610
  "prompt"
2273
3611
  ],
2274
3612
  "$defs": {
2275
- "HistoryLabels": {
2276
- "type": "object",
2277
- "additionalProperties": {
2278
- "type": "string",
2279
- "maxLength": 256,
2280
- "minLength": 1,
2281
- "not": {
2282
- "pattern": "[\\u0000-\\u001f\\u007f-\\u009f]"
2283
- }
2284
- },
2285
- "propertyNames": {
2286
- "type": "string",
2287
- "maxLength": 64,
3613
+ "BatchStrategy": {
3614
+ "description": "How a batch of same-prefix prompts is scheduled across the parallel runner.\nAlso accepted as a CLI value (`--batch-strategy`, parsed in the `oneharness`\nbinary) — the parsing lives there so this core crate stays free of `clap`.",
3615
+ "oneOf": [
3616
+ {
3617
+ "description": "Fire all prompts at once (a single wave): minimum wall-clock. Every call\nmay race to *write* the shared prefix to the provider cache (none exists\nyet), so this optimizes latency, not tokens. The default.",
3618
+ "type": "string",
3619
+ "const": "speed"
3620
+ },
3621
+ {
3622
+ "description": "Warm-then-fan: run one prompt first to *write* the shared prefix to cache,\nwait for it, then fan the rest out concurrently so they *read* the warmed\nprefix instead of each re-writing it. Optimizes cost at some wall-clock\nexpense.",
3623
+ "type": "string",
3624
+ "const": "min-tokens"
3625
+ }
3626
+ ]
3627
+ },
3628
+ "HistoryLabels": {
3629
+ "type": "object",
3630
+ "additionalProperties": {
3631
+ "type": "string",
3632
+ "maxLength": 256,
3633
+ "minLength": 1,
3634
+ "not": {
3635
+ "pattern": "[\\u0000-\\u001f\\u007f-\\u009f]"
3636
+ }
3637
+ },
3638
+ "propertyNames": {
3639
+ "type": "string",
3640
+ "maxLength": 64,
2288
3641
  "not": {
2289
3642
  "pattern": "[^A-Za-z0-9._-]"
2290
3643
  },
2291
3644
  "pattern": "^[A-Za-z0-9]"
2292
3645
  }
2293
3646
  },
3647
+ "OutputFormat": {
3648
+ "description": "How a harness emits its result, which decides how `text` is extracted.\n\nAlso accepted as a CLI value (`--output-format`, parsed in the `oneharness`\nbinary) and a config-file value (`output_format`, via `Deserialize`). The\nCLI parsing lives in the binary so this core crate stays free of `clap`.",
3649
+ "oneOf": [
3650
+ {
3651
+ "description": "Plain text on stdout; `text` is the trimmed stdout.",
3652
+ "type": "string",
3653
+ "const": "text"
3654
+ },
3655
+ {
3656
+ "description": "A single JSON document on stdout.",
3657
+ "type": "string",
3658
+ "const": "json"
3659
+ },
3660
+ {
3661
+ "description": "Line-delimited JSON events on stdout.",
3662
+ "type": "string",
3663
+ "const": "stream-json"
3664
+ }
3665
+ ]
3666
+ },
2294
3667
  "PermissionMode": {
2295
3668
  "description": "The unified approval mode, from least to most autonomy. A harness may not\nsupport every value (see [`crate::domain::harness::HarnessSpec::mode`]); the\ncommand layer refuses an unsupported one before spawning, never silently\ndowngrading it.",
2296
3669
  "oneOf": [
@@ -2325,6 +3698,21 @@
2325
3698
  "const": "bypass"
2326
3699
  }
2327
3700
  ]
3701
+ },
3702
+ "RunMode": {
3703
+ "description": "How the selected harnesses are run. Accepted as a CLI value (`--run-mode`,\nparsed in the `oneharness` binary) and a config-file value (`run_mode`, via\n`Deserialize`); the CLI parsing lives in the binary so this core crate stays\nfree of `clap`.",
3704
+ "oneOf": [
3705
+ {
3706
+ "description": "Run every selected harness at once, each an independent subprocess, and\nreport them all. The default — the historical behavior.",
3707
+ "type": "string",
3708
+ "const": "parallel"
3709
+ },
3710
+ {
3711
+ "description": "Run the selected harnesses in priority order (the `--harness` / config\norder, else registry order under `--all`), stopping at the first that\nactually runs the task; fall through only the candidates that cannot run\nat all (see [`startup_failure_reason`]).",
3712
+ "type": "string",
3713
+ "const": "fallback"
3714
+ }
3715
+ ]
2328
3716
  }
2329
3717
  }
2330
3718
  },
@@ -2347,9 +3735,17 @@
2347
3735
  "description": "A [`HistoryLookup`] that selects the most recent session.",
2348
3736
  "type": "object",
2349
3737
  "properties": {
3738
+ "all": {
3739
+ "description": "Show every record in the session rather than the run summaries.",
3740
+ "type": "boolean"
3741
+ },
2350
3742
  "allProjects": {
2351
3743
  "type": "boolean"
2352
3744
  },
3745
+ "config": {
3746
+ "description": "Load configuration from exactly this file, skipping user/project\ndiscovery.",
3747
+ "type": "string"
3748
+ },
2353
3749
  "historyDir": {
2354
3750
  "type": "string"
2355
3751
  },
@@ -2358,6 +3754,10 @@
2358
3754
  "type": "boolean",
2359
3755
  "const": true
2360
3756
  },
3757
+ "noConfig": {
3758
+ "description": "Ignore every configuration file.",
3759
+ "type": "boolean"
3760
+ },
2361
3761
  "project": {
2362
3762
  "type": "string"
2363
3763
  },
@@ -2375,9 +3775,17 @@
2375
3775
  "description": "A [`HistoryLookup`] that names its session.",
2376
3776
  "type": "object",
2377
3777
  "properties": {
3778
+ "all": {
3779
+ "description": "Show every record in the session rather than the run summaries.",
3780
+ "type": "boolean"
3781
+ },
2378
3782
  "allProjects": {
2379
3783
  "type": "boolean"
2380
3784
  },
3785
+ "config": {
3786
+ "description": "Load configuration from exactly this file, skipping user/project\ndiscovery.",
3787
+ "type": "string"
3788
+ },
2381
3789
  "historyDir": {
2382
3790
  "type": "string"
2383
3791
  },
@@ -2385,6 +3793,10 @@
2385
3793
  "description": "Whether the most recent session was asked for instead. An ordinary\n`bool`, so a caller holding a `boolean` can pass it straight through.\n`true` here also satisfies [`HistoryLookup::Last`], which the union tries\nfirst — so a lookup that reaches this variant always meant the name.",
2386
3794
  "type": "boolean"
2387
3795
  },
3796
+ "noConfig": {
3797
+ "description": "Ignore every configuration file.",
3798
+ "type": "boolean"
3799
+ },
2388
3800
  "project": {
2389
3801
  "type": "string"
2390
3802
  },
@@ -2410,11 +3822,23 @@
2410
3822
  "allProjects": {
2411
3823
  "type": "boolean"
2412
3824
  },
3825
+ "config": {
3826
+ "description": "Load configuration from exactly this file, skipping user/project\ndiscovery.",
3827
+ "type": "string"
3828
+ },
2413
3829
  "historyDir": {
2414
3830
  "type": "string"
2415
3831
  },
3832
+ "noConfig": {
3833
+ "description": "Ignore every configuration file.",
3834
+ "type": "boolean"
3835
+ },
2416
3836
  "project": {
2417
3837
  "type": "string"
3838
+ },
3839
+ "variant": {
3840
+ "description": "Narrow to one configured harness identity (`claude-code:work`).",
3841
+ "type": "string"
2418
3842
  }
2419
3843
  },
2420
3844
  "additionalProperties": false
@@ -2434,6 +3858,10 @@
2434
3858
  "allProjects": {
2435
3859
  "type": "boolean"
2436
3860
  },
3861
+ "config": {
3862
+ "description": "Load configuration from exactly this file, skipping user/project\ndiscovery.",
3863
+ "type": "string"
3864
+ },
2437
3865
  "events": {
2438
3866
  "type": "boolean"
2439
3867
  },
@@ -2443,8 +3871,16 @@
2443
3871
  "labels": {
2444
3872
  "$ref": "#/$defs/HistoryLabels"
2445
3873
  },
3874
+ "noConfig": {
3875
+ "description": "Ignore every configuration file.",
3876
+ "type": "boolean"
3877
+ },
2446
3878
  "project": {
2447
3879
  "type": "string"
3880
+ },
3881
+ "variant": {
3882
+ "description": "Narrow to one configured harness identity (`claude-code:work`).",
3883
+ "type": "string"
2448
3884
  }
2449
3885
  },
2450
3886
  "additionalProperties": false,
@@ -12063,6 +13499,7 @@
12063
13499
  "list_report": {
12064
13500
  "$schema": "https://json-schema.org/draft/2020-12/schema",
12065
13501
  "title": "ListReport",
13502
+ "description": "The `oneharness list` output contract.",
12066
13503
  "type": "object",
12067
13504
  "properties": {
12068
13505
  "harnesses": {
@@ -12111,6 +13548,7 @@
12111
13548
  ]
12112
13549
  },
12113
13550
  "HarnessInfo": {
13551
+ "description": "Everything the registry declares about one harness.",
12114
13552
  "type": "object",
12115
13553
  "properties": {
12116
13554
  "control": {
@@ -12262,11 +13700,11 @@
12262
13700
  ]
12263
13701
  },
12264
13702
  "ModeInfo": {
12265
- "description": "One supported approval mode for a harness, with its headless behavior, in\n`oneharness list`. A [`PermissionMode`] absent from a harness's array is\nunsupported for it (a `--mode` request would be refused).",
13703
+ "description": "One supported approval mode for a harness, with its headless behavior. A\n[`PermissionMode`] absent from a harness's array is unsupported for it (a\n`--mode` request would be refused).",
12266
13704
  "type": "object",
12267
13705
  "properties": {
12268
13706
  "headless": {
12269
- "description": "`\"clean\"` (never blocks headless) or `\"hangs\"` (would block on an\napproval prompt; refused without --permit-prompts).",
13707
+ "description": "`\"clean\"` (never blocks headless) or `\"hangs\"` (would block on an\napproval prompt; refused without `--permit-prompts`).",
12270
13708
  "$ref": "#/$defs/ModeHeadless"
12271
13709
  },
12272
13710
  "mode": {
@@ -12334,6 +13772,7 @@
12334
13772
  ]
12335
13773
  },
12336
13774
  "VariantInfo": {
13775
+ "description": "One configured identity of a harness — a `[harness.<id>.variant.<name>]`\ntable, resolved the way a run would resolve it.",
12337
13776
  "type": "object",
12338
13777
  "properties": {
12339
13778
  "args": {
@@ -12402,6 +13841,7 @@
12402
13841
  "detect_report": {
12403
13842
  "$schema": "https://json-schema.org/draft/2020-12/schema",
12404
13843
  "title": "DetectReport",
13844
+ "description": "The `oneharness detect` output contract.",
12405
13845
  "type": "object",
12406
13846
  "properties": {
12407
13847
  "detected": {
@@ -12420,6 +13860,7 @@
12420
13860
  ],
12421
13861
  "$defs": {
12422
13862
  "DetectInfo": {
13863
+ "description": "One probed harness identity.",
12423
13864
  "type": "object",
12424
13865
  "properties": {
12425
13866
  "available": {
@@ -12453,5 +13894,1794 @@
12453
13894
  ]
12454
13895
  }
12455
13896
  }
13897
+ },
13898
+ "detect_options": {
13899
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
13900
+ "title": "DetectOptions",
13901
+ "description": "Options accepted by the language SDKs' `detect()`.",
13902
+ "type": "object",
13903
+ "properties": {
13904
+ "all": {
13905
+ "type": "boolean"
13906
+ },
13907
+ "bins": {
13908
+ "type": "object",
13909
+ "additionalProperties": {
13910
+ "type": "string"
13911
+ }
13912
+ },
13913
+ "config": {
13914
+ "type": "string"
13915
+ },
13916
+ "exclude": {
13917
+ "type": "array",
13918
+ "items": {
13919
+ "type": "string"
13920
+ }
13921
+ },
13922
+ "harnesses": {
13923
+ "type": "array",
13924
+ "items": {
13925
+ "type": "string"
13926
+ }
13927
+ },
13928
+ "noConfig": {
13929
+ "type": "boolean"
13930
+ },
13931
+ "requireAvailable": {
13932
+ "description": "Exit non-zero if any probed harness is not installed. The SDKs surface\nthat as a thrown process error rather than a report a caller must\nre-check.",
13933
+ "type": "boolean"
13934
+ }
13935
+ },
13936
+ "additionalProperties": false
13937
+ },
13938
+ "config_options": {
13939
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
13940
+ "title": "ConfigOptions",
13941
+ "description": "Options accepted by the language SDKs' `config()`.",
13942
+ "type": "object",
13943
+ "properties": {
13944
+ "config": {
13945
+ "type": "string"
13946
+ },
13947
+ "cwd": {
13948
+ "type": "string"
13949
+ },
13950
+ "noConfig": {
13951
+ "type": "boolean"
13952
+ }
13953
+ },
13954
+ "additionalProperties": false
13955
+ },
13956
+ "config_report": {
13957
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
13958
+ "title": "ConfigReport",
13959
+ "description": "The `oneharness config` report: the fully layered configuration with the\nprovenance of every value, so a consumer can see exactly which file (or\ndefault) shaped each setting of a run.",
13960
+ "type": "object",
13961
+ "properties": {
13962
+ "all": {
13963
+ "$ref": "#/$defs/Field"
13964
+ },
13965
+ "allowed_tools": {
13966
+ "$ref": "#/$defs/Field2"
13967
+ },
13968
+ "bypass": {
13969
+ "$ref": "#/$defs/Field"
13970
+ },
13971
+ "config_files": {
13972
+ "description": "The files consulted, in layering order (user first, project last).",
13973
+ "type": "array",
13974
+ "items": {
13975
+ "type": "string"
13976
+ }
13977
+ },
13978
+ "denied_tools": {
13979
+ "$ref": "#/$defs/Field2"
13980
+ },
13981
+ "env": {
13982
+ "description": "Per-key provenance for the top-level `[env]`.",
13983
+ "type": "object",
13984
+ "additionalProperties": {
13985
+ "$ref": "#/$defs/Field3"
13986
+ }
13987
+ },
13988
+ "exclude": {
13989
+ "$ref": "#/$defs/Field2"
13990
+ },
13991
+ "harness": {
13992
+ "description": "Per-harness overrides, with per-field provenance.",
13993
+ "type": "object",
13994
+ "additionalProperties": {
13995
+ "$ref": "#/$defs/HarnessReport"
13996
+ }
13997
+ },
13998
+ "harnesses": {
13999
+ "$ref": "#/$defs/Field2"
14000
+ },
14001
+ "history": {
14002
+ "$ref": "#/$defs/Field"
14003
+ },
14004
+ "history_dir": {
14005
+ "$ref": "#/$defs/Field3"
14006
+ },
14007
+ "history_labels": {
14008
+ "description": "Per-key provenance for history labels.",
14009
+ "type": "object",
14010
+ "additionalProperties": {
14011
+ "$ref": "#/$defs/Field3"
14012
+ }
14013
+ },
14014
+ "hooks": {
14015
+ "$ref": "#/$defs/Field10"
14016
+ },
14017
+ "max_parallel": {
14018
+ "$ref": "#/$defs/Field8"
14019
+ },
14020
+ "mode": {
14021
+ "description": "The configured `mode`, if any. Unset when only the legacy `bypass` field\n(or neither) is set — the effective mode then derives from `bypass`.",
14022
+ "$ref": "#/$defs/Field4"
14023
+ },
14024
+ "model": {
14025
+ "$ref": "#/$defs/Field3"
14026
+ },
14027
+ "models": {
14028
+ "description": "The model fan-out list (`models` / repeated `--model` / `ONEHARNESS_MODELS`),\nif any. Unset when the run uses a single per-harness model.",
14029
+ "$ref": "#/$defs/Field2"
14030
+ },
14031
+ "output_format": {
14032
+ "$ref": "#/$defs/Field6"
14033
+ },
14034
+ "reasoning": {
14035
+ "description": "Reasoning / thinking effort (`--reasoning` / `ONEHARNESS_REASONING`), if\nany. Forwarded to reasoning-capable harnesses only.",
14036
+ "$ref": "#/$defs/Field3"
14037
+ },
14038
+ "require_available": {
14039
+ "$ref": "#/$defs/Field"
14040
+ },
14041
+ "run_mode": {
14042
+ "description": "The configured run mode, if any. Unset falls back to `parallel` (the\nbuilt-in default) at run time.",
14043
+ "$ref": "#/$defs/Field9"
14044
+ },
14045
+ "schema_file": {
14046
+ "$ref": "#/$defs/Field3"
14047
+ },
14048
+ "schema_max_retries": {
14049
+ "$ref": "#/$defs/Field7"
14050
+ },
14051
+ "schema_version": {
14052
+ "type": "string"
14053
+ },
14054
+ "stream": {
14055
+ "description": "Whether config asks every `run` to stream (`--stream` / ONEHARNESS_STREAM);\ndefaults to false, the built-in buffered report.",
14056
+ "$ref": "#/$defs/Field"
14057
+ },
14058
+ "system": {
14059
+ "$ref": "#/$defs/Field3"
14060
+ },
14061
+ "timeout": {
14062
+ "$ref": "#/$defs/Field5"
14063
+ }
14064
+ },
14065
+ "required": [
14066
+ "schema_version",
14067
+ "config_files",
14068
+ "all",
14069
+ "harnesses",
14070
+ "exclude",
14071
+ "model",
14072
+ "models",
14073
+ "system",
14074
+ "reasoning",
14075
+ "bypass",
14076
+ "mode",
14077
+ "timeout",
14078
+ "output_format",
14079
+ "stream",
14080
+ "schema_file",
14081
+ "schema_max_retries",
14082
+ "max_parallel",
14083
+ "run_mode",
14084
+ "require_available",
14085
+ "history",
14086
+ "history_dir",
14087
+ "history_labels",
14088
+ "allowed_tools",
14089
+ "denied_tools",
14090
+ "hooks",
14091
+ "env",
14092
+ "harness"
14093
+ ],
14094
+ "$defs": {
14095
+ "Field": {
14096
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14097
+ "type": "object",
14098
+ "properties": {
14099
+ "source": {
14100
+ "type": [
14101
+ "string",
14102
+ "null"
14103
+ ]
14104
+ },
14105
+ "value": {
14106
+ "type": [
14107
+ "boolean",
14108
+ "null"
14109
+ ]
14110
+ }
14111
+ },
14112
+ "required": [
14113
+ "value",
14114
+ "source"
14115
+ ]
14116
+ },
14117
+ "Field10": {
14118
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14119
+ "type": "object",
14120
+ "properties": {
14121
+ "source": {
14122
+ "type": [
14123
+ "string",
14124
+ "null"
14125
+ ]
14126
+ },
14127
+ "value": {
14128
+ "type": [
14129
+ "array",
14130
+ "null"
14131
+ ],
14132
+ "items": {
14133
+ "$ref": "#/$defs/HookEntry"
14134
+ }
14135
+ }
14136
+ },
14137
+ "required": [
14138
+ "value",
14139
+ "source"
14140
+ ]
14141
+ },
14142
+ "Field2": {
14143
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14144
+ "type": "object",
14145
+ "properties": {
14146
+ "source": {
14147
+ "type": [
14148
+ "string",
14149
+ "null"
14150
+ ]
14151
+ },
14152
+ "value": {
14153
+ "type": [
14154
+ "array",
14155
+ "null"
14156
+ ],
14157
+ "items": {
14158
+ "type": "string"
14159
+ }
14160
+ }
14161
+ },
14162
+ "required": [
14163
+ "value",
14164
+ "source"
14165
+ ]
14166
+ },
14167
+ "Field3": {
14168
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14169
+ "type": "object",
14170
+ "properties": {
14171
+ "source": {
14172
+ "type": [
14173
+ "string",
14174
+ "null"
14175
+ ]
14176
+ },
14177
+ "value": {
14178
+ "type": [
14179
+ "string",
14180
+ "null"
14181
+ ]
14182
+ }
14183
+ },
14184
+ "required": [
14185
+ "value",
14186
+ "source"
14187
+ ]
14188
+ },
14189
+ "Field4": {
14190
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14191
+ "type": "object",
14192
+ "properties": {
14193
+ "source": {
14194
+ "type": [
14195
+ "string",
14196
+ "null"
14197
+ ]
14198
+ },
14199
+ "value": {
14200
+ "anyOf": [
14201
+ {
14202
+ "$ref": "#/$defs/PermissionMode"
14203
+ },
14204
+ {
14205
+ "type": "null"
14206
+ }
14207
+ ]
14208
+ }
14209
+ },
14210
+ "required": [
14211
+ "value",
14212
+ "source"
14213
+ ]
14214
+ },
14215
+ "Field5": {
14216
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14217
+ "type": "object",
14218
+ "properties": {
14219
+ "source": {
14220
+ "type": [
14221
+ "string",
14222
+ "null"
14223
+ ]
14224
+ },
14225
+ "value": {
14226
+ "type": [
14227
+ "integer",
14228
+ "null"
14229
+ ],
14230
+ "format": "uint64",
14231
+ "minimum": 0
14232
+ }
14233
+ },
14234
+ "required": [
14235
+ "value",
14236
+ "source"
14237
+ ]
14238
+ },
14239
+ "Field6": {
14240
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14241
+ "type": "object",
14242
+ "properties": {
14243
+ "source": {
14244
+ "type": [
14245
+ "string",
14246
+ "null"
14247
+ ]
14248
+ },
14249
+ "value": {
14250
+ "anyOf": [
14251
+ {
14252
+ "$ref": "#/$defs/OutputFormat"
14253
+ },
14254
+ {
14255
+ "type": "null"
14256
+ }
14257
+ ]
14258
+ }
14259
+ },
14260
+ "required": [
14261
+ "value",
14262
+ "source"
14263
+ ]
14264
+ },
14265
+ "Field7": {
14266
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14267
+ "type": "object",
14268
+ "properties": {
14269
+ "source": {
14270
+ "type": [
14271
+ "string",
14272
+ "null"
14273
+ ]
14274
+ },
14275
+ "value": {
14276
+ "type": [
14277
+ "integer",
14278
+ "null"
14279
+ ],
14280
+ "format": "uint32",
14281
+ "minimum": 0
14282
+ }
14283
+ },
14284
+ "required": [
14285
+ "value",
14286
+ "source"
14287
+ ]
14288
+ },
14289
+ "Field8": {
14290
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14291
+ "type": "object",
14292
+ "properties": {
14293
+ "source": {
14294
+ "type": [
14295
+ "string",
14296
+ "null"
14297
+ ]
14298
+ },
14299
+ "value": {
14300
+ "type": [
14301
+ "integer",
14302
+ "null"
14303
+ ],
14304
+ "format": "uint",
14305
+ "minimum": 0
14306
+ }
14307
+ },
14308
+ "required": [
14309
+ "value",
14310
+ "source"
14311
+ ]
14312
+ },
14313
+ "Field9": {
14314
+ "description": "One resolved field in the `oneharness config` report: the effective value\nplus where it came from (a config file path, or [`DEFAULT_SOURCE`]). Both\nare `null` when the field is unset everywhere and has no built-in default.",
14315
+ "type": "object",
14316
+ "properties": {
14317
+ "source": {
14318
+ "type": [
14319
+ "string",
14320
+ "null"
14321
+ ]
14322
+ },
14323
+ "value": {
14324
+ "anyOf": [
14325
+ {
14326
+ "$ref": "#/$defs/RunMode"
14327
+ },
14328
+ {
14329
+ "type": "null"
14330
+ }
14331
+ ]
14332
+ }
14333
+ },
14334
+ "required": [
14335
+ "value",
14336
+ "source"
14337
+ ]
14338
+ },
14339
+ "HarnessReport": {
14340
+ "description": "One harness's `[harness.<id>]` overrides, with provenance.",
14341
+ "type": "object",
14342
+ "properties": {
14343
+ "allowed_tools": {
14344
+ "$ref": "#/$defs/Field2"
14345
+ },
14346
+ "args": {
14347
+ "$ref": "#/$defs/Field2"
14348
+ },
14349
+ "bin": {
14350
+ "$ref": "#/$defs/Field3"
14351
+ },
14352
+ "denied_tools": {
14353
+ "$ref": "#/$defs/Field2"
14354
+ },
14355
+ "env": {
14356
+ "type": "object",
14357
+ "additionalProperties": {
14358
+ "$ref": "#/$defs/Field3"
14359
+ }
14360
+ },
14361
+ "hooks": {
14362
+ "type": "object",
14363
+ "additionalProperties": true
14364
+ },
14365
+ "model": {
14366
+ "$ref": "#/$defs/Field3"
14367
+ },
14368
+ "reasoning": {
14369
+ "$ref": "#/$defs/Field3"
14370
+ },
14371
+ "settings": {
14372
+ "type": "object",
14373
+ "additionalProperties": true
14374
+ },
14375
+ "variant": {
14376
+ "type": "object",
14377
+ "additionalProperties": {
14378
+ "$ref": "#/$defs/VariantReport"
14379
+ }
14380
+ }
14381
+ },
14382
+ "required": [
14383
+ "model",
14384
+ "reasoning",
14385
+ "bin",
14386
+ "args",
14387
+ "allowed_tools",
14388
+ "denied_tools",
14389
+ "hooks",
14390
+ "settings",
14391
+ "env",
14392
+ "variant"
14393
+ ]
14394
+ },
14395
+ "HookEntry": {
14396
+ "description": "One `[[hooks]]` entry: a pre-tool gate installed into each targeted harness.\nThe `command` may contain `{harness}`, replaced with the harness id when the\nhook is built (so one entry can route `mygate hook {harness}` to every CLI).",
14397
+ "type": "object",
14398
+ "properties": {
14399
+ "command": {
14400
+ "description": "The command the harness runs before a tool call. `{harness}` is\nsubstituted with the harness id. Required and non-empty.",
14401
+ "type": "string"
14402
+ },
14403
+ "harnesses": {
14404
+ "description": "Restrict this entry to these harness ids; absent means every harness\nbeing synced.",
14405
+ "type": [
14406
+ "array",
14407
+ "null"
14408
+ ],
14409
+ "items": {
14410
+ "type": "string"
14411
+ }
14412
+ },
14413
+ "matcher": {
14414
+ "description": "Tool-name matcher in the harness's dialect (most read it as a regex);\napplied to every targeted harness as written. Absent means match-all.",
14415
+ "type": [
14416
+ "string",
14417
+ "null"
14418
+ ]
14419
+ },
14420
+ "plugin_name": {
14421
+ "description": "Identity for plugin-delivered harnesses (Goose, OpenCode) and Copilot's\nper-owner file, so two tools' hooks never collide. Defaults to\n`oneharness`.",
14422
+ "type": [
14423
+ "string",
14424
+ "null"
14425
+ ]
14426
+ },
14427
+ "timeout": {
14428
+ "description": "Timeout in seconds, for the harnesses whose hook schema carries one\n(Goose, Crush); ignored by the others.",
14429
+ "type": [
14430
+ "integer",
14431
+ "null"
14432
+ ],
14433
+ "format": "uint64",
14434
+ "minimum": 0
14435
+ }
14436
+ },
14437
+ "additionalProperties": false,
14438
+ "required": [
14439
+ "command",
14440
+ "matcher",
14441
+ "timeout",
14442
+ "plugin_name",
14443
+ "harnesses"
14444
+ ]
14445
+ },
14446
+ "OutputFormat": {
14447
+ "description": "How a harness emits its result, which decides how `text` is extracted.\n\nAlso accepted as a CLI value (`--output-format`, parsed in the `oneharness`\nbinary) and a config-file value (`output_format`, via `Deserialize`). The\nCLI parsing lives in the binary so this core crate stays free of `clap`.",
14448
+ "oneOf": [
14449
+ {
14450
+ "description": "Plain text on stdout; `text` is the trimmed stdout.",
14451
+ "type": "string",
14452
+ "const": "text"
14453
+ },
14454
+ {
14455
+ "description": "A single JSON document on stdout.",
14456
+ "type": "string",
14457
+ "const": "json"
14458
+ },
14459
+ {
14460
+ "description": "Line-delimited JSON events on stdout.",
14461
+ "type": "string",
14462
+ "const": "stream-json"
14463
+ }
14464
+ ]
14465
+ },
14466
+ "PermissionMode": {
14467
+ "description": "The unified approval mode, from least to most autonomy. A harness may not\nsupport every value (see [`crate::domain::harness::HarnessSpec::mode`]); the\ncommand layer refuses an unsupported one before spawning, never silently\ndowngrading it.",
14468
+ "oneOf": [
14469
+ {
14470
+ "description": "No mutations — the agent may read but not edit files or run commands —\n*without* the plan workflow: it just does whatever read-only work the task\nallows. Mapped to each harness's strongest per-run no-mutation enforcement\n(Codex's read-only sandbox, Claude's deny rules, Copilot's `--deny-tool`,\nCursor's `ask` mode). The enforced counterpart to [`Self::Plan`].",
14471
+ "type": "string",
14472
+ "const": "read-only"
14473
+ },
14474
+ {
14475
+ "description": "Read and propose only — like [`Self::ReadOnly`], but additionally engages\nthe harness's *plan* workflow: research the task and write a plan rather\nthan act. Supported only where a native plan mode exists (Claude/Qwen/\nCursor/Copilot, OpenCode's `plan` agent); harnesses with no plan workflow\n(Codex, Goose, Crush) reject it — use [`Self::ReadOnly`] for those.",
14476
+ "type": "string",
14477
+ "const": "plan"
14478
+ },
14479
+ {
14480
+ "description": "The harness's normal ask flow, mapped to its cleanest *non-interactive*\nvariant so a headless run never blocks waiting for input (Claude's\n`dontAsk` deny-and-continue, Goose's fail-closed `approve`, Copilot's\nauto-deny). Where no such variant exists the harness's [`ModeHeadless`]\nis [`ModeHeadless::Hangs`].",
14481
+ "type": "string",
14482
+ "const": "default"
14483
+ },
14484
+ {
14485
+ "description": "Auto-approve file edits, still gate shell/commands. (Claude's\n`acceptEdits`, Qwen's `auto-edit`.)",
14486
+ "type": "string",
14487
+ "const": "edit"
14488
+ },
14489
+ {
14490
+ "description": "Auto-approve operations the harness deems safe (a classifier), gate the\nrisky ones. (Claude's `auto`, Qwen's `auto`, Goose's `smart_approve`.)",
14491
+ "type": "string",
14492
+ "const": "auto"
14493
+ },
14494
+ {
14495
+ "description": "Approve everything — no prompts, no gating. The headless default, because\nan unattended agent otherwise hangs on the first approval. Every harness\nsupports it. (Claude's `bypassPermissions`, Codex's\n`--dangerously-bypass-approvals-and-sandbox`, Qwen/Crush `--yolo`, …)",
14496
+ "type": "string",
14497
+ "const": "bypass"
14498
+ }
14499
+ ]
14500
+ },
14501
+ "RunMode": {
14502
+ "description": "How the selected harnesses are run. Accepted as a CLI value (`--run-mode`,\nparsed in the `oneharness` binary) and a config-file value (`run_mode`, via\n`Deserialize`); the CLI parsing lives in the binary so this core crate stays\nfree of `clap`.",
14503
+ "oneOf": [
14504
+ {
14505
+ "description": "Run every selected harness at once, each an independent subprocess, and\nreport them all. The default — the historical behavior.",
14506
+ "type": "string",
14507
+ "const": "parallel"
14508
+ },
14509
+ {
14510
+ "description": "Run the selected harnesses in priority order (the `--harness` / config\norder, else registry order under `--all`), stopping at the first that\nactually runs the task; fall through only the candidates that cannot run\nat all (see [`startup_failure_reason`]).",
14511
+ "type": "string",
14512
+ "const": "fallback"
14513
+ }
14514
+ ]
14515
+ },
14516
+ "VariantReport": {
14517
+ "type": "object",
14518
+ "properties": {
14519
+ "allowed_tools": {
14520
+ "$ref": "#/$defs/Field2"
14521
+ },
14522
+ "args": {
14523
+ "$ref": "#/$defs/Field2"
14524
+ },
14525
+ "bin": {
14526
+ "$ref": "#/$defs/Field3"
14527
+ },
14528
+ "denied_tools": {
14529
+ "$ref": "#/$defs/Field2"
14530
+ },
14531
+ "env": {
14532
+ "type": "object",
14533
+ "additionalProperties": {
14534
+ "$ref": "#/$defs/Field3"
14535
+ }
14536
+ },
14537
+ "env_file": {
14538
+ "$ref": "#/$defs/Field3"
14539
+ },
14540
+ "env_from": {
14541
+ "type": "object",
14542
+ "additionalProperties": {
14543
+ "$ref": "#/$defs/Field3"
14544
+ }
14545
+ },
14546
+ "hooks": {
14547
+ "type": "object",
14548
+ "additionalProperties": true
14549
+ },
14550
+ "model": {
14551
+ "$ref": "#/$defs/Field3"
14552
+ },
14553
+ "reasoning": {
14554
+ "$ref": "#/$defs/Field3"
14555
+ },
14556
+ "settings": {
14557
+ "type": "object",
14558
+ "additionalProperties": true
14559
+ },
14560
+ "unset_env": {
14561
+ "$ref": "#/$defs/Field2"
14562
+ }
14563
+ },
14564
+ "required": [
14565
+ "model",
14566
+ "reasoning",
14567
+ "bin",
14568
+ "args",
14569
+ "allowed_tools",
14570
+ "denied_tools",
14571
+ "hooks",
14572
+ "settings",
14573
+ "env_file",
14574
+ "env_from",
14575
+ "unset_env",
14576
+ "env"
14577
+ ]
14578
+ }
14579
+ }
14580
+ },
14581
+ "sync_options": {
14582
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14583
+ "title": "SyncOptions",
14584
+ "description": "Options accepted by the language SDKs' `sync()`.",
14585
+ "type": "object",
14586
+ "properties": {
14587
+ "check": {
14588
+ "description": "Report what would change and write nothing.",
14589
+ "type": "boolean"
14590
+ },
14591
+ "config": {
14592
+ "type": "string"
14593
+ },
14594
+ "cwd": {
14595
+ "type": "string"
14596
+ },
14597
+ "global": {
14598
+ "type": "boolean"
14599
+ },
14600
+ "harnesses": {
14601
+ "type": "array",
14602
+ "items": {
14603
+ "type": "string"
14604
+ }
14605
+ },
14606
+ "noConfig": {
14607
+ "type": "boolean"
14608
+ }
14609
+ },
14610
+ "additionalProperties": false
14611
+ },
14612
+ "sync_report": {
14613
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14614
+ "title": "SyncReport",
14615
+ "description": "The `oneharness sync` output contract.",
14616
+ "type": "object",
14617
+ "properties": {
14618
+ "check": {
14619
+ "description": "True under `--check`: statuses describe what *would* happen.",
14620
+ "type": "boolean"
14621
+ },
14622
+ "config_files": {
14623
+ "description": "The oneharness config files the synced settings came from.",
14624
+ "type": "array",
14625
+ "items": {
14626
+ "type": "string"
14627
+ }
14628
+ },
14629
+ "results": {
14630
+ "type": "array",
14631
+ "items": {
14632
+ "$ref": "#/$defs/SyncResult"
14633
+ }
14634
+ },
14635
+ "schema_version": {
14636
+ "type": "string"
14637
+ }
14638
+ },
14639
+ "required": [
14640
+ "schema_version",
14641
+ "config_files",
14642
+ "check",
14643
+ "results"
14644
+ ],
14645
+ "$defs": {
14646
+ "FileStatus": {
14647
+ "description": "What applying a fragment did (or, under `check`, would do) to one file.\n\nSerialized as the report token itself, so the wire value and the variant a\nconsumer matches on cannot drift apart.",
14648
+ "oneOf": [
14649
+ {
14650
+ "description": "The file did not exist and was (or would be) created.",
14651
+ "type": "string",
14652
+ "const": "created"
14653
+ },
14654
+ {
14655
+ "description": "The file existed and its content changed (or would change).",
14656
+ "type": "string",
14657
+ "const": "updated"
14658
+ },
14659
+ {
14660
+ "description": "The file already contains everything the fragment asks for.",
14661
+ "type": "string",
14662
+ "const": "unchanged"
14663
+ }
14664
+ ]
14665
+ },
14666
+ "HookFileResult": {
14667
+ "description": "One installed `[[hooks]]` file.",
14668
+ "type": "object",
14669
+ "properties": {
14670
+ "file": {
14671
+ "type": "string"
14672
+ },
14673
+ "status": {
14674
+ "$ref": "#/$defs/FileStatus"
14675
+ }
14676
+ },
14677
+ "required": [
14678
+ "file",
14679
+ "status"
14680
+ ]
14681
+ },
14682
+ "SyncResult": {
14683
+ "description": "What one harness's sync did (or would do).",
14684
+ "type": "object",
14685
+ "properties": {
14686
+ "file": {
14687
+ "description": "The permission/settings config file written (or that would be written);\n`null` when nothing of that kind is configured for this harness.",
14688
+ "type": [
14689
+ "string",
14690
+ "null"
14691
+ ]
14692
+ },
14693
+ "harness": {
14694
+ "type": "string"
14695
+ },
14696
+ "hooks": {
14697
+ "description": "Normalized `[[hooks]]` files installed into this harness (a Goose hook\nwrites two). Empty when no `[[hooks]]` entry targets it.",
14698
+ "type": "array",
14699
+ "items": {
14700
+ "$ref": "#/$defs/HookFileResult"
14701
+ }
14702
+ },
14703
+ "status": {
14704
+ "$ref": "#/$defs/SyncStatus"
14705
+ },
14706
+ "unmapped": {
14707
+ "description": "Top-level settings that have no mapping for this harness (e.g. a\ntop-level `allowed_tools` while the harness has no allow-list concept)\n— visible here and warned on stderr, never silently dropped.",
14708
+ "type": "array",
14709
+ "items": {
14710
+ "type": "string"
14711
+ }
14712
+ }
14713
+ },
14714
+ "required": [
14715
+ "harness",
14716
+ "file",
14717
+ "status",
14718
+ "hooks",
14719
+ "unmapped"
14720
+ ]
14721
+ },
14722
+ "SyncStatus": {
14723
+ "description": "What one harness's permission/settings sync did (or would do).\n\n[`FileStatus`] plus the one outcome a *file* never has: a harness with no\npermission/settings fragment to apply at all. Keeping them one closed set —\nrather than the report's earlier free string — is what makes an unreachable\nstatus unconstructible and lets the contract publish the four values.",
14724
+ "oneOf": [
14725
+ {
14726
+ "description": "The file did not exist and was (or would be) created.",
14727
+ "type": "string",
14728
+ "const": "created"
14729
+ },
14730
+ {
14731
+ "description": "The file existed and its content changed (or would change).",
14732
+ "type": "string",
14733
+ "const": "updated"
14734
+ },
14735
+ {
14736
+ "description": "The file already contains everything the fragment asks for.",
14737
+ "type": "string",
14738
+ "const": "unchanged"
14739
+ },
14740
+ {
14741
+ "description": "No permission/settings fragment applies to this harness, so there was no\nfile to write. Hook files carry their own [`FileStatus`].",
14742
+ "type": "string",
14743
+ "const": "skipped"
14744
+ }
14745
+ ]
14746
+ }
14747
+ }
14748
+ },
14749
+ "init_options": {
14750
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14751
+ "title": "InitOptions",
14752
+ "description": "Options accepted by the language SDKs' `init()`.",
14753
+ "type": "object",
14754
+ "properties": {
14755
+ "force": {
14756
+ "type": "boolean"
14757
+ },
14758
+ "path": {
14759
+ "description": "Where to write the starter config. Absent means `oneharness.toml` in the\nworking directory, exactly as the CLI's own default.",
14760
+ "type": "string"
14761
+ }
14762
+ },
14763
+ "additionalProperties": false
14764
+ },
14765
+ "usage_options": {
14766
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14767
+ "title": "UsageOptions",
14768
+ "description": "Options accepted by the language SDKs' `usage()`.",
14769
+ "type": "object",
14770
+ "properties": {
14771
+ "all": {
14772
+ "type": "boolean"
14773
+ },
14774
+ "bins": {
14775
+ "type": "object",
14776
+ "additionalProperties": {
14777
+ "type": "string"
14778
+ }
14779
+ },
14780
+ "config": {
14781
+ "type": "string"
14782
+ },
14783
+ "cwd": {
14784
+ "type": "string"
14785
+ },
14786
+ "exclude": {
14787
+ "type": "array",
14788
+ "items": {
14789
+ "type": "string"
14790
+ }
14791
+ },
14792
+ "harnesses": {
14793
+ "type": "array",
14794
+ "items": {
14795
+ "type": "string"
14796
+ }
14797
+ },
14798
+ "noConfig": {
14799
+ "type": "boolean"
14800
+ },
14801
+ "timeoutSeconds": {
14802
+ "type": "integer",
14803
+ "format": "uint64",
14804
+ "minimum": 0
14805
+ }
14806
+ },
14807
+ "additionalProperties": false
14808
+ },
14809
+ "usage_report": {
14810
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
14811
+ "title": "UsageReport",
14812
+ "description": "One usage report: every probed identity, stamped with a single observation\ntime supplied by the caller (this module reads no clock).\n\nDeserializing is a consumer boundary — `oneharness-core` is published for\nsibling tools — so the envelope is validated on the way in rather than\ntrusted: see [`UsageReportWire`].",
14813
+ "type": "object",
14814
+ "properties": {
14815
+ "identities": {
14816
+ "type": "array",
14817
+ "items": {
14818
+ "$ref": "#/$defs/UsageIdentity"
14819
+ }
14820
+ },
14821
+ "observed_at": {
14822
+ "description": "The instant the identities were observed, minted by the io layer's single\nclock read. A [`UtcInstant`], so the field cannot be *set* to something\nthat is not one — see [`UsageReport::new`].",
14823
+ "$ref": "#/$defs/UtcInstant"
14824
+ },
14825
+ "schema_version": {
14826
+ "description": "The shape version, as a type with one value — see [`SchemaVersion`].",
14827
+ "type": "string",
14828
+ "const": "0.1"
14829
+ }
14830
+ },
14831
+ "required": [
14832
+ "schema_version",
14833
+ "observed_at",
14834
+ "identities"
14835
+ ],
14836
+ "$defs": {
14837
+ "AuthMode": {
14838
+ "description": "How the identity authenticates, which is what decides whether plan headroom\nexists at all.",
14839
+ "oneOf": [
14840
+ {
14841
+ "description": "A first-party subscription (Claude.ai, ChatGPT, a GitHub Copilot seat).",
14842
+ "type": "string",
14843
+ "const": "subscription"
14844
+ },
14845
+ {
14846
+ "description": "An API key. Both claude-code and codex affirmatively report no plan\nheadroom in this mode — see [`UnavailableReason::ApiKeyAuth`].",
14847
+ "type": "string",
14848
+ "const": "api_key"
14849
+ },
14850
+ {
14851
+ "description": "Not established by the probe.",
14852
+ "type": "string",
14853
+ "const": "unknown"
14854
+ }
14855
+ ]
14856
+ },
14857
+ "IdentitySelector": {
14858
+ "description": "How one identity is selected for a probe. A secret-valued selector records\nonly the variable's *name*, so a credential can never reach the report.",
14859
+ "oneOf": [
14860
+ {
14861
+ "description": "An environment variable naming a credential *directory* — Claude Code's\n`CLAUDE_CONFIG_DIR`, codex's `CODEX_HOME`. The path is not a secret.",
14862
+ "type": "object",
14863
+ "properties": {
14864
+ "env": {
14865
+ "type": "string"
14866
+ },
14867
+ "kind": {
14868
+ "type": "string",
14869
+ "const": "env_path"
14870
+ },
14871
+ "path": {
14872
+ "type": "string"
14873
+ }
14874
+ },
14875
+ "required": [
14876
+ "kind",
14877
+ "env",
14878
+ "path"
14879
+ ]
14880
+ },
14881
+ {
14882
+ "description": "An environment variable carrying a credential — Copilot's GitHub token.\nThe value is deliberately absent.",
14883
+ "type": "object",
14884
+ "properties": {
14885
+ "env": {
14886
+ "type": "string"
14887
+ },
14888
+ "kind": {
14889
+ "type": "string",
14890
+ "const": "env_secret"
14891
+ }
14892
+ },
14893
+ "required": [
14894
+ "kind",
14895
+ "env"
14896
+ ]
14897
+ },
14898
+ {
14899
+ "description": "The harness's ambient credential store, with nothing overridden.",
14900
+ "type": "object",
14901
+ "properties": {
14902
+ "kind": {
14903
+ "type": "string",
14904
+ "const": "ambient"
14905
+ }
14906
+ },
14907
+ "required": [
14908
+ "kind"
14909
+ ]
14910
+ }
14911
+ ]
14912
+ },
14913
+ "QuotaAmount": {
14914
+ "description": "A counter that cannot legitimately be negative. An entitlement is a ceiling\nand a consumption is an amount spent; neither has a meaning below zero, so a\nnegative one is a payload that failed to parse rather than an account state,\nand it is rejected at the boundary like [`UsedPercent`].\n\nDeliberately *not* used for [`QuotaCounters::remaining`], which is genuinely\nnegative for an account past its ceiling — the deficit is the signal there,\nso constraining it would discard a real over-consumption reading.",
14915
+ "type": "integer",
14916
+ "format": "uint64",
14917
+ "minimum": 0
14918
+ },
14919
+ "QuotaCounters": {
14920
+ "description": "The raw counters behind a metered window.",
14921
+ "type": "object",
14922
+ "properties": {
14923
+ "entitlement": {
14924
+ "$ref": "#/$defs/QuotaAmount"
14925
+ },
14926
+ "has_quota": {
14927
+ "description": "Whether any quota remains on this plan.",
14928
+ "type": "boolean"
14929
+ },
14930
+ "overage_permitted": {
14931
+ "description": "Whether spending past the entitlement is permitted. `has_quota: false`\n*and* `overage_permitted: false` together are the machine-readable\n\"exhausted and blocked\" signal — see [`QuotaCounters::blocked`].",
14932
+ "type": "boolean"
14933
+ },
14934
+ "remaining": {
14935
+ "description": "The server's own remaining figure, taken as authoritative rather than\nrecomputed from `entitlement - used`: Copilot's observed values disagree\nby about 1 and the server's figure wins. Signed, and the one counter here\nthat is: an account past its ceiling reports a real deficit.",
14936
+ "type": "integer",
14937
+ "format": "int64"
14938
+ },
14939
+ "unit": {
14940
+ "$ref": "#/$defs/QuotaUnit"
14941
+ },
14942
+ "used": {
14943
+ "$ref": "#/$defs/QuotaAmount"
14944
+ }
14945
+ },
14946
+ "required": [
14947
+ "entitlement",
14948
+ "used",
14949
+ "remaining",
14950
+ "has_quota",
14951
+ "overage_permitted",
14952
+ "unit"
14953
+ ]
14954
+ },
14955
+ "QuotaUnit": {
14956
+ "description": "What the counters count.",
14957
+ "oneOf": [
14958
+ {
14959
+ "description": "GitHub AI credits, $0.01 each — Copilot's unit when `token_based_billing`\nis true.",
14960
+ "type": "string",
14961
+ "const": "ai_credits"
14962
+ },
14963
+ {
14964
+ "description": "The harness did not say what its counters count.",
14965
+ "type": "string",
14966
+ "const": "unspecified"
14967
+ }
14968
+ ]
14969
+ },
14970
+ "UnavailableReason": {
14971
+ "description": "Why an identity affirmatively has no plan headroom. Distinct from\n[`UnknownReason`]: these are answers, not absences of one.",
14972
+ "oneOf": [
14973
+ {
14974
+ "description": "API-key auth. Verified for both claude-code (`rate_limits_available:\nfalse`, `subscription_type: null`) and codex (`chatgpt authentication\nrequired to read rate limits`): the harness exposes no plan headroom in\nthis mode. This is a finding, never a guess — and it is *not*\n[`UsageAvailability::Unknown`].",
14975
+ "type": "string",
14976
+ "const": "api_key_auth"
14977
+ },
14978
+ {
14979
+ "description": "No stored credential for the selected identity — codex's `codex account\nauthentication required to read rate limits`, a different code branch\nfrom the API-key one above.",
14980
+ "type": "string",
14981
+ "const": "not_logged_in"
14982
+ },
14983
+ {
14984
+ "description": "The harness answered, but carried no readable window at all.",
14985
+ "type": "string",
14986
+ "const": "no_windows_reported"
14987
+ },
14988
+ {
14989
+ "description": "The harness has **no first-party plan quota** for headroom to exist in:\nOpenCode Zen is pay-as-you-go with nothing that resets, and Goose ships\nno first-party inference plan at all. Nothing is missing here — the\nquantity itself is undefined, which is why this is not\n[`Self::NoHeadroomReader`].",
14990
+ "type": "string",
14991
+ "const": "no_plan_quota"
14992
+ },
14993
+ {
14994
+ "description": "A plan quota exists but the harness exposes **no non-interactive reader**\nfor it: Cursor's dollar pools reach only its interactive TUI, Crush's\nHyper credits have no balance command or API, and Qwen's Coding Plan\nweekly quota has no reader of any kind. A future CLI release could add\none, which is exactly what separates this from [`Self::NoPlanQuota`].",
14995
+ "type": "string",
14996
+ "const": "no_headroom_reader"
14997
+ }
14998
+ ]
14999
+ },
15000
+ "UnknownReason": {
15001
+ "description": "Why nothing is known. Reserved **strictly** for unprobed or probe-failed —\nAPI-key auth is [`UnavailableReason::ApiKeyAuth`], not this.",
15002
+ "oneOf": [
15003
+ {
15004
+ "description": "No probe was run for this identity.",
15005
+ "type": "object",
15006
+ "properties": {
15007
+ "kind": {
15008
+ "type": "string",
15009
+ "const": "unprobed"
15010
+ }
15011
+ },
15012
+ "required": [
15013
+ "kind"
15014
+ ]
15015
+ },
15016
+ {
15017
+ "description": "A probe ran and failed, carrying the harness's own message.",
15018
+ "type": "object",
15019
+ "properties": {
15020
+ "kind": {
15021
+ "type": "string",
15022
+ "const": "probe_failed"
15023
+ },
15024
+ "message": {
15025
+ "type": "string"
15026
+ }
15027
+ },
15028
+ "required": [
15029
+ "kind",
15030
+ "message"
15031
+ ]
15032
+ },
15033
+ {
15034
+ "description": "The harness's binary is not installed, so its probe could not run. The\nharness may well have headroom; this identity simply has no reader on\nthis machine. Mirrors a run's `skipped` status: data, never a crash.\nBuild it with [`UnknownReason::binary_missing`].",
15035
+ "type": "object",
15036
+ "properties": {
15037
+ "bin": {
15038
+ "type": "string"
15039
+ },
15040
+ "kind": {
15041
+ "type": "string",
15042
+ "const": "binary_missing"
15043
+ }
15044
+ },
15045
+ "required": [
15046
+ "kind",
15047
+ "bin"
15048
+ ]
15049
+ }
15050
+ ]
15051
+ },
15052
+ "UsageAvailability": {
15053
+ "description": "Tri-state headroom availability.\n\nThe three states are genuinely different answers and are never collapsed:\n`available` carries real data, `unavailable` is an affirmative \"this identity\nhas no plan headroom to report\" **with a reason**, and `unknown` means only\nthat nothing was learned. There is no percentage reachable from either\nnon-available state, so neither can be rendered as `0%` used.",
15054
+ "oneOf": [
15055
+ {
15056
+ "description": "Real headroom data: one entry per non-null window, never empty.",
15057
+ "type": "object",
15058
+ "properties": {
15059
+ "state": {
15060
+ "type": "string",
15061
+ "const": "available"
15062
+ },
15063
+ "windows": {
15064
+ "$ref": "#/$defs/Windows"
15065
+ }
15066
+ },
15067
+ "required": [
15068
+ "state",
15069
+ "windows"
15070
+ ]
15071
+ },
15072
+ {
15073
+ "description": "The harness answered and affirmatively reported no plan headroom.",
15074
+ "type": "object",
15075
+ "properties": {
15076
+ "reason": {
15077
+ "$ref": "#/$defs/UnavailableReason"
15078
+ },
15079
+ "state": {
15080
+ "type": "string",
15081
+ "const": "unavailable"
15082
+ }
15083
+ },
15084
+ "required": [
15085
+ "state",
15086
+ "reason"
15087
+ ]
15088
+ },
15089
+ {
15090
+ "description": "Nothing was learned — the identity was not probed, or the probe failed.",
15091
+ "type": "object",
15092
+ "properties": {
15093
+ "reason": {
15094
+ "$ref": "#/$defs/UnknownReason"
15095
+ },
15096
+ "state": {
15097
+ "type": "string",
15098
+ "const": "unknown"
15099
+ }
15100
+ },
15101
+ "required": [
15102
+ "state",
15103
+ "reason"
15104
+ ]
15105
+ }
15106
+ ]
15107
+ },
15108
+ "UsageIdentity": {
15109
+ "description": "One harness identity's headroom.\n\nDeserializing is a consumer boundary like the envelope's, so every string an\nidentity carries is flattened through [`without_control_chars`] on the way in\n— see [`UsageIdentityWire`].",
15110
+ "type": "object",
15111
+ "properties": {
15112
+ "auth_mode": {
15113
+ "$ref": "#/$defs/AuthMode"
15114
+ },
15115
+ "availability": {
15116
+ "$ref": "#/$defs/UsageAvailability"
15117
+ },
15118
+ "harness": {
15119
+ "description": "Canonical harness id, matching a [`crate::domain::harness`] registry id.",
15120
+ "type": "string"
15121
+ },
15122
+ "plan": {
15123
+ "description": "The plan as the harness spells it, **verbatim**: Claude's `max` and\ncodex's `pro` are different vocabularies and are never unified into one\nenum. Absent when the harness reports no plan (an API-key session).",
15124
+ "type": [
15125
+ "string",
15126
+ "null"
15127
+ ]
15128
+ },
15129
+ "selector": {
15130
+ "description": "How this identity was selected — never the credential itself.",
15131
+ "$ref": "#/$defs/IdentitySelector"
15132
+ },
15133
+ "variant": {
15134
+ "description": "The named variant this identity came from, when it was selected by a\ncomposed id (`claude-code:work`). Absent for a bare harness id, matching\n[`crate::domain::report::RunResult::variant`] — so a consumer joins a\nusage identity to the runs it describes on the same pair of fields.\n\nTwo subscriptions of one harness therefore stay distinguishable even when\ntheir [`IdentitySelector`]s do not distinguish them (a variant that\nselects an identity by credential rather than by directory).\n\nA [`VariantName`], so the field cannot be *set* to a name no config could\nhave declared — the same enforcement [`UsageReport::observed_at`] gets\nfrom [`UtcInstant`]. It serializes transparently, so the wire keeps the\nplain string [`crate::domain::report::RunResult::variant`] carries.",
15135
+ "type": [
15136
+ "string",
15137
+ "null"
15138
+ ]
15139
+ }
15140
+ },
15141
+ "required": [
15142
+ "harness",
15143
+ "selector",
15144
+ "auth_mode",
15145
+ "availability"
15146
+ ]
15147
+ },
15148
+ "UsageWindow": {
15149
+ "description": "One rate-limit window. Emitted only for a window the harness actually\nreported: a null window (Claude's `seven_day_opus: null`, codex's `secondary:\nnull`) means \"not applicable to this plan\", **not** \"0% used\", so it is\nomitted rather than zero-filled.",
15150
+ "type": "object",
15151
+ "properties": {
15152
+ "id": {
15153
+ "description": "The harness-native window identifier, verbatim where the harness names\none (`five_hour`, `tangelo`, `chat`) and `<limitId>/<slot>` where codex's\ntwo-level buckets are flattened.",
15154
+ "type": "string"
15155
+ },
15156
+ "is_binding": {
15157
+ "description": "Whether this is the limit currently binding, when the harness says so\n(Claude's `limits[].is_active`). Absent when it does not.",
15158
+ "type": [
15159
+ "boolean",
15160
+ "null"
15161
+ ]
15162
+ },
15163
+ "label": {
15164
+ "description": "A human label the harness supplied (codex's `limitName`), when it did.",
15165
+ "type": [
15166
+ "string",
15167
+ "null"
15168
+ ]
15169
+ },
15170
+ "resets_at": {
15171
+ "description": "When the window resets, always absolute RFC 3339 UTC — a [`UtcInstant`],\nso no other text is representable here. Absent when the harness reported\nno reset, or one that could not be normalized.",
15172
+ "anyOf": [
15173
+ {
15174
+ "$ref": "#/$defs/UtcInstant"
15175
+ },
15176
+ {
15177
+ "type": "null"
15178
+ }
15179
+ ]
15180
+ },
15181
+ "scope": {
15182
+ "description": "The model display name this window is scoped to, when it is scoped.",
15183
+ "type": [
15184
+ "string",
15185
+ "null"
15186
+ ]
15187
+ },
15188
+ "usage": {
15189
+ "$ref": "#/$defs/WindowUsage"
15190
+ }
15191
+ },
15192
+ "oneOf": [
15193
+ {
15194
+ "description": "The harness stated the length (codex's `windowDurationMins`).",
15195
+ "type": "object",
15196
+ "properties": {
15197
+ "window_seconds": {
15198
+ "type": "integer",
15199
+ "format": "uint64",
15200
+ "minimum": 1
15201
+ },
15202
+ "window_seconds_source": {
15203
+ "type": "string",
15204
+ "const": "reported"
15205
+ }
15206
+ },
15207
+ "required": [
15208
+ "window_seconds_source",
15209
+ "window_seconds"
15210
+ ]
15211
+ },
15212
+ {
15213
+ "description": "Derived from the harness's own window key (Claude's `five_hour`).",
15214
+ "type": "object",
15215
+ "properties": {
15216
+ "window_seconds": {
15217
+ "type": "integer",
15218
+ "format": "uint64",
15219
+ "minimum": 1
15220
+ },
15221
+ "window_seconds_source": {
15222
+ "type": "string",
15223
+ "const": "inferred_from_id"
15224
+ }
15225
+ },
15226
+ "required": [
15227
+ "window_seconds_source",
15228
+ "window_seconds"
15229
+ ]
15230
+ },
15231
+ {
15232
+ "description": "Not derivable — an opaque key, or a calendar window with no fixed length.",
15233
+ "type": "object",
15234
+ "properties": {
15235
+ "window_seconds_source": {
15236
+ "type": "string",
15237
+ "const": "unknown"
15238
+ }
15239
+ },
15240
+ "required": [
15241
+ "window_seconds_source"
15242
+ ]
15243
+ }
15244
+ ],
15245
+ "required": [
15246
+ "id",
15247
+ "usage"
15248
+ ]
15249
+ },
15250
+ "UsedPercent": {
15251
+ "description": "A validated percent-**used** figure, whatever polarity the harness reported.\n\nValidated at the boundary rather than trusted: a harness's payload is\nexternal input, and a `NaN`, an infinity, or a negative percentage would\nrender as a nonsense bar. A value *above* 100 is accepted and preserved\nrather than clamped — it means the harness reported consumption past its own\nceiling (an overage), which is precisely when a consumer needs the figure.\n\n`schemars` describes the newtype's private field rather than the `f64` the\nserde attributes make it travel as, so the derived schema constrained\nnothing at all — `with` plus the boundary's own bound is what makes the\ngenerated validators check what [`UsedPercent::new`] checks. (JSON has no\n`NaN` or infinity literal, so \"finite\" needs nothing said.)",
15252
+ "type": "number",
15253
+ "format": "double",
15254
+ "minimum": 0
15255
+ },
15256
+ "UtcInstant": {
15257
+ "description": "An RFC 3339 timestamp in UTC (`Z`), in oneharness's canonical spelling.",
15258
+ "type": "string"
15259
+ },
15260
+ "WindowUsage": {
15261
+ "description": "What a window's consumption looks like. An unlimited quota carries no\ncounters, so it can never be rendered as a metered bar at 0% used.",
15262
+ "oneOf": [
15263
+ {
15264
+ "type": "object",
15265
+ "properties": {
15266
+ "counters": {
15267
+ "description": "The raw counters behind the percentage, when the harness reported\nevery one of them. Never partially fabricated, and absent rather than\nnull when the payload did not carry the full set.",
15268
+ "anyOf": [
15269
+ {
15270
+ "$ref": "#/$defs/QuotaCounters"
15271
+ },
15272
+ {
15273
+ "type": "null"
15274
+ }
15275
+ ]
15276
+ },
15277
+ "kind": {
15278
+ "type": "string",
15279
+ "const": "metered"
15280
+ },
15281
+ "used_percent": {
15282
+ "description": "**Always percent-used**, whatever polarity the source used, and\nvalidated at the boundary — see [`UsedPercent`].",
15283
+ "$ref": "#/$defs/UsedPercent"
15284
+ }
15285
+ },
15286
+ "required": [
15287
+ "kind",
15288
+ "used_percent"
15289
+ ]
15290
+ },
15291
+ {
15292
+ "description": "The harness reported this quota as unlimited. No counter is read: an\nunlimited Copilot snapshot reports `entitlement: 0` / `remaining: 0`\nalongside `percent_remaining: 100.0`, which are meaningless as counters.",
15293
+ "type": "object",
15294
+ "properties": {
15295
+ "kind": {
15296
+ "type": "string",
15297
+ "const": "unlimited"
15298
+ }
15299
+ },
15300
+ "required": [
15301
+ "kind"
15302
+ ]
15303
+ }
15304
+ ]
15305
+ },
15306
+ "Windows": {
15307
+ "description": "A non-empty list of windows. The non-emptiness is the invariant that keeps\n\"available\" from ever meaning \"no data\" — construct it with [`Windows::new`].",
15308
+ "type": "array",
15309
+ "items": {
15310
+ "$ref": "#/$defs/UsageWindow"
15311
+ }
15312
+ }
15313
+ }
15314
+ },
15315
+ "gate_options": {
15316
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15317
+ "title": "GateOptions",
15318
+ "description": "Options accepted by the language SDKs' `gate()` — the pre-tool gate an\ninstalled hook invokes, driven directly so a consumer hosting its own hook\nrunner never has to shell out and parse.",
15319
+ "type": "object",
15320
+ "properties": {
15321
+ "denyIfContains": {
15322
+ "type": "string"
15323
+ },
15324
+ "event": {
15325
+ "description": "The harness's pre-tool hook event, written to the gate's stdin.",
15326
+ "type": "string"
15327
+ },
15328
+ "harness": {
15329
+ "description": "The harness whose hook protocol to speak.",
15330
+ "type": "string",
15331
+ "minLength": 1
15332
+ },
15333
+ "reason": {
15334
+ "type": "string"
15335
+ }
15336
+ },
15337
+ "additionalProperties": false,
15338
+ "required": [
15339
+ "harness",
15340
+ "event"
15341
+ ]
15342
+ },
15343
+ "mock_options": {
15344
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15345
+ "title": "MockOptions",
15346
+ "description": "Options accepted by the language SDKs' `mock()`.",
15347
+ "type": "object",
15348
+ "properties": {
15349
+ "event": {
15350
+ "description": "The harness's pre-tool hook event, written to the responder's stdin.",
15351
+ "type": "string"
15352
+ },
15353
+ "harness": {
15354
+ "type": "string",
15355
+ "minLength": 1
15356
+ },
15357
+ "rules": {
15358
+ "type": "string"
15359
+ },
15360
+ "spyFile": {
15361
+ "type": "string"
15362
+ }
15363
+ },
15364
+ "additionalProperties": false,
15365
+ "required": [
15366
+ "harness",
15367
+ "event"
15368
+ ]
15369
+ },
15370
+ "interrupt_options": {
15371
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15372
+ "title": "InterruptOptions",
15373
+ "description": "Options accepted by the language SDKs' `interrupt()`.",
15374
+ "type": "object",
15375
+ "properties": {
15376
+ "cwd": {
15377
+ "type": "string"
15378
+ },
15379
+ "input": {
15380
+ "type": "string"
15381
+ },
15382
+ "session": {
15383
+ "description": "The caller-owned session handle the target run was started with.",
15384
+ "type": "string",
15385
+ "minLength": 1
15386
+ },
15387
+ "sessionDir": {
15388
+ "type": "string"
15389
+ }
15390
+ },
15391
+ "additionalProperties": false,
15392
+ "required": [
15393
+ "session"
15394
+ ]
15395
+ },
15396
+ "interrupt_response": {
15397
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15398
+ "title": "ControlResponse",
15399
+ "description": "The answer to one `oneharness interrupt`: either the abort was served, or it was refused with a reason.",
15400
+ "oneOf": [
15401
+ {
15402
+ "type": "object",
15403
+ "properties": {
15404
+ "error": false,
15405
+ "mechanism": {
15406
+ "$ref": "#/$defs/ControlShape"
15407
+ },
15408
+ "ok": {
15409
+ "type": "boolean",
15410
+ "const": true
15411
+ },
15412
+ "reason": false,
15413
+ "redirected": {
15414
+ "description": "Whether the request's redirection was committed with the abort. Omitted rather than sent as `false`, so a plain interrupt's answer gains no field the supervisor did not ask for.",
15415
+ "type": "boolean"
15416
+ },
15417
+ "v": {
15418
+ "type": "integer",
15419
+ "const": 2
15420
+ }
15421
+ },
15422
+ "required": [
15423
+ "v",
15424
+ "ok",
15425
+ "mechanism"
15426
+ ]
15427
+ },
15428
+ {
15429
+ "type": "object",
15430
+ "properties": {
15431
+ "error": {
15432
+ "type": "string"
15433
+ },
15434
+ "mechanism": false,
15435
+ "ok": {
15436
+ "type": "boolean",
15437
+ "const": false
15438
+ },
15439
+ "reason": {
15440
+ "$ref": "#/$defs/ControlReason"
15441
+ },
15442
+ "redirected": {
15443
+ "const": false
15444
+ },
15445
+ "v": {
15446
+ "type": "integer",
15447
+ "const": 2
15448
+ }
15449
+ },
15450
+ "required": [
15451
+ "v",
15452
+ "ok",
15453
+ "error",
15454
+ "reason"
15455
+ ]
15456
+ }
15457
+ ],
15458
+ "$defs": {
15459
+ "ControlReason": {
15460
+ "description": "Why a control request could not be served. Distinct reasons because a\nsupervisor reacts differently to each: `unsupported` is permanent for the\nharness, `not_running` means the dispatch is gone, `no_active_turn` means\nthe run is alive but between turns.",
15461
+ "oneOf": [
15462
+ {
15463
+ "description": "The harness declares no [`ControlShape`] — the lever does not exist.",
15464
+ "type": "string",
15465
+ "const": "unsupported"
15466
+ },
15467
+ {
15468
+ "description": "The run is alive but no turn is in flight right now.",
15469
+ "type": "string",
15470
+ "const": "no_active_turn"
15471
+ },
15472
+ {
15473
+ "description": "No run is listening on the socket (never started, already exited, or a\nstale socket file left by an abnormally-terminated dispatch).",
15474
+ "type": "string",
15475
+ "const": "not_running"
15476
+ }
15477
+ ]
15478
+ },
15479
+ "ControlShape": {
15480
+ "description": "How a harness accepts an out-of-band interrupt for an in-flight turn.\n\nRegistry data on [`crate::domain::harness::HarnessSpec::control`], sourced\nfrom a live interrupt against the real CLI — never guessed. `None` there\nmeans `oneharness interrupt` is a loud usage error for the harness, never a\nsilent no-op: a supervisor that is told \"ok\" while the turn keeps running is\nworse off than one told the lever does not exist.",
15481
+ "oneOf": [
15482
+ {
15483
+ "description": "Claude Code: the control frame rides the run process's **own stdin**\n(`-p --input-format stream-json`), so no sidecar server is needed. A\n`{\"type\":\"control_request\",…,\"request\":{\"subtype\":\"interrupt\"}}` line\naborts the turn with a `result` document; the session survives and a\nlater turn continues it with full context. Verified live: a plain user\nmessage written mid-turn is *silently dropped*, so the control frame is\nthe only mechanism that works.",
15484
+ "type": "string",
15485
+ "const": "claude-control-request"
15486
+ },
15487
+ {
15488
+ "description": "Codex: `turn/interrupt {threadId,turnId}` over the `codex app-server`\nJSON-RPC stdio protocol, which oneharness spawns as the run's own child\nand drives the thread/turn lifecycle on — so the interrupt rides the same\nopen stdin and nothing is shared or pooled.",
15489
+ "type": "string",
15490
+ "const": "codex-app-server"
15491
+ },
15492
+ {
15493
+ "description": "OpenCode: `POST /api/session/{id}/interrupt` against `opencode serve`.",
15494
+ "type": "string",
15495
+ "const": "opencode-http"
15496
+ },
15497
+ {
15498
+ "description": "Goose and Copilot: the ACP `session/cancel` **notification** (no `id`)\nover their JSON-RPC stdio servers.",
15499
+ "type": "string",
15500
+ "const": "acp-cancel"
15501
+ },
15502
+ {
15503
+ "description": "Crush: `POST /v1/workspaces/{id}/agent/sessions/{sid}/cancel` against\n`crush server`.",
15504
+ "type": "string",
15505
+ "const": "crush-http"
15506
+ }
15507
+ ]
15508
+ }
15509
+ }
15510
+ },
15511
+ "history_clear_options": {
15512
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15513
+ "title": "HistoryClearOptions",
15514
+ "description": "Options accepted by the language SDKs' `historyClear()`.",
15515
+ "type": "object",
15516
+ "properties": {
15517
+ "allProjects": {
15518
+ "type": "boolean"
15519
+ },
15520
+ "config": {
15521
+ "type": "string"
15522
+ },
15523
+ "historyDir": {
15524
+ "type": "string"
15525
+ },
15526
+ "noConfig": {
15527
+ "type": "boolean"
15528
+ },
15529
+ "project": {
15530
+ "type": "string"
15531
+ },
15532
+ "yes": {
15533
+ "description": "Actually delete. Absent or false reports what would be removed and\nremoves nothing, so a caller can always look first.",
15534
+ "type": "boolean"
15535
+ }
15536
+ },
15537
+ "additionalProperties": false
15538
+ },
15539
+ "history_clear_report": {
15540
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15541
+ "title": "HistoryClearReport",
15542
+ "description": "The `oneharness history clear` output contract.\n\n`clear` is a dry run until `--yes`, and the two phases have always printed\n*different* documents: a real run reports `removed`, a dry run reports\n`would_remove` plus the hint that makes it real. That difference is the\ncontract, so this is a sum of the two frames rather than one struct with\nboth counts optional — which would let a consumer read a deletion count off\na run that deleted nothing. Untagged, because `dry_run` is the discriminant\nthe published shape already carries.",
15543
+ "anyOf": [
15544
+ {
15545
+ "$ref": "#/$defs/HistoryClearRemoved"
15546
+ },
15547
+ {
15548
+ "$ref": "#/$defs/HistoryClearDryRun"
15549
+ }
15550
+ ],
15551
+ "$defs": {
15552
+ "HistoryClearDryRun": {
15553
+ "description": "The frame a run without `--yes` prints: these files *would* go.",
15554
+ "type": "object",
15555
+ "properties": {
15556
+ "dry_run": {
15557
+ "type": "boolean",
15558
+ "const": true
15559
+ },
15560
+ "files": {
15561
+ "type": "array",
15562
+ "items": {
15563
+ "type": "string"
15564
+ }
15565
+ },
15566
+ "hint": {
15567
+ "description": "How to make the dry run real. Constant text, carried in the document so\na JSON consumer gets the same guidance the text view prints.",
15568
+ "type": "string"
15569
+ },
15570
+ "would_remove": {
15571
+ "type": "integer",
15572
+ "format": "uint",
15573
+ "minimum": 0
15574
+ }
15575
+ },
15576
+ "required": [
15577
+ "would_remove",
15578
+ "files",
15579
+ "dry_run",
15580
+ "hint"
15581
+ ]
15582
+ },
15583
+ "HistoryClearRemoved": {
15584
+ "description": "The frame a `--yes` run prints: these files are gone.",
15585
+ "type": "object",
15586
+ "properties": {
15587
+ "dry_run": {
15588
+ "description": "Always `false` — the field is what tells the two frames apart, so it is\na literal rather than a flag either constructor could get wrong.",
15589
+ "type": "boolean",
15590
+ "const": false
15591
+ },
15592
+ "files": {
15593
+ "type": "array",
15594
+ "items": {
15595
+ "type": "string"
15596
+ }
15597
+ },
15598
+ "removed": {
15599
+ "type": "integer",
15600
+ "format": "uint",
15601
+ "minimum": 0
15602
+ }
15603
+ },
15604
+ "required": [
15605
+ "removed",
15606
+ "files",
15607
+ "dry_run"
15608
+ ]
15609
+ }
15610
+ }
15611
+ },
15612
+ "history_migrate_options": {
15613
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15614
+ "title": "HistoryMigrateOptions",
15615
+ "description": "Options accepted by the language SDKs' `historyMigrate()`.",
15616
+ "type": "object",
15617
+ "properties": {
15618
+ "config": {
15619
+ "type": "string"
15620
+ },
15621
+ "historyDir": {
15622
+ "type": "string"
15623
+ },
15624
+ "noConfig": {
15625
+ "type": "boolean"
15626
+ }
15627
+ },
15628
+ "additionalProperties": false
15629
+ },
15630
+ "history_migrate_report": {
15631
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
15632
+ "title": "HistoryMigrateReport",
15633
+ "description": "The `oneharness history migrate` output contract.\n\nA type rather than the inline `json!` literal it replaced, because an SDK\ncannot validate a document that has no schema — which is what left this\ncapability's `output` unbacked in the capability manifest.",
15634
+ "type": "object",
15635
+ "properties": {
15636
+ "files": {
15637
+ "description": "One entry per session file the migration touched.",
15638
+ "type": "array",
15639
+ "items": {
15640
+ "$ref": "#/$defs/MigrationSummary"
15641
+ }
15642
+ },
15643
+ "files_processed": {
15644
+ "description": "`files.len()`, carried so a consumer reading only the summary does not\nhave to walk the array.",
15645
+ "type": "integer",
15646
+ "format": "uint",
15647
+ "minimum": 0
15648
+ }
15649
+ },
15650
+ "required": [
15651
+ "files",
15652
+ "files_processed"
15653
+ ],
15654
+ "$defs": {
15655
+ "MigrationSummary": {
15656
+ "description": "Outcome for one session file processed by [`migrate`]. Counts refer to\nwhole legacy records and current v1.0 lines; unreadable lines are preserved\nbyte-for-byte and reported as skipped.",
15657
+ "type": "object",
15658
+ "properties": {
15659
+ "already_current": {
15660
+ "type": "integer",
15661
+ "format": "uint",
15662
+ "minimum": 0
15663
+ },
15664
+ "path": {
15665
+ "type": "string"
15666
+ },
15667
+ "records_migrated": {
15668
+ "type": "integer",
15669
+ "format": "uint",
15670
+ "minimum": 0
15671
+ },
15672
+ "skipped": {
15673
+ "type": "integer",
15674
+ "format": "uint",
15675
+ "minimum": 0
15676
+ }
15677
+ },
15678
+ "required": [
15679
+ "path",
15680
+ "records_migrated",
15681
+ "skipped",
15682
+ "already_current"
15683
+ ]
15684
+ }
15685
+ }
12456
15686
  }
12457
15687
  }