@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,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermetic scenario: WORKSPACE LOCK TIMEOUT — a turn that cannot acquire its
|
|
3
|
+
* workspace within the configured wait fails with an actionable reason and
|
|
4
|
+
* RETURNS.
|
|
5
|
+
*
|
|
6
|
+
* Invariant pinned: the activity serializes on the workspace root
|
|
7
|
+
* (`shared/workspace/workspace-lock.ts`); while another turn holds the lock it
|
|
8
|
+
* reports a visible waiting state and heartbeats; past
|
|
9
|
+
* `Config.workspaceLockTimeoutMs` it maps `WorkspaceLockTimeoutError` to
|
|
10
|
+
* EXECUTION_FAILED with the lock's own message (which names the directory)
|
|
11
|
+
* and one system row, persists ONCE, and returns — a Temporal retry would only
|
|
12
|
+
* queue behind the same holder.
|
|
13
|
+
*
|
|
14
|
+
* The order, ruled at Q-S3-8 and landed at S3 M2a: the runtime takes the
|
|
15
|
+
* lock right after provisioning the workspace, BEFORE the tool surface, the
|
|
16
|
+
* skills, the attachments and the graph — so a turn that cannot have the
|
|
17
|
+
* tree builds no model and compiles no sub-agent. Until then the
|
|
18
|
+
* orchestrator took the lock AFTER the whole of `performSetup`. The setup
|
|
19
|
+
* labels are the runtime's resolution phases'; the adapter's own labels
|
|
20
|
+
* ("Connecting tools…", "Configuring sub-agents…", "Creating agent…") never
|
|
21
|
+
* appear, because the turn ends before the adapter runs.
|
|
22
|
+
*
|
|
23
|
+
* Why this is the one terminal arm WITHOUT a file golden (owner ruling,
|
|
24
|
+
* 2026-09-11, entry 20260911.03 M0; carried for native): the wire copy embeds
|
|
25
|
+
* the absolute workspace path, a per-run temp directory. The S0 rule is to
|
|
26
|
+
* control a volatile source at its origin or escalate — never redact — so
|
|
27
|
+
* this scenario pins every byte the path does not touch with explicit
|
|
28
|
+
* assertions and builds the expected message with the SAME error class over
|
|
29
|
+
* the real resolved path.
|
|
30
|
+
*
|
|
31
|
+
* Determinism: the lock wait is `waitedMs + pollIntervalMs > timeoutMs`, so a
|
|
32
|
+
* timeout below the 1 s poll interval fails on the FIRST contended attempt with
|
|
33
|
+
* no sleep; `waitedMs` is measured on the scripted clock, so it is 0.
|
|
34
|
+
*
|
|
35
|
+
* Regenerate: nothing to regenerate — no snapshot.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { mkdirSync } from "node:fs";
|
|
39
|
+
import { realpath } from "node:fs/promises";
|
|
40
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
41
|
+
import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
42
|
+
|
|
43
|
+
vi.mock("../../../../shared/model-client.js", async () =>
|
|
44
|
+
(await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
|
|
45
|
+
);
|
|
46
|
+
vi.mock("../../../../client/stigmer-client.js", async () =>
|
|
47
|
+
(await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
import {
|
|
51
|
+
ScriptedClock,
|
|
52
|
+
createHermeticEnvironment,
|
|
53
|
+
type HermeticEnvironment,
|
|
54
|
+
} from "../../../../__test-utils__/hermetic-activity.js";
|
|
55
|
+
import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
|
|
56
|
+
import {
|
|
57
|
+
WorkspaceLockTimeoutError,
|
|
58
|
+
acquireWorkspaceLock,
|
|
59
|
+
type ReleaseWorkspaceLock,
|
|
60
|
+
} from "../../../../shared/workspace/workspace-lock.js";
|
|
61
|
+
import {
|
|
62
|
+
beginDeepAgentScenario,
|
|
63
|
+
deepAgentExecutionRecord,
|
|
64
|
+
runDeepAgentTurn,
|
|
65
|
+
sessionWorkspaceDir,
|
|
66
|
+
} from "../../__test-utils__/hermetic-deep-agent.js";
|
|
67
|
+
import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
|
|
68
|
+
|
|
69
|
+
/** Below the lock's 1 s poll interval: the first contended attempt times out. */
|
|
70
|
+
const LOCK_TIMEOUT_MS = 250;
|
|
71
|
+
|
|
72
|
+
describe("ExecuteDeepAgent hermetic — workspace lock timeout", () => {
|
|
73
|
+
let env: HermeticEnvironment;
|
|
74
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
75
|
+
const clock = new ScriptedClock();
|
|
76
|
+
|
|
77
|
+
beforeAll(() => {
|
|
78
|
+
env = createHermeticEnvironment();
|
|
79
|
+
registry = stubRegistryFetch();
|
|
80
|
+
clock.install();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
afterAll(() => {
|
|
84
|
+
clock.uninstall();
|
|
85
|
+
registry.restore();
|
|
86
|
+
env.dispose();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("fails the turn with the lock's message when another turn holds the workspace", async () => {
|
|
90
|
+
// ── Arrange: another turn already holds this session's workspace ─────────
|
|
91
|
+
const record = deepAgentExecutionRecord({ message: "Never streams." });
|
|
92
|
+
const scenario = beginDeepAgentScenario({
|
|
93
|
+
env,
|
|
94
|
+
clock,
|
|
95
|
+
record,
|
|
96
|
+
script: () => {
|
|
97
|
+
throw new Error("the model must never be asked while the workspace is held");
|
|
98
|
+
},
|
|
99
|
+
config: { workspaceLockTimeoutMs: LOCK_TIMEOUT_MS },
|
|
100
|
+
});
|
|
101
|
+
// Created AFTER the scenario begins (which clears the session workspace)
|
|
102
|
+
// and BEFORE either side locks it, so both resolve the same realpath
|
|
103
|
+
// (macOS's /var -> /private/var) and contend on ONE key.
|
|
104
|
+
const workspaceDir = sessionWorkspaceDir(env);
|
|
105
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
106
|
+
const resolvedDir = await realpath(workspaceDir);
|
|
107
|
+
let releaseHeldLock: ReleaseWorkspaceLock | undefined = await acquireWorkspaceLock(workspaceDir);
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
// ── Act ────────────────────────────────────────────────────────────────
|
|
111
|
+
const invocation = await runDeepAgentTurn(scenario);
|
|
112
|
+
|
|
113
|
+
// ── Assert: outcome and phases ─────────────────────────────────────────
|
|
114
|
+
expect(invocation.outcome.kind, "a lock timeout RETURNS — a retry would queue behind the same holder").toBe(
|
|
115
|
+
"returned",
|
|
116
|
+
);
|
|
117
|
+
const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
|
|
118
|
+
expect(slim.phase).toBe("EXECUTION_FAILED");
|
|
119
|
+
expect(record.persistedPhases, "the one and only full persist").toEqual([ExecutionPhase.EXECUTION_FAILED]);
|
|
120
|
+
|
|
121
|
+
// ── Assert: the copy, built with the same class over the real path ─────
|
|
122
|
+
const expectedMessage = new WorkspaceLockTimeoutError(resolvedDir, 0).message;
|
|
123
|
+
const final = record.lastFullStatus!;
|
|
124
|
+
expect(final.error).toBe(expectedMessage);
|
|
125
|
+
expect(final.completedAt).not.toBe("");
|
|
126
|
+
expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
|
|
127
|
+
`Execution failed: ${expectedMessage}`,
|
|
128
|
+
]);
|
|
129
|
+
expect(final.messages, "the system row is the whole transcript").toHaveLength(1);
|
|
130
|
+
|
|
131
|
+
// ── Assert: the order — the lock is tried before the tool surface ─────
|
|
132
|
+
expect(record.setupProgress).toEqual([
|
|
133
|
+
"Fetching execution",
|
|
134
|
+
"Resolving agent blueprint",
|
|
135
|
+
"Resolving environment",
|
|
136
|
+
"Provisioning workspace",
|
|
137
|
+
"Waiting for workspace — in use by another session",
|
|
138
|
+
]);
|
|
139
|
+
expect(recordedModelBuilds(), "no model is built for a turn that cannot have the tree (Q-S3-8)").toHaveLength(0);
|
|
140
|
+
|
|
141
|
+
// ── Assert: hermeticity ────────────────────────────────────────────────
|
|
142
|
+
expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
|
|
143
|
+
// The runtime's heartbeat posture (Q-S3-8, parent Q8): every resolution
|
|
144
|
+
// phase pulses on entry and the terminal write pulses once, so a turn
|
|
145
|
+
// that ends at the lock has heartbeated before any stream existed.
|
|
146
|
+
expect(invocation.heartbeats.length, "the runtime heartbeats through resolution").toBeGreaterThan(0);
|
|
147
|
+
} finally {
|
|
148
|
+
await releaseHeldLock?.();
|
|
149
|
+
releaseHeldLock = undefined;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { Command } from "@langchain/langgraph";
|
|
3
|
-
import {
|
|
3
|
+
import { detectPendingInterrupts, resolveResumeInput, reconcileUnattendedSkips } from "../hitl.js";
|
|
4
4
|
import { ApprovalAction, ApprovalPolicySource, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
5
5
|
import { create } from "@bufbuild/protobuf";
|
|
6
6
|
import {
|
|
@@ -8,50 +8,19 @@ import {
|
|
|
8
8
|
ToolCallSchema,
|
|
9
9
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
10
10
|
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
11
|
-
import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
12
|
-
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
13
11
|
import type { GraphStateSnapshot } from "../hitl.js";
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
create(ToolCallSchema, {
|
|
27
|
-
id: tc.id,
|
|
28
|
-
name: "test_tool",
|
|
29
|
-
status: tc.status,
|
|
30
|
-
approvalAction: tc.approvalAction,
|
|
31
|
-
}),
|
|
32
|
-
),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
$typeName: "ai.stigmer.agentic.agentexecution.v1.AgentExecution",
|
|
37
|
-
$unknown: undefined,
|
|
38
|
-
metadata: undefined,
|
|
39
|
-
spec: {
|
|
40
|
-
$typeName: "ai.stigmer.agentic.agentexecution.v1.AgentExecutionSpec",
|
|
41
|
-
$unknown: undefined,
|
|
42
|
-
sessionId: "session-1",
|
|
43
|
-
agentId: "agent-1",
|
|
44
|
-
message: "test message",
|
|
45
|
-
executionConfig: undefined,
|
|
46
|
-
workspaceFileRefs: [],
|
|
47
|
-
callbackToken: new Uint8Array(),
|
|
48
|
-
autoApproveAll: false,
|
|
49
|
-
parentWorkflowId: "",
|
|
50
|
-
},
|
|
51
|
-
status: create(AgentExecutionStatusSchema, {
|
|
52
|
-
messages: [msg],
|
|
53
|
-
}),
|
|
54
|
-
} as unknown as AgentExecution;
|
|
13
|
+
/** The runtime's reading of the adjudicated rows (`approvalDecisionsOf`): a decision per WAITING tool-call id. */
|
|
14
|
+
function makeDecisions(
|
|
15
|
+
toolCalls: Array<{ id: string; status: ToolCallStatus; approvalAction: ApprovalAction }>,
|
|
16
|
+
): ReadonlyMap<string, ApprovalAction> {
|
|
17
|
+
const decisions = new Map<string, ApprovalAction>();
|
|
18
|
+
for (const tc of toolCalls) {
|
|
19
|
+
if (tc.status === ToolCallStatus.TOOL_CALL_WAITING_APPROVAL && tc.approvalAction !== ApprovalAction.UNSPECIFIED) {
|
|
20
|
+
decisions.set(tc.id, tc.approvalAction);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return decisions;
|
|
55
24
|
}
|
|
56
25
|
|
|
57
26
|
function makeGraphState(
|
|
@@ -70,29 +39,29 @@ function makeGraphState(
|
|
|
70
39
|
}
|
|
71
40
|
|
|
72
41
|
describe("resolveResumeInput", () => {
|
|
73
|
-
it("reports not-a-resume when no interrupts exist (caller
|
|
74
|
-
const
|
|
42
|
+
it("reports not-a-resume when no interrupts exist (the caller sends the turn's user message)", () => {
|
|
43
|
+
const decisions = makeDecisions([]);
|
|
75
44
|
const state: GraphStateSnapshot = { values: {}, tasks: [] };
|
|
76
45
|
|
|
77
|
-
const result = resolveResumeInput(
|
|
46
|
+
const result = resolveResumeInput(decisions, state);
|
|
78
47
|
|
|
79
48
|
expect(result.isResumeFromApproval).toBe(false);
|
|
80
49
|
// No graphInput on this branch — the turn's user message has exactly ONE
|
|
81
|
-
// construction site (
|
|
50
|
+
// construction site (the caller's), never a second copy here.
|
|
82
51
|
expect("graphInput" in result).toBe(false);
|
|
83
52
|
});
|
|
84
53
|
|
|
85
54
|
it("reports not-a-resume when interrupts exist but no decisions", () => {
|
|
86
|
-
const
|
|
55
|
+
const decisions = makeDecisions([]);
|
|
87
56
|
const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
|
|
88
57
|
|
|
89
|
-
const result = resolveResumeInput(
|
|
58
|
+
const result = resolveResumeInput(decisions, state);
|
|
90
59
|
|
|
91
60
|
expect(result.isResumeFromApproval).toBe(false);
|
|
92
61
|
});
|
|
93
62
|
|
|
94
63
|
it("builds Command(resume) when interrupts match decisions", () => {
|
|
95
|
-
const
|
|
64
|
+
const decisions = makeDecisions([{
|
|
96
65
|
id: "call-1",
|
|
97
66
|
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
98
67
|
approvalAction: ApprovalAction.APPROVE,
|
|
@@ -100,14 +69,14 @@ describe("resolveResumeInput", () => {
|
|
|
100
69
|
|
|
101
70
|
const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
|
|
102
71
|
|
|
103
|
-
const result = resolveResumeInput(
|
|
72
|
+
const result = resolveResumeInput(decisions, state);
|
|
104
73
|
|
|
105
74
|
if (!result.isResumeFromApproval) throw new Error("expected an approval resume");
|
|
106
75
|
expect(result.graphInput).toBeInstanceOf(Command);
|
|
107
76
|
});
|
|
108
77
|
|
|
109
78
|
it("builds a resume Command for a REJECT decision (denies the tool, does not fail the run)", () => {
|
|
110
|
-
const
|
|
79
|
+
const decisions = makeDecisions([{
|
|
111
80
|
id: "call-1",
|
|
112
81
|
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
113
82
|
approvalAction: ApprovalAction.REJECT,
|
|
@@ -115,7 +84,7 @@ describe("resolveResumeInput", () => {
|
|
|
115
84
|
|
|
116
85
|
const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
|
|
117
86
|
|
|
118
|
-
const result = resolveResumeInput(
|
|
87
|
+
const result = resolveResumeInput(decisions, state);
|
|
119
88
|
|
|
120
89
|
// REJECT resumes the gate like any other decision — the gate returns a
|
|
121
90
|
// denial ToolMessage and the run continues. There is no execution-level
|
|
@@ -126,7 +95,7 @@ describe("resolveResumeInput", () => {
|
|
|
126
95
|
});
|
|
127
96
|
|
|
128
97
|
it("handles multiple interrupts with mixed decisions", () => {
|
|
129
|
-
const
|
|
98
|
+
const decisions = makeDecisions([
|
|
130
99
|
{
|
|
131
100
|
id: "call-1",
|
|
132
101
|
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
@@ -144,13 +113,13 @@ describe("resolveResumeInput", () => {
|
|
|
144
113
|
{ taskId: "task-2", toolCallId: "call-2" },
|
|
145
114
|
]);
|
|
146
115
|
|
|
147
|
-
const result = resolveResumeInput(
|
|
116
|
+
const result = resolveResumeInput(decisions, state);
|
|
148
117
|
|
|
149
118
|
expect(result.isResumeFromApproval).toBe(true);
|
|
150
119
|
});
|
|
151
120
|
|
|
152
121
|
it("skips already-resumed interrupts", () => {
|
|
153
|
-
const
|
|
122
|
+
const decisions = makeDecisions([{
|
|
154
123
|
id: "call-1",
|
|
155
124
|
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
156
125
|
approvalAction: ApprovalAction.APPROVE,
|
|
@@ -160,82 +129,41 @@ describe("resolveResumeInput", () => {
|
|
|
160
129
|
{ taskId: "task-1", toolCallId: "call-1", hasResume: true },
|
|
161
130
|
]);
|
|
162
131
|
|
|
163
|
-
const result = resolveResumeInput(
|
|
132
|
+
const result = resolveResumeInput(decisions, state);
|
|
164
133
|
|
|
165
134
|
expect(result.isResumeFromApproval).toBe(false);
|
|
166
135
|
});
|
|
167
136
|
});
|
|
168
137
|
|
|
169
|
-
describe("
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}),
|
|
138
|
+
describe("detectPendingInterrupts", () => {
|
|
139
|
+
it("normalizes each un-resumed interrupt into a pending approval and skips resumed ones", () => {
|
|
140
|
+
const state: GraphStateSnapshot = {
|
|
141
|
+
values: {},
|
|
142
|
+
tasks: [
|
|
143
|
+
{
|
|
144
|
+
id: "task-1",
|
|
145
|
+
interrupts: [{
|
|
146
|
+
value: { tool_call_id: "call-1", tool_name: "shell", mcp_server_slug: "", message: "Run it?", policy_source: "classifier_default" },
|
|
147
|
+
}],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: "task-2",
|
|
151
|
+
interrupts: [{ value: { tool_call_id: "call-2", tool_name: "write_file", message: "Write?" }, resumeValue: { action: "approve" } }],
|
|
152
|
+
},
|
|
185
153
|
],
|
|
186
|
-
}
|
|
187
|
-
}
|
|
154
|
+
};
|
|
188
155
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
id: "call-reject",
|
|
192
|
-
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
193
|
-
approvalAction: ApprovalAction.REJECT,
|
|
194
|
-
}]);
|
|
195
|
-
|
|
196
|
-
reconcileNonExecutingDecisions(status);
|
|
197
|
-
|
|
198
|
-
const tc = status.messages[0].toolCalls[0];
|
|
199
|
-
expect(tc.status).toBe(ToolCallStatus.TOOL_CALL_SKIPPED);
|
|
200
|
-
expect(tc.error).toContain("Rejected by user");
|
|
201
|
-
// The REJECT decision is preserved so the audit trail stays honest.
|
|
202
|
-
expect(tc.approvalAction).toBe(ApprovalAction.REJECT);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it("terminalizes a SKIP decision to SKIPPED (fixes the stuck-WAITING for skip too)", () => {
|
|
206
|
-
const status = statusWith([{
|
|
207
|
-
id: "call-skip",
|
|
208
|
-
status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
|
|
209
|
-
approvalAction: ApprovalAction.SKIP,
|
|
210
|
-
}]);
|
|
211
|
-
|
|
212
|
-
reconcileNonExecutingDecisions(status);
|
|
213
|
-
|
|
214
|
-
expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_SKIPPED);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it("leaves APPROVE / APPROVE_ALL untouched (the tool executes)", () => {
|
|
218
|
-
const status = statusWith([
|
|
219
|
-
{ id: "call-approve", status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL, approvalAction: ApprovalAction.APPROVE },
|
|
220
|
-
{ id: "call-approve-all", status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL, approvalAction: ApprovalAction.APPROVE_ALL },
|
|
156
|
+
expect(detectPendingInterrupts(state)).toEqual([
|
|
157
|
+
{ toolCallId: "call-1", toolName: "shell", mcpServerSlug: "", message: "Run it?", policySource: "classifier_default" },
|
|
221
158
|
]);
|
|
222
|
-
|
|
223
|
-
reconcileNonExecutingDecisions(status);
|
|
224
|
-
|
|
225
|
-
// Still WAITING — real tool events (not this reconciler) terminalize them.
|
|
226
|
-
expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
227
|
-
expect(status.messages[0].toolCalls[1].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
228
159
|
});
|
|
229
160
|
|
|
230
|
-
it("
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
expect(() => reconcileNonExecutingDecisions(status)).not.toThrow();
|
|
238
|
-
expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
161
|
+
it("reads an absent policy source as undefined", () => {
|
|
162
|
+
const state: GraphStateSnapshot = {
|
|
163
|
+
values: {},
|
|
164
|
+
tasks: [{ id: "task-1", interrupts: [{ value: { tool_call_id: "call-1", tool_name: "shell", message: "Run it?" } }] }],
|
|
165
|
+
};
|
|
166
|
+
expect(detectPendingInterrupts(state)[0].policySource).toBeUndefined();
|
|
239
167
|
});
|
|
240
168
|
});
|
|
241
169
|
|
|
@@ -7,14 +7,16 @@ import { create } from "@bufbuild/protobuf";
|
|
|
7
7
|
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
8
8
|
import { ExecutionArtifactKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
9
9
|
import { InlinePublisher } from "../inline-publisher.js";
|
|
10
|
-
import {
|
|
10
|
+
import { V3StatusBuilder } from "../v3-status-builder.js";
|
|
11
11
|
import { LocalWorkspaceBackend } from "../../../shared/workspace/local-backend.js";
|
|
12
12
|
import type { ArtifactStorage } from "../../../shared/artifact-storage.js";
|
|
13
13
|
import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
|
|
14
14
|
import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// The publisher writes artifacts through the transcript builder's
|
|
17
|
+
// `ExecutionStatusWriter` face (`addArtifact`); the one builder since S3 M2b.
|
|
18
|
+
function makeStatusBuilder(): V3StatusBuilder {
|
|
19
|
+
return new V3StatusBuilder("exec-test", create(AgentExecutionStatusSchema, {}));
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function mockWorkspaceBackend(files: Record<string, string>): WorkspaceBackend {
|
|
@@ -53,7 +55,7 @@ function sha256(content: string): string {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
describe("InlinePublisher", () => {
|
|
56
|
-
let sb:
|
|
58
|
+
let sb: V3StatusBuilder;
|
|
57
59
|
let storage: ReturnType<typeof mockArtifactStorage>;
|
|
58
60
|
let backend: WorkspaceBackend;
|
|
59
61
|
let publisher: InlinePublisher;
|
|
@@ -207,7 +209,7 @@ describe("InlinePublisher with LocalWorkspaceBackend (disk-backed)", () => {
|
|
|
207
209
|
await mkdir(join(dir, "src"), { recursive: true });
|
|
208
210
|
await writeFile(join(dir, "src/app.ts"), "export const x = 42;", "utf-8");
|
|
209
211
|
|
|
210
|
-
const sb = new
|
|
212
|
+
const sb = new V3StatusBuilder("exec-disk", create(AgentExecutionStatusSchema, {}));
|
|
211
213
|
const storage = mockArtifactStorage();
|
|
212
214
|
const backend = new LocalWorkspaceBackend(dir);
|
|
213
215
|
|
|
@@ -235,7 +237,7 @@ describe("InlinePublisher with LocalWorkspaceBackend (disk-backed)", () => {
|
|
|
235
237
|
const dir = join(tmpdir(), `stigmer-publisher-test-${Date.now()}`);
|
|
236
238
|
await mkdir(dir, { recursive: true });
|
|
237
239
|
|
|
238
|
-
const sb = new
|
|
240
|
+
const sb = new V3StatusBuilder("exec-miss", create(AgentExecutionStatusSchema, {}));
|
|
239
241
|
const storage = mockArtifactStorage();
|
|
240
242
|
const backend = new LocalWorkspaceBackend(dir);
|
|
241
243
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* the workspace — an out-of-root name is simply nonexistent, and the
|
|
15
15
|
* `.stigmer` symlink keeps platform-dir reads addressable in-root.
|
|
16
16
|
*
|
|
17
|
-
* The graph here is composed exactly the way setup.ts composes the parent:
|
|
17
|
+
* The graph here is composed exactly the way turn-setup.ts composes the parent:
|
|
18
18
|
* the PRODUCTION buildMiddlewareStack (pathNormalization present on every
|
|
19
19
|
* graph) + the CAS capture backend + the PRODUCTION buildPlanModePermissions
|
|
20
20
|
* rules. These tests are also the empirical proof that langchain's
|
|
@@ -44,7 +44,7 @@ const OUTSIDE_CONTENT = "OUT_OF_ROOT_SECRET_TOKEN: must never cross the boundary
|
|
|
44
44
|
const PLATFORM_CONTENT = "PLATFORM_SKILL_TOKEN: reached through the .stigmer symlink";
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Build a plan-mode parent graph the way setup.ts does: the production
|
|
47
|
+
* Build a plan-mode parent graph the way turn-setup.ts does: the production
|
|
48
48
|
* middleware stack with pathNormalization set (derived, like the graph's
|
|
49
49
|
* permissions, from the plan-mode rules), a filesystem-only CAS capture
|
|
50
50
|
* backend (no shellEnv — plan mode clears it), and the production
|