@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.151
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 +907 -0
- package/README.md +139 -10
- 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 +79 -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/agy-terminal-envelope.mjs +67 -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 +1092 -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 +627 -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 +1200 -0
- package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
- package/dist/harness-runtime/lib/delegation-instructions.mjs +166 -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 +113 -0
- package/dist/harness-runtime/lib/native-children.d.mts +34 -0
- package/dist/harness-runtime/lib/native-children.mjs +265 -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 +23 -0
- package/dist/harness-runtime/lib/provider-overload-policy.mjs +242 -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 +277 -0
- package/dist/services/check-runner-proof.js +305 -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 +1401 -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 +71 -0
- package/dist/services/controller-child-observer.js +121 -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 +463 -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 +1395 -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 +240 -18
- 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/dist/verification-components.json +299 -0
- package/package.json +51 -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
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import { AppError, isAppError } from "../shared/errors.js";
|
|
5
|
+
import { validateSchema } from "../services/schema-validation.js";
|
|
6
|
+
export function prepareError(error, input = {}) {
|
|
7
|
+
if (isAppError(error)) {
|
|
8
|
+
// A malformed user input is safely correctable. A broken schema registry,
|
|
9
|
+
// binding, or storage is not; do not disguise infrastructure damage as a
|
|
10
|
+
// retryable command typo.
|
|
11
|
+
const inputErrorCodes = new Set([
|
|
12
|
+
"usage", "validation", "schema_validation", "invalid_json", "not_found",
|
|
13
|
+
"path_escape", "input_file_missing", "input_file_not_regular", "input_file_unreadable",
|
|
14
|
+
"response_file_parent_invalid", "response_file_invalid", "context_checksum_mismatch", "invalid_run_config_state", "invalid_work_state", "invalid_stage_state", "runtime_budget_invalid", "runtime_scope_manifest_invalid", "runtime_scope_resume_invalid",
|
|
15
|
+
"fork_path_conflict", "fork_output_not_empty", "fork_checkpoint_invalid", "fork_engine_unavailable", "snapshot_missing",
|
|
16
|
+
"repair_check_declaration_missing", "review_repair_check_required", "review_check_reference_unknown", "semantic_status_inconsistent", "migration_report_invalid", "controller_context_missing", "snapshot_output_inside_runtime"
|
|
17
|
+
]);
|
|
18
|
+
if (!inputErrorCodes.has(error.code) && error.details.phase !== "prepare")
|
|
19
|
+
throw error;
|
|
20
|
+
throw new AppError(error.code, error.message, 2, {
|
|
21
|
+
...error.details,
|
|
22
|
+
phase: "prepare",
|
|
23
|
+
effect: error.details.effect ?? "no_effect",
|
|
24
|
+
recoverable: error.details.recoverable ?? true,
|
|
25
|
+
...input
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const code = error?.code;
|
|
29
|
+
if (typeof input.file !== "string" || !["ENOENT", "EACCES", "EPERM", "EISDIR", "ENOTDIR", "ELOOP", "ENAMETOOLONG"].includes(code ?? ""))
|
|
30
|
+
throw error;
|
|
31
|
+
throw new AppError("input_file_unreadable", `Cannot read input file${typeof input.file === "string" ? `: ${input.file}` : ""}`, 2, {
|
|
32
|
+
phase: "prepare", effect: "no_effect", recoverable: true, ...input, cause: code ?? String(error)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export function prepareTextFile(file, label = "input file", maxBytes) {
|
|
36
|
+
const prepared = prepareFileBytes(file, label, maxBytes);
|
|
37
|
+
if (maxBytes === undefined)
|
|
38
|
+
return { file: prepared.file, text: prepared.bytes.toString("utf8") };
|
|
39
|
+
try {
|
|
40
|
+
return { file: prepared.file, text: new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(prepared.bytes) };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return prepareError(new AppError("validation", `${label} must contain valid UTF-8`, 2), { file: prepared.file, label });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function readBoundedUtf8Stream(stream, maxBytes) {
|
|
47
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
48
|
+
throw new AppError("usage", "Invalid input byte bound", 2);
|
|
49
|
+
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
50
|
+
let data = "", byteLength = 0;
|
|
51
|
+
for await (const chunk of stream) {
|
|
52
|
+
const bytes = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
53
|
+
byteLength += bytes.length;
|
|
54
|
+
if (byteLength > maxBytes)
|
|
55
|
+
throw new AppError("usage", "Standard input exceeds its byte bound", 2);
|
|
56
|
+
try {
|
|
57
|
+
data += decoder.decode(bytes, { stream: true });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new AppError("validation", "Standard input must contain valid UTF-8", 2);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return data + decoder.decode();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new AppError("validation", "Standard input must contain valid UTF-8", 2);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function prepareFileBytes(file, label = "input file", maxBytes) {
|
|
71
|
+
const absolute = path.resolve(file);
|
|
72
|
+
let descriptor;
|
|
73
|
+
try {
|
|
74
|
+
descriptor = fs.openSync(absolute, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);
|
|
75
|
+
const stat = fs.fstatSync(descriptor);
|
|
76
|
+
if (!stat.isFile()) {
|
|
77
|
+
throw new AppError("input_file_not_regular", `${label} must be a readable regular file: ${absolute}`, 2, { file: absolute, label });
|
|
78
|
+
}
|
|
79
|
+
if (maxBytes === undefined)
|
|
80
|
+
return { file: absolute, bytes: fs.readFileSync(descriptor) };
|
|
81
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
82
|
+
throw new AppError("usage", "Invalid input byte bound", 2);
|
|
83
|
+
const oversized = () => new AppError("usage", `${label} exceeds its byte bound`, 2);
|
|
84
|
+
if (stat.size > maxBytes)
|
|
85
|
+
throw oversized();
|
|
86
|
+
// Read at most one extra byte: the file can grow after fstat.
|
|
87
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
88
|
+
let length = 0;
|
|
89
|
+
while (length < buffer.length) {
|
|
90
|
+
const count = fs.readSync(descriptor, buffer, length, buffer.length - length, null);
|
|
91
|
+
if (!count)
|
|
92
|
+
break;
|
|
93
|
+
length += count;
|
|
94
|
+
}
|
|
95
|
+
if (length > maxBytes)
|
|
96
|
+
throw oversized();
|
|
97
|
+
return { file: absolute, bytes: buffer.subarray(0, length) };
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (error?.code === "ENOENT") {
|
|
101
|
+
throw new AppError("input_file_missing", `${label} does not exist: ${absolute}`, 2, {
|
|
102
|
+
phase: "prepare", effect: "no_effect", recoverable: true, file: absolute, label
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return prepareError(error, { file: absolute, label });
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
if (descriptor !== undefined)
|
|
109
|
+
fs.closeSync(descriptor);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function prepareJsonText(text, input) {
|
|
113
|
+
try {
|
|
114
|
+
return { file: input.file, text, value: JSON.parse(text) };
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Keep the established public code so agents can recognise this as a
|
|
118
|
+
// safe correction-and-retry condition.
|
|
119
|
+
throw new AppError("invalid_json", `Invalid JSON in ${input.label ?? "input"}: ${input.file}`, 2, {
|
|
120
|
+
phase: "prepare", effect: "no_effect", recoverable: true, file: input.file, label: input.label ?? "input",
|
|
121
|
+
cause: "Invalid JSON syntax", input_sha256: crypto.createHash("sha256").update(text).digest("hex")
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export function prepareJsonFile(file, label = "input JSON") {
|
|
126
|
+
const prepared = prepareTextFile(file, label);
|
|
127
|
+
return prepareJsonText(prepared.text, { file: prepared.file, label });
|
|
128
|
+
}
|
|
129
|
+
export function prepareJsonSchema(file, label, schema) {
|
|
130
|
+
const prepared = prepareJsonFile(file, label);
|
|
131
|
+
try {
|
|
132
|
+
validateSchema({ ...schema, file: prepared.file, data: prepared.value });
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return prepareError(error, { file: prepared.file, label });
|
|
136
|
+
}
|
|
137
|
+
return prepared;
|
|
138
|
+
}
|
|
139
|
+
/** Read-only destination check; execution still handles filesystem races. */
|
|
140
|
+
export function prepareOutputFile(value) { return prepareOutput(value, false); }
|
|
141
|
+
export function prepareOutputDirectory(value) { return prepareOutput(value, true); }
|
|
142
|
+
function prepareOutput(value, directory) {
|
|
143
|
+
const file = path.resolve(value);
|
|
144
|
+
try {
|
|
145
|
+
let ancestor = directory ? file : path.dirname(file);
|
|
146
|
+
while (!fs.existsSync(ancestor) && path.dirname(ancestor) !== ancestor)
|
|
147
|
+
ancestor = path.dirname(ancestor);
|
|
148
|
+
if (!fs.statSync(ancestor).isDirectory())
|
|
149
|
+
throw new AppError("validation", "Output parent must be a directory", 2);
|
|
150
|
+
fs.accessSync(ancestor, fs.constants.W_OK | fs.constants.X_OK);
|
|
151
|
+
if (fs.existsSync(file)) {
|
|
152
|
+
const stat = fs.statSync(file);
|
|
153
|
+
if (directory ? !stat.isDirectory() : !stat.isFile())
|
|
154
|
+
throw new AppError("validation", directory ? "Output must name a directory" : "Output must name a regular file", 2);
|
|
155
|
+
fs.accessSync(file, fs.constants.W_OK | (directory ? fs.constants.X_OK : 0));
|
|
156
|
+
}
|
|
157
|
+
return file;
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
const code = error?.code;
|
|
161
|
+
if (["ENOENT", "EACCES", "EPERM", "ENOTDIR", "ELOOP", "ENAMETOOLONG"].includes(code ?? ""))
|
|
162
|
+
return prepareError(new AppError("validation", "Output destination is not writable or has an invalid parent", 2, { cause: code }), { file, parameter: "output" });
|
|
163
|
+
return prepareError(error, { file, parameter: "output" });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
2
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
3
|
+
import { readBoundedUtf8Stream, prepareJsonText } from "./input-preparation.js";
|
|
4
|
+
import { PreparedInstalledFlowSource } from "../services/installed-flow-source.js";
|
|
5
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
6
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
7
|
+
import { writePreparationError } from "./error-output.js";
|
|
8
|
+
import { memoryInitStartupInputSchemas } from "../services/memory-init-startup-custody.js";
|
|
9
|
+
import { isDiagnosticFlow } from "../domain/diagnostic-flows.js";
|
|
10
|
+
/** Executing engine's real handler admission only. The caller owns independent
|
|
11
|
+
* release/source selection; this command never opens storage or creates a RUN. */
|
|
12
|
+
export async function runMemoryFlowAdmissionCli(args, io = process) {
|
|
13
|
+
try {
|
|
14
|
+
const output = parseOutputOptions(args), route = prepareCommandRoute(output.args);
|
|
15
|
+
if (route.key !== "runtime flow admit" || output.responseFile || output.progressJsonl) {
|
|
16
|
+
throw new AppError("usage", "Flow admission accepts bounded stdin and stdout output only", 2, { effect: "no_effect" });
|
|
17
|
+
}
|
|
18
|
+
const input = prepareJsonText(await readBoundedUtf8Stream(io.stdin, 64 * 1024 * 1024), { file: "<stdin>", label: "flow admission" }).value;
|
|
19
|
+
if (!input || typeof input !== "object" || Array.isArray(input)
|
|
20
|
+
|| !["source,source_sha256", "source,source_sha256,startup_input_schema"].includes(Object.keys(input).sort().join())) {
|
|
21
|
+
throw new AppError("usage", "Flow admission requires an exact source snapshot and independent digest", 2, { effect: "no_effect" });
|
|
22
|
+
}
|
|
23
|
+
const selected = input;
|
|
24
|
+
const operation = route.parsed.options.get("operation")?.[0] ?? "";
|
|
25
|
+
const flowId = isDiagnosticFlow(operation) ? operation : operation === "memory-upgrade" ? "mb-upgrade" : "mb-init";
|
|
26
|
+
const startupSchema = memoryInitStartupInputSchemas.find(schema => schema === selected.startup_input_schema);
|
|
27
|
+
if (Object.hasOwn(selected, "startup_input_schema") && (startupSchema === undefined || flowId !== "mb-init")) {
|
|
28
|
+
throw new AppError("usage", "Executing engine does not support the requested startup input schema", 2, { effect: "no_effect" });
|
|
29
|
+
}
|
|
30
|
+
if (typeof selected.source_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(selected.source_sha256)) {
|
|
31
|
+
throw new AppError("usage", "Flow admission requires a SHA-256 source digest", 2, { effect: "no_effect" });
|
|
32
|
+
}
|
|
33
|
+
const source = PreparedInstalledFlowSource.restoreRetained(selected.source, selected.source_sha256);
|
|
34
|
+
const flow = source.resolveRegisteredFlow();
|
|
35
|
+
if (flow.descriptor.id !== flowId)
|
|
36
|
+
throw new AppError("usage", "Flow source does not match the requested engine admission operation", 2, { effect: "no_effect" });
|
|
37
|
+
const facts = { schema_id: isDiagnosticFlow(flowId) ? "dd-flow/diagnostic-engine-flow@1" : flowId === "mb-upgrade" ? "dd-flow/memory-upgrade-engine-flow@1"
|
|
38
|
+
: startupSchema === undefined ? "dd-flow/memory-init-engine-flow@1" : "dd-flow/memory-init-engine-flow@2",
|
|
39
|
+
...(startupSchema === undefined ? {} : { startup_input_schema: startupSchema }),
|
|
40
|
+
flow_id: flowId, source_sha256: source.sha256,
|
|
41
|
+
descriptor_sha256: source.descriptorReference().sha256, stages: flow.descriptor.stages.map(stage => stage.id) };
|
|
42
|
+
io.stdout.write(`${JSON.stringify({ ok: true, action: "runtime_flow_admit", facts, sha256: hybridDigest(facts) }, null, output.json ? undefined : 2)}\n`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const record = errorRecord(error);
|
|
47
|
+
writePreparationError(io, args, record);
|
|
48
|
+
return record.exitCode;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { AppError } from "../shared/errors.js";
|
|
3
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
4
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
5
|
+
const stages = new Set(["preflight", "discover", "compose", "verify", "review", "finish"]);
|
|
6
|
+
const upgradeStages = new Set(["preflight", "diff-analysis", "upgrade", "verify", "review", "finish"]);
|
|
7
|
+
function refuse(message) {
|
|
8
|
+
throw new AppError("usage", message, 2, { phase: "prepare", effect: "no_effect" });
|
|
9
|
+
}
|
|
10
|
+
/** Pure invocation preparation. File bytes, stored replay and productive
|
|
11
|
+
* authority remain with their existing owners; no ambient defaults here. */
|
|
12
|
+
export function prepareMemoryInitInvocation(args) {
|
|
13
|
+
return prepareMemoryInvocation(args, "mb-init");
|
|
14
|
+
}
|
|
15
|
+
export function prepareMemoryUpgradeInvocation(args) {
|
|
16
|
+
return prepareMemoryInvocation(args, "mb-upgrade");
|
|
17
|
+
}
|
|
18
|
+
function prepareMemoryInvocation(args, flowId) {
|
|
19
|
+
const route = prepareCommandRoute(args);
|
|
20
|
+
if (!(flowId === "mb-init" ? ["init", "flow mb-init"] : ["upgrade", "flow mb-upgrade"]).includes(route.key))
|
|
21
|
+
refuse(`Use ${flowId === "mb-init" ? "init" : "upgrade"} or flow ${flowId}`);
|
|
22
|
+
const options = route.parsed.options;
|
|
23
|
+
const value = (name) => options.get(name)?.[0];
|
|
24
|
+
const scope = { projectRoot: value("project-root"), workspaceRoot: value("workspace-root"), requestId: value("request-id") };
|
|
25
|
+
if (![scope.projectRoot, scope.workspaceRoot].every(path.isAbsolute)
|
|
26
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9_.-]{0,95}$/.test(scope.requestId))
|
|
27
|
+
refuse("Init needs absolute roots and a bounded request id");
|
|
28
|
+
const execution = {};
|
|
29
|
+
const maxParallel = value("max-parallel");
|
|
30
|
+
const delegation = value("delegation"), nativeConfigHome = value("native-config-home");
|
|
31
|
+
if (maxParallel !== undefined || delegation !== undefined)
|
|
32
|
+
execution.delegation = {
|
|
33
|
+
mode: delegation === "native" ? "native" : "external", max_parallel: Number(maxParallel ?? 1)
|
|
34
|
+
};
|
|
35
|
+
if (delegation === "native" && Number(maxParallel ?? 1) > 15)
|
|
36
|
+
refuse("Native concurrency must be 1..15");
|
|
37
|
+
if (nativeConfigHome !== undefined && (!path.isAbsolute(nativeConfigHome) || delegation !== "native")
|
|
38
|
+
|| options.has("allow-live-probe") && delegation !== "native")
|
|
39
|
+
refuse("Native probe options require explicit native delegation; an optional config home must be absolute");
|
|
40
|
+
const profile = value("profile");
|
|
41
|
+
const profileFile = value("profile-file");
|
|
42
|
+
if (profileFile !== undefined && (!path.isAbsolute(profileFile) || profile !== undefined))
|
|
43
|
+
refuse("--profile-file must be absolute and is exclusive with --profile");
|
|
44
|
+
if (profile !== undefined)
|
|
45
|
+
execution.rootProfile = profile;
|
|
46
|
+
for (const assignment of options.get("stage-profile") ?? []) {
|
|
47
|
+
const at = assignment.indexOf("="), stage = assignment.slice(0, at), profile = assignment.slice(at + 1);
|
|
48
|
+
if (at < 1 || !(flowId === "mb-init" ? stages : upgradeStages).has(stage) || !profile.trim() || execution.stageProfiles?.[stage] !== undefined)
|
|
49
|
+
refuse("--stage-profile requires a unique stage=profile assignment");
|
|
50
|
+
(execution.stageProfiles ??= {})[stage] = profile;
|
|
51
|
+
}
|
|
52
|
+
if (options.has("work-profile")) {
|
|
53
|
+
execution.workProfiles = [...options.get("work-profile")];
|
|
54
|
+
if (new Set(execution.workProfiles).size !== execution.workProfiles.length)
|
|
55
|
+
refuse("--work-profile must not repeat a profile");
|
|
56
|
+
}
|
|
57
|
+
const intakeFile = value("intake-file"), intakeSha256 = value("intake-sha256");
|
|
58
|
+
if (Boolean(intakeFile) !== Boolean(intakeSha256)
|
|
59
|
+
|| intakeSha256 !== undefined && !/^[a-f0-9]{64}$/.test(intakeSha256)
|
|
60
|
+
|| intakeFile !== undefined && !path.isAbsolute(intakeFile))
|
|
61
|
+
refuse("Original intake needs an absolute --intake-file and --intake-sha256 pair");
|
|
62
|
+
const gitRoute = value("git-route"), integrationBranch = value("integration-branch");
|
|
63
|
+
if (Boolean(gitRoute) !== Boolean(integrationBranch))
|
|
64
|
+
refuse("--git-route and --integration-branch must be supplied together");
|
|
65
|
+
const gitPolicy = gitRoute === undefined ? undefined : {
|
|
66
|
+
route: gitRoute, integrationBranch: integrationBranch
|
|
67
|
+
};
|
|
68
|
+
if (options.has("prepare-only") && options.has("detach"))
|
|
69
|
+
refuse("--prepare-only does not launch a controller and is exclusive with --detach");
|
|
70
|
+
return { scope, execution, gitPolicy, intakeFile, intakeSha256, profileFile, nativeConfigHome, allowLiveProbe: options.has("allow-live-probe"), nonInteractive: options.has("non-interactive"), detach: options.has("detach"), prepareOnly: options.has("prepare-only") };
|
|
71
|
+
}
|
|
72
|
+
/** Omitted selectors replay the retained choices, never current aliases.
|
|
73
|
+
* Supplied selectors must equal the original raw selection, not merely resolve
|
|
74
|
+
* to today's equivalent profile. Intake paths are locators, hashes bind bytes. */
|
|
75
|
+
export function assertMemoryInitInvocationReplay(invocation, original, intakeSha256) {
|
|
76
|
+
if (hybridDigest(invocation.scope) !== hybridDigest(original.scope)
|
|
77
|
+
|| invocation.intakeSha256 !== undefined && invocation.intakeSha256 !== intakeSha256
|
|
78
|
+
|| invocation.gitPolicy !== undefined && hybridDigest(invocation.gitPolicy) !== hybridDigest(original.git_policy)
|
|
79
|
+
|| Object.entries(invocation.execution).some(([key, value]) => !Object.hasOwn(original.execution, key)
|
|
80
|
+
|| hybridDigest(value) !== hybridDigest(key === "delegation" && invocation.execution.delegation?.mode === "native"
|
|
81
|
+
? { mode: original.execution.delegation?.mode, max_parallel: original.execution.delegation?.max_parallel }
|
|
82
|
+
: original.execution[key]))) {
|
|
83
|
+
throw new AppError("memory_init_request_conflict", "Request id belongs to different original init inputs", 1, { effect: "no_effect", next_action: "replay_exact_request_or_choose_new_id" });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
4
|
+
import { Writable } from "node:stream";
|
|
5
|
+
import { once } from "node:events";
|
|
6
|
+
import { createContext } from "../runtime/context.js";
|
|
7
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
8
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
9
|
+
import { readMemoryInitStartupInput } from "../services/memory-init-startup-custody.js";
|
|
10
|
+
import { readMemoryInitRequestInput } from "../services/memory-init-request-input.js";
|
|
11
|
+
import { prepareMemoryInitFreshRequest, prepareMemoryInitSelection, startMemoryInitRun } from "../services/memory-init-start.js";
|
|
12
|
+
import { PreparedMemoryInitLintCapability } from "../services/memory-init-lint-capability.js";
|
|
13
|
+
import { PreparedMemoryInitWorktrunkCapability } from "../services/memory-init-worktrunk-capability.js";
|
|
14
|
+
import { produceMemoryInitNativeCapacity } from "../services/memory-init-native-capacity.js";
|
|
15
|
+
import { openMemoryInitStores, assertMemoryInitStorePrerequisites } from "../services/memory-init-stores.js";
|
|
16
|
+
import { prepareMemoryInitControllerStart, prepareMemoryUpgradeControllerStart } from "../services/memory-init-controller-start.js";
|
|
17
|
+
import { runControllerStatus } from "../services/run-controller.js";
|
|
18
|
+
import { requireRun } from "../services/run-controller-state.js";
|
|
19
|
+
import { requireProjectByRoot } from "../services/projects.js";
|
|
20
|
+
import { routeArgsThroughEngine } from "../services/engines.js";
|
|
21
|
+
import { parseRuntimeBudget } from "../services/runtime-budget.js";
|
|
22
|
+
import { prepareFileBytes } from "./input-preparation.js";
|
|
23
|
+
import { prepareMemoryInitInvocation, assertMemoryInitInvocationReplay } from "./memory-init-invocation.js";
|
|
24
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
25
|
+
import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
|
|
26
|
+
import { writePreparationError } from "./error-output.js";
|
|
27
|
+
import { onboardExecutor } from "../services/executor-onboarding.js";
|
|
28
|
+
import { readOperatorProfiles, readOperatorProfileInput } from "../services/operator-profiles.js";
|
|
29
|
+
import { resolveDdFlowHome } from "../storage/paths.js";
|
|
30
|
+
import { askExecutorChoice } from "./executor-onboarding.js";
|
|
31
|
+
import { isDiagnosticFlow } from "../domain/diagnostic-flows.js";
|
|
32
|
+
import { prepareDiagnosticControllerStart } from "../services/memory-init-controller-start.js";
|
|
33
|
+
/** Backpressure bounds the observing client's output; closing it never controls the RUN. */
|
|
34
|
+
export async function writeMemoryInitObservation(stdout, text) {
|
|
35
|
+
const disconnected = () => Boolean(stdout.destroyed);
|
|
36
|
+
if (disconnected())
|
|
37
|
+
return false;
|
|
38
|
+
const waiting = new AbortController();
|
|
39
|
+
try {
|
|
40
|
+
// Observe errors even when write returns true: a short pipe write can
|
|
41
|
+
// report EPIPE asynchronously. Writable emits callback errors as events.
|
|
42
|
+
const closed = once(stdout, "close", { signal: waiting.signal });
|
|
43
|
+
const written = new Promise(resolve => {
|
|
44
|
+
stdout.write(text, error => { if (!error)
|
|
45
|
+
resolve(); });
|
|
46
|
+
});
|
|
47
|
+
await Promise.race([written, closed]);
|
|
48
|
+
return !disconnected();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error.code === "EPIPE")
|
|
52
|
+
return false;
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
waiting.abort();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Both public spellings enter this owner. The controller, never this observer,
|
|
60
|
+
* owns Sessions and productive dispatch; disconnect does not request stop. */
|
|
61
|
+
export async function runMemoryInitCli(args, env = process.env, io = process) {
|
|
62
|
+
let context;
|
|
63
|
+
let effects = false;
|
|
64
|
+
try {
|
|
65
|
+
const output = parseOutputOptions(args), invocation = prepareMemoryInitInvocation(output.args);
|
|
66
|
+
parseRuntimeBudget(env.DD_FLOW_RUNTIME_BUDGET);
|
|
67
|
+
if (output.responseFile)
|
|
68
|
+
prepareResponseDestination(output.responseFile);
|
|
69
|
+
const reader = createContext(env, "read_existing");
|
|
70
|
+
let retained;
|
|
71
|
+
try {
|
|
72
|
+
retained = readMemoryInitStartupInput(reader, invocation.scope);
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
reader.db.close?.();
|
|
76
|
+
}
|
|
77
|
+
let prepared;
|
|
78
|
+
if (retained) {
|
|
79
|
+
if (retained.payload.schema_id !== "dd-flow/memory-init-startup-input@3")
|
|
80
|
+
throw new AppError("memory_init_original_request_required", "Public init replay requires independently retained original input", 1, { effect: "no_effect" });
|
|
81
|
+
const raw = readMemoryInitRequestInput(retained.payload.request_input, invocation.scope, retained.payload.objective);
|
|
82
|
+
// A supplied file is an explicit selector and must still match. Omitted
|
|
83
|
+
// files never reopen mutable profile inputs during exact replay.
|
|
84
|
+
if (invocation.profileFile)
|
|
85
|
+
invocation.execution.rootProfile = readOperatorProfileInput(invocation.profileFile);
|
|
86
|
+
assertMemoryInitInvocationReplay(invocation, raw.selection, retained.payload.request_input.intake_sha256);
|
|
87
|
+
if (invocation.nativeConfigHome) {
|
|
88
|
+
const reference = retained.payload.execution.snapshot.settings.delegation.native_capacity_receipt;
|
|
89
|
+
const encoded = retained.payload.execution.receipt_blobs?.find(([checksum]) => checksum === reference?.sha256)?.[1];
|
|
90
|
+
if (!encoded || JSON.parse(Buffer.from(encoded, "base64").toString("utf8")).input.native_config_home !== invocation.nativeConfigHome)
|
|
91
|
+
throw new AppError("memory_init_request_conflict", "Native private configuration selection changed", 1, { effect: "no_effect" });
|
|
92
|
+
}
|
|
93
|
+
context = openMemoryInitStores(env, { scope: invocation.scope, selectionSha256: hybridDigest(raw.selection) }).context;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
if (!invocation.intakeFile || !invocation.intakeSha256 || !invocation.gitPolicy)
|
|
97
|
+
throw new AppError("usage", "Fresh init requires original intake file/hash and explicit Git route/integration branch", 2, { phase: "prepare", effect: "no_effect" });
|
|
98
|
+
const raw = prepareFileBytes(invocation.intakeFile, "original init intake", 64 * 1024).bytes;
|
|
99
|
+
if (createHash("sha256").update(raw).digest("hex") !== invocation.intakeSha256)
|
|
100
|
+
throw new AppError("memory_init_intake_changed", "Original intake bytes differ from --intake-sha256", 2, { phase: "prepare", effect: "no_effect" });
|
|
101
|
+
let objective;
|
|
102
|
+
try {
|
|
103
|
+
objective = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(raw);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
throw new AppError("usage", "Original init intake must be UTF-8", 2, { phase: "prepare", effect: "no_effect" });
|
|
107
|
+
}
|
|
108
|
+
// Controller birth/lease confirmation uses this OS observation. Known
|
|
109
|
+
// inability must refuse before candidate, stores or project publication.
|
|
110
|
+
const identity = spawnSync("ps", ["-o", "lstart=", "-p", String(process.pid)], { env: { ...env, TZ: "UTC", LC_ALL: "C" }, encoding: "utf8", timeout: 1000, shell: false, windowsHide: true });
|
|
111
|
+
if (identity.error || identity.signal || identity.status !== 0 || !identity.stdout.trim())
|
|
112
|
+
throw new AppError("memory_init_runtime_unavailable", "Controller physical identity observation is unavailable", 1, { phase: "prepare", effect: "no_effect", next_action: "restore_system_process_observation" });
|
|
113
|
+
const stdin = io.stdin ?? process.stdin;
|
|
114
|
+
const nonInteractive = invocation.nonInteractive || output.json || output.progressJsonl
|
|
115
|
+
|| !stdin.isTTY || !io.stderr.isTTY;
|
|
116
|
+
const selected = await onboardExecutor({
|
|
117
|
+
...(typeof invocation.execution.rootProfile === "string" ? { profileId: invocation.execution.rootProfile } : {}),
|
|
118
|
+
...(invocation.profileFile ? { profileFile: invocation.profileFile } : {})
|
|
119
|
+
}, () => readOperatorProfiles(resolveDdFlowHome(env)), { allowSkip: false, nonInteractive }, settings => askExecutorChoice(settings, { stdin, stderr: io.stderr }, { allowSave: false, allowSkip: false }));
|
|
120
|
+
if (selected.source === "explicit-file" || selected.source === "explicit-profile")
|
|
121
|
+
invocation.execution.rootProfile = selected.profile;
|
|
122
|
+
else if (invocation.execution.rootProfile === undefined && selected.source === "explicit-id")
|
|
123
|
+
invocation.execution.rootProfile = selected.profile.id;
|
|
124
|
+
let native;
|
|
125
|
+
if (invocation.execution.delegation?.mode === "native") {
|
|
126
|
+
if (!invocation.allowLiveProbe)
|
|
127
|
+
throw new AppError("usage", "Fresh native init requires --allow-live-probe", 2, { effect: "no_effect" });
|
|
128
|
+
const admissionReader = createContext(env, "read_existing");
|
|
129
|
+
let profile;
|
|
130
|
+
try {
|
|
131
|
+
const baseline = prepareMemoryInitSelection(admissionReader, invocation.scope, { execution: {
|
|
132
|
+
...invocation.execution, delegation: { mode: "external", max_parallel: invocation.execution.delegation.max_parallel ?? 1 }
|
|
133
|
+
}, gitPolicy: invocation.gitPolicy, objective });
|
|
134
|
+
PreparedMemoryInitLintCapability.prepare(baseline.target, env);
|
|
135
|
+
PreparedMemoryInitWorktrunkCapability.prepare(baseline.target, env);
|
|
136
|
+
baseline.engine.admitMemoryInitFlow(baseline.source, "dd-flow/memory-init-startup-input@3");
|
|
137
|
+
assertMemoryInitStorePrerequisites(env, invocation.scope);
|
|
138
|
+
const snapshot = baseline.execution.snapshot();
|
|
139
|
+
profile = snapshot.profiles.find(entry => entry.id === snapshot.settings.root_profile).profile;
|
|
140
|
+
if (snapshot.profiles.some(entry => hybridDigest({ ...entry.profile, id: profile.id }) !== hybridDigest(profile)))
|
|
141
|
+
throw new AppError("generic_execution_invalid", "Native delegation cannot change execution profiles", 2, { effect: "no_effect" });
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
admissionReader.db.close?.();
|
|
145
|
+
}
|
|
146
|
+
// From here a failed reply cannot imply no effect: daemon/child custody
|
|
147
|
+
// is independent from later startup publication and RUN allocation.
|
|
148
|
+
effects = true;
|
|
149
|
+
native = await produceMemoryInitNativeCapacity({ home: resolveDdFlowHome(env), scope: invocation.scope, profile,
|
|
150
|
+
maximum: invocation.execution.delegation.max_parallel ?? 1,
|
|
151
|
+
...(invocation.nativeConfigHome !== undefined ? { nativeConfigHome: invocation.nativeConfigHome } : {}),
|
|
152
|
+
allowLiveProbe: invocation.allowLiveProbe, env, requestSha256: hybridDigest({ scope: invocation.scope,
|
|
153
|
+
execution: invocation.execution, gitPolicy: invocation.gitPolicy, objective, intake: invocation.intakeSha256 }) });
|
|
154
|
+
invocation.execution.delegation.nativeCapacityReceipt = native.reference;
|
|
155
|
+
}
|
|
156
|
+
const owner = prepareMemoryInitFreshRequest(env, invocation.scope, { execution: invocation.execution, gitPolicy: invocation.gitPolicy, objective,
|
|
157
|
+
...(native ? { receipts: native.receipts, receiptBytes: native.receiptBytes } : {}) }, raw);
|
|
158
|
+
context = owner.context;
|
|
159
|
+
prepared = owner.prepared;
|
|
160
|
+
}
|
|
161
|
+
// Beyond this boundary, absence of a success receipt is not no-effect.
|
|
162
|
+
effects = true;
|
|
163
|
+
const started = startMemoryInitRun(context, invocation.scope, prepared ? () => prepared : undefined);
|
|
164
|
+
return await launchAndObserveMemoryFlow(context, invocation, started, "mb-init", output, env, io);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
const record = errorRecord(error);
|
|
168
|
+
if (effects)
|
|
169
|
+
record.details = { ...record.details, effect: record.details.effect === "partial" ? "partial" : "unknown", next_action: "observe_or_reconcile_exact_request" };
|
|
170
|
+
writePreparationError(io, args, record);
|
|
171
|
+
return record.exitCode;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
context?.db.close?.();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Shared foreground observer only; the existing RUN-bound controller owns
|
|
178
|
+
* physical Sessions. Neither alias gains another orchestration lifecycle. */
|
|
179
|
+
export async function launchAndObserveMemoryFlow(context, invocation, started, flowId, output, env, io) {
|
|
180
|
+
const action = `flow_${flowId.replaceAll("-", "_")}`;
|
|
181
|
+
if (invocation.prepareOnly) {
|
|
182
|
+
const run = requireRun(context, requireProjectByRoot(context, invocation.scope.projectRoot).id, started.runId);
|
|
183
|
+
const response = { ok: true, action: `${action}_prepared`, flow_id: flowId, ...started,
|
|
184
|
+
run_id: started.runId, request_id: invocation.scope.requestId, run_root: run.run_root,
|
|
185
|
+
project_root: run.project_root, workspace_root: run.workspace_root };
|
|
186
|
+
await writeMemoryInitObservation(io.stdout, `${JSON.stringify(writeResponseFile(response, output), null, output.json || output.progressJsonl ? undefined : 2)}\n`);
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
const launch = isDiagnosticFlow(flowId) ? prepareDiagnosticControllerStart(context, invocation.scope, flowId)
|
|
190
|
+
: (flowId === "mb-init" ? prepareMemoryInitControllerStart : prepareMemoryUpgradeControllerStart)(context, invocation.scope);
|
|
191
|
+
// Use the existing RUN-bound router: a global CLI must not launch its own
|
|
192
|
+
// controller code in place of the independently frozen RUN executable.
|
|
193
|
+
const receiptChunks = [];
|
|
194
|
+
let receiptSize = 0, oversizedReceipt = false;
|
|
195
|
+
const capture = new Writable({ write(chunk, _, next) {
|
|
196
|
+
receiptSize += Buffer.byteLength(chunk);
|
|
197
|
+
if (receiptSize > 1024 * 1024)
|
|
198
|
+
oversizedReceipt = true;
|
|
199
|
+
else
|
|
200
|
+
receiptChunks.push(Buffer.from(chunk));
|
|
201
|
+
next();
|
|
202
|
+
} });
|
|
203
|
+
const routed = await routeArgsThroughEngine(context, ["run", "drive", "launch", "--project-root", launch.input.projectRoot,
|
|
204
|
+
"--run", launch.input.runId, "--request-id", launch.input.requestId, "--context-file", launch.input.contextFile,
|
|
205
|
+
"--context-sha256", launch.input.contextSha256, "--json"], { stdout: capture, stderr: io.stderr }, undefined, { ...env, DD_FLOW_ENGINE_MODE: undefined }, invocation.scope.projectRoot);
|
|
206
|
+
if (!routed?.routed || routed.inProcess || routed.exitCode !== 0 || oversizedReceipt)
|
|
207
|
+
throw new AppError("memory_init_controller_launch_unknown", "Observe or reconcile the exact RUN-bound controller launch", 1, { effect: "unknown" });
|
|
208
|
+
let receipt;
|
|
209
|
+
try {
|
|
210
|
+
receipt = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(receiptChunks)));
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
throw new AppError("memory_init_controller_launch_unknown", "Selected engine returned no valid controller receipt", 1, { effect: "unknown" });
|
|
214
|
+
}
|
|
215
|
+
const accepted = receipt.controller;
|
|
216
|
+
if (receipt.ok !== true || !accepted || accepted.run_id !== started.runId || accepted.request_id !== invocation.scope.requestId)
|
|
217
|
+
throw new AppError("memory_init_controller_launch_unknown", "Selected engine returned a foreign controller receipt", 1, { effect: "unknown" });
|
|
218
|
+
const emit = (result) => writeMemoryInitObservation(io.stdout, `${JSON.stringify(result, null, output.json || output.progressJsonl ? undefined : 2)}\n`);
|
|
219
|
+
if (output.progressJsonl && !await emit({ ok: true, action: "flow_accepted", flow_id: flowId, ...started, ...receipt }))
|
|
220
|
+
return 0;
|
|
221
|
+
let result = receipt;
|
|
222
|
+
if (!invocation.detach) {
|
|
223
|
+
let after = 0;
|
|
224
|
+
let recentEvents = [];
|
|
225
|
+
for (;;) {
|
|
226
|
+
// The client has no ownership of the detached controller process.
|
|
227
|
+
if (io.stdout.destroyed)
|
|
228
|
+
return 0;
|
|
229
|
+
result = runControllerStatus(context, { projectRoot: invocation.scope.projectRoot, runId: started.runId, after });
|
|
230
|
+
const events = result.events, controller = result.controller;
|
|
231
|
+
after = result.next_cursor;
|
|
232
|
+
recentEvents = [...recentEvents, ...events].slice(-100);
|
|
233
|
+
if (output.progressJsonl && events.length && !await emit({ ok: true, action: "flow_progress", flow_id: flowId, ...result }))
|
|
234
|
+
return 0;
|
|
235
|
+
if (!controller)
|
|
236
|
+
throw new AppError("memory_init_controller_receipt_missing", "Observe or reconcile the retained controller", 1, { effect: "unknown" });
|
|
237
|
+
if (["completed", "cancelled", "superseded", "recovery_required", "failed", "waiting_for_user", "waiting_for_context"].includes(controller.status)) {
|
|
238
|
+
result = { ...result, events: recentEvents };
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
await delay(250);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const response = { ...result, action, flow_id: flowId, run_id: started.runId, request_id: invocation.scope.requestId };
|
|
245
|
+
if (!await emit(writeResponseFile(response, output)))
|
|
246
|
+
return 0;
|
|
247
|
+
const status = result.controller?.status;
|
|
248
|
+
return ["recovery_required", "failed", "cancelled", "superseded"].includes(status ?? "") ? 1 : 0;
|
|
249
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
4
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
5
|
+
import { createContext } from "../runtime/context.js";
|
|
6
|
+
import { getResourceDatabase } from "../storage/database.js";
|
|
7
|
+
import { withStoreCleanup } from "../storage/native-cleanup.js";
|
|
8
|
+
import { PreparedMemoryInitRuntimeStorage } from "../services/memory-init-storage.js";
|
|
9
|
+
import { PreparedMemoryInitResourceStorage } from "../services/memory-init-resource-storage.js";
|
|
10
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
11
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
12
|
+
import { writePreparationError } from "./error-output.js";
|
|
13
|
+
/** Selected engine's non-migrating operation admission. No AppContext initialize. */
|
|
14
|
+
export function runMemoryStorageAdmissionCli(args, env = process.env, io = process) {
|
|
15
|
+
try {
|
|
16
|
+
const output = parseOutputOptions(args), route = prepareCommandRoute(output.args);
|
|
17
|
+
if (route.key !== "runtime storage admit" || output.responseFile || output.progressJsonl) {
|
|
18
|
+
throw new AppError("usage", "Storage admission accepts stdout output only", 2, { effect: "no_effect" });
|
|
19
|
+
}
|
|
20
|
+
const operation = route.parsed.options.get("operation")[0];
|
|
21
|
+
const home = env.DD_FLOW_HOME;
|
|
22
|
+
if (!home || !path.isAbsolute(home) || path.resolve(home) !== home || fs.realpathSync(home) !== home) {
|
|
23
|
+
throw new AppError("usage", "Storage admission requires an explicit canonical absolute DD_FLOW_HOME", 2, { effect: "no_effect" });
|
|
24
|
+
}
|
|
25
|
+
const file = path.join(home, "db.sqlite"), owner = fs.lstatSync(file);
|
|
26
|
+
if (!owner.isFile() || owner.nlink !== 1)
|
|
27
|
+
throw new AppError("run_storage_unprepared", "RUN storage must be a regular single-linked file", 1, { effect: "no_effect" });
|
|
28
|
+
const resource = PreparedMemoryInitResourceStorage.prepare({ ddFlowHome: home, env });
|
|
29
|
+
const context = createContext(env, "prepared_existing");
|
|
30
|
+
const facts = withStoreCleanup(() => {
|
|
31
|
+
const run = operation === "memory-upgrade" ? PreparedMemoryInitRuntimeStorage.prepareUpgrade(context) : PreparedMemoryInitRuntimeStorage.prepare(context);
|
|
32
|
+
const resourceWriter = getResourceDatabase(path.dirname(resource.facts().store_path), "prepared_existing");
|
|
33
|
+
return withStoreCleanup(() => {
|
|
34
|
+
if (resourceWriter.get("SELECT dd_flow_writer_version() AS version")?.version !== resource.facts().executing_writer_version) {
|
|
35
|
+
throw new AppError("store_writer_incompatible", "Resource connection writer differs from admitted storage", 1, { effect: "no_effect" });
|
|
36
|
+
}
|
|
37
|
+
resource.revalidate({ ddFlowHome: home, env });
|
|
38
|
+
const current = fs.lstatSync(file);
|
|
39
|
+
if (!current.isFile() || current.nlink !== 1 || current.dev !== owner.dev || current.ino !== owner.ino) {
|
|
40
|
+
throw new AppError("run_storage_changed", "RUN store changed during admission", 1, { effect: "no_effect" });
|
|
41
|
+
}
|
|
42
|
+
return { schema_id: `dd-flow/${operation}-engine-storage@1`, operation, route: "verified-no-op", outcome: "no-op",
|
|
43
|
+
run: { ...run.facts(), store_dev: owner.dev, store_ino: owner.ino }, resource: resource.facts() };
|
|
44
|
+
}, () => resourceWriter.close?.());
|
|
45
|
+
}, () => context.db.close?.());
|
|
46
|
+
io.stdout.write(`${JSON.stringify({ ok: true, action: "runtime_storage_admit", facts, sha256: hybridDigest(facts) }, null, output.json ? undefined : 2)}\n`);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const record = errorRecord(error);
|
|
51
|
+
writePreparationError(io, args, record);
|
|
52
|
+
return record.exitCode;
|
|
53
|
+
}
|
|
54
|
+
}
|