@zhushanwen/subagent-core 0.2.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/README.md +114 -0
- package/dist/chunk-3VOERJPJ.js +22 -0
- package/dist/chunk-A4IVZWVX.js +31 -0
- package/dist/execution/engine/engines/zcode/constants.cjs +54 -0
- package/dist/execution/engine/engines/zcode/constants.d.cts +31 -0
- package/dist/execution/engine/engines/zcode/constants.d.ts +31 -0
- package/dist/execution/engine/engines/zcode/constants.js +22 -0
- package/dist/execution/engine/engines/zcode/reader.cjs +276 -0
- package/dist/execution/engine/engines/zcode/reader.d.cts +20 -0
- package/dist/execution/engine/engines/zcode/reader.d.ts +20 -0
- package/dist/execution/engine/engines/zcode/reader.js +239 -0
- package/dist/execution/engine/paths.cjs +55 -0
- package/dist/execution/engine/paths.d.cts +8 -0
- package/dist/execution/engine/paths.d.ts +8 -0
- package/dist/execution/engine/paths.js +26 -0
- package/dist/execution/relay-env.cjs +62 -0
- package/dist/execution/relay-env.d.cts +33 -0
- package/dist/execution/relay-env.d.ts +33 -0
- package/dist/execution/relay-env.js +20 -0
- package/dist/index.cjs +1852 -0
- package/dist/index.d.cts +1184 -0
- package/dist/index.d.ts +1184 -0
- package/dist/index.js +1810 -0
- package/dist/types-BxyAidGf.d.cts +875 -0
- package/dist/types-BxyAidGf.d.ts +875 -0
- package/package.json +99 -0
- package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +142 -0
- package/src/__tests__/append-system-prompt-assembly.test.ts +242 -0
- package/src/__tests__/builtin-workflows-structure.test.ts +180 -0
- package/src/__tests__/derive-closed-display-parity.test.ts +93 -0
- package/src/__tests__/fr4-get-state-handshake.test.ts +125 -0
- package/src/__tests__/fr8-orphan-recovery.test.ts +259 -0
- package/src/__tests__/m2-append-content-probe.test.ts +73 -0
- package/src/__tests__/manifest-store.test.ts +368 -0
- package/src/__tests__/record-store-cache.test.ts +335 -0
- package/src/__tests__/record-store-index.test.ts +560 -0
- package/src/__tests__/record-store-last-line.test.ts +129 -0
- package/src/__tests__/review-fix-loop-script.test.ts +288 -0
- package/src/__tests__/review-fix-loop-utils.test.ts +2377 -0
- package/src/__tests__/robustness-low-batch1.test.ts +286 -0
- package/src/__tests__/robustness-medium-batch1.test.ts +69 -0
- package/src/__tests__/robustness-medium-batch2.test.ts +65 -0
- package/src/__tests__/robustness-medium-batch3.test.ts +30 -0
- package/src/__tests__/robustness-medium-batch4.test.ts +358 -0
- package/src/__tests__/session-runner.test.ts +69 -0
- package/src/__tests__/smoke.test.ts +9 -0
- package/src/__tests__/stream-sink.test.ts +203 -0
- package/src/core/__tests__/host-services.test.ts +144 -0
- package/src/core/__tests__/logger.test.ts +78 -0
- package/src/core/__tests__/notify-ports.test.ts +104 -0
- package/src/core/host-services.ts +97 -0
- package/src/core/logger.ts +47 -0
- package/src/core/notify-ports.ts +126 -0
- package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +53 -0
- package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +1 -0
- package/src/execution/__tests__/agent-result-mapper.test.ts +150 -0
- package/src/execution/__tests__/alive-store.test.ts +147 -0
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +490 -0
- package/src/execution/__tests__/channel-registry-handshake.test.ts +242 -0
- package/src/execution/__tests__/chat-engine-routing.test.ts +610 -0
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +190 -0
- package/src/execution/__tests__/concurrency-pool.test.ts +250 -0
- package/src/execution/__tests__/config.test.ts +302 -0
- package/src/execution/__tests__/delivery-methods.test.ts +424 -0
- package/src/execution/__tests__/dialog-queue.test.ts +299 -0
- package/src/execution/__tests__/epipe-fallback.test.ts +241 -0
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +243 -0
- package/src/execution/__tests__/execute-nesting.test.ts +323 -0
- package/src/execution/__tests__/execute-options-mapper.test.ts +200 -0
- package/src/execution/__tests__/execution-record.test.ts +1394 -0
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +171 -0
- package/src/execution/__tests__/finalize-record.test.ts +367 -0
- package/src/execution/__tests__/finalized-marker.test.ts +104 -0
- package/src/execution/__tests__/format-schema-instruction.test.ts +169 -0
- package/src/execution/__tests__/gc-timer.test.ts +184 -0
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +254 -0
- package/src/execution/__tests__/helpers/mock-extension-api.ts +30 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +242 -0
- package/src/execution/__tests__/host-mode.test.ts +87 -0
- package/src/execution/__tests__/lifecycle-manager-lock.test.ts +211 -0
- package/src/execution/__tests__/lifecycle-manager.test.ts +383 -0
- package/src/execution/__tests__/lifecycle-predicates.test.ts +116 -0
- package/src/execution/__tests__/manifest-parentid.test.ts +117 -0
- package/src/execution/__tests__/model-resolver.test.ts +465 -0
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +287 -0
- package/src/execution/__tests__/nested-visibility.test.ts +325 -0
- package/src/execution/__tests__/output-collector.test.ts +358 -0
- package/src/execution/__tests__/path-encoding.test.ts +104 -0
- package/src/execution/__tests__/pi-invocation.test.ts +134 -0
- package/src/execution/__tests__/record-store.test.ts +1057 -0
- package/src/execution/__tests__/records-cwd-isolation.test.ts +91 -0
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +339 -0
- package/src/execution/__tests__/recursive-visibility-env.test.ts +273 -0
- package/src/execution/__tests__/relay-env.test.ts +42 -0
- package/src/execution/__tests__/resource-policy.test.ts +109 -0
- package/src/execution/__tests__/rpc-mode.test.ts +89 -0
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +267 -0
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +253 -0
- package/src/execution/__tests__/run-spawn-edges.test.ts +687 -0
- package/src/execution/__tests__/run-spawn-integration.test.ts +933 -0
- package/src/execution/__tests__/run-spawn-resume.test.ts +322 -0
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +196 -0
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +199 -0
- package/src/execution/__tests__/session-context-resolver.test.ts +167 -0
- package/src/execution/__tests__/session-file-gc.test.ts +293 -0
- package/src/execution/__tests__/session-reconstructor.test.ts +379 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +178 -0
- package/src/execution/__tests__/session-runner-schema-env.test.ts +350 -0
- package/src/execution/__tests__/spawn-args.test.ts +445 -0
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +189 -0
- package/src/execution/__tests__/spawn-event-adapter.test.ts +167 -0
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +207 -0
- package/src/execution/__tests__/spawned-children.test.ts +92 -0
- package/src/execution/__tests__/start-sync-model-guard.test.ts +150 -0
- package/src/execution/__tests__/stdin-writer.test.ts +462 -0
- package/src/execution/__tests__/stream-sink-retirement.test.ts +261 -0
- package/src/execution/__tests__/subagent-service-abort.test.ts +60 -0
- package/src/execution/__tests__/subagent-service-message-close.test.ts +629 -0
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +180 -0
- package/src/execution/__tests__/subagent-service.test.ts +788 -0
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +310 -0
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +612 -0
- package/src/execution/__tests__/temp-prompt.test.ts +53 -0
- package/src/execution/__tests__/timeout-integration.test.ts +615 -0
- package/src/execution/__tests__/tombstone-store.test.ts +73 -0
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +194 -0
- package/src/execution/__tests__/turn-limiter.test.ts +65 -0
- package/src/execution/__tests__/ui-channels.test.ts +187 -0
- package/src/execution/__tests__/ui-interaction-model.test.ts +67 -0
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +369 -0
- package/src/execution/__tests__/ui-request-handler.test.ts +204 -0
- package/src/execution/__tests__/ui-request-observability.test.ts +113 -0
- package/src/execution/__tests__/ui-request-queue.test.ts +133 -0
- package/src/execution/__tests__/worktree-manager.test.ts +633 -0
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +229 -0
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +181 -0
- package/src/execution/__tests__/worktree-registry.test.ts +199 -0
- package/src/execution/agent-registry.ts +199 -0
- package/src/execution/agent-result-mapper.ts +90 -0
- package/src/execution/alive-store.ts +119 -0
- package/src/execution/argv-mirror.ts +113 -0
- package/src/execution/best-effort.ts +38 -0
- package/src/execution/channel-registry-access.ts +144 -0
- package/src/execution/concurrency-pool.ts +116 -0
- package/src/execution/config.ts +165 -0
- package/src/execution/dialog-queue.ts +330 -0
- package/src/execution/engine/__tests__/common/data-dir.test.ts +78 -0
- package/src/execution/engine/__tests__/common/errors.test.ts +132 -0
- package/src/execution/engine/__tests__/common/event-journal.test.ts +177 -0
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +192 -0
- package/src/execution/engine/__tests__/common/nesting-guard.test.ts +81 -0
- package/src/execution/engine/__tests__/common/persona-router.test.ts +123 -0
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +154 -0
- package/src/execution/engine/__tests__/common/schema-emulation.test.ts +128 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +28 -0
- package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +141 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +109 -0
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +101 -0
- package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +77 -0
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +104 -0
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +201 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +76 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +79 -0
- package/src/execution/engine/__tests__/engine-discovery.test.ts +87 -0
- package/src/execution/engine/__tests__/model-prompt.test.ts +197 -0
- package/src/execution/engine/__tests__/paths.test.ts +39 -0
- package/src/execution/engine/__tests__/registry.test.ts +120 -0
- package/src/execution/engine/__tests__/routing.test.ts +231 -0
- package/src/execution/engine/common/data-dir.ts +66 -0
- package/src/execution/engine/common/errors.ts +183 -0
- package/src/execution/engine/common/event-journal.ts +254 -0
- package/src/execution/engine/common/journal-replay.ts +62 -0
- package/src/execution/engine/common/kill-chain.ts +221 -0
- package/src/execution/engine/common/nesting-guard.ts +50 -0
- package/src/execution/engine/common/persona-router.ts +108 -0
- package/src/execution/engine/common/pool-manager.ts +226 -0
- package/src/execution/engine/common/schema-emulation.ts +189 -0
- package/src/execution/engine/common/session-view-projection.ts +51 -0
- package/src/execution/engine/engine-discovery.ts +65 -0
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +469 -0
- package/src/execution/engine/engines/pi/__tests__/reader.test.ts +155 -0
- package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +164 -0
- package/src/execution/engine/engines/pi/pi-engine.ts +415 -0
- package/src/execution/engine/engines/pi/reader.ts +48 -0
- package/src/execution/engine/engines/pi/registration.ts +35 -0
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +100 -0
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +39 -0
- package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +150 -0
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +246 -0
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +228 -0
- package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +210 -0
- package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +71 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +127 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +580 -0
- package/src/execution/engine/engines/zcode/constants.ts +43 -0
- package/src/execution/engine/engines/zcode/golden-sample.ts +39 -0
- package/src/execution/engine/engines/zcode/launcher.ts +161 -0
- package/src/execution/engine/engines/zcode/parser.ts +436 -0
- package/src/execution/engine/engines/zcode/preparer.ts +363 -0
- package/src/execution/engine/engines/zcode/reader.ts +381 -0
- package/src/execution/engine/engines/zcode/registration.ts +37 -0
- package/src/execution/engine/engines/zcode/zcode-engine.ts +658 -0
- package/src/execution/engine/host-task-spec.ts +47 -0
- package/src/execution/engine/model-prompt.ts +158 -0
- package/src/execution/engine/paths.ts +42 -0
- package/src/execution/engine/port.ts +153 -0
- package/src/execution/engine/registry.ts +133 -0
- package/src/execution/engine/routing.ts +218 -0
- package/src/execution/engine/types.ts +309 -0
- package/src/execution/execute-options-mapper.ts +115 -0
- package/src/execution/execution-record.ts +984 -0
- package/src/execution/finalize-record.ts +254 -0
- package/src/execution/finalized-marker.ts +70 -0
- package/src/execution/get-state-handshake.ts +104 -0
- package/src/execution/host-mode.ts +56 -0
- package/src/execution/idle-gc.ts +47 -0
- package/src/execution/lifecycle-manager.ts +513 -0
- package/src/execution/lifecycle-predicates.ts +65 -0
- package/src/execution/manifest-store.ts +256 -0
- package/src/execution/model-config-service.ts +250 -0
- package/src/execution/model-resolver.ts +248 -0
- package/src/execution/notifier.ts +372 -0
- package/src/execution/notify-ledger.ts +580 -0
- package/src/execution/output-collector.ts +228 -0
- package/src/execution/path-encoding.ts +60 -0
- package/src/execution/pi-invocation.ts +120 -0
- package/src/execution/record-entry.ts +132 -0
- package/src/execution/record-store.ts +1265 -0
- package/src/execution/relay-env.ts +37 -0
- package/src/execution/session-context-resolver.ts +64 -0
- package/src/execution/session-file-gc.ts +120 -0
- package/src/execution/session-pending.ts +170 -0
- package/src/execution/session-reconstructor.ts +678 -0
- package/src/execution/session-runner.ts +1789 -0
- package/src/execution/sessions-index.ts +304 -0
- package/src/execution/spawn-event-adapter.ts +363 -0
- package/src/execution/stdin-writer.ts +198 -0
- package/src/execution/stream-sink.ts +126 -0
- package/src/execution/subagent-service.ts +2268 -0
- package/src/execution/subprocess-agent-runner.ts +317 -0
- package/src/execution/temp-prompt.ts +62 -0
- package/src/execution/tombstone-store.ts +72 -0
- package/src/execution/turn-limiter.ts +102 -0
- package/src/execution/types.ts +1023 -0
- package/src/execution/ui-channels.ts +216 -0
- package/src/execution/ui-interaction-model.ts +48 -0
- package/src/execution/ui-request-handler-factory.ts +243 -0
- package/src/execution/ui-request-observability.ts +81 -0
- package/src/execution/ui-request-queue.ts +184 -0
- package/src/execution/worktree-manager.ts +688 -0
- package/src/execution/worktree-registry.ts +279 -0
- package/src/index.ts +87 -0
- package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +349 -0
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +202 -0
- package/src/orchestration/__tests__/agent-call-stream.test.ts +152 -0
- package/src/orchestration/__tests__/args-validator.test.ts +143 -0
- package/src/orchestration/__tests__/config-loader.test.ts +503 -0
- package/src/orchestration/__tests__/error-recovery-handlers.test.ts +809 -0
- package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +404 -0
- package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +56 -0
- package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +166 -0
- package/src/orchestration/__tests__/execute-agent-call.test.ts +451 -0
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +600 -0
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +96 -0
- package/src/orchestration/__tests__/lifecycle.test.ts +659 -0
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +95 -0
- package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +183 -0
- package/src/orchestration/__tests__/script-lint.test.ts +831 -0
- package/src/orchestration/__tests__/skill-discovery.test.ts +210 -0
- package/src/orchestration/__tests__/test-mocks.ts +197 -0
- package/src/orchestration/__tests__/worker-exit-without-result.test.ts +368 -0
- package/src/orchestration/__tests__/worker-host.test.ts +120 -0
- package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +164 -0
- package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +563 -0
- package/src/orchestration/__tests__/worker-script-builder.test.ts +309 -0
- package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +129 -0
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +317 -0
- package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +110 -0
- package/src/orchestration/agent-opts-resolver.ts +174 -0
- package/src/orchestration/args-validator.ts +127 -0
- package/src/orchestration/config-loader.ts +316 -0
- package/src/orchestration/error-recovery.ts +1018 -0
- package/src/orchestration/execute-agent-call.ts +256 -0
- package/src/orchestration/launcher.ts +455 -0
- package/src/orchestration/lifecycle.ts +399 -0
- package/src/orchestration/models/__tests__/budget.test.ts +307 -0
- package/src/orchestration/models/agent-call.ts +83 -0
- package/src/orchestration/models/budget.ts +118 -0
- package/src/orchestration/models/ports.ts +164 -0
- package/src/orchestration/models/run-runtime.ts +104 -0
- package/src/orchestration/models/run-spec.ts +83 -0
- package/src/orchestration/models/run-state.ts +44 -0
- package/src/orchestration/models/trace.ts +183 -0
- package/src/orchestration/models/types.ts +301 -0
- package/src/orchestration/models/workflow-run.ts +254 -0
- package/src/orchestration/models/workflow-script-registry.ts +35 -0
- package/src/orchestration/models/workflow-script.ts +117 -0
- package/src/orchestration/script-lint.ts +766 -0
- package/src/orchestration/skill-discovery.ts +135 -0
- package/src/orchestration/worker-handle.ts +115 -0
- package/src/orchestration/worker-host.ts +98 -0
- package/src/orchestration/worker-script-builder.ts +421 -0
- package/src/orchestration/workflow-files.ts +85 -0
- package/src/orchestration/workflow-script-registry-impl.ts +133 -0
- package/src/shared/__tests__/agent-ref.test.ts +34 -0
- package/src/shared/__tests__/meta-parser.test.ts +304 -0
- package/src/shared/__tests__/model-ref.test.ts +306 -0
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +288 -0
- package/src/shared/__tests__/resource-discovery.test.ts +749 -0
- package/src/shared/__tests__/resource-meta.test.ts +51 -0
- package/src/shared/__tests__/schema-jsonify.test.ts +81 -0
- package/src/shared/__tests__/timer-delay.test.ts +61 -0
- package/src/shared/agent-event.ts +13 -0
- package/src/shared/agent-ref.ts +57 -0
- package/src/shared/meta-parser.ts +261 -0
- package/src/shared/model-ref.ts +286 -0
- package/src/shared/resource-discovery.ts +835 -0
- package/src/shared/resource-meta.ts +65 -0
- package/src/shared/schema-env.ts +44 -0
- package/src/shared/schema-jsonify.ts +58 -0
- package/src/shared/timer-delay.ts +54 -0
- package/src/shared/xml-injection.ts +35 -0
- package/workflows/README.md +81 -0
- package/workflows/_shared/agent-refs.cjs +40 -0
- package/workflows/chain.js +137 -0
- package/workflows/map-reduce.js +180 -0
- package/workflows/parallel.js +154 -0
- package/workflows/review-fix-loop-utils.cjs +1542 -0
- package/workflows/review-fix-loop.js +1605 -0
- package/workflows/scatter-gather.js +184 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [F1] 端到端回归:execute() 返回不可克隆值 → run 收敛到 done,failed(非永久 running 悬挂)。
|
|
3
|
+
*
|
|
4
|
+
* 完整链路(真实 Worker 线程 + 真实 WorkerHostImpl,无 mock worker):
|
|
5
|
+
* 脚本 return { fn: () => 1 } → postMessage DataCloneError → worker 侧 _safePost 记录 +
|
|
6
|
+
* F1 fallback 回发可克隆 error 消息 → 主线程 handleScriptError(既有 script-error 重试
|
|
7
|
+
* 矩阵:3 次 rebuild + 指数退避 1s/2s/4s)→ 第 4 次 error 超限 → run done,failed。
|
|
8
|
+
*
|
|
9
|
+
* 修复前:return 消息被静默吞掉 → worker exit(0) → handleWorkerExit(0) no-op → run 永久
|
|
10
|
+
* running、runAndWait 无限挂起(本测试会超时红)。
|
|
11
|
+
*
|
|
12
|
+
* 主线程 belt(exit(0) 无终态消息 → 立即 failed)由 worker-exit-without-result.test.ts
|
|
13
|
+
* handler 级单测覆盖;两条防线共同保证「run 必达终态」不变式。
|
|
14
|
+
*
|
|
15
|
+
* 真实退避耗时 ~7s(1+2+4s)+ 4 次 worker 启动——per-test timeout 放宽到 30s。
|
|
16
|
+
*/
|
|
17
|
+
import { describe, expect, it, vi } from "vitest";
|
|
18
|
+
|
|
19
|
+
import { runWorkflow } from "../lifecycle.ts";
|
|
20
|
+
import type { LifecycleDeps, RunStore } from "../models/ports.ts";
|
|
21
|
+
import type { RunSpec } from "../models/run-spec.ts";
|
|
22
|
+
import type { WorkflowRun } from "../models/workflow-run.ts";
|
|
23
|
+
import { WorkerHostImpl } from "../worker-host.ts";
|
|
24
|
+
|
|
25
|
+
/** 轮询直到 run 到达 done 终态或超时(挂起 → 超时红,即「非悬挂」断言本身)。 */
|
|
26
|
+
async function waitForTerminal(
|
|
27
|
+
runs: Map<string, WorkflowRun>,
|
|
28
|
+
runId: string,
|
|
29
|
+
timeoutMs: number,
|
|
30
|
+
): Promise<WorkflowRun> {
|
|
31
|
+
const deadline = Date.now() + timeoutMs;
|
|
32
|
+
for (;;) {
|
|
33
|
+
const run = runs.get(runId);
|
|
34
|
+
if (run && run.state.status === "done") return run;
|
|
35
|
+
if (Date.now() > deadline) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`run ${runId} did not reach a terminal state within ${timeoutMs}ms ` +
|
|
38
|
+
`(status=${run?.state.status ?? "unknown"}) — hang regression`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe("[F1] 不可克隆 return → run failed(非悬挂)— e2e", () => {
|
|
46
|
+
it(
|
|
47
|
+
"return { fn: () => 1 } → 经 script-error 重试矩阵收敛到 done,failed,归因含 structured-clone failed",
|
|
48
|
+
async () => {
|
|
49
|
+
const runs = new Map<string, WorkflowRun>();
|
|
50
|
+
const store: RunStore = {
|
|
51
|
+
save: vi.fn(async () => {}),
|
|
52
|
+
loadAll: async () => [],
|
|
53
|
+
stateFilePath: (id: string) => `/tmp/f1-e2e/${id}.jsonl`,
|
|
54
|
+
};
|
|
55
|
+
const deps = {
|
|
56
|
+
store,
|
|
57
|
+
workerHost: new WorkerHostImpl(),
|
|
58
|
+
runner: { run: vi.fn(async () => ({})) },
|
|
59
|
+
runs,
|
|
60
|
+
eventBus: { emit: vi.fn() },
|
|
61
|
+
onRunDone: vi.fn(),
|
|
62
|
+
log: vi.fn(),
|
|
63
|
+
} as unknown as LifecycleDeps & { onRunDone: ReturnType<typeof vi.fn> };
|
|
64
|
+
|
|
65
|
+
const spec: RunSpec = {
|
|
66
|
+
scriptSource: "return { ok: true, fn: () => 1 };",
|
|
67
|
+
args: {},
|
|
68
|
+
scriptName: "f1-non-cloneable",
|
|
69
|
+
scriptPath: "f1-non-cloneable.js",
|
|
70
|
+
slug: "f1-non-cloneable",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const runId = await runWorkflow(spec, deps);
|
|
74
|
+
expect(runs.get(runId)?.state.status).toBe("running");
|
|
75
|
+
|
|
76
|
+
// 挂起 → 此处超时 throw(修复前行为);收敛 → done
|
|
77
|
+
const run = await waitForTerminal(runs, runId, 30_000);
|
|
78
|
+
|
|
79
|
+
expect(run.state.reason).toBe("failed");
|
|
80
|
+
// worker 侧 fallback 消息经 handleScriptError 超限路径写入归因
|
|
81
|
+
expect(run.state.error).toContain("structured-clone failed");
|
|
82
|
+
// 终态副作用齐全(对比 SW-DATA-3/F1 前的幽灵悬挂:无 unregister / 无 onRunDone)
|
|
83
|
+
expect(deps.eventBus.emit).toHaveBeenCalledWith(
|
|
84
|
+
"pending:unregister",
|
|
85
|
+
expect.objectContaining({ id: runId, reason: "failed" }),
|
|
86
|
+
);
|
|
87
|
+
expect(deps.onRunDone).toHaveBeenCalledTimes(1);
|
|
88
|
+
// 终态已落盘(F1 不变式的持久化半边:非但收敛,且状态被记录可恢复)
|
|
89
|
+
expect(store.save).toHaveBeenCalled();
|
|
90
|
+
// workerLogs(DataCloneError 详情)随 error 消息落入 errorLogs,诊断不丢
|
|
91
|
+
expect(run.state.errorLogs.length).toBeGreaterThan(0);
|
|
92
|
+
},
|
|
93
|
+
35_000,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// 内置 workflow 脚本 scriptPath 锚定 fail-fast(u0-failfast / D1 附带加固,计划偏差 #6 扩展)。
|
|
2
|
+
//
|
|
3
|
+
// 验证目标:worker 依赖加载从「cwd 静默回退」收紧为 fail-fast——scriptPath 缺席时
|
|
4
|
+
// 必须报 core_module_load_failed 且不加载用户目录下的同名依赖文件
|
|
5
|
+
// (review-fix-loop.js → review-fix-loop-utils.cjs;chain/parallel/map-reduce/
|
|
6
|
+
// scatter-gather → _shared/agent-refs.cjs),消除从 cwd 误加载/被植入同名文件的代码加载面。
|
|
7
|
+
//
|
|
8
|
+
// 驱动方式:node:child_process spawn node -e 探针 + AsyncFunction 包装。五个脚本均含
|
|
9
|
+
// 顶层 await(agent/parallel 入口)与顶层 return,是 worker 模板宿主形态——纯文件加载
|
|
10
|
+
// (.js ESM / .cjs CJS)在解析期即 SyntaxError,守卫无从执行(review-fix-loop-script.test.ts
|
|
11
|
+
// 头注释同样记录了该形态约束)。探针以 AsyncFunction 构造器复刻 worker 模板的「async
|
|
12
|
+
// 函数包装 + require 注入」宿主形态后求值真实源码副本,仍是真实子进程 + 真实退出码。
|
|
13
|
+
// 负向探针在 cwd 预置植入版依赖(require 即抛标记错误),断言标记未出现——直接验证
|
|
14
|
+
// 安全属性本体;正向探针以「require 之后的确定性行为」作为依赖加载成功的证据
|
|
15
|
+
// (review-fix-loop 白名单校验执行 = VALID_ARG_KEYS 已解构;chain 推进到编排段
|
|
16
|
+
// 首个模板全局 log = _shared/agent-refs.cjs 已 require)。
|
|
17
|
+
import { execFile } from "node:child_process";
|
|
18
|
+
import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { promisify } from "node:util";
|
|
22
|
+
|
|
23
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
24
|
+
|
|
25
|
+
const WORKFLOWS_DIR = join(__dirname, "..", "..", "..", "workflows");
|
|
26
|
+
|
|
27
|
+
/** 五个内置脚本(stem → 源文件名),副本统一以 .cjs 落 sandbox。 */
|
|
28
|
+
const SCRIPT_STEMS = ["review-fix-loop", "chain", "parallel", "map-reduce", "scatter-gather"] as const;
|
|
29
|
+
|
|
30
|
+
/** 各脚本到达依赖加载守卫所需的最小合法 $ARGS(编排四件的必需参数校验先于守卫——
|
|
31
|
+
* 真实触发场景即「args 合法 + scriptPath 缺失」,与 worker 宿主总是成对注入的契约一致)。 */
|
|
32
|
+
const MIN_VALID_ARGS: Record<(typeof SCRIPT_STEMS)[number], string> = {
|
|
33
|
+
"review-fix-loop": '{ targetType: "file", target: "probe" }',
|
|
34
|
+
chain: '{ task: "probe" }',
|
|
35
|
+
parallel: '{ target: "probe" }',
|
|
36
|
+
"map-reduce": '{ operation: "probe", items: ["a"] }',
|
|
37
|
+
"scatter-gather": '{ task: "probe" }',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** 植入依赖的标记错误文本:出现即证明 cwd 回退加载仍然存在(fail-fast 被绕过)。 */
|
|
41
|
+
const PLANTED_MARKER = "PLANTED-CWD-UTILS-LOADED";
|
|
42
|
+
|
|
43
|
+
const run = promisify(execFile);
|
|
44
|
+
|
|
45
|
+
/** execFile reject 侧的最小形状(Node ExecException 子集,避免 any / 无守卫断言)。 */
|
|
46
|
+
interface ExecFailure extends Error {
|
|
47
|
+
code?: number | string;
|
|
48
|
+
stderr?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isExecFailure(e: unknown): e is ExecFailure {
|
|
52
|
+
return e instanceof Error;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let sandboxDir = "";
|
|
56
|
+
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
sandboxDir = mkdtempSync(join(tmpdir(), "rfl-scriptpath-failfast-"));
|
|
59
|
+
for (const stem of SCRIPT_STEMS) {
|
|
60
|
+
copyFileSync(join(WORKFLOWS_DIR, stem + ".js"), join(sandboxDir, stem + ".cjs"));
|
|
61
|
+
}
|
|
62
|
+
// _shared 布局对齐真实 workflows/(四编排脚本经 SCRIPT_DIR + "/_shared" 定位)
|
|
63
|
+
mkdirSync(join(sandboxDir, "_shared"));
|
|
64
|
+
copyFileSync(join(WORKFLOWS_DIR, "_shared", "agent-refs.cjs"), join(sandboxDir, "_shared", "agent-refs.cjs"));
|
|
65
|
+
// review-fix-loop 的纯函数层依赖(正向探针的 scriptPath 锚定 require 对象)
|
|
66
|
+
copyFileSync(join(WORKFLOWS_DIR, "review-fix-loop-utils.cjs"), join(sandboxDir, "review-fix-loop-utils.cjs"));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
afterEach(() => {
|
|
70
|
+
rmSync(sandboxDir, { recursive: true, force: true });
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/** cwd 植入件:若任一脚本回退 process.cwd() 加载依赖,本文件被 require 即抛标记错误。 */
|
|
74
|
+
function plantHostileUtils(dir: string): void {
|
|
75
|
+
const payload = 'throw new Error("' + PLANTED_MARKER + '");\n';
|
|
76
|
+
writeFileSync(join(dir, "review-fix-loop-utils.cjs"), payload, "utf8");
|
|
77
|
+
writeFileSync(join(dir, "_shared", "agent-refs.cjs"), payload, "utf8");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 跑 node 子进程并要求非零退出,返回 stderr。意外零退出 → 显式红(探针失效不静默)。 */
|
|
81
|
+
async function runNodeExpectFailure(args: string[], cwd: string): Promise<string> {
|
|
82
|
+
const outcome = await run(process.execPath, args, { cwd, timeout: 30_000 }).then(
|
|
83
|
+
(): ExecFailure | null => null,
|
|
84
|
+
(e: unknown): ExecFailure | null => (isExecFailure(e) ? e : null),
|
|
85
|
+
);
|
|
86
|
+
if (outcome === null) {
|
|
87
|
+
throw new Error("expected non-zero exit, but node exited 0: " + args.join(" "));
|
|
88
|
+
}
|
|
89
|
+
return String(outcome.stderr ?? "");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** 跑 node 子进程并要求零退出,返回 { stdout, stderr }。非零退出 → 显式红。 */
|
|
93
|
+
async function runNodeExpectSuccess(args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {
|
|
94
|
+
const outcome = await run(process.execPath, args, { cwd, timeout: 30_000 }).then(
|
|
95
|
+
(r: { stdout: string; stderr: string }) => r,
|
|
96
|
+
(): null => null,
|
|
97
|
+
);
|
|
98
|
+
if (outcome === null) {
|
|
99
|
+
throw new Error("expected zero exit, but node exited non-zero: " + args.join(" "));
|
|
100
|
+
}
|
|
101
|
+
return outcome;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** -e 探针体:AsyncFunction 包装复刻 worker 模板宿主形态,注入 workerData/$ARGS/log
|
|
105
|
+
* 后求值指定脚本副本。log 为模板全局(map-reduce 在守卫前有 log 调用,缺失会提前
|
|
106
|
+
* ReferenceError 而到不了守卫),实现为 writeSync(1) 记录到 stdout——编排脚本自身的
|
|
107
|
+
* try/catch 会吞掉后续缺失模板全局的 ReferenceError 并正常返回(exit 0),「依赖加载
|
|
108
|
+
* 之后的启动日志已打出」因此构成依赖加载成功的确定性证据。 */
|
|
109
|
+
function probeCode(stem: string, workerDataJson: string, argsJson: string): string {
|
|
110
|
+
const copyPath = join(sandboxDir, stem + ".cjs");
|
|
111
|
+
return [
|
|
112
|
+
"const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;",
|
|
113
|
+
"const src = require('fs').readFileSync(" + JSON.stringify(copyPath) + ", 'utf8');",
|
|
114
|
+
"const runner = new AsyncFunction('workerData', '$ARGS', 'require', 'log', src + '\\n');",
|
|
115
|
+
"const workerData = " + workerDataJson + ";",
|
|
116
|
+
"const $ARGS = " + argsJson + ";",
|
|
117
|
+
"runner(workerData, $ARGS, require, function (m) { require('fs').writeSync(1, String(m) + '\\n'); }).catch(function (e) {",
|
|
118
|
+
" require('fs').writeSync(2, String((e && e.message) || e) + '\\n');",
|
|
119
|
+
" process.exit(1);",
|
|
120
|
+
"});",
|
|
121
|
+
].join("\n");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
describe("内置 workflow 脚本 scriptPath 锚定 fail-fast(u0-failfast)", () => {
|
|
125
|
+
it.each(SCRIPT_STEMS.map((stem) => [stem]))(
|
|
126
|
+
"%s:scriptPath 缺席 → 非零退出 + core_module_load_failed,cwd 植入依赖不被加载",
|
|
127
|
+
async (stem) => {
|
|
128
|
+
plantHostileUtils(sandboxDir);
|
|
129
|
+
const stderr = await runNodeExpectFailure(
|
|
130
|
+
["-e", probeCode(stem, "undefined", MIN_VALID_ARGS[stem])],
|
|
131
|
+
sandboxDir,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(stderr).toContain("core_module_load_failed");
|
|
135
|
+
// 恢复动作可操作:指明注入义务(workerData.scriptPath / WorkerHost)
|
|
136
|
+
expect(stderr).toContain("workerData");
|
|
137
|
+
expect(stderr).toContain("WorkerHost");
|
|
138
|
+
// 安全属性本体:cwd 回退已消除,植入的同名依赖未被加载
|
|
139
|
+
expect(stderr).not.toContain(PLANTED_MARKER);
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
it.each([
|
|
144
|
+
["workerData 为空对象", "{}"],
|
|
145
|
+
["scriptPath 非字符串", "{ scriptPath: 123 }"],
|
|
146
|
+
])("review-fix-loop:%s → fail-fast 报 core_module_load_failed", async (_label, workerDataJson) => {
|
|
147
|
+
plantHostileUtils(sandboxDir);
|
|
148
|
+
const stderr = await runNodeExpectFailure(
|
|
149
|
+
["-e", probeCode("review-fix-loop", workerDataJson, "{}")],
|
|
150
|
+
sandboxDir,
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
expect(stderr).toContain("core_module_load_failed");
|
|
154
|
+
expect(stderr).not.toContain(PLANTED_MARKER);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("正向探针(review-fix-loop):scriptPath 注入后 utils 锚定加载成功(白名单校验执行 = VALID_ARG_KEYS 已解构)", async () => {
|
|
158
|
+
const workerDataJson = "{ scriptPath: " + JSON.stringify(join(sandboxDir, "review-fix-loop.cjs")) + " }";
|
|
159
|
+
const stderr = await runNodeExpectFailure(
|
|
160
|
+
["-e", probeCode("review-fix-loop", workerDataJson, "{ definitelyNotAValidKey: true }")],
|
|
161
|
+
sandboxDir,
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// utils 加载成功的证据:白名单校验执行并拒绝伪造键(fail 协议消息),而非模块加载失败
|
|
165
|
+
expect(stderr).toContain("未知参数: definitelyNotAValidKey");
|
|
166
|
+
expect(stderr).not.toContain("core_module_load_failed");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("正向探针(chain):scriptPath 注入后 _shared/agent-refs.cjs 锚定加载成功(依赖加载后的编排启动日志已打出)", async () => {
|
|
170
|
+
const workerDataJson = "{ scriptPath: " + JSON.stringify(join(sandboxDir, "chain.cjs")) + " }";
|
|
171
|
+
const { stdout, stderr } = await runNodeExpectSuccess(
|
|
172
|
+
["-e", probeCode("chain", workerDataJson, '{ task: "probe" }')],
|
|
173
|
+
sandboxDir,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// 依赖加载成功的证据:chain.js 的守卫与 require 位于 try 之外(require 失败 →
|
|
177
|
+
// 非零退出 + core_module_load_failed),其后的启动日志「chain 开始」能出现在
|
|
178
|
+
// stdout 即证明 _shared/agent-refs.cjs 已锚定加载且执行推进到编排段
|
|
179
|
+
expect(stdout).toContain("chain 开始");
|
|
180
|
+
expect(stderr).not.toContain("core_module_load_failed");
|
|
181
|
+
expect(stderr).not.toContain(PLANTED_MARKER);
|
|
182
|
+
});
|
|
183
|
+
});
|