@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
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins the skills phase (`turn-context.ts` `mountSkills`) as the runtime's
|
|
3
|
+
* one reader of skills for EVERY owner: the root's merged refs and each
|
|
4
|
+
* sub-agent's own, resolved through one resolver into `TurnSkills`.
|
|
5
|
+
*
|
|
6
|
+
* What is asserted: the shape (root vs a map keyed by sub-agent name; no
|
|
7
|
+
* entry for a sub-agent without refs), that a skill the root and a sub-agent
|
|
8
|
+
* share is fetched per owner but MOUNTED once (the hash-keyed mount marker,
|
|
9
|
+
* so the second write is a cache hit), that one owner's failing ref costs
|
|
10
|
+
* that owner alone (the root's skills stand; the sub-agent gets what
|
|
11
|
+
* resolved), and that a harness without sub-agents (`capabilities.subAgents`
|
|
12
|
+
* false) resolves the root only — the flag's first reader. The phase reports
|
|
13
|
+
* its one label, so the runtime's label list is unchanged.
|
|
14
|
+
*
|
|
15
|
+
* The control-plane client is doubled at its module boundary with scripted
|
|
16
|
+
* skills; `HOME` is the hermetic environment's, so the mounts land under a
|
|
17
|
+
* temp platform dir and nothing touches the developer's `~/.stigmer`.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
21
|
+
import { mkdirSync } from "node:fs";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { create } from "@bufbuild/protobuf";
|
|
24
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
25
|
+
import { SubAgentSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
26
|
+
import { SkillSchema, type Skill } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
|
|
27
|
+
import { ApiResourceReferenceSchema, type ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
|
|
28
|
+
|
|
29
|
+
import { createHermeticEnvironment } from "../../__test-utils__/hermetic-activity.js";
|
|
30
|
+
import { mockStigmerClient } from "../../__test-utils__/mock-client.js";
|
|
31
|
+
import { testConfig } from "../../__test-utils__/config-fixture.js";
|
|
32
|
+
import { turnInputFixture } from "../../__test-utils__/turn-input-fixture.js";
|
|
33
|
+
import { TimingRecorder } from "../../shared/cold-start-timing.js";
|
|
34
|
+
import { mountSkills, type ResolutionDeps } from "../turn-context.js";
|
|
35
|
+
|
|
36
|
+
const env = createHermeticEnvironment();
|
|
37
|
+
|
|
38
|
+
function ref(slug: string): ApiResourceReference {
|
|
39
|
+
return create(ApiResourceReferenceSchema, { slug, org: "kit-org" });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function skill(slug: string): Skill {
|
|
43
|
+
return create(SkillSchema, {
|
|
44
|
+
metadata: { id: `skill-${slug}`, slug, org: "kit-org" },
|
|
45
|
+
spec: { name: slug, description: `The ${slug} skill`, skillMd: `# ${slug}` },
|
|
46
|
+
status: { versionHash: `hash-${slug}` },
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A client that answers the scripted skills by slug and refuses the rest; every fetch is counted. */
|
|
51
|
+
function skillClient(available: readonly string[]) {
|
|
52
|
+
const fetches: string[] = [];
|
|
53
|
+
const client = mockStigmerClient({
|
|
54
|
+
getSkillByReference: vi.fn(async (r: ApiResourceReference) => {
|
|
55
|
+
fetches.push(r.slug);
|
|
56
|
+
if (!available.includes(r.slug)) throw new Error(`skill ${r.slug} not found`);
|
|
57
|
+
return skill(r.slug);
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
return { client, fetches };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function depsWith(client: ResolutionDeps["client"], sessionId: string): { deps: ResolutionDeps; labels: string[] } {
|
|
64
|
+
const labels: string[] = [];
|
|
65
|
+
return {
|
|
66
|
+
labels,
|
|
67
|
+
deps: {
|
|
68
|
+
input: { executionId: `aex-${sessionId}`, threadId: "", turnSeq: 0 },
|
|
69
|
+
client,
|
|
70
|
+
config: testConfig({ workspaceRootDir: env.workspaceRootDir }),
|
|
71
|
+
status: create(AgentExecutionStatusSchema, {}),
|
|
72
|
+
artifactStorage: undefined,
|
|
73
|
+
timing: new TimingRecorder(),
|
|
74
|
+
signal: new AbortController().signal,
|
|
75
|
+
heartbeat: () => {},
|
|
76
|
+
enterPhase: () => {},
|
|
77
|
+
reportProgress: async (label) => {
|
|
78
|
+
labels.push(label);
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function blueprintWith(rootRefs: readonly string[], subAgents: ReadonlyArray<{ name: string; refs: readonly string[] }>) {
|
|
85
|
+
return turnInputFixture({
|
|
86
|
+
blueprint: {
|
|
87
|
+
mergedSkillRefs: rootRefs.map(ref),
|
|
88
|
+
subAgents: subAgents.map((sa) => create(SubAgentSchema, { name: sa.name, skillRefs: sa.refs.map(ref) })),
|
|
89
|
+
},
|
|
90
|
+
}).blueprint;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
describe("mountSkills: the runtime resolves every owner's skills", () => {
|
|
94
|
+
let n = 0;
|
|
95
|
+
let sessionId: string;
|
|
96
|
+
let primaryDir: string;
|
|
97
|
+
|
|
98
|
+
beforeAll(() => {
|
|
99
|
+
mkdirSync(env.workspaceRootDir, { recursive: true });
|
|
100
|
+
});
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
sessionId = `ses-skills-${++n}`;
|
|
103
|
+
primaryDir = join(env.workspaceRootDir, sessionId);
|
|
104
|
+
mkdirSync(primaryDir, { recursive: true });
|
|
105
|
+
});
|
|
106
|
+
afterAll(() => {
|
|
107
|
+
env.dispose();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("resolves the root's merged refs and each sub-agent's own, keyed by the sub-agent's name; a sub-agent without refs has no entry", async () => {
|
|
111
|
+
const { client } = skillClient(["alpha", "beta", "gamma"]);
|
|
112
|
+
const { deps, labels } = depsWith(client, sessionId);
|
|
113
|
+
const skills = await mountSkills(deps, {
|
|
114
|
+
blueprint: blueprintWith(["alpha"], [{ name: "researcher", refs: ["beta", "gamma"] }, { name: "writer", refs: [] }]),
|
|
115
|
+
sessionId,
|
|
116
|
+
primaryDir,
|
|
117
|
+
subAgents: true,
|
|
118
|
+
});
|
|
119
|
+
expect(skills.root.map((s) => s.name)).toEqual(["alpha"]);
|
|
120
|
+
expect([...skills.bySubAgent.keys()]).toEqual(["researcher"]);
|
|
121
|
+
expect(skills.bySubAgent.get("researcher")!.map((s) => s.name)).toEqual(["beta", "gamma"]);
|
|
122
|
+
expect(skills.bySubAgent.get("researcher")![0]!.path, "a sub-agent's skill mounts where the root's do").toBe(".stigmer/skills/beta/SKILL.md");
|
|
123
|
+
expect(labels, "one label for the whole phase").toEqual(["Resolving skills"]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("a skill the root and a sub-agent share is fetched per owner but mounted once (the second resolution is a mount-cache hit)", async () => {
|
|
127
|
+
const { client, fetches } = skillClient(["shared"]);
|
|
128
|
+
const { deps } = depsWith(client, sessionId);
|
|
129
|
+
const writes = vi.spyOn(await import("../../shared/skill-mount.js"), "writeSkillMount");
|
|
130
|
+
const skills = await mountSkills(deps, {
|
|
131
|
+
blueprint: blueprintWith(["shared"], [{ name: "researcher", refs: ["shared"] }]),
|
|
132
|
+
sessionId,
|
|
133
|
+
primaryDir,
|
|
134
|
+
subAgents: true,
|
|
135
|
+
});
|
|
136
|
+
expect(skills.root.map((s) => s.name)).toEqual(["shared"]);
|
|
137
|
+
expect(skills.bySubAgent.get("researcher")!.map((s) => s.name)).toEqual(["shared"]);
|
|
138
|
+
expect(fetches, "the control plane is asked once per owner").toEqual(["shared", "shared"]);
|
|
139
|
+
expect(writes, "the mount is written once; the second owner hits the hash-keyed marker").toHaveBeenCalledTimes(1);
|
|
140
|
+
writes.mockRestore();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("one owner's failing ref costs that owner alone: the root's skills stand and the sub-agent gets what resolved", async () => {
|
|
144
|
+
const { client } = skillClient(["alpha", "beta"]);
|
|
145
|
+
const { deps } = depsWith(client, sessionId);
|
|
146
|
+
const skills = await mountSkills(deps, {
|
|
147
|
+
blueprint: blueprintWith(["alpha"], [{ name: "researcher", refs: ["missing", "beta"] }]),
|
|
148
|
+
sessionId,
|
|
149
|
+
primaryDir,
|
|
150
|
+
subAgents: true,
|
|
151
|
+
});
|
|
152
|
+
expect(skills.root.map((s) => s.name)).toEqual(["alpha"]);
|
|
153
|
+
expect(skills.bySubAgent.get("researcher")!.map((s) => s.name), "warned and skipped, never thrown").toEqual(["beta"]);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("a harness without sub-agents resolves the root only: no sub-agent ref is fetched", async () => {
|
|
157
|
+
const { client, fetches } = skillClient(["alpha", "beta"]);
|
|
158
|
+
const { deps } = depsWith(client, sessionId);
|
|
159
|
+
const skills = await mountSkills(deps, {
|
|
160
|
+
blueprint: blueprintWith(["alpha"], [{ name: "researcher", refs: ["beta"] }]),
|
|
161
|
+
sessionId,
|
|
162
|
+
primaryDir,
|
|
163
|
+
subAgents: false,
|
|
164
|
+
});
|
|
165
|
+
expect(skills.root.map((s) => s.name)).toEqual(["alpha"]);
|
|
166
|
+
expect(skills.bySubAgent.size).toBe(0);
|
|
167
|
+
expect(fetches).toEqual(["alpha"]);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
@@ -10,9 +10,11 @@ import { create } from "@bufbuild/protobuf";
|
|
|
10
10
|
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
11
11
|
import { UpdateStatusResponseSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
|
|
12
12
|
import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
|
|
13
|
-
import { ExecutionControlSignal, MessageType, ServiceTier, ThinkingMode, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
13
|
+
import { ExecutionControlSignal, FileChangeKind, MessageType, ServiceTier, ThinkingMode, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
14
14
|
|
|
15
15
|
import type { StigmerClient } from "../../client/stigmer-client.js";
|
|
16
|
+
import type { TurnProgress } from "../capture.js";
|
|
17
|
+
import { newProgressCaptureState, type ProgressSubstrate } from "../../shared/filereview/progress.js";
|
|
16
18
|
import { PersistChokepoint } from "../persist-chokepoint.js";
|
|
17
19
|
import { UsageAccumulator } from "../usage-accumulator.js";
|
|
18
20
|
|
|
@@ -43,7 +45,10 @@ function heldClient(answers: ExecutionControlSignal[] = []) {
|
|
|
43
45
|
return { client, gates, writes };
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
function chokepointOver(
|
|
48
|
+
function chokepointOver(
|
|
49
|
+
client: StigmerClient,
|
|
50
|
+
options: { usage?: UsageAccumulator; progress?: TurnProgress; onPlatformStop?: () => void } = {},
|
|
51
|
+
) {
|
|
47
52
|
const status = create(AgentExecutionStatusSchema, {});
|
|
48
53
|
const heartbeat = vi.fn();
|
|
49
54
|
const onPlatformStop = options.onPlatformStop ?? vi.fn();
|
|
@@ -53,6 +58,7 @@ function chokepointOver(client: StigmerClient, options: { usage?: UsageAccumulat
|
|
|
53
58
|
status,
|
|
54
59
|
offload: undefined,
|
|
55
60
|
usage: () => options.usage,
|
|
61
|
+
progress: () => options.progress,
|
|
56
62
|
heartbeat,
|
|
57
63
|
onPlatformStop,
|
|
58
64
|
});
|
|
@@ -90,6 +96,36 @@ describe("PersistChokepoint: one write", () => {
|
|
|
90
96
|
expect(onPlatformStop).toHaveBeenCalledTimes(1);
|
|
91
97
|
});
|
|
92
98
|
|
|
99
|
+
it("refreshes file_change_progress from the turn's capture before the write, and re-attaches only when the tree moved", async () => {
|
|
100
|
+
const { client, gates } = heldClient();
|
|
101
|
+
const captures: boolean[] = [true, false];
|
|
102
|
+
const substrate: ProgressSubstrate = {
|
|
103
|
+
capture: async () => ({
|
|
104
|
+
delta: { entries: [{ pathBefore: "a.md", pathAfter: "a.md", kind: FileChangeKind.MODIFY, linesAdded: 2, linesRemoved: 0 }] },
|
|
105
|
+
changed: captures.shift() ?? false,
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
const { chokepoint, status } = chokepointOver(client, {
|
|
109
|
+
progress: { changeSetId: "aex_test:0", substrate, state: newProgressCaptureState() },
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const first = chokepoint.write();
|
|
113
|
+
await vi.waitFor(() => expect(gates).toHaveLength(1));
|
|
114
|
+
expect(status.fileChangeProgress?.changeSetId, "attached before the bytes leave").toBe("aex_test:0");
|
|
115
|
+
expect(status.fileChangeProgress?.linesAdded).toBe(2);
|
|
116
|
+
const attachedAt = status.fileChangeProgress?.capturedAt;
|
|
117
|
+
gates[0]!.open();
|
|
118
|
+
await first;
|
|
119
|
+
|
|
120
|
+
// The floor (2 s) has not elapsed for the second write: no capture, the
|
|
121
|
+
// snapshot stands; a capture that reports `changed: false` would stand too.
|
|
122
|
+
const second = chokepoint.write();
|
|
123
|
+
await vi.waitFor(() => expect(gates).toHaveLength(2));
|
|
124
|
+
expect(status.fileChangeProgress?.capturedAt).toBe(attachedAt);
|
|
125
|
+
gates[1]!.open();
|
|
126
|
+
await second;
|
|
127
|
+
});
|
|
128
|
+
|
|
93
129
|
it("writes no streaming_usage when no turn was reported", async () => {
|
|
94
130
|
const { client, gates } = heldClient();
|
|
95
131
|
const { chokepoint, status } = chokepointOver(client, { usage: new UsageAccumulator() });
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The turn runtime under a DETERMINISTIC state id, proven without any engine:
|
|
3
|
+
* the scripted fake adapter declaring `stateIdSource: "deterministic"` (the
|
|
4
|
+
* native harness's posture — `thread-{sessionId}` exists before any engine
|
|
5
|
+
* does) through the kit's runtime-side half under `MockActivityEnvironment`.
|
|
6
|
+
*
|
|
7
|
+
* `run-turn.test.ts` runs the same half under `engine-minted`; this file is
|
|
8
|
+
* the other arm of `isReinvocation` (`turn-context.ts`): here the thread id
|
|
9
|
+
* is present on the FIRST turn, so the runtime's reinvocation fact — the
|
|
10
|
+
* seed, the reconcile, the exact-apply — must come from the persisted
|
|
11
|
+
* transcript and from nothing else. Every kit arm that resumes (the approval
|
|
12
|
+
* round trip) therefore exercises that arm end to end, and the bind arm is
|
|
13
|
+
* reported SKIPPED (a deterministic harness never binds).
|
|
14
|
+
*
|
|
15
|
+
* What is asserted HERE beside the kit are the deterministic FACTS the
|
|
16
|
+
* engine-minted file cannot show: no session write ever happens (there is
|
|
17
|
+
* no id to bind), and a first turn with a thread id already present is
|
|
18
|
+
* still a first turn (nothing seeded, no decision read).
|
|
19
|
+
*
|
|
20
|
+
* Its own file, not a second block in `run-turn.test.ts`: the hermetic
|
|
21
|
+
* environment is created at module level because the subject's `config` is
|
|
22
|
+
* read at collection time, and the forks pool keeps each file's environment
|
|
23
|
+
* private.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
27
|
+
import { ExecutionPhase } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
28
|
+
|
|
29
|
+
vi.mock("../../client/stigmer-client.js", async () =>
|
|
30
|
+
(await import("../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
import { ScriptedClock, createHermeticEnvironment } from "../../__test-utils__/hermetic-activity.js";
|
|
34
|
+
import { stubRegistryFetch } from "../../__test-utils__/model-registry-fixture.js";
|
|
35
|
+
import { scriptedSubject } from "../../__test-utils__/harness-contract/scripted-adapter.js";
|
|
36
|
+
import {
|
|
37
|
+
assertApprovalRoundTrip,
|
|
38
|
+
assertCompletedTurn,
|
|
39
|
+
describeHarnessRuntimeContract,
|
|
40
|
+
type RuntimeContractHarness,
|
|
41
|
+
} from "../../__test-utils__/harness-contract/runtime-contract.js";
|
|
42
|
+
|
|
43
|
+
const TASK_QUEUE = "runtime-deterministic-test-queue";
|
|
44
|
+
|
|
45
|
+
const env = createHermeticEnvironment();
|
|
46
|
+
const clock = new ScriptedClock();
|
|
47
|
+
const subject = scriptedSubject({
|
|
48
|
+
pausePrimitive: "interrupt",
|
|
49
|
+
stateIdSource: "deterministic",
|
|
50
|
+
config: { workspaceRootDir: env.workspaceRootDir, taskQueue: TASK_QUEUE },
|
|
51
|
+
});
|
|
52
|
+
const harness: RuntimeContractHarness = { subject, env, clock };
|
|
53
|
+
|
|
54
|
+
describe("run-turn: the deterministic fake adapter through the real runtime", () => {
|
|
55
|
+
let registry: ReturnType<typeof stubRegistryFetch>;
|
|
56
|
+
|
|
57
|
+
beforeAll(() => {
|
|
58
|
+
registry = stubRegistryFetch();
|
|
59
|
+
clock.install();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterAll(() => {
|
|
63
|
+
clock.uninstall();
|
|
64
|
+
registry.restore();
|
|
65
|
+
env.dispose();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describeHarnessRuntimeContract(harness);
|
|
69
|
+
|
|
70
|
+
describe("the deterministic facts", () => {
|
|
71
|
+
beforeAll(async () => {
|
|
72
|
+
await subject.adapter.boot(subject.config);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("a first turn with the thread id already present is a first turn: nothing seeded, no session write", async () => {
|
|
76
|
+
clock.reset();
|
|
77
|
+
const { driver, final } = await assertCompletedTurn(harness, "det-completed");
|
|
78
|
+
expect(driver.record.persistedPhases).toEqual([ExecutionPhase.EXECUTION_IN_PROGRESS, ExecutionPhase.EXECUTION_COMPLETED]);
|
|
79
|
+
expect(driver.record.sessionUpdates, "a deterministic harness never binds a state id").toHaveLength(0);
|
|
80
|
+
expect(final.messages.length, "the transcript is this turn's alone").toBeGreaterThan(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("the approval round trip resumes on the transcript, not the thread id: the WAITING row is carried and settled, and no session write happens", async () => {
|
|
84
|
+
clock.reset();
|
|
85
|
+
const { driver } = await assertApprovalRoundTrip(harness, "det-approval");
|
|
86
|
+
expect(driver.record.persistedPhases).toEqual([
|
|
87
|
+
ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
|
|
88
|
+
ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
89
|
+
ExecutionPhase.EXECUTION_COMPLETED,
|
|
90
|
+
]);
|
|
91
|
+
expect(driver.record.sessionUpdates).toHaveLength(0);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -38,24 +38,25 @@ vi.mock("../../client/stigmer-client.js", async () =>
|
|
|
38
38
|
import { ScriptedClock, createHermeticEnvironment } from "../../__test-utils__/hermetic-activity.js";
|
|
39
39
|
import { stubRegistryFetch } from "../../__test-utils__/model-registry-fixture.js";
|
|
40
40
|
import { scriptedSubject } from "../../__test-utils__/harness-contract/scripted-adapter.js";
|
|
41
|
+
import { initGitWorkspace } from "../../__test-utils__/git-workspace-fixture.js";
|
|
42
|
+
import { scenario } from "../../__test-utils__/harness-contract/types.js";
|
|
41
43
|
import {
|
|
42
44
|
COST_CAP_FAKE_PRICE_USD,
|
|
43
45
|
FAILURE_MESSAGES,
|
|
44
|
-
NEVER_SEEN,
|
|
45
46
|
RUNTIME_SETUP_LABELS,
|
|
46
|
-
RuntimeExecutionDriver,
|
|
47
47
|
aiMessages,
|
|
48
48
|
assertApprovalRoundTrip,
|
|
49
49
|
assertCompletedTurn,
|
|
50
50
|
assertCostCapTerminates,
|
|
51
51
|
assertFailedSurfaceWritesItsCopy,
|
|
52
|
+
assertNonExecutingDecisionSettlesSkipped,
|
|
52
53
|
assertRejectedBindFails,
|
|
53
54
|
describeHarnessRuntimeContract,
|
|
55
|
+
RuntimeExecutionDriver,
|
|
54
56
|
slimOf,
|
|
55
57
|
systemMessages,
|
|
56
58
|
type RuntimeContractHarness,
|
|
57
59
|
} from "../../__test-utils__/harness-contract/runtime-contract.js";
|
|
58
|
-
import { scenario } from "../../__test-utils__/harness-contract/types.js";
|
|
59
60
|
import { TERMINAL_COPY } from "../terminal-table.js";
|
|
60
61
|
|
|
61
62
|
const TASK_QUEUE = "runtime-test-queue";
|
|
@@ -137,29 +138,44 @@ describe("run-turn: the fake adapter through the real runtime", () => {
|
|
|
137
138
|
expect(aiMessages(final)).toEqual([]);
|
|
138
139
|
});
|
|
139
140
|
|
|
140
|
-
it("REJECT
|
|
141
|
-
//
|
|
142
|
-
// (`
|
|
143
|
-
//
|
|
144
|
-
// harness
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
// deliberately NOT in the kit (S2 M4 finding F1, Q-M4-1).
|
|
141
|
+
it("REJECT continues the run without the tool and the row settles SKIPPED with its reason (stigmer#197; S3 M1, Q-S3-2)", async () => {
|
|
142
|
+
// Until S3 M1 this arm pinned the opposite: the runtime FAILED a
|
|
143
|
+
// reinvocation carrying any REJECT (`rejectedByUserArm`, Cursor's
|
|
144
|
+
// legacy), against the proto's `APPROVAL_ACTION_REJECT` doc, the
|
|
145
|
+
// conformance suite and the native harness (S2 M4 finding F1, Q-M4-1).
|
|
146
|
+
// The kit's runtime half now carries the contract for every subject;
|
|
147
|
+
// what is the fake's own here is the persist cadence around it.
|
|
148
148
|
clock.reset();
|
|
149
|
-
const driver =
|
|
150
|
-
|
|
149
|
+
const { driver, final } = await assertNonExecutingDecisionSettlesSkipped(harness, ApprovalAction.REJECT, "fake-reject");
|
|
150
|
+
expect(driver.record.persistedPhases).toEqual([
|
|
151
|
+
ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
|
|
152
|
+
ExecutionPhase.EXECUTION_IN_PROGRESS,
|
|
153
|
+
ExecutionPhase.EXECUTION_COMPLETED,
|
|
154
|
+
]);
|
|
155
|
+
expect(aiMessages(final)).toContain("Moving on.");
|
|
156
|
+
expect(systemMessages(final), "no terminal copy: the run ended normally").toEqual([]);
|
|
157
|
+
});
|
|
151
158
|
|
|
152
|
-
|
|
159
|
+
it("structured output on a file-review-pending turn is resolved before the pause and rides the reconcile's completion (Q-M4-8)", async () => {
|
|
160
|
+
clock.reset();
|
|
161
|
+
const driver = new RuntimeExecutionDriver(harness, "fake-review-structured", {
|
|
162
|
+
structuredOutputSchema: { type: "object", properties: { answer: { type: "number" } }, required: ["answer"] },
|
|
163
|
+
});
|
|
164
|
+
initGitWorkspace(driver.workspaceDir, { "README.md": "# kit\n" });
|
|
165
|
+
|
|
166
|
+
// The engine edits a file and answers in JSON (tier 1 extracts it; no
|
|
167
|
+
// LLM is asked), then the runtime pauses for the review.
|
|
168
|
+
const first = await driver.turn([scenario.flowingWrite("fake-review-structured-w", "answer.md"), scenario.say('{"answer": 42}')]);
|
|
153
169
|
expect(slimOf(subject, first).phase).toBe("EXECUTION_WAITING_FOR_APPROVAL");
|
|
154
|
-
driver.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
expect(
|
|
161
|
-
expect(
|
|
162
|
-
expect(
|
|
170
|
+
expect(driver.record.lastFullStatus?.structuredOutput, "resolved before the WAITING persist").toEqual({ answer: 42 });
|
|
171
|
+
|
|
172
|
+
clock.tick();
|
|
173
|
+
driver.record.decideCapturedFileChanges({ approve: ["answer.md"] }, new Date().toISOString());
|
|
174
|
+
const second = await driver.turn([]);
|
|
175
|
+
const slim = slimOf(subject, second);
|
|
176
|
+
expect(slim.phase).toBe("EXECUTION_COMPLETED");
|
|
177
|
+
expect(slim.structured, "the pure-reconcile completion carries the answer as a value").toEqual({ answer: 42 });
|
|
178
|
+
expect(slim.final_text).toBe('{"answer": 42}');
|
|
163
179
|
});
|
|
164
180
|
});
|
|
165
181
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins which model the attachment phase asks the registry about when it
|
|
3
|
+
* sizes the vision budget (`turn-context.ts` `resolveTurnAttachments`): the
|
|
4
|
+
* model the execution named, or the registry's default when it named none —
|
|
5
|
+
* the model the native harness will build in that case. Before S3 M1 the
|
|
6
|
+
* phase asked about the raw executionConfig name, so an execution with no
|
|
7
|
+
* model named asked about `""` (always "unknown", read as sighted) while the
|
|
8
|
+
* native orchestrator asked about the resolved default (its `setup.ts`,
|
|
9
|
+
* retired with it).
|
|
10
|
+
*
|
|
11
|
+
* The registry module is doubled at its boundary: this test is about WHICH
|
|
12
|
+
* name is asked, not about the registry's answer. The phase is entered with
|
|
13
|
+
* no attachments so nothing touches the file system; the budget's decisions
|
|
14
|
+
* over real images are `shared/__tests__/attachment-vision.test.ts`'s.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
18
|
+
import { create } from "@bufbuild/protobuf";
|
|
19
|
+
import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
20
|
+
import { AgentExecutionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
|
|
21
|
+
|
|
22
|
+
vi.mock("../../shared/model-registry.js", () => ({
|
|
23
|
+
getDefaultModel: vi.fn(async () => "registry-default-model"),
|
|
24
|
+
getModelVisionCapability: vi.fn(async () => true),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
import { getDefaultModel, getModelVisionCapability } from "../../shared/model-registry.js";
|
|
28
|
+
import { DEEP_AGENT_VISION_PROFILE } from "../../shared/attachment-vision.js";
|
|
29
|
+
import { TimingRecorder } from "../../shared/cold-start-timing.js";
|
|
30
|
+
import { mockStigmerClient } from "../../__test-utils__/mock-client.js";
|
|
31
|
+
import { testConfig } from "../../__test-utils__/config-fixture.js";
|
|
32
|
+
import { resolveTurnAttachments, type ResolutionDeps } from "../turn-context.js";
|
|
33
|
+
|
|
34
|
+
function deps(): ResolutionDeps {
|
|
35
|
+
return {
|
|
36
|
+
input: { executionId: "aex_1", threadId: "", turnSeq: 0 },
|
|
37
|
+
client: mockStigmerClient(),
|
|
38
|
+
config: testConfig(),
|
|
39
|
+
status: create(AgentExecutionStatusSchema, {}),
|
|
40
|
+
artifactStorage: undefined,
|
|
41
|
+
timing: new TimingRecorder(),
|
|
42
|
+
signal: new AbortController().signal,
|
|
43
|
+
heartbeat: () => {},
|
|
44
|
+
enterPhase: () => {},
|
|
45
|
+
reportProgress: async () => {},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function resolveWithModel(modelName: string | undefined): Promise<void> {
|
|
50
|
+
await resolveTurnAttachments(deps(), {
|
|
51
|
+
spec: create(AgentExecutionSpecSchema, modelName === undefined ? {} : { executionConfig: { modelName } }),
|
|
52
|
+
sessionId: "ses_1",
|
|
53
|
+
primaryDir: "/nowhere",
|
|
54
|
+
visionProfile: DEEP_AGENT_VISION_PROFILE,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe("resolveTurnAttachments: the model the vision budget asks about", () => {
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
vi.mocked(getDefaultModel).mockClear();
|
|
61
|
+
vi.mocked(getModelVisionCapability).mockClear();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("asks about the model the execution named, without consulting the default", async () => {
|
|
65
|
+
await resolveWithModel("claude-haiku-4.5");
|
|
66
|
+
expect(vi.mocked(getModelVisionCapability)).toHaveBeenCalledWith("claude-haiku-4.5");
|
|
67
|
+
expect(vi.mocked(getDefaultModel)).not.toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("asks about the registry's default when the execution named none — the model the turn will run on, not the empty string", async () => {
|
|
71
|
+
await resolveWithModel(undefined);
|
|
72
|
+
expect(vi.mocked(getDefaultModel)).toHaveBeenCalledTimes(1);
|
|
73
|
+
expect(vi.mocked(getModelVisionCapability)).toHaveBeenCalledWith("registry-default-model");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("treats an empty model name as none", async () => {
|
|
77
|
+
await resolveWithModel("");
|
|
78
|
+
expect(vi.mocked(getModelVisionCapability)).toHaveBeenCalledWith("registry-default-model");
|
|
79
|
+
});
|
|
80
|
+
});
|