@stigmer/runner 3.0.9-dev.20260615153829 → 3.1.0
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/dist/.build-fingerprint +1 -1
- package/dist/__test-utils__/approval-contract/types.d.ts +174 -0
- package/dist/__test-utils__/approval-contract/types.js +24 -0
- package/dist/__test-utils__/approval-contract/types.js.map +1 -0
- package/dist/activities/call-agent-status.d.ts +19 -1
- package/dist/activities/call-agent-status.js +64 -5
- package/dist/activities/call-agent-status.js.map +1 -1
- package/dist/activities/call-llm.js +19 -53
- package/dist/activities/call-llm.js.map +1 -1
- package/dist/activities/classify-tool-approvals.d.ts +24 -0
- package/dist/activities/classify-tool-approvals.js +69 -17
- package/dist/activities/classify-tool-approvals.js.map +1 -1
- package/dist/activities/discover-mcp-server.d.ts +7 -0
- package/dist/activities/discover-mcp-server.js +11 -1
- package/dist/activities/discover-mcp-server.js.map +1 -1
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +140 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +130 -0
- package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.d.ts +18 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +123 -0
- package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -0
- package/dist/activities/execute-cursor/approval-policy.d.ts +17 -61
- package/dist/activities/execute-cursor/approval-policy.js +8 -120
- package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
- package/dist/activities/execute-cursor/approval-state.d.ts +219 -9
- package/dist/activities/execute-cursor/approval-state.js +233 -17
- package/dist/activities/execute-cursor/approval-state.js.map +1 -1
- package/dist/activities/execute-cursor/capture-flow.d.ts +127 -0
- package/dist/activities/execute-cursor/capture-flow.js +234 -0
- package/dist/activities/execute-cursor/capture-flow.js.map +1 -0
- package/dist/activities/execute-cursor/cas-observations.d.ts +96 -0
- package/dist/activities/execute-cursor/cas-observations.js +184 -0
- package/dist/activities/execute-cursor/cas-observations.js.map +1 -0
- package/dist/activities/execute-cursor/command-provenance.d.ts +62 -0
- package/dist/activities/execute-cursor/command-provenance.js +128 -0
- package/dist/activities/execute-cursor/command-provenance.js.map +1 -0
- package/dist/activities/execute-cursor/exact-apply.d.ts +110 -0
- package/dist/activities/execute-cursor/exact-apply.js +204 -0
- package/dist/activities/execute-cursor/exact-apply.js.map +1 -0
- package/dist/activities/execute-cursor/hook-script.d.ts +53 -24
- package/dist/activities/execute-cursor/hook-script.js +310 -47
- package/dist/activities/execute-cursor/hook-script.js.map +1 -1
- package/dist/activities/execute-cursor/index.d.ts +8 -1
- package/dist/activities/execute-cursor/index.js +500 -64
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/message-translator.d.ts +258 -11
- package/dist/activities/execute-cursor/message-translator.js +836 -90
- package/dist/activities/execute-cursor/message-translator.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +20 -23
- package/dist/activities/execute-cursor/prompt-builder.js +74 -15
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/workspace-setup.d.ts +17 -0
- package/dist/activities/execute-cursor/workspace-setup.js +212 -33
- package/dist/activities/execute-cursor/workspace-setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.d.ts +19 -0
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js +143 -0
- package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js.map +1 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +88 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +81 -0
- package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -0
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +47 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js +68 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -0
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +8 -1
- package/dist/activities/execute-deep-agent/attachment-injector.js +7 -7
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +42 -0
- package/dist/activities/execute-deep-agent/cas-capture-backend.js +47 -0
- package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +79 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js +112 -0
- package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -0
- package/dist/activities/execute-deep-agent/hitl.d.ts +16 -3
- package/dist/activities/execute-deep-agent/hitl.js +11 -3
- package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.d.ts +2 -1
- package/dist/activities/execute-deep-agent/index.js +393 -33
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/inline-publisher.d.ts +7 -1
- package/dist/activities/execute-deep-agent/inline-publisher.js +23 -2
- package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +53 -2
- package/dist/activities/execute-deep-agent/setup.js +149 -92
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +36 -0
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +56 -0
- package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +1 -0
- package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +34 -1
- package/dist/activities/execute-deep-agent/status-builder-shared.js +26 -25
- package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
- package/dist/activities/execute-deep-agent/status-builder.d.ts +17 -5
- package/dist/activities/execute-deep-agent/status-builder.js +44 -3
- package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming-side-effects.js +2 -19
- package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
- package/dist/activities/execute-deep-agent/streaming.js +3 -15
- package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -7
- package/dist/activities/execute-deep-agent/subagent-transformer.js +23 -7
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +30 -3
- package/dist/activities/execute-deep-agent/subagent-wiring.js +29 -3
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/execute-deep-agent/v3-status-builder.js +32 -2
- package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
- package/dist/claimcheck/payload-codec.js +9 -5
- package/dist/claimcheck/payload-codec.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +2 -0
- package/dist/client/stigmer-client.js +2 -0
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/middleware/approval-gate.d.ts +85 -4
- package/dist/middleware/approval-gate.js +165 -38
- package/dist/middleware/approval-gate.js.map +1 -1
- package/dist/middleware/types.d.ts +2 -5
- package/dist/shared/activity-input.d.ts +43 -0
- package/dist/shared/activity-input.js +17 -0
- package/dist/shared/activity-input.js.map +1 -0
- package/dist/shared/approval-canonicalize.d.ts +19 -0
- package/dist/shared/approval-canonicalize.js +119 -0
- package/dist/shared/approval-canonicalize.js.map +1 -0
- package/dist/shared/approval-fingerprint.d.ts +106 -0
- package/dist/shared/approval-fingerprint.js +113 -0
- package/dist/shared/approval-fingerprint.js.map +1 -0
- package/dist/shared/approval-policy.d.ts +182 -12
- package/dist/shared/approval-policy.js +213 -27
- package/dist/shared/approval-policy.js.map +1 -1
- package/dist/shared/args-preview.d.ts +52 -0
- package/dist/shared/args-preview.js +93 -0
- package/dist/shared/args-preview.js.map +1 -0
- package/dist/shared/artifact-storage.d.ts +19 -1
- package/dist/shared/artifact-storage.js +48 -11
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/file-change.d.ts +44 -0
- package/dist/shared/file-change.js +57 -0
- package/dist/shared/file-change.js.map +1 -0
- package/dist/shared/file-tools.d.ts +107 -0
- package/dist/shared/file-tools.js +168 -0
- package/dist/shared/file-tools.js.map +1 -0
- package/dist/shared/filereview/capture.d.ts +202 -0
- package/dist/shared/filereview/capture.js +498 -0
- package/dist/shared/filereview/capture.js.map +1 -0
- package/dist/shared/filereview/cas-substrate.d.ts +190 -0
- package/dist/shared/filereview/cas-substrate.js +284 -0
- package/dist/shared/filereview/cas-substrate.js.map +1 -0
- package/dist/shared/filereview/digest.d.ts +40 -0
- package/dist/shared/filereview/digest.js +66 -0
- package/dist/shared/filereview/digest.js.map +1 -0
- package/dist/shared/filereview/events.d.ts +170 -0
- package/dist/shared/filereview/events.js +298 -0
- package/dist/shared/filereview/events.js.map +1 -0
- package/dist/shared/filereview/git-substrate.d.ts +175 -0
- package/dist/shared/filereview/git-substrate.js +439 -0
- package/dist/shared/filereview/git-substrate.js.map +1 -0
- package/dist/shared/filereview/index.d.ts +11 -0
- package/dist/shared/filereview/index.js +12 -0
- package/dist/shared/filereview/index.js.map +1 -0
- package/dist/shared/filereview/secret-paths.d.ts +63 -0
- package/dist/shared/filereview/secret-paths.js +105 -0
- package/dist/shared/filereview/secret-paths.js.map +1 -0
- package/dist/shared/fingerprint-secret.d.ts +26 -0
- package/dist/shared/fingerprint-secret.js +47 -0
- package/dist/shared/fingerprint-secret.js.map +1 -0
- package/dist/shared/model-client.d.ts +51 -0
- package/dist/shared/model-client.js +77 -0
- package/dist/shared/model-client.js.map +1 -0
- package/dist/shared/plan-artifact.js +0 -2
- package/dist/shared/plan-artifact.js.map +1 -1
- package/dist/shared/status-offload.d.ts +83 -9
- package/dist/shared/status-offload.js +399 -79
- package/dist/shared/status-offload.js.map +1 -1
- package/dist/shared/status.js +14 -1
- package/dist/shared/status.js.map +1 -1
- package/dist/shared/tool-kind.d.ts +19 -0
- package/dist/shared/tool-kind.js +13 -0
- package/dist/shared/tool-kind.js.map +1 -1
- package/dist/shared/tool-row.d.ts +88 -0
- package/dist/shared/tool-row.js +127 -0
- package/dist/shared/tool-row.js.map +1 -0
- package/dist/shared/workspace/platform-dir.d.ts +25 -0
- package/dist/shared/workspace/platform-dir.js +38 -2
- package/dist/shared/workspace/platform-dir.js.map +1 -1
- package/dist/workflows/call-agent-orchestrator.js +56 -7
- package/dist/workflows/call-agent-orchestrator.js.map +1 -1
- package/dist/workflows/connect-mcp-server.d.ts +50 -0
- package/dist/workflows/connect-mcp-server.js +136 -15
- package/dist/workflows/connect-mcp-server.js.map +1 -1
- package/dist/workflows/types.d.ts +8 -0
- package/package.json +2 -2
- package/src/__test-utils__/approval-contract/contract.ts +224 -0
- package/src/__test-utils__/approval-contract/types.ts +179 -0
- package/src/__test-utils__/fake-artifact-storage.ts +72 -0
- package/src/__tests__/approval-gateway-contract.test.ts +29 -0
- package/src/__tests__/claimcheck-codec.test.ts +16 -53
- package/src/__tests__/golden-e2e.test.ts +2 -0
- package/src/__tests__/runner-token-coordinator.test.ts +3 -3
- package/src/activities/__tests__/call-agent-status.test.ts +135 -0
- package/src/activities/__tests__/call-llm.test.ts +1 -1
- package/src/activities/__tests__/classify-tool-approvals.test.ts +208 -1
- package/src/activities/__tests__/discover-mcp-server.test.ts +30 -0
- package/src/activities/__tests__/workflow-event-activities.test.ts +2 -1
- package/src/activities/call-agent-status.ts +74 -4
- package/src/activities/call-llm.ts +18 -63
- package/src/activities/classify-tool-approvals.ts +101 -19
- package/src/activities/discover-mcp-server.ts +29 -1
- package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +216 -0
- package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +148 -0
- package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +41 -9
- package/src/activities/execute-cursor/__tests__/approval-state.test.ts +292 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +68 -1
- package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +1005 -0
- package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +187 -0
- package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +97 -0
- package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +240 -0
- package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +203 -0
- package/src/activities/execute-cursor/__tests__/exact-apply.test.ts +375 -0
- package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +1294 -24
- package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +446 -0
- package/src/activities/execute-cursor/__tests__/hook-script.test.ts +384 -110
- package/src/activities/execute-cursor/__tests__/message-translator.test.ts +171 -25
- package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +189 -0
- package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +44 -23
- package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +190 -10
- package/src/activities/execute-cursor/approval-policy.ts +28 -159
- package/src/activities/execute-cursor/approval-state.ts +366 -18
- package/src/activities/execute-cursor/capture-flow.ts +323 -0
- package/src/activities/execute-cursor/cas-observations.ts +204 -0
- package/src/activities/execute-cursor/command-provenance.ts +168 -0
- package/src/activities/execute-cursor/exact-apply.ts +253 -0
- package/src/activities/execute-cursor/hook-script.ts +317 -51
- package/src/activities/execute-cursor/index.ts +575 -67
- package/src/activities/execute-cursor/message-translator.ts +963 -89
- package/src/activities/execute-cursor/prompt-builder.ts +80 -14
- package/src/activities/execute-cursor/workspace-setup.ts +257 -42
- package/src/activities/execute-deep-agent/__test-utils__/gateway-substrate.ts +180 -0
- package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +134 -0
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +84 -0
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +11 -24
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +64 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-observer.test.ts +163 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +8 -5
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +342 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +284 -0
- package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +14 -36
- package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +31 -13
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +349 -0
- package/src/activities/execute-deep-agent/__tests__/stamp-flowed-rows.test.ts +119 -0
- package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +91 -10
- package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +9 -9
- package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +213 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +3 -6
- package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +84 -1
- package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +4 -1
- package/src/activities/execute-deep-agent/approval-file-change.ts +80 -0
- package/src/activities/execute-deep-agent/attachment-injector.ts +20 -11
- package/src/activities/execute-deep-agent/cas-capture-backend.ts +66 -0
- package/src/activities/execute-deep-agent/cas-capture-observer.ts +125 -0
- package/src/activities/execute-deep-agent/hitl.ts +23 -7
- package/src/activities/execute-deep-agent/index.ts +463 -40
- package/src/activities/execute-deep-agent/inline-publisher.ts +27 -4
- package/src/activities/execute-deep-agent/setup.ts +223 -125
- package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +64 -0
- package/src/activities/execute-deep-agent/status-builder-shared.ts +62 -23
- package/src/activities/execute-deep-agent/status-builder.ts +63 -8
- package/src/activities/execute-deep-agent/streaming-side-effects.ts +2 -16
- package/src/activities/execute-deep-agent/streaming.ts +3 -13
- package/src/activities/execute-deep-agent/subagent-transformer.ts +53 -13
- package/src/activities/execute-deep-agent/subagent-wiring.ts +50 -3
- package/src/activities/execute-deep-agent/v3-status-builder.ts +36 -2
- package/src/claimcheck/payload-codec.ts +8 -8
- package/src/client/stigmer-client.ts +9 -1
- package/src/middleware/__tests__/approval-gate.test.ts +488 -4
- package/src/middleware/approval-gate.ts +247 -38
- package/src/middleware/types.ts +5 -5
- package/src/shared/__tests__/activity-input.test.ts +78 -0
- package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
- package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
- package/src/shared/__tests__/approval-policy.test.ts +274 -40
- package/src/shared/__tests__/args-preview.test.ts +78 -0
- package/src/shared/__tests__/artifact-storage-extended.test.ts +62 -10
- package/src/shared/__tests__/artifact-storage.test.ts +123 -11
- package/src/shared/__tests__/file-change.test.ts +85 -0
- package/src/shared/__tests__/file-tools.test.ts +90 -0
- package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
- package/src/shared/__tests__/lease-scope-corpus.test.ts +56 -0
- package/src/shared/__tests__/model-client.test.ts +162 -0
- package/src/shared/__tests__/plan-artifact.test.ts +11 -26
- package/src/shared/__tests__/policy-source-corpus.test.ts +58 -0
- package/src/shared/__tests__/status-offload.test.ts +573 -16
- package/src/shared/__tests__/status.test.ts +4 -5
- package/src/shared/__tests__/tool-kind.test.ts +24 -1
- package/src/shared/__tests__/tool-row.test.ts +221 -0
- package/src/shared/activity-input.ts +57 -0
- package/src/shared/approval-canonicalize.ts +159 -0
- package/src/shared/approval-fingerprint.ts +148 -0
- package/src/shared/approval-policy.ts +303 -27
- package/src/shared/args-preview.ts +98 -0
- package/src/shared/artifact-storage.ts +62 -11
- package/src/shared/checkpointer/__tests__/http-saver.test.ts +1 -2
- package/src/shared/file-change.ts +64 -0
- package/src/shared/file-tools.ts +169 -0
- package/src/shared/filereview/__tests__/capture.test.ts +856 -0
- package/src/shared/filereview/__tests__/cas-substrate.test.ts +404 -0
- package/src/shared/filereview/__tests__/digest.test.ts +100 -0
- package/src/shared/filereview/__tests__/events.test.ts +245 -0
- package/src/shared/filereview/__tests__/git-substrate.test.ts +362 -0
- package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +286 -0
- package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
- package/src/shared/filereview/capture.ts +727 -0
- package/src/shared/filereview/cas-substrate.ts +401 -0
- package/src/shared/filereview/digest.ts +83 -0
- package/src/shared/filereview/events.ts +449 -0
- package/src/shared/filereview/git-substrate.ts +555 -0
- package/src/shared/filereview/index.ts +60 -0
- package/src/shared/filereview/secret-paths.ts +121 -0
- package/src/shared/fingerprint-secret.ts +53 -0
- package/src/shared/model-client.ts +122 -0
- package/src/shared/plan-artifact.ts +0 -2
- package/src/shared/status-offload.ts +433 -77
- package/src/shared/status.ts +13 -0
- package/src/shared/tool-kind.ts +33 -0
- package/src/shared/tool-row.ts +135 -0
- package/src/shared/workspace/platform-dir.ts +41 -2
- package/src/workflow-engine/__tests__/golden-execution.test.ts +35 -18
- package/src/workflow-engine/__tests__/tasks/try.test.ts +1 -1
- package/src/workflows/__tests__/connect-mcp-server.test.ts +304 -29
- package/src/workflows/call-agent-orchestrator.ts +53 -6
- package/src/workflows/connect-mcp-server.ts +179 -24
- package/src/workflows/types.ts +8 -0
|
@@ -42,6 +42,7 @@ describe("ConnectMcpServerWorkflow", () => {
|
|
|
42
42
|
previousToolsFingerprint: "",
|
|
43
43
|
previousToolApprovals: [],
|
|
44
44
|
newToolsFingerprint: "abc123def456",
|
|
45
|
+
previousTools: [],
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
const classifyResult: ToolApprovalResult[] = [
|
|
@@ -93,21 +94,21 @@ describe("ConnectMcpServerWorkflow", () => {
|
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
// ─────────────────────────────────────────────────────────────────────────
|
|
96
|
-
//
|
|
97
|
+
// Incremental classification (content-addressed reuse)
|
|
97
98
|
// ─────────────────────────────────────────────────────────────────────────
|
|
98
99
|
|
|
99
|
-
describe("
|
|
100
|
-
it("reuses
|
|
100
|
+
describe("incremental classification", () => {
|
|
101
|
+
it("reuses prior decisions and skips the LLM when all tools are unchanged", async () => {
|
|
101
102
|
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
102
103
|
|
|
103
|
-
const
|
|
104
|
+
const search = { name: "search", description: "Search", inputSchema: null };
|
|
105
|
+
const del = { name: "delete_repo", description: "Delete", inputSchema: null };
|
|
104
106
|
mockDiscoverActivity.mockResolvedValue(
|
|
105
107
|
makeDiscoveryResult({
|
|
106
|
-
tools: [
|
|
107
|
-
|
|
108
|
-
previousToolsFingerprint: fingerprint,
|
|
108
|
+
tools: [search, del],
|
|
109
|
+
previousTools: [search, del],
|
|
109
110
|
previousToolApprovals: [
|
|
110
|
-
{ toolName: "
|
|
111
|
+
{ toolName: "delete_repo", requiresApproval: true, message: "Delete repo" },
|
|
111
112
|
],
|
|
112
113
|
}),
|
|
113
114
|
);
|
|
@@ -115,73 +116,346 @@ describe("ConnectMcpServerWorkflow", () => {
|
|
|
115
116
|
const result = await connectMcpServer({ mcp_server_id: "mcp-cached" });
|
|
116
117
|
|
|
117
118
|
expect(mockClassifyActivity).not.toHaveBeenCalled();
|
|
119
|
+
// The gated tool is carried forward; the unchanged un-gated tool stays absent.
|
|
118
120
|
expect(result.tool_approvals).toEqual([
|
|
119
|
-
{ tool_name: "
|
|
121
|
+
{ tool_name: "delete_repo", requires_approval: true, message: "Delete repo" },
|
|
120
122
|
]);
|
|
121
123
|
});
|
|
122
124
|
|
|
123
|
-
it("
|
|
125
|
+
it("classifies all tools on first connect (no previous tools)", async () => {
|
|
124
126
|
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
125
127
|
|
|
126
|
-
const fingerprint = "deadbeef12345678";
|
|
127
128
|
mockDiscoverActivity.mockResolvedValue(
|
|
128
129
|
makeDiscoveryResult({
|
|
129
|
-
tools: [
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
tools: [
|
|
131
|
+
{ name: "search", description: "Search", inputSchema: null },
|
|
132
|
+
{ name: "create", description: "Create", inputSchema: null },
|
|
133
|
+
],
|
|
134
|
+
previousTools: [],
|
|
132
135
|
previousToolApprovals: [],
|
|
133
136
|
}),
|
|
134
137
|
);
|
|
135
138
|
mockClassifyActivity.mockResolvedValue([]);
|
|
136
139
|
|
|
137
|
-
await connectMcpServer({ mcp_server_id: "mcp-
|
|
140
|
+
await connectMcpServer({ mcp_server_id: "mcp-first" });
|
|
138
141
|
|
|
139
142
|
expect(mockClassifyActivity).toHaveBeenCalledOnce();
|
|
143
|
+
expect(mockClassifyActivity.mock.calls[0][0].tools).toHaveLength(2);
|
|
140
144
|
});
|
|
141
145
|
|
|
142
|
-
it("
|
|
146
|
+
it("classifies only the newly added tool and merges with carried-forward decisions", async () => {
|
|
143
147
|
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
144
148
|
|
|
149
|
+
const known = { name: "search", description: "Search", inputSchema: null };
|
|
150
|
+
const gated = { name: "delete_repo", description: "Delete", inputSchema: null };
|
|
151
|
+
const added = { name: "create_pr", description: "Create PR", inputSchema: null };
|
|
145
152
|
mockDiscoverActivity.mockResolvedValue(
|
|
146
153
|
makeDiscoveryResult({
|
|
147
|
-
tools: [
|
|
148
|
-
|
|
149
|
-
previousToolsFingerprint: "old-fingerprint",
|
|
154
|
+
tools: [known, gated, added],
|
|
155
|
+
previousTools: [known, gated],
|
|
150
156
|
previousToolApprovals: [
|
|
151
|
-
{ toolName: "
|
|
157
|
+
{ toolName: "delete_repo", requiresApproval: true, message: "Delete repo" },
|
|
152
158
|
],
|
|
153
159
|
}),
|
|
154
160
|
);
|
|
155
161
|
mockClassifyActivity.mockResolvedValue([
|
|
156
|
-
{ tool_name: "
|
|
162
|
+
{ tool_name: "create_pr", requires_approval: true, message: "Create PR" },
|
|
163
|
+
]);
|
|
164
|
+
|
|
165
|
+
const result = await connectMcpServer({ mcp_server_id: "mcp-added" });
|
|
166
|
+
|
|
167
|
+
expect(mockClassifyActivity).toHaveBeenCalledOnce();
|
|
168
|
+
expect(mockClassifyActivity.mock.calls[0][0].tools).toEqual([
|
|
169
|
+
{ name: "create_pr", description: "Create PR", input_schema: null },
|
|
170
|
+
]);
|
|
171
|
+
expect(result.tool_approvals).toEqual([
|
|
172
|
+
{ tool_name: "delete_repo", requires_approval: true, message: "Delete repo" },
|
|
173
|
+
{ tool_name: "create_pr", requires_approval: true, message: "Create PR" },
|
|
174
|
+
]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("re-classifies a tool whose definition changed (same name, new schema)", async () => {
|
|
178
|
+
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
179
|
+
|
|
180
|
+
mockDiscoverActivity.mockResolvedValue(
|
|
181
|
+
makeDiscoveryResult({
|
|
182
|
+
tools: [{ name: "run", description: "Run", inputSchema: { properties: { cmd: {} } } }],
|
|
183
|
+
previousTools: [{ name: "run", description: "Run", inputSchema: null }],
|
|
184
|
+
previousToolApprovals: [],
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
mockClassifyActivity.mockResolvedValue([
|
|
188
|
+
{ tool_name: "run", requires_approval: true, message: "Run {{args.cmd}}" },
|
|
157
189
|
]);
|
|
158
190
|
|
|
159
191
|
const result = await connectMcpServer({ mcp_server_id: "mcp-changed" });
|
|
160
192
|
|
|
161
193
|
expect(mockClassifyActivity).toHaveBeenCalledOnce();
|
|
194
|
+
expect(mockClassifyActivity.mock.calls[0][0].tools).toHaveLength(1);
|
|
162
195
|
expect(result.tool_approvals).toEqual([
|
|
163
|
-
{ tool_name: "
|
|
196
|
+
{ tool_name: "run", requires_approval: true, message: "Run {{args.cmd}}" },
|
|
164
197
|
]);
|
|
165
198
|
});
|
|
166
199
|
|
|
167
|
-
it("
|
|
200
|
+
it("drops a previously-gated tool that no longer exists", async () => {
|
|
168
201
|
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
169
202
|
|
|
203
|
+
const kept = { name: "search", description: "Search", inputSchema: null };
|
|
170
204
|
mockDiscoverActivity.mockResolvedValue(
|
|
171
205
|
makeDiscoveryResult({
|
|
172
|
-
tools: [],
|
|
173
|
-
|
|
174
|
-
previousToolsFingerprint: "",
|
|
206
|
+
tools: [kept],
|
|
207
|
+
previousTools: [kept, { name: "removed", description: "Gone", inputSchema: null }],
|
|
175
208
|
previousToolApprovals: [
|
|
176
|
-
{ toolName: "
|
|
209
|
+
{ toolName: "removed", requiresApproval: true, message: "Approve removed" },
|
|
210
|
+
],
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
const result = await connectMcpServer({ mcp_server_id: "mcp-removed" });
|
|
215
|
+
|
|
216
|
+
expect(mockClassifyActivity).not.toHaveBeenCalled();
|
|
217
|
+
expect(result.tool_approvals).toEqual([]);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
222
|
+
// planIncrementalClassification — pure helper
|
|
223
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
describe("planIncrementalClassification", () => {
|
|
226
|
+
it("treats every tool as new when there is no previous state", async () => {
|
|
227
|
+
const { planIncrementalClassification } = await import("../connect-mcp-server.js");
|
|
228
|
+
const tools = [
|
|
229
|
+
{ name: "a", description: "A", inputSchema: null },
|
|
230
|
+
{ name: "b", description: "B", inputSchema: null },
|
|
231
|
+
];
|
|
232
|
+
const { toolsToClassify, carriedForward } = planIncrementalClassification([], [], tools);
|
|
233
|
+
expect(toolsToClassify).toEqual(tools);
|
|
234
|
+
expect(carriedForward).toEqual([]);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("carries forward a gated decision for an unchanged tool", async () => {
|
|
238
|
+
const { planIncrementalClassification } = await import("../connect-mcp-server.js");
|
|
239
|
+
const tool = { name: "delete_repo", description: "Delete", inputSchema: null };
|
|
240
|
+
const { toolsToClassify, carriedForward } = planIncrementalClassification(
|
|
241
|
+
[tool],
|
|
242
|
+
[{ toolName: "delete_repo", requiresApproval: true, message: "Delete repo" }],
|
|
243
|
+
[tool],
|
|
244
|
+
);
|
|
245
|
+
expect(toolsToClassify).toEqual([]);
|
|
246
|
+
expect(carriedForward).toEqual([
|
|
247
|
+
{ tool_name: "delete_repo", requires_approval: true, message: "Delete repo" },
|
|
248
|
+
]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("emits nothing for an unchanged tool that was not gated", async () => {
|
|
252
|
+
const { planIncrementalClassification } = await import("../connect-mcp-server.js");
|
|
253
|
+
const tool = { name: "search", description: "Search", inputSchema: null };
|
|
254
|
+
const { toolsToClassify, carriedForward } = planIncrementalClassification([tool], [], [tool]);
|
|
255
|
+
expect(toolsToClassify).toEqual([]);
|
|
256
|
+
expect(carriedForward).toEqual([]);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it("flags a tool for classification when its definition changed", async () => {
|
|
260
|
+
const { planIncrementalClassification } = await import("../connect-mcp-server.js");
|
|
261
|
+
const prev = { name: "run", description: "Run", inputSchema: null };
|
|
262
|
+
const next = { name: "run", description: "Run", inputSchema: { properties: { cmd: {} } } };
|
|
263
|
+
const { toolsToClassify, carriedForward } = planIncrementalClassification(
|
|
264
|
+
[prev],
|
|
265
|
+
[{ toolName: "run", requiresApproval: true, message: "old" }],
|
|
266
|
+
[next],
|
|
267
|
+
);
|
|
268
|
+
expect(toolsToClassify).toEqual([next]);
|
|
269
|
+
// The changed tool is NOT carried forward — it will be re-classified.
|
|
270
|
+
expect(carriedForward).toEqual([]);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("partitions a mix of unchanged, changed, added, and removed tools", async () => {
|
|
274
|
+
const { planIncrementalClassification } = await import("../connect-mcp-server.js");
|
|
275
|
+
const unchanged = { name: "search", description: "Search", inputSchema: null };
|
|
276
|
+
const changedPrev = { name: "edit", description: "Edit", inputSchema: null };
|
|
277
|
+
const changedNext = { name: "edit", description: "Edit a file", inputSchema: null };
|
|
278
|
+
const added = { name: "create", description: "Create", inputSchema: null };
|
|
279
|
+
const removed = { name: "remove", description: "Remove", inputSchema: null };
|
|
280
|
+
|
|
281
|
+
const { toolsToClassify, carriedForward } = planIncrementalClassification(
|
|
282
|
+
[unchanged, changedPrev, removed],
|
|
283
|
+
[
|
|
284
|
+
{ toolName: "search", requiresApproval: true, message: "Search msg" },
|
|
285
|
+
{ toolName: "remove", requiresApproval: true, message: "Remove msg" },
|
|
286
|
+
],
|
|
287
|
+
[unchanged, changedNext, added],
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
expect(toolsToClassify).toEqual([changedNext, added]);
|
|
291
|
+
expect(carriedForward).toEqual([
|
|
292
|
+
{ tool_name: "search", requires_approval: true, message: "Search msg" },
|
|
293
|
+
]);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
298
|
+
// applyDestructiveHintTightener — pure helper (annotations tighten only)
|
|
299
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
300
|
+
|
|
301
|
+
describe("applyDestructiveHintTightener", () => {
|
|
302
|
+
it("force-gates a tool the classifier left un-gated when destructiveHint=true", async () => {
|
|
303
|
+
const { applyDestructiveHintTightener } = await import("../connect-mcp-server.js");
|
|
304
|
+
|
|
305
|
+
const gated: ToolApprovalResult[] = [];
|
|
306
|
+
const tools = [
|
|
307
|
+
{ name: "wipe_db", description: "Wipe", inputSchema: null, annotations: { destructiveHint: true } },
|
|
308
|
+
];
|
|
309
|
+
|
|
310
|
+
const { tightened, addedCount } = applyDestructiveHintTightener(gated, tools);
|
|
311
|
+
|
|
312
|
+
expect(addedCount).toBe(1);
|
|
313
|
+
expect(tightened).toEqual([
|
|
314
|
+
{
|
|
315
|
+
tool_name: "wipe_db",
|
|
316
|
+
requires_approval: true,
|
|
317
|
+
message: "Execute wipe_db",
|
|
318
|
+
from_destructive_hint: true,
|
|
319
|
+
},
|
|
320
|
+
]);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("does not duplicate a tool that is already gated", async () => {
|
|
324
|
+
const { applyDestructiveHintTightener } = await import("../connect-mcp-server.js");
|
|
325
|
+
|
|
326
|
+
const gated: ToolApprovalResult[] = [
|
|
327
|
+
{ tool_name: "wipe_db", requires_approval: true, message: "Wipe {{args.db}}" },
|
|
328
|
+
];
|
|
329
|
+
const tools = [
|
|
330
|
+
{ name: "wipe_db", description: "Wipe", inputSchema: null, annotations: { destructiveHint: true } },
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
const { tightened, addedCount } = applyDestructiveHintTightener(gated, tools);
|
|
334
|
+
|
|
335
|
+
expect(addedCount).toBe(0);
|
|
336
|
+
// The richer classifier message is preserved — no clobbering.
|
|
337
|
+
expect(tightened).toEqual(gated);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("NEVER relaxes: a spoofed readOnlyHint on a destructive tool stays/forces gated", async () => {
|
|
341
|
+
const { applyDestructiveHintTightener } = await import("../connect-mcp-server.js");
|
|
342
|
+
|
|
343
|
+
// A malicious server marks a destructive tool readOnly to dodge approval.
|
|
344
|
+
const tools = [
|
|
345
|
+
{
|
|
346
|
+
name: "delete_all",
|
|
347
|
+
description: "Deletes everything",
|
|
348
|
+
inputSchema: null,
|
|
349
|
+
annotations: { readOnlyHint: true, destructiveHint: true },
|
|
350
|
+
},
|
|
351
|
+
];
|
|
352
|
+
|
|
353
|
+
const { tightened, addedCount } = applyDestructiveHintTightener([], tools);
|
|
354
|
+
|
|
355
|
+
// readOnlyHint is ignored; destructiveHint force-gates it.
|
|
356
|
+
expect(addedCount).toBe(1);
|
|
357
|
+
expect(tightened[0]).toEqual({
|
|
358
|
+
tool_name: "delete_all",
|
|
359
|
+
requires_approval: true,
|
|
360
|
+
message: "Execute delete_all",
|
|
361
|
+
from_destructive_hint: true,
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it("readOnlyHint alone never un-gates a classifier-gated tool", async () => {
|
|
366
|
+
const { applyDestructiveHintTightener } = await import("../connect-mcp-server.js");
|
|
367
|
+
|
|
368
|
+
const gated: ToolApprovalResult[] = [
|
|
369
|
+
{ tool_name: "send_money", requires_approval: true, message: "Send {{args.amount}}" },
|
|
370
|
+
];
|
|
371
|
+
const tools = [
|
|
372
|
+
{ name: "send_money", description: "Transfer", inputSchema: null, annotations: { readOnlyHint: true } },
|
|
373
|
+
];
|
|
374
|
+
|
|
375
|
+
const { tightened, addedCount } = applyDestructiveHintTightener(gated, tools);
|
|
376
|
+
|
|
377
|
+
expect(addedCount).toBe(0);
|
|
378
|
+
expect(tightened).toEqual(gated);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("leaves tools without annotations or with destructiveHint!=true untouched", async () => {
|
|
382
|
+
const { applyDestructiveHintTightener } = await import("../connect-mcp-server.js");
|
|
383
|
+
|
|
384
|
+
const tools = [
|
|
385
|
+
{ name: "read_file", description: "Read", inputSchema: null, annotations: { destructiveHint: false } },
|
|
386
|
+
{ name: "list_dir", description: "List", inputSchema: null, annotations: null },
|
|
387
|
+
{ name: "stat", description: "Stat", inputSchema: null },
|
|
388
|
+
];
|
|
389
|
+
|
|
390
|
+
const { tightened, addedCount } = applyDestructiveHintTightener([], tools);
|
|
391
|
+
|
|
392
|
+
expect(addedCount).toBe(0);
|
|
393
|
+
expect(tightened).toEqual([]);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe("connectMcpServer — destructiveHint tightener integration", () => {
|
|
398
|
+
it("force-gates a destructive-annotated tool the classifier auto-approved", async () => {
|
|
399
|
+
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
400
|
+
|
|
401
|
+
mockDiscoverActivity.mockResolvedValue(
|
|
402
|
+
makeDiscoveryResult({
|
|
403
|
+
tools: [
|
|
404
|
+
{ name: "search", description: "Search", inputSchema: null },
|
|
405
|
+
{
|
|
406
|
+
name: "purge_cache",
|
|
407
|
+
description: "Purge",
|
|
408
|
+
inputSchema: null,
|
|
409
|
+
annotations: { destructiveHint: true },
|
|
410
|
+
},
|
|
177
411
|
],
|
|
178
412
|
}),
|
|
179
413
|
);
|
|
414
|
+
// Classifier auto-approves both (returns no gated tools).
|
|
180
415
|
mockClassifyActivity.mockResolvedValue([]);
|
|
181
416
|
|
|
182
|
-
await connectMcpServer({ mcp_server_id: "mcp-
|
|
417
|
+
const result = await connectMcpServer({ mcp_server_id: "mcp-destructive" });
|
|
183
418
|
|
|
184
|
-
expect(
|
|
419
|
+
expect(result.tool_approvals).toEqual([
|
|
420
|
+
{
|
|
421
|
+
tool_name: "purge_cache",
|
|
422
|
+
requires_approval: true,
|
|
423
|
+
message: "Execute purge_cache",
|
|
424
|
+
from_destructive_hint: true,
|
|
425
|
+
},
|
|
426
|
+
]);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it("re-asserts gating for a carried-forward tool the server flips to destructive", async () => {
|
|
430
|
+
const { connectMcpServer } = await import("../connect-mcp-server.js");
|
|
431
|
+
|
|
432
|
+
// Unchanged tool (reuse path, classifier skipped) that the server now
|
|
433
|
+
// annotates destructive on the live connect.
|
|
434
|
+
const tool = {
|
|
435
|
+
name: "rotate_keys",
|
|
436
|
+
description: "Rotate",
|
|
437
|
+
inputSchema: null,
|
|
438
|
+
annotations: { destructiveHint: true },
|
|
439
|
+
};
|
|
440
|
+
mockDiscoverActivity.mockResolvedValue(
|
|
441
|
+
makeDiscoveryResult({
|
|
442
|
+
tools: [tool],
|
|
443
|
+
previousTools: [{ name: "rotate_keys", description: "Rotate", inputSchema: null }],
|
|
444
|
+
previousToolApprovals: [],
|
|
445
|
+
}),
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
const result = await connectMcpServer({ mcp_server_id: "mcp-flip" });
|
|
449
|
+
|
|
450
|
+
expect(mockClassifyActivity).not.toHaveBeenCalled();
|
|
451
|
+
expect(result.tool_approvals).toEqual([
|
|
452
|
+
{
|
|
453
|
+
tool_name: "rotate_keys",
|
|
454
|
+
requires_approval: true,
|
|
455
|
+
message: "Execute rotate_keys",
|
|
456
|
+
from_destructive_hint: true,
|
|
457
|
+
},
|
|
458
|
+
]);
|
|
185
459
|
});
|
|
186
460
|
});
|
|
187
461
|
|
|
@@ -355,5 +629,6 @@ function makeDiscoveryResult(
|
|
|
355
629
|
previousToolsFingerprint: overrides.previousToolsFingerprint ?? "",
|
|
356
630
|
previousToolApprovals: overrides.previousToolApprovals ?? [],
|
|
357
631
|
newToolsFingerprint: overrides.newToolsFingerprint ?? "new-fp-default",
|
|
632
|
+
previousTools: overrides.previousTools ?? [],
|
|
358
633
|
};
|
|
359
634
|
}
|
|
@@ -169,6 +169,39 @@ export async function orchestrateAgentCall(
|
|
|
169
169
|
activityDone = true;
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
+
// Last-written file-review reference for this child, as a deterministic key, so
|
|
173
|
+
// we write pending_file_reviews only when the child's AWAITING_REVIEW set changes
|
|
174
|
+
// (avoids status-write storms). undefined = never written yet.
|
|
175
|
+
let lastFileReviewKey: string | undefined;
|
|
176
|
+
|
|
177
|
+
// Poll-derive the child's file-review gate and surface it (reference-only) on the
|
|
178
|
+
// parent. No new Temporal signal: the orchestrator already holds the child open
|
|
179
|
+
// (async-completion) and reads its status here on the same cadence as progress.
|
|
180
|
+
async function syncFileReviews(childId: string): Promise<void> {
|
|
181
|
+
let ids: string[];
|
|
182
|
+
try {
|
|
183
|
+
ids = await statusProxy.GetAwaitingFileReviewChangeSetIds(childId);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
log.warn("Failed to derive child file-review state (non-fatal)", {
|
|
186
|
+
error: String(err),
|
|
187
|
+
taskName: input.taskName,
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// Deterministic change key (sorted): a stable comparison across replays.
|
|
192
|
+
const key = [...ids].sort().join(",");
|
|
193
|
+
if (key === lastFileReviewKey) return;
|
|
194
|
+
lastFileReviewKey = key;
|
|
195
|
+
try {
|
|
196
|
+
await statusProxy.UpdateWorkflowFileReviewStatus(input.workflowExecutionId, childId, ids);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
log.warn("Failed to update workflow file-review status (non-fatal)", {
|
|
199
|
+
error: String(err),
|
|
200
|
+
taskName: input.taskName,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
172
205
|
while (!activityDone) {
|
|
173
206
|
// Wait for a signal, activity completion, or periodic timeout for progress polling.
|
|
174
207
|
// condition() returns false on timeout, true when the predicate became true.
|
|
@@ -183,6 +216,7 @@ export async function orchestrateAgentCall(
|
|
|
183
216
|
if (childExecId && !initialProgressEmitted) {
|
|
184
217
|
initialProgressEmitted = true;
|
|
185
218
|
await emitProgress(input, childExecId, null);
|
|
219
|
+
await syncFileReviews(childExecId);
|
|
186
220
|
}
|
|
187
221
|
|
|
188
222
|
// Periodic progress: on timeout, poll the child execution for live data
|
|
@@ -199,6 +233,7 @@ export async function orchestrateAgentCall(
|
|
|
199
233
|
if (progress) {
|
|
200
234
|
await emitProgress(input, childExecId, progress);
|
|
201
235
|
}
|
|
236
|
+
await syncFileReviews(childExecId);
|
|
202
237
|
}
|
|
203
238
|
|
|
204
239
|
// Handle HITL approval notification
|
|
@@ -228,12 +263,24 @@ export async function orchestrateAgentCall(
|
|
|
228
263
|
await emitProgress(input, childExecId, null);
|
|
229
264
|
}
|
|
230
265
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
266
|
+
// Scoped clears for this child only (per-child merge) — a completing child must
|
|
267
|
+
// not wipe a parallel sibling's still-pending gate. Skipped if the child never
|
|
268
|
+
// started (nothing was ever surfaced for it).
|
|
269
|
+
if (childExecId) {
|
|
270
|
+
try {
|
|
271
|
+
await statusProxy.ClearWorkflowApprovalStatus(input.workflowExecutionId, childExecId);
|
|
272
|
+
} catch (clearErr) {
|
|
273
|
+
log.warn("Failed to clear workflow approval status (non-fatal)", {
|
|
274
|
+
error: String(clearErr),
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
await statusProxy.UpdateWorkflowFileReviewStatus(input.workflowExecutionId, childExecId, []);
|
|
279
|
+
} catch (clearErr) {
|
|
280
|
+
log.warn("Failed to clear workflow file-review status (non-fatal)", {
|
|
281
|
+
error: String(clearErr),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
237
284
|
}
|
|
238
285
|
|
|
239
286
|
if (activityError) {
|