@forwardimpact/libharness 0.1.22 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/LICENSE +21 -201
  2. package/README.md +196 -80
  3. package/bin/fit-benchmark.js +44 -0
  4. package/bin/fit-harness.js +358 -0
  5. package/bin/fit-selfedit.js +165 -0
  6. package/bin/fit-trace.js +510 -0
  7. package/package.json +41 -11
  8. package/src/agent-runner.js +256 -0
  9. package/src/benchmark/apm-installer.js +207 -0
  10. package/src/benchmark/env-loader.js +158 -0
  11. package/src/benchmark/hook-env.js +40 -0
  12. package/src/benchmark/invariants.js +141 -0
  13. package/src/benchmark/judge.js +187 -0
  14. package/src/benchmark/npm-installer.js +87 -0
  15. package/src/benchmark/report.js +604 -0
  16. package/src/benchmark/result.js +127 -0
  17. package/src/benchmark/runner.js +688 -0
  18. package/src/benchmark/scheduler.js +78 -0
  19. package/src/benchmark/task-family.js +260 -0
  20. package/src/benchmark/workdir.js +344 -0
  21. package/src/commands/assert.js +153 -0
  22. package/src/commands/benchmark-definition.js +175 -0
  23. package/src/commands/benchmark-invariants.js +73 -0
  24. package/src/commands/benchmark-report.js +51 -0
  25. package/src/commands/benchmark-run.js +175 -0
  26. package/src/commands/by-discussion.js +94 -0
  27. package/src/commands/callback.js +119 -0
  28. package/src/commands/discuss.js +132 -0
  29. package/src/commands/facilitate.js +123 -0
  30. package/src/commands/output.js +36 -0
  31. package/src/commands/run.js +152 -0
  32. package/src/commands/supervise.js +136 -0
  33. package/src/commands/task-input.js +54 -0
  34. package/src/commands/tee.js +53 -0
  35. package/src/commands/trace.js +630 -0
  36. package/src/commands/work-tracker.js +35 -0
  37. package/src/cost.js +79 -0
  38. package/src/discuss-tools.js +173 -0
  39. package/src/discusser.js +394 -0
  40. package/src/events/github.js +161 -0
  41. package/src/facilitator.js +205 -0
  42. package/src/inbox-poller.js +81 -0
  43. package/src/index.js +72 -2
  44. package/src/judge.js +210 -0
  45. package/src/message-bus.js +118 -0
  46. package/src/orchestration-loop.js +330 -0
  47. package/src/orchestration-toolkit.js +441 -0
  48. package/src/orchestrator-helpers.js +23 -0
  49. package/src/profile-prompt.js +266 -0
  50. package/src/redaction.js +253 -0
  51. package/src/render/line-renderer.js +54 -0
  52. package/src/render/orchestrator-filter.js +19 -0
  53. package/src/render/palette.js +63 -0
  54. package/src/render/tool-hints.js +154 -0
  55. package/src/render/turn-renderer.js +96 -0
  56. package/src/reply-emitter.js +47 -0
  57. package/src/sequence-counter.js +21 -0
  58. package/src/signature-filter.js +27 -0
  59. package/src/supervisor.js +236 -0
  60. package/src/tee-writer.js +150 -0
  61. package/src/trace-collector.js +444 -0
  62. package/src/trace-github.js +473 -0
  63. package/src/trace-multi.js +101 -0
  64. package/src/trace-query.js +748 -0
  65. package/src/trace-render.js +211 -0
  66. package/src/trace-usage.js +249 -0
  67. package/src/fixture/assertions.js +0 -42
  68. package/src/fixture/cache.js +0 -50
  69. package/src/fixture/eval.js +0 -146
  70. package/src/fixture/index.js +0 -9
  71. package/src/fixture/pathway.js +0 -451
  72. package/src/fixture/services.js +0 -56
  73. package/src/mock/clients.js +0 -135
  74. package/src/mock/config.js +0 -45
  75. package/src/mock/data.js +0 -46
  76. package/src/mock/fs.js +0 -111
  77. package/src/mock/grpc.js +0 -94
  78. package/src/mock/http.js +0 -60
  79. package/src/mock/index.js +0 -36
  80. package/src/mock/infra.js +0 -219
  81. package/src/mock/logger.js +0 -42
  82. package/src/mock/observer.js +0 -74
  83. package/src/mock/resource-index.js +0 -95
  84. package/src/mock/service-callbacks.js +0 -39
  85. package/src/mock/services.js +0 -79
  86. package/src/mock/spy.js +0 -44
  87. package/src/mock/storage.js +0 -118
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Result-record schemas and runtime validators.
3
+ *
4
+ * Two schemas live here:
5
+ * - RESULT_RECORD_SCHEMA — one record per (task, runIndex) from a full
6
+ * benchmark run. Has a happy branch (invariants + judge present) and a
7
+ * pre-flight-failure branch (invariants/judgeVerdict/submission absent).
8
+ * - INVARIANTS_RECORD_SCHEMA — narrower output of `benchmark-invariants`:
9
+ * ad-hoc grading without a full lifecycle.
10
+ *
11
+ * Validation is throw-on-mismatch so the runner can wrap every JSONL append
12
+ * in a guard and reject schema drift at write time.
13
+ */
14
+
15
+ import { z } from "zod";
16
+
17
+ const VERDICT_ENUM = z.enum(["pass", "fail"]);
18
+
19
+ const INVARIANTS_SHAPE = z.object({
20
+ verdict: VERDICT_ENUM,
21
+ details: z.array(z.unknown()),
22
+ exitCode: z.number().int(),
23
+ stderr: z.string().optional(),
24
+ });
25
+
26
+ const JUDGE_VERDICT_SHAPE = z.object({
27
+ verdict: VERDICT_ENUM,
28
+ summary: z.string(),
29
+ });
30
+
31
+ /**
32
+ * Per-participant cost attribution. `costUsd` is the sum of these; the
33
+ * breakdown lets reports show where the spend went. The judge runs as its
34
+ * own SDK session, so its cost is tracked separately from agent/supervisor.
35
+ */
36
+ const COST_BREAKDOWN_SHAPE = z.object({
37
+ agent: z.number(),
38
+ supervisor: z.number(),
39
+ judge: z.number(),
40
+ });
41
+
42
+ const PROFILES_SHAPE = z.object({
43
+ agent: z.union([z.string(), z.null()]),
44
+ supervisor: z.union([z.string(), z.null()]),
45
+ judge: z.union([z.string(), z.null()]),
46
+ });
47
+
48
+ const PREFLIGHT_ERROR_SHAPE = z.object({
49
+ phase: z.string(),
50
+ message: z.string(),
51
+ exitCode: z.number().int(),
52
+ });
53
+
54
+ const COMMON_FIELDS = {
55
+ taskId: z.string().min(1),
56
+ runIndex: z.number().int().min(0),
57
+ verdict: VERDICT_ENUM,
58
+ costUsd: z.number(),
59
+ costBreakdown: COST_BREAKDOWN_SHAPE.optional(),
60
+ turns: z.number().int().min(0),
61
+ profiles: PROFILES_SHAPE,
62
+ model: z.object({
63
+ agent: z.string(),
64
+ supervisor: z.string().optional(),
65
+ judge: z.string().optional(),
66
+ }),
67
+ skillSetHash: z.string(),
68
+ familyRevision: z.string(),
69
+ durationMs: z.number().int().min(0),
70
+ };
71
+
72
+ const AGENT_ERROR_SHAPE = z.object({
73
+ message: z.string(),
74
+ aborted: z.boolean(),
75
+ });
76
+
77
+ const HAPPY_RECORD = z.object({
78
+ ...COMMON_FIELDS,
79
+ invariants: INVARIANTS_SHAPE,
80
+ submission: z.string(),
81
+ judgeVerdict: JUDGE_VERDICT_SHAPE.optional(),
82
+ agentTracePath: z.string(),
83
+ supervisorTracePath: z.string(),
84
+ judgeTracePath: z.string(),
85
+ agentError: AGENT_ERROR_SHAPE.optional(),
86
+ preflightError: z.undefined().optional(),
87
+ });
88
+
89
+ const PREFLIGHT_RECORD = z.object({
90
+ ...COMMON_FIELDS,
91
+ costUsd: z.literal(0),
92
+ preflightError: PREFLIGHT_ERROR_SHAPE,
93
+ // Trace paths are populated even on preflight failure (the runner allocates
94
+ // them in WorkdirManager.start) so the record is uniform across branches
95
+ // and downstream consumers can reference them without conditional fields.
96
+ agentTracePath: z.string(),
97
+ supervisorTracePath: z.string(),
98
+ judgeTracePath: z.string(),
99
+ invariants: z.undefined().optional(),
100
+ submission: z.undefined().optional(),
101
+ judgeVerdict: z.undefined().optional(),
102
+ agentError: z.undefined().optional(),
103
+ });
104
+
105
+ export const RESULT_RECORD_SCHEMA = z.union([HAPPY_RECORD, PREFLIGHT_RECORD]);
106
+
107
+ export const INVARIANTS_RECORD_SCHEMA = z.object({
108
+ taskId: z.string().min(1),
109
+ invariants: INVARIANTS_SHAPE,
110
+ exitCode: z.number().int(),
111
+ });
112
+
113
+ /**
114
+ * Throw on schema mismatch.
115
+ * @param {object} record
116
+ */
117
+ export function validateResultRecord(record) {
118
+ RESULT_RECORD_SCHEMA.parse(record);
119
+ }
120
+
121
+ /**
122
+ * Throw on schema mismatch.
123
+ * @param {object} record
124
+ */
125
+ export function validateInvariantsRecord(record) {
126
+ INVARIANTS_RECORD_SCHEMA.parse(record);
127
+ }