@deksden-com/dd-flow-cli 0.9.0-beta.14 → 0.9.0-beta.140
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/CHANGELOG.md +733 -0
- package/README.md +143 -1
- package/dist/build-info.json +8 -8
- package/dist/cli/argument-values.js +38 -0
- package/dist/cli/command-inputs.js +376 -0
- package/dist/cli/command-metadata.js +197 -0
- package/dist/cli/command-option-descriptions.js +191 -0
- package/dist/cli/completion-cli.js +70 -0
- package/dist/cli/completion.js +57 -0
- package/dist/cli/error-output.js +52 -0
- package/dist/cli/executor-onboarding.js +76 -0
- package/dist/cli/flows.js +29 -0
- package/dist/cli/harnesses.js +84 -0
- package/dist/cli/help.js +328 -18
- package/dist/cli/hook-ingress.js +78 -0
- package/dist/cli/input-preparation.js +165 -0
- package/dist/cli/memory-flow-admission.js +44 -0
- package/dist/cli/memory-init-invocation.js +78 -0
- package/dist/cli/memory-init.js +240 -0
- package/dist/cli/memory-storage-admission.js +53 -0
- package/dist/cli/models.js +39 -0
- package/dist/cli/native-hook-ingress.js +80 -0
- package/dist/cli/operator-profiles.js +61 -0
- package/dist/cli/output-options.js +35 -0
- package/dist/cli/response-file.js +71 -0
- package/dist/cli/run-cli.js +1689 -545
- package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
- package/dist/cli/runtime-maintenance-ingress.js +52 -0
- package/dist/cli/runtime-process.js +153 -0
- package/dist/cli/setup.js +149 -0
- package/dist/cli.js +71 -2
- package/dist/domain/stage-catalog.js +1 -1
- package/dist/domain/stage-handler-identities.js +20 -0
- package/dist/harness-runtime/DD-ZCODE.md +112 -0
- package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
- package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
- package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
- package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
- package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
- package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
- package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
- package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
- package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
- package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
- package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
- package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
- package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
- package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +371 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +724 -0
- package/dist/harness-runtime/lib/dd-agy.mjs +70 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +196 -0
- package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex.mjs +817 -0
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +129 -0
- package/dist/harness-runtime/lib/dd-droid.mjs +584 -0
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +498 -0
- package/dist/harness-runtime/lib/dd-grok.mjs +177 -0
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +507 -0
- package/dist/harness-runtime/lib/dd-opencode.mjs +354 -0
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +750 -0
- package/dist/harness-runtime/lib/dd-zcode.mjs +1145 -0
- package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
- package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
- package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
- package/dist/harness-runtime/lib/driver-recovery.mjs +139 -0
- package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
- package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
- package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
- package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
- package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
- package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
- package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
- package/dist/harness-runtime/lib/managed-daemon.d.mts +13 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +654 -0
- package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
- package/dist/harness-runtime/lib/model-observations.mjs +101 -0
- package/dist/harness-runtime/lib/native-children.d.mts +16 -0
- package/dist/harness-runtime/lib/native-children.mjs +113 -0
- package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
- package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
- package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
- package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
- package/dist/harness-runtime/lib/native-streams.mjs +45 -0
- package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
- package/dist/harness-runtime/lib/observation-clock.mjs +92 -0
- package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
- package/dist/harness-runtime/lib/operation-context.mjs +5 -0
- package/dist/harness-runtime/lib/operation-errors.d.mts +14 -0
- package/dist/harness-runtime/lib/operation-errors.mjs +116 -0
- package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
- package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
- package/dist/harness-runtime/lib/process-json.d.mts +5 -0
- package/dist/harness-runtime/lib/process-json.mjs +201 -0
- package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
- package/dist/harness-runtime/lib/provider-overload-policy.d.mts +13 -0
- package/dist/harness-runtime/lib/provider-overload-policy.mjs +138 -0
- package/dist/harness-runtime/lib/runner-events.mjs +200 -0
- package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
- package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
- package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
- package/dist/harness-runtime/lib/setup-progress.mjs +51 -0
- package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
- package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
- package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
- package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
- package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
- package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
- package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
- package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
- package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
- package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
- package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
- package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
- package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
- package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
- package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
- package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
- package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
- package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
- package/dist/protocol/local-files.js +18 -9
- package/dist/runtime/context.js +8 -4
- package/dist/schemas/agent-profile.schema.json +1 -1
- package/dist/schemas/code-review-result.schema.json +1 -1
- package/dist/schemas/code-verification.schema.json +7 -5
- package/dist/schemas/code-work-batch.schema.json +2 -2
- package/dist/schemas/discovery-result.schema.json +184 -0
- package/dist/schemas/execution-bundle.schema.json +205 -0
- package/dist/schemas/execution-settings.schema.json +162 -0
- package/dist/schemas/flow-descriptor.schema.json +54 -0
- package/dist/schemas/flow-run.schema.json +28 -0
- package/dist/schemas/harness-catalog.schema.json +80 -0
- package/dist/schemas/mb-init-compose-result.schema.json +457 -0
- package/dist/schemas/mb-init-discover-result.schema.json +500 -0
- package/dist/schemas/mb-init-finish-result.schema.json +422 -0
- package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
- package/dist/schemas/mb-init-review-result.schema.json +396 -0
- package/dist/schemas/mb-init-verify-result.schema.json +391 -0
- package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
- package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
- package/dist/schemas/memory-composition-work-result.schema.json +38 -0
- package/dist/schemas/memory-repair-work-result.schema.json +49 -0
- package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
- package/dist/schemas/memory-review-work-result.schema.json +43 -0
- package/dist/schemas/model-catalog.schema.json +153 -0
- package/dist/schemas/plan-review-decision.schema.json +3 -3
- package/dist/schemas/plan-review-result.schema.json +2 -2
- package/dist/schemas/profile-settings.schema.json +122 -0
- package/dist/schemas/release-manifest.schema.json +291 -0
- package/dist/schemas/run-control-receipt.schema.json +118 -0
- package/dist/schemas/run-control-request.schema.json +36 -0
- package/dist/schemas/run-engine-binding.schema.json +1 -1
- package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
- package/dist/services/branch-context.js +3 -3
- package/dist/services/canon.js +11 -8
- package/dist/services/check-runner-evidence.js +168 -0
- package/dist/services/cleanup.js +133 -40
- package/dist/services/cli-operation-classifier.js +25 -62
- package/dist/services/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +1156 -107
- package/dist/services/codex-hook-delivery.js +32 -0
- package/dist/services/command-context.js +80 -0
- package/dist/services/compatibility-preflight.js +13 -3
- package/dist/services/config.js +11 -8
- package/dist/services/continuation-outcome.js +20 -0
- package/dist/services/controller-child-capacity.js +13 -0
- package/dist/services/controller-child-observer.js +115 -0
- package/dist/services/controller-execution.js +88 -0
- package/dist/services/controller-fanout.js +202 -0
- package/dist/services/dashboard.js +143 -58
- package/dist/services/descriptor-coordinator-session.js +35 -0
- package/dist/services/descriptor-root-work.js +53 -0
- package/dist/services/descriptor-run-settlement.js +105 -0
- package/dist/services/descriptor-run-start.js +449 -0
- package/dist/services/descriptor-stage-coordinator.js +197 -0
- package/dist/services/descriptor-stage-settlement.js +222 -0
- package/dist/services/descriptor-stage-start.js +139 -0
- package/dist/services/discovery/agy-discovery.js +2 -0
- package/dist/services/discovery/codex-discovery.js +2 -0
- package/dist/services/discovery/droid-discovery.js +2 -0
- package/dist/services/discovery/grok-discovery.js +2 -0
- package/dist/services/discovery/opencode-discovery.js +2 -0
- package/dist/services/discovery/static.js +31 -0
- package/dist/services/discovery/zcode-discovery.js +2 -0
- package/dist/services/engines.js +294 -153
- package/dist/services/eval-snapshots.js +1215 -116
- package/dist/services/execution-bundles.js +263 -0
- package/dist/services/execution-policy.js +185 -0
- package/dist/services/executor-onboarding.js +56 -0
- package/dist/services/external-work-launch.js +308 -0
- package/dist/services/flow-catalog.js +21 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +250 -0
- package/dist/services/generic-execution.js +164 -0
- package/dist/services/harness-adapter.js +355 -36
- package/dist/services/harness-config.js +2 -0
- package/dist/services/harness-discovery.js +29 -0
- package/dist/services/harness-doctor.js +75 -0
- package/dist/services/harness-probe-effects.js +51 -0
- package/dist/services/harness-version-probe.js +100 -0
- package/dist/services/hooks.js +771 -325
- package/dist/services/hybrid-contracts.js +483 -0
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +95 -0
- package/dist/services/installed-flow-source.js +183 -0
- package/dist/services/lanes.js +78 -65
- package/dist/services/lifecycle-command.js +1 -288
- package/dist/services/lifecycle-contract.js +1 -0
- package/dist/services/lifecycle-invocations.js +2007 -0
- package/dist/services/managed-daemon-binding.js +38 -0
- package/dist/services/managed-lease-monitor.js +133 -0
- package/dist/services/managed-processes.js +475 -55
- package/dist/services/memory-accepted-composition.js +77 -0
- package/dist/services/memory-baseline-preservation.js +65 -0
- package/dist/services/memory-completed-correction-wave.js +320 -0
- package/dist/services/memory-compose-handler.js +258 -0
- package/dist/services/memory-composition-acceptance.js +199 -0
- package/dist/services/memory-composition-graph.js +134 -0
- package/dist/services/memory-composition-registration.js +146 -0
- package/dist/services/memory-composition-work-custody.js +151 -0
- package/dist/services/memory-composition-work-results.js +96 -0
- package/dist/services/memory-corrected-review-acceptance.js +129 -0
- package/dist/services/memory-corrected-review-batch.js +30 -0
- package/dist/services/memory-corrected-review-findings.js +106 -0
- package/dist/services/memory-corrected-review-inputs.js +210 -0
- package/dist/services/memory-corrected-review-projection.js +78 -0
- package/dist/services/memory-corrected-review-receipt.js +170 -0
- package/dist/services/memory-corrected-review-registration.js +191 -0
- package/dist/services/memory-correction-check-receipt.js +219 -0
- package/dist/services/memory-correction-input-owner.js +6 -0
- package/dist/services/memory-discover-handler.js +104 -0
- package/dist/services/memory-finish-evidence.js +435 -0
- package/dist/services/memory-finish-handler.js +215 -0
- package/dist/services/memory-finish-integration.js +280 -0
- package/dist/services/memory-finish-readiness.js +122 -0
- package/dist/services/memory-git-integration.js +151 -0
- package/dist/services/memory-historical-corrected-review.js +206 -0
- package/dist/services/memory-historical-original-review.js +130 -0
- package/dist/services/memory-historical-repair-registration.js +99 -0
- package/dist/services/memory-historical-second-review.js +128 -0
- package/dist/services/memory-init-bootstrap-readiness.js +210 -0
- package/dist/services/memory-init-contexts.js +89 -0
- package/dist/services/memory-init-controller-start.js +84 -0
- package/dist/services/memory-init-engine-release.js +223 -0
- package/dist/services/memory-init-git-policy.js +136 -0
- package/dist/services/memory-init-lint-capability.js +185 -0
- package/dist/services/memory-init-native-capacity.js +296 -0
- package/dist/services/memory-init-preflight.js +330 -0
- package/dist/services/memory-init-project-bootstrap.js +599 -0
- package/dist/services/memory-init-request-candidate.js +157 -0
- package/dist/services/memory-init-request-input.js +66 -0
- package/dist/services/memory-init-resource-storage.js +125 -0
- package/dist/services/memory-init-run-allocation.js +81 -0
- package/dist/services/memory-init-run-bundle.js +98 -0
- package/dist/services/memory-init-start.js +181 -0
- package/dist/services/memory-init-startup-custody.js +80 -0
- package/dist/services/memory-init-startup-input.js +240 -0
- package/dist/services/memory-init-storage.js +81 -0
- package/dist/services/memory-init-stores.js +359 -0
- package/dist/services/memory-init-worktrunk-capability.js +178 -0
- package/dist/services/memory-layer-publication.js +611 -0
- package/dist/services/memory-layer.js +156 -0
- package/dist/services/memory-lint-config.js +85 -0
- package/dist/services/memory-native-review-copy.js +165 -0
- package/dist/services/memory-normal-flow-entry.js +75 -0
- package/dist/services/memory-ordinary-defaults.js +112 -0
- package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
- package/dist/services/memory-preflight-handler.js +259 -0
- package/dist/services/memory-repair-current-view.js +299 -0
- package/dist/services/memory-repair-document-delta.js +451 -0
- package/dist/services/memory-repair-history.js +491 -0
- package/dist/services/memory-repair-physical-binding.js +312 -0
- package/dist/services/memory-repair-publication-files.js +152 -0
- package/dist/services/memory-repair-publication-intent.js +27 -0
- package/dist/services/memory-repair-publication-plan.js +160 -0
- package/dist/services/memory-repair-publication-source.js +225 -0
- package/dist/services/memory-repair-publication.js +794 -0
- package/dist/services/memory-repair-registration.js +239 -0
- package/dist/services/memory-repair-work-baseline.js +413 -0
- package/dist/services/memory-repair-work-completion.js +97 -0
- package/dist/services/memory-repair-work-custody.js +73 -0
- package/dist/services/memory-repair-work-results.js +89 -0
- package/dist/services/memory-repair-workspace.js +252 -0
- package/dist/services/memory-repair-writer-copy.js +735 -0
- package/dist/services/memory-result-binding.js +173 -0
- package/dist/services/memory-retained-review-authority.js +129 -0
- package/dist/services/memory-retained-review-results.js +70 -0
- package/dist/services/memory-retained-second-baseline.js +102 -0
- package/dist/services/memory-retained-second-repairs.js +156 -0
- package/dist/services/memory-review-acceptance.js +214 -0
- package/dist/services/memory-review-correction-plan.js +171 -0
- package/dist/services/memory-review-handler.js +585 -0
- package/dist/services/memory-review-inputs.js +200 -0
- package/dist/services/memory-review-receipt.js +180 -0
- package/dist/services/memory-review-registration.js +108 -0
- package/dist/services/memory-review-work-custody.js +124 -0
- package/dist/services/memory-review-work-input.js +72 -0
- package/dist/services/memory-review-work-results.js +73 -0
- package/dist/services/memory-second-corrected-review-inputs.js +165 -0
- package/dist/services/memory-second-correction-plan.js +76 -0
- package/dist/services/memory-second-repair-baseline.js +91 -0
- package/dist/services/memory-second-repair-launch.js +614 -0
- package/dist/services/memory-second-repair-registration.js +88 -0
- package/dist/services/memory-second-repair-source.js +187 -0
- package/dist/services/memory-second-review-acceptance.js +115 -0
- package/dist/services/memory-source-observations.js +117 -0
- package/dist/services/memory-stage-dispatch.js +28 -0
- package/dist/services/memory-stage-results.js +199 -0
- package/dist/services/memory-verification-acceptance.js +135 -0
- package/dist/services/memory-verification-checks.js +252 -0
- package/dist/services/memory-verification-receipt.js +159 -0
- package/dist/services/memory-verify-handler.js +135 -0
- package/dist/services/memory-work-result-preparation.js +63 -0
- package/dist/services/merge-queue.js +228 -149
- package/dist/services/merge-server.js +161 -35
- package/dist/services/migrations.js +37 -16
- package/dist/services/model-catalog.js +109 -0
- package/dist/services/model-discovery.js +46 -0
- package/dist/services/native-daemon-history.js +49 -0
- package/dist/services/native-session-control.js +39 -0
- package/dist/services/operator-profiles.js +236 -0
- package/dist/services/plan-runtime.js +26 -11
- package/dist/services/plans.js +28 -25
- package/dist/services/projects.js +37 -17
- package/dist/services/prompts.js +28 -17
- package/dist/services/protocols.js +163 -87
- package/dist/services/provider-capacity.js +385 -0
- package/dist/services/recovery-observation-budget.js +121 -0
- package/dist/services/recovery-snapshot-database.js +560 -0
- package/dist/services/release-archive-producer.js +52 -0
- package/dist/services/release-archive.js +143 -0
- package/dist/services/release-cache.js +142 -0
- package/dist/services/release-compatibility.js +18 -0
- package/dist/services/release-download.js +67 -0
- package/dist/services/release-envelope.js +104 -0
- package/dist/services/release-manifest.js +45 -0
- package/dist/services/release-payload.js +114 -0
- package/dist/services/release-producer.js +63 -0
- package/dist/services/release-provenance.js +160 -0
- package/dist/services/release-registry.js +66 -0
- package/dist/services/release-source.js +194 -0
- package/dist/services/repair-intents.js +42 -0
- package/dist/services/review-copy.js +165 -0
- package/dist/services/review-deferral.js +23 -0
- package/dist/services/run-control-receipt.js +56 -0
- package/dist/services/run-control-worker.js +411 -0
- package/dist/services/run-control.js +1056 -0
- package/dist/services/run-controller-adapter.js +399 -0
- package/dist/services/run-controller-capture.js +186 -0
- package/dist/services/run-controller-process.js +208 -0
- package/dist/services/run-controller-recovery.js +289 -0
- package/dist/services/run-controller-state.js +97 -0
- package/dist/services/run-controller.js +1205 -0
- package/dist/services/run-engine-bindings.js +1 -1
- package/dist/services/run-fork.js +147 -0
- package/dist/services/run-health.js +149 -0
- package/dist/services/run-observations.js +152 -0
- package/dist/services/run-projection.js +22 -64
- package/dist/services/run-recovery-guard.js +77 -0
- package/dist/services/run-recovery-runtime.js +112 -0
- package/dist/services/run-recovery.js +489 -0
- package/dist/services/run-start-custody.js +177 -0
- package/dist/services/runs.js +1019 -247
- package/dist/services/runtime-budget.js +430 -0
- package/dist/services/runtime-command.js +43 -0
- package/dist/services/runtime-scope-capture.js +52 -0
- package/dist/services/runtime-scope-control.js +468 -0
- package/dist/services/runtime-scope-resume.js +599 -0
- package/dist/services/runtime-scope-stop.js +210 -0
- package/dist/services/runtime-scope-worker.js +287 -0
- package/dist/services/runtime-service.js +96 -0
- package/dist/services/schema-validation.js +10 -8
- package/dist/services/scope-writer-cleanup.js +27 -0
- package/dist/services/sessions.js +35 -69
- package/dist/services/setup.js +377 -0
- package/dist/services/stage-blocker.js +17 -7
- package/dist/services/stage-context.js +193 -19
- package/dist/services/stage-handlers.js +74 -0
- package/dist/services/stage-lifecycle.js +100 -108
- package/dist/services/stage-pause.js +89 -75
- package/dist/services/stage-report-renderer.js +234 -6
- package/dist/services/stage-work-graph.js +52 -0
- package/dist/services/tooling.js +32 -23
- package/dist/services/usage.js +49 -101
- package/dist/services/verification-matrix.js +374 -0
- package/dist/services/vnext-code-review.js +223 -88
- package/dist/services/vnext-code.js +327 -226
- package/dist/services/vnext-contracts.js +10 -1
- package/dist/services/vnext-execution-profile.js +80 -5
- package/dist/services/vnext-fanout.js +311 -19
- package/dist/services/vnext-merge.js +332 -111
- package/dist/services/vnext-plan-review.js +279 -127
- package/dist/services/vnext-plan.js +229 -104
- package/dist/services/vnext-protocolize.js +411 -86
- package/dist/services/vnext-specify.js +119 -81
- package/dist/services/vnext-workspace-policy.js +7 -2
- package/dist/services/work-registry.js +1627 -199
- package/dist/services/workspace-bootstrap.js +52 -15
- package/dist/services/workspace-files.js +85 -0
- package/dist/services/worktrees.js +98 -44
- package/dist/shared/entity-references.js +8 -0
- package/dist/shared/errors.js +17 -0
- package/dist/storage/agent-output.js +26 -0
- package/dist/storage/database.js +891 -39
- package/dist/storage/foreign-key-transaction.js +39 -0
- package/dist/storage/immutable-input.js +45 -0
- package/dist/storage/import-guard.js +102 -0
- package/dist/storage/native-cleanup.js +52 -0
- package/dist/storage/paths.js +17 -4
- package/dist/storage/projection-lock.js +73 -0
- package/dist/storage/work-references.js +23 -0
- package/dist/storage/writer-contract.js +89 -0
- package/dist/storage/writer-migration.js +85 -0
- package/package.json +43 -13
- package/tools/create-canon-release.mjs +33 -0
- package/tools/produce-hybrid-release.mjs +41 -0
- package/tools/repair-paused-run-status.mjs +84 -0
|
@@ -1,59 +1,378 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
6
|
+
import { stopProcessGroup } from "../harness-runtime/lib/managed-daemon.mjs";
|
|
7
|
+
import { recoveryObservationBudget, recoveryRpcTimeout, withRecoveryObservation } from "./recovery-observation-budget.js";
|
|
8
|
+
import { ObservationClock, validateObservationDuration } from "../harness-runtime/lib/observation-clock.mjs";
|
|
9
|
+
import { canonicalNativeOperation, nativeOperationWait } from "../harness-runtime/lib/adapter-timeouts.mjs";
|
|
10
|
+
import { readOperationProgress, readOperationRecord, readOperationWaiting, suspendOperationClock } from "../harness-runtime/lib/operation-progress.mjs";
|
|
11
|
+
import { recoverDaemonReply } from "../harness-runtime/lib/daemon-observation.mjs";
|
|
12
|
+
import { isObservationLoss } from "../harness-runtime/lib/operation-errors.mjs";
|
|
13
|
+
import { readBoundedReleaseFile } from "./release-source.js";
|
|
14
|
+
const maxAdapterOutputBytes = 1_000_000;
|
|
15
|
+
/** Native hooks need a real executable, not a PATH-dependent shell expression. */
|
|
16
|
+
export function prepareHarnessFlowExecutable(context, stateDir, engine) {
|
|
17
|
+
// Native login shells rewrite search paths. The owned SDK must execute with
|
|
18
|
+
// the same original paths as its controller, not merely hash them as equal.
|
|
19
|
+
const searchPaths = ["PATH", "FPATH", "INFOPATH"].map(name => context.env[name] === undefined
|
|
20
|
+
? `delete process.env.${name};\n` : `process.env.${name} = ${JSON.stringify(context.env[name])};\n`).join("");
|
|
21
|
+
if (engine) {
|
|
22
|
+
const executable = path.join(stateDir, "dd-flow");
|
|
23
|
+
const contents = `#!${engine.nodeExecutable}\n${searchPaths}process.env.DD_FLOW_HOME = ${JSON.stringify(context.ddFlowHome)};\nprocess.env.DD_FLOW_ENGINE_MODE = "1";\nprocess.env.DD_FLOW_ENGINE_HOME = ${JSON.stringify(engine.manifest().snapshot_root)};\nconst { spawnSync } = await import("node:child_process");\nconst child = spawnSync(${JSON.stringify(engine.nodeExecutable)}, [${JSON.stringify(engine.entrypoint)}, ...process.argv.slice(2)], { stdio: "inherit", env: process.env });\nif (child.error) throw child.error;\nif (child.signal) process.kill(process.pid, child.signal);\nprocess.exit(child.status ?? 1);\n`;
|
|
24
|
+
try {
|
|
25
|
+
fs.writeFileSync(executable, contents, { flag: "wx", mode: 0o700 });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const conflict = () => new AppError("harness_runtime_binding_conflict", "Launch runtime executable already has different or linked content", 1, { path: executable });
|
|
29
|
+
if (error.code !== "EEXIST")
|
|
30
|
+
throw conflict();
|
|
31
|
+
try {
|
|
32
|
+
const stat = fs.lstatSync(executable);
|
|
33
|
+
if (!stat.isFile() || stat.nlink !== 1 || readBoundedReleaseFile(executable, 64 * 1024).toString("utf8") !== contents)
|
|
34
|
+
throw conflict();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw conflict();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return executable;
|
|
41
|
+
}
|
|
42
|
+
const configured = context.env.DD_FLOW_BIN;
|
|
43
|
+
if (configured !== undefined) {
|
|
44
|
+
if (!path.isAbsolute(configured) || !fs.existsSync(configured))
|
|
45
|
+
throw new AppError("harness_runtime_missing", "DD_FLOW_BIN must identify an existing absolute executable", 2);
|
|
46
|
+
if (path.basename(configured) === "dd-flow")
|
|
47
|
+
return configured;
|
|
48
|
+
}
|
|
49
|
+
const isolated = path.join(context.ddFlowHome, "bin", "dd-flow");
|
|
50
|
+
if (!configured && fs.existsSync(isolated))
|
|
51
|
+
return isolated;
|
|
52
|
+
const entry = fileURLToPath(new URL("../cli.js", import.meta.url));
|
|
53
|
+
if (!configured && !fs.existsSync(entry))
|
|
54
|
+
throw new AppError("harness_runtime_unbuilt", "Build the CLI or supply its pinned DD_FLOW_BIN before launching a harness", 1);
|
|
55
|
+
// The trusted lifecycle parser recognizes this basename, including for a
|
|
56
|
+
// custom pinned executable. Do not broaden that parser to arbitrary scripts.
|
|
57
|
+
const executable = path.join(stateDir, "dd-flow");
|
|
58
|
+
const dispatch = configured
|
|
59
|
+
? `const { spawnSync } = await import("node:child_process");\nconst child = spawnSync(${JSON.stringify(configured)}, process.argv.slice(2), { stdio: "inherit", env: process.env });\nif (child.error) throw child.error;\nif (child.signal) process.kill(process.pid, child.signal);\nprocess.exit(child.status ?? 1);\n`
|
|
60
|
+
: `await import(${JSON.stringify(pathToFileURL(entry).href)});\n`;
|
|
61
|
+
const contents = `#!${process.execPath}\n${searchPaths}process.env.DD_FLOW_HOME = ${JSON.stringify(context.ddFlowHome)};\n${dispatch}`;
|
|
62
|
+
try {
|
|
63
|
+
fs.writeFileSync(executable, contents, { flag: "wx", mode: 0o700 });
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error.code !== "EEXIST" || fs.readFileSync(executable, "utf8") !== contents)
|
|
67
|
+
throw new AppError("harness_runtime_binding_conflict", "Launch runtime executable already has different content", 1, { path: executable });
|
|
68
|
+
}
|
|
69
|
+
return executable;
|
|
70
|
+
}
|
|
4
71
|
export function runHarnessAdapter(input) {
|
|
5
|
-
const
|
|
72
|
+
const index = input.args.indexOf("--state-dir"), stateDir = index >= 0 ? input.args[index + 1] : undefined;
|
|
73
|
+
const operation = canonicalNativeOperation(input.harness ?? "", `${input.args[0]}.${input.args[1]}`);
|
|
74
|
+
const boundOperation = ["session.create", "session.fork", "session.start", "session.resume"].includes(operation);
|
|
75
|
+
const binding = { operation, ...(input.runtimeOwner ? { owner_id: input.runtimeOwner.owner_id } : {}) };
|
|
76
|
+
let retainedOutcome;
|
|
77
|
+
const onOutcome = (value) => {
|
|
78
|
+
const fingerprint = JSON.stringify(value);
|
|
79
|
+
if (fingerprint !== retainedOutcome) {
|
|
80
|
+
input.onNativeOutcome?.(value);
|
|
81
|
+
retainedOutcome = fingerprint;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const dispatched = runAdapterTransport(input, stateDir, binding);
|
|
85
|
+
return dispatched.catch(async (error) => {
|
|
86
|
+
if (!stateDir || !boundOperation || input.signal?.aborted || !(isObservationLoss(error) || isObservationLoss(error?.details?.cause)))
|
|
87
|
+
throw error;
|
|
88
|
+
try {
|
|
89
|
+
return await recoverDaemonReply(stateDir, input.operationId, { timeoutMs: recoveryRpcTimeout(30_000), ...(input.signal ? { signal: input.signal } : {}), ...(error?.observationClock ? { observationClock: error.observationClock } : {}), binding, onOutcome,
|
|
90
|
+
// Reconcile only original bookkeeping. Work/MERGE share this path and
|
|
91
|
+
// must not replay creation merely because its release receipt is pending.
|
|
92
|
+
onPendingSettlement: async (retained) => {
|
|
93
|
+
input.signal?.throwIfAborted();
|
|
94
|
+
await withRecoveryObservation(recoveryObservationBudget(retained), () => runAdapterTransport({ ...input, args: ["daemon", "operation", "settle", "--state-dir", stateDir, "--operation-id", input.operationId, "--json"], operationId: `${input.operationId}:settlement`, timeoutMs: recoveryRpcTimeout(30_000) }, stateDir, {}), true);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (recovery) {
|
|
99
|
+
if (recovery && typeof recovery === "object")
|
|
100
|
+
Object.assign(recovery, { cause: error });
|
|
101
|
+
throw recovery;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function runAdapterTransport(input, stateDir, binding = {}) {
|
|
106
|
+
// `null` is deliberate: a productive Turn has no adapter-wall-clock limit.
|
|
107
|
+
// Preserve it instead of treating it like an omitted short control request.
|
|
108
|
+
if (input.timeoutMs != null)
|
|
109
|
+
validateObservationDuration(input.timeoutMs);
|
|
110
|
+
const operation = canonicalNativeOperation(input.harness ?? "", `${input.args[0]}.${input.args[1]}`);
|
|
111
|
+
const productive = input.harness !== undefined && nativeOperationWait(input.harness, operation) === "native-work";
|
|
112
|
+
const timeoutMs = recoveryRpcTimeout(productive ? null : input.timeoutMs === undefined ? 120_000 : input.timeoutMs);
|
|
113
|
+
if (timeoutMs !== null)
|
|
114
|
+
validateObservationDuration(timeoutMs);
|
|
115
|
+
if (!input.operationId.trim())
|
|
116
|
+
throw new AppError("operation_id_required", "Harness calls require a scoped operation id", 2);
|
|
117
|
+
// The current adapter transport uses this name; its identity is runtime-owned,
|
|
118
|
+
// never the operation or trusted daemon identity of the calling coordinator.
|
|
119
|
+
const env = { ...input.env, DD_EVAL_OPERATION_ID: input.operationId };
|
|
120
|
+
delete env.DD_FLOW_DAEMON_ID;
|
|
121
|
+
delete env.DD_FLOW_SCOPE_CONTROL_TOKEN;
|
|
122
|
+
delete env.DD_FLOW_RUNTIME_OWNER;
|
|
123
|
+
if (input.runtimeOwner) {
|
|
124
|
+
if (!path.isAbsolute(input.executable) || input.runtimeOwner.adapter_executable !== undefined && input.runtimeOwner.adapter_executable !== input.executable)
|
|
125
|
+
throw new AppError("harness_runtime_binding_conflict", "Owned harness call must use its frozen absolute adapter executable", 1);
|
|
126
|
+
env.DD_FLOW_RUNTIME_OWNER = JSON.stringify({ ...input.runtimeOwner, adapter_executable: input.executable });
|
|
127
|
+
}
|
|
6
128
|
return new Promise((resolve, reject) => {
|
|
129
|
+
if (input.signal?.aborted)
|
|
130
|
+
return reject(new AppError("harness_adapter_aborted", "Harness adapter call was cancelled before dispatch", 1));
|
|
7
131
|
const detached = process.platform !== "win32";
|
|
8
|
-
const child = spawn(input.executable, input.args, { env: input.
|
|
132
|
+
const child = spawn(input.executable, input.args, { env, ...(input.cwd ? { cwd: input.cwd } : {}), detached, stdio: ["ignore", "pipe", "pipe"] });
|
|
9
133
|
let stdout = "";
|
|
10
134
|
let stderr = "";
|
|
135
|
+
let outputTooLarge = false;
|
|
11
136
|
let timedOut = false;
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
137
|
+
let aborted = false;
|
|
138
|
+
let cleanup;
|
|
139
|
+
let pendingDiagnostic = "", droppingDiagnostic = false, progressCursor = 0;
|
|
140
|
+
let prettyDiagnostic = "", retainedError;
|
|
141
|
+
const phases = new Set();
|
|
142
|
+
let operationSequence = 0;
|
|
143
|
+
let diagnosticReads = Promise.resolve();
|
|
144
|
+
const clock = timeoutMs === null ? null : new ObservationClock({ timeoutMs });
|
|
145
|
+
clock?.sample(progressCursor);
|
|
146
|
+
let settled = false;
|
|
147
|
+
let callbackError;
|
|
148
|
+
let spawnError;
|
|
149
|
+
const stopTransport = () => {
|
|
150
|
+
cleanup ??= stopProcessGroup(child, 5_000, { detached }).catch(error => {
|
|
151
|
+
if (timer)
|
|
152
|
+
clearInterval(timer);
|
|
153
|
+
if (heartbeat)
|
|
154
|
+
clearInterval(heartbeat);
|
|
155
|
+
input.signal?.removeEventListener("abort", abort);
|
|
156
|
+
const details = { cleanup_error: errorRecord(error) };
|
|
157
|
+
if (callbackError instanceof Error) {
|
|
158
|
+
Object.assign(callbackError, { cleanup_error: details.cleanup_error, details: { ...callbackError.details, ...details } });
|
|
159
|
+
reject(callbackError);
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
reject(new AppError(outputTooLarge ? "harness_adapter_output_limit" : timedOut ? "harness_adapter_timeout" : aborted ? "harness_adapter_aborted" : "harness_adapter_cleanup_unconfirmed", "Adapter transport cleanup could not be confirmed", 1, details));
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
const deliver = (callback) => {
|
|
166
|
+
try {
|
|
167
|
+
const result = callback();
|
|
168
|
+
if (result && typeof result.then === "function") {
|
|
169
|
+
void Promise.resolve(result).catch(() => { });
|
|
170
|
+
throw new AppError("progress_callback_async", "Harness callbacks must be synchronous", 1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
callbackError ??= error;
|
|
175
|
+
if (!settled)
|
|
176
|
+
stopTransport();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const heartbeat = input.progress && input.progressMessage ? setInterval(() => deliver(() => input.progress?.(`${input.progressMessage}; waiting for adapter completion`)), 15_000) : undefined;
|
|
180
|
+
let observing = false;
|
|
181
|
+
const timer = timeoutMs === null ? undefined : setInterval(async () => {
|
|
182
|
+
if (settled || cleanup)
|
|
183
|
+
return;
|
|
184
|
+
if (observing)
|
|
185
|
+
return;
|
|
186
|
+
observing = true;
|
|
187
|
+
// Helper phase progress must never replenish its owner's independent
|
|
188
|
+
// physical-settlement episode. ALS retains that existing budget here.
|
|
189
|
+
try {
|
|
190
|
+
recoveryRpcTimeout(timeoutMs);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
callbackError ??= error;
|
|
194
|
+
stopTransport();
|
|
195
|
+
observing = false;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const waiting = stateDir && await readOperationWaiting(stateDir, input.operationId, binding);
|
|
200
|
+
if (settled || cleanup)
|
|
201
|
+
return;
|
|
202
|
+
if (waiting)
|
|
203
|
+
suspendOperationClock(clock);
|
|
204
|
+
else if (clock.sample(progressCursor)) {
|
|
205
|
+
timedOut = true;
|
|
206
|
+
stopTransport();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
callbackError ??= error;
|
|
211
|
+
stopTransport();
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
observing = false;
|
|
215
|
+
}
|
|
216
|
+
}, Math.max(1, Math.min(1000, timeoutMs / 4)));
|
|
217
|
+
const abort = () => { aborted = true; stopTransport(); };
|
|
218
|
+
if (input.signal?.aborted)
|
|
219
|
+
abort();
|
|
220
|
+
else
|
|
221
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
222
|
+
const evidence = (value) => input.onEvidence?.({ operation_id: input.operationId, executable: input.executable, args: input.args, ...value, at: new Date().toISOString() });
|
|
223
|
+
const append = (current, chunk) => {
|
|
224
|
+
if (Buffer.byteLength(current) + Buffer.byteLength(chunk) > maxAdapterOutputBytes) {
|
|
225
|
+
outputTooLarge = true;
|
|
226
|
+
stopTransport();
|
|
227
|
+
return current;
|
|
228
|
+
}
|
|
229
|
+
return current + chunk;
|
|
230
|
+
};
|
|
231
|
+
const observeDiagnostic = (line) => {
|
|
232
|
+
if (prettyDiagnostic === null) {
|
|
233
|
+
if (line.trimEnd() === "}")
|
|
234
|
+
prettyDiagnostic = "";
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const candidate = prettyDiagnostic ? `${prettyDiagnostic}\n${line}` : line;
|
|
238
|
+
if (candidate.length > 64_000) {
|
|
239
|
+
prettyDiagnostic = null;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let value;
|
|
243
|
+
try {
|
|
244
|
+
value = JSON.parse(candidate);
|
|
245
|
+
prettyDiagnostic = "";
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
prettyDiagnostic = prettyDiagnostic || line.trimStart().startsWith("{") ? candidate : "";
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
252
|
+
return;
|
|
253
|
+
if (value.kind === "operation_progress" && stateDir && value.operation_id === input.operationId) {
|
|
254
|
+
// The diagnostic is only a wake-up: durable, bound evidence owns liveness.
|
|
255
|
+
diagnosticReads = diagnosticReads.then(async () => {
|
|
256
|
+
const record = await readOperationProgress(stateDir, input.operationId, binding);
|
|
257
|
+
if (!record || record.sequence <= operationSequence)
|
|
258
|
+
return;
|
|
259
|
+
const requested = await readOperationRecord(stateDir, input.operationId, "requested.json");
|
|
260
|
+
if (!requested)
|
|
261
|
+
throw new AppError("operation_progress_invalid", "Operation request disappeared while observing progress", 1);
|
|
262
|
+
for (const key of ["daemon_id", "params_sha256", "generation"])
|
|
263
|
+
binding[key] ??= requested[key] ?? null;
|
|
264
|
+
operationSequence = record.sequence;
|
|
265
|
+
clock?.sample(++progressCursor, Date.parse(record.observed_at));
|
|
266
|
+
}).catch(error => { callbackError ??= error; if (!settled)
|
|
267
|
+
stopTransport(); });
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const cause = adapterCause(candidate);
|
|
271
|
+
if (typeof cause.code === "string")
|
|
272
|
+
retainedError = cause;
|
|
273
|
+
if (clock && !(stateDir && ["session.create", "session.fork", "session.start", "session.resume", "session.prompt"].includes(operation))
|
|
274
|
+
&& ["native_hook_phase", "process_maintenance_phase"].includes(String(value.kind))
|
|
275
|
+
&& typeof value.phase === "string" && /^[a-z_]{1,48}$/.test(value.phase)
|
|
276
|
+
&& !["heartbeat", "poll", "elapsed", "wait", "waiting", "status"].includes(value.phase)) {
|
|
277
|
+
const marker = JSON.stringify([value.kind, value.phase, value.operation_id ?? value.process_id]);
|
|
278
|
+
if (!phases.has(marker)) {
|
|
279
|
+
phases.add(marker);
|
|
280
|
+
clock.sample(++progressCursor);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
child.stdout.setEncoding("utf8").on("data", (chunk) => { stdout = append(stdout, chunk); });
|
|
285
|
+
// Diagnostics have no lifetime quota. Stream to the existing evidence sink
|
|
286
|
+
// and carry only a bounded tail in the disposable RPC receipt.
|
|
287
|
+
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
288
|
+
stderr = (stderr + chunk).slice(-64_000);
|
|
289
|
+
for (const piece of chunk.split(/(?<=\n)/)) {
|
|
290
|
+
if (!droppingDiagnostic)
|
|
291
|
+
pendingDiagnostic += piece;
|
|
292
|
+
if (pendingDiagnostic.length > 64_000) {
|
|
293
|
+
prettyDiagnostic = prettyDiagnostic || pendingDiagnostic.trimStart().startsWith("{") ? null : "";
|
|
294
|
+
pendingDiagnostic = "";
|
|
295
|
+
droppingDiagnostic = true;
|
|
296
|
+
}
|
|
297
|
+
if (!piece.endsWith("\n"))
|
|
298
|
+
continue;
|
|
299
|
+
if (!droppingDiagnostic)
|
|
300
|
+
observeDiagnostic(pendingDiagnostic);
|
|
301
|
+
pendingDiagnostic = "";
|
|
302
|
+
droppingDiagnostic = false;
|
|
303
|
+
}
|
|
304
|
+
if (input.onEvidence)
|
|
305
|
+
deliver(() => evidence({ type: "adapter_diagnostic", stderr: chunk }));
|
|
306
|
+
});
|
|
307
|
+
child.once("error", (error) => { spawnError = error; });
|
|
308
|
+
child.once("close", async (status, signal) => {
|
|
309
|
+
if (settled)
|
|
310
|
+
return;
|
|
311
|
+
settled = true;
|
|
312
|
+
if (timer)
|
|
313
|
+
clearInterval(timer);
|
|
314
|
+
input.signal?.removeEventListener("abort", abort);
|
|
30
315
|
if (heartbeat)
|
|
31
316
|
clearInterval(heartbeat);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
317
|
+
await cleanup;
|
|
318
|
+
if (!droppingDiagnostic && pendingDiagnostic)
|
|
319
|
+
observeDiagnostic(pendingDiagnostic);
|
|
320
|
+
await diagnosticReads;
|
|
321
|
+
const progressFailure = callbackError;
|
|
322
|
+
deliver(() => evidence({ status, signal, timed_out: timedOut, aborted, stdout, stderr, ...(spawnError ? { error: spawnError.message } : {}) }));
|
|
323
|
+
if (spawnError)
|
|
324
|
+
return reject(new AppError("harness_adapter_failed", "Harness adapter call failed", 1, { cause: adapterCause(spawnError.message), ...(callbackError ? { evidence_error: String(callbackError) } : {}) }));
|
|
325
|
+
if (outputTooLarge)
|
|
326
|
+
return reject(new AppError("harness_adapter_output_limit", "Harness adapter exceeded the bounded reply limit", 1, { executable: input.executable, args: input.args.slice(0, 3), max_output_bytes: maxAdapterOutputBytes }));
|
|
35
327
|
if (timedOut)
|
|
36
|
-
return reject(new AppError("
|
|
328
|
+
return reject(Object.assign(new AppError("harness_adapter_timeout", "Harness adapter call timed out", 1, { executable: input.executable, args: input.args.slice(0, 3), timeout_ms: timeoutMs }), { observationClock: clock }));
|
|
329
|
+
if (aborted)
|
|
330
|
+
return reject(new AppError("harness_adapter_aborted", "Harness adapter call was cancelled", 1, { executable: input.executable, args: input.args.slice(0, 3) }));
|
|
37
331
|
if (status !== 0)
|
|
38
|
-
return reject(new AppError("
|
|
332
|
+
return reject(progressFailure ?? new AppError("harness_adapter_failed", "Harness adapter call failed", 1, { executable: input.executable, args: input.args.slice(0, 3), status, signal, stderr, cause: adapterCause(stdout, stderr, retainedError ? JSON.stringify(retainedError) : ""), ...(callbackError ? { evidence_error: String(callbackError) } : {}) }));
|
|
333
|
+
if (callbackError)
|
|
334
|
+
return reject(callbackError);
|
|
39
335
|
try {
|
|
40
|
-
|
|
336
|
+
const reply = JSON.parse(stdout);
|
|
337
|
+
if (!reply || typeof reply !== "object" || Array.isArray(reply))
|
|
338
|
+
throw new Error("not object");
|
|
339
|
+
const value = reply;
|
|
340
|
+
if (value.ok === false)
|
|
341
|
+
return reject(new AppError("harness_adapter_failed", "Harness adapter reported a runtime failure", 1, { cause: adapterCause(stdout) }));
|
|
342
|
+
resolve(reply);
|
|
41
343
|
}
|
|
42
344
|
catch {
|
|
43
|
-
reject(new AppError("
|
|
345
|
+
reject(new AppError("harness_adapter_invalid", "Harness adapter returned one invalid JSON object", 1, { executable: input.executable }));
|
|
44
346
|
}
|
|
45
347
|
});
|
|
46
348
|
});
|
|
47
349
|
}
|
|
350
|
+
function adapterCause(...outputs) {
|
|
351
|
+
for (const output of outputs)
|
|
352
|
+
for (const line of [output.trim(), ...output.trim().split("\n").reverse()]) {
|
|
353
|
+
try {
|
|
354
|
+
const value = JSON.parse(line);
|
|
355
|
+
const nested = value.error && typeof value.error === "object" && !Array.isArray(value.error) ? value.error : null;
|
|
356
|
+
const code = typeof nested?.code === "string" ? nested.code : typeof value.code === "string" ? value.code : null;
|
|
357
|
+
const message = typeof nested?.message === "string" ? nested.message : typeof value.error === "string" ? value.error : typeof value.message === "string" ? value.message : code;
|
|
358
|
+
if (code)
|
|
359
|
+
return errorRecord({ ...(nested ?? value), code, message });
|
|
360
|
+
}
|
|
361
|
+
catch { /* Adapter diagnostics need not be JSON. */ }
|
|
362
|
+
}
|
|
363
|
+
return { message: outputs.map(output => output.trim()).filter(Boolean).join("\n") || "adapter process failed" };
|
|
364
|
+
}
|
|
48
365
|
export function adapterSessionId(value) {
|
|
49
366
|
if (!value || typeof value !== "object")
|
|
50
367
|
return null;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
368
|
+
const reply = value;
|
|
369
|
+
for (const key of ["provider_session_id", "adapter_session_id", "session_id"])
|
|
370
|
+
if (typeof reply[key] === "string" && reply[key].trim())
|
|
371
|
+
return reply[key];
|
|
372
|
+
const session = reply.session;
|
|
373
|
+
if (session && typeof session === "object" && !Array.isArray(session))
|
|
374
|
+
for (const key of ["provider_session_id", "session_id"])
|
|
375
|
+
if (typeof session[key] === "string" && String(session[key]).trim())
|
|
376
|
+
return session[key];
|
|
58
377
|
return null;
|
|
59
378
|
}
|
|
@@ -10,6 +10,7 @@ export function harnessKey(value) {
|
|
|
10
10
|
zcode: "zcode-acp", "zcode-acp": "zcode-acp",
|
|
11
11
|
grok: "grok-acp", "grok-acp": "grok-acp",
|
|
12
12
|
agy: "antigravity-cli", "antigravity-cli": "antigravity-cli",
|
|
13
|
+
droid: "droid-cli", "droid-cli": "droid-cli",
|
|
13
14
|
opencode: "opencode-server", "opencode-server": "opencode-server"
|
|
14
15
|
};
|
|
15
16
|
const resolved = keys[value];
|
|
@@ -60,6 +61,7 @@ export function harnessRuntimeArguments(ddFlowHome, harness) {
|
|
|
60
61
|
"zcode-acp": "--zcode-acp-bin",
|
|
61
62
|
"grok-acp": "--grok-bin",
|
|
62
63
|
"antigravity-cli": "--agy-bin",
|
|
64
|
+
"droid-cli": "--droid-bin",
|
|
63
65
|
"opencode-server": "--opencode-bin"
|
|
64
66
|
};
|
|
65
67
|
return [option[key], runtime];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { validateHybridContract } from "./hybrid-contracts.js";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
import { discoverCodex } from "./discovery/codex-discovery.js";
|
|
5
|
+
import { discoverZcode } from "./discovery/zcode-discovery.js";
|
|
6
|
+
import { discoverAgy } from "./discovery/agy-discovery.js";
|
|
7
|
+
import { discoverOpenCode } from "./discovery/opencode-discovery.js";
|
|
8
|
+
import { discoverGrok } from "./discovery/grok-discovery.js";
|
|
9
|
+
import { discoverDroid } from "./discovery/droid-discovery.js";
|
|
10
|
+
import { readOnlyProbeScope, runScopedProbe, staticDiscoveryEffects } from "./harness-probe-effects.js";
|
|
11
|
+
const modules = { codex: discoverCodex, zcode: discoverZcode, agy: discoverAgy, opencode: discoverOpenCode, grok: discoverGrok, droid: discoverDroid };
|
|
12
|
+
export const harnessCatalog = {
|
|
13
|
+
schema_id: "dd-flow/harness-catalog@1", version: "1.0.0",
|
|
14
|
+
entries: Object.keys(modules).map(id => ({ id, executable_candidates: [id], probe_module: `${id}-discovery`,
|
|
15
|
+
probe_timeout_ms: 3000, version_range: "unknown_requires_review", protocol_version: "unknown_requires_protocol_probe" }))
|
|
16
|
+
};
|
|
17
|
+
export function discoverHarnesses(input) {
|
|
18
|
+
if (input.harness && !Object.hasOwn(modules, input.harness))
|
|
19
|
+
throw new AppError("usage", "Unknown harness family", 2, { effect: "no_effect" });
|
|
20
|
+
if (input.executable && !input.harness)
|
|
21
|
+
throw new AppError("usage", "Explicit executable requires one harness family", 2, { effect: "no_effect" });
|
|
22
|
+
const families = input.harness ? [input.harness] : Object.keys(modules);
|
|
23
|
+
const result = { schema_id: "dd-flow/discovery-result@1", request_id: input.requestId ?? randomUUID(), observed_at: new Date().toISOString(),
|
|
24
|
+
probe_scope: "static", live_authorization_receipt: null, entries: families.map(family => runScopedProbe(staticDiscoveryEffects, readOnlyProbeScope, () => modules[family](input))) };
|
|
25
|
+
if (validateHybridContract("harness-catalog", harnessCatalog).length || validateHybridContract("discovery-result", result).length) {
|
|
26
|
+
throw new AppError("discovery_contract", "Discovery owner produced invalid facts", 1, { effect: "no_effect" });
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { parse } from "semver";
|
|
4
|
+
import { AppError } from "../shared/errors.js";
|
|
5
|
+
import { legacyDoctorEffects, runScopedProbe } from "./harness-probe-effects.js";
|
|
6
|
+
import { readBoundedReleaseFile } from "./release-source.js";
|
|
7
|
+
import { discoverExecutable } from "./discovery/static.js";
|
|
8
|
+
const binOptions = {
|
|
9
|
+
codex: "codex-bin", zcode: "zcode-acp-bin", agy: "agy-bin", opencode: "opencode-bin", grok: "grok-bin", droid: "droid-bin"
|
|
10
|
+
};
|
|
11
|
+
function refuse(code, message, exitCode = 1) {
|
|
12
|
+
throw new AppError(code, message, exitCode, { phase: "harness_doctor", help: "harnesses doctor" });
|
|
13
|
+
}
|
|
14
|
+
/** Existing non-generative adapter doctor, bounded by its owner transport.
|
|
15
|
+
* Reported compatibility is not qualification or verified account access.
|
|
16
|
+
* OpenCode observes an explicitly bound existing daemon; it never starts one.
|
|
17
|
+
*/
|
|
18
|
+
export async function probeHarnessDoctor(input) {
|
|
19
|
+
const timeoutMs = input.timeoutMs ?? 30_000;
|
|
20
|
+
if (!Object.hasOwn(binOptions, input.harness) || !path.isAbsolute(input.executable)
|
|
21
|
+
|| !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60_000
|
|
22
|
+
|| input.stateDir !== undefined && !path.isAbsolute(input.stateDir)
|
|
23
|
+
|| input.nativeExecutable !== undefined && (!path.isAbsolute(input.nativeExecutable) || input.harness !== "zcode")
|
|
24
|
+
|| input.stateDir !== undefined && input.harness !== "opencode")
|
|
25
|
+
refuse("usage", "Doctor requires explicit contained diagnostic inputs", 2);
|
|
26
|
+
return runScopedProbe(legacyDoctorEffects[input.harness], input.scope, async () => {
|
|
27
|
+
if (input.harness === "droid" && discoverExecutable("system-ps", ["ps"], { env: { ...process.env, ...input.env } }).candidates.length === 0) {
|
|
28
|
+
throw new AppError("doctor_prerequisite_missing", "Droid doctor requires the OS ps utility for physical process settlement", 1, { phase: "harness_doctor", effect: "no_effect", prerequisite: "ps", help: "harnesses doctor" });
|
|
29
|
+
}
|
|
30
|
+
const args = [fileURLToPath(new URL(`../harness-runtime/bin/dd-${input.harness}.mjs`, import.meta.url)), "doctor",
|
|
31
|
+
`--${binOptions[input.harness]}`, input.executable, "--timeout-ms", String(timeoutMs), "--json"];
|
|
32
|
+
if (input.harness === "zcode") {
|
|
33
|
+
if (!input.nativeExecutable)
|
|
34
|
+
refuse("harness_selection_required", "ZCode doctor also requires --native-executable for its native runtime");
|
|
35
|
+
args.push("--zcode-path", input.nativeExecutable);
|
|
36
|
+
}
|
|
37
|
+
if (input.harness === "opencode") {
|
|
38
|
+
if (!input.stateDir)
|
|
39
|
+
refuse("harness_selection_required", "OpenCode doctor requires --state-dir for an existing owned daemon; no service is started");
|
|
40
|
+
let state;
|
|
41
|
+
try {
|
|
42
|
+
state = JSON.parse(readBoundedReleaseFile(path.join(input.stateDir, "daemon.json"), 1024 * 1024).toString("utf8"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return refuse("doctor_state_unavailable", "Selected daemon identity cannot be read");
|
|
46
|
+
}
|
|
47
|
+
const selected = state;
|
|
48
|
+
if (selected?.config?.bin !== input.executable)
|
|
49
|
+
refuse("doctor_state_mismatch", "Selected daemon does not bind the discovered executable");
|
|
50
|
+
args.push("--state-dir", input.stateDir);
|
|
51
|
+
}
|
|
52
|
+
const transport = await import(new URL("../harness-runtime/lib/process-json.mjs", import.meta.url).href);
|
|
53
|
+
let report;
|
|
54
|
+
try {
|
|
55
|
+
report = await transport.commandJson(process.execPath, args, { env: input.env, timeoutMs, signal: AbortSignal.timeout(timeoutMs), phase: "native-doctor" });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return refuse("harness_doctor_failed", "Adapter doctor failed or could not confirm its observation; no model Turn was requested");
|
|
59
|
+
}
|
|
60
|
+
if (!report || typeof report !== "object" || Array.isArray(report) || report.ok !== true)
|
|
61
|
+
refuse("harness_doctor_failed", "Adapter doctor did not return an accepted diagnostic");
|
|
62
|
+
const observed = report.observed_runtime && typeof report.observed_runtime === "object" ? report.observed_runtime : {};
|
|
63
|
+
const versionField = input.harness === "codex" ? "codex_cli" : input.harness === "zcode" ? "zcode_acp" : input.harness;
|
|
64
|
+
const versions = report.versions && typeof report.versions === "object" && !Array.isArray(report.versions) ? report.versions : {};
|
|
65
|
+
// Existing OpenCode doctor reports versions separately from observed_runtime.
|
|
66
|
+
const versionValue = input.harness === "opencode" ? versions.opencode : observed[versionField];
|
|
67
|
+
const version = typeof versionValue === "string" ? parse(versionValue)?.version ?? null : null;
|
|
68
|
+
const protocol = observed.dd_harness_contract;
|
|
69
|
+
const models = Array.isArray(report.models) ? report.models.filter((model) => typeof model === "string" && /^[A-Za-z0-9][A-Za-z0-9._:/+-]{0,255}$/.test(model)).slice(0, 10_000) : [];
|
|
70
|
+
return { harness: input.harness, effects: legacyDoctorEffects[input.harness], reported_version: version,
|
|
71
|
+
reported_protocol: typeof protocol === "string" && /^dd-[a-z0-9-]+@[0-9]+$/.test(protocol) ? protocol : null,
|
|
72
|
+
reported_models: [...new Set(models)].sort(), models_complete: false, reported_compatible: typeof report.compatible === "boolean" ? report.compatible : null,
|
|
73
|
+
account_access: "unknown", qualified: "unknown", model_turn: "not_requested" };
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
export const readOnlyProbeScope = Object.freeze({
|
|
3
|
+
processes: false, services: false, credentials: false, writes: false
|
|
4
|
+
});
|
|
5
|
+
/** Source-grounded effects of existing adapters; this is not permission to invoke them. */
|
|
6
|
+
export const legacyDoctorEffects = {
|
|
7
|
+
codex: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-codex.mjs:doctor/withBridge" },
|
|
8
|
+
zcode: { child_process: true, service_process: false, credential_access: "possible", filesystem: "read_only", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-zcode.mjs:doctor" },
|
|
9
|
+
agy: { child_process: true, service_process: false, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-agy.mjs:doctor" },
|
|
10
|
+
opencode: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-opencode-daemon.mjs:daemon.doctor/startDaemon" },
|
|
11
|
+
grok: { child_process: true, service_process: false, credential_access: "possible", filesystem: "read_only", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-grok.mjs:doctor" },
|
|
12
|
+
droid: { child_process: true, service_process: true, credential_access: "possible", filesystem: "temporary_or_runtime_writes", model_turn: "not_requested", source_owner: "harness-runtime/lib/dd-droid-daemon.mjs:runtime.start" }
|
|
13
|
+
};
|
|
14
|
+
for (const effects of Object.values(legacyDoctorEffects))
|
|
15
|
+
Object.freeze(effects);
|
|
16
|
+
Object.freeze(legacyDoctorEffects);
|
|
17
|
+
export const staticDiscoveryEffects = Object.freeze({
|
|
18
|
+
child_process: false, service_process: false, credential_access: "none", filesystem: "read_only", model_turn: "not_requested",
|
|
19
|
+
source_owner: "services/discovery/static.ts:discoverExecutable"
|
|
20
|
+
});
|
|
21
|
+
/** Enforce effect ceilings before invoking a probe. A non-generative label alone is insufficient. */
|
|
22
|
+
export function assertProbeWithinScope(effects, scope) {
|
|
23
|
+
const scopeKeys = ["processes", "services", "credentials", "writes"];
|
|
24
|
+
const effectKeys = ["child_process", "service_process", "credential_access", "filesystem", "model_turn", "source_owner"];
|
|
25
|
+
if (!scope || typeof scope !== "object" || Array.isArray(scope)
|
|
26
|
+
|| Object.keys(scope).some(key => !scopeKeys.includes(key))
|
|
27
|
+
|| scopeKeys.some(key => !Object.hasOwn(scope, key) || typeof scope[key] !== "boolean")
|
|
28
|
+
|| !effects || typeof effects !== "object" || Array.isArray(effects)
|
|
29
|
+
|| effectKeys.some(key => !Object.hasOwn(effects, key)) || Object.keys(effects).some(key => !effectKeys.includes(key))
|
|
30
|
+
|| typeof effects.child_process !== "boolean" || typeof effects.service_process !== "boolean"
|
|
31
|
+
|| !["none", "possible"].includes(effects.credential_access)
|
|
32
|
+
|| !["read_only", "temporary_or_runtime_writes"].includes(effects.filesystem)
|
|
33
|
+
|| !["not_requested", "possible"].includes(effects.model_turn)
|
|
34
|
+
|| typeof effects.source_owner !== "string" || !effects.source_owner.trim()) {
|
|
35
|
+
throw new AppError("probe_scope_invalid", "Probe effects and permissions require an explicit typed scope", 2, { phase: "probe_admission", effect: "no_effect", help: "harnesses" });
|
|
36
|
+
}
|
|
37
|
+
const blocked = [
|
|
38
|
+
effects.child_process && !scope.processes ? "child_process" : null,
|
|
39
|
+
effects.service_process && !scope.services ? "service_process" : null,
|
|
40
|
+
effects.credential_access !== "none" && !scope.credentials ? "credential_access" : null,
|
|
41
|
+
effects.filesystem !== "read_only" && !scope.writes ? "filesystem_writes" : null,
|
|
42
|
+
effects.model_turn !== "not_requested" ? "live_authorization_required" : null
|
|
43
|
+
].filter(Boolean);
|
|
44
|
+
if (blocked.length)
|
|
45
|
+
throw new AppError("probe_effects_not_authorized", "Probe exceeds the selected effect scope", 1, { phase: "probe_admission", effect: "no_effect", blocked_effects: blocked, help: "harnesses" });
|
|
46
|
+
}
|
|
47
|
+
/** The callback is not entered, including synchronous effects, until admission succeeds. */
|
|
48
|
+
export function runScopedProbe(effects, scope, probe) {
|
|
49
|
+
assertProbeWithinScope(effects, scope);
|
|
50
|
+
return probe();
|
|
51
|
+
}
|