@stigmer/runner 3.15.0 → 3.15.2-dev.20260913223433
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 +2 -4
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
- package/dist/__test-utils__/execution-record-fixture.js +4 -0
- package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
- package/dist/__test-utils__/file-review-projection.d.ts +40 -0
- package/dist/__test-utils__/file-review-projection.js +136 -0
- package/dist/__test-utils__/file-review-projection.js.map +1 -0
- package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
- package/dist/__test-utils__/harness-contract/types.js +15 -0
- package/dist/__test-utils__/harness-contract/types.js.map +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
- package/dist/__test-utils__/hermetic-activity.js +52 -14
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
- package/dist/__test-utils__/model-registry-fixture.js +31 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
- package/dist/__test-utils__/turn-input-fixture.js +1 -1
- package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
- package/dist/activities/call-agent.js +2 -2
- package/dist/activities/call-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +7 -5
- package/dist/activities/execute-cursor/adapter.js +7 -5
- package/dist/activities/execute-cursor/adapter.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
- package/dist/activities/execute-cursor/approval-policy.js +5 -2
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
- package/dist/activities/execute-cursor/approval-state.js +6 -3
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
- package/dist/activities/execute-cursor/cas-observations.js +19 -2
- package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
- package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
- package/dist/activities/execute-cursor/message-translator.js +19 -32
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
- package/dist/activities/execute-cursor/prompt-builder.js +76 -95
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
- package/dist/activities/execute-cursor/turn-boundary.js +30 -90
- package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
- package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
- package/dist/activities/execute-cursor/turn-settle.js +37 -49
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
- package/dist/activities/execute-cursor/turn-setup.js +29 -59
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
- package/dist/activities/execute-cursor/turn-stream.js +9 -22
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.js +5 -1
- package/dist/activities/execute-cursor/turn.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
- package/dist/activities/execute-deep-agent/adapter.js +78 -0
- package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
- package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
- package/dist/activities/execute-deep-agent/execution-state.js +4 -12
- package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
- package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
- package/dist/activities/execute-deep-agent/hitl.js +77 -103
- package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
- package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
- package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
- package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
- package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
- package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
- package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
- package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
- package/dist/activities/execute-deep-agent/turn.js +116 -0
- package/dist/activities/execute-deep-agent/turn.js.map +1 -0
- package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
- package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
- package/dist/activities/execute-deep-agent/v3-events.js +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
- package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/harness/approval-decisions.d.ts +61 -0
- package/dist/harness/approval-decisions.js +102 -0
- package/dist/harness/approval-decisions.js.map +1 -0
- package/dist/harness/capabilities.d.ts +16 -5
- package/dist/harness/capabilities.js +9 -0
- package/dist/harness/capabilities.js.map +1 -1
- package/dist/harness/capture.d.ts +144 -0
- package/dist/harness/capture.js +219 -0
- package/dist/harness/capture.js.map +1 -0
- package/dist/harness/persist-chokepoint.d.ts +19 -4
- package/dist/harness/persist-chokepoint.js +17 -4
- package/dist/harness/persist-chokepoint.js.map +1 -1
- package/dist/harness/run-turn.js +115 -29
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/terminal-table.d.ts +40 -11
- package/dist/harness/terminal-table.js +58 -19
- package/dist/harness/terminal-table.js.map +1 -1
- package/dist/harness/turn-context.d.ts +141 -76
- package/dist/harness/turn-context.js +194 -99
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +65 -12
- package/dist/harness/types.js +8 -2
- package/dist/harness/types.js.map +1 -1
- package/dist/harness-adapters.d.ts +12 -8
- package/dist/harness-adapters.js +17 -9
- package/dist/harness-adapters.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +1 -1
- package/dist/middleware/approval-gate.js +1 -1
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +39 -0
- package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
- package/dist/middleware/cost-advisory.js.map +1 -0
- package/dist/middleware/index.d.ts +23 -12
- package/dist/middleware/index.js +26 -18
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -2
- package/dist/runner-manager.js +1 -5
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +1 -5
- package/dist/runner.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +41 -18
- package/dist/shared/attachment-resolver.js +178 -46
- package/dist/shared/attachment-resolver.js.map +1 -1
- package/dist/shared/attachment-zip.d.ts +85 -0
- package/dist/shared/attachment-zip.js +185 -0
- package/dist/shared/attachment-zip.js.map +1 -0
- package/dist/shared/connect-backfill.js +5 -4
- package/dist/shared/connect-backfill.js.map +1 -1
- package/dist/shared/cost-guard.d.ts +3 -3
- package/dist/shared/cost-guard.js +3 -3
- package/dist/shared/execution-status-writer.d.ts +5 -5
- package/dist/shared/execution-status-writer.js +5 -5
- package/dist/shared/extract-structured-output.d.ts +8 -7
- package/dist/shared/extract-structured-output.js +8 -7
- package/dist/shared/extract-structured-output.js.map +1 -1
- package/dist/shared/filereview/cas-progress.d.ts +1 -18
- package/dist/shared/filereview/cas-progress.js +4 -0
- package/dist/shared/filereview/cas-progress.js.map +1 -1
- package/dist/shared/filereview/cas-touched.d.ts +56 -0
- package/dist/shared/filereview/cas-touched.js +63 -0
- package/dist/shared/filereview/cas-touched.js.map +1 -0
- package/dist/shared/filereview/index.d.ts +2 -1
- package/dist/shared/filereview/index.js +2 -1
- package/dist/shared/filereview/index.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +4 -5
- package/dist/shared/mcp-resolver.js +4 -5
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +3 -4
- package/dist/shared/persist-decision.js +3 -4
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +2 -2
- package/dist/shared/plan-mode-permissions.js +2 -2
- package/dist/shared/plan-mode-prompt.d.ts +1 -1
- package/dist/shared/plan-mode-prompt.js +1 -1
- package/dist/shared/prompt-sections.d.ts +163 -0
- package/dist/shared/prompt-sections.js +164 -0
- package/dist/shared/prompt-sections.js.map +1 -0
- package/dist/shared/skill-resolver.d.ts +4 -2
- package/dist/shared/skill-resolver.js +4 -2
- package/dist/shared/skill-resolver.js.map +1 -1
- package/dist/shared/tool-rounds.d.ts +32 -0
- package/dist/shared/tool-rounds.js +43 -0
- package/dist/shared/tool-rounds.js.map +1 -1
- package/dist/shared/tool-row.d.ts +34 -0
- package/dist/shared/tool-row.js +52 -0
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/workspace/session-provision.d.ts +3 -3
- package/dist/shared/workspace/session-provision.js +3 -3
- package/dist/shared/workspace/stigmer-link.d.ts +3 -3
- package/dist/shared/workspace/stigmer-link.js +3 -3
- package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
- package/dist/shared/workspace/writeback-coordinator.js +16 -53
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/package.json +4 -4
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
- package/src/__test-utils__/execution-record-fixture.ts +18 -2
- package/src/__test-utils__/file-review-projection.ts +156 -0
- package/src/__test-utils__/git-workspace-fixture.ts +58 -0
- package/src/__test-utils__/harness-boot-order-child.ts +7 -2
- package/src/__test-utils__/harness-contract/contract.ts +33 -20
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
- package/src/__test-utils__/harness-contract/types.ts +27 -3
- package/src/__test-utils__/hermetic-activity.ts +52 -14
- package/src/__test-utils__/model-registry-fixture.ts +32 -7
- package/src/__test-utils__/module-specifiers.ts +24 -0
- package/src/__test-utils__/turn-input-fixture.ts +2 -2
- package/src/__tests__/harness-boot-order.test.ts +9 -2
- package/src/activities/call-agent.ts +2 -2
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
- package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
- package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
- package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
- package/src/activities/execute-cursor/adapter.ts +7 -5
- package/src/activities/execute-cursor/approval-policy.ts +5 -2
- package/src/activities/execute-cursor/approval-state.ts +16 -8
- package/src/activities/execute-cursor/cas-observations.ts +20 -2
- package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
- package/src/activities/execute-cursor/message-translator.ts +29 -41
- package/src/activities/execute-cursor/prompt-builder.ts +99 -157
- package/src/activities/execute-cursor/turn-boundary.ts +34 -140
- package/src/activities/execute-cursor/turn-settle.ts +37 -51
- package/src/activities/execute-cursor/turn-setup.ts +30 -70
- package/src/activities/execute-cursor/turn-stream.ts +8 -31
- package/src/activities/execute-cursor/turn.ts +5 -1
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
- package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
- package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
- package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
- package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
- package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
- package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
- package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
- package/src/activities/execute-deep-agent/adapter.ts +94 -0
- package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
- package/src/activities/execute-deep-agent/execution-state.ts +4 -13
- package/src/activities/execute-deep-agent/hitl.ts +100 -123
- package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
- package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
- package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
- package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
- package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
- package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
- package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
- package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
- package/src/activities/execute-deep-agent/turn.ts +131 -0
- package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
- package/src/activities/execute-deep-agent/v3-events.ts +1 -1
- package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
- package/src/harness/__tests__/approval-decisions.test.ts +116 -0
- package/src/harness/__tests__/capture.test.ts +268 -0
- package/src/harness/__tests__/mount-skills.test.ts +169 -0
- package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
- package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
- package/src/harness/__tests__/run-turn.test.ts +39 -23
- package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
- package/src/harness/__tests__/turn-context.test.ts +73 -26
- package/src/harness/approval-decisions.ts +104 -0
- package/src/harness/capabilities.ts +16 -5
- package/src/harness/capture.ts +301 -0
- package/src/harness/persist-chokepoint.ts +24 -4
- package/src/harness/run-turn.ts +120 -29
- package/src/harness/terminal-table.ts +61 -20
- package/src/harness/turn-context.ts +208 -111
- package/src/harness/types.ts +66 -12
- package/src/harness-adapters.ts +17 -9
- package/src/middleware/__tests__/approval-gate.test.ts +1 -1
- package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
- package/src/middleware/approval-gate.ts +2 -2
- package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
- package/src/middleware/index.ts +29 -29
- package/src/middleware/types.ts +3 -2
- package/src/runner-manager.ts +0 -8
- package/src/runner.ts +0 -8
- package/src/shared/__tests__/attachment-naming.test.ts +6 -19
- package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
- package/src/shared/__tests__/attachment-zip.test.ts +236 -0
- package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
- package/src/shared/__tests__/cost-guard.test.ts +3 -3
- package/src/shared/__tests__/prompt-sections.test.ts +167 -0
- package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
- package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
- package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
- package/src/shared/attachment-resolver.ts +218 -55
- package/src/shared/attachment-zip.ts +281 -0
- package/src/shared/connect-backfill.ts +9 -11
- package/src/shared/cost-guard.ts +3 -3
- package/src/shared/execution-status-writer.ts +5 -5
- package/src/shared/extract-structured-output.ts +8 -7
- package/src/shared/filereview/__tests__/capture.test.ts +86 -4
- package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
- package/src/shared/filereview/cas-progress.ts +5 -19
- package/src/shared/filereview/cas-touched.ts +89 -0
- package/src/shared/filereview/index.ts +4 -2
- package/src/shared/mcp-resolver.ts +4 -5
- package/src/shared/persist-decision.ts +3 -4
- package/src/shared/plan-mode-permissions.ts +2 -2
- package/src/shared/plan-mode-prompt.ts +1 -1
- package/src/shared/prompt-sections.ts +256 -0
- package/src/shared/skill-resolver.ts +4 -2
- package/src/shared/tool-rounds.ts +48 -0
- package/src/shared/tool-row.ts +61 -0
- package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
- package/src/shared/workspace/session-provision.ts +3 -3
- package/src/shared/workspace/stigmer-link.ts +3 -3
- package/src/shared/workspace/writeback-coordinator.ts +16 -64
- package/src/tools/index.ts +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
- package/dist/activities/execute-cursor/capture-flow.js +0 -285
- package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
- package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
- package/dist/activities/execute-cursor/command-provenance.js +0 -38
- package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
- package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
- package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
- package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
- package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
- package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
- package/dist/activities/execute-deep-agent/environment.js +0 -58
- package/dist/activities/execute-deep-agent/environment.js.map +0 -1
- package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
- package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
- package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
- package/dist/activities/execute-deep-agent/index.d.ts +0 -15
- package/dist/activities/execute-deep-agent/index.js +0 -918
- package/dist/activities/execute-deep-agent/index.js.map +0 -1
- package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
- package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
- package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
- package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
- package/dist/activities/execute-deep-agent/post-stream.js +0 -71
- package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
- package/dist/activities/execute-deep-agent/setup.js +0 -767
- package/dist/activities/execute-deep-agent/setup.js.map +0 -1
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
- package/dist/activities/execute-deep-agent/status-builder.js +0 -365
- package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
- package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
- package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
- package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
- package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
- package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
- package/dist/activities/execute-deep-agent/streaming.js +0 -160
- package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
- package/dist/middleware/cost-cap.d.ts +0 -22
- package/dist/middleware/cost-cap.js.map +0 -1
- package/dist/middleware/graceful-stop.d.ts +0 -17
- package/dist/middleware/graceful-stop.js +0 -63
- package/dist/middleware/graceful-stop.js.map +0 -1
- package/dist/shared/skill-writer.d.ts +0 -75
- package/dist/shared/skill-writer.js +0 -207
- package/dist/shared/skill-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
- package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
- package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
- package/src/activities/execute-cursor/capture-flow.ts +0 -379
- package/src/activities/execute-cursor/command-provenance.ts +0 -73
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
- package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
- package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
- package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
- package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
- package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
- package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
- package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
- package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
- package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
- package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
- package/src/activities/execute-deep-agent/environment.ts +0 -76
- package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
- package/src/activities/execute-deep-agent/index.ts +0 -1072
- package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
- package/src/activities/execute-deep-agent/post-stream.ts +0 -109
- package/src/activities/execute-deep-agent/setup.ts +0 -1081
- package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
- package/src/activities/execute-deep-agent/status-builder.ts +0 -481
- package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
- package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
- package/src/activities/execute-deep-agent/streaming.ts +0 -313
- package/src/middleware/__tests__/cost-cap.test.ts +0 -192
- package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
- package/src/middleware/graceful-stop.ts +0 -86
- package/src/shared/__tests__/skill-writer.test.ts +0 -372
- package/src/shared/skill-writer.ts +0 -266
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic golden: the simplest possible turn through the whole
|
|
3
|
+
* `ExecuteDeepAgent` activity — one user message in, one assistant message
|
|
4
|
+
* out, no tools, no gate, no workspace entries.
|
|
5
|
+
*
|
|
6
|
+
* Invariant pinned: the activity resolves the four-resource chain, builds the
|
|
7
|
+
* REAL deepagents graph, streams it through the v3 protocol into
|
|
8
|
+
* `V3StatusBuilder`, persists IN_PROGRESS then COMPLETED, and returns the slim
|
|
9
|
+
* status. The golden (`goldens/plain-turn.status.json`) is the smallest
|
|
10
|
+
* status the native harness produces: one AI message with the scripted text
|
|
11
|
+
* and the scripted usage, `startedAt` / `completedAt` on the scripted clock.
|
|
12
|
+
*
|
|
13
|
+
* This file is also the PROBE the M0 plan named: no earlier test drove the
|
|
14
|
+
* real graph through `streamEvents(..., { version: "v3" })`. The scripted
|
|
15
|
+
* model streams, so the events under this golden are the ones a provider
|
|
16
|
+
* produces (`scripted-model.ts` header).
|
|
17
|
+
*
|
|
18
|
+
* Two shapes of the activity's wire contract ride on the same golden, and
|
|
19
|
+
* matching the SAME file is the assertion that they are invisible to the
|
|
20
|
+
* status: the legacy positional `(executionId, threadId)` form the control
|
|
21
|
+
* planes still may send (`shared/activity-input.ts`), and an empty
|
|
22
|
+
* `thread_id` (carried from `index.test.ts`: "handles empty threadId
|
|
23
|
+
* gracefully").
|
|
24
|
+
*
|
|
25
|
+
* Since S3 M2a the activity is the turn runtime over the native adapter, and
|
|
26
|
+
* `streamingUsage` carries the runtime accountant's fields — `model`,
|
|
27
|
+
* `estimatedCostUsd` priced at the registry's rates, the requested tier and
|
|
28
|
+
* thinking mode (Q-M2a-2: one writer of the summary, the runtime). Nothing
|
|
29
|
+
* else in this golden moved with the flip.
|
|
30
|
+
*
|
|
31
|
+
* Regenerate ONLY after a deliberate behavior change:
|
|
32
|
+
* npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
36
|
+
import { toJson } from "@bufbuild/protobuf";
|
|
37
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
38
|
+
import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
39
|
+
|
|
40
|
+
vi.mock("../../../../shared/model-client.js", async () =>
|
|
41
|
+
(await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
|
|
42
|
+
);
|
|
43
|
+
vi.mock("../../../../client/stigmer-client.js", async () =>
|
|
44
|
+
(await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
import {
|
|
48
|
+
ScriptedClock,
|
|
49
|
+
createHermeticEnvironment,
|
|
50
|
+
type HermeticEnvironment,
|
|
51
|
+
} from "../../../../__test-utils__/hermetic-activity.js";
|
|
52
|
+
import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
|
|
53
|
+
import {
|
|
54
|
+
FIXTURE,
|
|
55
|
+
beginDeepAgentScenario,
|
|
56
|
+
deepAgentExecutionRecord,
|
|
57
|
+
runDeepAgentTurn,
|
|
58
|
+
type DeepAgentTurnOptions,
|
|
59
|
+
} from "../../__test-utils__/hermetic-deep-agent.js";
|
|
60
|
+
import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
|
|
61
|
+
|
|
62
|
+
const USER_MESSAGE = "Say hello.";
|
|
63
|
+
const ASSISTANT_TEXT = "Hello from the hermetic fixture agent.";
|
|
64
|
+
const GOLDEN = "./goldens/plain-turn.status.json";
|
|
65
|
+
|
|
66
|
+
describe("ExecuteDeepAgent hermetic — plain turn", () => {
|
|
67
|
+
let env: HermeticEnvironment;
|
|
68
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
69
|
+
const clock = new ScriptedClock();
|
|
70
|
+
|
|
71
|
+
beforeAll(() => {
|
|
72
|
+
env = createHermeticEnvironment();
|
|
73
|
+
registry = stubRegistryFetch();
|
|
74
|
+
clock.install();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterAll(() => {
|
|
78
|
+
clock.uninstall();
|
|
79
|
+
registry.restore();
|
|
80
|
+
env.dispose();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
async function runPlainTurn(turn: DeepAgentTurnOptions = {}) {
|
|
84
|
+
clock.reset();
|
|
85
|
+
const record = deepAgentExecutionRecord({ message: USER_MESSAGE });
|
|
86
|
+
const scenario = beginDeepAgentScenario({
|
|
87
|
+
env,
|
|
88
|
+
clock,
|
|
89
|
+
record,
|
|
90
|
+
script: () => ({ turns: [{ text: ASSISTANT_TEXT, usage: { inputTokens: 1_200, outputTokens: 30 } }] }),
|
|
91
|
+
});
|
|
92
|
+
const invocation = await runDeepAgentTurn(scenario, turn);
|
|
93
|
+
return { record, invocation };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
it("persists IN_PROGRESS then COMPLETED with one assistant message and returns the slim status", async () => {
|
|
97
|
+
// ── Act ──────────────────────────────────────────────────────────────────
|
|
98
|
+
const { record, invocation } = await runPlainTurn();
|
|
99
|
+
|
|
100
|
+
// ── Assert: outcome and phases ───────────────────────────────────────────
|
|
101
|
+
expect(invocation.outcome.kind).toBe("returned");
|
|
102
|
+
const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
|
|
103
|
+
expect(slim.phase).toBe("EXECUTION_COMPLETED");
|
|
104
|
+
expect(record.persistedPhases).toEqual([
|
|
105
|
+
ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
106
|
+
ExecutionPhase.EXECUTION_COMPLETED,
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
// ── Assert: the transcript ───────────────────────────────────────────────
|
|
110
|
+
const final = record.lastFullStatus!;
|
|
111
|
+
const ai = final.messages.filter((m) => m.type === MessageType.MESSAGE_AI);
|
|
112
|
+
expect(ai, "one assistant message, no tool rows").toHaveLength(1);
|
|
113
|
+
expect(ai[0].content).toBe(ASSISTANT_TEXT);
|
|
114
|
+
expect(ai[0].toolCalls).toHaveLength(0);
|
|
115
|
+
expect(final.streamingUsage?.inputTokens).toBe(1_200n);
|
|
116
|
+
expect(final.streamingUsage?.outputTokens).toBe(30n);
|
|
117
|
+
|
|
118
|
+
// ── Assert: hermeticity and what production asked the model client for ──
|
|
119
|
+
expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
|
|
120
|
+
const primaryBuild = recordedModelBuilds()[0];
|
|
121
|
+
expect(primaryBuild?.modelName, "the execution's model, not the default").toBe(FIXTURE.model);
|
|
122
|
+
expect(primaryBuild?.proxyEndpoint, "the OSS posture has no proxy").toBeUndefined();
|
|
123
|
+
|
|
124
|
+
// ── Assert: the golden ───────────────────────────────────────────────────
|
|
125
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
|
|
126
|
+
await expect(json).toMatchFileSnapshot(GOLDEN);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("produces the same status from the legacy positional wire shape", async () => {
|
|
130
|
+
const { record, invocation } = await runPlainTurn({ positional: true });
|
|
131
|
+
expect(invocation.outcome.kind).toBe("returned");
|
|
132
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, record.lastFullStatus!), null, 2) + "\n";
|
|
133
|
+
await expect(json).toMatchFileSnapshot(GOLDEN);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("produces the same status with an empty thread_id", async () => {
|
|
137
|
+
const { record, invocation } = await runPlainTurn({ threadId: "" });
|
|
138
|
+
expect(invocation.outcome.kind).toBe("returned");
|
|
139
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, record.lastFullStatus!), null, 2) + "\n";
|
|
140
|
+
await expect(json).toMatchFileSnapshot(GOLDEN);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic golden: the PLATFORM STOP — the control plane answers a mid-stream
|
|
3
|
+
* persist with `ExecutionControlSignal.STOP`.
|
|
4
|
+
*
|
|
5
|
+
* What the arm does: the record's `controlSignal` answers STOP on the first
|
|
6
|
+
* full write that carries a tool row (the tool-call boundary forces that
|
|
7
|
+
* persist, `persist-decision.ts` `contentDirty`); the runtime's chokepoint
|
|
8
|
+
* reads the signal off the write and aborts the adapter's `stopSignal`; the
|
|
9
|
+
* adapter's loop, which AWAITED that persist, sees the abort before it pulls
|
|
10
|
+
* the next event, cancels the graph run and settles `interrupted`; the
|
|
11
|
+
* runtime's table maps the stop to COMPLETED with `platformStopArm`'s one
|
|
12
|
+
* row, "Execution stopped by the platform.", no `status.error`, and RETURNS.
|
|
13
|
+
*
|
|
14
|
+
* Ruled at Q-S3-3 (a platform STOP is the platform saying "stop spending
|
|
15
|
+
* now"; the runtime's abort is the one stop) and landed at S3 M2a. Until
|
|
16
|
+
* then the orchestrator answered STOP by activating `graceful-stop.ts`,
|
|
17
|
+
* which handed the model one more tool-free round: the transcript carried
|
|
18
|
+
* the model's wrap-up ("Stopping here as asked.") AND the middleware's own
|
|
19
|
+
* notice rendered as the agent's words (F-M0-7), and the run ended
|
|
20
|
+
* COMPLETED with no row. The graceful-stop middleware was deleted at S3 M2b
|
|
21
|
+
* (Q-M2a-4 sequenced it after the legacy loop that activated it); nothing in
|
|
22
|
+
* the graph answers a STOP any more, so the second scripted turn is never
|
|
23
|
+
* reached — this golden was byte-identical across the deletion.
|
|
24
|
+
*
|
|
25
|
+
* Regenerate ONLY after a deliberate behavior change:
|
|
26
|
+
* npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
30
|
+
import { toJson } from "@bufbuild/protobuf";
|
|
31
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
32
|
+
import {
|
|
33
|
+
ExecutionControlSignal,
|
|
34
|
+
ExecutionPhase,
|
|
35
|
+
MessageType,
|
|
36
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
37
|
+
|
|
38
|
+
vi.mock("../../../../shared/model-client.js", async () =>
|
|
39
|
+
(await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
|
|
40
|
+
);
|
|
41
|
+
vi.mock("../../../../client/stigmer-client.js", async () =>
|
|
42
|
+
(await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
import {
|
|
46
|
+
ScriptedClock,
|
|
47
|
+
createHermeticEnvironment,
|
|
48
|
+
type HermeticEnvironment,
|
|
49
|
+
} from "../../../../__test-utils__/hermetic-activity.js";
|
|
50
|
+
import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
|
|
51
|
+
import {
|
|
52
|
+
beginDeepAgentScenario,
|
|
53
|
+
deepAgentExecutionRecord,
|
|
54
|
+
runDeepAgentTurn,
|
|
55
|
+
} from "../../__test-utils__/hermetic-deep-agent.js";
|
|
56
|
+
|
|
57
|
+
const READ_CALL = { id: "call-hermetic-read-0001", name: "read_file", args: { file_path: "/notes.md" } };
|
|
58
|
+
const WRAP_UP = "Stopping here as asked.";
|
|
59
|
+
|
|
60
|
+
describe("ExecuteDeepAgent hermetic — platform STOP", () => {
|
|
61
|
+
let env: HermeticEnvironment;
|
|
62
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
63
|
+
const clock = new ScriptedClock();
|
|
64
|
+
|
|
65
|
+
beforeAll(() => {
|
|
66
|
+
env = createHermeticEnvironment();
|
|
67
|
+
registry = stubRegistryFetch();
|
|
68
|
+
clock.install();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
afterAll(() => {
|
|
72
|
+
clock.uninstall();
|
|
73
|
+
registry.restore();
|
|
74
|
+
env.dispose();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("stops the run at the STOP and completes with the platform-stop row (Q-S3-3)", async () => {
|
|
78
|
+
// ── Arrange ──────────────────────────────────────────────────────────────
|
|
79
|
+
let stopsAnswered = 0;
|
|
80
|
+
const record = deepAgentExecutionRecord({
|
|
81
|
+
message: "Look at my notes.",
|
|
82
|
+
controlSignal: (status) => {
|
|
83
|
+
if (status.messages.some((m) => m.toolCalls.length > 0)) {
|
|
84
|
+
stopsAnswered += 1;
|
|
85
|
+
return ExecutionControlSignal.STOP;
|
|
86
|
+
}
|
|
87
|
+
return ExecutionControlSignal.UNSPECIFIED;
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
const scenario = beginDeepAgentScenario({
|
|
91
|
+
env,
|
|
92
|
+
clock,
|
|
93
|
+
record,
|
|
94
|
+
script: () => ({
|
|
95
|
+
turns: [
|
|
96
|
+
{ text: "Let me look.", toolCalls: [READ_CALL], usage: { inputTokens: 1_200, outputTokens: 30 } },
|
|
97
|
+
{ text: WRAP_UP, usage: { inputTokens: 1_400, outputTokens: 10 } },
|
|
98
|
+
],
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ── Act ──────────────────────────────────────────────────────────────────
|
|
103
|
+
const invocation = await runDeepAgentTurn(scenario);
|
|
104
|
+
|
|
105
|
+
// ── Assert: the STOP was delivered, and the run stopped there ────────────
|
|
106
|
+
expect(stopsAnswered, "the platform said STOP at least once").toBeGreaterThan(0);
|
|
107
|
+
expect(invocation.outcome.kind, "a platform stop RETURNS").toBe("returned");
|
|
108
|
+
expect((invocation.outcome as { value: Record<string, unknown> }).value.phase).toBe("EXECUTION_COMPLETED");
|
|
109
|
+
expect(record.persistedPhases).toEqual([ExecutionPhase.EXECUTION_IN_PROGRESS, ExecutionPhase.EXECUTION_COMPLETED]);
|
|
110
|
+
const final = record.lastFullStatus!;
|
|
111
|
+
expect(final.error).toBe("");
|
|
112
|
+
expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
|
|
113
|
+
"Execution stopped by the platform.",
|
|
114
|
+
]);
|
|
115
|
+
const ai = final.messages.filter((m) => m.type === MessageType.MESSAGE_AI).map((m) => m.content);
|
|
116
|
+
expect(ai, "no wrap-up round and no injected notice: the run stopped at the STOP").toEqual(["Let me look.", ""]);
|
|
117
|
+
expect(ai).not.toContain(WRAP_UP);
|
|
118
|
+
|
|
119
|
+
// ── Assert: hermeticity ──────────────────────────────────────────────────
|
|
120
|
+
expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
|
|
121
|
+
|
|
122
|
+
// ── Assert: the golden ───────────────────────────────────────────────────
|
|
123
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
|
|
124
|
+
await expect(json).toMatchFileSnapshot("./goldens/platform-stop.status.json");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic golden: the TOOL-CALL BUDGET — `max_tool_rounds` exhausted by a
|
|
3
|
+
* model that keeps calling tools.
|
|
4
|
+
*
|
|
5
|
+
* What the arm does: `max_tool_rounds = 10` (the clamp floor,
|
|
6
|
+
* `shared/tool-rounds.ts` MIN_TOOL_ROUNDS) becomes LangGraph's
|
|
7
|
+
* `recursionLimit = 60` (SUPER_STEPS_PER_ROUND); the script proposes a
|
|
8
|
+
* DISTINCT `read_file` every round (distinct ids and paths, so the
|
|
9
|
+
* loop-detection middleware's "repetitive pattern" warning does not end the
|
|
10
|
+
* run first); the graph throws `GraphRecursionError`; the adapter's turn
|
|
11
|
+
* classifies it as the `tool_call_limit` outcome (`shared/tool-rounds.ts`
|
|
12
|
+
* `isGraphRecursionError`), and the runtime's `toolCallLimitArm` writes
|
|
13
|
+
* TERMINATED with the cross-repo prefix `TOOL_CALL_LIMIT_ERROR_PREFIX`
|
|
14
|
+
* (matched with `startsWith` by stigmer-cloud's `reply-extractor.ts`) and
|
|
15
|
+
* its row, PERSISTS it, and returns the slim.
|
|
16
|
+
*
|
|
17
|
+
* Ruled at Q-S3-6 and landed at S3 M2a. Until then the orchestrator RETURNED
|
|
18
|
+
* the TERMINATED status but never PERSISTED it (S3 M0 finding F-M0-4, a
|
|
19
|
+
* production defect): the last status the control plane held was the
|
|
20
|
+
* stream's mid-run IN_PROGRESS with no error, and only the activity's return
|
|
21
|
+
* value carried the truth. The golden
|
|
22
|
+
* (`goldens/recursion-limit.persisted.status.json`) now records the
|
|
23
|
+
* TERMINATED status the control plane holds, which is what that fix changed
|
|
24
|
+
* on purpose.
|
|
25
|
+
*
|
|
26
|
+
* Also visible here, F-M0-1 at scale: every tool row of the run sits on ONE
|
|
27
|
+
* empty AI message, because `ensureAiMessageForToolCall("")` creates it once
|
|
28
|
+
* and `currentAiMessage[""]` then catches every later row.
|
|
29
|
+
*
|
|
30
|
+
* How many rounds fit is the middleware stack's shape, not the knob's
|
|
31
|
+
* (S3 M2b, owner ruling 2026-09-13 on F-M2b-26): LangChain makes every
|
|
32
|
+
* middleware hook its own graph node, and `max_tool_rounds` becomes a
|
|
33
|
+
* super-step budget at the ×6 floor estimate, so a node fewer per round
|
|
34
|
+
* means more rounds within the same 60 steps. When `graceful-stop.ts` (an
|
|
35
|
+
* `afterModel` node) was deleted with Q-S3-3, this golden went from 11 tool
|
|
36
|
+
* calls to 13 before TERMINATED — the only hunk, the copy unchanged. That the
|
|
37
|
+
* knob counts super-steps and not rounds is recorded as an S5 design item
|
|
38
|
+
* (a round counter in the budget middleware would make it mean what it
|
|
39
|
+
* says); this file pins what the stack delivers today.
|
|
40
|
+
*
|
|
41
|
+
* Regenerate ONLY after a deliberate behavior change:
|
|
42
|
+
* npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
46
|
+
import { toJson } from "@bufbuild/protobuf";
|
|
47
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
48
|
+
import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
49
|
+
|
|
50
|
+
vi.mock("../../../../shared/model-client.js", async () =>
|
|
51
|
+
(await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
|
|
52
|
+
);
|
|
53
|
+
vi.mock("../../../../client/stigmer-client.js", async () =>
|
|
54
|
+
(await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
import {
|
|
58
|
+
ScriptedClock,
|
|
59
|
+
createHermeticEnvironment,
|
|
60
|
+
type HermeticEnvironment,
|
|
61
|
+
} from "../../../../__test-utils__/hermetic-activity.js";
|
|
62
|
+
import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
|
|
63
|
+
import { MIN_TOOL_ROUNDS } from "../../../../shared/tool-rounds.js";
|
|
64
|
+
import {
|
|
65
|
+
beginDeepAgentScenario,
|
|
66
|
+
deepAgentExecutionRecord,
|
|
67
|
+
runDeepAgentTurn,
|
|
68
|
+
} from "../../__test-utils__/hermetic-deep-agent.js";
|
|
69
|
+
import { TOOL_CALL_LIMIT_ERROR_PREFIX } from "../../../../shared/tool-rounds.js";
|
|
70
|
+
|
|
71
|
+
/** More rounds than the budget allows; the graph stops the script, not the other way round. */
|
|
72
|
+
const SCRIPTED_ROUNDS = 40;
|
|
73
|
+
|
|
74
|
+
describe("ExecuteDeepAgent hermetic — tool-call budget exhausted", () => {
|
|
75
|
+
let env: HermeticEnvironment;
|
|
76
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
77
|
+
const clock = new ScriptedClock();
|
|
78
|
+
|
|
79
|
+
beforeAll(() => {
|
|
80
|
+
env = createHermeticEnvironment();
|
|
81
|
+
registry = stubRegistryFetch();
|
|
82
|
+
clock.install();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
afterAll(() => {
|
|
86
|
+
clock.uninstall();
|
|
87
|
+
registry.restore();
|
|
88
|
+
env.dispose();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("returns TERMINATED with the cross-repo prefix, and persists nothing past IN_PROGRESS (F-M0-4)", async () => {
|
|
92
|
+
// ── Arrange ──────────────────────────────────────────────────────────────
|
|
93
|
+
const record = deepAgentExecutionRecord({ message: "Keep reading files.", maxToolRounds: MIN_TOOL_ROUNDS });
|
|
94
|
+
const scenario = beginDeepAgentScenario({
|
|
95
|
+
env,
|
|
96
|
+
clock,
|
|
97
|
+
record,
|
|
98
|
+
script: () => ({
|
|
99
|
+
turns: Array.from({ length: SCRIPTED_ROUNDS }, (_, i) => ({
|
|
100
|
+
text: `Reading file ${i}.`,
|
|
101
|
+
toolCalls: [{ id: `call-hermetic-loop-${String(i).padStart(4, "0")}`, name: "read_file", args: { file_path: `/f${i}.md` } }],
|
|
102
|
+
usage: { inputTokens: 1_000, outputTokens: 20 },
|
|
103
|
+
})),
|
|
104
|
+
}),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// ── Act ──────────────────────────────────────────────────────────────────
|
|
108
|
+
const invocation = await runDeepAgentTurn(scenario);
|
|
109
|
+
|
|
110
|
+
// ── Assert: the slim the workflow receives ───────────────────────────────
|
|
111
|
+
expect(invocation.outcome.kind).toBe("returned");
|
|
112
|
+
const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
|
|
113
|
+
expect(slim.phase).toBe("EXECUTION_TERMINATED");
|
|
114
|
+
expect(String(slim.error).startsWith(TOOL_CALL_LIMIT_ERROR_PREFIX), "the cross-repo prefix").toBe(true);
|
|
115
|
+
|
|
116
|
+
// ── Assert: what the control plane holds (F-M0-4 closed) ─────────────────
|
|
117
|
+
expect(record.persistedPhases, "the TERMINATED terminal is persisted").toEqual([
|
|
118
|
+
ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
119
|
+
ExecutionPhase.EXECUTION_TERMINATED,
|
|
120
|
+
]);
|
|
121
|
+
const persisted = record.lastFullStatus!;
|
|
122
|
+
expect(String(persisted.error).startsWith(TOOL_CALL_LIMIT_ERROR_PREFIX), "the persisted error carries the prefix").toBe(true);
|
|
123
|
+
expect(persisted.error, "the event count left the copy (Q-S3-6)").not.toMatch(/\d+ events?/);
|
|
124
|
+
expect(persisted.completedAt).not.toBe("");
|
|
125
|
+
const rows = record.toolCalls();
|
|
126
|
+
expect(rows.length, "fewer rounds ran than were scripted: the budget stopped the graph").toBeLessThan(SCRIPTED_ROUNDS);
|
|
127
|
+
expect(rows.length).toBeGreaterThanOrEqual(MIN_TOOL_ROUNDS);
|
|
128
|
+
const rowHosts = persisted.messages.filter((m) => m.type === MessageType.MESSAGE_AI && m.toolCalls.length > 0);
|
|
129
|
+
expect(rowHosts, "F-M0-1: every row on one empty AI message").toHaveLength(1);
|
|
130
|
+
expect(rowHosts[0].content).toBe("");
|
|
131
|
+
|
|
132
|
+
// ── Assert: hermeticity ──────────────────────────────────────────────────
|
|
133
|
+
expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
|
|
134
|
+
|
|
135
|
+
// ── Assert: the golden ───────────────────────────────────────────────────
|
|
136
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, persisted), null, 2) + "\n";
|
|
137
|
+
await expect(json).toMatchFileSnapshot("./goldens/recursion-limit.persisted.status.json");
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic golden: a RESOLUTION ERROR — the control plane rejects a read the
|
|
3
|
+
* setup depends on (`client.getAgent`) before any graph exists.
|
|
4
|
+
*
|
|
5
|
+
* Invariant pinned: the runtime's blueprint phase throws, the runtime's
|
|
6
|
+
* catch takes its generic-error arm (`terminal-table.ts` `unexpectedErrorArm`),
|
|
7
|
+
* persists ONE EXECUTION_FAILED status carrying
|
|
8
|
+
* `status.error = "Execution failed: [Error] <message>"` and two system rows
|
|
9
|
+
* — the boilerplate "Internal system error occurred. Please contact support
|
|
10
|
+
* if this issue persists." and `"Error details: [Error] <message>"` — and
|
|
11
|
+
* RETURNS the slim status (the workflow reads the phase; a throw would make
|
|
12
|
+
* Temporal retry a deterministic failure). Nothing streamed, no lock taken
|
|
13
|
+
* (the fault precedes the lock phase), no artifacts.
|
|
14
|
+
*
|
|
15
|
+
* The row shape is one of Q-S3-7's ruled alignments, landed at S3 M2a: the
|
|
16
|
+
* orchestrator wrote one row `"Error: [Error] <message>"`; the runtime's arm
|
|
17
|
+
* writes the boilerplate plus the details row. `status.error` itself did
|
|
18
|
+
* not move (the conformance suite pins it). The setup labels are the
|
|
19
|
+
* runtime's resolution phases' (a stated default of the M2a plan).
|
|
20
|
+
*
|
|
21
|
+
* Carried from `index.test.ts` ("returns EXECUTION_FAILED status when setup
|
|
22
|
+
* fails", "includes error message in failed status", "always returns a
|
|
23
|
+
* serializable result").
|
|
24
|
+
*
|
|
25
|
+
* Regenerate ONLY after a deliberate behavior change:
|
|
26
|
+
* npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
30
|
+
import { toJson } from "@bufbuild/protobuf";
|
|
31
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
32
|
+
import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
33
|
+
|
|
34
|
+
vi.mock("../../../../shared/model-client.js", async () =>
|
|
35
|
+
(await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
|
|
36
|
+
);
|
|
37
|
+
vi.mock("../../../../client/stigmer-client.js", async () =>
|
|
38
|
+
(await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
import {
|
|
42
|
+
ScriptedClock,
|
|
43
|
+
createHermeticEnvironment,
|
|
44
|
+
type HermeticEnvironment,
|
|
45
|
+
} from "../../../../__test-utils__/hermetic-activity.js";
|
|
46
|
+
import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
|
|
47
|
+
import {
|
|
48
|
+
beginDeepAgentScenario,
|
|
49
|
+
deepAgentExecutionRecord,
|
|
50
|
+
runDeepAgentTurn,
|
|
51
|
+
} from "../../__test-utils__/hermetic-deep-agent.js";
|
|
52
|
+
import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
|
|
53
|
+
|
|
54
|
+
const CONTROL_PLANE_FAULT = "hermetic fault injected at getAgent";
|
|
55
|
+
|
|
56
|
+
describe("ExecuteDeepAgent hermetic — resolution error", () => {
|
|
57
|
+
let env: HermeticEnvironment;
|
|
58
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
59
|
+
const clock = new ScriptedClock();
|
|
60
|
+
|
|
61
|
+
beforeAll(() => {
|
|
62
|
+
env = createHermeticEnvironment();
|
|
63
|
+
registry = stubRegistryFetch();
|
|
64
|
+
clock.install();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
afterAll(() => {
|
|
68
|
+
clock.uninstall();
|
|
69
|
+
registry.restore();
|
|
70
|
+
env.dispose();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("fails with the fault's message in status.error and one system row, and returns", async () => {
|
|
74
|
+
// ── Arrange ──────────────────────────────────────────────────────────────
|
|
75
|
+
const record = deepAgentExecutionRecord({ message: "Never reaches a model." });
|
|
76
|
+
const scenario = beginDeepAgentScenario({
|
|
77
|
+
env,
|
|
78
|
+
clock,
|
|
79
|
+
record,
|
|
80
|
+
script: () => {
|
|
81
|
+
throw new Error("the model must never be asked on a resolution failure");
|
|
82
|
+
},
|
|
83
|
+
clientOverrides: {
|
|
84
|
+
getAgent: vi.fn(async () => {
|
|
85
|
+
throw new Error(CONTROL_PLANE_FAULT);
|
|
86
|
+
}),
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ── Act ──────────────────────────────────────────────────────────────────
|
|
91
|
+
const invocation = await runDeepAgentTurn(scenario);
|
|
92
|
+
|
|
93
|
+
// ── Assert: outcome and phases ───────────────────────────────────────────
|
|
94
|
+
expect(invocation.outcome.kind, "a deterministic failure RETURNS; a retry would fail the same way").toBe(
|
|
95
|
+
"returned",
|
|
96
|
+
);
|
|
97
|
+
const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
|
|
98
|
+
expect(slim.phase).toBe("EXECUTION_FAILED");
|
|
99
|
+
expect(() => JSON.stringify(slim), "the return is serializable").not.toThrow();
|
|
100
|
+
expect(record.persistedPhases, "the one and only full persist").toEqual([ExecutionPhase.EXECUTION_FAILED]);
|
|
101
|
+
|
|
102
|
+
// ── Assert: the copy ─────────────────────────────────────────────────────
|
|
103
|
+
const final = record.lastFullStatus!;
|
|
104
|
+
expect(final.error).toBe(`Execution failed: [Error] ${CONTROL_PLANE_FAULT}`);
|
|
105
|
+
expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
|
|
106
|
+
"Internal system error occurred. Please contact support if this issue persists.",
|
|
107
|
+
`Error details: [Error] ${CONTROL_PLANE_FAULT}`,
|
|
108
|
+
]);
|
|
109
|
+
expect(final.messages, "the two system rows are the whole transcript").toHaveLength(2);
|
|
110
|
+
|
|
111
|
+
// ── Assert: nothing past the fault ───────────────────────────────────────
|
|
112
|
+
expect(recordedModelBuilds(), "no model was built").toHaveLength(0);
|
|
113
|
+
expect(record.setupProgress).toEqual(["Fetching execution", "Resolving agent blueprint"]);
|
|
114
|
+
|
|
115
|
+
// ── Assert: hermeticity ──────────────────────────────────────────────────
|
|
116
|
+
expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
|
|
117
|
+
|
|
118
|
+
// ── Assert: the golden ───────────────────────────────────────────────────
|
|
119
|
+
const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
|
|
120
|
+
await expect(json).toMatchFileSnapshot("./goldens/resolution-error.status.json");
|
|
121
|
+
});
|
|
122
|
+
});
|