jev-layer 0.1.0 → 0.2.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 (83) hide show
  1. package/CHANGELOG.md +45 -34
  2. package/CONTRIBUTING.md +146 -146
  3. package/LICENSE +21 -21
  4. package/README.md +123 -126
  5. package/README.ru.md +138 -117
  6. package/README.zh-CN.md +137 -117
  7. package/RELEASE.md +53 -53
  8. package/SECURITY.md +56 -56
  9. package/bin/jev.mjs +213 -213
  10. package/config/codex.mcp.toml +8 -8
  11. package/config/generic-mcp.json +13 -13
  12. package/config/hermes.mcp.yaml +9 -9
  13. package/config/jev.example.json +22 -22
  14. package/config/omp.mcp.json +14 -14
  15. package/config/providers.env.example +13 -13
  16. package/docs/AGENT-IMPLEMENTATION.md +250 -0
  17. package/docs/COMPATIBILITY.md +15 -15
  18. package/docs/HERMES-LOCAL-AGENT-HANDOFF.ru.md +177 -0
  19. package/docs/PROVIDERS.md +67 -0
  20. package/docs/SCHEMA-VERSIONING.md +96 -94
  21. package/docs/architecture.svg +77 -0
  22. package/docs/jev-layer-banner.svg +38 -0
  23. package/examples/capabilities.json +39 -39
  24. package/examples/route-request.json +28 -28
  25. package/integrations/codex/.codex-plugin/plugin.json +19 -19
  26. package/integrations/codex/.mcp.json +11 -11
  27. package/integrations/codex/AGENTS.md +1 -1
  28. package/integrations/codex/run-mcp.mjs +9 -9
  29. package/integrations/codex/skills/jev-route/SKILL.md +17 -17
  30. package/integrations/hermes/__init__.py +150 -51
  31. package/integrations/hermes/plugin.yaml +10 -5
  32. package/integrations/hermes/schemas.py +89 -12
  33. package/integrations/omp/extension.js +105 -105
  34. package/integrations/template/README.md +10 -10
  35. package/integrations/template/adapter.mjs +87 -87
  36. package/package.json +60 -59
  37. package/scripts/benchmark.mjs +35 -35
  38. package/scripts/browser-benchmark.mjs +92 -92
  39. package/scripts/browser-e2e.mjs +117 -117
  40. package/scripts/capability-e2e.mjs +31 -31
  41. package/scripts/clean-install-smoke.mjs +162 -162
  42. package/scripts/codex-mcp-smoke.mjs +119 -119
  43. package/scripts/context-filter-e2e.mjs +45 -45
  44. package/scripts/fail-open-smoke.mjs +120 -120
  45. package/scripts/feature-flags-smoke.mjs +46 -46
  46. package/scripts/mcp-receipt-smoke.mjs +113 -98
  47. package/scripts/model-route-report.mjs +15 -0
  48. package/scripts/openrouter-choice.mjs +59 -59
  49. package/scripts/replay-eval.mjs +124 -124
  50. package/scripts/smoke.mjs +34 -34
  51. package/scripts/supervision-e2e.mjs +138 -109
  52. package/src/browser.mjs +571 -569
  53. package/src/cli.mjs +33 -33
  54. package/src/config.mjs +85 -75
  55. package/src/context-filter.mjs +56 -56
  56. package/src/contract.mjs +72 -72
  57. package/src/discovery.mjs +65 -65
  58. package/src/hermes-adapter.mjs +123 -0
  59. package/src/mcp-server.mjs +267 -210
  60. package/src/model-route-metrics.mjs +89 -0
  61. package/src/model-routing.mjs +87 -0
  62. package/src/providers/demo.mjs +52 -52
  63. package/src/providers/index.mjs +12 -0
  64. package/src/providers/typesafe.mjs +126 -126
  65. package/src/receipts.mjs +227 -226
  66. package/src/registry.mjs +109 -109
  67. package/src/relevance-filter.mjs +99 -99
  68. package/src/route.mjs +219 -221
  69. package/src/shadow-compaction.mjs +170 -0
  70. package/src/supervision.mjs +268 -244
  71. package/test/browser.test.mjs +199 -199
  72. package/test/capability.test.mjs +54 -54
  73. package/test/context-filter.test.mjs +65 -65
  74. package/test/hermes-adapter.test.mjs +62 -0
  75. package/test/model-route-metrics.test.mjs +61 -0
  76. package/test/model-routing.test.mjs +59 -0
  77. package/test/openrouter-provider.test.mjs +55 -55
  78. package/test/provider-transports.test.mjs +205 -0
  79. package/test/providers.test.mjs +126 -0
  80. package/test/receipts.test.mjs +71 -71
  81. package/test/route.test.mjs +74 -74
  82. package/test/shadow-compaction.test.mjs +67 -0
  83. package/test/supervision.test.mjs +117 -99
