@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,161 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { AppError } from "../shared/errors.js";
|
|
3
|
+
import { appendAudit } from "./audit.js";
|
|
4
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
5
|
+
import { PreparedMemoryStageResult } from "./memory-stage-results.js";
|
|
6
|
+
import { stageGraphScope } from "./stage-work-graph.js";
|
|
7
|
+
import { addWorkBatch, prepareWorkBatch, readWorkBatchCustody } from "./work-registry.js";
|
|
8
|
+
const workerSchema = "dd-flow/memory-composition-work-result@1";
|
|
9
|
+
function refuse(reason) {
|
|
10
|
+
throw new AppError("memory_composition_registration_invalid", "Retained composition registration cannot authorize this graph", 1, { reason, effect: "no_effect" });
|
|
11
|
+
}
|
|
12
|
+
const bytesHash = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
13
|
+
function readReceipt(context, scope) {
|
|
14
|
+
const requestSha256 = hybridDigest(scope);
|
|
15
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id = ? AND event_type = 'memory.composition_registration' AND json_extract(payload_json, '$.request_sha256') = ?", [scope.project_id, requestSha256]);
|
|
16
|
+
if (!rows.length)
|
|
17
|
+
return null;
|
|
18
|
+
try {
|
|
19
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 2 * 1024 * 1024)
|
|
20
|
+
refuse("ambiguous_or_unbounded_receipt");
|
|
21
|
+
const receipt = JSON.parse(rows[0].payload_json);
|
|
22
|
+
if (receipt.schema_id !== "dd-flow/memory-composition-registration@1" || receipt.request_sha256 !== requestSha256
|
|
23
|
+
|| receipt.run_id !== scope.run_id || hybridDigest(receipt.scope) !== requestSha256 || receipt.result_schema !== workerSchema
|
|
24
|
+
|| [receipt.batch_sha256, receipt.compose_result_sha256, receipt.input_sha256, receipt.execution_sha256].some(hash => typeof hash !== "string" || !/^[a-f0-9]{64}$/.test(hash))
|
|
25
|
+
|| typeof receipt.result_base64 !== "string" || !receipt.work_ids || Array.isArray(receipt.work_ids)
|
|
26
|
+
|| typeof receipt.work_ids !== "object" || !Object.keys(receipt.work_ids).length && scope.stage !== "upgrade" || Object.keys(receipt.work_ids).length > 4096
|
|
27
|
+
|| Object.values(receipt.work_ids).some(id => typeof id !== "string")
|
|
28
|
+
|| new Set(Object.values(receipt.work_ids)).size !== Object.keys(receipt.work_ids).length)
|
|
29
|
+
refuse("foreign_receipt_binding");
|
|
30
|
+
const bytes = Buffer.from(receipt.result_base64, "base64");
|
|
31
|
+
if (!bytes.length || bytes.length > 1024 * 1024 || bytes.toString("base64") !== receipt.result_base64
|
|
32
|
+
|| bytesHash(bytes) !== receipt.compose_result_sha256)
|
|
33
|
+
refuse("changed_result_bytes");
|
|
34
|
+
for (const [key, id] of Object.entries(receipt.work_ids)) {
|
|
35
|
+
const custody = readWorkBatchCustody(context, id);
|
|
36
|
+
if (custody.item_key !== key || custody.request_sha256 !== requestSha256 || custody.batch_sha256 !== receipt.batch_sha256
|
|
37
|
+
|| hybridDigest(custody.work_ids) !== hybridDigest(receipt.work_ids) || hybridDigest(custody.scope) !== requestSha256)
|
|
38
|
+
refuse("changed_work_custody");
|
|
39
|
+
}
|
|
40
|
+
if (!Object.keys(receipt.work_ids).length) {
|
|
41
|
+
// No invented worker for deterministic-only upgrade. Its empty batch
|
|
42
|
+
// still has the same independent allocator receipt and active scope.
|
|
43
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='work.batch_registration' AND json_extract(payload_json,'$.request_sha256')=? LIMIT 2", [scope.project_id, requestSha256]);
|
|
44
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 32768 || hybridDigest(JSON.parse(rows[0].payload_json)) !== hybridDigest({
|
|
45
|
+
run_id: scope.run_id, scope, request_sha256: requestSha256, batch_sha256: hybridDigest([]), work_ids: {}, work_sha256: {}
|
|
46
|
+
}) || receipt.batch_sha256 !== hybridDigest([]))
|
|
47
|
+
refuse("changed_empty_batch_custody");
|
|
48
|
+
}
|
|
49
|
+
return receipt;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof AppError && error.code === "memory_composition_registration_invalid")
|
|
53
|
+
throw error;
|
|
54
|
+
return refuse("invalid_receipt_or_work_custody");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** SQL-only identity check for the settlement writer; no schema or filesystem I/O. */
|
|
58
|
+
export function memoryCompositionRegistrationDigest(context, scope) {
|
|
59
|
+
const receipt = readReceipt(context, scope);
|
|
60
|
+
if (!receipt)
|
|
61
|
+
refuse("composition_receipt_missing");
|
|
62
|
+
return hybridDigest(receipt);
|
|
63
|
+
}
|
|
64
|
+
/** Independent SQL blueprint bytes, never the final result or mutable file. */
|
|
65
|
+
export function readMemoryCompositionRegistration(context, scope) {
|
|
66
|
+
const receipt = readReceipt(context, scope);
|
|
67
|
+
if (!receipt)
|
|
68
|
+
refuse("composition_receipt_missing");
|
|
69
|
+
return structuredClone(receipt);
|
|
70
|
+
}
|
|
71
|
+
/** Finish selects the sole original plan for this independently owned stage
|
|
72
|
+
* attempt; an agent result does not choose a request key or its Work graph.
|
|
73
|
+
*/
|
|
74
|
+
export function selectMemoryCompositionRegistration(context, scope) {
|
|
75
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='memory.composition_registration' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.scope.stage')=? AND json_extract(payload_json,'$.scope.attempt')=? AND json_extract(payload_json,'$.scope.cycle')=? AND json_extract(payload_json,'$.scope.parent_work_id')=? LIMIT 2", [scope.project_id, scope.run_id, scope.stage, scope.attempt, scope.cycle, scope.parent_work_id]);
|
|
76
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 2 * 1024 * 1024)
|
|
77
|
+
refuse("original_composition_missing_or_ambiguous");
|
|
78
|
+
let retained;
|
|
79
|
+
try {
|
|
80
|
+
retained = JSON.parse(rows[0].payload_json);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return refuse("invalid_receipt_or_work_custody");
|
|
84
|
+
}
|
|
85
|
+
if (typeof retained?.scope?.request_key !== "string" || hybridDigest(retained.scope) !== hybridDigest({ ...scope, request_key: retained.scope.request_key }))
|
|
86
|
+
refuse("foreign_receipt_binding");
|
|
87
|
+
return readMemoryCompositionRegistration(context, { ...scope, request_key: retained.scope.request_key });
|
|
88
|
+
}
|
|
89
|
+
/** Registration custody, not semantic stage acceptance. The caller must first
|
|
90
|
+
* establish accepted predecessor/source and coordinator/Session authority.
|
|
91
|
+
* Prepared bytes and Work allocation commit together; no mutable file is read
|
|
92
|
+
* under the writer. An existing generic batch cannot be retroactively adopted.
|
|
93
|
+
*/
|
|
94
|
+
export function registerMemoryComposition(context, input, assertHandlerCustody) {
|
|
95
|
+
if (!(input.composition instanceof PreparedMemoryStageResult))
|
|
96
|
+
refuse("foreign_prepared_result");
|
|
97
|
+
const stage = input.composition.authoringStage();
|
|
98
|
+
const value = input.composition.compositionBatch({ ...input.binding, resultSchema: workerSchema });
|
|
99
|
+
const bytes = input.composition.bytes();
|
|
100
|
+
const batchInput = { parentWorkId: input.parentWorkId, requestKey: input.requestKey, stage, value };
|
|
101
|
+
// Generic CLI batches remain non-empty. The admitted upgrade graph alone
|
|
102
|
+
// may register zero agent tasks; addWorkBatch still checks parent/run/stage
|
|
103
|
+
// and records exact batch custody in the existing writer transaction.
|
|
104
|
+
const prepared = stage === "upgrade" && !value.works.length ? [] : prepareWorkBatch(context, batchInput);
|
|
105
|
+
return context.db.writeTransaction(() => {
|
|
106
|
+
assertHandlerCustody?.(context);
|
|
107
|
+
const parent = context.db.get("SELECT project_id, run_id FROM works WHERE work_id = ?", [input.parentWorkId]);
|
|
108
|
+
if (!parent || parent.run_id !== input.binding.runId)
|
|
109
|
+
refuse("foreign_coordinator");
|
|
110
|
+
const scope = { ...stageGraphScope(context, parent.project_id, parent.run_id, stage),
|
|
111
|
+
stage, parent_work_id: input.parentWorkId, request_key: input.requestKey };
|
|
112
|
+
// One immutable blueprint per coordinator/attempt. A different request key
|
|
113
|
+
// cannot create another productive graph or bypass a lost original receipt.
|
|
114
|
+
const originals = context.db.all("SELECT json_extract(payload_json,'$.request_sha256') AS request_sha256 FROM audit_events WHERE project_id=? AND event_type='memory.composition_registration' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.scope.stage')=? AND json_extract(payload_json,'$.scope.attempt')=? AND json_extract(payload_json,'$.scope.cycle')=? AND json_extract(payload_json,'$.scope.parent_work_id')=? LIMIT 2", [scope.project_id, scope.run_id, stage, scope.attempt, scope.cycle, scope.parent_work_id]);
|
|
115
|
+
if (originals.length > 1 || originals.length === 1 && originals[0].request_sha256 !== hybridDigest(scope))
|
|
116
|
+
refuse("original_composition_already_registered");
|
|
117
|
+
const prior = readReceipt(context, scope);
|
|
118
|
+
if (!prior && context.db.get("SELECT 1 FROM works w JOIN stage_work_memberships m ON m.work_id=w.work_id AND m.project_id=w.project_id AND m.run_id=w.run_id WHERE w.project_id=? AND w.run_id=? AND w.parent_work_id=? AND w.result_schema=? AND m.stage=? AND m.attempt=? AND m.cycle=? LIMIT 1", [scope.project_id, scope.run_id, scope.parent_work_id, workerSchema, stage, scope.attempt, scope.cycle]))
|
|
119
|
+
refuse("composition_receipt_missing");
|
|
120
|
+
if (prior && (prior.compose_result_sha256 !== input.composition.sha256 || prior.batch_sha256 !== hybridDigest(value.works)
|
|
121
|
+
|| prior.input_sha256 !== input.binding.inputSha256 || prior.execution_sha256 !== input.binding.executionSha256))
|
|
122
|
+
refuse("request_conflict");
|
|
123
|
+
const allocation = addWorkBatch(context, { ...batchInput, prepared });
|
|
124
|
+
const workIds = allocation.work_ids;
|
|
125
|
+
if (prior) {
|
|
126
|
+
if (hybridDigest(prior.work_ids) !== hybridDigest(workIds))
|
|
127
|
+
refuse("changed_allocation");
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
if (allocation.replayed)
|
|
131
|
+
refuse("composition_receipt_missing");
|
|
132
|
+
const receipt = { schema_id: "dd-flow/memory-composition-registration@1", scope, run_id: parent.run_id,
|
|
133
|
+
request_sha256: hybridDigest(scope), batch_sha256: hybridDigest(value.works), compose_result_sha256: input.composition.sha256,
|
|
134
|
+
result_base64: bytes.toString("base64"), input_sha256: input.binding.inputSha256,
|
|
135
|
+
execution_sha256: input.binding.executionSha256, result_schema: workerSchema, work_ids: workIds };
|
|
136
|
+
appendAudit(context, { projectId: parent.project_id, eventType: "memory.composition_registration", payload: { ...receipt } });
|
|
137
|
+
}
|
|
138
|
+
return { scope, compose_result_sha256: input.composition.sha256, work_ids: { ...workIds }, replayed: Boolean(prior) };
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Restore the exact registered bytes and re-prepare with independently selected
|
|
142
|
+
* frozen schema/execution and predecessor/source observations. No file or settings
|
|
143
|
+
* fallback; restored registration does not attest completed Works or stage acceptance.
|
|
144
|
+
*/
|
|
145
|
+
export function readRegisteredMemoryComposition(context, input) {
|
|
146
|
+
const receipt = readReceipt(context, input.scope);
|
|
147
|
+
if (!receipt)
|
|
148
|
+
refuse("composition_receipt_missing");
|
|
149
|
+
if (input.binding.runId !== input.scope.run_id || input.binding.stage !== input.scope.stage
|
|
150
|
+
|| input.binding.inputSha256 !== receipt.input_sha256 || input.binding.executionSha256 !== receipt.execution_sha256)
|
|
151
|
+
refuse("foreign_restore_binding");
|
|
152
|
+
const result = PreparedMemoryStageResult.prepare(Buffer.from(receipt.result_base64, "base64"), input.flow, input.binding);
|
|
153
|
+
if (result.authoringStage() !== input.scope.stage)
|
|
154
|
+
refuse("foreign_restore_binding");
|
|
155
|
+
const batch = result.compositionBatch({ runId: input.binding.runId, inputSha256: receipt.input_sha256,
|
|
156
|
+
executionSha256: receipt.execution_sha256, resultSchema: workerSchema });
|
|
157
|
+
if (result.sha256 !== receipt.compose_result_sha256 || hybridDigest(batch.works) !== receipt.batch_sha256
|
|
158
|
+
|| batch.works.length !== Object.keys(receipt.work_ids).length || batch.works.some(item => !Object.hasOwn(receipt.work_ids, item.key)))
|
|
159
|
+
refuse("changed_registered_graph");
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { AppError } from "../shared/errors.js";
|
|
3
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
4
|
+
import { PreparedMemoryCompositionWorkResult } from "./memory-composition-work-results.js";
|
|
5
|
+
import { PreparedMemoryStageResult } from "./memory-stage-results.js";
|
|
6
|
+
import { readRegisteredMemoryComposition, memoryCompositionRegistrationDigest } from "./memory-composition-registration.js";
|
|
7
|
+
import { readWorkBatchCustody } from "./work-registry.js";
|
|
8
|
+
import { stageWorkIds } from "./stage-work-graph.js";
|
|
9
|
+
import { assertRunBundleSqlAuthority } from "./runs.js";
|
|
10
|
+
import { PreparedMemoryResultBinding } from "./memory-result-binding.js";
|
|
11
|
+
import { appendAudit } from "./audit.js";
|
|
12
|
+
import { runtimeHarness } from "./execution-policy.js";
|
|
13
|
+
function refuse() {
|
|
14
|
+
throw new AppError("memory_composition_work_custody_invalid", "Registered Work differs from the independently selected composition", 1, { phase: "prepare", effect: "no_effect" });
|
|
15
|
+
}
|
|
16
|
+
function assignedRoots(context, custody) {
|
|
17
|
+
const run = context.db.get("SELECT workspace_root, run_root, run_dir FROM runs WHERE project_id = ? AND id = ?", [custody.scope.project_id, custody.scope.run_id]);
|
|
18
|
+
if (!run || !path.isAbsolute(run.workspace_root) || !path.isAbsolute(run.run_root ?? run.run_dir))
|
|
19
|
+
refuse();
|
|
20
|
+
return { workspace: run.workspace_root, run: run.run_root ?? run.run_dir };
|
|
21
|
+
}
|
|
22
|
+
/** Bridges independent SQL allocation custody and physical output preparation.
|
|
23
|
+
* The caller must independently select the accepted composition and frozen engine.
|
|
24
|
+
* This is not stage acceptance, Session settlement, or semantic completeness.
|
|
25
|
+
*/
|
|
26
|
+
export class PreparedRegisteredMemoryCompositionWorkResult {
|
|
27
|
+
sha256;
|
|
28
|
+
workId;
|
|
29
|
+
#custody;
|
|
30
|
+
#result;
|
|
31
|
+
#roots;
|
|
32
|
+
#registration = null;
|
|
33
|
+
#stageBinding = null;
|
|
34
|
+
#harness;
|
|
35
|
+
constructor(custody, roots, result, harness) {
|
|
36
|
+
this.#custody = custody;
|
|
37
|
+
this.#roots = roots;
|
|
38
|
+
this.#result = result;
|
|
39
|
+
this.#harness = harness;
|
|
40
|
+
this.sha256 = result.sha256;
|
|
41
|
+
this.workId = custody.work_id;
|
|
42
|
+
Object.freeze(this);
|
|
43
|
+
}
|
|
44
|
+
/** Restart path: composition bytes come from CLI registration, while its
|
|
45
|
+
* predecessor/source/schema/execution binding still comes from the controller.
|
|
46
|
+
*/
|
|
47
|
+
static prepareFromStageCustody(context, input, engine, binding) {
|
|
48
|
+
const custody = readWorkBatchCustody(context, binding.workId);
|
|
49
|
+
const stage = binding.flow.descriptor.id === "mb-init" ? "compose" : binding.flow.descriptor.id === "mb-upgrade" ? "upgrade" : refuse();
|
|
50
|
+
const selected = binding.bundle ? PreparedMemoryResultBinding.prepareRegisteredComposition(context, { ...binding, bundle: binding.bundle,
|
|
51
|
+
registrationScope: { project_id: binding.projectId, run_id: binding.runId, stage, attempt: custody.scope.attempt, cycle: custody.scope.cycle,
|
|
52
|
+
parent_work_id: binding.coordinatorWorkId, request_key: binding.requestKey } })
|
|
53
|
+
: binding.sources ? PreparedMemoryResultBinding.prepare(context, { ...binding, sources: binding.sources, stage }) : refuse();
|
|
54
|
+
const prepared = this.prepareFromRegistration(context, input, engine, { ...binding, resultBinding: selected.binding() });
|
|
55
|
+
prepared.#stageBinding = selected;
|
|
56
|
+
prepared.assertCustody(context);
|
|
57
|
+
return prepared;
|
|
58
|
+
}
|
|
59
|
+
static prepareFromRegistration(context, input, engine, binding) {
|
|
60
|
+
const custody = readWorkBatchCustody(context, binding.workId);
|
|
61
|
+
const stage = binding.flow.descriptor.id === "mb-init" ? "compose" : binding.flow.descriptor.id === "mb-upgrade" ? "upgrade" : refuse();
|
|
62
|
+
if (custody.scope.stage !== stage || custody.scope.parent_work_id !== binding.coordinatorWorkId
|
|
63
|
+
|| custody.scope.request_key !== binding.requestKey || !binding.resultBinding.executionSha256)
|
|
64
|
+
refuse();
|
|
65
|
+
const scope = { project_id: custody.scope.project_id, run_id: custody.scope.run_id,
|
|
66
|
+
stage, attempt: custody.scope.attempt, cycle: custody.scope.cycle,
|
|
67
|
+
parent_work_id: binding.coordinatorWorkId, request_key: binding.requestKey };
|
|
68
|
+
const registrationSha256 = memoryCompositionRegistrationDigest(context, scope);
|
|
69
|
+
const composition = readRegisteredMemoryComposition(context, { scope, flow: binding.flow, binding: binding.resultBinding });
|
|
70
|
+
const prepared = this.prepare(context, input, engine, { workId: binding.workId, coordinatorWorkId: binding.coordinatorWorkId, requestKey: binding.requestKey,
|
|
71
|
+
composition, compositionSha256: composition.sha256, runId: binding.resultBinding.runId,
|
|
72
|
+
inputSha256: binding.resultBinding.inputSha256, executionSha256: binding.resultBinding.executionSha256 });
|
|
73
|
+
prepared.#registration = { scope, sha256: registrationSha256 };
|
|
74
|
+
prepared.assertCustody(context);
|
|
75
|
+
return prepared;
|
|
76
|
+
}
|
|
77
|
+
static prepare(context, input, engine, binding) {
|
|
78
|
+
const custody = readWorkBatchCustody(context, binding.workId);
|
|
79
|
+
if (!(binding.composition instanceof PreparedMemoryStageResult) || binding.composition.sha256 !== binding.compositionSha256
|
|
80
|
+
|| custody.scope.run_id !== binding.runId || custody.scope.stage !== binding.composition.authoringStage()
|
|
81
|
+
|| custody.scope.parent_work_id !== binding.coordinatorWorkId || custody.scope.request_key !== binding.requestKey)
|
|
82
|
+
refuse();
|
|
83
|
+
const batch = binding.composition.compositionBatch({ ...binding, resultSchema: "dd-flow/memory-composition-work-result@1" });
|
|
84
|
+
if (hybridDigest(batch.works) !== custody.batch_sha256 || batch.works.length !== Object.keys(custody.work_ids).length
|
|
85
|
+
|| batch.works.some(item => !Object.hasOwn(custody.work_ids, item.key)))
|
|
86
|
+
refuse();
|
|
87
|
+
const assigned = batch.works.find(item => item.key === custody.item_key);
|
|
88
|
+
const row = context.db.get("SELECT * FROM works WHERE project_id = ? AND run_id = ? AND work_id = ?", [custody.scope.project_id, binding.runId, binding.workId]);
|
|
89
|
+
if (!assigned || !row || row.parent_work_id !== binding.coordinatorWorkId || row.task !== assigned.task
|
|
90
|
+
|| row.launch_policy !== assigned.launch_policy || row.result_schema !== assigned.result_schema
|
|
91
|
+
|| hybridDigest(JSON.parse(row.depends_on_json)) !== hybridDigest(assigned.depends_on.map(key => custody.work_ids[key]))
|
|
92
|
+
|| hybridDigest(JSON.parse(row.payload_json)) !== hybridDigest({ ...assigned.payload, _dd_flow_batch_request: {
|
|
93
|
+
request_sha256: custody.request_sha256, batch_sha256: custody.batch_sha256, item_key: custody.item_key
|
|
94
|
+
} }))
|
|
95
|
+
refuse();
|
|
96
|
+
const roots = assignedRoots(context, custody);
|
|
97
|
+
const result = PreparedMemoryCompositionWorkResult.prepare(input, engine, { ...binding, workKey: custody.item_key,
|
|
98
|
+
roots });
|
|
99
|
+
const route = binding.composition.compositionRoutes().find(item => item.key === custody.item_key);
|
|
100
|
+
if (!route)
|
|
101
|
+
refuse();
|
|
102
|
+
return new PreparedRegisteredMemoryCompositionWorkResult(custody, roots, result, runtimeHarness(route.execution.worker));
|
|
103
|
+
}
|
|
104
|
+
bytes() { return this.#result.bytes(); }
|
|
105
|
+
/** Physical I/O stays outside the writer; the reservation rechecks SQL only. */
|
|
106
|
+
revalidate(context) { this.#stageBinding?.revalidate(context); this.assertCustody(context); this.#result.revalidate(); }
|
|
107
|
+
assertCustody(context) {
|
|
108
|
+
if (hybridDigest(readWorkBatchCustody(context, this.#custody.work_id)) !== hybridDigest(this.#custody)
|
|
109
|
+
|| hybridDigest(assignedRoots(context, this.#custody)) !== hybridDigest(this.#roots))
|
|
110
|
+
refuse();
|
|
111
|
+
if (this.#registration && memoryCompositionRegistrationDigest(context, this.#registration.scope) !== this.#registration.sha256)
|
|
112
|
+
refuse();
|
|
113
|
+
this.#stageBinding?.assertCustody(context);
|
|
114
|
+
}
|
|
115
|
+
/** Active settlement authority is separate from immutable allocation custody. */
|
|
116
|
+
assertSettlementScope(context, sessionId, workSessionId) {
|
|
117
|
+
this.assertCustody(context);
|
|
118
|
+
const scope = this.#custody.scope;
|
|
119
|
+
const run = context.db.get("SELECT index_json FROM runs WHERE project_id = ? AND id = ?", [scope.project_id, scope.run_id]);
|
|
120
|
+
const index = run ? JSON.parse(run.index_json) : null;
|
|
121
|
+
const authoringStage = scope.stage;
|
|
122
|
+
if (!["compose", "upgrade"].includes(authoringStage))
|
|
123
|
+
refuse();
|
|
124
|
+
assertRunBundleSqlAuthority(context, { projectId: scope.project_id, runId: scope.run_id }, index?.execution_bundle);
|
|
125
|
+
const stage = index?.stage_runs?.findLast((item) => item.stage === authoringStage && item.status === "running");
|
|
126
|
+
if (!this.#registration || !this.#stageBinding || index?.current_stage !== authoringStage || !stage || (stage.attempt ?? "try-001") !== scope.attempt
|
|
127
|
+
|| !stageWorkIds(context, scope.project_id, scope.run_id, authoringStage).has(this.workId)
|
|
128
|
+
|| !stageWorkIds(context, scope.project_id, scope.run_id, authoringStage).has(scope.parent_work_id)
|
|
129
|
+
|| !context.db.get("SELECT 1 FROM work_sessions WHERE id = ? AND work_id = ? AND session_id = ? AND status = 'running'", [workSessionId, this.workId, sessionId])
|
|
130
|
+
|| !context.db.get("SELECT 1 FROM works WHERE work_id = ? AND project_id = ? AND run_id = ? AND status = 'running'", [scope.parent_work_id, scope.project_id, scope.run_id])
|
|
131
|
+
|| !context.db.get("SELECT 1 FROM sessions s JOIN runs r ON r.project_id = s.project_id AND r.id = s.run_id WHERE s.project_id = ? AND s.session_id = ? AND s.run_id = ? AND s.worker_id = ? AND s.harness = ? AND s.status = 'active' AND s.current_stage = 'work' AND s.project_root = r.project_root AND s.workspace_path = r.workspace_root", [scope.project_id, sessionId, scope.run_id, this.workId, this.#harness])) {
|
|
132
|
+
throw new AppError("memory_work_settlement_scope_invalid", "Composition Work settlement no longer belongs to its active stage and Session", 1, { work_id: this.workId, effect: "no_effect" });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Called inside the Work settlement writer, before its status CAS. The
|
|
136
|
+
* receipt commits or rolls back with the result and physical WorkSession.
|
|
137
|
+
* It retains successful output preparation without requiring an obsolete
|
|
138
|
+
* writer artifact to survive a declared dependent assembly unchanged.
|
|
139
|
+
*/
|
|
140
|
+
recordSettlement(context, sessionId, workSessionId) {
|
|
141
|
+
this.assertSettlementScope(context, sessionId, workSessionId);
|
|
142
|
+
const registration = this.#registration;
|
|
143
|
+
const rows = context.db.all("SELECT 1 FROM audit_events WHERE project_id=? AND event_type='memory.composition_work_settlement' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.work_id')=? LIMIT 1", [this.#custody.scope.project_id, this.#custody.scope.run_id, this.workId]);
|
|
144
|
+
if (rows.length)
|
|
145
|
+
refuse();
|
|
146
|
+
const session = context.db.get("SELECT provider_session_id FROM sessions WHERE project_id=? AND session_id=?", [this.#custody.scope.project_id, sessionId]);
|
|
147
|
+
if (!session || typeof session.provider_session_id !== "string" || !session.provider_session_id)
|
|
148
|
+
refuse();
|
|
149
|
+
appendAudit(context, { projectId: this.#custody.scope.project_id, eventType: "memory.composition_work_settlement", payload: {
|
|
150
|
+
schema_id: "dd-flow/memory-composition-work-settlement@1", run_id: this.#custody.scope.run_id, work_id: this.workId,
|
|
151
|
+
work_session_id: workSessionId, session_id: sessionId, harness: this.#harness, provider_session_id: session.provider_session_id,
|
|
152
|
+
scope: registration.scope, registration_sha256: registration.sha256,
|
|
153
|
+
allocation_sha256: hybridDigest(this.#custody), roots: this.#roots, result_sha256: this.sha256
|
|
154
|
+
} });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
import { AdmittedFrozenEngine } from "./frozen-engine.js";
|
|
5
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
6
|
+
import { PreparedMemoryStageResult, memorySourceKey } from "./memory-stage-results.js";
|
|
7
|
+
import { ObservedMemorySources } from "./memory-source-observations.js";
|
|
8
|
+
import { parseMemoryWorkResultProposal } from "./memory-work-result-json.js";
|
|
9
|
+
const schemaId = "dd-flow/memory-composition-work-result@1";
|
|
10
|
+
function refuse(reason) {
|
|
11
|
+
throw new AppError("memory_composition_work_result_invalid", "Composition Work result lacks assigned output proof", 2, { reason, phase: "prepare", effect: "no_effect" });
|
|
12
|
+
}
|
|
13
|
+
/** Frozen schema/assignment checks only. Retained outputs may have been
|
|
14
|
+
* overwritten by a declared dependent assembly; this is not current-byte or
|
|
15
|
+
* settlement authority. The productive Work path also observes physical bytes.
|
|
16
|
+
*/
|
|
17
|
+
export function validateMemoryCompositionWorkResult(input, engine, binding) {
|
|
18
|
+
try {
|
|
19
|
+
if (input.byteLength < 1 || input.byteLength > 1024 * 1024 || !binding.workId
|
|
20
|
+
|| !(engine instanceof AdmittedFrozenEngine) || !(binding.composition instanceof PreparedMemoryStageResult)
|
|
21
|
+
|| binding.composition.sha256 !== binding.compositionSha256)
|
|
22
|
+
refuse("foreign_preparation_binding");
|
|
23
|
+
const value = parseMemoryWorkResultProposal(input, "memory_composition_work_result_invalid");
|
|
24
|
+
const schema = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(engine.schema("memory-composition-work-result")));
|
|
25
|
+
if (schema.$id !== schemaId || !new Ajv2020({ strict: true, validateFormats: false }).compile(schema)(value))
|
|
26
|
+
refuse("invalid_result_schema");
|
|
27
|
+
const work = binding.composition.compositionBatch({ ...binding, resultSchema: schemaId }).works.find(item => item.key === binding.workKey);
|
|
28
|
+
if (!work)
|
|
29
|
+
refuse("unassigned_work_key");
|
|
30
|
+
const packet = work.payload.memory_composition;
|
|
31
|
+
if (value.run_id !== binding.runId || value.work_id !== binding.workId || value.packet_sha256 !== packet.packet_sha256)
|
|
32
|
+
refuse("foreign_result_identity");
|
|
33
|
+
if (value.outcome !== "accepted")
|
|
34
|
+
refuse("work_not_accepted");
|
|
35
|
+
const ids = value.units.map(unit => unit.id);
|
|
36
|
+
if (new Set(ids).size !== ids.length || ids.length !== packet.unit_ids.length || ids.some(id => !packet.unit_ids.includes(id)))
|
|
37
|
+
refuse("changed_unit_coverage");
|
|
38
|
+
const aliases = new Map();
|
|
39
|
+
for (const unit of value.units) {
|
|
40
|
+
for (const artifact of unit.artifacts) {
|
|
41
|
+
const logical = artifact.path;
|
|
42
|
+
if (logical.includes("\\") || logical.includes("\0") || logical.split("/").some(segment => !segment || segment === "." || segment === ".."))
|
|
43
|
+
refuse("unsafe_artifact_path");
|
|
44
|
+
if (!packet.write_scopes.some(scope => scope.root === artifact.root && (logical === scope.path || logical.startsWith(`${scope.path}/`))))
|
|
45
|
+
refuse("artifact_outside_write_scope");
|
|
46
|
+
if (!binding.composition.allowsCompositionOutput(artifact.root, logical))
|
|
47
|
+
refuse("private_composition_artifact");
|
|
48
|
+
const alias = memorySourceKey(artifact.root, logical.normalize("NFC").toLowerCase());
|
|
49
|
+
const identity = hybridDigest({ path: logical, sha256: artifact.sha256 });
|
|
50
|
+
if (aliases.has(alias) && aliases.get(alias) !== identity)
|
|
51
|
+
refuse("conflicting_artifact_reference");
|
|
52
|
+
aliases.set(alias, identity);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof AppError && ["memory_composition_work_result_invalid", "frozen_engine_invalid", "memory_stage_result_invalid"].includes(error.code))
|
|
59
|
+
throw error;
|
|
60
|
+
return refuse("invalid_result_or_binding");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Output-byte preparation only. The handler still owns SQL packet custody,
|
|
64
|
+
* physical Session settlement, actual write-boundary enforcement and semantic acceptance.
|
|
65
|
+
*/
|
|
66
|
+
export class PreparedMemoryCompositionWorkResult {
|
|
67
|
+
sha256;
|
|
68
|
+
#bytes;
|
|
69
|
+
#observed;
|
|
70
|
+
constructor(bytes, observed) {
|
|
71
|
+
this.#bytes = bytes;
|
|
72
|
+
this.#observed = observed;
|
|
73
|
+
this.sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
74
|
+
Object.freeze(this);
|
|
75
|
+
}
|
|
76
|
+
static prepare(input, engine, binding) {
|
|
77
|
+
try {
|
|
78
|
+
const bytes = Buffer.from(input), value = validateMemoryCompositionWorkResult(bytes, engine, binding);
|
|
79
|
+
const artifacts = value.units.flatMap(unit => unit.artifacts), selected = new Map();
|
|
80
|
+
for (const artifact of artifacts) {
|
|
81
|
+
selected.set(memorySourceKey(artifact.root, artifact.path), { root: artifact.root, path: artifact.path });
|
|
82
|
+
}
|
|
83
|
+
// Upgrade scopes are exact admitted file paths, not init-style output
|
|
84
|
+
// directories. Retain their output hashes while this Work is still
|
|
85
|
+
// correctable; publication cannot repair an already settled omission.
|
|
86
|
+
if (binding.composition.authoringStage() === "upgrade") {
|
|
87
|
+
const work = binding.composition.compositionBatch({ ...binding, resultSchema: schemaId }).works.find(item => item.key === binding.workKey);
|
|
88
|
+
const missing = work.payload.memory_composition.write_scopes
|
|
89
|
+
.filter(scope => scope.root === "workspace" && !selected.has(memorySourceKey(scope.root, scope.path)))
|
|
90
|
+
.map(scope => scope.path);
|
|
91
|
+
if (missing.length)
|
|
92
|
+
throw new AppError("memory_composition_work_result_invalid", "Include every assigned upgrade workspace file with its current hash in this Work result; correct only the result proposal, not settled peer Work or retained inputs", 2, { reason: "missing_workspace_outputs", phase: "prepare", effect: "no_effect", recoverable: true,
|
|
93
|
+
missing_count: missing.length, missing_paths: missing.slice(0, 32), result_sha256: createHash("sha256").update(bytes).digest("hex") });
|
|
94
|
+
}
|
|
95
|
+
const observed = ObservedMemorySources.capture(binding.roots, [...selected.values()]), hashes = observed.hashes();
|
|
96
|
+
if (artifacts.some(artifact => hashes.get(memorySourceKey(artifact.root, artifact.path)) !== artifact.sha256))
|
|
97
|
+
refuse("changed_artifact_bytes");
|
|
98
|
+
return new PreparedMemoryCompositionWorkResult(bytes, observed);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof AppError && ["memory_composition_work_result_invalid", "frozen_engine_invalid", "memory_source_observation_failed", "memory_stage_result_invalid"].includes(error.code))
|
|
102
|
+
throw error;
|
|
103
|
+
return refuse("invalid_result_or_binding");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
bytes() { return Buffer.from(this.#bytes); }
|
|
107
|
+
revalidate() { this.#observed.revalidate(); }
|
|
108
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
3
|
+
import { runtimeHarness } from "./execution-policy.js";
|
|
4
|
+
import { PreparedRegisteredCorrectedMemoryReview } from "./memory-corrected-review-registration.js";
|
|
5
|
+
import { PreparedCorrectedMemoryReviewInputs } from "./memory-corrected-review-inputs.js";
|
|
6
|
+
import { readMemoryReviewWorkSettlement } from "./memory-review-acceptance.js";
|
|
7
|
+
import { validateMemoryReviewWorkResult } from "./memory-review-work-results.js";
|
|
8
|
+
import { ObservedMemorySources } from "./memory-source-observations.js";
|
|
9
|
+
import { memorySourceKey } from "./memory-stage-results.js";
|
|
10
|
+
import { correctedMemoryReviewFindings } from "./memory-corrected-review-findings.js";
|
|
11
|
+
import { correctedMemoryReviewUnits } from "./memory-corrected-review-projection.js";
|
|
12
|
+
import { PreparedMemoryStageResult } from "./memory-stage-results.js";
|
|
13
|
+
const token = Symbol("corrected-memory-review-acceptance");
|
|
14
|
+
function refuse(reason) {
|
|
15
|
+
throw new AppError("memory_corrected_review_acceptance_invalid", "Selective review lacks independently registered and settled reviewer custody", 2, { reason, effect: "no_effect" });
|
|
16
|
+
}
|
|
17
|
+
/** Selective fan-in only, not finding resolution or Stage acceptance. Every
|
|
18
|
+
* allocated affected unit needs its own independent published settlement.
|
|
19
|
+
* Untouched initial reviewers must not be silently replaced or rerun. */
|
|
20
|
+
export class PreparedCorrectedMemoryReviewAcceptance {
|
|
21
|
+
static isPrepared(value) {
|
|
22
|
+
return typeof value === "object" && value !== null && #registration in value;
|
|
23
|
+
}
|
|
24
|
+
sha256;
|
|
25
|
+
#registration;
|
|
26
|
+
#workers;
|
|
27
|
+
#results;
|
|
28
|
+
#harness;
|
|
29
|
+
#observed;
|
|
30
|
+
constructor(key, registration, workers, results, harness, observed) {
|
|
31
|
+
if (key !== token)
|
|
32
|
+
refuse("acceptance_token_required");
|
|
33
|
+
this.#registration = registration;
|
|
34
|
+
this.#workers = workers;
|
|
35
|
+
this.#results = structuredClone(results);
|
|
36
|
+
this.#harness = harness;
|
|
37
|
+
this.#observed = observed;
|
|
38
|
+
this.sha256 = hybridDigest({ registration_sha256: registration.sha256, workers: workers.map(worker => ({
|
|
39
|
+
work_id: worker.workId, authority_sha256: worker.authority, result: worker.result
|
|
40
|
+
})), results });
|
|
41
|
+
Object.freeze(this);
|
|
42
|
+
}
|
|
43
|
+
static prepare(context, registration) {
|
|
44
|
+
if (!PreparedRegisteredCorrectedMemoryReview.isPrepared(registration))
|
|
45
|
+
refuse("prepared_corrected_registration_required");
|
|
46
|
+
if (!PreparedCorrectedMemoryReviewInputs.isPrepared(registration.inputs()))
|
|
47
|
+
refuse("first_corrected_registration_required");
|
|
48
|
+
if (context.db.isOwnedWriteTransaction?.())
|
|
49
|
+
refuse("preparation_outside_writer_required");
|
|
50
|
+
registration.revalidate(context);
|
|
51
|
+
const receipt = registration.receipt(), view = receipt.view, bundle = registration.inputs().bundle(), batch = registration.batch();
|
|
52
|
+
if (view.scope.bundle_sha256 !== bundle.sha256 || view.scope.execution_sha256 !== bundle.execution.sha256)
|
|
53
|
+
refuse("foreign_wave_bundle");
|
|
54
|
+
const harness = runtimeHarness(bundle.execution.work("review").worker);
|
|
55
|
+
const workers = context.db.readSnapshot(() => batch.works.map(item => readMemoryReviewWorkSettlement(context, receipt, receipt.work_ids[item.key], harness)));
|
|
56
|
+
const results = workers.map((worker, index) => validateMemoryReviewWorkResult(worker.bytes, bundle.engine(), {
|
|
57
|
+
workId: worker.workId, packet: batch.works[index].payload.memory_review, references: view.run_inputs
|
|
58
|
+
}));
|
|
59
|
+
assertSelectiveMemoryReviewCoverage(view.affected_unit_ids, results);
|
|
60
|
+
const root = context.db.get("SELECT run_root,run_dir FROM runs WHERE project_id=? AND id=?", [view.scope.project_id, view.scope.run_id]);
|
|
61
|
+
if (!root)
|
|
62
|
+
refuse("owned_run_missing");
|
|
63
|
+
const observed = ObservedMemorySources.capture({ run: root.run_root ?? root.run_dir }, workers.map(worker => ({ root: "run", path: worker.result.path })));
|
|
64
|
+
const hashes = observed.hashes();
|
|
65
|
+
if (workers.some(worker => hashes.get(memorySourceKey("run", worker.result.path)) !== worker.result.sha256))
|
|
66
|
+
refuse("published_review_result_changed");
|
|
67
|
+
const prepared = new PreparedCorrectedMemoryReviewAcceptance(token, registration, workers, results, harness, observed);
|
|
68
|
+
prepared.revalidate(context);
|
|
69
|
+
return prepared;
|
|
70
|
+
}
|
|
71
|
+
registration() { return this.#registration; }
|
|
72
|
+
results() { return structuredClone(this.#results); }
|
|
73
|
+
findingProjection() {
|
|
74
|
+
const wave = this.#registration.inputs().completedWave(), original = wave.registration().review();
|
|
75
|
+
const batch = wave.registration().batch(), receipt = wave.registration().receipt();
|
|
76
|
+
return correctedMemoryReviewFindings({ original: original.results(), current: this.results(),
|
|
77
|
+
diagnostics: original.original().registration().view.diagnostic_findings,
|
|
78
|
+
diagnosticReference: original.original().registration().view.run_inputs.find(ref => ref.root === "run" && ref.path === `${original.original().bundle().descriptor.stage("verify").directory}/result.json`),
|
|
79
|
+
affected: this.#registration.receipt().view.affected_unit_ids, originalReferences: original.references(), currentReferences: this.references(),
|
|
80
|
+
repairs: wave.repairResults().map(repair => ({ ...repair, unit_ids: batch.works.find(item => receipt.work_ids[item.key] === repair.work_id).payload.memory_repair.unit_ids })) });
|
|
81
|
+
}
|
|
82
|
+
resultProjection() {
|
|
83
|
+
const wave = this.#registration.inputs().completedWave(), original = wave.registration().review();
|
|
84
|
+
const coverage = correctedMemoryReviewUnits({ view: this.#registration.receipt().view, original: original.results(), current: this.results(),
|
|
85
|
+
originalReferences: original.references(), currentReferences: this.references(), repairWorkIds: wave.repairResults().map(repair => repair.work_id) });
|
|
86
|
+
return { ...coverage, ...this.findingProjection() };
|
|
87
|
+
}
|
|
88
|
+
assertResult(result) {
|
|
89
|
+
if (!(result instanceof PreparedMemoryStageResult))
|
|
90
|
+
refuse("prepared_result_required");
|
|
91
|
+
const value = result.value(), receipt = this.#registration.receipt(), expected = this.resultProjection();
|
|
92
|
+
if (value.run_id !== receipt.run_id || value.stage !== "review" || value.input_sha256 !== receipt.scope.input_sha256
|
|
93
|
+
|| hybridDigest({ units: value.units, findings: value.findings, outcome: value.outcome, details: value.details }) !== hybridDigest(expected))
|
|
94
|
+
refuse("review_claim_differs_from_settled_wave");
|
|
95
|
+
}
|
|
96
|
+
references() {
|
|
97
|
+
return this.#workers.map((worker, index) => ({ reviewer_work_id: worker.workId,
|
|
98
|
+
input_sha256: this.#registration.receipt().input_sha256, result: { ...worker.result }, unit_ids: [this.#results[index].unit_id] }));
|
|
99
|
+
}
|
|
100
|
+
settlementProof(context) {
|
|
101
|
+
this.assertCustody(context);
|
|
102
|
+
const receipt = this.#registration.receipt();
|
|
103
|
+
return { registration_scope: structuredClone(receipt.scope), registration_sha256: this.#registration.sha256, wave: receipt.wave,
|
|
104
|
+
check_receipt_sha256: receipt.check_receipt_sha256, workers: this.#workers.map(worker => ({
|
|
105
|
+
work_id: worker.workId, authority_sha256: worker.authority, result: { ...worker.result }
|
|
106
|
+
})) };
|
|
107
|
+
}
|
|
108
|
+
assertCustody(context) {
|
|
109
|
+
this.#registration.assertCustody(context);
|
|
110
|
+
const receipt = this.#registration.receipt();
|
|
111
|
+
for (const worker of this.#workers)
|
|
112
|
+
if (readMemoryReviewWorkSettlement(context, receipt, worker.workId, this.#harness).authority !== worker.authority)
|
|
113
|
+
refuse("review_settlement_changed");
|
|
114
|
+
}
|
|
115
|
+
revalidate(context) {
|
|
116
|
+
this.#registration.revalidate(context);
|
|
117
|
+
this.#observed.revalidate();
|
|
118
|
+
this.assertCustody(context);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Metadata completeness check only; this does not prove SQL/Session custody. */
|
|
122
|
+
export function assertSelectiveMemoryReviewCoverage(affected, results) {
|
|
123
|
+
if (!Array.isArray(affected) || !affected.length || affected.length > 256 || affected.some(id => typeof id !== "string" || !id)
|
|
124
|
+
|| new Set(affected).size !== affected.length || !Array.isArray(results) || results.length !== affected.length
|
|
125
|
+
|| results.some(result => !result || typeof result.unit_id !== "string" || typeof result.work_id !== "string" || !result.work_id
|
|
126
|
+
|| !affected.includes(result.unit_id)) || new Set(results.map(result => result.unit_id)).size !== affected.length
|
|
127
|
+
|| new Set(results.map(result => result.work_id)).size !== results.length)
|
|
128
|
+
refuse("selective_review_coverage_changed");
|
|
129
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
3
|
+
import { memoryReviewWorkerSchema } from "./memory-review-registration.js";
|
|
4
|
+
import { memoryReviewWaveByteLimit } from "./memory-review-limits.js";
|
|
5
|
+
/** Payload projection only. Fresh check, registered input/copy/Session and
|
|
6
|
+
* independent Work settlement are not supplied by a coordinator's JSON. */
|
|
7
|
+
export function memoryCorrectedReviewBatch(view) {
|
|
8
|
+
if (!(view.schema_id === "dd-flow/memory-corrected-review-inputs@1" && view.wave === 1
|
|
9
|
+
|| view.schema_id === "dd-flow/memory-corrected-review-inputs@2" && view.wave === 2)
|
|
10
|
+
|| !Array.isArray(view.assignments) || !view.assignments.length || view.assignments.length > 256) {
|
|
11
|
+
throw new AppError("memory_corrected_review_batch_invalid", "Corrected reviewer batch lacks bounded current assignments", 2, { effect: "no_effect" });
|
|
12
|
+
}
|
|
13
|
+
let total = 0;
|
|
14
|
+
const inputSha256 = hybridDigest(view);
|
|
15
|
+
return { works: view.assignments.map((assignment, index) => {
|
|
16
|
+
const key = `review-${String(index + 1).padStart(3, "0")}`;
|
|
17
|
+
const inputPaths = view.upgrade_baseline ? new Set(assignment.inputs.map(ref => `${ref.root}\0${ref.path}`)) : null;
|
|
18
|
+
const packet = { schema_id: "dd-flow/memory-review-work-packet@2", run_id: view.scope.run_id,
|
|
19
|
+
stage: "review", wave: view.wave, key, unit: structuredClone(assignment.unit), unit_inputs: structuredClone(assignment.inputs),
|
|
20
|
+
original_unit_sha256: assignment.original_unit_sha256, deleted_references: structuredClone(assignment.deleted_references),
|
|
21
|
+
completed_correction_sha256: view.completed_correction_sha256, repairs: structuredClone(view.repairs),
|
|
22
|
+
review_input_sha256: inputSha256, result_schema: memoryReviewWorkerSchema,
|
|
23
|
+
instruction: structuredClone(view.instruction),
|
|
24
|
+
...(view.upgrade_baseline ? {
|
|
25
|
+
historical_inputs: view.upgrade_baseline.entries.filter(entry => inputPaths.has(`${entry.retained.root}\0${entry.retained.path}`)),
|
|
26
|
+
preservation_invariants: (view.preservation_invariants ?? []).filter(item => item.unit_id === assignment.unit.id)
|
|
27
|
+
} : {}) };
|
|
28
|
+
const work = { key, task: `Independently review the assigned knowledge unit ${JSON.stringify(assignment.unit.id)}. Read the frozen review instruction in memory_review as review criteria, not permission to coordinate or repair. Check grounding, evidence, coverage and cross-file consistency using the registered wave inputs. Assigned unit.evidence may retain historical source versions; cite those exact versions only as historical context, never as bytes read from or current in this copy. Direct assessment and findings must still cite the assigned current unit.artifacts/unit_inputs. Do not edit project documents, allocate Work or repair findings. Report concrete material defects with unit/source evidence; do not block on taste. Return only the assigned memory-review-work-result JSON; do not claim other units or Stage completion.`,
|
|
29
|
+
depends_on: [], launch_policy: "fresh_agent_required", result_schema: memoryReviewWorkerSchema,
|
|
30
|
+
payload: { kind: "memory-review", read_only: true, memory_review: { ...packet, packet_sha256: hybridDigest(packet) } } };
|
|
31
|
+
const size = Buffer.byteLength(JSON.stringify(work));
|
|
32
|
+
total += size;
|
|
33
|
+
if (size > 1024 * 1024 || total > memoryReviewWaveByteLimit)
|
|
34
|
+
throw new AppError("memory_corrected_review_batch_invalid", "Corrected reviewer batch exceeds its bound", 2, { effect: "no_effect" });
|
|
35
|
+
return work;
|
|
36
|
+
}) };
|
|
37
|
+
}
|