@stigmer/runner 3.15.1 → 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
|
@@ -35,7 +35,7 @@ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/a
|
|
|
35
35
|
import { ApprovalAction, MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
36
36
|
import type { SDKMessage } from "@cursor/sdk";
|
|
37
37
|
|
|
38
|
-
import { approvalDecisionsOf } from "../../../harness/
|
|
38
|
+
import { approvalDecisionsOf } from "../../../harness/approval-decisions.js";
|
|
39
39
|
import { MessageAccumulator, reconcileDeniedToolCalls, toolCallIdentityToken } from "../message-translator.js";
|
|
40
40
|
import type { DeniedLedgerEntry } from "../approval-state.js";
|
|
41
41
|
|
|
@@ -83,7 +83,7 @@ function allToolCalls(messages: AgentMessage[]): ToolCall[] {
|
|
|
83
83
|
|
|
84
84
|
/** The later turn: the model proposes the same edit under a fresh id, the hook denies it, the turn boundary reconciles. */
|
|
85
85
|
async function laterTurnProposesSameEdit(seeded: AgentMessage[]): Promise<ToolCall[]> {
|
|
86
|
-
const acc = new MessageAccumulator(seeded, {
|
|
86
|
+
const acc = new MessageAccumulator(seeded, {});
|
|
87
87
|
acc.processEvent(toolCallEvent(LATER_ID, "running"));
|
|
88
88
|
acc.processEvent(toolCallEvent(LATER_ID, "error", "Blocked by hook"));
|
|
89
89
|
acc.finalize();
|
|
@@ -158,7 +158,7 @@ describe("a later same-identity proposal never lands on a decided row (F9)", ()
|
|
|
158
158
|
}),
|
|
159
159
|
];
|
|
160
160
|
|
|
161
|
-
const acc = new MessageAccumulator(seeded, {
|
|
161
|
+
const acc = new MessageAccumulator(seeded, {});
|
|
162
162
|
acc.processEvent(toolCallEvent(`${FIRST_ID}_RESUME`, "running"));
|
|
163
163
|
acc.processEvent(toolCallEvent(`${FIRST_ID}_RESUME`, "completed", RESULT_OF_FIRST));
|
|
164
164
|
acc.finalize();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @regression file-hitl-phase0 — pins file-edit HITL fix #2 (see _projects/2026-06/20260630.01.file-change-hitl-redesign/tasks/T01_3_regression-manifest.md)
|
|
3
3
|
*
|
|
4
|
-
* Cursor analog of execute-deep-agent/__tests__/sequential-
|
|
4
|
+
* Cursor analog of execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts:
|
|
5
5
|
* two SEQUENTIAL approval gates across a resume, on the Cursor deny-and-reconcile
|
|
6
6
|
* harness instead of the native in-process gate.
|
|
7
7
|
*
|
|
@@ -139,7 +139,7 @@ describe("Cursor sequential gates A->B across resume", () => {
|
|
|
139
139
|
const committed = approvedGateA();
|
|
140
140
|
const seeded = committed.map((m) => clone(AgentMessageSchema, m));
|
|
141
141
|
|
|
142
|
-
const acc = new MessageAccumulator(seeded, {
|
|
142
|
+
const acc = new MessageAccumulator(seeded, {});
|
|
143
143
|
for (const event of resumeIntoGateB()) acc.processEvent(event);
|
|
144
144
|
acc.finalize();
|
|
145
145
|
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for the extracted turn boundary (turn-boundary.ts) — the post-run
|
|
3
|
-
* pipeline shared by the primary path and the recovery retries
|
|
3
|
+
* pipeline shared by the primary path and the recovery retries: the hook's
|
|
4
|
+
* denials become WAITING_APPROVAL gates, unattended and secret denials are
|
|
5
|
+
* attributed and settled, a foreign hook's block is reported (#205), and a
|
|
6
|
+
* row that hung inside the harness on a completing turn is settled and
|
|
7
|
+
* disclosed (#965).
|
|
4
8
|
*
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The turn's FILE CHANGES are not the boundary's since S3 M4: the runtime
|
|
10
|
+
* captures them once after `runTurn` returns (`harness/capture.ts`, proven
|
|
11
|
+
* in `harness/__tests__/capture.test.ts` and the kit's runtime arm), so the
|
|
12
|
+
* five capture arms this file carried until then — the candidate, the clean
|
|
13
|
+
* turn, the missing baseline, the recovery re-entry authoring exactly once,
|
|
14
|
+
* the full-ledger stamp exclusion — live there now, restated for the
|
|
15
|
+
* runtime's status-based rules. One arm changed meaning with the lift and is
|
|
16
|
+
* pinned below: a turn whose only pause would have been a file review is a
|
|
17
|
+
* COMPLETING turn to this boundary, so its hung rows are settled before the
|
|
18
|
+
* runtime's review, not after it (F-M4-P9, Q-M4-11).
|
|
19
|
+
*
|
|
20
|
+
* Runs against a temp workspace dir with in-memory transcript + status
|
|
21
|
+
* protos; the gate reads a denied file's `before` from that dir.
|
|
12
22
|
*/
|
|
13
23
|
|
|
14
24
|
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
15
|
-
import { execFile } from "node:child_process";
|
|
16
25
|
import { tmpdir } from "node:os";
|
|
17
26
|
import { join } from "node:path";
|
|
18
|
-
import { promisify } from "node:util";
|
|
19
27
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
20
28
|
import { create, type JsonObject } from "@bufbuild/protobuf";
|
|
21
29
|
import {
|
|
@@ -25,26 +33,17 @@ import {
|
|
|
25
33
|
import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
26
34
|
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
27
35
|
import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
MessageType,
|
|
31
|
-
ToolCallStatus,
|
|
32
|
-
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
33
|
-
import { captureBaselineToLedger } from "../capture-flow.js";
|
|
36
|
+
import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
37
|
+
import { isToolCallRowHidden } from "../../../shared/tool-row.js";
|
|
34
38
|
import { denialLedgerPath } from "../approval-state.js";
|
|
35
39
|
import { toolCallIdentityToken, UNRESOLVED_TOOL_CALL_ERROR } from "../message-translator.js";
|
|
36
40
|
import { runTurnBoundary, type TurnBoundaryOptions } from "../turn-boundary.js";
|
|
37
41
|
|
|
38
|
-
const execFileAsync = promisify(execFile);
|
|
39
42
|
const EXEC_ID = "exec-boundary-1";
|
|
40
|
-
const CHANGE_SET_ID = `${EXEC_ID}:0`;
|
|
41
43
|
|
|
42
44
|
let repo: string;
|
|
43
45
|
let hitlDir: string;
|
|
44
46
|
|
|
45
|
-
async function git(args: string[]): Promise<void> {
|
|
46
|
-
await execFileAsync("git", args, { cwd: repo });
|
|
47
|
-
}
|
|
48
47
|
async function write(rel: string, content: string): Promise<void> {
|
|
49
48
|
await writeFile(join(repo, rel), content, "utf-8");
|
|
50
49
|
}
|
|
@@ -68,46 +67,39 @@ function streamedEdit(id: string, path: string, content: string): AgentMessage {
|
|
|
68
67
|
});
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
/** Boundary options for this
|
|
72
|
-
function boundaryOpts(
|
|
73
|
-
status: AgentExecutionStatus,
|
|
74
|
-
baselineTree: string,
|
|
75
|
-
overrides?: Partial<TurnBoundaryOptions>,
|
|
76
|
-
): TurnBoundaryOptions {
|
|
70
|
+
/** Boundary options for this turn; overrides layer the per-test shape. */
|
|
71
|
+
function boundaryOpts(status: AgentExecutionStatus, overrides?: Partial<TurnBoundaryOptions>): TurnBoundaryOptions {
|
|
77
72
|
return {
|
|
78
73
|
status,
|
|
79
74
|
executionId: EXEC_ID,
|
|
80
|
-
changeSetId: CHANGE_SET_ID,
|
|
81
75
|
hitlDir,
|
|
82
|
-
captureMode: true,
|
|
83
|
-
baselineTree,
|
|
84
76
|
primaryWorkspaceDir: repo,
|
|
85
|
-
gitWorkspace: true,
|
|
86
77
|
turnStartMessageIndex: 0,
|
|
87
|
-
approvalGrants: undefined,
|
|
88
|
-
globalBypass: false,
|
|
89
|
-
seededSubAgents: [],
|
|
90
|
-
artifactStorage: undefined,
|
|
91
78
|
mergedPolicies: new Map(),
|
|
92
79
|
...overrides,
|
|
93
80
|
};
|
|
94
81
|
}
|
|
95
82
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
83
|
+
/** A FAILED tool call carrying Cursor's generic hook-block error text (#205). */
|
|
84
|
+
function hookBlockedCall(id: string, name: string, args: JsonObject) {
|
|
85
|
+
return create(ToolCallSchema, {
|
|
86
|
+
id,
|
|
87
|
+
name,
|
|
88
|
+
status: ToolCallStatus.TOOL_CALL_FAILED,
|
|
89
|
+
error: "Command blocked by a hook.",
|
|
90
|
+
args,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Append one entry to this turn's denial ledger. */
|
|
95
|
+
async function appendLedgerEntry(entry: Record<string, unknown>): Promise<void> {
|
|
96
|
+
await writeFile(denialLedgerPath(hitlDir), JSON.stringify(entry) + "\n", { flag: "a" });
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
beforeEach(async () => {
|
|
103
100
|
repo = await mkdtemp(join(tmpdir(), "stigmer-boundary-repo-"));
|
|
104
101
|
hitlDir = await mkdtemp(join(tmpdir(), "stigmer-boundary-hitl-"));
|
|
105
|
-
await git(["init", "-q"]);
|
|
106
|
-
await git(["config", "user.email", "t@t.local"]);
|
|
107
|
-
await git(["config", "user.name", "t"]);
|
|
108
102
|
await write("notes.md", "original notes\n");
|
|
109
|
-
await git(["add", "-A"]);
|
|
110
|
-
await git(["commit", "-q", "-m", "initial"]);
|
|
111
103
|
});
|
|
112
104
|
|
|
113
105
|
afterEach(async () => {
|
|
@@ -116,98 +108,8 @@ afterEach(async () => {
|
|
|
116
108
|
});
|
|
117
109
|
|
|
118
110
|
describe("runTurnBoundary", () => {
|
|
119
|
-
it("authors a candidate, stamps the row, and pauses when the turn edited files", async () => {
|
|
120
|
-
const status = newStatus();
|
|
121
|
-
const baseline = await captureBaselineToLedger({
|
|
122
|
-
status,
|
|
123
|
-
gitRoot: repo,
|
|
124
|
-
executionId: EXEC_ID,
|
|
125
|
-
changeSetId: CHANGE_SET_ID,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
await write("notes.md", "original notes\n\n## TODO\n- ship\n");
|
|
129
|
-
status.messages.push(
|
|
130
|
-
streamedEdit("tc-1", "notes.md", "original notes\n\n## TODO\n- ship\n"),
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const result = await runTurnBoundary(boundaryOpts(status, baseline));
|
|
134
|
-
|
|
135
|
-
expect(result.waiting).toBe(true);
|
|
136
|
-
expect(result.capturedChangeCount).toBe(1);
|
|
137
|
-
expect(result.deniedToolCallCount).toBe(0);
|
|
138
|
-
expect(candidateEvents(status)).toHaveLength(1);
|
|
139
|
-
// The streamed row is stamped with the change set id (observational record
|
|
140
|
-
// anchoring the decision surface).
|
|
141
|
-
expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("reports a clean turn when nothing changed (no candidate, no pause)", async () => {
|
|
145
|
-
const status = newStatus();
|
|
146
|
-
const baseline = await captureBaselineToLedger({
|
|
147
|
-
status,
|
|
148
|
-
gitRoot: repo,
|
|
149
|
-
executionId: EXEC_ID,
|
|
150
|
-
changeSetId: CHANGE_SET_ID,
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
const result = await runTurnBoundary(boundaryOpts(status, baseline));
|
|
154
|
-
|
|
155
|
-
expect(result.waiting).toBe(false);
|
|
156
|
-
expect(result.capturedChangeCount).toBe(0);
|
|
157
|
-
expect(result.deniedToolCallCount).toBe(0);
|
|
158
|
-
expect(candidateEvents(status)).toHaveLength(0);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("skips capture when no baseline was authored this turn", async () => {
|
|
162
|
-
const status = newStatus();
|
|
163
|
-
await write("notes.md", "edited without a baseline\n");
|
|
164
|
-
|
|
165
|
-
const result = await runTurnBoundary(
|
|
166
|
-
boundaryOpts(status, "", { baselineTree: undefined }),
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
expect(result.waiting).toBe(false);
|
|
170
|
-
expect(result.capturedChangeCount).toBe(0);
|
|
171
|
-
expect(candidateEvents(status)).toHaveLength(0);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("re-entered after a no-op primary call, authors the candidate exactly once (recovery-retry sequence)", async () => {
|
|
175
|
-
const status = newStatus();
|
|
176
|
-
const baseline = await captureBaselineToLedger({
|
|
177
|
-
status,
|
|
178
|
-
gitRoot: repo,
|
|
179
|
-
executionId: EXEC_ID,
|
|
180
|
-
changeSetId: CHANGE_SET_ID,
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// Primary boundary: the resumed agent errored before touching anything —
|
|
184
|
-
// the tree is at baseline, no candidate is authored, the turn looks clean.
|
|
185
|
-
const primary = await runTurnBoundary(boundaryOpts(status, baseline));
|
|
186
|
-
expect(primary.waiting).toBe(false);
|
|
187
|
-
expect(candidateEvents(status)).toHaveLength(0);
|
|
188
|
-
|
|
189
|
-
// Recovery retry: a fresh agent re-ran the prompt and created the file.
|
|
190
|
-
await write("notes.md", "original notes\n\nretry made this edit\n");
|
|
191
|
-
status.messages.push(
|
|
192
|
-
streamedEdit("tc-retry", "notes.md", "original notes\n\nretry made this edit\n"),
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
// Boundary re-entry: the retry's edit reaches the ledger and arms the gate.
|
|
196
|
-
const retry = await runTurnBoundary(boundaryOpts(status, baseline));
|
|
197
|
-
expect(retry.waiting).toBe(true);
|
|
198
|
-
expect(retry.capturedChangeCount).toBe(1);
|
|
199
|
-
expect(candidateEvents(status)).toHaveLength(1);
|
|
200
|
-
expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
111
|
it("surfaces a hook denial as a WAITING_APPROVAL gate and pauses", async () => {
|
|
204
112
|
const status = newStatus();
|
|
205
|
-
const baseline = await captureBaselineToLedger({
|
|
206
|
-
status,
|
|
207
|
-
gitRoot: repo,
|
|
208
|
-
executionId: EXEC_ID,
|
|
209
|
-
changeSetId: CHANGE_SET_ID,
|
|
210
|
-
});
|
|
211
113
|
|
|
212
114
|
// The hook gated a shell command mid-turn; the streamed call is still
|
|
213
115
|
// RUNNING (Cursor reported the deny to the model, not a completion).
|
|
@@ -230,37 +132,17 @@ describe("runTurnBoundary", () => {
|
|
|
230
132
|
"utf-8",
|
|
231
133
|
);
|
|
232
134
|
|
|
233
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
135
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
234
136
|
|
|
235
137
|
expect(result.waiting).toBe(true);
|
|
236
138
|
expect(result.deniedToolCallCount).toBe(1);
|
|
237
|
-
expect(result.capturedChangeCount).toBe(0);
|
|
238
139
|
expect(shellCall.status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
239
140
|
});
|
|
240
141
|
|
|
241
142
|
// ── Issue #205: unattributed hook blocks and the kind split ────────────────
|
|
242
143
|
|
|
243
|
-
/** A FAILED tool call carrying Cursor's generic hook-block error text. */
|
|
244
|
-
function hookBlockedCall(id: string, name: string, args: JsonObject) {
|
|
245
|
-
return create(ToolCallSchema, {
|
|
246
|
-
id,
|
|
247
|
-
name,
|
|
248
|
-
status: ToolCallStatus.TOOL_CALL_FAILED,
|
|
249
|
-
error: "Command blocked by a hook.",
|
|
250
|
-
args,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/** Append one entry to this turn's denial ledger. */
|
|
255
|
-
async function appendLedgerEntry(entry: Record<string, unknown>): Promise<void> {
|
|
256
|
-
await writeFile(denialLedgerPath(hitlDir), JSON.stringify(entry) + "\n", { flag: "a" });
|
|
257
|
-
}
|
|
258
|
-
|
|
259
144
|
it("reports a foreign hook block on a non-pausing turn (the #205 silent-complete shape)", async () => {
|
|
260
145
|
const status = newStatus();
|
|
261
|
-
const baseline = await captureBaselineToLedger({
|
|
262
|
-
status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
|
|
263
|
-
});
|
|
264
146
|
|
|
265
147
|
// A foreign .cursor/hooks.json hook denied the write: Cursor stamped its
|
|
266
148
|
// generic error, our ledger stayed empty, the tree is untouched. Before
|
|
@@ -272,7 +154,7 @@ describe("runTurnBoundary", () => {
|
|
|
272
154
|
);
|
|
273
155
|
|
|
274
156
|
const result = await runTurnBoundary(
|
|
275
|
-
boundaryOpts(status,
|
|
157
|
+
boundaryOpts(status, { foreignGatingHooks: ["./team-policy.sh"] }),
|
|
276
158
|
);
|
|
277
159
|
|
|
278
160
|
expect(result.waiting).toBe(false);
|
|
@@ -286,9 +168,6 @@ describe("runTurnBoundary", () => {
|
|
|
286
168
|
|
|
287
169
|
it("attributes a secret hard-block (kind:'secret'): no pause, no false foreign-hook report", async () => {
|
|
288
170
|
const status = newStatus();
|
|
289
|
-
const baseline = await captureBaselineToLedger({
|
|
290
|
-
status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
|
|
291
|
-
});
|
|
292
171
|
|
|
293
172
|
const secretRow = hookBlockedCall("tc-secret", "edit", { path: ".env" });
|
|
294
173
|
status.messages.push(
|
|
@@ -302,7 +181,7 @@ describe("runTurnBoundary", () => {
|
|
|
302
181
|
"utf-8",
|
|
303
182
|
);
|
|
304
183
|
|
|
305
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
184
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
306
185
|
|
|
307
186
|
// Not a pause (the agent was told to move on), not a foreign block (our
|
|
308
187
|
// own kinded entry attributes it), and never a WAITING_APPROVAL overlay.
|
|
@@ -314,9 +193,6 @@ describe("runTurnBoundary", () => {
|
|
|
314
193
|
|
|
315
194
|
it("mixed turn: pauses on our anchor while still reporting the foreign block", async () => {
|
|
316
195
|
const status = newStatus();
|
|
317
|
-
const baseline = await captureBaselineToLedger({
|
|
318
|
-
status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
|
|
319
|
-
});
|
|
320
196
|
|
|
321
197
|
const ourGated = create(ToolCallSchema, {
|
|
322
198
|
id: "tc-ours", name: "shell",
|
|
@@ -329,7 +205,7 @@ describe("runTurnBoundary", () => {
|
|
|
329
205
|
);
|
|
330
206
|
await appendLedgerEntry({ toolName: "shell", token: toolCallIdentityToken(ourGated), kind: "approval" });
|
|
331
207
|
|
|
332
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
208
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
333
209
|
|
|
334
210
|
// The pause wins (a pausing turn is never silent); the foreign block is
|
|
335
211
|
// still surfaced so the caller can log it next to the approval.
|
|
@@ -338,41 +214,8 @@ describe("runTurnBoundary", () => {
|
|
|
338
214
|
expect(result.unattributedHookBlocks.map((b) => b.toolCallId)).toEqual(["tc-theirs"]);
|
|
339
215
|
});
|
|
340
216
|
|
|
341
|
-
it("excludes a kinded (secret) deny from the flowed-edit stamp (full-ledger deniedTokens)", async () => {
|
|
342
|
-
const status = newStatus();
|
|
343
|
-
const baseline = await captureBaselineToLedger({
|
|
344
|
-
status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
// One edit genuinely flowed (tree changed + streamed row); one secret-like
|
|
348
|
-
// write was hard-blocked (FAILED row + kind:"secret" entry, tree untouched).
|
|
349
|
-
await write("notes.md", "original notes\nplus a real edit\n");
|
|
350
|
-
status.messages.push(streamedEdit("tc-flowed", "notes.md", "original notes\nplus a real edit\n"));
|
|
351
|
-
const secretRow = hookBlockedCall("tc-secret", "edit", { path: ".env" });
|
|
352
|
-
status.messages.push(
|
|
353
|
-
create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, toolCalls: [secretRow] }),
|
|
354
|
-
);
|
|
355
|
-
await appendLedgerEntry({ toolName: "Write", token: toolCallIdentityToken(secretRow), kind: "secret" });
|
|
356
|
-
|
|
357
|
-
const result = await runTurnBoundary(boundaryOpts(status, baseline));
|
|
358
|
-
|
|
359
|
-
// The flowed edit is captured + stamped; the secret-blocked row is NOT
|
|
360
|
-
// stamped into a change set that does not contain its file — every ledger
|
|
361
|
-
// kind means "this action did not execute", so the stamp uses the FULL set.
|
|
362
|
-
expect(result.waiting).toBe(true);
|
|
363
|
-
expect(result.capturedChangeCount).toBe(1);
|
|
364
|
-
expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
|
|
365
|
-
expect(secretRow.fileChangeSetId).toBe("");
|
|
366
|
-
});
|
|
367
|
-
|
|
368
217
|
it("waits for the denial-stop cancel to settle before reading the ledger", async () => {
|
|
369
218
|
const status = newStatus();
|
|
370
|
-
const baseline = await captureBaselineToLedger({
|
|
371
|
-
status,
|
|
372
|
-
gitRoot: repo,
|
|
373
|
-
executionId: EXEC_ID,
|
|
374
|
-
changeSetId: CHANGE_SET_ID,
|
|
375
|
-
});
|
|
376
219
|
|
|
377
220
|
const shellCall = create(ToolCallSchema, {
|
|
378
221
|
id: "tc-late",
|
|
@@ -398,7 +241,7 @@ describe("runTurnBoundary", () => {
|
|
|
398
241
|
})();
|
|
399
242
|
|
|
400
243
|
const result = await runTurnBoundary(
|
|
401
|
-
boundaryOpts(status,
|
|
244
|
+
boundaryOpts(status, { denialCancelSettled }),
|
|
402
245
|
);
|
|
403
246
|
|
|
404
247
|
expect(result.deniedToolCallCount).toBe(1);
|
|
@@ -431,15 +274,9 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
|
|
|
431
274
|
|
|
432
275
|
it("settles the incident shape to INTERRUPTED and discloses it (regression: aex_01m1a6ww)", async () => {
|
|
433
276
|
const status = newStatus();
|
|
434
|
-
const baseline = await captureBaselineToLedger({
|
|
435
|
-
status,
|
|
436
|
-
gitRoot: repo,
|
|
437
|
-
executionId: EXEC_ID,
|
|
438
|
-
changeSetId: CHANGE_SET_ID,
|
|
439
|
-
});
|
|
440
277
|
status.messages.push(hangingGenerateImage("tc-genimage-1"));
|
|
441
278
|
|
|
442
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
279
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
443
280
|
|
|
444
281
|
// The turn completes (no pause) — but not silently.
|
|
445
282
|
expect(result.waiting).toBe(false);
|
|
@@ -461,39 +298,52 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
|
|
|
461
298
|
expect(last.content).toContain("No approval is pending");
|
|
462
299
|
});
|
|
463
300
|
|
|
464
|
-
it("leaves non-terminal rows to the pause machinery on a PAUSING turn", async () => {
|
|
301
|
+
it("leaves non-terminal rows to the pause machinery on a PAUSING turn (a denial pauses)", async () => {
|
|
465
302
|
const status = newStatus();
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
303
|
+
// Our hook denied a shell — the turn pauses for that approval…
|
|
304
|
+
const ourGated = create(ToolCallSchema, {
|
|
305
|
+
id: "tc-ours", name: "shell",
|
|
306
|
+
status: ToolCallStatus.TOOL_CALL_RUNNING,
|
|
307
|
+
args: { command: "rm -rf build" },
|
|
471
308
|
});
|
|
472
|
-
|
|
473
|
-
await
|
|
474
|
-
status.messages.push(
|
|
475
|
-
streamedEdit("tc-edit-1", "notes.md", "original notes\npaused-turn edit\n"),
|
|
476
|
-
);
|
|
309
|
+
status.messages.push(create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, toolCalls: [ourGated] }));
|
|
310
|
+
await appendLedgerEntry({ toolName: "shell", token: toolCallIdentityToken(ourGated), kind: "approval" });
|
|
477
311
|
// …while a hanging row rides the same turn.
|
|
478
312
|
status.messages.push(hangingGenerateImage("tc-genimage-2"));
|
|
479
313
|
|
|
480
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
314
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
481
315
|
|
|
482
316
|
expect(result.waiting).toBe(true);
|
|
483
317
|
expect(result.settledUnresolvedCount).toBe(0);
|
|
484
|
-
// Untouched by THIS sweep
|
|
485
|
-
// collapse machinery, which has its own treatment for
|
|
486
|
-
|
|
318
|
+
// Untouched by THIS sweep: a pausing turn's rows belong to the reconcile /
|
|
319
|
+
// collapse machinery, which has its own treatment for an attempt that
|
|
320
|
+
// streamed after the gate (the hidden SKIPPED twin), never #965's
|
|
321
|
+
// INTERRUPTED-with-disclosure.
|
|
322
|
+
const hung = status.messages[1].toolCalls[0];
|
|
323
|
+
expect(hung.status).not.toBe(ToolCallStatus.TOOL_CALL_INTERRUPTED);
|
|
324
|
+
expect(isToolCallRowHidden(hung), "collapsed by the reconcile, not settled by the sweep").toBe(true);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it("a turn whose only change is a flowed file edit is COMPLETING here: the hung row is settled before the runtime's review (F-M4-P9)", async () => {
|
|
328
|
+
const status = newStatus();
|
|
329
|
+
// The edit flowed and the tree changed — until S3 M4 that made the turn
|
|
330
|
+
// `waiting` and hid the hung row behind the review; the runtime captures
|
|
331
|
+
// the edit after this boundary, so the boundary now tells the truth
|
|
332
|
+
// about the row first.
|
|
333
|
+
await write("notes.md", "original notes\nflowed edit\n");
|
|
334
|
+
status.messages.push(streamedEdit("tc-edit-1", "notes.md", "original notes\nflowed edit\n"));
|
|
335
|
+
status.messages.push(hangingGenerateImage("tc-genimage-2"));
|
|
336
|
+
|
|
337
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
338
|
+
|
|
339
|
+
expect(result.waiting).toBe(false);
|
|
340
|
+
expect(result.settledUnresolvedCount).toBe(1);
|
|
341
|
+
expect(status.messages[1].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_INTERRUPTED);
|
|
342
|
+
expect(status.messages[0].toolCalls[0].fileChangeSetId, "the stamp is the runtime's, after this boundary").toBe("");
|
|
487
343
|
});
|
|
488
344
|
|
|
489
345
|
it("never settles a ledger-attributed row — that is the kinded machinery's call", async () => {
|
|
490
346
|
const status = newStatus();
|
|
491
|
-
const baseline = await captureBaselineToLedger({
|
|
492
|
-
status,
|
|
493
|
-
gitRoot: repo,
|
|
494
|
-
executionId: EXEC_ID,
|
|
495
|
-
changeSetId: CHANGE_SET_ID,
|
|
496
|
-
});
|
|
497
347
|
const secretWrite = create(ToolCallSchema, {
|
|
498
348
|
id: "tc-secret-1",
|
|
499
349
|
name: "edit",
|
|
@@ -515,7 +365,7 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
|
|
|
515
365
|
"utf-8",
|
|
516
366
|
);
|
|
517
367
|
|
|
518
|
-
const result = await runTurnBoundary(boundaryOpts(status
|
|
368
|
+
const result = await runTurnBoundary(boundaryOpts(status));
|
|
519
369
|
|
|
520
370
|
expect(result.settledUnresolvedCount).toBe(0);
|
|
521
371
|
expect(secretWrite.status).toBe(ToolCallStatus.TOOL_CALL_PENDING);
|
|
@@ -523,12 +373,6 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
|
|
|
523
373
|
|
|
524
374
|
it("scopes to THIS turn: seeded prior-turn rows and terminal rows are untouched", async () => {
|
|
525
375
|
const status = newStatus();
|
|
526
|
-
const baseline = await captureBaselineToLedger({
|
|
527
|
-
status,
|
|
528
|
-
gitRoot: repo,
|
|
529
|
-
executionId: EXEC_ID,
|
|
530
|
-
changeSetId: CHANGE_SET_ID,
|
|
531
|
-
});
|
|
532
376
|
// Message 0 is seeded prior-turn context (already adjudicated elsewhere).
|
|
533
377
|
status.messages.push(hangingGenerateImage("tc-prior-turn"));
|
|
534
378
|
// Message 1 opens this turn: one real terminal row.
|
|
@@ -547,7 +391,7 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
|
|
|
547
391
|
);
|
|
548
392
|
|
|
549
393
|
const result = await runTurnBoundary(
|
|
550
|
-
boundaryOpts(status,
|
|
394
|
+
boundaryOpts(status, { turnStartMessageIndex: 1 }),
|
|
551
395
|
);
|
|
552
396
|
|
|
553
397
|
expect(result.settledUnresolvedCount).toBe(0);
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Unit tests for the Cursor harness's shared stream seam (turn-stream.ts).
|
|
3
3
|
*
|
|
4
4
|
* These lock the behaviors the old bare retry loops used to DROP — live persist,
|
|
5
|
-
*
|
|
6
|
-
* — and the loop's side of the adapter contract: progress reported per event
|
|
5
|
+
* sub-agent tracking, the first-denial early stop — and the loop's side of the adapter contract: progress reported per event
|
|
7
6
|
* and per delta, usage reported priced, the persist awaited, and the runtime's
|
|
8
7
|
* stop signal honoured at every event boundary and inside a blocked pull by
|
|
9
8
|
* cancelling the SDK run. Since S2 M3 the loop no longer decides WHY it
|
|
@@ -30,7 +29,6 @@ import {
|
|
|
30
29
|
type StreamableRun,
|
|
31
30
|
type TurnStreamState,
|
|
32
31
|
} from "../turn-stream.js";
|
|
33
|
-
import type { ProgressSubstrate } from "../../../shared/filereview/progress.js";
|
|
34
32
|
|
|
35
33
|
// A stream event is only inspected by the loop for `type`/`name`/`status`/
|
|
36
34
|
// `message`; the accumulator (stubbed) owns the rest, so a minimal cast is safe.
|
|
@@ -109,9 +107,6 @@ function buildDeps(overrides: Partial<CursorTurnStreamDeps> = {}): BuiltDeps {
|
|
|
109
107
|
// contentDirty (accumulator.isDirty) forces the persist, so shouldSendUpdate
|
|
110
108
|
// is never consulted; markUpdateSent must still exist.
|
|
111
109
|
scheduler: { shouldSendUpdate: () => false, markUpdateSent: vi.fn() },
|
|
112
|
-
progressSubstrate: undefined,
|
|
113
|
-
progressState: { lastAtMs: 0 },
|
|
114
|
-
changeSetId: "exec-test:0",
|
|
115
110
|
hitlDir: undefined,
|
|
116
111
|
...overrides,
|
|
117
112
|
} as unknown as CursorTurnStreamDeps;
|
|
@@ -150,26 +145,6 @@ describe("consumeCursorTurnStream", () => {
|
|
|
150
145
|
expect(accumulator.trackSubAgentExecution).toHaveBeenCalledTimes(1);
|
|
151
146
|
});
|
|
152
147
|
|
|
153
|
-
it("attaches DD-32/DD-33 mid-run progress when a substrate is present", async () => {
|
|
154
|
-
const capture = vi.fn(async () => ({ delta: { entries: [] }, changed: true }));
|
|
155
|
-
const progressSubstrate = { capture } as unknown as ProgressSubstrate;
|
|
156
|
-
const { deps, sink } = buildDeps({ progressSubstrate });
|
|
157
|
-
|
|
158
|
-
await consumeCursorTurnStream(mockRun([ev({ type: "assistant" })]), deps);
|
|
159
|
-
|
|
160
|
-
expect(capture).toHaveBeenCalled();
|
|
161
|
-
// changed:true → the transient snapshot is attached to status.
|
|
162
|
-
expect(sink.status.fileChangeProgress).toBeDefined();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("does not touch progress when no substrate is configured", async () => {
|
|
166
|
-
const { deps, sink } = buildDeps({ progressSubstrate: undefined });
|
|
167
|
-
|
|
168
|
-
await consumeCursorTurnStream(mockRun([ev({ type: "assistant" })]), deps);
|
|
169
|
-
|
|
170
|
-
expect(sink.status.fileChangeProgress).toBeUndefined();
|
|
171
|
-
});
|
|
172
|
-
|
|
173
148
|
it("captures a stream ERROR status message onto state.streamErrorMessage", async () => {
|
|
174
149
|
const { deps, state } = buildDeps();
|
|
175
150
|
|
|
@@ -37,11 +37,13 @@
|
|
|
37
37
|
* pins it, which is what lets the contract kit run this adapter outside any
|
|
38
38
|
* activity context).
|
|
39
39
|
*
|
|
40
|
-
* The
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
40
|
+
* The turn boundary (`turn-boundary.ts`) runs inside `turn.ts` and reads
|
|
41
|
+
* this harness's deny-and-retry evidence — the denial ledger — into WAITING
|
|
42
|
+
* rows and settled rows. The file-review capture is NOT here since S3 M4:
|
|
43
|
+
* the runtime pins the baseline before this adapter runs and captures the
|
|
44
|
+
* whole turn's tree after it returns (`harness/capture.ts`); what this
|
|
45
|
+
* adapter contributes is the hook sidecar it binds as the runtime's CAS
|
|
46
|
+
* observations (`turn-setup.ts` `installGate`).
|
|
45
47
|
*
|
|
46
48
|
* Extracted from `index.ts` `createCursorActivities` at S2 M3b; split from
|
|
47
49
|
* the turn body at S2 M5. The seventeen hermetic goldens under
|
|
@@ -105,8 +105,11 @@ export const SALIENT_ARG_FIELDS = ["file_path", "path", "target_notebook", "comm
|
|
|
105
105
|
* `edit`/`shell`/`delete` all return true. Only mutating/destructive tools are
|
|
106
106
|
* gated; everything else (read-only built-ins, and — at the hook layer —
|
|
107
107
|
* auto-approved MCP tools) is allowed. This "gate the dangerous set, allow the
|
|
108
|
-
* rest" model
|
|
109
|
-
*
|
|
108
|
+
* rest" model is the platform's one approval rule, read through the shared
|
|
109
|
+
* `approvalCategory` / `toolApprovalCategory` (`shared/tool-kind.ts`) that the
|
|
110
|
+
* native gate (`middleware/approval-gate.ts` `resolveToolApproval`) also
|
|
111
|
+
* reads — one taxonomy, two enforcement points. It is deliberately fail-OPEN
|
|
112
|
+
* for unknown tools: the merged MCP policy map carries
|
|
110
113
|
* only the tools that REQUIRE approval, so a fail-closed default would wrongly
|
|
111
114
|
* deny every auto-approved MCP tool, which the hook cannot distinguish from an
|
|
112
115
|
* unknown built-in by name.
|