@zhushanwen/subagent-core 0.4.0 → 0.6.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/{chunk-4KN4TTG7.js → chunk-43ONBFZX.js} +1 -1
- package/dist/{chunk-X7SZ5HLQ.js → chunk-V3VHZ2VX.js} +20 -27
- package/dist/execution/engine/engines/zcode/constants.cjs +29 -41
- package/dist/execution/engine/engines/zcode/constants.d.cts +65 -53
- package/dist/execution/engine/engines/zcode/constants.d.ts +65 -53
- package/dist/execution/engine/engines/zcode/constants.js +17 -27
- package/dist/execution/engine/engines/zcode/reader.d.cts +2 -1
- package/dist/execution/engine/engines/zcode/reader.d.ts +2 -1
- package/dist/execution/engine/engines/zcode/reader.js +2 -2
- package/dist/index.cjs +17100 -14082
- package/dist/index.d.cts +5336 -4033
- package/dist/index.d.ts +5336 -4033
- package/dist/index.js +17020 -14055
- package/dist/{types-DpUO16pj.d.cts → types-C3fE3R9x.d.cts} +280 -112
- package/dist/{types-DpUO16pj.d.ts → types-C3fE3R9x.d.ts} +280 -112
- package/dist.bundle/index.cjs +34933 -0
- package/package.json +3 -3
- package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +0 -1
- package/src/__tests__/append-system-prompt-assembly.test.ts +8 -7
- package/src/__tests__/fr4-get-state-handshake.test.ts +2 -2
- package/src/__tests__/m2-append-content-probe.test.ts +0 -1
- package/src/__tests__/manifest-store.test.ts +10 -9
- package/src/__tests__/record-store-cache.test.ts +0 -2
- package/src/__tests__/record-store-index.test.ts +1 -2
- package/src/__tests__/review-fix-loop-script.test.ts +4 -2
- package/src/__tests__/review-fix-loop-utils.test.ts +10 -10
- package/src/__tests__/robustness-low-batch1.test.ts +6 -5
- package/src/__tests__/robustness-medium-batch1.test.ts +2 -2
- package/src/__tests__/robustness-medium-batch2.test.ts +17 -6
- package/src/__tests__/robustness-medium-batch4.test.ts +2 -2
- package/src/__tests__/session-runner.test.ts +1 -1
- package/src/core/__tests__/host-services.test.ts +2 -2
- package/src/core/__tests__/logger.test.ts +1 -1
- package/src/core/error-message.ts +9 -0
- package/src/core/host-services.ts +21 -5
- package/src/core/notify-ports.ts +18 -5
- package/src/execution/__tests__/agent-profile.test.ts +4 -4
- package/src/execution/__tests__/agent-registry.test.ts +370 -0
- package/src/execution/__tests__/agent-result-mapper.test.ts +18 -2
- package/src/execution/__tests__/agents-assembly.test.ts +2 -2
- package/src/execution/__tests__/alive-store.test.ts +1 -1
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
- package/src/execution/__tests__/chat-engine-routing.test.ts +68 -33
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +4 -4
- package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
- package/src/execution/__tests__/collect-budget.test.ts +291 -0
- package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
- package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
- package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
- package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
- package/src/execution/__tests__/config.test.ts +1 -1
- package/src/execution/__tests__/delivery-methods.test.ts +75 -62
- package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
- package/src/execution/__tests__/descendant-sweep.test.ts +6 -6
- package/src/execution/__tests__/dialog-queue.test.ts +2 -2
- package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
- package/src/execution/__tests__/epipe-fallback.test.ts +29 -24
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +21 -91
- package/src/execution/__tests__/execute-nesting.test.ts +34 -188
- package/src/execution/__tests__/execution-record.test.ts +217 -60
- package/src/execution/__tests__/execution-runtime-face.test.ts +5 -5
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +4 -4
- package/src/execution/__tests__/finalize-record.test.ts +173 -17
- package/src/execution/__tests__/finalized-marker.test.ts +1 -1
- package/src/execution/__tests__/gc-timer.test.ts +56 -3
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +12 -12
- package/src/execution/__tests__/get-state-handshake.test.ts +1 -1
- package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
- package/src/execution/__tests__/helpers/session-runner-mocks.ts +113 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +150 -3
- package/src/execution/__tests__/helpers/subagent-service-mocks.ts +137 -0
- package/src/execution/__tests__/keep-alive-no-progress.test.ts +50 -148
- package/src/execution/__tests__/kill-all-escalation.test.ts +2 -2
- package/src/execution/__tests__/lifecycle-predicates.test.ts +1 -2
- package/src/execution/__tests__/manifest-parentid.test.ts +4 -4
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +1 -1
- package/src/execution/__tests__/model-resolver.test.ts +2 -2
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +23 -121
- package/src/execution/__tests__/nested-visibility.test.ts +2 -0
- package/src/execution/__tests__/notify-batch.test.ts +500 -0
- package/src/execution/__tests__/notify-ledger.test.ts +1000 -18
- package/src/execution/__tests__/output-collector.test.ts +117 -6
- package/src/execution/__tests__/pi-invocation.test.ts +36 -4
- package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
- package/src/execution/__tests__/record-store.test.ts +10 -9
- package/src/execution/__tests__/records-cwd-isolation.test.ts +2 -2
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +29 -132
- package/src/execution/__tests__/recursive-visibility-env.test.ts +55 -179
- package/src/execution/__tests__/relay-env.test.ts +12 -1
- package/src/execution/__tests__/rpc-mode.test.ts +2 -2
- package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +387 -0
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +15 -9
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +4 -4
- package/src/execution/__tests__/run-spawn-edges.test.ts +17 -15
- package/src/execution/__tests__/run-spawn-integration.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-resume.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +4 -4
- package/src/execution/__tests__/service-kill-escalation.test.ts +7 -5
- package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
- package/src/execution/__tests__/session-file-gc.test.ts +36 -1
- package/src/execution/__tests__/session-pending.test.ts +257 -14
- package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +1 -1
- package/src/execution/__tests__/session-runner-close-prune.test.ts +2 -2
- package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +3 -3
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +5 -4
- package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +290 -0
- package/src/execution/__tests__/session-runner-schema-env.test.ts +7 -5
- package/src/execution/__tests__/settled-watchdog.test.ts +282 -47
- package/src/execution/__tests__/spawn-args.test.ts +11 -10
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +26 -23
- package/src/execution/__tests__/spawn-event-adapter.test.ts +3 -3
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
- package/src/execution/__tests__/spawned-children.test.ts +2 -1
- package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
- package/src/execution/__tests__/start-sync-model-guard.test.ts +5 -5
- package/src/execution/__tests__/stdin-writer.test.ts +6 -4
- package/src/execution/__tests__/stream-sink-retirement.test.ts +6 -6
- package/src/execution/__tests__/subagent-actions-core.test.ts +48 -22
- package/src/execution/__tests__/subagent-service-message-close.test.ts +29 -26
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +21 -8
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -22
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +30 -29
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +45 -20
- package/src/execution/__tests__/subagent-service.test.ts +37 -30
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +88 -12
- package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +75 -0
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +22 -20
- package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
- package/src/execution/__tests__/temp-prompt.test.ts +1 -1
- package/src/execution/__tests__/timeout-integration.test.ts +6 -5
- package/src/execution/__tests__/tombstone-store.test.ts +1 -1
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +1 -1
- package/src/execution/__tests__/turn-limiter.test.ts +1 -1
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +12 -6
- package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
- package/src/execution/__tests__/ui-request-queue.test.ts +142 -2
- package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
- package/src/execution/__tests__/worktree-manager.test.ts +14 -5
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +4 -3
- package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
- package/src/execution/__tests__/worktree-registry.test.ts +1 -1
- package/src/execution/agent-registry.ts +74 -30
- package/src/execution/agent-result-mapper.ts +3 -0
- package/src/execution/cold-resurrect.ts +199 -0
- package/src/execution/collect-coordinator.ts +200 -0
- package/src/execution/config.ts +77 -5
- package/src/execution/engine/__tests__/common/capability-gate.test.ts +91 -0
- package/src/execution/engine/__tests__/common/data-dir.test.ts +1 -1
- package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
- package/src/execution/engine/__tests__/common/journal-wiring.test.ts +84 -0
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +34 -7
- package/src/execution/engine/__tests__/common/persona-router.test.ts +4 -5
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +213 -53
- package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +149 -0
- package/src/execution/engine/__tests__/common/session-view-service.test.ts +499 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +22 -112
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +15 -28
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +12 -12
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +2 -2
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +21 -82
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +4 -7
- package/src/execution/engine/__tests__/engine-discovery.test.ts +15 -3
- package/src/execution/engine/__tests__/model-prompt.test.ts +15 -3
- package/src/execution/engine/__tests__/registry.test.ts +4 -2
- package/src/execution/engine/__tests__/routing.test.ts +115 -6
- package/src/execution/engine/common/capability-gate.ts +92 -0
- package/src/execution/engine/common/journal-wiring.ts +97 -0
- package/src/execution/engine/common/kill-chain.ts +42 -10
- package/src/execution/engine/common/nesting-guard.ts +66 -0
- package/src/execution/engine/common/persona-router.ts +18 -8
- package/src/execution/engine/common/pool-manager.ts +332 -78
- package/src/execution/engine/common/session-view-service.ts +506 -0
- package/src/execution/engine/common/session-view-types.ts +125 -0
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +174 -28
- package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +257 -0
- package/src/execution/{argv-mirror.ts → engine/engines/pi/argv-mirror.ts} +43 -21
- package/src/execution/{get-state-handshake.ts → engine/engines/pi/get-state-handshake.ts} +1 -1
- package/src/execution/{output-collector.ts → engine/engines/pi/output-collector.ts} +108 -19
- package/src/execution/engine/engines/pi/pi-engine.ts +434 -38
- package/src/execution/{pi-invocation.ts → engine/engines/pi/pi-invocation.ts} +2 -2
- package/src/execution/engine/engines/pi/reader.ts +11 -0
- package/src/execution/engine/engines/pi/registration.ts +4 -2
- package/src/execution/{session-runner.ts → engine/engines/pi/session-runner.ts} +617 -412
- package/src/execution/{spawn-event-adapter.ts → engine/engines/pi/spawn-event-adapter.ts} +75 -34
- package/src/execution/{stdin-writer.ts → engine/engines/pi/stdin-writer.ts} +10 -9
- package/src/execution/{temp-prompt.ts → engine/engines/pi/temp-prompt.ts} +2 -2
- package/src/execution/{turn-limiter.ts → engine/engines/pi/turn-limiter.ts} +1 -1
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +54 -27
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +13 -12
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +7 -210
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +6 -110
- package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +247 -0
- package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +451 -0
- package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +20 -8
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +77 -110
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +26 -320
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +210 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +353 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +282 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +372 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +48 -148
- package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
- package/src/execution/engine/engines/zcode/connection.ts +24 -11
- package/src/execution/engine/engines/zcode/constants.ts +75 -71
- package/src/execution/engine/engines/zcode/golden-sample.ts +8 -46
- package/src/execution/engine/engines/zcode/parser.ts +12 -346
- package/src/execution/engine/engines/zcode/preparer.ts +12 -143
- package/src/execution/engine/engines/zcode/session-channel.ts +351 -39
- package/src/execution/engine/engines/zcode/zcode-engine.ts +665 -760
- package/src/execution/engine/host-task-spec.ts +32 -36
- package/src/execution/engine/model-validation.ts +177 -0
- package/src/execution/engine/port.ts +24 -6
- package/src/execution/engine/routing.ts +75 -1
- package/src/execution/engine/types.ts +30 -103
- package/src/execution/execution-record.ts +229 -144
- package/src/execution/finalize-record.ts +141 -99
- package/src/execution/idle-gc.ts +28 -0
- package/src/execution/lifecycle-predicates.ts +1 -1
- package/src/execution/notifier.ts +234 -25
- package/src/execution/notify-host.ts +232 -0
- package/src/execution/record-entry.ts +16 -0
- package/src/execution/record-store.ts +280 -103
- package/src/execution/round-settlement.ts +93 -0
- package/src/execution/session-file-gc.ts +96 -62
- package/src/execution/session-reconstructor.ts +256 -143
- package/src/execution/sessions-index.ts +117 -47
- package/src/execution/settled-watchdog.ts +264 -52
- package/src/execution/subagent-actions-core.ts +84 -28
- package/src/execution/subagent-service.ts +1225 -964
- package/src/execution/subprocess-agent-runner.ts +144 -97
- package/src/execution/sync-rebuild.ts +87 -0
- package/src/execution/types.ts +72 -0
- package/src/execution/ui-request-handler-factory.ts +102 -74
- package/src/execution/ui-request-queue.ts +50 -19
- package/src/index.ts +442 -316
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +1 -1
- package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
- package/src/orchestration/__tests__/args-validator.test.ts +14 -0
- package/src/orchestration/__tests__/config-loader.test.ts +1 -1
- package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +1 -1
- package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +11 -9
- package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
- package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store.test.ts +7 -6
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +2 -2
- package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +1 -1
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
- package/src/orchestration/__tests__/lifecycle.test.ts +7 -5
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
- package/src/orchestration/__tests__/run-snapshot.test.ts +8 -5
- package/src/orchestration/__tests__/script-generate.test.ts +5 -5
- package/src/orchestration/__tests__/script-lint.test.ts +17 -0
- package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
- package/src/orchestration/__tests__/test-mocks.ts +2 -0
- package/src/orchestration/__tests__/worker-exit-without-result.test.ts +7 -6
- package/src/orchestration/__tests__/worker-message-pump-finalize-run.test.ts +229 -0
- package/src/orchestration/__tests__/{error-recovery-handlers.test.ts → worker-message-pump-handlers.test.ts} +27 -19
- package/src/orchestration/__tests__/{error-recovery-postmessage-defense.test.ts → worker-message-pump-postmessage-defense.test.ts} +8 -8
- package/src/orchestration/__tests__/{error-recovery-serialize-failed-result.test.ts → worker-message-pump-serialize-failed-result.test.ts} +2 -2
- package/src/orchestration/__tests__/{error-recovery-workflow-call.test.ts → worker-message-pump-workflow-call.test.ts} +1 -1
- package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +1 -1
- package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
- package/src/orchestration/agent-opts-resolver.ts +1 -1
- package/src/orchestration/args-validator.ts +53 -31
- package/src/orchestration/execute-agent-call.ts +19 -73
- package/src/orchestration/launcher.ts +128 -81
- package/src/orchestration/lifecycle.ts +43 -45
- package/src/orchestration/models/ports.ts +4 -4
- package/src/orchestration/models/run-runtime.ts +2 -2
- package/src/orchestration/models/trace.ts +1 -1
- package/src/orchestration/models/types.ts +111 -22
- package/src/orchestration/models/workflow-run.ts +1 -1
- package/src/orchestration/script-lint.ts +91 -58
- package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +157 -150
- package/src/shared/__tests__/atomic-write.test.ts +1 -1
- package/src/shared/__tests__/meta-parser.test.ts +151 -0
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
- package/src/shared/__tests__/resource-discovery.test.ts +258 -215
- package/src/shared/atomic-write.ts +12 -9
- package/src/shared/meta-parser.ts +158 -84
- package/src/shared/model-ref.ts +15 -2
- package/src/shared/resource-discovery.ts +9 -183
- package/src/shared/schema-jsonify.ts +1 -1
- package/workflows/review-fix-loop-utils.cjs +151 -89
- package/workflows/review-fix-loop-utils.d.cts +287 -0
- package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
- package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
- package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
- package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +0 -387
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -710
- package/src/execution/engine/engines/zcode/appserver-home.ts +0 -442
- package/src/execution/engine/engines/zcode/appserver-probe.ts +0 -141
- package/src/execution/engine/engines/zcode/launcher.ts +0 -161
- package/src/execution/execute-options-mapper.ts +0 -115
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
|
@@ -1,120 +1,21 @@
|
|
|
1
1
|
// contract.abort.test.ts —— conformance C4(abort 行为):运行中 cancel → 宿主合成
|
|
2
2
|
// 终态(exitCode=null)、无悬挂 promise(run 正常 resolve、exited 收口)、错误事件
|
|
3
|
-
// 先于终态 emit(不变量 5 的事件面)。fake
|
|
3
|
+
// 先于终态 emit(不变量 5 的事件面)。fake app-server 注入(不依赖真机)。
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// (fake-appserver.mjs 挂起场景,stop 链优先于杀链——D3)。两形态各自覆盖:
|
|
5
|
+
// 2026-09 重构(共享宿主 HOME):CLI spawn 降级链删除后引擎只剩 app-server 常驻链,
|
|
6
|
+
// abort 用例只覆盖常驻形态(fake-appserver.mjs 挂起场景,stop 链优先于杀链——D3)。
|
|
8
7
|
// capabilities.interrupt 维持 kill-only 声明(D5——改链路先于改声明,stop 链路经
|
|
9
8
|
// conformance 真机验证后再评估升 native)。
|
|
10
9
|
|
|
11
|
-
import {
|
|
12
|
-
import * as fs from "node:fs";
|
|
13
|
-
import * as os from "node:os";
|
|
14
|
-
import * as path from "node:path";
|
|
15
|
-
import { PassThrough } from "node:stream";
|
|
16
|
-
|
|
17
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import { describe, expect, it, vi } from "vitest";
|
|
18
11
|
|
|
12
|
+
import type { AgentCallOpts } from "../../../../orchestration/models/types.ts";
|
|
19
13
|
import type { RunContext } from "../../port.ts";
|
|
20
|
-
import type { AgentEvent
|
|
21
|
-
import { ZcodeEngine, type ZcodeEngineDeps } from "../../engines/zcode/zcode-engine.ts";
|
|
22
|
-
import type { ZcodeLaunchedProcess } from "../../engines/zcode/launcher.ts";
|
|
14
|
+
import type { AgentEvent } from "../../types.ts";
|
|
23
15
|
import { makeAppserverHarness, sentMethodNames } from "./zcode-appserver-harness.ts";
|
|
24
16
|
|
|
25
|
-
const PROVIDER = "provider-x";
|
|
26
|
-
|
|
27
|
-
let tmpRoot: string;
|
|
28
|
-
let dataDir: string;
|
|
29
|
-
let v2Path: string;
|
|
30
|
-
|
|
31
|
-
function writeJson(p: string, v: unknown): void {
|
|
32
|
-
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
33
|
-
fs.writeFileSync(p, JSON.stringify(v));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** 长驻 fake 进程:stdout 永不结束(模拟运行中),abort 由测试主动触发。 */
|
|
37
|
-
function makeHangingLaunch(): {
|
|
38
|
-
launch: ZcodeEngineDeps["launch"];
|
|
39
|
-
proc: () => ZcodeLaunchedProcess | undefined;
|
|
40
|
-
triggerAbort: () => void;
|
|
41
|
-
} {
|
|
42
|
-
let launched: ZcodeLaunchedProcess | undefined;
|
|
43
|
-
const stdout = new PassThrough();
|
|
44
|
-
const stderr = new PassThrough();
|
|
45
|
-
let killTriggered = false;
|
|
46
|
-
let resolveExited: (v: { code: number | null; signal: string | undefined }) => void = () => {};
|
|
47
|
-
const exited = new Promise<{ code: number | null; signal: string | undefined }>((resolve) => {
|
|
48
|
-
resolveExited = resolve;
|
|
49
|
-
});
|
|
50
|
-
const launch = (): ZcodeLaunchedProcess => {
|
|
51
|
-
launched = {
|
|
52
|
-
// D10 记账形态:child = 立即退出的真实 node 短进程(本用例不消费记账面)
|
|
53
|
-
child: spawn(process.execPath, ["-e", ""]),
|
|
54
|
-
pid: 4242,
|
|
55
|
-
stdout,
|
|
56
|
-
stderr,
|
|
57
|
-
abort: async () => {
|
|
58
|
-
killTriggered = true;
|
|
59
|
-
// 杀链语义:进程被信号杀死(code=null)——微任务后 settle 模拟 kill 时序
|
|
60
|
-
setTimeout(() => resolveExited({ code: null, signal: "SIGTERM" }), 5);
|
|
61
|
-
},
|
|
62
|
-
exited,
|
|
63
|
-
killedByUs: () => killTriggered,
|
|
64
|
-
};
|
|
65
|
-
return launched;
|
|
66
|
-
};
|
|
67
|
-
return { launch, proc: () => launched, triggerAbort: () => resolveExited({ code: null, signal: "SIGTERM" }) };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
beforeEach(() => {
|
|
71
|
-
tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "c4-abort-"));
|
|
72
|
-
dataDir = path.join(tmpRoot, "data");
|
|
73
|
-
v2Path = path.join(tmpRoot, "v2.json");
|
|
74
|
-
writeJson(v2Path, {
|
|
75
|
-
provider: { [PROVIDER]: { options: { apiKey: "k" }, models: { m1: {} } } },
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
afterEach(() => {
|
|
80
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
81
|
-
});
|
|
82
|
-
|
|
83
17
|
describe("conformance C4:abort 行为(运行中 cancel → 合成终态、无悬挂)", () => {
|
|
84
|
-
|
|
85
|
-
const fake = makeHangingLaunch();
|
|
86
|
-
const engine = new ZcodeEngine({
|
|
87
|
-
engineDataDir: () => dataDir,
|
|
88
|
-
sources: { v2ConfigPath: v2Path },
|
|
89
|
-
processEnv: { PATH: "/usr/bin", XYZ_ZCODE_MODE: "spawn" },
|
|
90
|
-
launch: fake.launch,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const controller = new AbortController();
|
|
94
|
-
const events: AgentEvent[] = [];
|
|
95
|
-
const ctx: RunContext = {
|
|
96
|
-
taskId: "sa-c4",
|
|
97
|
-
poolKey: "",
|
|
98
|
-
signal: controller.signal,
|
|
99
|
-
onEvent: (ev) => events.push(ev),
|
|
100
|
-
};
|
|
101
|
-
const task: AgentTaskSpec = { task: "hang", slug: "abort", model: `${PROVIDER}/m1` };
|
|
102
|
-
|
|
103
|
-
const runP = engine.run(task, ctx);
|
|
104
|
-
// run 进行中触发 abort(等待 spawn 完成——微任务两拍让 launch 已执行)
|
|
105
|
-
await new Promise((r) => setTimeout(r, 20));
|
|
106
|
-
controller.abort();
|
|
107
|
-
const { handle, outcome } = await runP; // 必须正常 resolve(杀链合成终态,不悬挂)
|
|
108
|
-
|
|
109
|
-
expect(outcome.exitCode).toBeNull();
|
|
110
|
-
expect(outcome.error).toContain("中止");
|
|
111
|
-
// 终态前 error 事件已 emit(不变量 5 的事件面——journal 可重放出失败事实)
|
|
112
|
-
expect(events.some((e) => e.type === "error")).toBe(true);
|
|
113
|
-
expect(fake.proc()?.killedByUs()).toBe(true);
|
|
114
|
-
expect(handle.data.engineId).toBe("zcode");
|
|
115
|
-
}, 15_000);
|
|
116
|
-
|
|
117
|
-
// [R6] app-server 常驻形态:abort 走 D3 链(stop → grace → killChain)。挂起场景
|
|
18
|
+
// app-server 常驻形态:abort 走 D3 链(stop → grace → killChain)。挂起场景
|
|
118
19
|
// (只推 state.updated,turn 永不落定)+ stopBehavior 缺省 terminal = stop 优雅
|
|
119
20
|
// 生效路径——不杀共享进程,run 正常 resolve(C4 的常驻通道面)。
|
|
120
21
|
it("app-server 模式:abort → stop 帧先发 → 优雅收口(run resolve、exitCode=null、error 事件先于终态、kill-only 声明维持)", async () => {
|
|
@@ -125,10 +26,20 @@ describe("conformance C4:abort 行为(运行中 cancel → 合成终态、
|
|
|
125
26
|
|
|
126
27
|
const controller = new AbortController();
|
|
127
28
|
const events: AgentEvent[] = [];
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
29
|
+
const ctx: RunContext = {
|
|
30
|
+
taskId: "sa-c4-appserver",
|
|
31
|
+
poolKey: "",
|
|
32
|
+
signal: controller.signal,
|
|
33
|
+
onEvent: (e) => events.push(e),
|
|
34
|
+
};
|
|
35
|
+
// D6 合流后单一任务形状 AgentCallOpts(prompt≡原 task、description≡原 slug 源)
|
|
36
|
+
const task: AgentCallOpts = {
|
|
37
|
+
prompt: "hang",
|
|
38
|
+
description: "abort-appserver",
|
|
39
|
+
model: "conformance-provider/m1",
|
|
40
|
+
cwd: h.workspace,
|
|
41
|
+
};
|
|
42
|
+
const runP = h.engine.run(task, ctx);
|
|
132
43
|
// 推进到 send 已达(create+send 帧落 fake 流水)再 abort——abort 先于 create 会
|
|
133
44
|
// 走 pre-aborted 短路面,覆盖不到 stop 链
|
|
134
45
|
await vi.waitFor(
|
|
@@ -141,8 +52,7 @@ describe("conformance C4:abort 行为(运行中 cancel → 合成终态、
|
|
|
141
52
|
expect(outcome.exitCode).toBeNull();
|
|
142
53
|
expect(outcome.error).toContain("session/stop");
|
|
143
54
|
// 错误事件先于终态 emit(不变量 5 的事件面——journal 可重放出失败事实)。abort
|
|
144
|
-
// 终态不合成 turn_end
|
|
145
|
-
// 无任何非 error 事件流出)
|
|
55
|
+
// 终态不合成 turn_end(只断言 error 事件到达,且其后无任何非 error 事件流出)
|
|
146
56
|
const errorIdx = events.findIndex((e) => e.type === "error");
|
|
147
57
|
expect(errorIdx).toBeGreaterThanOrEqual(0);
|
|
148
58
|
expect(events.slice(errorIdx + 1).every((e) => e.type === "error")).toBe(true);
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
// contract.agent-events.test.ts —— conformance C3(AgentEvent 不变量)+ 负例自证
|
|
2
2
|
// (A12「套件有牙」:故意破坏一个不变量的样本必须被断言器检出——用「注入坏
|
|
3
|
-
// parser
|
|
3
|
+
// parser」的形态:构造抽掉 message_end / usage 半映射的坏样本流,断言套件转红;
|
|
4
4
|
// 若断言器检不出破坏则本元测试失败)。
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
6
|
+
// 2026-09 重构(共享宿主 HOME):CLI spawn 链删除后引擎只剩 app-server 常驻链,
|
|
7
|
+
// C3 的引擎全链覆盖只走 app-server 形态(fake 常驻引擎 + stream 口径,文件末
|
|
8
|
+
// describe;app-server 设计 §3.4 不变量 1:text_delta 拼接 == read 全文、终态唯一
|
|
9
|
+
// turn.terminal 权威、message_end.usage 完整、tool 事件不合成——granularity 声明
|
|
10
|
+
// 与实际流出一致)。断言器行为正反例与负例自证均为手工构造样本,不依赖引擎实现。
|
|
11
11
|
|
|
12
12
|
import { describe, expect, it } from "vitest";
|
|
13
13
|
|
|
14
14
|
import type { AgentEvent } from "../../../types.ts";
|
|
15
|
-
import { ZCODE_APPSERVER_GOLDEN
|
|
16
|
-
import {
|
|
17
|
-
import { parseZcodeTerminal, synthesizeCoarseEvents } from "../../engines/zcode/parser.ts";
|
|
15
|
+
import { ZCODE_APPSERVER_GOLDEN } from "../../engines/zcode/golden-sample.ts";
|
|
16
|
+
import { ZCODE_SHARED_POOL_KEY } from "../../engines/zcode/constants.ts";
|
|
18
17
|
import {
|
|
19
18
|
goldenReadFullText,
|
|
20
19
|
makeAppserverHarness,
|
|
@@ -24,18 +23,7 @@ import {
|
|
|
24
23
|
checkAgentEventInvariants,
|
|
25
24
|
} from "./agent-event-invariants.ts";
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
function goldenCoarseEvents(): AgentEvent[] {
|
|
29
|
-
const terminal = parseZcodeTerminal(ZCODE_GOLDEN_STDOUT);
|
|
30
|
-
if (!terminal.ok) throw new Error("golden 样本解析失败");
|
|
31
|
-
return synthesizeCoarseEvents(terminal.payload.response, terminal.payload.usage);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
describe("conformance C3:AgentEvent 不变量(真实 parser 产出全绿)", () => {
|
|
35
|
-
it("zcode golden 合成事件满足五条不变量(coarse 口径)", () => {
|
|
36
|
-
assertAgentEventInvariants(goldenCoarseEvents(), { granularity: "coarse" });
|
|
37
|
-
});
|
|
38
|
-
|
|
26
|
+
describe("conformance C3:AgentEvent 不变量(断言器正反例,手工构造样本)", () => {
|
|
39
27
|
it("不变量 1:终态唯一——turn_end 后不得再出现非 error 事件", () => {
|
|
40
28
|
const events: AgentEvent[] = [{ type: "message_end" }, { type: "turn_end" }, { type: "text_delta", delta: "x" }];
|
|
41
29
|
const findings = checkAgentEventInvariants(events, { granularity: "coarse" });
|
|
@@ -113,8 +101,7 @@ describe("conformance 负例自证(A12:套件有牙)", () => {
|
|
|
113
101
|
|
|
114
102
|
// ============================================================
|
|
115
103
|
// [R6] C3 app-server 口径:fake 常驻引擎全链(eventGranularity=stream 形态)
|
|
116
|
-
// ——
|
|
117
|
-
// spawn 路径,双通道都是生产可达形态)。
|
|
104
|
+
// —— 2026-09 重构后唯一生产形态(CLI spawn 降级链已删,无钉扎/降级双通道)。
|
|
118
105
|
// ============================================================
|
|
119
106
|
|
|
120
107
|
describe("conformance C3:zcode app-server 常驻通道(stream 口径,fake 常驻全链)", () => {
|
|
@@ -123,7 +110,7 @@ describe("conformance C3:zcode app-server 常驻通道(stream 口径,fake
|
|
|
123
110
|
try {
|
|
124
111
|
const events: AgentEvent[] = [];
|
|
125
112
|
const { outcome } = await h.engine.run(
|
|
126
|
-
{
|
|
113
|
+
{ prompt: "做点什么", description: "c3-appserver", model: "conformance-provider/m1", cwd: h.workspace },
|
|
127
114
|
{ taskId: "sa-c3-appserver", poolKey: "", onEvent: (e) => events.push(e) },
|
|
128
115
|
);
|
|
129
116
|
|
|
@@ -158,7 +145,7 @@ describe("conformance C3:zcode app-server 常驻通道(stream 口径,fake
|
|
|
158
145
|
try {
|
|
159
146
|
const events: AgentEvent[] = [];
|
|
160
147
|
const { outcome } = await h.engine.run(
|
|
161
|
-
{
|
|
148
|
+
{ prompt: "做点什么", description: "c3-no-terminal", model: "conformance-provider/m1", cwd: h.workspace },
|
|
162
149
|
{ taskId: "sa-c3-no-terminal", poolKey: "", onEvent: (e) => events.push(e) },
|
|
163
150
|
);
|
|
164
151
|
expect(outcome.error).toBeUndefined();
|
|
@@ -169,14 +156,14 @@ describe("conformance C3:zcode app-server 常驻通道(stream 口径,fake
|
|
|
169
156
|
}
|
|
170
157
|
}, 20_000);
|
|
171
158
|
|
|
172
|
-
it("handle
|
|
159
|
+
it("handle 携带 shared poolKey(共享宿主 HOME 的 journal 分组锚点,①级读取钥匙随 handle 走)", async () => {
|
|
173
160
|
const h = makeAppserverHarness();
|
|
174
161
|
try {
|
|
175
162
|
const { handle, outcome } = await h.engine.run(
|
|
176
|
-
{
|
|
163
|
+
{ prompt: "做点什么", description: "c3-anchor", model: "conformance-provider/m1", cwd: h.workspace },
|
|
177
164
|
{ taskId: "sa-c3-anchor", poolKey: "" },
|
|
178
165
|
);
|
|
179
|
-
expect(handle.data.poolKey).toBe(
|
|
166
|
+
expect(handle.data.poolKey).toBe(ZCODE_SHARED_POOL_KEY);
|
|
180
167
|
expect(handle.data.sessionRef["sessionId"]).toBe(outcome.sessionId);
|
|
181
168
|
// golden 锚点:sessionId 来自 session.sessionId(projection.sessionId 恒 "unknown" 勿用)
|
|
182
169
|
expect(JSON.parse(ZCODE_APPSERVER_GOLDEN.createResponse).session.sessionId).toBe("sess_golden_r3_01");
|
|
@@ -44,7 +44,7 @@ describe("conformance C5:read 降级链(三级都不 throw)", () => {
|
|
|
44
44
|
dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "c5-read-"));
|
|
45
45
|
});
|
|
46
46
|
afterEach(() => {
|
|
47
|
-
fs.rmSync(dataDir, { recursive: true, force: true });
|
|
47
|
+
fs.rmSync(dataDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it("重放等价性:journal 重放 turns 与 live 累积一致(共用 updateFromEvent reducer)", () => {
|
|
@@ -25,10 +25,11 @@ import { describe, expect, it } from "vitest";
|
|
|
25
25
|
import { getSubagentService } from "../../../subagent-service.ts";
|
|
26
26
|
import { ZcodeEngine } from "../../engines/zcode/zcode-engine.ts";
|
|
27
27
|
import { createPiEngine } from "../../engines/pi/registration.ts";
|
|
28
|
+
import type { PiEngineService } from "../../engines/pi/pi-engine.ts";
|
|
28
29
|
import type { RunContext } from "../../port.ts";
|
|
29
30
|
import type { AgentEvent } from "../../../types.ts";
|
|
30
|
-
import type {
|
|
31
|
-
import { getPiInvocation } from "
|
|
31
|
+
import type { AgentCallOpts } from "../../../../orchestration/models/types.ts";
|
|
32
|
+
import { getPiInvocation } from "../../engines/pi/pi-invocation.ts";
|
|
32
33
|
import {
|
|
33
34
|
RELAY_ENV_NODE,
|
|
34
35
|
RELAY_ENV_RECORD_ID,
|
|
@@ -51,8 +52,8 @@ describe.skipIf(!LIVE)("conformance run 层(真实 spawn,手动门)", () =
|
|
|
51
52
|
testCtx.skip("SubagentService 未装配(需在真实会话进程内运行)");
|
|
52
53
|
return;
|
|
53
54
|
}
|
|
54
|
-
const engine = createPiEngine(() => service);
|
|
55
|
-
const task:
|
|
55
|
+
const engine = createPiEngine(() => service as unknown as PiEngineService);
|
|
56
|
+
const task: AgentCallOpts = { prompt: "Reply with the single word: ok", description: "live-c2" };
|
|
56
57
|
const ctx: RunContext = { taskId: "sa-live-pi-c2", poolKey: "shared" };
|
|
57
58
|
const { outcome } = await engine.run(task, ctx);
|
|
58
59
|
expect(outcome.error).toBeUndefined();
|
|
@@ -68,9 +69,9 @@ describe.skipIf(!LIVE)("conformance run 层(真实 spawn,手动门)", () =
|
|
|
68
69
|
}, 60_000);
|
|
69
70
|
|
|
70
71
|
// [R6] 常驻通道的 conformance run 层(RA8「C1-C8 适配后全绿」的 live 面):
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
// engines/zcode/__tests__/zcode-engine.live.test.ts
|
|
72
|
+
// 跑最小任务——C2 outcome + C3 stream 不变量(app-server 设计 §3.4 不变量 1)。
|
|
73
|
+
// 2026-09 起单一 app-server 形态即缺省路径(无模式钉扎 env);更深断言(schema/
|
|
74
|
+
// abort/进程锚定)由 engines/zcode/__tests__/zcode-engine.live.test.ts 承载。
|
|
74
75
|
it("zcode:app-server 常驻通道 run 全链(C2 outcome 无 error + C3 stream 事件不变量)", async (testCtx) => {
|
|
75
76
|
const model = process.env["ZCODE_E2E_MODEL"];
|
|
76
77
|
if (model === undefined || model === "") {
|
|
@@ -79,11 +80,10 @@ describe.skipIf(!LIVE)("conformance run 层(真实 spawn,手动门)", () =
|
|
|
79
80
|
}
|
|
80
81
|
const engine = new ZcodeEngine({
|
|
81
82
|
engineDataDir: () => "/tmp/zcode-conformance-live-appserver",
|
|
82
|
-
processEnv: { ...process.env, XYZ_ZCODE_MODE: "appserver" },
|
|
83
83
|
});
|
|
84
84
|
const events: AgentEvent[] = [];
|
|
85
85
|
const { outcome } = await engine.run(
|
|
86
|
-
{
|
|
86
|
+
{ prompt: "Reply with the single word: ok", description: "live-appserver-c2", model, cwd: "/tmp" },
|
|
87
87
|
{ taskId: "sa-live-zcode-appserver", poolKey: "", onEvent: (e) => events.push(e) },
|
|
88
88
|
);
|
|
89
89
|
expect(outcome.error).toBeUndefined();
|
|
@@ -200,9 +200,9 @@ describe.skipIf(!LIVE)("conformance relay 变体(经代理 spawn 全链,手
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
try {
|
|
203
|
-
const engine = createPiEngine(() => service);
|
|
203
|
+
const engine = createPiEngine(() => service as unknown as PiEngineService);
|
|
204
204
|
const events: AgentEvent[] = [];
|
|
205
|
-
const task:
|
|
205
|
+
const task: AgentCallOpts = { prompt: "Reply with the single word: ok", description: "live-relay-c2" };
|
|
206
206
|
const ctx: RunContext = {
|
|
207
207
|
taskId: "sa-live-pi-relay",
|
|
208
208
|
poolKey: "shared",
|
|
@@ -221,7 +221,7 @@ describe.skipIf(!LIVE)("conformance relay 变体(经代理 spawn 全链,手
|
|
|
221
221
|
else process.env[key] = savedEnv[key];
|
|
222
222
|
}
|
|
223
223
|
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
224
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
224
|
+
fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
225
225
|
}
|
|
226
226
|
});
|
|
227
227
|
});
|
|
@@ -15,7 +15,7 @@ import { describe, expect, it } from "vitest";
|
|
|
15
15
|
|
|
16
16
|
import type { AgentEvent } from "../../../types.ts";
|
|
17
17
|
import { JournalWriter, replayJournal } from "../../common/event-journal.ts";
|
|
18
|
-
import { parseSpawnLine } from "
|
|
18
|
+
import { parseSpawnLine } from "../../engines/pi/spawn-event-adapter.ts";
|
|
19
19
|
import { assertAgentEventInvariants } from "./agent-event-invariants.ts";
|
|
20
20
|
|
|
21
21
|
interface PiGoldenFile {
|
|
@@ -45,7 +45,7 @@ describe("pi golden 回放(conformance C3/C5-journal,免 LLM)", () => {
|
|
|
45
45
|
// 深比较(含 undefined 键缺省语义——JSON 序列化后 undefined 字段自然消失,两侧同构)
|
|
46
46
|
expect(replayed).toEqual(golden.events);
|
|
47
47
|
} finally {
|
|
48
|
-
rmSync(dir, { recursive: true, force: true });
|
|
48
|
+
rmSync(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// golden-replay.zcode.test.ts —— zcode 引擎 golden 回放层(conformance 免 LLM 默认
|
|
2
|
-
//
|
|
3
|
-
// zcode-golden-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// golden-replay.zcode.test.ts —— zcode 引擎 golden 回放层(conformance 免 LLM 默认
|
|
2
|
+
// CI 层)。语料 = app-server NDJSON 帧序列(附录 A.2 任务生命周期帧序;采集 SSOT
|
|
3
|
+
// = engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json)——双副本 diff
|
|
4
|
+
// 校验(fixture 与 golden-sample.ts 内嵌副本一致,防漂移:更新样本必须同步两处,
|
|
5
|
+
// 探针的干跑校验消费内嵌副本,两处不一致 = 探针在测旧契约)+ 帧形态不变量断言
|
|
6
|
+
// (A8「golden 帧序列语料 diff 通过」的本仓段)。
|
|
6
7
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// 回放层,帧形态不变量在此断言;A8「golden 帧序列语料 diff 通过」的本仓段)。
|
|
8
|
+
// 2026-09 重构(共享宿主 HOME):CLI spawn 链删除后 spawn stdout 语料(单 JSON
|
|
9
|
+
// 样本及其 fixture)随 spawn 回归一并删除,本层仅保留 app-server 帧序列语料
|
|
10
|
+
// (常驻通道唯一生产形态)。
|
|
11
11
|
|
|
12
12
|
import { readFileSync } from "node:fs";
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
@@ -15,86 +15,21 @@ import { fileURLToPath } from "node:url";
|
|
|
15
15
|
|
|
16
16
|
import { describe, expect, it } from "vitest";
|
|
17
17
|
|
|
18
|
-
import { ZCODE_APPSERVER_GOLDEN
|
|
19
|
-
import {
|
|
20
|
-
mapZcodeOutcomeUsage,
|
|
21
|
-
parseZcodeTerminal,
|
|
22
|
-
synthesizeCoarseEvents,
|
|
23
|
-
} from "../../engines/zcode/parser.ts";
|
|
24
|
-
import { assertAgentEventInvariants } from "./agent-event-invariants.ts";
|
|
18
|
+
import { ZCODE_APPSERVER_GOLDEN } from "../../engines/zcode/golden-sample.ts";
|
|
25
19
|
|
|
26
20
|
// conformance 目录(engine/__tests__/conformance)→ engine 根的相对定位
|
|
27
|
-
const
|
|
21
|
+
const appserverFixturePath = join(
|
|
28
22
|
dirname(fileURLToPath(import.meta.url)),
|
|
29
23
|
"..", "..", // conformance → __tests__ → engine
|
|
30
|
-
"engines", "zcode", "__tests__", "__fixtures__", "zcode-golden-
|
|
24
|
+
"engines", "zcode", "__tests__", "__fixtures__", "zcode-golden-appserver.json",
|
|
31
25
|
);
|
|
32
26
|
|
|
33
|
-
interface ZcodeGoldenFile {
|
|
34
|
-
_meta: { engineVersion: string; exitCode: number };
|
|
35
|
-
stdoutRaw: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const fixture = JSON.parse(readFileSync(fixturePath, "utf8")) as ZcodeGoldenFile;
|
|
39
|
-
|
|
40
|
-
// [R6] app-server 帧序列语料 fixture(采集 SSOT——双副本 diff 的另一副本)
|
|
41
|
-
const appserverFixturePath = join(dirname(fixturePath), "zcode-golden-appserver.json");
|
|
42
27
|
interface AppServerGoldenFile {
|
|
43
28
|
_meta: Record<string, unknown>;
|
|
44
29
|
frames: { createResponse: string; pushStream: string[]; terminal: string[]; readResponse: string };
|
|
45
30
|
}
|
|
46
31
|
const appserverFixture = JSON.parse(readFileSync(appserverFixturePath, "utf8")) as AppServerGoldenFile;
|
|
47
32
|
|
|
48
|
-
describe("zcode golden 回放(conformance C3,免 LLM/免二进制)", () => {
|
|
49
|
-
it("双副本 diff:golden-sample.ts 内嵌副本 === fixture stdoutRaw(防漂移,A12)", () => {
|
|
50
|
-
expect(ZCODE_GOLDEN_STDOUT).toBe(fixture.stdoutRaw);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("parser 对实录样本回归:sessionId/response/usage 形状完整(探针干跑同源断言)", () => {
|
|
54
|
-
const terminal = parseZcodeTerminal(fixture.stdoutRaw);
|
|
55
|
-
expect(terminal.ok).toBe(true);
|
|
56
|
-
if (!terminal.ok) return;
|
|
57
|
-
expect(terminal.payload.sessionId).toMatch(/^sess_/);
|
|
58
|
-
expect(terminal.payload.response).toBe("ok");
|
|
59
|
-
expect(terminal.payload.usage).toEqual({ input: 12599, output: 17, cacheRead: 512, cacheWrite: 0 });
|
|
60
|
-
// 终态层 usage(orchestration 版):cost 显式 0(无来源不给残缺)、contextTokens 取 projection
|
|
61
|
-
expect(terminal.payload.outcomeUsage).toEqual({
|
|
62
|
-
input: 12599,
|
|
63
|
-
output: 17,
|
|
64
|
-
cacheRead: 512,
|
|
65
|
-
cacheWrite: 0,
|
|
66
|
-
cost: 0,
|
|
67
|
-
contextTokens: 12616,
|
|
68
|
-
turns: 1,
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("coarse 事件合成满足产出不变量(turn_end 最后、其前必有 message_end、usage 完整)", () => {
|
|
73
|
-
const terminal = parseZcodeTerminal(fixture.stdoutRaw);
|
|
74
|
-
if (!terminal.ok) throw new Error("golden 样本解析失败(上一用例应已转红)");
|
|
75
|
-
const events = synthesizeCoarseEvents(terminal.payload.response, terminal.payload.usage);
|
|
76
|
-
assertAgentEventInvariants(events, { granularity: "coarse" });
|
|
77
|
-
expect(events.map((e) => e.type)).toEqual(["message_end", "turn_end"]);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("usage 无来源样本:mapZcodeOutcomeUsage 显式缺省(不给残缺对象,不变量 2 的输入面)", () => {
|
|
81
|
-
expect(mapZcodeOutcomeUsage(undefined, undefined)).toBeUndefined();
|
|
82
|
-
expect(mapZcodeOutcomeUsage({ inputTokens: 1 }, undefined)).toEqual({
|
|
83
|
-
input: 1,
|
|
84
|
-
output: 0,
|
|
85
|
-
cacheRead: 0,
|
|
86
|
-
cacheWrite: 0,
|
|
87
|
-
cost: 0,
|
|
88
|
-
contextTokens: 0,
|
|
89
|
-
turns: 1,
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// ============================================================
|
|
95
|
-
// [R6] app-server 帧序列语料回放(常驻通道主力语料,conformance 层接管双副本 diff)
|
|
96
|
-
// ============================================================
|
|
97
|
-
|
|
98
33
|
describe("zcode app-server golden 回放(conformance C3 帧形态,免 LLM/免二进制)", () => {
|
|
99
34
|
it("双副本 diff:golden-sample.ts 内嵌副本 === fixture frames(防漂移,A8 本仓段)", () => {
|
|
100
35
|
expect(ZCODE_APPSERVER_GOLDEN.createResponse).toBe(appserverFixture.frames.createResponse);
|
|
@@ -141,7 +76,7 @@ describe("zcode app-server golden 回放(conformance C3 帧形态,免 LLM/
|
|
|
141
76
|
expect(readText).toBe(deltaJoined); // text_delta 拼接 == 收尾帧 == read 全文
|
|
142
77
|
});
|
|
143
78
|
|
|
144
|
-
it("终态权威帧:turn.terminal 存在且先于收尾帧;usage 与
|
|
79
|
+
it("终态权威帧:turn.terminal 存在且先于收尾帧;usage 与 read step-finish tokens 同源(漂移对照锚点)", () => {
|
|
145
80
|
const terminal = ZCODE_APPSERVER_GOLDEN.terminal.map((l) => JSON.parse(l) as {
|
|
146
81
|
params?: { kind?: string; status?: string; payload?: { usage?: { inputTokens: number; outputTokens: number } } };
|
|
147
82
|
});
|
|
@@ -151,11 +86,15 @@ describe("zcode app-server golden 回放(conformance C3 帧形态,免 LLM/
|
|
|
151
86
|
expect(terminal[terminalFrameIdx]?.params?.status).toBe("success");
|
|
152
87
|
expect(terminalFrameIdx).toBeLessThan(closingFrameIdx);
|
|
153
88
|
|
|
154
|
-
|
|
155
|
-
|
|
89
|
+
// usage 跨源对照锚点:收尾帧 usage == read 应答 step-finish tokens(同一轮真实
|
|
90
|
+
// 计费面,两源必须一致;旧 spawn golden 对照随语料删除)
|
|
91
|
+
const read = JSON.parse(ZCODE_APPSERVER_GOLDEN.readResponse) as {
|
|
92
|
+
messages: Array<{ info: { role: string }; parts: Array<{ type: string; tokens?: { input: number; output: number } }> }>;
|
|
93
|
+
};
|
|
94
|
+
const stepFinish = (read.messages.at(-1)?.parts ?? []).find((p) => p.type === "step-finish");
|
|
156
95
|
expect(terminal[closingFrameIdx]?.params?.payload?.usage).toEqual({
|
|
157
|
-
inputTokens:
|
|
158
|
-
outputTokens:
|
|
96
|
+
inputTokens: stepFinish?.tokens?.input,
|
|
97
|
+
outputTokens: stepFinish?.tokens?.output,
|
|
159
98
|
});
|
|
160
99
|
});
|
|
161
100
|
});
|
|
@@ -38,7 +38,7 @@ export interface AppserverHarness {
|
|
|
38
38
|
dispose(): Promise<void>;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/** 组装连到 fake-appserver
|
|
41
|
+
/** 组装连到 fake-appserver 的常驻引擎(单一 app-server 形态——2026-09 起无模式分派)。 */
|
|
42
42
|
export function makeAppserverHarness(opts: AppserverHarnessOptions = {}): AppserverHarness {
|
|
43
43
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "zcode-conformance-appserver-"));
|
|
44
44
|
const dataDir = path.join(tmpRoot, "data");
|
|
@@ -78,9 +78,6 @@ export function makeAppserverHarness(opts: AppserverHarnessOptions = {}): Appser
|
|
|
78
78
|
sources: { v2ConfigPath: v2Path },
|
|
79
79
|
processEnv: {
|
|
80
80
|
PATH: process.env.PATH ?? "",
|
|
81
|
-
// 定向 appserver(R5 D2①):不探不降——conformance 测常驻路径本体,缺省路径的
|
|
82
|
-
// 探针门控/降级链归 zcode-engine-degrade.test.ts
|
|
83
|
-
XYZ_ZCODE_MODE: "appserver",
|
|
84
81
|
FAKE_STATE_FILE: stateFile,
|
|
85
82
|
FAKE_SESSION_SCENARIO: scenarioFile,
|
|
86
83
|
},
|
|
@@ -92,7 +89,7 @@ export function makeAppserverHarness(opts: AppserverHarnessOptions = {}): Appser
|
|
|
92
89
|
dataDir,
|
|
93
90
|
dispose: () =>
|
|
94
91
|
engine.dispose().finally(() => {
|
|
95
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
92
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
96
93
|
}),
|
|
97
94
|
};
|
|
98
95
|
}
|
|
@@ -114,8 +111,8 @@ export function readFakeState(file: string): Array<Record<string, unknown>> {
|
|
|
114
111
|
/** fake 收到的客户端帧方法名序列(abort 链「stop 先于杀链」断言面)。 */
|
|
115
112
|
export function sentMethodNames(stateFile: string): string[] {
|
|
116
113
|
return readFakeState(stateFile)
|
|
117
|
-
.map((e) => e["frame"])
|
|
118
|
-
.filter((f): f is Record<string, unknown> => typeof f === "object" && f !== null && typeof f["method"] === "string")
|
|
114
|
+
.map((e) => (e as Record<string, unknown>)["frame"])
|
|
115
|
+
.filter((f): f is Record<string, unknown> => typeof f === "object" && f !== null && typeof (f as Record<string, unknown>)["method"] === "string")
|
|
119
116
|
.map((f) => f["method"] as string);
|
|
120
117
|
}
|
|
121
118
|
|
|
@@ -15,8 +15,20 @@ import { clearEngines, registerEngine } from "../registry.ts";
|
|
|
15
15
|
function stubEngine(id: string): EnginePort {
|
|
16
16
|
return {
|
|
17
17
|
id,
|
|
18
|
-
capabilities: () => ({
|
|
19
|
-
|
|
18
|
+
capabilities: () => ({
|
|
19
|
+
schemaEnforcement: "emulated",
|
|
20
|
+
steer: "unsupported",
|
|
21
|
+
conversation: "unsupported",
|
|
22
|
+
personaInjection: "prompt",
|
|
23
|
+
eventGranularity: "coarse",
|
|
24
|
+
sandbox: "none",
|
|
25
|
+
sessionRead: "outcome-only",
|
|
26
|
+
resume: "unsupported",
|
|
27
|
+
interrupt: "kill-only",
|
|
28
|
+
permissionMode: "ignored",
|
|
29
|
+
maxTurns: false,
|
|
30
|
+
}),
|
|
31
|
+
probe: async () => ({ ok: true, engineVersion: "test", checks: [] }),
|
|
20
32
|
run: async () => {
|
|
21
33
|
throw new Error("unused");
|
|
22
34
|
},
|
|
@@ -38,7 +50,7 @@ beforeEach(() => {
|
|
|
38
50
|
|
|
39
51
|
afterEach(() => {
|
|
40
52
|
clearEngines();
|
|
41
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
53
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
42
54
|
});
|
|
43
55
|
|
|
44
56
|
describe("syncEnginesFile", () => {
|
|
@@ -16,8 +16,20 @@ import { buildEngineModelsPromptAppend, buildSubagentEngineSection } from "../mo
|
|
|
16
16
|
function fakeEngine(id: string, models: Array<{ id: string; name?: string }> | null): EnginePort {
|
|
17
17
|
return {
|
|
18
18
|
id,
|
|
19
|
-
capabilities: () => ({
|
|
20
|
-
|
|
19
|
+
capabilities: () => ({
|
|
20
|
+
schemaEnforcement: "emulated",
|
|
21
|
+
steer: "unsupported",
|
|
22
|
+
conversation: "unsupported",
|
|
23
|
+
personaInjection: "prompt",
|
|
24
|
+
eventGranularity: "coarse",
|
|
25
|
+
sandbox: "none",
|
|
26
|
+
sessionRead: "outcome-only",
|
|
27
|
+
resume: "unsupported",
|
|
28
|
+
interrupt: "kill-only",
|
|
29
|
+
permissionMode: "ignored",
|
|
30
|
+
maxTurns: false,
|
|
31
|
+
}),
|
|
32
|
+
probe: async () => ({ ok: true, engineVersion: "test", checks: [] }),
|
|
21
33
|
run: async () => {
|
|
22
34
|
throw new Error("not used in this test");
|
|
23
35
|
},
|
|
@@ -38,7 +50,7 @@ beforeEach(() => {
|
|
|
38
50
|
|
|
39
51
|
afterEach(() => {
|
|
40
52
|
clearEngines();
|
|
41
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
53
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
42
54
|
});
|
|
43
55
|
|
|
44
56
|
describe("buildEngineModelsPromptAppend(defaultEngine 开关语义)", () => {
|
|
@@ -17,7 +17,8 @@ import {
|
|
|
17
17
|
listEngines,
|
|
18
18
|
registerEngine,
|
|
19
19
|
} from "../registry.ts";
|
|
20
|
-
import type {
|
|
20
|
+
import type { SessionView } from "../types.ts";
|
|
21
|
+
import type { AgentCallOpts } from "../../../orchestration/models/types.ts";
|
|
21
22
|
|
|
22
23
|
/** 最小可运行假引擎(完整实现 EnginePort 五面——不 cast,防接口漂移失检)。 */
|
|
23
24
|
function makeFakeEngine(id: string): EnginePort {
|
|
@@ -34,10 +35,11 @@ function makeFakeEngine(id: string): EnginePort {
|
|
|
34
35
|
resume: "unsupported",
|
|
35
36
|
interrupt: "kill-only",
|
|
36
37
|
permissionMode: "fixed",
|
|
38
|
+
maxTurns: false,
|
|
37
39
|
}),
|
|
38
40
|
probe: () =>
|
|
39
41
|
Promise.resolve({ ok: true, engineVersion: "0.0.0-test", checks: [{ name: "stub", ok: true }] }),
|
|
40
|
-
run: (_task:
|
|
42
|
+
run: (_task: AgentCallOpts, _ctx: RunContext) =>
|
|
41
43
|
Promise.reject(new Error("fake engine: run not implemented")),
|
|
42
44
|
interact: () => Promise.resolve({ ok: false, code: "engine_capability_unsupported", message: "stub" }),
|
|
43
45
|
read: (_handle: Parameters<EnginePort["read"]>[0]): Promise<SessionView> =>
|