agent-nuvira 3.3.3 → 3.3.4
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.
- package/README.md +13 -5
- package/dist/agent-sdk/src/agent.d.ts +2 -0
- package/dist/agent-sdk/src/agent.d.ts.map +1 -1
- package/dist/agent-sdk/src/define.d.ts +64 -0
- package/dist/agent-sdk/src/define.d.ts.map +1 -0
- package/dist/agent-sdk/src/define.js +76 -0
- package/dist/agent-sdk/src/define.js.map +1 -0
- package/dist/agent-sdk/src/index.d.ts +9 -0
- package/dist/agent-sdk/src/index.d.ts.map +1 -1
- package/dist/agent-sdk/src/index.js +9 -0
- package/dist/agent-sdk/src/index.js.map +1 -1
- package/dist/agent-sdk/src/scaffold.d.ts +11 -0
- package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
- package/dist/agent-sdk/src/scaffold.js +16 -6
- package/dist/agent-sdk/src/scaffold.js.map +1 -1
- package/dist/agents/long-form-plan.d.ts.map +1 -1
- package/dist/agents/long-form-plan.js +2 -1
- package/dist/agents/long-form-plan.js.map +1 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +5 -4
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/agent.d.ts +2 -2
- package/dist/cli/agent.js +10 -10
- package/dist/cli/chat.d.ts +94 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +354 -20
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +5 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +9 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +3 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/edit.js +2 -2
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -1
- package/dist/cli/eval.js +105 -2
- package/dist/cli/eval.js.map +1 -1
- package/dist/cli/execute.d.ts +16 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +192 -22
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/loop-executor.d.ts +55 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +212 -13
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +9 -8
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/models.d.ts +1 -1
- package/dist/cli/models.js +4 -4
- package/dist/cli/parity.d.ts +85 -0
- package/dist/cli/parity.d.ts.map +1 -0
- package/dist/cli/parity.js +506 -0
- package/dist/cli/parity.js.map +1 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +2 -1
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/retrieval.d.ts.map +1 -1
- package/dist/cli/retrieval.js +5 -4
- package/dist/cli/retrieval.js.map +1 -1
- package/dist/cli/sdk.js +4 -4
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli/trace.d.ts.map +1 -1
- package/dist/cli/trace.js +2 -1
- package/dist/cli/trace.js.map +1 -1
- package/dist/cli/workflow.js +2 -2
- package/dist/cli/workflow.js.map +1 -1
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/findings/verdicts.d.ts +241 -0
- package/dist/findings/verdicts.d.ts.map +1 -0
- package/dist/findings/verdicts.js +284 -0
- package/dist/findings/verdicts.js.map +1 -0
- package/dist/gateway/adapters.d.ts +65 -0
- package/dist/gateway/adapters.d.ts.map +1 -1
- package/dist/gateway/adapters.js +216 -10
- package/dist/gateway/adapters.js.map +1 -1
- package/dist/gateway/channel-directory.d.ts +31 -0
- package/dist/gateway/channel-directory.d.ts.map +1 -1
- package/dist/gateway/channel-directory.js +40 -0
- package/dist/gateway/channel-directory.js.map +1 -1
- package/dist/gateway/gateway-log.d.ts +1 -1
- package/dist/gateway/gateway-log.d.ts.map +1 -1
- package/dist/gateway/gateway-log.js.map +1 -1
- package/dist/gateway/hooks.d.ts +87 -19
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +62 -23
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/gateway/inbound-media.d.ts +147 -0
- package/dist/gateway/inbound-media.d.ts.map +1 -0
- package/dist/gateway/inbound-media.js +317 -0
- package/dist/gateway/inbound-media.js.map +1 -0
- package/dist/gateway/inbox.d.ts +8 -1
- package/dist/gateway/inbox.d.ts.map +1 -1
- package/dist/gateway/inbox.js.map +1 -1
- package/dist/gateway/platform-config.d.ts +14 -0
- package/dist/gateway/platform-config.d.ts.map +1 -1
- package/dist/gateway/platform-config.js +26 -8
- package/dist/gateway/platform-config.js.map +1 -1
- package/dist/gateway/realtime.d.ts +114 -0
- package/dist/gateway/realtime.d.ts.map +1 -0
- package/dist/gateway/realtime.js +402 -0
- package/dist/gateway/realtime.js.map +1 -0
- package/dist/gateway/registry.d.ts +31 -0
- package/dist/gateway/registry.d.ts.map +1 -1
- package/dist/gateway/registry.js +224 -4
- package/dist/gateway/registry.js.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
- package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
- package/dist/gateway/whatsapp/bridge.d.ts +6 -2
- package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/bridge.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/factory.d.ts +14 -0
- package/dist/inference/factory.d.ts.map +1 -1
- package/dist/inference/factory.js +17 -0
- package/dist/inference/factory.js.map +1 -1
- package/dist/inference/groq-adapter.d.ts +2 -0
- package/dist/inference/groq-adapter.d.ts.map +1 -1
- package/dist/inference/groq-adapter.js +16 -6
- package/dist/inference/groq-adapter.js.map +1 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +29 -0
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/benchmark.d.ts.map +1 -1
- package/dist/learning/benchmark.js +3 -2
- package/dist/learning/benchmark.js.map +1 -1
- package/dist/learning/continuation.d.ts.map +1 -1
- package/dist/learning/continuation.js +2 -1
- package/dist/learning/continuation.js.map +1 -1
- package/dist/learning/cost-tracker.d.ts.map +1 -1
- package/dist/learning/cost-tracker.js +2 -1
- package/dist/learning/cost-tracker.js.map +1 -1
- package/dist/learning/deferred-task.d.ts.map +1 -1
- package/dist/learning/deferred-task.js +13 -4
- package/dist/learning/deferred-task.js.map +1 -1
- package/dist/learning/eval-framework.d.ts.map +1 -1
- package/dist/learning/eval-framework.js +2 -1
- package/dist/learning/eval-framework.js.map +1 -1
- package/dist/learning/long-form.d.ts.map +1 -1
- package/dist/learning/long-form.js +2 -1
- package/dist/learning/long-form.js.map +1 -1
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +2 -1
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/reasoning-cache.d.ts.map +1 -1
- package/dist/learning/reasoning-cache.js +2 -1
- package/dist/learning/reasoning-cache.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +37 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +66 -0
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +2 -1
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/retrieval.d.ts.map +1 -1
- package/dist/learning/retrieval.js +2 -1
- package/dist/learning/retrieval.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +160 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -0
- package/dist/learning/seeded-benchmark.js +321 -0
- package/dist/learning/seeded-benchmark.js.map +1 -0
- package/dist/learning/seeded-bugs.d.ts +142 -0
- package/dist/learning/seeded-bugs.d.ts.map +1 -0
- package/dist/learning/seeded-bugs.js +535 -0
- package/dist/learning/seeded-bugs.js.map +1 -0
- package/dist/learning/step-checkpoint.d.ts +127 -0
- package/dist/learning/step-checkpoint.d.ts.map +1 -0
- package/dist/learning/step-checkpoint.js +244 -0
- package/dist/learning/step-checkpoint.js.map +1 -0
- package/dist/nlu/intent-confirm.d.ts +23 -1
- package/dist/nlu/intent-confirm.d.ts.map +1 -1
- package/dist/nlu/intent-confirm.js +85 -2
- package/dist/nlu/intent-confirm.js.map +1 -1
- package/dist/nlu/learnings.d.ts +7 -0
- package/dist/nlu/learnings.d.ts.map +1 -1
- package/dist/nlu/learnings.js +7 -0
- package/dist/nlu/learnings.js.map +1 -1
- package/dist/observability/debug-log.d.ts +250 -0
- package/dist/observability/debug-log.d.ts.map +1 -0
- package/dist/observability/debug-log.js +500 -0
- package/dist/observability/debug-log.js.map +1 -0
- package/dist/observability/event-bus.d.ts.map +1 -1
- package/dist/observability/event-bus.js +4 -1
- package/dist/observability/event-bus.js.map +1 -1
- package/dist/observability/otel.d.ts +278 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +590 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/parity/drivers.d.ts +99 -0
- package/dist/parity/drivers.d.ts.map +1 -0
- package/dist/parity/drivers.js +1362 -0
- package/dist/parity/drivers.js.map +1 -0
- package/dist/parity/graph.d.ts +73 -0
- package/dist/parity/graph.d.ts.map +1 -0
- package/dist/parity/graph.js +162 -0
- package/dist/parity/graph.js.map +1 -0
- package/dist/parity/matrix.d.ts +105 -0
- package/dist/parity/matrix.d.ts.map +1 -0
- package/dist/parity/matrix.js +352 -0
- package/dist/parity/matrix.js.map +1 -0
- package/dist/parity/observation.d.ts +444 -0
- package/dist/parity/observation.d.ts.map +1 -0
- package/dist/parity/observation.js +333 -0
- package/dist/parity/observation.js.map +1 -0
- package/dist/parity/scenarios.d.ts +229 -0
- package/dist/parity/scenarios.d.ts.map +1 -0
- package/dist/parity/scenarios.js +175 -0
- package/dist/parity/scenarios.js.map +1 -0
- package/dist/parity/surfaces.d.ts +122 -0
- package/dist/parity/surfaces.d.ts.map +1 -0
- package/dist/parity/surfaces.js +190 -0
- package/dist/parity/surfaces.js.map +1 -0
- package/dist/runtime/fault-injection.d.ts +173 -0
- package/dist/runtime/fault-injection.d.ts.map +1 -0
- package/dist/runtime/fault-injection.js +281 -0
- package/dist/runtime/fault-injection.js.map +1 -0
- package/dist/tools/child-agent-entry.d.ts +23 -0
- package/dist/tools/child-agent-entry.d.ts.map +1 -0
- package/dist/tools/child-agent-entry.js +129 -0
- package/dist/tools/child-agent-entry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts +124 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -0
- package/dist/tools/child-agent-runtime.js +704 -0
- package/dist/tools/child-agent-runtime.js.map +1 -0
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +82 -10
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/delegation-system.d.ts +31 -0
- package/dist/tools/delegation-system.d.ts.map +1 -1
- package/dist/tools/delegation-system.js +70 -9
- package/dist/tools/delegation-system.js.map +1 -1
- package/dist/tools/extract/docx.d.ts +27 -0
- package/dist/tools/extract/docx.d.ts.map +1 -0
- package/dist/tools/extract/docx.js +48 -0
- package/dist/tools/extract/docx.js.map +1 -0
- package/dist/tools/extract/html-text.d.ts +27 -0
- package/dist/tools/extract/html-text.d.ts.map +1 -0
- package/dist/tools/extract/html-text.js +86 -0
- package/dist/tools/extract/html-text.js.map +1 -0
- package/dist/tools/extract/pdf-ocr.d.ts +58 -0
- package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
- package/dist/tools/extract/pdf-ocr.js +116 -0
- package/dist/tools/extract/pdf-ocr.js.map +1 -0
- package/dist/tools/extract/pdf.d.ts +65 -0
- package/dist/tools/extract/pdf.d.ts.map +1 -0
- package/dist/tools/extract/pdf.js +197 -0
- package/dist/tools/extract/pdf.js.map +1 -0
- package/dist/tools/extract/pptx.d.ts +32 -0
- package/dist/tools/extract/pptx.d.ts.map +1 -0
- package/dist/tools/extract/pptx.js +77 -0
- package/dist/tools/extract/pptx.js.map +1 -0
- package/dist/tools/extract/xlsx.d.ts +47 -0
- package/dist/tools/extract/xlsx.d.ts.map +1 -0
- package/dist/tools/extract/xlsx.js +111 -0
- package/dist/tools/extract/xlsx.js.map +1 -0
- package/dist/tools/finding-tool.d.ts +76 -0
- package/dist/tools/finding-tool.d.ts.map +1 -0
- package/dist/tools/finding-tool.js +125 -0
- package/dist/tools/finding-tool.js.map +1 -0
- package/dist/tools/messaging-tools.d.ts +41 -11
- package/dist/tools/messaging-tools.d.ts.map +1 -1
- package/dist/tools/messaging-tools.js +104 -55
- package/dist/tools/messaging-tools.js.map +1 -1
- package/dist/tools/neutts-synth.d.ts +27 -3
- package/dist/tools/neutts-synth.d.ts.map +1 -1
- package/dist/tools/neutts-synth.js +57 -13
- package/dist/tools/neutts-synth.js.map +1 -1
- package/dist/tools/pipeline-tool.d.ts +43 -1
- package/dist/tools/pipeline-tool.d.ts.map +1 -1
- package/dist/tools/pipeline-tool.js +13 -2
- package/dist/tools/pipeline-tool.js.map +1 -1
- package/dist/tools/read-extract.d.ts +116 -45
- package/dist/tools/read-extract.d.ts.map +1 -1
- package/dist/tools/read-extract.js +494 -158
- package/dist/tools/read-extract.js.map +1 -1
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +152 -23
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/subagent-refusal.d.ts +15 -0
- package/dist/tools/subagent-refusal.d.ts.map +1 -0
- package/dist/tools/subagent-refusal.js +18 -0
- package/dist/tools/subagent-refusal.js.map +1 -0
- package/dist/tools/subagent-spawner.d.ts +122 -0
- package/dist/tools/subagent-spawner.d.ts.map +1 -1
- package/dist/tools/subagent-spawner.js +249 -28
- package/dist/tools/subagent-spawner.js.map +1 -1
- package/dist/tools/tool-hooks.d.ts +177 -0
- package/dist/tools/tool-hooks.d.ts.map +1 -0
- package/dist/tools/tool-hooks.js +427 -0
- package/dist/tools/tool-hooks.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +82 -0
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +167 -9
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/tool-refusal.d.ts +68 -0
- package/dist/tools/tool-refusal.d.ts.map +1 -0
- package/dist/tools/tool-refusal.js +78 -0
- package/dist/tools/tool-refusal.js.map +1 -0
- package/dist/tools/toolsets.d.ts +8 -0
- package/dist/tools/toolsets.d.ts.map +1 -1
- package/dist/tools/toolsets.js +12 -2
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/vision-tools.d.ts +88 -83
- package/dist/tools/vision-tools.d.ts.map +1 -1
- package/dist/tools/vision-tools.js +134 -103
- package/dist/tools/vision-tools.js.map +1 -1
- package/dist/tools/worktree.d.ts +210 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +374 -0
- package/dist/tools/worktree.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +32 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/web-dashboard/attachment-extract.d.ts +64 -0
- package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
- package/dist/web-dashboard/attachment-extract.js +154 -0
- package/dist/web-dashboard/attachment-extract.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +108 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +36 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/hub-data.d.ts +37 -0
- package/dist/web-dashboard/hub-data.d.ts.map +1 -1
- package/dist/web-dashboard/hub-data.js +61 -1
- package/dist/web-dashboard/hub-data.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +14 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +247 -13
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +196 -48
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/package.json +18 -3
- package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/dist/tools/child-agent-worker.js +0 -212
- package/src/web-dashboard/public/assets/index-CxDj7p6i.js +0 -207
- package/src/web-dashboard/public/assets/index-CxDj7p6i.js.map +0 -1
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WS7 (#29) — the seeded-bug benchmark.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS IS TEST INFRASTRUCTURE AND NOT A MATRIX ROW. `src/parity/matrix.ts`
|
|
5
|
+
* says it in one line: the seeded-bug benchmark is not a capability a surface can
|
|
6
|
+
* have, so it has no cells and no parity verdict of its own. What it has is a job —
|
|
7
|
+
* measure whether the agent can FIND and FIX a defect it was not told about, which
|
|
8
|
+
* is the thing a coding agent is for and the thing the M2b suite could only
|
|
9
|
+
* approximate: M2b tasks are written by hand and graded by hidden tests, but
|
|
10
|
+
* nothing proves the task was BROKEN before the agent ran, so a task that already
|
|
11
|
+
* passed measured nothing.
|
|
12
|
+
*
|
|
13
|
+
* THE PROPERTY THAT MAKES THIS A BENCHMARK RATHER THAN A TASK LIST. Every seeded
|
|
14
|
+
* bug is declared TWICE — the broken workspace the agent receives, and the same
|
|
15
|
+
* workspace after a reference fix — and `verifySeededBug` runs the checks against
|
|
16
|
+
* both. The checks must FAIL on the seed (and say so in their own words) and PASS
|
|
17
|
+
* after the fix. A seed that already passes its checks, or a check that cannot
|
|
18
|
+
* pass even when fixed, fails verification and is NOT scored: `runSeededSuite`
|
|
19
|
+
* verifies every task before it runs a single model call. `nuvira eval
|
|
20
|
+
* verify-seeds` exposes the same verification directly, so the ratchet is
|
|
21
|
+
* runnable from a terminal and in CI without a provider.
|
|
22
|
+
*
|
|
23
|
+
* WHAT 'FAILING' HAS TO MEAN. A check that exits non-zero because it crashed —
|
|
24
|
+
* a syntax error, a missing module — would satisfy a naive verification while
|
|
25
|
+
* proving nothing about the bug. So a seed counts as genuinely broken only when
|
|
26
|
+
* its check exits non-zero AND prints the failure marker its own assertions
|
|
27
|
+
* print (`FAIL`). Combined with "the same check passes once the fix is applied",
|
|
28
|
+
* that pins both ends: the check is well-formed, and it is the DEFECT that makes
|
|
29
|
+
* it fail.
|
|
30
|
+
*
|
|
31
|
+
* PLAIN NODE, ON PURPOSE. Every seed is a CommonJS `.js` file with a `.js` test
|
|
32
|
+
* script and no dependencies, so verification is deterministic, offline, and
|
|
33
|
+
* needs nothing but the `node` already running the suite. (A future Python seed
|
|
34
|
+
* would have to be gated on an interpreter actually being present rather than
|
|
35
|
+
* assumed — the honest version of "we also test Python".)
|
|
36
|
+
*
|
|
37
|
+
* Deliberately NOT measured here: collateral damage to files the fix should not
|
|
38
|
+
* touch is scored from a diff of the workspace against the seed
|
|
39
|
+
* (`src/learning/seeded-benchmark.ts`), not from reference patterns, because
|
|
40
|
+
* "this file still contains line X" is a weaker claim than "this file is
|
|
41
|
+
* unchanged" and the benchmark should not make the weak one.
|
|
42
|
+
*/
|
|
43
|
+
import { execSync } from 'node:child_process';
|
|
44
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
45
|
+
import { tmpdir } from 'node:os';
|
|
46
|
+
import { join } from 'node:path';
|
|
47
|
+
/** The exact request every seeded task makes — uniform, so the score compares competence. */
|
|
48
|
+
export function seededGoal(bug) {
|
|
49
|
+
const commands = bug.checks.map((c) => `\`${c.command}\``).join(' and ');
|
|
50
|
+
return (`${commands} fails in this project. Diagnose the defect in the source and fix it so the ` +
|
|
51
|
+
`check passes. Do not modify the check file, and do not change any file that is not ` +
|
|
52
|
+
`responsible for the failure.`);
|
|
53
|
+
}
|
|
54
|
+
const RANGE_TEST = `const assert = require('node:assert');
|
|
55
|
+
const { range } = require('../src/range.js');
|
|
56
|
+
try {
|
|
57
|
+
assert.deepStrictEqual(range(3), [0, 1, 2]);
|
|
58
|
+
assert.deepStrictEqual(range(0), []);
|
|
59
|
+
console.log('ok');
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error('FAIL: ' + err.message);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
const TOP_SCORES_TEST = `const assert = require('node:assert');
|
|
66
|
+
const { topScores } = require('../src/top-scores.js');
|
|
67
|
+
try {
|
|
68
|
+
assert.deepStrictEqual(topScores([10, 9, 100], 2), [100, 10]);
|
|
69
|
+
assert.deepStrictEqual(topScores([5, 5, 1], 2), [5, 5]);
|
|
70
|
+
console.log('ok');
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.error('FAIL: ' + err.message);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
const SUM_ASYNC_TEST = `const assert = require('node:assert');
|
|
77
|
+
const { sumAsync } = require('../src/sum-async.js');
|
|
78
|
+
(async () => {
|
|
79
|
+
try {
|
|
80
|
+
assert.strictEqual(await sumAsync([1, 2, 3]), 6);
|
|
81
|
+
assert.strictEqual(await sumAsync([]), 0);
|
|
82
|
+
console.log('ok');
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error('FAIL: ' + err.message);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
})();
|
|
88
|
+
`;
|
|
89
|
+
const FORMAT_AMOUNT_TEST = `const assert = require('node:assert');
|
|
90
|
+
const { formatAmount } = require('../src/format-amount.js');
|
|
91
|
+
try {
|
|
92
|
+
assert.strictEqual(formatAmount(12.5), '$12.50');
|
|
93
|
+
assert.strictEqual(formatAmount(0), '$0.00');
|
|
94
|
+
assert.strictEqual(formatAmount(null), '—');
|
|
95
|
+
console.log('ok');
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.error('FAIL: ' + err.message);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
const CLONE_CONFIG_TEST = `const assert = require('node:assert');
|
|
102
|
+
const { cloneConfig } = require('../src/clone-config.js');
|
|
103
|
+
try {
|
|
104
|
+
const original = { name: 'svc', limits: { max: 10 } };
|
|
105
|
+
const copy = cloneConfig(original);
|
|
106
|
+
copy.limits.max = 99;
|
|
107
|
+
assert.strictEqual(original.limits.max, 10, 'the original object was mutated through the copy');
|
|
108
|
+
assert.strictEqual(copy.name, 'svc');
|
|
109
|
+
console.log('ok');
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error('FAIL: ' + err.message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
const ADD_TAG_TEST = `const assert = require('node:assert');
|
|
116
|
+
const { addTag } = require('../src/add-tag.js');
|
|
117
|
+
try {
|
|
118
|
+
const tags = ['a'];
|
|
119
|
+
const next = addTag(tags, 'b');
|
|
120
|
+
assert.deepStrictEqual(next, ['a', 'b']);
|
|
121
|
+
assert.deepStrictEqual(tags, ['a'], 'addTag mutated the caller array');
|
|
122
|
+
console.log('ok');
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.error('FAIL: ' + err.message);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
const AVERAGE_TEST = `const assert = require('node:assert');
|
|
129
|
+
const { averageOf } = require('../src/average-of.js');
|
|
130
|
+
try {
|
|
131
|
+
assert.strictEqual(averageOf([10, null, 20]), 15);
|
|
132
|
+
assert.strictEqual(averageOf([null]), 0);
|
|
133
|
+
console.log('ok');
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('FAIL: ' + err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
/**
|
|
140
|
+
* The suite.
|
|
141
|
+
*
|
|
142
|
+
* Each entry is a real defect with a real fix, small enough that a strong model
|
|
143
|
+
* can find it from the failing check and that the reference fix is unambiguous.
|
|
144
|
+
* The axes are the ones that actually bite in production code: an inclusive bound,
|
|
145
|
+
* a comparator that was never given, an async callback in a synchronous-looking
|
|
146
|
+
* call, a falsy guard that eats a legitimate zero, a copy that is only one level
|
|
147
|
+
* deep, a helper that mutates its caller's data, and a denominator that was not
|
|
148
|
+
* updated with the filter beside it.
|
|
149
|
+
*/
|
|
150
|
+
export const SEEDED_BUGS = [
|
|
151
|
+
{
|
|
152
|
+
id: 'seed-range-off-by-one',
|
|
153
|
+
title: 'Range helper returns one element too many',
|
|
154
|
+
axis: 'boundary',
|
|
155
|
+
difficulty: 'easy',
|
|
156
|
+
bug: '`for (let i = 0; i <= n; i += 1)` makes `range(n)` produce n+1 elements; the bound must be exclusive.',
|
|
157
|
+
files: [
|
|
158
|
+
{
|
|
159
|
+
path: 'src/range.js',
|
|
160
|
+
content: `function range(n) {
|
|
161
|
+
const out = [];
|
|
162
|
+
for (let i = 0; i <= n; i += 1) out.push(i);
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = { range };
|
|
167
|
+
`,
|
|
168
|
+
},
|
|
169
|
+
{ path: 'test/range.test.js', content: RANGE_TEST },
|
|
170
|
+
],
|
|
171
|
+
fixedFiles: [
|
|
172
|
+
{
|
|
173
|
+
path: 'src/range.js',
|
|
174
|
+
content: `function range(n) {
|
|
175
|
+
const out = [];
|
|
176
|
+
for (let i = 0; i < n; i += 1) out.push(i);
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = { range };
|
|
181
|
+
`,
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
target: 'src/range.js',
|
|
185
|
+
checks: [{ file: 'test/range.test.js', command: 'node test/range.test.js' }],
|
|
186
|
+
detectionSignals: ['off-by-one', 'off by one', 'inclusive', 'exclusive', '<='],
|
|
187
|
+
tokenBudget: 20_000,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: 'seed-top-scores-lexical-sort',
|
|
191
|
+
title: 'Top scores sorted as strings',
|
|
192
|
+
axis: 'comparator',
|
|
193
|
+
difficulty: 'easy',
|
|
194
|
+
bug: '`scores.sort()` sorts lexically without a comparator, so 100 ranks below 9. The fix must also stop mutating the caller array.',
|
|
195
|
+
files: [
|
|
196
|
+
{
|
|
197
|
+
path: 'src/top-scores.js',
|
|
198
|
+
content: `function topScores(scores, n) {
|
|
199
|
+
return scores.sort().slice(0, n);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
module.exports = { topScores };
|
|
203
|
+
`,
|
|
204
|
+
},
|
|
205
|
+
{ path: 'test/top-scores.test.js', content: TOP_SCORES_TEST },
|
|
206
|
+
],
|
|
207
|
+
fixedFiles: [
|
|
208
|
+
{
|
|
209
|
+
path: 'src/top-scores.js',
|
|
210
|
+
content: `function topScores(scores, n) {
|
|
211
|
+
return [...scores].sort((a, b) => b - a).slice(0, n);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
module.exports = { topScores };
|
|
215
|
+
`,
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
target: 'src/top-scores.js',
|
|
219
|
+
checks: [{ file: 'test/top-scores.test.js', command: 'node test/top-scores.test.js' }],
|
|
220
|
+
detectionSignals: ['lexicograph', 'string', 'comparator', 'numeric'],
|
|
221
|
+
tokenBudget: 20_000,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
id: 'seed-sum-async-for-each',
|
|
225
|
+
title: 'Async callback in a synchronous-looking forEach',
|
|
226
|
+
axis: 'async',
|
|
227
|
+
difficulty: 'medium',
|
|
228
|
+
bug: '`values.forEach(async …)` never awaits the callbacks, so the function resolves before the calls finish and returns the initial 0.',
|
|
229
|
+
files: [
|
|
230
|
+
{
|
|
231
|
+
path: 'src/sum-async.js',
|
|
232
|
+
content: `async function sumAsync(values) {
|
|
233
|
+
let total = 0;
|
|
234
|
+
values.forEach(async (value) => {
|
|
235
|
+
total += await Promise.resolve(value);
|
|
236
|
+
});
|
|
237
|
+
return total;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
module.exports = { sumAsync };
|
|
241
|
+
`,
|
|
242
|
+
},
|
|
243
|
+
{ path: 'test/sum-async.test.js', content: SUM_ASYNC_TEST },
|
|
244
|
+
],
|
|
245
|
+
fixedFiles: [
|
|
246
|
+
{
|
|
247
|
+
path: 'src/sum-async.js',
|
|
248
|
+
content: `async function sumAsync(values) {
|
|
249
|
+
let total = 0;
|
|
250
|
+
for (const value of values) {
|
|
251
|
+
total += await Promise.resolve(value);
|
|
252
|
+
}
|
|
253
|
+
return total;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = { sumAsync };
|
|
257
|
+
`,
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
target: 'src/sum-async.js',
|
|
261
|
+
checks: [{ file: 'test/sum-async.test.js', command: 'node test/sum-async.test.js' }],
|
|
262
|
+
detectionSignals: ['forall', 'not awaited', 'await', 'race', 'synchronous'],
|
|
263
|
+
tokenBudget: 20_000,
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
id: 'seed-format-amount-falsy-zero',
|
|
267
|
+
title: 'A falsy guard swallows a legitimate zero',
|
|
268
|
+
axis: 'truthiness',
|
|
269
|
+
difficulty: 'easy',
|
|
270
|
+
bug: 'A falsy guard (if (!amount)) treats 0 as missing; the guard must test for null/undefined instead, while null must still read as an em dash.',
|
|
271
|
+
files: [
|
|
272
|
+
{
|
|
273
|
+
path: 'src/format-amount.js',
|
|
274
|
+
content: `function formatAmount(amount) {
|
|
275
|
+
if (!amount) return '—';
|
|
276
|
+
return '$' + amount.toFixed(2);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
module.exports = { formatAmount };
|
|
280
|
+
`,
|
|
281
|
+
},
|
|
282
|
+
{ path: 'test/format-amount.test.js', content: FORMAT_AMOUNT_TEST },
|
|
283
|
+
],
|
|
284
|
+
fixedFiles: [
|
|
285
|
+
{
|
|
286
|
+
path: 'src/format-amount.js',
|
|
287
|
+
content: `function formatAmount(amount) {
|
|
288
|
+
if (amount === null || amount === undefined) return '—';
|
|
289
|
+
return '$' + amount.toFixed(2);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
module.exports = { formatAmount };
|
|
293
|
+
`,
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
target: 'src/format-amount.js',
|
|
297
|
+
checks: [{ file: 'test/format-amount.test.js', command: 'node test/format-amount.test.js' }],
|
|
298
|
+
detectionSignals: ['falsy', 'truthy', 'zero', '!amount', 'null'],
|
|
299
|
+
tokenBudget: 20_000,
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 'seed-clone-config-shallow',
|
|
303
|
+
title: 'Config clone is only one level deep',
|
|
304
|
+
axis: 'aliasing',
|
|
305
|
+
difficulty: 'medium',
|
|
306
|
+
bug: '`{ ...cfg }` copies the top level only, so `copy.limits` IS `original.limits` and mutating one changes the other.',
|
|
307
|
+
files: [
|
|
308
|
+
{
|
|
309
|
+
path: 'src/clone-config.js',
|
|
310
|
+
content: `function cloneConfig(config) {
|
|
311
|
+
return { ...config };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
module.exports = { cloneConfig };
|
|
315
|
+
`,
|
|
316
|
+
},
|
|
317
|
+
{ path: 'test/clone-config.test.js', content: CLONE_CONFIG_TEST },
|
|
318
|
+
],
|
|
319
|
+
fixedFiles: [
|
|
320
|
+
{
|
|
321
|
+
path: 'src/clone-config.js',
|
|
322
|
+
content: `function cloneConfig(config) {
|
|
323
|
+
return structuredClone(config);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
module.exports = { cloneConfig };
|
|
327
|
+
`,
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
target: 'src/clone-config.js',
|
|
331
|
+
checks: [{ file: 'test/clone-config.test.js', command: 'node test/clone-config.test.js' }],
|
|
332
|
+
detectionSignals: ['shallow', 'deep', 'nested', 'aliasing', 'reference'],
|
|
333
|
+
tokenBudget: 20_000,
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
id: 'seed-add-tag-mutates-input',
|
|
337
|
+
title: 'Helper mutates its caller array',
|
|
338
|
+
axis: 'mutation',
|
|
339
|
+
difficulty: 'easy',
|
|
340
|
+
bug: '`tags.push(tag); return tags;` returns the caller\'s own array after mutating it; it must return a new array.',
|
|
341
|
+
files: [
|
|
342
|
+
{
|
|
343
|
+
path: 'src/add-tag.js',
|
|
344
|
+
content: `function addTag(tags, tag) {
|
|
345
|
+
tags.push(tag);
|
|
346
|
+
return tags;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
module.exports = { addTag };
|
|
350
|
+
`,
|
|
351
|
+
},
|
|
352
|
+
{ path: 'test/add-tag.test.js', content: ADD_TAG_TEST },
|
|
353
|
+
],
|
|
354
|
+
fixedFiles: [
|
|
355
|
+
{
|
|
356
|
+
path: 'src/add-tag.js',
|
|
357
|
+
content: `function addTag(tags, tag) {
|
|
358
|
+
return [...tags, tag];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
module.exports = { addTag };
|
|
362
|
+
`,
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
target: 'src/add-tag.js',
|
|
366
|
+
checks: [{ file: 'test/add-tag.test.js', command: 'node test/add-tag.test.js' }],
|
|
367
|
+
detectionSignals: ['mutat', 'in place', 'copy', 'push'],
|
|
368
|
+
tokenBudget: 20_000,
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
id: 'seed-average-filtered-denominator',
|
|
372
|
+
title: 'Denominator not updated with the filter',
|
|
373
|
+
axis: 'aggregation',
|
|
374
|
+
difficulty: 'medium',
|
|
375
|
+
bug: 'Entries are filtered out of the SUM but not out of the DIVISOR, so a missing measurement drags every average down.',
|
|
376
|
+
files: [
|
|
377
|
+
{
|
|
378
|
+
path: 'src/average-of.js',
|
|
379
|
+
content: `function averageOf(measurements) {
|
|
380
|
+
const real = measurements.filter((m) => m !== null);
|
|
381
|
+
if (measurements.length === 0) return 0;
|
|
382
|
+
const sum = real.reduce((total, value) => total + value, 0);
|
|
383
|
+
return sum / measurements.length;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
module.exports = { averageOf };
|
|
387
|
+
`,
|
|
388
|
+
},
|
|
389
|
+
{ path: 'test/average-of.test.js', content: AVERAGE_TEST },
|
|
390
|
+
],
|
|
391
|
+
fixedFiles: [
|
|
392
|
+
{
|
|
393
|
+
path: 'src/average-of.js',
|
|
394
|
+
content: `function averageOf(measurements) {
|
|
395
|
+
const real = measurements.filter((m) => m !== null);
|
|
396
|
+
if (real.length === 0) return 0;
|
|
397
|
+
const sum = real.reduce((total, value) => total + value, 0);
|
|
398
|
+
return sum / real.length;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
module.exports = { averageOf };
|
|
402
|
+
`,
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
target: 'src/average-of.js',
|
|
406
|
+
checks: [{ file: 'test/average-of.test.js', command: 'node test/average-of.test.js' }],
|
|
407
|
+
detectionSignals: ['denominator', 'divisor', 'length', 'filtered'],
|
|
408
|
+
tokenBudget: 20_000,
|
|
409
|
+
},
|
|
410
|
+
];
|
|
411
|
+
/** A bug by id, or undefined. */
|
|
412
|
+
export function seededBugById(id) {
|
|
413
|
+
return SEEDED_BUGS.find((bug) => bug.id === id);
|
|
414
|
+
}
|
|
415
|
+
/** Write a workspace to `dir`. `fixed` swaps in the reference fix. */
|
|
416
|
+
export function materializeSeededBug(bug, dir, fixed = false) {
|
|
417
|
+
const files = fixed
|
|
418
|
+
? [
|
|
419
|
+
...bug.files.filter((f) => !bug.fixedFiles.some((fixedFile) => fixedFile.path === f.path)),
|
|
420
|
+
...bug.fixedFiles,
|
|
421
|
+
]
|
|
422
|
+
: bug.files;
|
|
423
|
+
for (const file of files) {
|
|
424
|
+
const abs = join(dir, file.path);
|
|
425
|
+
mkdirSync(join(abs, '..'), { recursive: true });
|
|
426
|
+
writeFileSync(abs, file.content, 'utf-8');
|
|
427
|
+
}
|
|
428
|
+
return dir;
|
|
429
|
+
}
|
|
430
|
+
/** Run one check in a workspace. Never throws — a failure IS the result. */
|
|
431
|
+
export function runSeedCheck(workspace, check, timeoutMs = 30_000) {
|
|
432
|
+
const start = Date.now();
|
|
433
|
+
try {
|
|
434
|
+
const output = execSync(check.command, {
|
|
435
|
+
cwd: workspace,
|
|
436
|
+
timeout: timeoutMs,
|
|
437
|
+
stdio: 'pipe',
|
|
438
|
+
encoding: 'utf-8',
|
|
439
|
+
shell: process.platform === 'win32' ? 'cmd.exe' : '/bin/bash',
|
|
440
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
441
|
+
});
|
|
442
|
+
return { command: check.command, exitCode: 0, output: String(output).trim(), durationMs: Date.now() - start };
|
|
443
|
+
}
|
|
444
|
+
catch (err) {
|
|
445
|
+
const e = err;
|
|
446
|
+
const stdout = typeof e.stdout === 'string' ? e.stdout : String(e.stdout || '');
|
|
447
|
+
const stderr = typeof e.stderr === 'string' ? e.stderr : String(e.stderr || '');
|
|
448
|
+
return {
|
|
449
|
+
command: check.command,
|
|
450
|
+
// A killed check (timeout) reports no status; 1 keeps it a failure rather
|
|
451
|
+
// than an accidental pass.
|
|
452
|
+
exitCode: e.status ?? 1,
|
|
453
|
+
output: `${stdout}\n${stderr}`.trim(),
|
|
454
|
+
durationMs: Date.now() - start,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Prove a seed is genuinely broken and genuinely fixable.
|
|
460
|
+
*
|
|
461
|
+
* Both halves are required, and the marker requirement is what stops a check that
|
|
462
|
+
* merely CRASHED from counting as evidence of a bug: a syntax error also exits
|
|
463
|
+
* non-zero, so "it failed" alone would verify nothing. The fix half is what proves
|
|
464
|
+
* the check is well-formed; the marker half is what proves the failure is the
|
|
465
|
+
* defect's.
|
|
466
|
+
*/
|
|
467
|
+
export function verifySeededBug(bug) {
|
|
468
|
+
const seedDir = mkdtempSync(join(tmpdir(), `seed-verify-${bug.id}-`));
|
|
469
|
+
const fixedDir = mkdtempSync(join(tmpdir(), `seed-verify-fixed-${bug.id}-`));
|
|
470
|
+
try {
|
|
471
|
+
materializeSeededBug(bug, seedDir, false);
|
|
472
|
+
materializeSeededBug(bug, fixedDir, true);
|
|
473
|
+
const details = [];
|
|
474
|
+
let seedFails = true;
|
|
475
|
+
let fixPasses = true;
|
|
476
|
+
for (const check of bug.checks) {
|
|
477
|
+
const seeded = runSeedCheck(seedDir, check);
|
|
478
|
+
// The marker requirement: the check must fail BY ASSERTING, not by crashing.
|
|
479
|
+
const failedByAsserting = seeded.exitCode !== 0 && /FAIL/.test(seeded.output);
|
|
480
|
+
if (!failedByAsserting)
|
|
481
|
+
seedFails = false;
|
|
482
|
+
details.push(` seed ${check.command} → exit ${seeded.exitCode}` +
|
|
483
|
+
(failedByAsserting ? '' : ` (no FAIL marker — ${firstLine(seeded.output) || 'no output'})`) +
|
|
484
|
+
`\n ${firstLine(seeded.output)}`);
|
|
485
|
+
const repaired = runSeedCheck(fixedDir, check);
|
|
486
|
+
if (repaired.exitCode !== 0)
|
|
487
|
+
fixPasses = false;
|
|
488
|
+
details.push(` fixed ${check.command} → exit ${repaired.exitCode}` +
|
|
489
|
+
(repaired.exitCode === 0 ? '' : ` (${firstLine(repaired.output) || 'no output'})`));
|
|
490
|
+
}
|
|
491
|
+
return {
|
|
492
|
+
id: bug.id,
|
|
493
|
+
title: bug.title,
|
|
494
|
+
seedFails,
|
|
495
|
+
fixPasses,
|
|
496
|
+
ok: seedFails && fixPasses,
|
|
497
|
+
detail: details.join('\n'),
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
finally {
|
|
501
|
+
rmSync(seedDir, { recursive: true, force: true });
|
|
502
|
+
rmSync(fixedDir, { recursive: true, force: true });
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/** The first non-empty line of output, for a one-line report. */
|
|
506
|
+
function firstLine(output) {
|
|
507
|
+
return (output || '').split('\n').map((l) => l.trim()).find(Boolean) ?? '';
|
|
508
|
+
}
|
|
509
|
+
/** A table of verifications, ready to print. */
|
|
510
|
+
export function formatSeedVerification(results) {
|
|
511
|
+
const lines = ['Seeded-bug verification (each seed must FAIL its checks, and PASS once fixed):', ''];
|
|
512
|
+
for (const result of results) {
|
|
513
|
+
lines.push(` ${result.ok ? '✅' : '✗ '} ${result.id.padEnd(36)} ${result.title}`);
|
|
514
|
+
if (!result.ok) {
|
|
515
|
+
lines.push(` seed fails: ${result.seedFails ? 'yes' : 'NO'} · fix passes: ${result.fixPasses ? 'yes' : 'NO'}`);
|
|
516
|
+
lines.push(result.detail);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
const bad = results.filter((r) => !r.ok).length;
|
|
520
|
+
lines.push('');
|
|
521
|
+
lines.push(bad === 0
|
|
522
|
+
? `✓ all ${results.length} seeded bug(s) verified — every one is genuinely broken, and genuinely fixable.`
|
|
523
|
+
: `✗ ${bad} of ${results.length} seeded bug(s) did not verify — a task that is not broken scores nothing.`);
|
|
524
|
+
return lines.join('\n');
|
|
525
|
+
}
|
|
526
|
+
/** Read a file from a workspace, or null. */
|
|
527
|
+
export function readWorkspaceFile(workspace, path) {
|
|
528
|
+
try {
|
|
529
|
+
return readFileSync(join(workspace, path), 'utf-8');
|
|
530
|
+
}
|
|
531
|
+
catch {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
//# sourceMappingURL=seeded-bugs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeded-bugs.js","sourceRoot":"","sources":["../../src/learning/seeded-bugs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WS5 (#27) — the resume ledger: replay a run's unchanged MODEL CALLS.
|
|
3
|
+
*
|
|
4
|
+
* WHY REPLAYING MODEL CALLS IS THE USEFUL UNIT. `--resume` already existed for the
|
|
5
|
+
* pipeline engine, where it skips completed TASKS (`agents/checkpoint-store.ts`).
|
|
6
|
+
* A task is a coarse unit: one that half-finished is re-run from its start, and on
|
|
7
|
+
* an agent LOOP — where a turn is many model calls, each of which may have cost a
|
|
8
|
+
* slow provider round trip — the expensive thing is the calls, not the tasks. So
|
|
9
|
+
* this ledger records each step's answer and replays the ones whose input has not
|
|
10
|
+
* changed, which is what makes a re-run cost two calls instead of twenty.
|
|
11
|
+
*
|
|
12
|
+
* WHY THE KEY IS A DIGEST OF THE WHOLE INPUT, NOT THE STEP NUMBER. A step's number
|
|
13
|
+
* is the same on every run and means nothing about its content: replay by position
|
|
14
|
+
* and a plan that shifted by one step serves an answer to a question that was never
|
|
15
|
+
* asked — silently, because a replayed answer is indistinguishable from a fresh one
|
|
16
|
+
* in the transcript. The digest covers the whole thread AND the tool schema, so a
|
|
17
|
+
* changed tool result, a changed schema, a reordered message or an edited goal all
|
|
18
|
+
* MISS and the step is paid for again.
|
|
19
|
+
*
|
|
20
|
+
* WHY AN EMPTY RECORDED STEP IS NEVER REPLAYED. A response with no text and no tool
|
|
21
|
+
* call is a provider failure, not an answer. Replaying it would reproduce the
|
|
22
|
+
* failure while removing the only thing that would have fixed it — the call itself
|
|
23
|
+
* — and would hide the fact that the provider was never consulted.
|
|
24
|
+
*
|
|
25
|
+
* WHY NOTHING HAPPENS WITHOUT A REQUEST. An ordinary run must not read, write, or
|
|
26
|
+
* even look for a record: `--resume` is the only thing that opens the store, and a
|
|
27
|
+
* turn that was never asked to resume pays no filesystem cost and cannot inherit
|
|
28
|
+
* another run's answers by accident.
|
|
29
|
+
*
|
|
30
|
+
* WHY IT REPORTS WHAT IT LOADED AND WHAT IT REPLAYED SEPARATELY. At open time the
|
|
31
|
+
* only knowable fact is what the RECORD holds; whether any of it will be usable is
|
|
32
|
+
* decided step by step, once the thread is actually built. Announcing an outcome at
|
|
33
|
+
* open is how a resumed run came to print "nothing to replay" before it had tried
|
|
34
|
+
* anything — including on runs that then replayed everything.
|
|
35
|
+
*/
|
|
36
|
+
import type { ToolCallResponse } from '../inference/interface.js';
|
|
37
|
+
/** The environment key a deployment asks for a resume through. */
|
|
38
|
+
export declare const RESUME_ENABLE_ENV = "NUVIRA_RESUME";
|
|
39
|
+
/** ─── Requests ─────────────────────────────────────────────────────────────── */
|
|
40
|
+
/**
|
|
41
|
+
* A resolved resume request.
|
|
42
|
+
*
|
|
43
|
+
* An absent `id` means "the record for this ask, in this directory" — resolved at
|
|
44
|
+
* open time through `checkpointIdFor`, which is what makes `--resume` with no
|
|
45
|
+
* argument mean the LAST run of the same ask HERE, rather than some global newest.
|
|
46
|
+
*/
|
|
47
|
+
export interface ResumeRequest {
|
|
48
|
+
id?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a resume request from a caller's option, with the environment as the
|
|
52
|
+
* fallback.
|
|
53
|
+
*
|
|
54
|
+
* `undefined` means nobody said anything, and only then does `NUVIRA_RESUME`
|
|
55
|
+
* decide (`1` asks for the auto record, any other value names one). An explicit
|
|
56
|
+
* `false` is a DECISION and outranks the environment, so a surface with an off
|
|
57
|
+
* switch can decline a request a deployment made for every turn.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveResumeRequest(input: {
|
|
60
|
+
resume?: string | boolean;
|
|
61
|
+
}): ResumeRequest | undefined;
|
|
62
|
+
/** ─── Digests ──────────────────────────────────────────────────────────────── */
|
|
63
|
+
/**
|
|
64
|
+
* The key a step is stored under: a hash of its whole input.
|
|
65
|
+
*
|
|
66
|
+
* Key ORDER is normalised, so a tool-call argument object that came back with its
|
|
67
|
+
* keys in a different order hashes the same — that is a JSON-round-trip artefact,
|
|
68
|
+
* not a change of input — while a different VALUE anywhere hashes differently.
|
|
69
|
+
*/
|
|
70
|
+
export declare function stepDigest(thread: readonly unknown[], schemas: readonly unknown[]): string;
|
|
71
|
+
/** ─── The ledger ───────────────────────────────────────────────────────────── */
|
|
72
|
+
/**
|
|
73
|
+
* The ledger a loop threads its steps through.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately tiny: `replay` answers "was this step already answered, and for
|
|
76
|
+
* THIS input", `record` files an answer for the next run, and `openNotice` says
|
|
77
|
+
* what the record held. Everything a caller needs to decide is here; how the
|
|
78
|
+
* numbers are reported is `closeResume`'s job.
|
|
79
|
+
*/
|
|
80
|
+
export interface StepReplay {
|
|
81
|
+
/** The recorded answer for this exact input, or null (with a reason recorded). */
|
|
82
|
+
replay(key: string, digest: string): ToolCallResponse | null;
|
|
83
|
+
/** File an answer this run paid for, so the next one can replay it. */
|
|
84
|
+
record(key: string, digest: string, response: ToolCallResponse): void;
|
|
85
|
+
/** What the RECORD held, said before any step was attempted. */
|
|
86
|
+
openNotice(): string;
|
|
87
|
+
}
|
|
88
|
+
/** An opened resume: its record id, and the ledger to thread through the run. */
|
|
89
|
+
export interface OpenResume {
|
|
90
|
+
id: string;
|
|
91
|
+
goal: string;
|
|
92
|
+
cwd: string;
|
|
93
|
+
ledger: StepReplay;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Open the record for this ask, reading it once (a record is not re-read per step).
|
|
97
|
+
*/
|
|
98
|
+
export declare function openResume(input: {
|
|
99
|
+
goal: string;
|
|
100
|
+
cwd: string;
|
|
101
|
+
resume: ResumeRequest;
|
|
102
|
+
}): OpenResume;
|
|
103
|
+
/** What a resumed run replayed, what it paid for, and whether the record survived. */
|
|
104
|
+
export interface ResumeOutcome {
|
|
105
|
+
id: string;
|
|
106
|
+
/** Steps served from the record (each one a model call NOT made). */
|
|
107
|
+
replayed: number;
|
|
108
|
+
/** Model calls the RESUMED run still made (0 = every step came from the record). */
|
|
109
|
+
modelCalls: number;
|
|
110
|
+
/** False when the record could not be written (the run itself still happened). */
|
|
111
|
+
saved: boolean;
|
|
112
|
+
/** The operator-facing line: the counts, and why nothing replayed when it didn't. */
|
|
113
|
+
notice: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Close the ledger: write back what this run learned, and report the real counts.
|
|
117
|
+
*
|
|
118
|
+
* The record is rewritten only from what this run staged — the entries it replayed
|
|
119
|
+
* plus the ones it paid for — which is what makes the chain work: the next resume
|
|
120
|
+
* replays what this one learned, and a step nobody could use is not carried along
|
|
121
|
+
* as if it had been.
|
|
122
|
+
*/
|
|
123
|
+
export declare function closeResume(resume: OpenResume, input: {
|
|
124
|
+
goal: string;
|
|
125
|
+
cwd: string;
|
|
126
|
+
}): ResumeOutcome;
|
|
127
|
+
//# sourceMappingURL=step-checkpoint.d.ts.map
|