@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.150
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 +895 -0
- package/README.md +140 -6
- package/dist/build-info.json +8 -8
- package/dist/cli/argument-values.js +38 -0
- package/dist/cli/command-inputs.js +386 -0
- package/dist/cli/command-metadata.js +232 -0
- package/dist/cli/command-option-descriptions.js +192 -0
- package/dist/cli/completion-cli.js +70 -0
- package/dist/cli/completion.js +57 -0
- package/dist/cli/diagnostic-invocation.js +46 -0
- package/dist/cli/diagnostic.js +120 -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 +396 -19
- package/dist/cli/hook-ingress.js +102 -0
- package/dist/cli/input-preparation.js +165 -0
- package/dist/cli/memory-flow-admission.js +50 -0
- package/dist/cli/memory-init-invocation.js +85 -0
- package/dist/cli/memory-init.js +249 -0
- package/dist/cli/memory-storage-admission.js +54 -0
- package/dist/cli/memory-storage-qualification.js +105 -0
- package/dist/cli/memory-storage-transition.js +123 -0
- package/dist/cli/memory-upgrade.js +189 -0
- package/dist/cli/models.js +39 -0
- package/dist/cli/native-hook-ingress.js +90 -0
- package/dist/cli/native-hook-preparation.js +55 -0
- package/dist/cli/operator-profiles.js +61 -0
- package/dist/cli/output-options.js +35 -0
- package/dist/cli/response-file.js +72 -0
- package/dist/cli/run-cli.js +1734 -550
- 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 +150 -0
- package/dist/cli.js +89 -2
- package/dist/domain/diagnostic-aspects.js +103 -0
- package/dist/domain/diagnostic-flows.js +8 -0
- package/dist/domain/stage-catalog.js +1 -1
- package/dist/domain/stage-handler-identities.js +28 -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-error-boundary.mjs +58 -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/agy-native-inspection.mjs +216 -0
- package/dist/harness-runtime/lib/agy-native_pb.js +117 -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 +2 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +462 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1096 -0
- package/dist/harness-runtime/lib/dd-agy.mjs +86 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +231 -0
- package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex.mjs +954 -0
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +141 -0
- package/dist/harness-runtime/lib/dd-droid.mjs +626 -0
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +555 -0
- package/dist/harness-runtime/lib/dd-grok.mjs +180 -0
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +622 -0
- package/dist/harness-runtime/lib/dd-opencode.mjs +390 -0
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +752 -0
- package/dist/harness-runtime/lib/dd-zcode.mjs +1175 -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 +140 -0
- package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
- package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
- package/dist/harness-runtime/lib/entity-references.mjs +9 -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 +16 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +698 -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 +23 -0
- package/dist/harness-runtime/lib/native-children.mjs +219 -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 +95 -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 +16 -0
- package/dist/harness-runtime/lib/operation-errors.mjs +127 -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 +15 -0
- package/dist/harness-runtime/lib/provider-overload-policy.mjs +151 -0
- package/dist/harness-runtime/lib/runner-events.mjs +202 -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 +53 -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-decision.schema.json +9 -0
- 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/diagnostic-stage-result.schema.json +354 -0
- package/dist/schemas/diagnostic-work-result.schema.json +296 -0
- package/dist/schemas/discovery-result.schema.json +184 -0
- package/dist/schemas/execution-bundle.schema.json +211 -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 +29 -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/mb-upgrade-stage-result.schema.json +863 -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 +56 -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 +12 -3
- package/dist/schemas/plan-review-result.schema.json +2 -2
- package/dist/schemas/profile-settings.schema.json +122 -0
- package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
- package/dist/schemas/release-impact.schema.json +3 -3
- 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/stage-start-response.schema.json +4 -0
- package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
- package/dist/services/accepted-intent.js +139 -0
- package/dist/services/branch-context.js +3 -3
- package/dist/services/canon.js +54 -15
- package/dist/services/check-environment.js +21 -0
- package/dist/services/check-runner-evidence.js +562 -0
- package/dist/services/cleanup.js +133 -40
- package/dist/services/cli-operation-classifier.js +26 -63
- package/dist/services/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +1398 -119
- package/dist/services/codex-hook-delivery.js +32 -0
- package/dist/services/command-context.js +80 -0
- package/dist/services/compatibility-preflight.js +16 -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 +94 -0
- package/dist/services/controller-fanout.js +226 -0
- package/dist/services/controller-memory-task.js +45 -0
- package/dist/services/controller-memory-worker.js +49 -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 +107 -0
- package/dist/services/descriptor-run-start.js +475 -0
- package/dist/services/descriptor-stage-coordinator.js +250 -0
- package/dist/services/descriptor-stage-settlement.js +223 -0
- package/dist/services/descriptor-stage-start.js +175 -0
- package/dist/services/diagnostic-evidence.js +73 -0
- package/dist/services/diagnostic-report-publication.js +72 -0
- package/dist/services/diagnostic-report.js +67 -0
- package/dist/services/diagnostic-run-bundle.js +74 -0
- package/dist/services/diagnostic-snapshot.js +159 -0
- package/dist/services/diagnostic-stage-handlers.js +108 -0
- package/dist/services/diagnostic-stage-results.js +132 -0
- package/dist/services/diagnostic-start.js +84 -0
- package/dist/services/diagnostic-work-batch.js +34 -0
- package/dist/services/diagnostic-work-collection.js +97 -0
- package/dist/services/diagnostic-work-registration.js +101 -0
- package/dist/services/diagnostic-work-results.js +93 -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 +354 -163
- package/dist/services/eval-snapshots.js +1316 -150
- package/dist/services/execution-bundles.js +275 -0
- package/dist/services/execution-policy.js +185 -0
- package/dist/services/executor-onboarding.js +56 -0
- package/dist/services/external-work-launch.js +310 -0
- package/dist/services/flow-catalog.js +30 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +387 -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/hook-memory-routing.js +188 -0
- package/dist/services/hook-recovery-guard.js +14 -0
- package/dist/services/hook-session-observation.js +24 -0
- package/dist/services/hooks.js +791 -326
- package/dist/services/hybrid-contracts.js +474 -0
- package/dist/services/hybrid-digest.js +14 -0
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +95 -0
- package/dist/services/installed-flow-source.js +226 -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 +2148 -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 +449 -69
- package/dist/services/memory-accepted-composition.js +78 -0
- package/dist/services/memory-baseline-preservation.js +65 -0
- package/dist/services/memory-completed-correction-wave.js +328 -0
- package/dist/services/memory-compose-handler.js +400 -0
- package/dist/services/memory-composition-acceptance.js +375 -0
- package/dist/services/memory-composition-graph.js +165 -0
- package/dist/services/memory-composition-registration.js +161 -0
- package/dist/services/memory-composition-work-custody.js +156 -0
- package/dist/services/memory-composition-work-results.js +108 -0
- package/dist/services/memory-corrected-review-acceptance.js +129 -0
- package/dist/services/memory-corrected-review-batch.js +37 -0
- package/dist/services/memory-corrected-review-findings.js +108 -0
- package/dist/services/memory-corrected-review-inputs.js +215 -0
- package/dist/services/memory-corrected-review-projection.js +78 -0
- package/dist/services/memory-corrected-review-receipt.js +178 -0
- package/dist/services/memory-corrected-review-registration.js +192 -0
- package/dist/services/memory-correction-check-receipt.js +235 -0
- package/dist/services/memory-correction-input-owner.js +6 -0
- package/dist/services/memory-custody-snapshot.js +36 -0
- package/dist/services/memory-discover-handler.js +104 -0
- package/dist/services/memory-finish-evidence.js +457 -0
- package/dist/services/memory-finish-handler.js +229 -0
- package/dist/services/memory-finish-integration.js +450 -0
- package/dist/services/memory-finish-readiness.js +169 -0
- package/dist/services/memory-git-integration.js +220 -0
- package/dist/services/memory-historical-corrected-review.js +212 -0
- package/dist/services/memory-historical-original-review.js +143 -0
- package/dist/services/memory-historical-repair-registration.js +105 -0
- package/dist/services/memory-historical-second-review.js +147 -0
- package/dist/services/memory-init-bootstrap-readiness.js +210 -0
- package/dist/services/memory-init-contexts.js +131 -0
- package/dist/services/memory-init-controller-start.js +103 -0
- package/dist/services/memory-init-engine-release.js +223 -0
- package/dist/services/memory-init-git-policy.js +165 -0
- package/dist/services/memory-init-lint-capability.js +203 -0
- package/dist/services/memory-init-native-capacity.js +309 -0
- package/dist/services/memory-init-preflight.js +334 -0
- package/dist/services/memory-init-project-bootstrap.js +599 -0
- package/dist/services/memory-init-request-candidate.js +213 -0
- package/dist/services/memory-init-request-input.js +82 -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 +135 -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 +91 -0
- package/dist/services/memory-init-stores.js +359 -0
- package/dist/services/memory-init-worktrunk-capability.js +174 -0
- package/dist/services/memory-layer-publication.js +611 -0
- package/dist/services/memory-layer.js +221 -0
- package/dist/services/memory-lint-config.js +194 -0
- package/dist/services/memory-native-review-copy.js +103 -0
- package/dist/services/memory-normal-flow-entry.js +87 -0
- package/dist/services/memory-ordinary-defaults.js +129 -0
- package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
- package/dist/services/memory-preflight-handler.js +274 -0
- package/dist/services/memory-repair-current-view.js +299 -0
- package/dist/services/memory-repair-document-delta.js +488 -0
- package/dist/services/memory-repair-history.js +496 -0
- package/dist/services/memory-repair-physical-binding.js +194 -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 +162 -0
- package/dist/services/memory-repair-publication-source.js +225 -0
- package/dist/services/memory-repair-publication.js +795 -0
- package/dist/services/memory-repair-registration.js +240 -0
- package/dist/services/memory-repair-work-baseline.js +415 -0
- package/dist/services/memory-repair-work-completion.js +117 -0
- package/dist/services/memory-repair-work-custody.js +73 -0
- package/dist/services/memory-repair-work-results.js +108 -0
- package/dist/services/memory-repair-workspace.js +261 -0
- package/dist/services/memory-repair-writer-copy.js +736 -0
- package/dist/services/memory-result-binding.js +239 -0
- package/dist/services/memory-retained-review-authority.js +138 -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 +162 -0
- package/dist/services/memory-review-acceptance.js +214 -0
- package/dist/services/memory-review-correction-plan.js +206 -0
- package/dist/services/memory-review-handler.js +585 -0
- package/dist/services/memory-review-inputs.js +246 -0
- package/dist/services/memory-review-limits.js +10 -0
- package/dist/services/memory-review-receipt.js +180 -0
- package/dist/services/memory-review-registration.js +117 -0
- package/dist/services/memory-review-work-custody.js +126 -0
- package/dist/services/memory-review-work-input.js +91 -0
- package/dist/services/memory-review-work-results.js +95 -0
- package/dist/services/memory-second-corrected-review-inputs.js +167 -0
- package/dist/services/memory-second-correction-plan.js +77 -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 +65 -0
- package/dist/services/memory-stage-results.js +290 -0
- package/dist/services/memory-tool-probe.js +25 -0
- package/dist/services/memory-upgrade-analysis-handler.js +243 -0
- package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
- package/dist/services/memory-upgrade-evidence.js +100 -0
- package/dist/services/memory-upgrade-inventory.js +442 -0
- package/dist/services/memory-upgrade-publication-custody.js +73 -0
- package/dist/services/memory-upgrade-publication.js +413 -0
- package/dist/services/memory-upgrade-selection.js +430 -0
- package/dist/services/memory-upgrade-start.js +60 -0
- package/dist/services/memory-upgrade-storage-readiness.js +340 -0
- package/dist/services/memory-verification-acceptance.js +156 -0
- package/dist/services/memory-verification-checks.js +317 -0
- package/dist/services/memory-verification-receipt.js +160 -0
- package/dist/services/memory-verify-handler.js +137 -0
- package/dist/services/memory-work-result-json.js +12 -0
- package/dist/services/memory-work-result-preparation.js +64 -0
- package/dist/services/merge-queue.js +228 -149
- package/dist/services/merge-server.js +163 -35
- package/dist/services/migrations.js +164 -114
- package/dist/services/model-catalog.js +109 -0
- package/dist/services/model-discovery.js +46 -0
- package/dist/services/native-daemon-history.js +50 -0
- package/dist/services/native-session-control.js +39 -0
- package/dist/services/operator-profiles.js +236 -0
- package/dist/services/physical-startup.js +45 -0
- package/dist/services/plan-runtime.js +26 -11
- package/dist/services/plans.js +28 -25
- package/dist/services/project-registry.js +97 -0
- package/dist/services/project-summary.js +1 -1
- package/dist/services/projects.js +17 -87
- package/dist/services/prompt-delivery.js +71 -0
- package/dist/services/prompts.js +28 -17
- package/dist/services/protocols.js +163 -87
- package/dist/services/provider-capacity.js +455 -0
- package/dist/services/recovery-observation-budget.js +121 -0
- package/dist/services/recovery-snapshot-database.js +588 -0
- package/dist/services/release-archive-producer.js +52 -0
- package/dist/services/release-archive.js +143 -0
- package/dist/services/release-cache.js +150 -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 +31 -0
- package/dist/services/repair-receipt.js +13 -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 +428 -0
- package/dist/services/run-control.js +1092 -0
- package/dist/services/run-controller-adapter.js +400 -0
- package/dist/services/run-controller-capture.js +186 -0
- package/dist/services/run-controller-process.js +205 -0
- package/dist/services/run-controller-recovery.js +295 -0
- package/dist/services/run-controller-state.js +97 -0
- package/dist/services/run-controller.js +1326 -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 +107 -0
- package/dist/services/run-recovery-runtime.js +112 -0
- package/dist/services/run-recovery.js +456 -0
- package/dist/services/run-start-custody.js +189 -0
- package/dist/services/runs.js +1023 -246
- package/dist/services/runtime-budget.js +446 -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 +605 -0
- package/dist/services/runtime-scope-stop.js +211 -0
- package/dist/services/runtime-scope-worker.js +314 -0
- package/dist/services/runtime-service.js +19 -14
- package/dist/services/schema-validation.js +10 -8
- package/dist/services/scope-writer-cleanup.js +27 -0
- package/dist/services/sessions.js +36 -91
- package/dist/services/setup.js +427 -0
- package/dist/services/stage-blocker.js +17 -7
- package/dist/services/stage-context.js +193 -19
- package/dist/services/stage-handlers.js +89 -0
- package/dist/services/stage-lifecycle.js +152 -116
- package/dist/services/stage-pause.js +202 -91
- package/dist/services/stage-report-renderer.js +234 -6
- package/dist/services/stage-work-graph.js +52 -0
- package/dist/services/tooling.js +41 -30
- package/dist/services/usage.js +49 -101
- package/dist/services/verification-matrix.js +393 -0
- package/dist/services/version-status.js +1 -1
- package/dist/services/vnext-code-review.js +235 -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 +355 -21
- package/dist/services/vnext-merge.js +332 -111
- package/dist/services/vnext-plan-review.js +287 -132
- package/dist/services/vnext-plan.js +228 -104
- package/dist/services/vnext-protocolize.js +533 -95
- package/dist/services/vnext-specify.js +123 -81
- package/dist/services/vnext-workspace-policy.js +7 -2
- package/dist/services/work-registry.js +1706 -200
- package/dist/services/workspace-bootstrap.js +53 -15
- package/dist/services/workspace-files.js +85 -0
- package/dist/services/worktrees.js +105 -48
- package/dist/shared/entity-references.js +1 -0
- package/dist/shared/errors.js +27 -0
- package/dist/storage/agent-output.js +26 -0
- package/dist/storage/data-preservation.js +65 -0
- package/dist/storage/database.js +930 -40
- package/dist/storage/foreign-key-transaction.js +39 -0
- package/dist/storage/immutable-input.js +45 -0
- package/dist/storage/import-guard.js +159 -0
- package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
- package/dist/storage/native-cleanup.js +52 -0
- package/dist/storage/paired-writer-migration.js +424 -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 +96 -0
- package/dist/storage/writer-migration.js +346 -0
- package/dist/storage/writer-restore.js +217 -0
- package/package.json +50 -13
- package/tools/create-canon-release.mjs +33 -0
- package/tools/probe-codex-history.mjs +37 -0
- package/tools/produce-hybrid-release.mjs +41 -0
- package/tools/repair-paused-run-status.mjs +84 -0
package/dist/services/engines.js
CHANGED
|
@@ -2,40 +2,76 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { spawn
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { commandText } from '../harness-runtime/lib/process-json.mjs';
|
|
7
|
+
import { SETUP_STARTUP_MS, publishSetup } from '../harness-runtime/lib/setup-progress.mjs';
|
|
6
8
|
import { createRequire } from "node:module";
|
|
9
|
+
import { valid } from "semver";
|
|
7
10
|
import { getCliBuildInfo } from "./build-info.js";
|
|
8
11
|
import { AppError } from "../shared/errors.js";
|
|
9
|
-
import { ensureDir, engineStoreRoot, engineVersionRoot, resolveProjectRoot } from "../storage/paths.js";
|
|
10
|
-
import {
|
|
12
|
+
import { canonicalPath, ensureDir, engineStoreRoot, engineVersionRoot, resolveProjectRoot } from "../storage/paths.js";
|
|
13
|
+
import { resolveWorkReference } from "../storage/work-references.js";
|
|
14
|
+
import { classifyCliOperation, isRouterNative } from "./cli-operation-classifier.js";
|
|
11
15
|
import { requireProtocol } from "./protocols.js";
|
|
12
16
|
import { resolveCanonRootBeforeContext } from "./canon.js";
|
|
13
17
|
import { appendAudit } from "./audit.js";
|
|
18
|
+
import { readBoundedReleaseFile } from "./release-source.js";
|
|
14
19
|
import { findProjectByRoot } from "./projects.js";
|
|
20
|
+
import { parseCommandArgs } from "./lifecycle-command.js";
|
|
15
21
|
import { allRunEngineBindings, locateRunRoot, readRunEngineBinding, runEngineBindingSchemaId, writeRunEngineBinding } from "./run-engine-bindings.js";
|
|
16
22
|
export const engineManifestSchemaId = "dd-flow/engine-manifest@1";
|
|
17
|
-
const routerNativeFamilies = new Set(["engine", "version", "schema"]);
|
|
18
23
|
const sourceFile = fileURLToPath(import.meta.url);
|
|
19
|
-
const packageRequire = createRequire(sourceFile);
|
|
20
24
|
export function isEngineMode(env) {
|
|
21
25
|
return env.DD_FLOW_ENGINE_MODE === "1";
|
|
22
26
|
}
|
|
23
27
|
export function isRouterNativeCommand(args) {
|
|
24
|
-
|
|
25
|
-
if (!first || first === "--version")
|
|
26
|
-
return true;
|
|
27
|
-
if (first === "--help" || first === "-h")
|
|
28
|
-
return true;
|
|
29
|
-
if (args.includes("--help") || args.includes("-h"))
|
|
30
|
-
return true;
|
|
31
|
-
return routerNativeFamilies.has(first) || first === "codex" && args[1] === "hook" && args[2] === "handle";
|
|
28
|
+
return isRouterNative(args);
|
|
32
29
|
}
|
|
33
30
|
export function installCurrentEngine(context, input = {}) {
|
|
31
|
+
const installation = prepareInstallation(context, input);
|
|
32
|
+
const first = installation.next();
|
|
33
|
+
if (first.done && input.forRouting)
|
|
34
|
+
return first.value;
|
|
35
|
+
const manifest = first.done ? requireManifest(path.join(String(first.value.path), 'engine.json')) : first.value;
|
|
36
|
+
return probeEntrypoint(manifest, undefined, context.ddFlowHome, process.env).then(() => first.done ? first.value : installation.next().value)
|
|
37
|
+
.catch(error => {
|
|
38
|
+
let cleanup_error;
|
|
39
|
+
try {
|
|
40
|
+
installation.return({});
|
|
41
|
+
}
|
|
42
|
+
catch (cleanup) {
|
|
43
|
+
cleanup_error = { message: String(cleanup).slice(0, 2000) };
|
|
44
|
+
}
|
|
45
|
+
throw new AppError('engine_install_failed', 'Staged engine admission failed', 1, { ...error.details, cause: error.code, probe_error: { code: error.code, details: error.details }, ...(cleanup_error ? { cleanup_error } : {}) });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function* prepareInstallation(context, input) {
|
|
34
49
|
const build = getCliBuildInfo();
|
|
35
50
|
const packageRoot = findPackageRoot(path.dirname(sourceFile));
|
|
36
51
|
if (!packageRoot) {
|
|
37
52
|
throw new AppError("engine_install_failed", "Cannot locate package root for current dd-flow engine", 1);
|
|
38
53
|
}
|
|
54
|
+
return yield* installPackageSnapshot(context, packageRoot, build.package_name, build.version, input);
|
|
55
|
+
}
|
|
56
|
+
/** Delivery from an independently selected package, not the invoking CLI.
|
|
57
|
+
* The caller owns release/dependency qualification of expectedChecksum.
|
|
58
|
+
* Existing snapshots are preserved even when not yet bound to a RUN. */
|
|
59
|
+
export function installPackageEngine(context, input) {
|
|
60
|
+
if (!path.isAbsolute(input.packageRoot) || fs.realpathSync(input.packageRoot) !== input.packageRoot
|
|
61
|
+
|| !/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(input.packageName)
|
|
62
|
+
|| valid(input.version) !== input.version
|
|
63
|
+
|| !/^[a-f0-9]{64}$/.test(input.expectedChecksum)) {
|
|
64
|
+
throw new AppError("engine_install_failed", "Selected package requires a canonical root and independent content checksum", 1, { effect: "no_effect" });
|
|
65
|
+
}
|
|
66
|
+
const metadata = JSON.parse(readBoundedReleaseFile(path.join(input.packageRoot, "package.json"), 1024 * 1024).toString("utf8"));
|
|
67
|
+
if (metadata.name !== input.packageName || metadata.version !== input.version
|
|
68
|
+
|| snapshotFilesChecksum(packageSnapshotFiles(input.packageRoot)) !== input.expectedChecksum) {
|
|
69
|
+
throw new AppError("engine_install_failed", "Selected package identity or contents changed before delivery", 1, { effect: "no_effect" });
|
|
70
|
+
}
|
|
71
|
+
return installPackageSnapshot(context, input.packageRoot, input.packageName, input.version, { force: true, forRouting: true }, input.expectedChecksum, input.validateStaged).next().value;
|
|
72
|
+
}
|
|
73
|
+
function* installPackageSnapshot(context, packageRoot, packageName, version, input, expectedChecksum, validateStaged) {
|
|
74
|
+
const build = { package_name: packageName, version };
|
|
39
75
|
const target = engineVersionRoot(context.ddFlowHome, build.package_name, build.version);
|
|
40
76
|
const manifestPath = path.join(target, "engine.json");
|
|
41
77
|
const existing = readManifest(manifestPath);
|
|
@@ -66,14 +102,24 @@ export function installCurrentEngine(context, input = {}) {
|
|
|
66
102
|
const tmp = path.join(parent, `.${path.basename(target)}.tmp-${process.pid}-${Date.now()}`);
|
|
67
103
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
68
104
|
ensureDir(tmp);
|
|
105
|
+
publishSetup('probe_started', `engine-staging:${tmp}`);
|
|
69
106
|
copyPackageSnapshot(packageRoot, tmp);
|
|
70
107
|
const stagedManifest = buildManifest(context, build.package_name, build.version, packageRoot, target, tmp);
|
|
71
108
|
const stagedChecksum = stagedManifest.integrity.checksum;
|
|
109
|
+
if (expectedChecksum !== undefined && stagedChecksum !== expectedChecksum) {
|
|
110
|
+
throw new AppError("engine_install_failed", "Selected package changed during delivery", 1, { effect: "partial", path: tmp });
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
validateStaged?.(tmp);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
throw new AppError("engine_install_failed", "Staged package no longer matches its selected release", 1, { effect: "partial", path: tmp, reason: error instanceof AppError ? error.details.reason ?? error.code : "staged_selection_changed" });
|
|
117
|
+
}
|
|
72
118
|
const activationTarget = input.force
|
|
73
119
|
&& existing
|
|
74
120
|
&& stagedChecksum
|
|
75
121
|
&& stagedChecksum !== existing.integrity.checksum
|
|
76
|
-
&& engineIsBound(context.ddFlowHome, existing)
|
|
122
|
+
&& (expectedChecksum !== undefined || engineIsBound(context.ddFlowHome, existing))
|
|
77
123
|
? `${target}--${stagedChecksum}`
|
|
78
124
|
: target;
|
|
79
125
|
const duplicate = stagedChecksum ? findInstalledManifest(context.ddFlowHome, {
|
|
@@ -81,7 +127,7 @@ export function installCurrentEngine(context, input = {}) {
|
|
|
81
127
|
packageVersion: build.version,
|
|
82
128
|
integrityChecksum: stagedChecksum
|
|
83
129
|
}) : null;
|
|
84
|
-
if (duplicate) {
|
|
130
|
+
if (duplicate && manifestDiagnostics(duplicate, { checkEntrypoint: false }).length === 0) {
|
|
85
131
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
86
132
|
return {
|
|
87
133
|
ok: true,
|
|
@@ -94,13 +140,15 @@ export function installCurrentEngine(context, input = {}) {
|
|
|
94
140
|
const manifest = { ...stagedManifest, package_root: activationTarget, snapshot_root: activationTarget };
|
|
95
141
|
fs.writeFileSync(path.join(tmp, "engine.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
96
142
|
const checkedManifest = requireManifest(path.join(tmp, "engine.json"));
|
|
97
|
-
const stagedDiagnostics = manifestDiagnostics({ ...checkedManifest, package_root: tmp, snapshot_root: tmp }, { checkEntrypoint:
|
|
143
|
+
const stagedDiagnostics = manifestDiagnostics({ ...checkedManifest, package_root: tmp, snapshot_root: tmp }, { checkEntrypoint: false });
|
|
98
144
|
if (stagedDiagnostics.length > 0) {
|
|
99
145
|
throw new AppError("engine_install_failed", "Staged dd-flow engine failed its integrity or dependency health check", 1, {
|
|
100
146
|
diagnostics: stagedDiagnostics,
|
|
101
147
|
path: tmp
|
|
102
148
|
});
|
|
103
149
|
}
|
|
150
|
+
if (!input.forRouting)
|
|
151
|
+
yield { ...checkedManifest, package_root: tmp, snapshot_root: tmp };
|
|
104
152
|
activateEngineAtomically(tmp, activationTarget);
|
|
105
153
|
const installed = requireManifest(path.join(activationTarget, "engine.json"));
|
|
106
154
|
return {
|
|
@@ -117,7 +165,7 @@ export function installCurrentEngine(context, input = {}) {
|
|
|
117
165
|
}
|
|
118
166
|
export function listEngines(context) {
|
|
119
167
|
const root = engineStoreRoot(context.ddFlowHome);
|
|
120
|
-
const engines = readInstalledManifests(root).map(manifestSummary);
|
|
168
|
+
const engines = readInstalledManifests(root).map(manifest => manifestSummary(manifest));
|
|
121
169
|
return { ok: true, schema_id: "dd-flow/engine-list@1", engine_store: root, engines };
|
|
122
170
|
}
|
|
123
171
|
export function engineInfo(context, input) {
|
|
@@ -135,14 +183,23 @@ export function resolveEngine(context, input = {}) {
|
|
|
135
183
|
}
|
|
136
184
|
return { ok: true, schema_id: "dd-flow/engine-resolve@1", selection, contexts: compatibilityContexts(context, { ...input, classification }) };
|
|
137
185
|
}
|
|
138
|
-
export function doctorEngines(context, input = {}) {
|
|
186
|
+
export async function doctorEngines(context, input = {}) {
|
|
139
187
|
const root = engineStoreRoot(context.ddFlowHome);
|
|
140
188
|
const installed = readInstalledManifests(root);
|
|
141
|
-
const checks =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
189
|
+
const checks = [];
|
|
190
|
+
for (const manifest of installed) {
|
|
191
|
+
const diagnostics = manifestDiagnostics(manifest);
|
|
192
|
+
let probe_error;
|
|
193
|
+
if (!diagnostics.length)
|
|
194
|
+
try {
|
|
195
|
+
await probeEntrypoint(manifest, undefined, context.ddFlowHome, context.env);
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
probe_error = error instanceof AppError ? error.details : { message: String(error) };
|
|
199
|
+
diagnostics.push(error instanceof AppError && error.code === 'engine_probe_failed' ? 'entrypoint_dependency_load_failed' : 'entrypoint_probe_unavailable');
|
|
200
|
+
}
|
|
201
|
+
checks.push({ engine: manifestSummary(manifest, diagnostics), status: diagnostics.includes("entrypoint_probe_unavailable") ? "unverified" : diagnostics.length ? "corrupt" : "ok", diagnostics, ...(probe_error ? { probe_error } : {}) });
|
|
202
|
+
}
|
|
146
203
|
const classification = input.classification ?? classifyCliOperation(["engine", "doctor"], input.env ?? context.env);
|
|
147
204
|
const selection = selectEngine(context, input, {}, classification);
|
|
148
205
|
return {
|
|
@@ -155,7 +212,7 @@ export function doctorEngines(context, input = {}) {
|
|
|
155
212
|
exit_code: checks.every((check) => check.status === "ok") && selection.status === "selected" ? 0 : 1
|
|
156
213
|
};
|
|
157
214
|
}
|
|
158
|
-
export function routeArgsThroughEngine(context, args, io, stdin, env, resolvedProjectRoot) {
|
|
215
|
+
export async function routeArgsThroughEngine(context, args, io, stdin, env, resolvedProjectRoot) {
|
|
159
216
|
if (isEngineMode(env) || isRouterNativeCommand(args))
|
|
160
217
|
return Promise.resolve(null);
|
|
161
218
|
const classification = classifyCliOperation(args, env);
|
|
@@ -174,13 +231,18 @@ export function routeArgsThroughEngine(context, args, io, stdin, env, resolvedPr
|
|
|
174
231
|
if (!selection.selected)
|
|
175
232
|
return Promise.resolve(null);
|
|
176
233
|
const current = getCliBuildInfo();
|
|
177
|
-
|
|
234
|
+
const currentRoot = findPackageRoot(path.dirname(sourceFile));
|
|
235
|
+
if (selection.selected.package_name === current.package_name && selection.selected.package_version === current.version
|
|
236
|
+
&& currentRoot !== null && fs.realpathSync(selection.selected.snapshot_root) === fs.realpathSync(currentRoot)) {
|
|
178
237
|
return Promise.resolve({ routed: true, exitCode: 0, inProcess: true });
|
|
179
238
|
}
|
|
180
239
|
const entrypoint = resolveManifestEntrypoint(selection.selected);
|
|
240
|
+
// The admitted immutable entrypoint executes the requested operation itself.
|
|
241
|
+
// A separate --version process adds no operation-specific admission.
|
|
181
242
|
return spawnEngine(selection.selected, entrypoint, args, io, stdin, env, current.version);
|
|
182
243
|
}
|
|
183
|
-
export function
|
|
244
|
+
export async function prepareRunEngineBind(context, input) {
|
|
245
|
+
const reason = requiredText(input.reason, "reason");
|
|
184
246
|
const projectRoot = resolveProjectRoot(input.projectRoot);
|
|
185
247
|
const located = locateRunRoot(context.db, projectRoot, input.runId);
|
|
186
248
|
if (!located)
|
|
@@ -190,40 +252,43 @@ export function bindRunEngine(context, input) {
|
|
|
190
252
|
packageName: input.packageName ?? getCliBuildInfo().package_name,
|
|
191
253
|
packageVersion: input.engineVersion,
|
|
192
254
|
...(input.integrityChecksum ? { integrityChecksum: input.integrityChecksum } : {})
|
|
193
|
-
});
|
|
255
|
+
}, { checkEntrypoint: false });
|
|
194
256
|
const requested = engineIdentity(manifest);
|
|
195
257
|
if (existing) {
|
|
196
258
|
if (sameEngineIdentity(existing.engine, requested))
|
|
197
|
-
return {
|
|
259
|
+
return { kind: "replay", binding: existing };
|
|
198
260
|
throw new AppError("run_engine_binding_immutable", "RUN engine binding cannot be changed", 1, {
|
|
199
261
|
run_id: located.run_id,
|
|
200
262
|
current: existing.engine,
|
|
201
263
|
requested
|
|
202
264
|
});
|
|
203
265
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
266
|
+
await probeEntrypoint(manifest, ['run', 'status', located.run_id, '--project-root', projectRoot, '--json'], context.ddFlowHome, context.env, 'run_engine');
|
|
267
|
+
return { kind: "create", projectRoot, located, manifest, requested, reason, entrypoint: resolveManifestEntrypoint(manifest) };
|
|
268
|
+
}
|
|
269
|
+
export async function bindRunEngine(context, input, supplied) {
|
|
270
|
+
const prepared = supplied ?? await prepareRunEngineBind(context, input);
|
|
271
|
+
if (prepared.kind === "replay")
|
|
272
|
+
return { ok: true, action: "run_engine_bind", changed: false, binding: prepared.binding };
|
|
273
|
+
const { projectRoot, located, manifest, requested, reason } = prepared;
|
|
274
|
+
const current = locateRunRoot(context.db, projectRoot, input.runId);
|
|
275
|
+
if (!current || current.run_root !== located.run_root)
|
|
276
|
+
throw new AppError('run_engine_binding_conflict', 'RUN identity changed during probe', 1);
|
|
277
|
+
requireBoundManifest(context.ddFlowHome, { packageName: manifest.package_name, packageVersion: manifest.package_version, integrityChecksum: requested.integrity_checksum });
|
|
278
|
+
const existing = readRunEngineBinding(located.binding_path, { allowMissing: true });
|
|
279
|
+
if (existing) {
|
|
280
|
+
if (sameEngineIdentity(existing.engine, requested))
|
|
281
|
+
return { ok: true, action: "run_engine_bind", changed: false, binding: existing };
|
|
282
|
+
throw new AppError("run_engine_binding_immutable", "RUN engine binding cannot be changed", 1, { run_id: located.run_id, current: existing.engine, requested });
|
|
219
283
|
}
|
|
284
|
+
const probeArgs = ["run", "status", located.run_id, "--project-root", projectRoot, "--json"];
|
|
220
285
|
const binding = {
|
|
221
286
|
schema_id: runEngineBindingSchemaId,
|
|
222
287
|
run_id: located.run_id,
|
|
223
288
|
project_root: projectRoot,
|
|
224
289
|
bound_at: context.now(),
|
|
225
290
|
source: "legacy_recovery",
|
|
226
|
-
reason
|
|
291
|
+
reason,
|
|
227
292
|
engine: requested,
|
|
228
293
|
probe: { status: "passed", command: `dd-flow ${probeArgs.join(" ")}` }
|
|
229
294
|
};
|
|
@@ -252,9 +317,51 @@ export function bindCurrentEngineToRun(context, input) {
|
|
|
252
317
|
};
|
|
253
318
|
return writeRunEngineBinding(path.join(input.runRoot, "engine-binding.json"), binding).binding;
|
|
254
319
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
320
|
+
/** Forks are a new execution authority. The source binding stays immutable;
|
|
321
|
+
* this replaces only the copied binding after proving the selected engine can
|
|
322
|
+
* read the copied RUN. */
|
|
323
|
+
export async function upgradeForkedRunEngine(context, input) {
|
|
324
|
+
const projectRoot = resolveProjectRoot(input.projectRoot);
|
|
325
|
+
const located = locateRunRoot(context.db, projectRoot, input.runId);
|
|
326
|
+
if (!located)
|
|
327
|
+
throw new AppError("not_found", `Forked RUN is not registered: ${input.runId}`, 1);
|
|
328
|
+
const manifest = requireBoundManifest(context.ddFlowHome, {
|
|
329
|
+
packageName: getCliBuildInfo().package_name,
|
|
330
|
+
packageVersion: input.engineVersion,
|
|
331
|
+
...(input.integrityChecksum ? { integrityChecksum: input.integrityChecksum } : {})
|
|
332
|
+
});
|
|
333
|
+
const requested = engineIdentity(manifest);
|
|
334
|
+
const priorBinding = fs.readFileSync(located.binding_path, 'utf8');
|
|
335
|
+
const lineage = path.join(located.run_root, "fork-lineage.json");
|
|
336
|
+
if (!fs.existsSync(lineage))
|
|
337
|
+
throw new AppError("fork_lineage_missing", "Engine upgrade is permitted only for a derived RUN", 1, { run_id: located.run_id });
|
|
338
|
+
const probeArgs = ["run", "status", located.run_id, "--project-root", projectRoot, "--json"];
|
|
339
|
+
const priorLineage = fs.readFileSync(lineage, 'utf8');
|
|
340
|
+
await probeEntrypoint(manifest, probeArgs, context.ddFlowHome, context.env, 'fork_engine');
|
|
341
|
+
if (fs.readFileSync(located.binding_path, 'utf8') !== priorBinding || fs.readFileSync(lineage, 'utf8') !== priorLineage)
|
|
342
|
+
throw new AppError('fork_engine_binding_conflict', 'Fork identity changed during probe', 1);
|
|
343
|
+
requireBoundManifest(context.ddFlowHome, { packageName: manifest.package_name, packageVersion: manifest.package_version, integrityChecksum: manifest.integrity.checksum });
|
|
344
|
+
const binding = { schema_id: runEngineBindingSchemaId, run_id: located.run_id, project_root: projectRoot, bound_at: context.now(), source: "fork_upgrade", reason: requiredText(input.reason, "reason"), engine: requested, probe: { status: "passed", command: `dd-flow ${probeArgs.join(" ")}` } };
|
|
345
|
+
const temporary = `${located.binding_path}.fork-${process.pid}-${Date.now()}.tmp`;
|
|
346
|
+
fs.writeFileSync(temporary, `${JSON.stringify(binding, null, 2)}\n`);
|
|
347
|
+
fs.renameSync(temporary, located.binding_path);
|
|
348
|
+
return binding;
|
|
349
|
+
}
|
|
350
|
+
function boundRunEngineForArgs(context, args, projectRoot, options = {}) {
|
|
351
|
+
if (!projectRoot)
|
|
352
|
+
return null;
|
|
353
|
+
let runId = runIdForArgs(args);
|
|
354
|
+
const parsed = parseLightArgs(args), [family, command] = parsed.positional;
|
|
355
|
+
if (family === "work" && command !== "repair") {
|
|
356
|
+
const reference = option(parsed, "parent") ?? positional(parsed, command === "deps" ? 3 : 2);
|
|
357
|
+
if (reference) {
|
|
358
|
+
const project = context.db.get("SELECT id FROM projects WHERE root = ?", [canonicalPath(projectRoot, false)]);
|
|
359
|
+
if (!project)
|
|
360
|
+
return null;
|
|
361
|
+
runId = resolveWorkReference(context, reference, { projectId: project.id, runId }).run_id;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (!runId)
|
|
258
365
|
return null;
|
|
259
366
|
const located = locateRunRoot(context.db, projectRoot, runId);
|
|
260
367
|
if (!located)
|
|
@@ -262,22 +369,58 @@ function boundRunEngineForArgs(context, args, projectRoot) {
|
|
|
262
369
|
const binding = readRunEngineBinding(located.binding_path, { allowMissing: true });
|
|
263
370
|
if (!binding)
|
|
264
371
|
return null;
|
|
372
|
+
// SQL locates the current project; a restored binding retains its historical
|
|
373
|
+
// project_root bytes. Do not reinterpret that provenance as a live locator.
|
|
374
|
+
if (binding.run_id !== located.run_id)
|
|
375
|
+
throw new AppError("run_engine_binding_invalid", "RUN engine binding belongs to another scope", 1, { run_id: located.run_id });
|
|
265
376
|
const manifest = requireBoundManifest(context.ddFlowHome, {
|
|
266
377
|
packageName: binding.engine.package_name,
|
|
267
378
|
packageVersion: binding.engine.package_version,
|
|
268
379
|
integrityChecksum: binding.engine.integrity_checksum,
|
|
269
380
|
snapshotRoot: binding.engine.snapshot_root
|
|
270
|
-
});
|
|
381
|
+
}, options);
|
|
271
382
|
return { binding, manifest };
|
|
272
383
|
}
|
|
384
|
+
/** Detached RUN owners may be launched by a scope spanning several engines.
|
|
385
|
+
* Resolve the same retained pin as the public router before spawning directly. */
|
|
386
|
+
export function boundRunEngineEntrypoint(context, input) {
|
|
387
|
+
const bound = boundRunEngineForArgs(context, ["run", "status", input.runId], input.projectRoot);
|
|
388
|
+
if (!bound)
|
|
389
|
+
throw new AppError("run_engine_binding_missing", "Detached RUN ownership requires its retained engine", 1, { run_id: input.runId });
|
|
390
|
+
return resolveManifestEntrypoint(bound.manifest);
|
|
391
|
+
}
|
|
392
|
+
/** Routing already admitted the complete snapshot. Inside that executor the
|
|
393
|
+
* RUN pin, not a mutable project's old/new compatibility range, owns writes.
|
|
394
|
+
* Compare the actual physical module identity; environment aliases cannot
|
|
395
|
+
* impersonate another installed engine. No snapshot scan on each lease ACK.
|
|
396
|
+
*/
|
|
397
|
+
export function selectBoundExecutingEngine(context, args, projectRoot, env) {
|
|
398
|
+
if (!isEngineMode(env))
|
|
399
|
+
return null;
|
|
400
|
+
const bound = boundRunEngineForArgs(context, args, projectRoot, { verifyContent: false });
|
|
401
|
+
if (!bound)
|
|
402
|
+
return null;
|
|
403
|
+
const current = currentBuildManifest(context, getCliBuildInfo(), false);
|
|
404
|
+
if (!sameEngineIdentity(engineIdentity(current), bound.binding.engine))
|
|
405
|
+
throw new AppError("run_engine_binding_invalid", "Executing engine differs from the retained RUN pin", 1, { run_id: bound.binding.run_id });
|
|
406
|
+
return { status: "selected", package_name: current.package_name, required_range: `=${current.package_version}`,
|
|
407
|
+
recommended_version: current.package_version, selected: current, install_hint: null, project_root: projectRoot,
|
|
408
|
+
memory_bank_version: readCompatibilityForProject(projectRoot)?.memory_bank_version ?? null, diagnostics: [] };
|
|
409
|
+
}
|
|
273
410
|
function runIdForArgs(args) {
|
|
274
|
-
const [family, command, ...rest] =
|
|
275
|
-
const parsed =
|
|
411
|
+
const input = parseLightArgs(args), [family, command, ...rest] = input.positional;
|
|
412
|
+
const parsed = { ...input, positional: rest };
|
|
276
413
|
if (family === "run" && command !== "start" && command !== "list") {
|
|
277
|
-
if (command
|
|
414
|
+
if (["drive", "control"].includes(command ?? ""))
|
|
415
|
+
return option(parsed, "run");
|
|
416
|
+
if (["flags", "vars", "config", "recovery", "capacity"].includes(command ?? ""))
|
|
278
417
|
return positional(parsed, 1);
|
|
418
|
+
if (command === "snapshot")
|
|
419
|
+
return positional(parsed, 0) === "create" ? positional(parsed, 1) : null;
|
|
279
420
|
return positional(parsed, 0);
|
|
280
421
|
}
|
|
422
|
+
if (family === "stage" && ["fanout", "native"].includes(command ?? ""))
|
|
423
|
+
return positional(parsed, 1);
|
|
281
424
|
if (family === "stage" && command !== "start")
|
|
282
425
|
return positional(parsed, 0);
|
|
283
426
|
if (family === "stage" && command === "start" && !parsed.options.has("bootstrap"))
|
|
@@ -288,9 +431,9 @@ function runIdForArgs(args) {
|
|
|
288
431
|
return option(parsed, "run");
|
|
289
432
|
if (family === "protocol" && command === "sync-from-run")
|
|
290
433
|
return option(parsed, "run");
|
|
291
|
-
return
|
|
434
|
+
return option(parsed, "run");
|
|
292
435
|
}
|
|
293
|
-
function requireBoundManifest(ddFlowHome, input) {
|
|
436
|
+
function requireBoundManifest(ddFlowHome, input, options = {}) {
|
|
294
437
|
const manifest = input.snapshotRoot
|
|
295
438
|
? requireManifest(path.join(input.snapshotRoot, "engine.json"))
|
|
296
439
|
: findInstalledManifest(ddFlowHome, {
|
|
@@ -303,7 +446,7 @@ function requireBoundManifest(ddFlowHome, input) {
|
|
|
303
446
|
|| manifest.package_version !== input.packageVersion
|
|
304
447
|
|| input.integrityChecksum !== undefined && manifest.integrity.checksum !== input.integrityChecksum
|
|
305
448
|
|| input.snapshotRoot !== undefined && path.resolve(manifest.snapshot_root) !== path.resolve(input.snapshotRoot)
|
|
306
|
-
||
|
|
449
|
+
|| manifestDiagnostics(manifest, options).length !== 0) {
|
|
307
450
|
throw new AppError("run_engine_binding_invalid", "RUN engine binding points to a missing or unhealthy engine snapshot", 1, {
|
|
308
451
|
package_name: input.packageName,
|
|
309
452
|
package_version: input.packageVersion,
|
|
@@ -344,7 +487,7 @@ function executionManifest(context) {
|
|
|
344
487
|
return requireManifest(path.join(String(installed.path), "engine.json"));
|
|
345
488
|
}
|
|
346
489
|
function requiredText(value, label) {
|
|
347
|
-
const normalized = value.trim();
|
|
490
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
348
491
|
if (!normalized)
|
|
349
492
|
throw new AppError("usage", `Missing required value: ${label}`, 2);
|
|
350
493
|
return normalized;
|
|
@@ -380,14 +523,14 @@ export function selectEngine(context, input, options = {}, classification = inpu
|
|
|
380
523
|
const requiredRange = stringValue(compatibility?.engine?.version_range) ?? (classification.mode === "mb_upgrade" ? null : `>=${build.version} <9999.0.0`);
|
|
381
524
|
const recommended = stringValue(compatibility?.engine?.recommended_version) ?? build.version;
|
|
382
525
|
const installHintTemplate = stringValue(compatibility?.engine?.old_engine_install_hint) ?? `npx ${packageName}@<version> engine install`;
|
|
383
|
-
|
|
526
|
+
// An engine-mode caller already executes this module's build. Another
|
|
527
|
+
// installed engine cannot establish compatibility for its current writes.
|
|
528
|
+
// Keep full snapshot validation in routing/binding, not lease maintenance.
|
|
529
|
+
const executingCurrent = options.allowCurrentInProcess && isEngineMode(input.env ?? process.env);
|
|
530
|
+
const manifests = executingCurrent ? [] : readInstalledManifests(engineStoreRoot(context.ddFlowHome))
|
|
384
531
|
.filter((manifest) => manifest.package_name === packageName)
|
|
385
532
|
.filter((manifest) => requiredRange !== null && satisfiesRange(manifest.package_version, requiredRange))
|
|
386
|
-
.filter((manifest) =>
|
|
387
|
-
&& manifest.package_name === build.package_name
|
|
388
|
-
&& manifest.package_version === build.version
|
|
389
|
-
? true
|
|
390
|
-
: manifestHealthy(manifest))
|
|
533
|
+
.filter((manifest) => manifestHealthy(manifest))
|
|
391
534
|
.sort((a, b) => {
|
|
392
535
|
const versionOrder = compareSemverStrings(b.package_version, a.package_version);
|
|
393
536
|
if (versionOrder !== 0)
|
|
@@ -402,7 +545,7 @@ export function selectEngine(context, input, options = {}, classification = inpu
|
|
|
402
545
|
requiredRange !== null &&
|
|
403
546
|
packageName === build.package_name &&
|
|
404
547
|
satisfiesRange(build.version, requiredRange)
|
|
405
|
-
? currentBuildManifest(context, build)
|
|
548
|
+
? currentBuildManifest(context, build, options.verifyCurrentContent !== false)
|
|
406
549
|
: null);
|
|
407
550
|
const diagnostics = [
|
|
408
551
|
...targetBlockers,
|
|
@@ -420,9 +563,38 @@ export function selectEngine(context, input, options = {}, classification = inpu
|
|
|
420
563
|
diagnostics
|
|
421
564
|
};
|
|
422
565
|
}
|
|
423
|
-
function currentBuildManifest(context, build) {
|
|
566
|
+
function currentBuildManifest(context, build, verifyContent) {
|
|
424
567
|
const packageRoot = findPackageRoot(path.dirname(sourceFile)) ?? process.cwd();
|
|
425
|
-
|
|
568
|
+
const manifestFile = path.join(packageRoot, "engine.json");
|
|
569
|
+
const installedLayout = path.basename(path.dirname(path.dirname(packageRoot))) === "engines"
|
|
570
|
+
&& path.basename(path.dirname(packageRoot)) === path.basename(path.dirname(engineVersionRoot(context.ddFlowHome, build.package_name, build.version)));
|
|
571
|
+
if (fs.existsSync(manifestFile) || installedLayout) {
|
|
572
|
+
const installed = readManifest(manifestFile);
|
|
573
|
+
// Use the executing module's physical root, never an environment alias.
|
|
574
|
+
// A damaged installed manifest must not become a development fallback.
|
|
575
|
+
if (!installed || installed.package_name !== build.package_name || installed.package_version !== build.version
|
|
576
|
+
|| installed.engine_version !== build.version || installed.engine_id !== "dd-flow-engine"
|
|
577
|
+
|| typeof installed.snapshot_root !== "string" || !fs.existsSync(installed.snapshot_root)
|
|
578
|
+
|| fs.realpathSync(installed.snapshot_root) !== fs.realpathSync(packageRoot)
|
|
579
|
+
|| typeof installed.entrypoint !== "string" || installed.integrity?.source !== "package_snapshot"
|
|
580
|
+
|| typeof installed.integrity?.checksum !== "string" || !/^[a-f0-9]{64}$/.test(installed.integrity.checksum)
|
|
581
|
+
|| (installed.schema_registry && (!Array.isArray(installed.schema_registry.entries)
|
|
582
|
+
|| installed.schema_registry.entries.some(entry => !entry || typeof entry.path !== "string"
|
|
583
|
+
|| typeof entry.id !== "string" || typeof entry.name !== "string" || !/^[a-f0-9]{64}$/.test(entry.checksum ?? ""))))) {
|
|
584
|
+
throw new AppError("unhealthy_engine", "Executing engine snapshot manifest does not match its build", 1, { manifest: manifestFile });
|
|
585
|
+
}
|
|
586
|
+
const diagnostics = manifestDiagnostics(installed, { checkEntrypoint: false, verifyContent });
|
|
587
|
+
if (diagnostics.length)
|
|
588
|
+
throw new AppError("unhealthy_engine", "Executing engine snapshot is unhealthy", 1, { manifest: manifestFile, diagnostics });
|
|
589
|
+
return installed;
|
|
590
|
+
}
|
|
591
|
+
// Only an unmaterialized package has no snapshot proof. Canon and
|
|
592
|
+
// package-manager aliases are expected in development checkouts.
|
|
593
|
+
const manifest = buildManifest(context, build.package_name, build.version, packageRoot, packageRoot, packageRoot, null);
|
|
594
|
+
// An ephemeral routing choice has no snapshot proof. Hash bytes only when
|
|
595
|
+
// materializing/validating an installed snapshot, never on every CLI call.
|
|
596
|
+
manifest.integrity.mode = "degraded_local_development";
|
|
597
|
+
return manifest;
|
|
426
598
|
}
|
|
427
599
|
export function compatibilityContexts(context, input = {}) {
|
|
428
600
|
const env = input.env ?? process.env;
|
|
@@ -560,40 +732,16 @@ function canonCompatibilitySha(memorybankRoot) {
|
|
|
560
732
|
return null;
|
|
561
733
|
}
|
|
562
734
|
}
|
|
563
|
-
|
|
564
|
-
const positional = [];
|
|
565
|
-
const options = new Map();
|
|
566
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
567
|
-
const value = args[index];
|
|
568
|
-
if (value?.startsWith("--")) {
|
|
569
|
-
const equal = value.indexOf("=");
|
|
570
|
-
if (equal > 2) {
|
|
571
|
-
const key = value.slice(2, equal);
|
|
572
|
-
options.set(key, [...(options.get(key) ?? []), value.slice(equal + 1)]);
|
|
573
|
-
continue;
|
|
574
|
-
}
|
|
575
|
-
const key = value.slice(2);
|
|
576
|
-
const next = args[index + 1];
|
|
577
|
-
if (!next || next.startsWith("--"))
|
|
578
|
-
options.set(key, [...(options.get(key) ?? []), ""]);
|
|
579
|
-
else {
|
|
580
|
-
options.set(key, [...(options.get(key) ?? []), next]);
|
|
581
|
-
index += 1;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
else if (value)
|
|
585
|
-
positional.push(value);
|
|
586
|
-
}
|
|
587
|
-
return { positional, options };
|
|
588
|
-
}
|
|
735
|
+
const parseLightArgs = parseCommandArgs;
|
|
589
736
|
function option(parsed, key) {
|
|
590
737
|
const values = parsed.options.get(key);
|
|
591
|
-
|
|
738
|
+
const value = values?.[values.length - 1];
|
|
739
|
+
return value && value !== "__dd_flow_flag__" ? value : null;
|
|
592
740
|
}
|
|
593
741
|
function positional(parsed, index) {
|
|
594
742
|
return parsed.positional[index] ?? null;
|
|
595
743
|
}
|
|
596
|
-
function buildManifest(context, packageName, version, packageRoot, snapshotRoot, checksumRoot) {
|
|
744
|
+
function buildManifest(context, packageName, version, packageRoot, snapshotRoot, checksumRoot, checksum = engineSnapshotChecksum(checksumRoot)) {
|
|
597
745
|
return {
|
|
598
746
|
schema_id: engineManifestSchemaId,
|
|
599
747
|
package_name: packageName,
|
|
@@ -609,35 +757,54 @@ function buildManifest(context, packageName, version, packageRoot, snapshotRoot,
|
|
|
609
757
|
supports_contracts: {
|
|
610
758
|
compatibility: ["dd-flow/compatibility@1"],
|
|
611
759
|
version: ["dd-flow/version-report@1"],
|
|
612
|
-
status: ["dd-flow/status-report@1"]
|
|
760
|
+
status: ["dd-flow/status-report@1"],
|
|
761
|
+
hybrid: ["dd-flow/flow-descriptor@1", "dd-flow/execution-settings@1", "dd-flow/execution-bundle@1", "dd-flow/memory-bootstrap-receipt@2"]
|
|
613
762
|
},
|
|
614
763
|
schema_registry: buildSchemaRegistry(checksumRoot),
|
|
615
764
|
integrity: {
|
|
616
765
|
source: "package_snapshot",
|
|
617
|
-
checksum
|
|
766
|
+
checksum,
|
|
618
767
|
mode: "full_content"
|
|
619
768
|
}
|
|
620
769
|
};
|
|
621
770
|
}
|
|
622
771
|
function copyPackageSnapshot(packageRoot, target) {
|
|
772
|
+
let copied = 0;
|
|
773
|
+
for (const [relative, source] of packageSnapshotFiles(packageRoot)) {
|
|
774
|
+
const destination = path.join(target, relative);
|
|
775
|
+
ensureDir(path.dirname(destination));
|
|
776
|
+
fs.copyFileSync(source, destination);
|
|
777
|
+
if (++copied % 64 === 0)
|
|
778
|
+
publishSetup('transfer_progress', `${target}:${copied}`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
/** The same source inventory drives validation and copying; no staging writes. */
|
|
782
|
+
export function packageSnapshotFiles(packageRoot) {
|
|
783
|
+
const files = new Map();
|
|
784
|
+
const collect = (source, relative, skipNodeModules = false) => {
|
|
785
|
+
if (!fs.statSync(source).isDirectory()) {
|
|
786
|
+
files.set(relative, source);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
|
|
790
|
+
if (skipNodeModules && entry.name === "node_modules")
|
|
791
|
+
continue;
|
|
792
|
+
const child = path.join(source, entry.name), name = path.join(relative, entry.name);
|
|
793
|
+
if (entry.isDirectory())
|
|
794
|
+
collect(child, name, skipNodeModules);
|
|
795
|
+
else if (entry.isFile())
|
|
796
|
+
files.set(name, child);
|
|
797
|
+
}
|
|
798
|
+
};
|
|
623
799
|
for (const item of ["dist", "package.json", "README.md", "CHANGELOG.md", "tools"]) {
|
|
624
800
|
const from = path.join(packageRoot, item);
|
|
625
801
|
if (!fs.existsSync(from))
|
|
626
802
|
continue;
|
|
627
|
-
|
|
628
|
-
const stat = fs.statSync(from);
|
|
629
|
-
if (stat.isDirectory())
|
|
630
|
-
copyDir(from, to);
|
|
631
|
-
else {
|
|
632
|
-
ensureDir(path.dirname(to));
|
|
633
|
-
fs.copyFileSync(from, to);
|
|
634
|
-
}
|
|
803
|
+
collect(from, item);
|
|
635
804
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const queue = [{ sourceRoot: packageRoot, targetRoot: target, ancestors: new Set() }];
|
|
640
|
-
const copied = new Set();
|
|
805
|
+
const queue = [{ sourceRoot: packageRoot, targetRoot: "" }];
|
|
806
|
+
const placed = new Map();
|
|
807
|
+
const virtualRoot = path.resolve(path.sep, "dd-flow-snapshot");
|
|
641
808
|
while (queue.length > 0) {
|
|
642
809
|
const current = queue.shift();
|
|
643
810
|
if (!current)
|
|
@@ -646,17 +813,48 @@ function copyProductionDependencies(packageRoot, target) {
|
|
|
646
813
|
const sourceRoot = resolvePackageRoot(dependency, current.sourceRoot);
|
|
647
814
|
if (!sourceRoot)
|
|
648
815
|
throw new AppError("engine_install_failed", `Cannot resolve runtime dependency: ${dependency}`, 1);
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
816
|
+
// Standard Node lookup permits hoisting identical selected packages.
|
|
817
|
+
// Copying a shared DAG under every parent makes SDK snapshots grow
|
|
818
|
+
// exponentially; conflicting versions still need their own local slot.
|
|
819
|
+
const search = createRequire(path.join(virtualRoot, current.targetRoot, "package.json")).resolve.paths(dependency) ?? [];
|
|
820
|
+
const candidates = search.filter(directory => directory.startsWith(`${virtualRoot}${path.sep}`))
|
|
821
|
+
.map(directory => path.relative(virtualRoot, path.join(directory, dependency)));
|
|
822
|
+
const existing = candidates.find(candidate => placed.has(candidate));
|
|
823
|
+
if (existing && placed.get(existing) === sourceRoot)
|
|
656
824
|
continue;
|
|
657
|
-
|
|
825
|
+
const targetRoot = existing ? path.join(current.targetRoot, "node_modules", dependency) : path.join("node_modules", dependency);
|
|
826
|
+
placed.set(targetRoot, sourceRoot);
|
|
827
|
+
collect(sourceRoot, targetRoot, true);
|
|
828
|
+
queue.push({ sourceRoot, targetRoot });
|
|
658
829
|
}
|
|
659
830
|
}
|
|
831
|
+
return files;
|
|
832
|
+
}
|
|
833
|
+
export function prepareForkEngine(engineVersion, integrityChecksum) {
|
|
834
|
+
const build = getCliBuildInfo();
|
|
835
|
+
if (engineVersion !== build.version)
|
|
836
|
+
throw new AppError("fork_engine_unavailable", "Fork installs the invoking CLI engine; invoke the requested version to upgrade the fork", 2, { requested: engineVersion, available: build.version });
|
|
837
|
+
const packageRoot = findPackageRoot(path.dirname(sourceFile));
|
|
838
|
+
if (!packageRoot || !fs.existsSync(path.join(packageRoot, "dist", "cli.js")))
|
|
839
|
+
throw new AppError("harness_runtime_unbuilt", "Build the CLI before preparing a fork", 1);
|
|
840
|
+
const files = packageSnapshotFiles(packageRoot);
|
|
841
|
+
if (integrityChecksum !== undefined) {
|
|
842
|
+
const checksum = snapshotFilesChecksum(files);
|
|
843
|
+
if (checksum !== integrityChecksum)
|
|
844
|
+
throw new AppError("fork_engine_unavailable", "Requested engine checksum differs from the invoking CLI artifact", 2, { requested: integrityChecksum });
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
function snapshotFilesChecksum(files) {
|
|
848
|
+
const checksum = crypto.createHash("sha256");
|
|
849
|
+
for (const [relative, source] of [...files].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
|
|
850
|
+
if (path.basename(relative) === "engine.json")
|
|
851
|
+
continue;
|
|
852
|
+
checksum.update(relative);
|
|
853
|
+
checksum.update("\0");
|
|
854
|
+
checksum.update(fs.readFileSync(source));
|
|
855
|
+
checksum.update("\0");
|
|
856
|
+
}
|
|
857
|
+
return checksum.digest("hex");
|
|
660
858
|
}
|
|
661
859
|
function readProductionDependencies(packageRoot) {
|
|
662
860
|
try {
|
|
@@ -676,20 +874,14 @@ function readProductionDependencies(packageRoot) {
|
|
|
676
874
|
}
|
|
677
875
|
}
|
|
678
876
|
function resolvePackageRoot(name, from) {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
if (parent === current)
|
|
686
|
-
return null;
|
|
687
|
-
current = parent;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
catch {
|
|
691
|
-
return null;
|
|
877
|
+
// Inspect package roots through Node's lookup paths, not the require entry:
|
|
878
|
+
// production dependencies can expose only an ESM import condition.
|
|
879
|
+
for (const directory of createRequire(path.join(from, "package.json")).resolve.paths(name) ?? []) {
|
|
880
|
+
const candidate = path.join(directory, name);
|
|
881
|
+
if (fs.existsSync(path.join(candidate, "package.json")))
|
|
882
|
+
return fs.realpathSync(candidate);
|
|
692
883
|
}
|
|
884
|
+
return null;
|
|
693
885
|
}
|
|
694
886
|
function inferInstallSource(packageRoot, ddFlowHome) {
|
|
695
887
|
const normalized = path.resolve(packageRoot);
|
|
@@ -713,19 +905,6 @@ function hasAncestorFile(start, name) {
|
|
|
713
905
|
current = parent;
|
|
714
906
|
}
|
|
715
907
|
}
|
|
716
|
-
function copyDir(from, to, skipNodeModules = false) {
|
|
717
|
-
ensureDir(to);
|
|
718
|
-
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
719
|
-
if (skipNodeModules && entry.name === "node_modules")
|
|
720
|
-
continue;
|
|
721
|
-
const source = path.join(from, entry.name);
|
|
722
|
-
const target = path.join(to, entry.name);
|
|
723
|
-
if (entry.isDirectory())
|
|
724
|
-
copyDir(source, target, skipNodeModules);
|
|
725
|
-
else if (entry.isFile())
|
|
726
|
-
fs.copyFileSync(source, target);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
908
|
function acquireInstallLock(lockDir) {
|
|
730
909
|
ensureDir(path.dirname(lockDir));
|
|
731
910
|
try {
|
|
@@ -750,6 +929,9 @@ function readInstalledManifests(root) {
|
|
|
750
929
|
if (!fs.statSync(packageRoot).isDirectory())
|
|
751
930
|
continue;
|
|
752
931
|
for (const versionDir of fs.readdirSync(packageRoot)) {
|
|
932
|
+
// Failed staging, activation backups and locks are not installations.
|
|
933
|
+
if (versionDir.startsWith(".") || /\.previous-\d+-\d+$/.test(versionDir) || versionDir.endsWith(".lock"))
|
|
934
|
+
continue;
|
|
753
935
|
const manifest = readManifest(path.join(packageRoot, versionDir, "engine.json"));
|
|
754
936
|
if (manifest)
|
|
755
937
|
manifests.push(manifest);
|
|
@@ -802,7 +984,7 @@ function manifestDiagnostics(manifest, options = {}) {
|
|
|
802
984
|
if (!manifest.integrity || manifest.integrity.mode !== "full_content" || !manifest.integrity.checksum) {
|
|
803
985
|
diagnostics.push("content_checksum_missing");
|
|
804
986
|
}
|
|
805
|
-
else if (fs.existsSync(snapshotRoot)) {
|
|
987
|
+
else if (options.verifyContent !== false && fs.existsSync(snapshotRoot)) {
|
|
806
988
|
try {
|
|
807
989
|
if (engineSnapshotChecksum(snapshotRoot) !== manifest.integrity.checksum)
|
|
808
990
|
diagnostics.push("content_checksum_mismatch");
|
|
@@ -816,6 +998,8 @@ function manifestDiagnostics(manifest, options = {}) {
|
|
|
816
998
|
const schemaPath = safeResolveSnapshotPath(manifest, entry.path);
|
|
817
999
|
if (!schemaPath || !fs.existsSync(schemaPath))
|
|
818
1000
|
diagnostics.push(`schema_registry_missing:${entry.name}`);
|
|
1001
|
+
else if (options.verifyContent === false)
|
|
1002
|
+
continue;
|
|
819
1003
|
else if (fileChecksum(schemaPath) !== entry.checksum)
|
|
820
1004
|
diagnostics.push(`schema_registry_checksum_mismatch:${entry.name}`);
|
|
821
1005
|
else {
|
|
@@ -829,25 +1013,21 @@ function manifestDiagnostics(manifest, options = {}) {
|
|
|
829
1013
|
}
|
|
830
1014
|
}
|
|
831
1015
|
}
|
|
832
|
-
if (options.checkEntrypoint !== false && entrypoint && fs.existsSync(entrypoint) && !diagnostics.includes("entrypoint_outside_snapshot")) {
|
|
833
|
-
const health = spawnSync(process.execPath, [entrypoint, "--version", "--json"], {
|
|
834
|
-
cwd: snapshotRoot,
|
|
835
|
-
env: {
|
|
836
|
-
...process.env,
|
|
837
|
-
DD_FLOW_ENGINE_MODE: "1",
|
|
838
|
-
DD_FLOW_ENGINE_HOME: snapshotRoot,
|
|
839
|
-
DD_FLOW_ENGINE_HEALTHCHECK: "1"
|
|
840
|
-
},
|
|
841
|
-
encoding: "utf8",
|
|
842
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
843
|
-
timeout: 15_000
|
|
844
|
-
});
|
|
845
|
-
if (health.status !== 0)
|
|
846
|
-
diagnostics.push("entrypoint_dependency_load_failed");
|
|
847
|
-
}
|
|
848
1016
|
return diagnostics;
|
|
849
1017
|
}
|
|
850
|
-
function
|
|
1018
|
+
async function probeEntrypoint(manifest, args = ['--version', '--json'], runtimeHome, env = {}, purpose = 'engine') {
|
|
1019
|
+
publishSetup('probe_started', manifest.snapshot_root);
|
|
1020
|
+
try {
|
|
1021
|
+
await commandText(resolveManifestEntrypoint(manifest), args, { cwd: manifest.snapshot_root,
|
|
1022
|
+
env: { ...env, DD_FLOW_ENGINE_MODE: '1', DD_FLOW_ENGINE_HOME: manifest.snapshot_root, ...(runtimeHome ? { DD_FLOW_HOME: runtimeHome } : {}), ...(args[0] === '--version' ? { DD_FLOW_ENGINE_HEALTHCHECK: '1' } : {}) }, startupMs: SETUP_STARTUP_MS, phase: 'engine-probe' });
|
|
1023
|
+
publishSetup('probe_completed', manifest.snapshot_root);
|
|
1024
|
+
}
|
|
1025
|
+
catch (cause) {
|
|
1026
|
+
const error = cause;
|
|
1027
|
+
throw new AppError(error.details?.reason === 'child_exit' && error.details?.signal === null && error.details?.exit_code !== null ? `${purpose}_probe_failed` : `${purpose}_probe_unavailable`, 'Selected engine probe did not complete successfully', 1, { cause: error.code, message: error.message, ...error.details });
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function manifestSummary(manifest, diagnostics = manifestDiagnostics(manifest, { checkEntrypoint: false })) {
|
|
851
1031
|
return {
|
|
852
1032
|
schema_id: manifest.schema_id,
|
|
853
1033
|
package_name: manifest.package_name,
|
|
@@ -859,8 +1039,8 @@ function manifestSummary(manifest) {
|
|
|
859
1039
|
snapshot_root: manifest.snapshot_root,
|
|
860
1040
|
resolved_entrypoint: safeResolveManifestEntrypoint(manifest),
|
|
861
1041
|
installed_at: manifest.installed_at,
|
|
862
|
-
healthy:
|
|
863
|
-
diagnostics
|
|
1042
|
+
healthy: diagnostics.length === 0,
|
|
1043
|
+
diagnostics
|
|
864
1044
|
};
|
|
865
1045
|
}
|
|
866
1046
|
function resolveManifestEntrypoint(manifest) {
|
|
@@ -916,7 +1096,6 @@ function spawnEngine(manifest, entrypoint, args, io, stdin, env, routedFromVersi
|
|
|
916
1096
|
return new Promise((resolve, reject) => {
|
|
917
1097
|
const child = spawn(process.execPath, [entrypoint, ...args], {
|
|
918
1098
|
env: {
|
|
919
|
-
...process.env,
|
|
920
1099
|
...env,
|
|
921
1100
|
DD_FLOW_ENGINE_MODE: "1",
|
|
922
1101
|
DD_FLOW_ENGINE_HOME: manifest.snapshot_root,
|
|
@@ -1010,23 +1189,35 @@ function findPackageRoot(start) {
|
|
|
1010
1189
|
current = parent;
|
|
1011
1190
|
}
|
|
1012
1191
|
}
|
|
1192
|
+
let checksumScanOrdinal = 0;
|
|
1013
1193
|
export function engineSnapshotChecksum(root) {
|
|
1194
|
+
// A CLI can legitimately revalidate the same snapshot at several boundaries.
|
|
1195
|
+
// Distinguish actual scans without making duplicate phase notifications progress.
|
|
1196
|
+
const scan = `engine-digest:${root}:scan-${++checksumScanOrdinal}`;
|
|
1197
|
+
publishSetup('probe_started', scan);
|
|
1014
1198
|
const files = [];
|
|
1015
1199
|
collectFiles(root, root, files);
|
|
1016
1200
|
const checksum = crypto.createHash("sha256");
|
|
1201
|
+
let checked = 0;
|
|
1017
1202
|
for (const file of files.sort()) {
|
|
1018
1203
|
checksum.update(file);
|
|
1019
1204
|
checksum.update("\0");
|
|
1020
1205
|
checksum.update(fs.readFileSync(path.join(root, file)));
|
|
1206
|
+
if (++checked % 64 === 0)
|
|
1207
|
+
publishSetup('identity_digest_progress', `${scan}:${checked}`);
|
|
1021
1208
|
checksum.update("\0");
|
|
1022
1209
|
}
|
|
1023
|
-
|
|
1210
|
+
const result = checksum.digest("hex");
|
|
1211
|
+
publishSetup('identity_digest_completed', scan);
|
|
1212
|
+
return result;
|
|
1024
1213
|
}
|
|
1025
1214
|
function collectFiles(root, current, files) {
|
|
1026
1215
|
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
1027
1216
|
if (entry.name === "engine.json")
|
|
1028
1217
|
continue;
|
|
1029
1218
|
const full = path.join(current, entry.name);
|
|
1219
|
+
if (entry.isSymbolicLink())
|
|
1220
|
+
throw new AppError("engine_integrity_symlink", "Pinned engine snapshot contains an unhashed symbolic link", 1, { path: path.relative(root, full) });
|
|
1030
1221
|
if (entry.isDirectory())
|
|
1031
1222
|
collectFiles(root, full, files);
|
|
1032
1223
|
else if (entry.isFile())
|