@@ -1,244 +1,268 @@
1
- import { randomUUID } from "node:crypto";
2
- import { stableJson } from "./contract.mjs";
3
- import { DemoProvider } from "./providers/demo.mjs";
4
- import { OpenRouterDecisionsProvider, TypeSafeProvider } from "./providers/typesafe.mjs";
5
- import { appendSupervisionReceipt } from "./receipts.mjs";
6
-
7
- export const SUPERVISION_ENV = "JEV_SUPERVISION";
8
- export const SUPERVISION_DIMENSIONS = Object.freeze([
9
- "requirements_addressed",
10
- "verification_needed",
11
- "meaningful_progress",
12
- "worker_stuck",
13
- "work_off_track",
14
- "completion",
15
- ]);
16
-
17
- const MAX_STATE_BYTES = 8_000;
18
-
19
- export function supervisionEnabled(options = {}) {
20
- if (options.enabled === true) return true;
21
- if (options.enabled === false) return false;
22
- return process.env[SUPERVISION_ENV] === "1";
23
- }
24
-
25
- export function buildSupervisionRequest({
26
- job = {},
27
- observation = {},
28
- evidence = {},
29
- harness = "unknown",
30
- actor_permissions = [],
31
- policy = {},
32
- } = {}) {
33
- return {
34
- schema_version: 1,
35
- harness,
36
- intent: "Assess supervised work against its requirements and verification evidence.",
37
- actor_permissions: Array.isArray(actor_permissions) ? actor_permissions.filter((value) => typeof value === "string") : [],
38
- policy: { ...policy },
39
- context: {
40
- job: bounded(job),
41
- observation: bounded(observation),
42
- evidence: bounded(evidence),
43
- supervision: {
44
- judgments: bounded(evidence?.judgments ?? {}),
45
- },
46
- },
47
- };
48
- }
49
-
50
- export function supervisionQuestions() {
51
- return Object.fromEntries(SUPERVISION_DIMENSIONS.map((dimension) => [dimension, {
52
- type: "noul",
53
- instructions: questionInstructions(dimension),
54
- criteria: {
55
- true: "The statement is supported by the supplied work state and evidence.",
56
- false: "The statement is not supported, is contradicted, or is unknown.",
57
- },
58
- }]));
59
- }
60
-
61
- export function normalizeAssessment(raw) {
62
- const answers = raw?.answers;
63
- if (!answers || typeof answers !== "object") throw new Error("supervision response has no answers object");
64
- const assessment = {};
65
- for (const dimension of SUPERVISION_DIMENSIONS) {
66
- const answer = answers[dimension];
67
- const probability = readProbability(answer);
68
- if (probability === null) throw new Error(`supervision response has no valid ${dimension} judgment`);
69
- assessment[dimension] = Number(probability.toFixed(4));
70
- }
71
- return assessment;
72
- }
73
-
74
- export function deterministicSupervisionPolicy({ assessment, evidence = {}, attempts = 0, policy = {} } = {}) {
75
- const values = assessment && typeof assessment === "object" ? assessment : {};
76
- const threshold = Number.isFinite(policy.threshold) ? Math.max(0, Math.min(1, policy.threshold)) : 0.7;
77
- const maxRetries = Number.isInteger(policy.max_retries) && policy.max_retries >= 0 ? policy.max_retries : 2;
78
- const verificationEvidence = evidence.verification_passed === true || evidence.tests_passed === true;
79
-
80
- if (value(values.worker_stuck) >= threshold) {
81
- return attempts < maxRetries
82
- ? { action: "retry", reason: "worker appears stuck and retry budget remains", policy_source: "deterministic_host_policy" }
83
- : { action: "escalate", reason: "worker appears stuck and retry budget is exhausted", policy_source: "deterministic_host_policy" };
84
- }
85
- if (value(values.work_off_track) >= threshold) {
86
- return attempts < maxRetries
87
- ? { action: "retry", reason: "work appears off track and retry budget remains", policy_source: "deterministic_host_policy" }
88
- : { action: "escalate", reason: "work appears off track and retry budget is exhausted", policy_source: "deterministic_host_policy" };
89
- }
90
- if (value(values.verification_needed) >= threshold || (value(values.completion) >= threshold && !verificationEvidence)) {
91
- return { action: "verify", reason: "verification is required before continuing or finishing", policy_source: "deterministic_host_policy" };
92
- }
93
- if (value(values.completion) >= threshold && value(values.requirements_addressed) >= threshold) {
94
- return { action: "finish", reason: "completion and requirement coverage are supported", policy_source: "deterministic_host_policy" };
95
- }
96
- return { action: "continue", reason: value(values.meaningful_progress) >= threshold ? "meaningful progress is supported" : "continue while evidence is incomplete", policy_source: "deterministic_host_policy" };
97
- }
98
-
99
- export async function superviseWork({
100
- job,
101
- observation,
102
- evidence,
103
- harness,
104
- actor_permissions,
105
- policy,
106
- provider = "demo",
107
- enabled,
108
- attempts = 0,
109
- receiptPath,
110
- } = {}) {
111
- const started = performance.now();
112
- const request = buildSupervisionRequest({ job, observation, evidence, harness, actor_permissions, policy });
113
- const base = {
114
- status: "fallback",
115
- action: "continue",
116
- reason: "supervision unavailable",
117
- assessment: null,
118
- policy: null,
119
- request,
120
- metrics: { wall_time_ms: 0, jev_calls: 0, cost_usd: 0, failures: 0 },
121
- receipt: null,
122
- };
123
-
124
- if (!supervisionEnabled({ enabled })) return finalize(base, started, "disabled", 0);
125
- let resolved;
126
- try {
127
- resolved = resolveProvider(provider);
128
- if (!resolved || typeof resolved.evaluate !== "function") throw new Error("provider does not support supervision evaluation");
129
- } catch (error) {
130
- return finalize(base, started, "provider_error", 1, error);
131
- }
132
-
133
- let raw;
134
- try {
135
- raw = await resolved.evaluate({ state: request, questions: supervisionQuestions() });
136
- } catch (error) {
137
- return finalize(base, started, "provider_error", 1, error);
138
- }
139
-
140
- let assessment;
141
- try {
142
- assessment = normalizeAssessment(raw);
143
- } catch (error) {
144
- return finalize({ ...base, raw_jev: raw }, started, "malformed_response", 1, error);
145
- }
146
-
147
- const selectedPolicy = deterministicSupervisionPolicy({ assessment, evidence, attempts, policy });
148
- const result = {
149
- status: "judged",
150
- action: selectedPolicy.action,
151
- reason: selectedPolicy.reason,
152
- assessment,
153
- policy: selectedPolicy,
154
- request,
155
- metrics: {
156
- wall_time_ms: Number((performance.now() - started).toFixed(3)),
157
- jev_calls: 1,
158
- cost_usd: finiteCost(raw?.usage?.cost),
159
- failures: 0,
160
- },
161
- receipt: {
162
- correlation_id: randomUUID(),
163
- provider: resolved.name ?? providerName(provider),
164
- latency_ms: Number((performance.now() - started).toFixed(3)),
165
- cost_usd: finiteCost(raw?.usage?.cost),
166
- dimensions: SUPERVISION_DIMENSIONS.length,
167
- },
168
- };
169
- if (receiptPath) {
170
- try {
171
- const appended = await appendSupervisionReceipt({ path: receiptPath, request, result });
172
- result.receipt_path = appended.path;
173
- } catch (error) {
174
- result.receipt_error = error instanceof Error ? error.message : String(error);
175
- }
176
- }
177
- return result;
178
- }
179
-
180
- function resolveProvider(provider) {
181
- if (provider && typeof provider === "object") return provider;
182
- if (provider === "demo") return new DemoProvider();
183
- if (provider === "openrouter") return new OpenRouterDecisionsProvider();
184
- if (provider === "typesafe") return new TypeSafeProvider();
185
- throw new Error(`unsupported provider: ${provider}`);
186
- }
187
-
188
- function finalize(result, started, reason, jevCalls, error = null) {
189
- const message = error instanceof Error ? error.message : error ? String(error) : reason;
190
- return {
191
- ...result,
192
- reason: message,
193
- metrics: {
194
- ...result.metrics,
195
- wall_time_ms: Number((performance.now() - started).toFixed(3)),
196
- jev_calls: jevCalls,
197
- failures: reason === "disabled" ? 0 : 1,
198
- },
199
- fallback: { type: reason, reason: message },
200
- };
201
- }
202
-
203
- function readProbability(answer) {
204
- if (typeof answer === "boolean") return answer ? 1 : 0;
205
- if (typeof answer === "number" && Number.isFinite(answer) && answer >= 0 && answer <= 1) return answer;
206
- if (!answer || typeof answer !== "object") return null;
207
- for (const key of ["probability", "p_true", "score", "value", "noul"]) {
208
- const value = answer[key];
209
- if (typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1) return value;
210
- if (typeof value === "boolean") return value ? 1 : 0;
211
- }
212
- return null;
213
- }
214
-
215
- function questionInstructions(dimension) {
216
- const labels = {
217
- requirements_addressed: "The worker has addressed the stated requirements.",
218
- verification_needed: "Additional verification is needed before trusting the current work.",
219
- meaningful_progress: "The worker has made meaningful progress toward the goal.",
220
- worker_stuck: "The worker is stuck and is not making useful progress.",
221
- work_off_track: "The worker's current work is materially off track.",
222
- completion: "The work is complete for the stated requirements.",
223
- };
224
- return `Judge whether this statement is supported: ${labels[dimension]}`;
225
- }
226
-
227
- function bounded(value) {
228
- const encoded = stableJson(value ?? {});
229
- if (Buffer.byteLength(encoded, "utf8") <= MAX_STATE_BYTES) return value ?? {};
230
- return { truncated: true, preview: encoded.slice(0, MAX_STATE_BYTES) };
231
- }
232
-
233
- function value(assessment, key) {
234
- const candidate = key === undefined ? assessment : assessment?.[key];
235
- return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : 0;
236
- }
237
-
238
- function finiteCost(value) {
239
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
240
- }
241
-
242
- function providerName(provider) {
243
- return typeof provider === "string" ? provider : "unknown";
244
- }
1
+ import { randomUUID } from "node:crypto";
2
+ import { stableJson } from "./contract.mjs";
3
+ import { resolveProvider } from "./providers/index.mjs";
4
+ import { appendSupervisionReceipt } from "./receipts.mjs";
5
+
6
+ export const SUPERVISION_ENV = "JEV_SUPERVISION";
7
+ export const SUPERVISION_DIMENSIONS = Object.freeze([
8
+ "requirements_addressed",
9
+ "verification_needed",
10
+ "meaningful_progress",
11
+ "worker_stuck",
12
+ "work_off_track",
13
+ "completion",
14
+ ]);
15
+
16
+ const MAX_STATE_BYTES = 8_000;
17
+
18
+ export function supervisionEnabled(options = {}) {
19
+ if (options.enabled === true) return true;
20
+ if (options.enabled === false) return false;
21
+ return process.env[SUPERVISION_ENV] === "1";
22
+ }
23
+
24
+ export function buildSupervisionRequest({
25
+ job = {},
26
+ observation = {},
27
+ evidence = {},
28
+ harness = "unknown",
29
+ actor_permissions = [],
30
+ policy = {},
31
+ } = {}) {
32
+ return {
33
+ schema_version: 1,
34
+ harness,
35
+ intent: "Assess supervised work against its requirements and verification evidence.",
36
+ actor_permissions: Array.isArray(actor_permissions) ? actor_permissions.filter((value) => typeof value === "string") : [],
37
+ policy: { ...policy },
38
+ context: {
39
+ job: bounded(job),
40
+ observation: bounded(observation),
41
+ evidence: bounded(evidence),
42
+ supervision: {
43
+ judgments: bounded(evidence?.judgments ?? {}),
44
+ evidence_state: deterministicEvidenceState(evidence),
45
+ },
46
+ },
47
+ };
48
+ }
49
+
50
+ export function supervisionQuestions() {
51
+ return Object.fromEntries(SUPERVISION_DIMENSIONS.map((dimension) => [dimension, {
52
+ type: "noul",
53
+ instructions: questionInstructions(dimension),
54
+ criteria: {
55
+ true: "The statement is supported by the supplied work state and evidence.",
56
+ false: "The statement is not supported, is contradicted, or is unknown.",
57
+ },
58
+ }]));
59
+ }
60
+
61
+ export function normalizeAssessment(raw) {
62
+ const answers = raw?.answers;
63
+ if (!answers || typeof answers !== "object") throw new Error("supervision response has no answers object");
64
+ const assessment = {};
65
+ for (const dimension of SUPERVISION_DIMENSIONS) {
66
+ const answer = answers[dimension];
67
+ const probability = readProbability(answer);
68
+ if (probability === null) throw new Error(`supervision response has no valid ${dimension} judgment`);
69
+ assessment[dimension] = Number(probability.toFixed(4));
70
+ }
71
+ return assessment;
72
+ }
73
+
74
+ export function deterministicEvidenceState(evidence = {}) {
75
+ const sources = [];
76
+ const positive = evidence?.verification_passed === true || evidence?.tests_passed === true;
77
+ const negative = evidence?.verification_failed === true || evidence?.tests_failed === true;
78
+ if (evidence?.verification_passed === true) sources.push("verification_passed");
79
+ if (evidence?.tests_passed === true) sources.push("tests_passed");
80
+ if (evidence?.verification_failed === true) sources.push("verification_failed");
81
+ if (evidence?.tests_failed === true) sources.push("tests_failed");
82
+ if (Array.isArray(evidence?.receipts)) {
83
+ for (const receipt of evidence.receipts) {
84
+ if (!receipt || typeof receipt !== "object") continue;
85
+ const id = typeof receipt.id === "string" && receipt.id ? receipt.id : null;
86
+ if (receipt.status === "completed") {
87
+ sources.push(id ? `receipt:${id}` : "receipt:completed");
88
+ } else if (receipt.status === "failed") {
89
+ sources.push(id ? `receipt_failed:${id}` : "receipt:failed");
90
+ }
91
+ }
92
+ }
93
+ const hasPositiveReceipt = sources.some((source) => source === "receipt:completed" || source.startsWith("receipt:"));
94
+ const hasNegativeReceipt = sources.some((source) => source === "receipt:failed" || source.startsWith("receipt_failed:"));
95
+ if ((positive || hasPositiveReceipt) && (negative || hasNegativeReceipt)) return { state: "contradictory", sources };
96
+ if (negative || hasNegativeReceipt) return { state: "contradictory", sources };
97
+ return { state: positive || hasPositiveReceipt ? "present" : "missing", sources };
98
+ }
99
+
100
+ export function deterministicSupervisionPolicy({ assessment, evidence = {}, attempts = 0, policy = {} } = {}) {
101
+ const values = assessment && typeof assessment === "object" ? assessment : {};
102
+ const threshold = Number.isFinite(policy.threshold) ? Math.max(0, Math.min(1, policy.threshold)) : 0.7;
103
+ const maxRetries = Number.isInteger(policy.max_retries) && policy.max_retries >= 0 ? policy.max_retries : 2;
104
+ const evidenceState = deterministicEvidenceState(evidence);
105
+ const verificationEvidence = evidenceState.state === "present";
106
+
107
+ if (evidenceState.state === "contradictory") {
108
+ return { action: "verify", reason: "verification evidence is contradictory", policy_source: "deterministic_host_policy", evidence_state: evidenceState };
109
+ }
110
+ if (value(values.worker_stuck) >= threshold) {
111
+ return attempts < maxRetries
112
+ ? { action: "retry", reason: "worker appears stuck and retry budget remains", policy_source: "deterministic_host_policy" }
113
+ : { action: "escalate", reason: "worker appears stuck and retry budget is exhausted", policy_source: "deterministic_host_policy" };
114
+ }
115
+ if (value(values.work_off_track) >= threshold) {
116
+ return attempts < maxRetries
117
+ ? { action: "retry", reason: "work appears off track and retry budget remains", policy_source: "deterministic_host_policy" }
118
+ : { action: "escalate", reason: "work appears off track and retry budget is exhausted", policy_source: "deterministic_host_policy" };
119
+ }
120
+ if (value(values.verification_needed) >= threshold || (value(values.completion) >= threshold && !verificationEvidence)) {
121
+ return { action: "verify", reason: "verification is required before continuing or finishing", policy_source: "deterministic_host_policy" };
122
+ }
123
+ if (value(values.completion) >= threshold && value(values.requirements_addressed) >= threshold) {
124
+ return { action: "finish", reason: "completion and requirement coverage are supported", policy_source: "deterministic_host_policy" };
125
+ }
126
+ return { action: "continue", reason: value(values.meaningful_progress) >= threshold ? "meaningful progress is supported" : "continue while evidence is incomplete", policy_source: "deterministic_host_policy" };
127
+ }
128
+
129
+ export async function superviseWork({
130
+ job,
131
+ observation,
132
+ evidence,
133
+ harness,
134
+ actor_permissions,
135
+ policy,
136
+ provider = "demo",
137
+ config,
138
+ enabled,
139
+ attempts = 0,
140
+ receiptPath,
141
+ } = {}) {
142
+ const started = performance.now();
143
+ const request = buildSupervisionRequest({ job, observation, evidence, harness, actor_permissions, policy });
144
+ const base = {
145
+ status: "fallback",
146
+ action: "continue",
147
+ reason: "supervision unavailable",
148
+ assessment: null,
149
+ policy: null,
150
+ request,
151
+ metrics: { wall_time_ms: 0, jev_calls: 0, cost_usd: 0, failures: 0 },
152
+ receipt: null,
153
+ };
154
+
155
+ if (!supervisionEnabled({ enabled })) return finalize(base, started, "disabled", 0);
156
+ let resolved;
157
+ try {
158
+ resolved = resolveProvider(provider, { config });
159
+ if (!resolved || typeof resolved.evaluate !== "function") throw new Error("provider does not support supervision evaluation");
160
+ } catch (error) {
161
+ return finalize(base, started, "provider_error", 1, error);
162
+ }
163
+
164
+ let raw;
165
+ try {
166
+ raw = await resolved.evaluate({ state: request, questions: supervisionQuestions() });
167
+ } catch (error) {
168
+ return finalize(base, started, "provider_error", 1, error);
169
+ }
170
+
171
+ let assessment;
172
+ try {
173
+ assessment = normalizeAssessment(raw);
174
+ } catch (error) {
175
+ return finalize({ ...base, raw_jev: raw }, started, "malformed_response", 1, error);
176
+ }
177
+
178
+ const selectedPolicy = deterministicSupervisionPolicy({ assessment, evidence, attempts, policy });
179
+ const result = {
180
+ status: "judged",
181
+ action: selectedPolicy.action,
182
+ reason: selectedPolicy.reason,
183
+ assessment,
184
+ evidence_state: deterministicEvidenceState(evidence),
185
+ policy: selectedPolicy,
186
+ request,
187
+ metrics: {
188
+ wall_time_ms: Number((performance.now() - started).toFixed(3)),
189
+ jev_calls: 1,
190
+ cost_usd: finiteCost(raw?.usage?.cost),
191
+ failures: 0,
192
+ },
193
+ receipt: {
194
+ correlation_id: randomUUID(),
195
+ provider: resolved.name ?? providerName(provider),
196
+ latency_ms: Number((performance.now() - started).toFixed(3)),
197
+ cost_usd: finiteCost(raw?.usage?.cost),
198
+ dimensions: SUPERVISION_DIMENSIONS.length,
199
+ },
200
+ };
201
+ if (receiptPath) {
202
+ try {
203
+ const appended = await appendSupervisionReceipt({ path: receiptPath, request, result });
204
+ result.receipt_path = appended.path;
205
+ } catch (error) {
206
+ result.receipt_error = error instanceof Error ? error.message : String(error);
207
+ }
208
+ }
209
+ return result;
210
+ }
211
+
212
+ function finalize(result, started, reason, jevCalls, error = null) {
213
+ const message = error instanceof Error ? error.message : error ? String(error) : reason;
214
+ return {
215
+ ...result,
216
+ reason: message,
217
+ metrics: {
218
+ ...result.metrics,
219
+ wall_time_ms: Number((performance.now() - started).toFixed(3)),
220
+ jev_calls: jevCalls,
221
+ failures: reason === "disabled" ? 0 : 1,
222
+ },
223
+ fallback: { type: reason, reason: message },
224
+ };
225
+ }
226
+
227
+ function readProbability(answer) {
228
+ if (typeof answer === "boolean") return answer ? 1 : 0;
229
+ if (typeof answer === "number" && Number.isFinite(answer) && answer >= 0 && answer <= 1) return answer;
230
+ if (!answer || typeof answer !== "object") return null;
231
+ for (const key of ["probability", "p_true", "score", "value", "noul"]) {
232
+ const value = answer[key];
233
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1) return value;
234
+ if (typeof value === "boolean") return value ? 1 : 0;
235
+ }
236
+ return null;
237
+ }
238
+
239
+ function questionInstructions(dimension) {
240
+ const labels = {
241
+ requirements_addressed: "The worker has addressed the stated requirements.",
242
+ verification_needed: "Additional verification is needed before trusting the current work.",
243
+ meaningful_progress: "The worker has made meaningful progress toward the goal.",
244
+ worker_stuck: "The worker is stuck and is not making useful progress.",
245
+ work_off_track: "The worker's current work is materially off track.",
246
+ completion: "The work is complete for the stated requirements.",
247
+ };
248
+ return `Judge whether this statement is supported: ${labels[dimension]}`;
249
+ }
250
+
251
+ function bounded(value) {
252
+ const encoded = stableJson(value ?? {});
253
+ if (Buffer.byteLength(encoded, "utf8") <= MAX_STATE_BYTES) return value ?? {};
254
+ return { truncated: true, preview: encoded.slice(0, MAX_STATE_BYTES) };
255
+ }
256
+
257
+ function value(assessment, key) {
258
+ const candidate = key === undefined ? assessment : assessment?.[key];
259
+ return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : 0;
260
+ }
261
+
262
+ function finiteCost(value) {
263
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
264
+ }
265
+
266
+ function providerName(provider) {
267
+ return typeof provider === "string" ? provider : "unknown";
268
+ }