@stigmer/runner 3.15.3-dev.20260914100347 → 3.15.3-dev.20260916211208
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 +1 -0
- package/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/approval-contract/types.d.ts +1 -1
- package/dist/__test-utils__/hermetic-activity.d.ts +61 -7
- package/dist/__test-utils__/hermetic-activity.js +100 -9
- package/dist/__test-utils__/hermetic-activity.js.map +1 -1
- package/dist/__test-utils__/model-registry-fixture.d.ts +22 -3
- package/dist/__test-utils__/model-registry-fixture.js +22 -7
- package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +14 -11
- package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +61 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
- package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +1 -1
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +52 -14
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +46 -12
- package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +21 -28
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -11
- package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +70 -26
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +82 -32
- package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
- package/dist/activities/execute-cursor/adapter.d.ts +8 -7
- package/dist/activities/execute-cursor/adapter.js +13 -9
- package/dist/activities/execute-cursor/adapter.js.map +1 -1
- package/dist/activities/execute-cursor/approval-policy.d.ts +10 -10
- package/dist/activities/execute-cursor/approval-policy.js +12 -23
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +35 -1
- package/dist/activities/execute-cursor/approval-state.js +65 -0
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/{message-translator.d.ts → boundary-rows.d.ts} +45 -341
- package/dist/activities/execute-cursor/boundary-rows.js +1018 -0
- package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
- package/dist/activities/execute-cursor/cursor-capabilities.d.ts +1 -1
- package/dist/activities/execute-cursor/cursor-capabilities.js +1 -1
- package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +33 -14
- package/dist/activities/execute-cursor/cursor-event-recorder.js +43 -21
- package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-cursor/prompt-builder.js +4 -4
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/sdk-warmup.d.ts +15 -6
- package/dist/activities/execute-cursor/sdk-warmup.js +15 -6
- package/dist/activities/execute-cursor/sdk-warmup.js.map +1 -1
- package/dist/activities/execute-cursor/service-tier.js +1 -2
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +38 -59
- package/dist/activities/execute-cursor/session-lifecycle.js +59 -96
- package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
- package/dist/activities/execute-cursor/session-store.d.ts +100 -0
- package/dist/activities/execute-cursor/session-store.js +157 -0
- package/dist/activities/execute-cursor/session-store.js.map +1 -0
- package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
- package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
- package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
- package/dist/activities/execute-cursor/tool-result.js +130 -0
- package/dist/activities/execute-cursor/tool-result.js.map +1 -0
- package/dist/activities/execute-cursor/translator.d.ts +178 -0
- package/dist/activities/execute-cursor/translator.js +485 -0
- package/dist/activities/execute-cursor/translator.js.map +1 -0
- package/dist/activities/execute-cursor/turn-boundary.d.ts +15 -5
- package/dist/activities/execute-cursor/turn-boundary.js +10 -14
- 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 +47 -34
- package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
- package/dist/activities/execute-cursor/turn-setup.d.ts +2 -2
- package/dist/activities/execute-cursor/turn-setup.js +5 -5
- package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
- package/dist/activities/execute-cursor/turn-stream.d.ts +23 -14
- package/dist/activities/execute-cursor/turn-stream.js +41 -28
- package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
- package/dist/activities/execute-cursor/turn.d.ts +4 -4
- package/dist/activities/execute-cursor/turn.js +5 -5
- package/dist/activities/execute-cursor/usage-pricing.d.ts +2 -2
- package/dist/activities/execute-cursor/usage-pricing.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +2 -2
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +16 -11
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -10
- package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +2 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +12 -3
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +18 -4
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +10 -1
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +24 -11
- package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -1
- package/dist/activities/execute-deep-agent/adapter.d.ts +1 -1
- package/dist/activities/execute-deep-agent/adapter.js +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +19 -19
- package/dist/activities/execute-deep-agent/approval-file-change.js +16 -15
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +2 -2
- package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +2 -2
- package/dist/activities/execute-deep-agent/hitl.d.ts +2 -2
- package/dist/activities/execute-deep-agent/hitl.js +2 -2
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +13 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js +3 -3
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +3 -3
- package/dist/activities/execute-deep-agent/prompt-builder.js +6 -7
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +16 -8
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +20 -33
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +3 -3
- package/dist/activities/execute-deep-agent/subagent-transformer.js +1 -1
- package/dist/activities/execute-deep-agent/translator.d.ts +134 -0
- package/dist/activities/execute-deep-agent/translator.js +418 -0
- package/dist/activities/execute-deep-agent/translator.js.map +1 -0
- package/dist/activities/execute-deep-agent/turn-settle.d.ts +13 -7
- package/dist/activities/execute-deep-agent/turn-settle.js +34 -45
- package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn-setup.d.ts +8 -8
- package/dist/activities/execute-deep-agent/turn-setup.js +7 -7
- package/dist/activities/execute-deep-agent/turn-stream.d.ts +13 -10
- package/dist/activities/execute-deep-agent/turn-stream.js +44 -41
- package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
- package/dist/activities/execute-deep-agent/turn.d.ts +3 -3
- package/dist/activities/execute-deep-agent/turn.js +3 -3
- package/dist/config.d.ts +2 -2
- package/dist/harness/approval-decisions.d.ts +1 -1
- package/dist/harness/approval-decisions.js +1 -1
- package/dist/harness/capabilities.d.ts +21 -11
- package/dist/harness/capabilities.js +2 -2
- package/dist/harness/capture.d.ts +4 -4
- package/dist/harness/capture.js +4 -4
- package/dist/harness/persist-chokepoint.d.ts +3 -3
- package/dist/harness/persist-chokepoint.js +3 -3
- package/dist/harness/registry.d.ts +2 -2
- package/dist/harness/registry.js +2 -2
- package/dist/harness/run-turn.d.ts +6 -4
- package/dist/harness/run-turn.js +31 -9
- package/dist/harness/run-turn.js.map +1 -1
- package/dist/harness/stop-controller.d.ts +1 -1
- package/dist/harness/stop-controller.js +1 -1
- package/dist/harness/terminal-table.d.ts +7 -7
- package/dist/harness/terminal-table.js +7 -7
- package/dist/harness/transcript/builder.d.ts +182 -0
- package/dist/harness/transcript/builder.js +693 -0
- package/dist/harness/transcript/builder.js.map +1 -0
- package/dist/harness/transcript/events.d.ts +218 -0
- package/dist/harness/transcript/events.js +50 -0
- package/dist/harness/transcript/events.js.map +1 -0
- package/dist/harness/transcript/state.d.ts +110 -0
- package/dist/harness/transcript/state.js +148 -0
- package/dist/harness/transcript/state.js.map +1 -0
- package/dist/harness/turn-context.d.ts +54 -38
- package/dist/harness/turn-context.js +42 -43
- package/dist/harness/turn-context.js.map +1 -1
- package/dist/harness/types.d.ts +63 -22
- package/dist/harness/types.js +12 -11
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage-accumulator.d.ts +2 -2
- package/dist/harness/usage-accumulator.js +2 -2
- package/dist/harness-adapters.d.ts +5 -4
- package/dist/harness-adapters.js +5 -4
- package/dist/harness-adapters.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +6 -0
- package/dist/middleware/approval-gate.js +7 -57
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/cost-advisory.d.ts +3 -3
- package/dist/middleware/cost-advisory.js +3 -3
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/runner-manager.js +1 -1
- package/dist/runner-manager.js.map +1 -1
- package/dist/shared/approval-policy.d.ts +53 -0
- package/dist/shared/approval-policy.js +76 -0
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/args-preview.d.ts +45 -22
- package/dist/shared/args-preview.js +51 -41
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/attachment-resolver.d.ts +4 -4
- package/dist/shared/attachment-resolver.js +4 -4
- package/dist/shared/attachment-vision.d.ts +2 -1
- package/dist/shared/attachment-vision.js.map +1 -1
- package/dist/shared/attachment-zip.d.ts +2 -2
- package/dist/shared/attachment-zip.js +2 -2
- package/dist/shared/cost-guard.d.ts +2 -2
- package/dist/shared/cost-guard.js +2 -2
- package/dist/shared/exact-apply.d.ts +1 -1
- package/dist/shared/exact-apply.js +1 -1
- package/dist/shared/execution-context.d.ts +2 -2
- package/dist/shared/execution-context.js +2 -2
- package/dist/shared/extract-structured-output.d.ts +2 -2
- package/dist/shared/extract-structured-output.js +2 -2
- package/dist/shared/filereview/cas-touched.d.ts +2 -2
- package/dist/shared/filereview/cas-touched.js +2 -2
- package/dist/shared/heartbeat.d.ts +1 -1
- package/dist/shared/heartbeat.js +1 -1
- package/dist/shared/llm-backend.d.ts +0 -4
- package/dist/shared/llm-backend.js +0 -4
- package/dist/shared/llm-backend.js.map +1 -1
- package/dist/shared/model-error.d.ts +1 -2
- package/dist/shared/model-error.js +1 -2
- package/dist/shared/model-error.js.map +1 -1
- package/dist/shared/persist-decision.d.ts +18 -24
- package/dist/shared/persist-decision.js +19 -11
- package/dist/shared/persist-decision.js.map +1 -1
- package/dist/shared/prompt-sections.d.ts +4 -4
- package/dist/shared/prompt-sections.js +4 -4
- package/dist/shared/skill-resolver.d.ts +3 -3
- package/dist/shared/skill-resolver.js +3 -3
- package/dist/shared/status-offload.d.ts +1 -1
- package/dist/shared/status-offload.js +2 -2
- package/dist/shared/status-offload.js.map +1 -1
- package/dist/shared/streaming-scheduler.d.ts +2 -7
- package/dist/shared/streaming-scheduler.js +6 -14
- package/dist/shared/streaming-scheduler.js.map +1 -1
- package/dist/shared/subagent-rows.d.ts +2 -2
- package/dist/shared/subagent-rows.js +2 -2
- package/dist/shared/todos.d.ts +3 -3
- package/dist/shared/todos.js +3 -3
- package/dist/shared/tool-row.d.ts +19 -1
- package/dist/shared/tool-row.js +36 -2
- package/dist/shared/tool-row.js.map +1 -1
- package/dist/shared/worker-shutdown.d.ts +1 -1
- package/dist/shared/worker-shutdown.js +1 -1
- package/dist/shared/workspace/session-provision.d.ts +1 -1
- package/dist/shared/workspace/session-provision.js +1 -1
- package/dist/shared/workspace/sources/empty.d.ts +1 -1
- package/dist/shared/workspace/sources/empty.js +1 -2
- package/dist/shared/workspace/sources/empty.js.map +1 -1
- package/dist/shared/workspace/sources/git.js +4 -4
- package/dist/shared/workspace/sources/git.js.map +1 -1
- package/dist/shared/workspace/sources/local-path.js +6 -6
- package/dist/shared/workspace/sources/local-path.js.map +1 -1
- package/dist/shared/workspace/stigmer-link.d.ts +1 -1
- package/dist/shared/workspace/stigmer-link.js +1 -1
- package/dist/shared/workspace/types.d.ts +2 -5
- package/dist/shared/workspace/types.js +0 -6
- package/dist/shared/workspace/types.js.map +1 -1
- package/dist/shared/workspace/writeback-coordinator.d.ts +17 -4
- package/dist/shared/workspace/writeback-coordinator.js +7 -9
- package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
- package/package.json +5 -5
- package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +70 -0
- package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +35 -1
- package/src/__test-utils__/approval-contract/contract.ts +1 -1
- package/src/__test-utils__/approval-contract/types.ts +1 -1
- package/src/__test-utils__/harness-boot-order-child.ts +1 -1
- package/src/__test-utils__/harness-contract/contract.ts +8 -8
- package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
- package/src/__test-utils__/harness-contract/runtime-contract.ts +52 -16
- package/src/__test-utils__/harness-contract/scripted-adapter.ts +47 -43
- package/src/__test-utils__/hermetic-activity.ts +113 -9
- package/src/__test-utils__/model-registry-fixture.ts +31 -7
- package/src/__test-utils__/module-specifiers.ts +32 -3
- package/src/__tests__/harness-boot-order.test.ts +1 -1
- package/src/__tests__/harness-contract.test.ts +1 -1
- package/src/__tests__/runner-manager.test.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +32 -8
- package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +12 -10
- package/src/activities/execute-cursor/__test-utils__/fold.ts +116 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +1 -1
- package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +72 -19
- package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +35 -29
- package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +94 -38
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/approval-state.test.ts +14 -21
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +3 -3
- package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/cursor-baseurl-routing.test.ts +10 -8
- package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
- package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +24 -12
- package/src/activities/execute-cursor/__tests__/cursor-generate-image-live.test.ts +7 -2
- package/src/activities/execute-cursor/__tests__/cursor-hook-protocol-live.test.ts +163 -0
- package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +23 -20
- package/src/activities/execute-cursor/__tests__/cursor-transcript-live.test.ts +298 -0
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +4 -2
- package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.status.json +71 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +73 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +72 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +109 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +78 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +119 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +68 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +67 -0
- package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +1 -1
- package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +10 -7
- package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +146 -0
- package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +8 -5
- package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +6 -2
- package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +4 -1
- package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +6 -2
- package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +122 -0
- package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +276 -0
- package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +12 -9
- package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +196 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +145 -0
- package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +4 -1
- package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +165 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +7 -4
- package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +138 -0
- package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +130 -0
- package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +17 -2
- package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -2
- package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +43 -60
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +23 -28
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +2 -1
- package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +5 -5
- package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +11 -13
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +8 -11
- package/src/activities/execute-cursor/__tests__/session-lifecycle.test.ts +86 -58
- package/src/activities/execute-cursor/__tests__/session-store.test.ts +220 -0
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +8 -22
- package/src/activities/execute-cursor/__tests__/translator.test.ts +594 -0
- package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +8 -5
- package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +87 -63
- package/src/activities/execute-cursor/adapter.ts +13 -9
- package/src/activities/execute-cursor/approval-policy.ts +12 -24
- package/src/activities/execute-cursor/approval-state.ts +66 -1
- package/src/activities/execute-cursor/boundary-rows.ts +1132 -0
- package/src/activities/execute-cursor/cursor-capabilities.ts +1 -1
- package/src/activities/execute-cursor/cursor-event-recorder.ts +57 -28
- package/src/activities/execute-cursor/fetch-interceptor.ts +1 -1
- package/src/activities/execute-cursor/http2-interceptor.ts +1 -1
- package/src/activities/execute-cursor/prompt-builder.ts +6 -6
- package/src/activities/execute-cursor/sdk-warmup.ts +15 -6
- package/src/activities/execute-cursor/service-tier.ts +1 -2
- package/src/activities/execute-cursor/session-lifecycle.ts +63 -109
- package/src/activities/execute-cursor/session-store.ts +187 -0
- package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
- package/src/activities/execute-cursor/tool-result.ts +128 -0
- package/src/activities/execute-cursor/translator.ts +541 -0
- package/src/activities/execute-cursor/turn-boundary.ts +21 -14
- package/src/activities/execute-cursor/turn-settle.ts +46 -34
- package/src/activities/execute-cursor/turn-setup.ts +5 -5
- package/src/activities/execute-cursor/turn-stream.ts +49 -46
- package/src/activities/execute-cursor/turn.ts +5 -5
- package/src/activities/execute-cursor/usage-pricing.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +2 -2
- package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +23 -11
- package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +1 -1
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +2 -3
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +25 -4
- package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +25 -11
- package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +6 -17
- package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +25 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +2 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +4 -14
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +4 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +2 -9
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +109 -76
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +2 -10
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +1 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +3 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +1 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +92 -0
- package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +9 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +3 -3
- package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +7 -6
- package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +10 -11
- package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +4 -4
- package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +9 -8
- package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +21 -13
- package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +2 -2
- package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +7 -7
- package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +28 -12
- package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +21 -21
- package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -5
- package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +35 -30
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +3 -4
- package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +12 -10
- package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +13 -3
- package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +26 -18
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +1 -1
- package/src/activities/execute-deep-agent/__tests__/{subagent-tracker.test.ts → translator-subagents.test.ts} +76 -57
- package/src/activities/execute-deep-agent/__tests__/{v3-status-builder.test.ts → translator-through-builder.test.ts} +213 -299
- package/src/activities/execute-deep-agent/__tests__/translator.test.ts +505 -0
- package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +11 -29
- package/src/activities/execute-deep-agent/adapter.ts +1 -1
- package/src/activities/execute-deep-agent/approval-file-change.ts +20 -22
- package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +2 -2
- package/src/activities/execute-deep-agent/hitl.ts +2 -2
- package/src/activities/execute-deep-agent/inline-publisher.ts +16 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +6 -7
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +22 -31
- package/src/activities/execute-deep-agent/subagent-transformer.ts +3 -3
- package/src/activities/execute-deep-agent/translator.ts +463 -0
- package/src/activities/execute-deep-agent/turn-settle.ts +35 -43
- package/src/activities/execute-deep-agent/turn-setup.ts +8 -8
- package/src/activities/execute-deep-agent/turn-stream.ts +53 -51
- package/src/activities/execute-deep-agent/turn.ts +3 -3
- package/src/config.ts +2 -2
- package/src/harness/README.md +335 -0
- package/src/harness/__tests__/approval-decisions.test.ts +2 -2
- package/src/harness/__tests__/capture.test.ts +3 -3
- package/src/harness/__tests__/import-direction.test.ts +3 -2
- package/src/harness/__tests__/mount-skills.test.ts +4 -1
- package/src/harness/__tests__/readme-index.test.ts +339 -0
- package/src/harness/__tests__/run-turn.test.ts +131 -6
- package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
- package/src/harness/__tests__/transcript-writers.test.ts +191 -0
- package/src/harness/__tests__/turn-attachments-vision.test.ts +5 -2
- package/src/harness/__tests__/turn-context.test.ts +5 -5
- package/src/harness/approval-decisions.ts +1 -1
- package/src/harness/capabilities.ts +21 -11
- package/src/harness/capture.ts +4 -4
- package/src/harness/persist-chokepoint.ts +3 -3
- package/src/harness/registry.ts +2 -2
- package/src/harness/run-turn.ts +33 -9
- package/src/harness/stop-controller.ts +1 -1
- package/src/harness/terminal-table.ts +7 -7
- package/src/harness/transcript/__tests__/builder.test.ts +975 -0
- package/src/harness/transcript/__tests__/state.test.ts +143 -0
- package/src/harness/transcript/builder.ts +755 -0
- package/src/harness/transcript/events.ts +262 -0
- package/src/harness/transcript/state.ts +167 -0
- package/src/harness/turn-context.ts +61 -46
- package/src/harness/types.ts +64 -22
- package/src/harness/usage-accumulator.ts +2 -2
- package/src/harness-adapters.ts +5 -4
- package/src/middleware/__tests__/cost-advisory.test.ts +2 -2
- package/src/middleware/approval-gate.ts +7 -74
- package/src/middleware/cost-advisory.ts +3 -3
- package/src/middleware/index.ts +1 -1
- package/src/runner-manager.ts +1 -1
- package/src/shared/__tests__/approval-policy.test.ts +45 -0
- package/src/shared/__tests__/args-preview.test.ts +40 -20
- package/src/shared/__tests__/attachment-naming.test.ts +1 -1
- package/src/shared/__tests__/attachment-resolver.test.ts +5 -5
- package/src/shared/__tests__/attachment-zip.test.ts +1 -1
- package/src/shared/__tests__/blueprint-resolver.test.ts +1 -1
- package/src/shared/__tests__/cost-guard.test.ts +1 -1
- package/src/shared/__tests__/exact-apply.test.ts +2 -1
- package/src/shared/__tests__/persist-decision.test.ts +19 -33
- package/src/shared/__tests__/prompt-sections.test.ts +1 -1
- package/src/shared/__tests__/stamp-flowed-rows.test.ts +1 -1
- package/src/shared/__tests__/status-offload.test.ts +1 -1
- package/src/shared/__tests__/streaming-scheduler.test.ts +8 -9
- package/src/shared/__tests__/todos.test.ts +1 -1
- package/src/shared/__tests__/tool-row.test.ts +1 -1
- package/src/shared/approval-policy.ts +95 -0
- package/src/shared/args-preview.ts +51 -42
- package/src/shared/attachment-resolver.ts +4 -4
- package/src/shared/attachment-vision.ts +2 -1
- package/src/shared/attachment-zip.ts +2 -2
- package/src/shared/cost-guard.ts +2 -2
- package/src/shared/exact-apply.ts +1 -1
- package/src/shared/execution-context.ts +2 -2
- package/src/shared/extract-structured-output.ts +2 -2
- package/src/shared/filereview/__tests__/capture.test.ts +9 -5
- package/src/shared/filereview/__tests__/git-substrate.test.ts +4 -1
- package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +3 -3
- package/src/shared/filereview/cas-touched.ts +2 -2
- package/src/shared/heartbeat.ts +1 -1
- package/src/shared/llm-backend.ts +0 -4
- package/src/shared/model-error.ts +1 -2
- package/src/shared/persist-decision.ts +19 -28
- package/src/shared/prompt-sections.ts +4 -4
- package/src/shared/skill-resolver.ts +3 -3
- package/src/shared/status-offload.ts +2 -2
- package/src/shared/streaming-scheduler.ts +8 -13
- package/src/shared/subagent-rows.ts +2 -2
- package/src/shared/todos.ts +3 -3
- package/src/shared/tool-row.ts +38 -2
- package/src/shared/worker-shutdown.ts +1 -1
- package/src/shared/workspace/__tests__/git-source.test.ts +3 -3
- package/src/shared/workspace/__tests__/provisioner.test.ts +5 -5
- package/src/shared/workspace/__tests__/session-provision.test.ts +2 -2
- package/src/shared/workspace/__tests__/writeback-coordinator.integration.test.ts +8 -9
- package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +25 -25
- package/src/shared/workspace/provisioner.ts +1 -1
- package/src/shared/workspace/session-provision.ts +1 -1
- package/src/shared/workspace/sources/empty.ts +2 -2
- package/src/shared/workspace/sources/git.ts +3 -4
- package/src/shared/workspace/sources/local-path.ts +5 -6
- package/src/shared/workspace/stigmer-link.ts +1 -1
- package/src/shared/workspace/types.ts +2 -5
- package/src/shared/workspace/writeback-coordinator.ts +23 -12
- package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
- package/dist/activities/execute-cursor/delta-enricher.js +0 -265
- package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
- package/dist/activities/execute-cursor/message-translator.js +0 -2040
- package/dist/activities/execute-cursor/message-translator.js.map +0 -1
- package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
- package/dist/activities/execute-cursor/todo-tracker.js +0 -80
- package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
- package/dist/activities/execute-deep-agent/execution-state.js +0 -68
- package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
- package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
- package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
- package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
- package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
- package/dist/activities/execute-deep-agent/v3-events.js +0 -35
- package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
- package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
- package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
- package/dist/shared/execution-status-writer.d.ts +0 -31
- package/dist/shared/execution-status-writer.js +0 -43
- package/dist/shared/execution-status-writer.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
- package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
- package/src/activities/execute-cursor/delta-enricher.ts +0 -307
- package/src/activities/execute-cursor/message-translator.ts +0 -2319
- package/src/activities/execute-cursor/todo-tracker.ts +0 -91
- package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
- package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
- package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
- package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
- package/src/activities/execute-deep-agent/execution-state.ts +0 -78
- package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
- package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
- package/src/activities/execute-deep-agent/v3-events.ts +0 -153
- package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
- package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
- package/src/shared/execution-status-writer.ts +0 -56
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @regression file-hitl-phase0 — pins
|
|
2
|
+
* @regression file-hitl-phase0 — pins four rules of the file-edit gate: one
|
|
3
|
+
* approval gate per turn (a distinct co-pending sibling defers to SKIPPED);
|
|
4
|
+
* decisions bind to the active turn's ledger, never a stale one; the executed
|
|
5
|
+
* capture supersedes the model's proposal; the hook-captured input is
|
|
6
|
+
* authoritative over the streamed snapshot.
|
|
3
7
|
*
|
|
4
8
|
* Unit tests for the Cursor-harness HITL denial-ledger flow.
|
|
5
9
|
*
|
|
@@ -61,11 +65,12 @@ import {
|
|
|
61
65
|
reconcileDeniedToolCalls,
|
|
62
66
|
clearProvisionalPostDenialNarration,
|
|
63
67
|
collapseRedundantToolCallTwins,
|
|
64
|
-
toolCallIdentityToken,
|
|
65
68
|
detectUnattributedHookBlocks,
|
|
66
69
|
stampUnattendedSkippedToolCalls,
|
|
67
70
|
HOOK_BLOCK_ERROR_MARKERS,
|
|
68
|
-
} from "../
|
|
71
|
+
} from "../boundary-rows.js";
|
|
72
|
+
import { builderOver } from "../__test-utils__/fold.js";
|
|
73
|
+
import { toolCallIdentityToken } from "../approval-state.js";
|
|
69
74
|
import { mockWorkspaceBackend } from "../../../__test-utils__/mock-workspace.js";
|
|
70
75
|
import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
|
|
71
76
|
import { generateHookScript } from "../hook-script.js";
|
|
@@ -240,7 +245,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
240
245
|
});
|
|
241
246
|
const messages = [aiMessageWith([tc])];
|
|
242
247
|
|
|
243
|
-
const reconciled = await reconcileDeniedToolCalls(messages, [
|
|
248
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
244
249
|
{ toolName: "Write", token: grantToken("write", "gated.txt") },
|
|
245
250
|
]);
|
|
246
251
|
|
|
@@ -279,7 +284,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
279
284
|
]);
|
|
280
285
|
|
|
281
286
|
// MCP tools are keyed name-only (their name is consistent across layers).
|
|
282
|
-
await reconcileDeniedToolCalls(messages, [
|
|
287
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
283
288
|
{ toolName: "apply_x", token: grantToken("apply_x", "") },
|
|
284
289
|
], policies);
|
|
285
290
|
|
|
@@ -302,7 +307,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
302
307
|
});
|
|
303
308
|
const messages = [aiMessageWith([denied, allowed])];
|
|
304
309
|
|
|
305
|
-
const reconciled = await reconcileDeniedToolCalls(messages, [
|
|
310
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
306
311
|
{ toolName: "Write", token: grantToken("write", "gated.txt") },
|
|
307
312
|
]);
|
|
308
313
|
|
|
@@ -323,7 +328,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
323
328
|
const second = toolCall({ id: "c2", name: "edit", args: { path: "gated.txt" } });
|
|
324
329
|
const messages = [aiMessageWith([first, second])];
|
|
325
330
|
|
|
326
|
-
const reconciled = await reconcileDeniedToolCalls(messages, [
|
|
331
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
327
332
|
{ toolName: "Write", token: grantToken("write", "gated.txt") },
|
|
328
333
|
]);
|
|
329
334
|
|
|
@@ -344,7 +349,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
344
349
|
it("synthesizes a WAITING_APPROVAL tool call when a denial produced no stream event", async () => {
|
|
345
350
|
const messages = [aiMessageWith([])];
|
|
346
351
|
|
|
347
|
-
const reconciled = await reconcileDeniedToolCalls(messages, [
|
|
352
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
348
353
|
{ toolName: "Shell", token: grantToken("shell", "rm -rf build") },
|
|
349
354
|
]);
|
|
350
355
|
|
|
@@ -363,7 +368,7 @@ describe("reconcileDeniedToolCalls", () => {
|
|
|
363
368
|
it("is a no-op when the ledger is empty", async () => {
|
|
364
369
|
const tc = toolCall({ id: "c1", status: ToolCallStatus.TOOL_CALL_COMPLETED });
|
|
365
370
|
const messages = [aiMessageWith([tc])];
|
|
366
|
-
expect(await reconcileDeniedToolCalls(messages, [])).toEqual([]);
|
|
371
|
+
expect(await reconcileDeniedToolCalls(messages, builderOver(messages), [])).toEqual([]);
|
|
367
372
|
expect(tc.status).toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
|
|
368
373
|
});
|
|
369
374
|
});
|
|
@@ -391,8 +396,7 @@ describe("reconcileDeniedToolCalls — duplicate denial-twin collapse", () => {
|
|
|
391
396
|
});
|
|
392
397
|
const messages = [aiMessageWith([gate, twin])];
|
|
393
398
|
|
|
394
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
395
|
-
messages,
|
|
399
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
396
400
|
[{ toolName: "Write", token: grantToken("write", "notes.md") }],
|
|
397
401
|
undefined,
|
|
398
402
|
rootBackend(),
|
|
@@ -432,8 +436,7 @@ describe("reconcileDeniedToolCalls — duplicate denial-twin collapse", () => {
|
|
|
432
436
|
});
|
|
433
437
|
const messages = [aiMessageWith([gate, twin])];
|
|
434
438
|
|
|
435
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
436
|
-
messages,
|
|
439
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
437
440
|
[{ toolName: "Shell", token: grantToken("shell", "rm -rf build") }],
|
|
438
441
|
undefined,
|
|
439
442
|
rootBackend(),
|
|
@@ -470,8 +473,7 @@ describe("reconcileDeniedToolCalls — duplicate denial-twin collapse", () => {
|
|
|
470
473
|
});
|
|
471
474
|
const messages = [aiMessageWith([gateA, gateB])];
|
|
472
475
|
|
|
473
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
474
|
-
messages,
|
|
476
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
475
477
|
[
|
|
476
478
|
// The hook records the content-exact token for an edit (its primary token).
|
|
477
479
|
{ toolName: "Write", token: toolCallIdentityToken(gateA) },
|
|
@@ -508,8 +510,7 @@ describe("reconcileDeniedToolCalls — duplicate denial-twin collapse", () => {
|
|
|
508
510
|
});
|
|
509
511
|
const messages = [aiMessageWith([gate, twin])];
|
|
510
512
|
|
|
511
|
-
await reconcileDeniedToolCalls(
|
|
512
|
-
messages,
|
|
513
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
513
514
|
[{ toolName: "Write", token: grantToken("write", "notes.md") }],
|
|
514
515
|
undefined,
|
|
515
516
|
rootBackend(),
|
|
@@ -552,8 +553,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
552
553
|
});
|
|
553
554
|
const messages = [aiMessageWith([edit, shell])];
|
|
554
555
|
|
|
555
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
556
|
-
messages,
|
|
556
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
557
557
|
[
|
|
558
558
|
{ toolName: "Write", token: grantToken("write", "notes.md") },
|
|
559
559
|
{ toolName: "Shell", token: grantToken("shell", "cat > notes.md") },
|
|
@@ -595,8 +595,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
595
595
|
});
|
|
596
596
|
const messages = [aiMessageWith([edit]), aiMessageWith([shell])];
|
|
597
597
|
|
|
598
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
599
|
-
messages,
|
|
598
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
600
599
|
[
|
|
601
600
|
{ toolName: "Write", token: grantToken("write", "notes.md") },
|
|
602
601
|
{ toolName: "Shell", token: grantToken("shell", "cat > notes.md") },
|
|
@@ -631,8 +630,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
631
630
|
});
|
|
632
631
|
const messages = [aiMessageWith([shell, edit])];
|
|
633
632
|
|
|
634
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
635
|
-
messages,
|
|
633
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
636
634
|
[
|
|
637
635
|
{ toolName: "Shell", token: toolCallIdentityToken(shell) },
|
|
638
636
|
{ toolName: "Write", token: toolCallIdentityToken(edit) },
|
|
@@ -666,8 +664,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
666
664
|
});
|
|
667
665
|
const messages = [aiMessageWith([mcp, edit])];
|
|
668
666
|
|
|
669
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
670
|
-
messages,
|
|
667
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
671
668
|
[
|
|
672
669
|
{ toolName: "fetch", token: toolCallIdentityToken(mcp) },
|
|
673
670
|
{ toolName: "Write", token: toolCallIdentityToken(edit) },
|
|
@@ -692,8 +689,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
692
689
|
});
|
|
693
690
|
const messages = [aiMessageWith([edit])];
|
|
694
691
|
|
|
695
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
696
|
-
messages,
|
|
692
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
697
693
|
[{ toolName: "Write", token: grantToken("write", "notes.md") }],
|
|
698
694
|
undefined,
|
|
699
695
|
rootBackend(),
|
|
@@ -725,8 +721,7 @@ describe("reconcileDeniedToolCalls — one gate per turn (deny-only workaround)"
|
|
|
725
721
|
});
|
|
726
722
|
const messages = [aiMessageWith([edit, shell])];
|
|
727
723
|
|
|
728
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
729
|
-
messages,
|
|
724
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
730
725
|
[
|
|
731
726
|
{ toolName: "Write", token: grantToken("write", "notes.md") },
|
|
732
727
|
{ toolName: "Shell", token: grantToken("shell", "cat > notes.md") },
|
|
@@ -801,8 +796,7 @@ describe("reconcileDeniedToolCalls — interrupted non-terminal rows (raced work
|
|
|
801
796
|
];
|
|
802
797
|
|
|
803
798
|
// Only the anchor's denial is in the ledger — the workaround's raced it.
|
|
804
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
805
|
-
messages,
|
|
799
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
806
800
|
[{ toolName: "Shell", token: toolCallIdentityToken(anchor) }],
|
|
807
801
|
undefined,
|
|
808
802
|
rootBackend(),
|
|
@@ -848,8 +842,7 @@ describe("reconcileDeniedToolCalls — interrupted non-terminal rows (raced work
|
|
|
848
842
|
create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, content: "trailing reaction" }),
|
|
849
843
|
];
|
|
850
844
|
|
|
851
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
852
|
-
messages,
|
|
845
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
853
846
|
[{ toolName: "Shell", token: toolCallIdentityToken(anchor) }],
|
|
854
847
|
undefined,
|
|
855
848
|
rootBackend(),
|
|
@@ -1066,8 +1059,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1066
1059
|
});
|
|
1067
1060
|
const messages = [aiMessageWith([tc])];
|
|
1068
1061
|
|
|
1069
|
-
await reconcileDeniedToolCalls(
|
|
1070
|
-
messages,
|
|
1062
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1071
1063
|
[{
|
|
1072
1064
|
toolName: "Write",
|
|
1073
1065
|
token: grantToken("write", "src/new.ts"),
|
|
@@ -1097,8 +1089,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1097
1089
|
});
|
|
1098
1090
|
const messages = [aiMessageWith([tc])];
|
|
1099
1091
|
|
|
1100
|
-
await reconcileDeniedToolCalls(
|
|
1101
|
-
messages,
|
|
1092
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1102
1093
|
[{
|
|
1103
1094
|
toolName: "Write",
|
|
1104
1095
|
token: grantToken("write", ".env"),
|
|
@@ -1122,8 +1113,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1122
1113
|
});
|
|
1123
1114
|
const messages = [aiMessageWith([tc])];
|
|
1124
1115
|
|
|
1125
|
-
await reconcileDeniedToolCalls(
|
|
1126
|
-
messages,
|
|
1116
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1127
1117
|
[{
|
|
1128
1118
|
toolName: "StrReplace",
|
|
1129
1119
|
token: grantToken("write", "src/app.ts"),
|
|
@@ -1147,8 +1137,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1147
1137
|
});
|
|
1148
1138
|
const messages = [aiMessageWith([tc])];
|
|
1149
1139
|
|
|
1150
|
-
await reconcileDeniedToolCalls(
|
|
1151
|
-
messages,
|
|
1140
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1152
1141
|
[{
|
|
1153
1142
|
toolName: "EditNotebook",
|
|
1154
1143
|
token: grantToken("write", "nb.ipynb"),
|
|
@@ -1170,8 +1159,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1170
1159
|
});
|
|
1171
1160
|
const messages = [aiMessageWith([tc])];
|
|
1172
1161
|
|
|
1173
|
-
await reconcileDeniedToolCalls(
|
|
1174
|
-
messages,
|
|
1162
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1175
1163
|
[{
|
|
1176
1164
|
toolName: "Shell",
|
|
1177
1165
|
token: grantToken("shell", "rm -rf build"),
|
|
@@ -1190,8 +1178,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1190
1178
|
// proposed content from the captured input, not a bare {path}.
|
|
1191
1179
|
const messages = [aiMessageWith([])];
|
|
1192
1180
|
|
|
1193
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
1194
|
-
messages,
|
|
1181
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1195
1182
|
[{
|
|
1196
1183
|
toolName: "Write",
|
|
1197
1184
|
token: grantToken("write", "ghost.md"),
|
|
@@ -1217,8 +1204,7 @@ describe("reconcileDeniedToolCalls — authoritative hook input overlay", () =>
|
|
|
1217
1204
|
});
|
|
1218
1205
|
const messages = [aiMessageWith([tc])];
|
|
1219
1206
|
|
|
1220
|
-
await reconcileDeniedToolCalls(
|
|
1221
|
-
messages,
|
|
1207
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1222
1208
|
[{
|
|
1223
1209
|
toolName: "Write",
|
|
1224
1210
|
token: grantToken("write", "big.ts"),
|
|
@@ -1259,8 +1245,7 @@ describe("reconcileDeniedToolCalls — normalized-path fallback (abs/rel drift)"
|
|
|
1259
1245
|
});
|
|
1260
1246
|
const messages = [aiMessageWith([streamed])];
|
|
1261
1247
|
|
|
1262
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
1263
|
-
messages,
|
|
1248
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1264
1249
|
[{ toolName: "Write", token: grantToken("write", "/root/notes.md") }],
|
|
1265
1250
|
undefined,
|
|
1266
1251
|
rootBackend(),
|
|
@@ -1288,8 +1273,7 @@ describe("reconcileDeniedToolCalls — normalized-path fallback (abs/rel drift)"
|
|
|
1288
1273
|
});
|
|
1289
1274
|
const messages = [aiMessageWith([streamed])];
|
|
1290
1275
|
|
|
1291
|
-
await reconcileDeniedToolCalls(
|
|
1292
|
-
messages,
|
|
1276
|
+
await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1293
1277
|
[{ toolName: "Write", token: grantToken("write", "/root/src/app.ts") }],
|
|
1294
1278
|
undefined,
|
|
1295
1279
|
rootBackend(),
|
|
@@ -1304,8 +1288,7 @@ describe("reconcileDeniedToolCalls — normalized-path fallback (abs/rel drift)"
|
|
|
1304
1288
|
// The genuine no-stream-event denial (rare) must still surface a gate.
|
|
1305
1289
|
const messages = [aiMessageWith([])];
|
|
1306
1290
|
|
|
1307
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
1308
|
-
messages,
|
|
1291
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1309
1292
|
[{ toolName: "Write", token: grantToken("write", "/root/ghost.md") }],
|
|
1310
1293
|
undefined,
|
|
1311
1294
|
rootBackend(),
|
|
@@ -1327,8 +1310,7 @@ describe("reconcileDeniedToolCalls — normalized-path fallback (abs/rel drift)"
|
|
|
1327
1310
|
});
|
|
1328
1311
|
const messages = [aiMessageWith([streamed])];
|
|
1329
1312
|
|
|
1330
|
-
const reconciled = await reconcileDeniedToolCalls(
|
|
1331
|
-
messages,
|
|
1313
|
+
const reconciled = await reconcileDeniedToolCalls(messages, builderOver(messages),
|
|
1332
1314
|
[{ toolName: "Write", token: grantToken("write", "/root/notes.md") }],
|
|
1333
1315
|
undefined,
|
|
1334
1316
|
rootBackend(),
|
|
@@ -1566,7 +1548,7 @@ describe("first-denial stop contract", () => {
|
|
|
1566
1548
|
expect(messages.some((m) => m.content.includes("try the shell"))).toBe(false);
|
|
1567
1549
|
|
|
1568
1550
|
// Phase 12 reconcile + redact on the stopped transcript yields the clean shape.
|
|
1569
|
-
const denied = await reconcileDeniedToolCalls(messages, await readDenialLedger(ws));
|
|
1551
|
+
const denied = await reconcileDeniedToolCalls(messages, builderOver(messages), await readDenialLedger(ws));
|
|
1570
1552
|
expect(denied).toHaveLength(1);
|
|
1571
1553
|
expect(edit.status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
1572
1554
|
const redacted = clearProvisionalPostDenialNarration(messages, denied);
|
|
@@ -1610,7 +1592,8 @@ describe("first-denial stop contract", () => {
|
|
|
1610
1592
|
expect(cancelled).toBe(false);
|
|
1611
1593
|
expect(consumed).toBe(3); // the whole turn is consumed
|
|
1612
1594
|
// And the boundary reconcile manufactures no gate from it either.
|
|
1613
|
-
const
|
|
1595
|
+
const messages: AgentMessage[] = [];
|
|
1596
|
+
const denied = await reconcileDeniedToolCalls(messages, builderOver(messages), await readDenialLedger(ws));
|
|
1614
1597
|
expect(denied).toEqual([]);
|
|
1615
1598
|
});
|
|
1616
1599
|
|
|
@@ -1641,7 +1624,7 @@ describe("first-denial stop contract", () => {
|
|
|
1641
1624
|
|
|
1642
1625
|
// Phase 12 on the stopped transcript: the anchor gates, and the one raced
|
|
1643
1626
|
// reaction message is blanked by the trim backstop.
|
|
1644
|
-
const denied = await reconcileDeniedToolCalls(messages, await readDenialLedger(ws), undefined, rootBackend());
|
|
1627
|
+
const denied = await reconcileDeniedToolCalls(messages, builderOver(messages), await readDenialLedger(ws), undefined, rootBackend());
|
|
1645
1628
|
expect(denied).toHaveLength(1);
|
|
1646
1629
|
expect(shell.status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
|
|
1647
1630
|
const redacted = clearProvisionalPostDenialNarration(messages, denied);
|
|
@@ -1812,7 +1795,7 @@ describe("reconcileDeniedToolCalls — non-approval kinds never gate", () => {
|
|
|
1812
1795
|
error: "blocked by a hook", args: { path: ".env" },
|
|
1813
1796
|
});
|
|
1814
1797
|
const messages = [aiMessageWith([secretRow])];
|
|
1815
|
-
const denied = await reconcileDeniedToolCalls(messages, [
|
|
1798
|
+
const denied = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
1816
1799
|
{ toolName: "Write", token: toolCallIdentityToken(secretRow), kind: "secret" },
|
|
1817
1800
|
{ toolName: "Write", token: grantToken("write", "app.log"), kind: "capture-error" },
|
|
1818
1801
|
{ toolName: "Shell", token: grantToken("shell", "make"), kind: "fail-closed" },
|
|
@@ -1834,7 +1817,7 @@ describe("reconcileDeniedToolCalls — non-approval kinds never gate", () => {
|
|
|
1834
1817
|
error: "blocked by a hook", args: { path: ".env" },
|
|
1835
1818
|
});
|
|
1836
1819
|
const messages = [aiMessageWith([gated, secretRow])];
|
|
1837
|
-
const denied = await reconcileDeniedToolCalls(messages, [
|
|
1820
|
+
const denied = await reconcileDeniedToolCalls(messages, builderOver(messages), [
|
|
1838
1821
|
// Ledger order puts the secret FIRST: the anchor must still be the first
|
|
1839
1822
|
// APPROVAL entry, never a non-approval kind.
|
|
1840
1823
|
{ toolName: "Write", token: toolCallIdentityToken(secretRow), kind: "secret" },
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* watchdog failed the run ("approval propagation is broken").
|
|
20
20
|
*
|
|
21
21
|
* The fix (seed the transcript on resume + reconcile re-runs by canonical
|
|
22
|
-
* identity in
|
|
22
|
+
* identity in the Cursor translator) makes the resume status a strict superset:
|
|
23
23
|
* the committed ids survive, the re-runs reconcile in place, and the genuinely
|
|
24
24
|
* new gated tool is appended. The guard then accepts it.
|
|
25
25
|
*
|
|
@@ -27,13 +27,14 @@
|
|
|
27
27
|
* (nonTerminalTranscriptRegression): a from-empty rebuild is REJECTED (the bug),
|
|
28
28
|
* a seeded rebuild is ACCEPTED (the fix).
|
|
29
29
|
*
|
|
30
|
-
* This exercises the
|
|
30
|
+
* This exercises the translator + builder + denial-reconciliation directly — the
|
|
31
31
|
* unit that owns the resume emitter — rather than the full Temporal activity,
|
|
32
32
|
* keeping the reproduction hermetic and pinned to the exact code under change.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
35
|
import { describe, it, expect } from "vitest";
|
|
36
36
|
import { create, clone } from "@bufbuild/protobuf";
|
|
37
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
37
38
|
import {
|
|
38
39
|
AgentMessageSchema,
|
|
39
40
|
ToolCallSchema,
|
|
@@ -47,12 +48,9 @@ import {
|
|
|
47
48
|
ToolCallStatus,
|
|
48
49
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
49
50
|
import type { SDKMessage } from "@cursor/sdk";
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
clearProvisionalPostDenialNarration,
|
|
54
|
-
buildToolCallProto,
|
|
55
|
-
} from "../message-translator.js";
|
|
51
|
+
import { reconcileDeniedToolCalls, clearProvisionalPostDenialNarration } from "../boundary-rows.js";
|
|
52
|
+
import { CursorFold, builderOver } from "../__test-utils__/fold.js";
|
|
53
|
+
import { TranscriptBuilder } from "../../../harness/transcript/builder.js";
|
|
56
54
|
import {
|
|
57
55
|
grantToken,
|
|
58
56
|
buildApprovalGrants,
|
|
@@ -213,11 +211,9 @@ describe("Cursor HITL resume — append-only transcript", () => {
|
|
|
213
211
|
const committed = persistedRunOneMessages();
|
|
214
212
|
|
|
215
213
|
// Pre-fix behavior: status.messages starts empty on resume, so the
|
|
216
|
-
//
|
|
214
|
+
// translator can never reconcile onto the committed calls.
|
|
217
215
|
const fromEmpty: AgentMessage[] = [];
|
|
218
|
-
|
|
219
|
-
for (const event of resumeEvents()) acc.processEvent(event);
|
|
220
|
-
acc.finalize();
|
|
216
|
+
new CursorFold({ messages: fromEmpty }).events(...resumeEvents()).finalize();
|
|
221
217
|
|
|
222
218
|
// The committed ids are absent — exactly what trips the backend guard.
|
|
223
219
|
const ids = new Set(allToolCalls(fromEmpty).map((tc) => tc.id));
|
|
@@ -233,15 +229,13 @@ describe("Cursor HITL resume — append-only transcript", () => {
|
|
|
233
229
|
const committed = persistedRunOneMessages();
|
|
234
230
|
|
|
235
231
|
// Post-fix behavior: index.ts seeds status.messages from the persisted
|
|
236
|
-
// execution (cloned) before constructing the
|
|
232
|
+
// execution (cloned) before constructing the translator and the builder.
|
|
237
233
|
const seeded = committed.map((m) => clone(AgentMessageSchema, m));
|
|
238
|
-
|
|
239
|
-
for (const event of resumeEvents()) acc.processEvent(event);
|
|
240
|
-
acc.finalize();
|
|
234
|
+
new CursorFold({ messages: seeded }).events(...resumeEvents()).finalize();
|
|
241
235
|
|
|
242
236
|
// Post-stream denial overlay (the activity's Phase 12): only `click` is in
|
|
243
237
|
// the ledger, so only it flips to WAITING_APPROVAL.
|
|
244
|
-
const denied = await reconcileDeniedToolCalls(seeded, clickDenialLedger());
|
|
238
|
+
const denied = await reconcileDeniedToolCalls(seeded, builderOver(seeded), clickDenialLedger());
|
|
245
239
|
const redacted = clearProvisionalPostDenialNarration(seeded, denied);
|
|
246
240
|
|
|
247
241
|
const tools = allToolCalls(seeded);
|
|
@@ -282,9 +276,11 @@ describe("Cursor HITL resume — append-only transcript", () => {
|
|
|
282
276
|
|
|
283
277
|
it("FIX: a sub-agent's gated tool also survives resume (the seeded sub-agent rows are wrapped by reference and indexed)", () => {
|
|
284
278
|
// Sub-agent parity: the runtime seeds `status.subAgentExecutions` on a
|
|
285
|
-
// resume (`seedFromPersistedStatus
|
|
286
|
-
// array, exactly as it
|
|
287
|
-
// retained, indexed by id, and a
|
|
279
|
+
// resume (`seedFromPersistedStatus`, through the builder's `seed()`) and
|
|
280
|
+
// the builder holds that very array, exactly as it holds
|
|
281
|
+
// `status.messages`, so the seeded row is retained, indexed by id, and a
|
|
282
|
+
// resumed update lands on it in place. This arm hands the seeded status
|
|
283
|
+
// to the constructor, which indexes by the same routine `seed()` does.
|
|
288
284
|
const seededSub = create(SubAgentExecutionSchema, {
|
|
289
285
|
id: "sub_1",
|
|
290
286
|
name: "researcher",
|
|
@@ -292,11 +288,12 @@ describe("Cursor HITL resume — append-only transcript", () => {
|
|
|
292
288
|
});
|
|
293
289
|
const statusRows = [seededSub];
|
|
294
290
|
|
|
295
|
-
const
|
|
296
|
-
|
|
291
|
+
const status = create(AgentExecutionStatusSchema, {});
|
|
292
|
+
status.subAgentExecutions = statusRows;
|
|
293
|
+
new TranscriptBuilder("exec-resume", status).finalize();
|
|
297
294
|
|
|
298
|
-
expect(
|
|
299
|
-
expect(
|
|
295
|
+
expect(status.subAgentExecutions, "the status's own array, not a copy").toBe(statusRows);
|
|
296
|
+
expect(status.subAgentExecutions.some((s) => s.id === "sub_1")).toBe(true);
|
|
300
297
|
});
|
|
301
298
|
|
|
302
299
|
it("FIX: the approved tools are ALLOWED by the hook on resume — not re-denied (the loop's source)", () => {
|
|
@@ -404,12 +401,10 @@ describe("Cursor HITL resume — two approvals then clean completion (no loop)",
|
|
|
404
401
|
const committed = committedBuiltInApprovals();
|
|
405
402
|
const seeded = committed.map((m) => clone(AgentMessageSchema, m));
|
|
406
403
|
|
|
407
|
-
|
|
408
|
-
for (const event of builtInResumeEvents()) acc.processEvent(event);
|
|
409
|
-
acc.finalize();
|
|
404
|
+
new CursorFold({ messages: seeded }).events(...builtInResumeEvents()).finalize();
|
|
410
405
|
|
|
411
406
|
// The hook allowed both (no denials this turn), so the overlay adds nothing.
|
|
412
|
-
const denied = await reconcileDeniedToolCalls(seeded, []);
|
|
407
|
+
const denied = await reconcileDeniedToolCalls(seeded, builderOver(seeded), []);
|
|
413
408
|
expect(denied).toHaveLength(0);
|
|
414
409
|
|
|
415
410
|
const tools = allToolCalls(seeded);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @regression file-hitl-phase0 — pins
|
|
2
|
+
* @regression file-hitl-phase0 — pins that decisions bind to the active turn's
|
|
3
|
+
* denial ledger, never a stale one, and that a resume respects its order.
|
|
3
4
|
*
|
|
4
5
|
* Behavior tests for the generated preToolUse bash hook.
|
|
5
6
|
*
|
|
@@ -312,7 +312,7 @@ describe("http2-interceptor", () => {
|
|
|
312
312
|
});
|
|
313
313
|
});
|
|
314
314
|
|
|
315
|
-
describe("the token ref is read per request (the root rotates it in place
|
|
315
|
+
describe("the token ref is read per request (the root rotates it in place)", () => {
|
|
316
316
|
let mock: ReturnType<typeof createMockConnect>;
|
|
317
317
|
let proxyTokenRef: { current: string | null };
|
|
318
318
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* The Cursor prompt, whole, as goldens — one per shape `buildPrompt` selects.
|
|
3
3
|
*
|
|
4
4
|
* `build-prompt.test.ts` pins every branch with `toContain`; the hermetic
|
|
5
|
-
* goldens are status JSON and never see a prompt. So until
|
|
5
|
+
* goldens are status JSON and never see a prompt. So until #1096 no test
|
|
6
6
|
* pinned a rendered Cursor prompt byte for byte. These goldens are the
|
|
7
7
|
* photograph taken BEFORE the shared prompt glue moved into
|
|
8
|
-
* `shared/prompt-sections.ts` (
|
|
8
|
+
* `shared/prompt-sections.ts` (#1096), so the move could be proven
|
|
9
9
|
* byte-identical except where a ruling says otherwise — the same discipline
|
|
10
|
-
*
|
|
10
|
+
* the hermetic net applied to the activity's status (#1048).
|
|
11
11
|
*
|
|
12
12
|
* The shapes (`buildPrompt`'s four, plus the two per-execution directives):
|
|
13
13
|
* the enhanced prompt on a first execution with every section populated
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* and the HITL recovery on a fresh agent mid-HITL.
|
|
23
23
|
*
|
|
24
24
|
* Rulings that moved a golden are quoted here:
|
|
25
|
-
* -
|
|
25
|
+
* - 2026-09-14 (#1096). Every `<input_files>` bullet gained the
|
|
26
26
|
* file's size — `- \`.stigmer/inputs/spec.pdf\`` became
|
|
27
27
|
* `- \`.stigmer/inputs/spec.pdf\` (204800 bytes)` — in the four goldens
|
|
28
28
|
* that carry attachments (`enhanced.everything`, `enhanced.plan-mode`,
|
|
@@ -176,7 +176,7 @@ function everything(reason: AgentResolutionReason, overrides: Partial<BuildPromp
|
|
|
176
176
|
// Goldens
|
|
177
177
|
// ---------------------------------------------------------------------------
|
|
178
178
|
|
|
179
|
-
describe("Cursor prompt goldens
|
|
179
|
+
describe("Cursor prompt goldens", () => {
|
|
180
180
|
it("the enhanced prompt on a first execution, every section populated", async () => {
|
|
181
181
|
const prompt = buildPrompt(everything("created_first_execution"));
|
|
182
182
|
await expect(prompt).toMatchFileSnapshot("./goldens/prompt.enhanced.everything.prompt.md");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A later, same-identity proposal is a NEW act: it never lands on a row the
|
|
3
|
-
* user already decided (
|
|
3
|
+
* user already decided (found by the contract kit in #1070).
|
|
4
4
|
*
|
|
5
5
|
* The defect the harness contract kit found against this adapter: within one
|
|
6
6
|
* execution, after the user APPROVED `edit a.txt` and the resumed agent ran
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* one — flipped it back to WAITING_APPROVAL with its APPROVE still on it and
|
|
12
12
|
* wiped its result; the actual streamed call was hidden as a twin. On the next
|
|
13
13
|
* invocation `approvalDecisionsOf` read that row as a decision and the new,
|
|
14
|
-
* never-approved proposal ran under the old approval. The
|
|
14
|
+
* never-approved proposal ran under the old approval. The stream fold had the
|
|
15
15
|
* sibling flaw: a re-issue after a SKIP or REJECT was reconciled onto the
|
|
16
16
|
* declined row by identity, inheriting its decision.
|
|
17
17
|
*
|
|
18
|
-
* The rule, in `
|
|
18
|
+
* The rule, in `boundary-rows.ts` and the translator's seeded-row match: a row the server has adjudicated
|
|
19
19
|
* (`isAdjudicatedRow`) is never the home of THIS turn's denial and never a
|
|
20
20
|
* twin to collapse; a row the user DECLINED (`isDeclinedRow`) is never the
|
|
21
21
|
* home of a later same-identity call. The approved re-issue (the
|
|
@@ -36,7 +36,9 @@ import { ApprovalAction, MessageType, ToolCallStatus } from "@stigmer/protos/ai/
|
|
|
36
36
|
import type { SDKMessage } from "@cursor/sdk";
|
|
37
37
|
|
|
38
38
|
import { approvalDecisionsOf } from "../../../harness/approval-decisions.js";
|
|
39
|
-
import {
|
|
39
|
+
import { reconcileDeniedToolCalls } from "../boundary-rows.js";
|
|
40
|
+
import { CursorFold, builderOver } from "../__test-utils__/fold.js";
|
|
41
|
+
import { toolCallIdentityToken } from "../approval-state.js";
|
|
40
42
|
import type { DeniedLedgerEntry } from "../approval-state.js";
|
|
41
43
|
|
|
42
44
|
const PATH = "/work/a.txt";
|
|
@@ -83,12 +85,9 @@ function allToolCalls(messages: AgentMessage[]): ToolCall[] {
|
|
|
83
85
|
|
|
84
86
|
/** The later turn: the model proposes the same edit under a fresh id, the hook denies it, the turn boundary reconciles. */
|
|
85
87
|
async function laterTurnProposesSameEdit(seeded: AgentMessage[]): Promise<ToolCall[]> {
|
|
86
|
-
|
|
87
|
-
acc.processEvent(toolCallEvent(LATER_ID, "running"));
|
|
88
|
-
acc.processEvent(toolCallEvent(LATER_ID, "error", "Blocked by hook"));
|
|
89
|
-
acc.finalize();
|
|
88
|
+
new CursorFold({ messages: seeded }).events(toolCallEvent(LATER_ID, "running"), toolCallEvent(LATER_ID, "error", "Blocked by hook")).finalize();
|
|
90
89
|
const ledger: DeniedLedgerEntry[] = [{ toolName: "Write", token: toolCallIdentityToken(allToolCalls(seeded).find((tc) => tc.id === LATER_ID)!) }];
|
|
91
|
-
return reconcileDeniedToolCalls(seeded, ledger);
|
|
90
|
+
return reconcileDeniedToolCalls(seeded, builderOver(seeded), ledger);
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
function decisionsTheRuntimeWouldRead(messages: AgentMessage[]): ReadonlyMap<string, ApprovalAction> {
|
|
@@ -158,10 +157,9 @@ describe("a later same-identity proposal never lands on a decided row (F9)", ()
|
|
|
158
157
|
}),
|
|
159
158
|
];
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
acc.finalize();
|
|
160
|
+
new CursorFold({ messages: seeded })
|
|
161
|
+
.events(toolCallEvent(`${FIRST_ID}_RESUME`, "running"), toolCallEvent(`${FIRST_ID}_RESUME`, "completed", RESULT_OF_FIRST))
|
|
162
|
+
.finalize();
|
|
165
163
|
|
|
166
164
|
const tools = allToolCalls(seeded);
|
|
167
165
|
expect(tools.map((tc) => tc.id), "one row, the committed id").toEqual([FIRST_ID]);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @regression file-hitl-phase0 — pins
|
|
2
|
+
* @regression file-hitl-phase0 — pins that decisions bind to the active turn's
|
|
3
|
+
* denial ledger, never a stale one, and that a resume respects its order.
|
|
3
4
|
*
|
|
4
5
|
* Cursor analog of execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts:
|
|
5
6
|
* two SEQUENTIAL approval gates across a resume, on the Cursor deny-and-reconcile
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
* for the first time — and the REAL bash hook must ALLOW A's re-issue while
|
|
22
23
|
* DENYING B, the out-of-process half the native gate has no equivalent for.
|
|
23
24
|
*
|
|
24
|
-
* Exercises the
|
|
25
|
+
* Exercises the translator + builder + denial reconciliation (the units that own
|
|
25
26
|
* the Cursor resume emitter) plus the generated hook, keeping the reproduction
|
|
26
27
|
* hermetic and pinned to the exact code under change.
|
|
27
28
|
*/
|
|
@@ -40,11 +41,9 @@ import {
|
|
|
40
41
|
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
41
42
|
import type { SDKMessage } from "@cursor/sdk";
|
|
42
43
|
|
|
43
|
-
import {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
toolCallIdentityToken,
|
|
47
|
-
} from "../message-translator.js";
|
|
44
|
+
import { reconcileDeniedToolCalls } from "../boundary-rows.js";
|
|
45
|
+
import { CursorFold, builderOver } from "../__test-utils__/fold.js";
|
|
46
|
+
import { toolCallIdentityToken } from "../approval-state.js";
|
|
48
47
|
import {
|
|
49
48
|
buildApprovalGrants,
|
|
50
49
|
buildApprovalState,
|
|
@@ -139,16 +138,14 @@ describe("Cursor sequential gates A->B across resume", () => {
|
|
|
139
138
|
const committed = approvedGateA();
|
|
140
139
|
const seeded = committed.map((m) => clone(AgentMessageSchema, m));
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
for (const event of resumeIntoGateB()) acc.processEvent(event);
|
|
144
|
-
acc.finalize();
|
|
141
|
+
new CursorFold({ messages: seeded }).events(...resumeIntoGateB()).finalize();
|
|
145
142
|
|
|
146
143
|
// Gate B was denied this turn; its identity comes off the reconciled call.
|
|
147
144
|
const bCall = allToolCalls(seeded).find((tc) => tc.name === "shell")!;
|
|
148
145
|
const ledger: DeniedLedgerEntry[] = [
|
|
149
146
|
{ toolName: "shell", token: toolCallIdentityToken(bCall) },
|
|
150
147
|
];
|
|
151
|
-
await reconcileDeniedToolCalls(seeded, ledger);
|
|
148
|
+
await reconcileDeniedToolCalls(seeded, builderOver(seeded), ledger);
|
|
152
149
|
|
|
153
150
|
const tools = allToolCalls(seeded);
|
|
154
151
|
const byId = new Map(tools.map((tc) => [tc.id, tc]));
|