@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,108 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { isDiagnosticFlow, diagnosticFlowStages } from "../domain/diagnostic-flows.js";
|
|
3
|
+
import { readFlowRunExecutionBundle } from "./runs.js";
|
|
4
|
+
import { requireProjectByRoot } from "./projects.js";
|
|
5
|
+
import { resolveProjectRoot } from "../storage/paths.js";
|
|
6
|
+
import { diagnosticSnapshotPaths, readDiagnosticSnapshot, readDiagnosticSnapshotCustody } from "./diagnostic-snapshot.js";
|
|
7
|
+
import { PreparedDescriptorStageStart } from "./descriptor-stage-start.js";
|
|
8
|
+
import { PreparedDescriptorStageCoordinator, readDescriptorStageInput } from "./descriptor-stage-coordinator.js";
|
|
9
|
+
import { PreparedDescriptorStageSettlement } from "./descriptor-stage-settlement.js";
|
|
10
|
+
import { PreparedDescriptorRunSettlement } from "./descriptor-run-settlement.js";
|
|
11
|
+
import { assertDiagnosticCriticResolution, assertDiagnosticReportData, assertDiagnosticStageScope, sealDiagnosticStageLimitations, validateDiagnosticStageResult } from "./diagnostic-stage-results.js";
|
|
12
|
+
import { readAcceptedStageData } from "./stage-report-renderer.js";
|
|
13
|
+
import { registerDiagnosticStageGraph } from "./diagnostic-work-registration.js";
|
|
14
|
+
import { PreparedDiagnosticWorkCollection } from "./diagnostic-work-collection.js";
|
|
15
|
+
import { collectDiagnosticCandidates, sealDiagnosticCandidateIds } from "./diagnostic-work-results.js";
|
|
16
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
17
|
+
import { prepareDiagnosticReport } from "./diagnostic-report.js";
|
|
18
|
+
import { prepareDiagnosticReportPublication } from "./diagnostic-report-publication.js";
|
|
19
|
+
export const diagnosticStageHandlers = Object.freeze(Object.entries(diagnosticFlowStages).flatMap(([flowId, stages]) => stages.map(stage => Object.freeze({ flowId, stage, entryId: "diagnostic-stage-entry", finishId: "diagnostic-stage-finish",
|
|
20
|
+
entry: startDiagnosticStage, finish: finishDiagnosticStage }))));
|
|
21
|
+
function refuse(reason) { throw new AppError("diagnostic_stage_invalid", "Diagnostic stage cannot accept this result", 2, { reason, effect: "no_effect" }); }
|
|
22
|
+
function select(context, input) {
|
|
23
|
+
const bundle = readFlowRunExecutionBundle(context, input), project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
24
|
+
if (!bundle || !isDiagnosticFlow(bundle.manifest.flow_id)
|
|
25
|
+
|| !diagnosticFlowStages[bundle.manifest.flow_id].includes(input.stage))
|
|
26
|
+
refuse("registered_diagnostic_stage_required");
|
|
27
|
+
const frozen = bundle.execution.snapshot().scope;
|
|
28
|
+
const snapshotSelection = { projectId: project.id, projectRoot: frozen.projectRoot, sourceRoot: frozen.projectRoot,
|
|
29
|
+
requestId: frozen.requestId, flowId: bundle.manifest.flow_id };
|
|
30
|
+
const snapshot = readDiagnosticSnapshot(context, snapshotSelection, input.runId);
|
|
31
|
+
if (!snapshot || snapshot.root !== frozen.workspace)
|
|
32
|
+
refuse("snapshot_required");
|
|
33
|
+
return { bundle, snapshot, snapshotSelection, scope: { projectId: project.id, runId: input.runId, stage: input.stage } };
|
|
34
|
+
}
|
|
35
|
+
export function startDiagnosticStage(context, input) {
|
|
36
|
+
const selected = select(context, input);
|
|
37
|
+
const fence = (writer) => {
|
|
38
|
+
if (hybridDigest(readDiagnosticSnapshotCustody(writer, selected.snapshotSelection, input.runId)) !== hybridDigest(selected.snapshot))
|
|
39
|
+
refuse("snapshot_changed");
|
|
40
|
+
};
|
|
41
|
+
const start = PreparedDescriptorStageStart.prepare(context, input).apply(context);
|
|
42
|
+
const coordinator = PreparedDescriptorStageCoordinator.prepare(context, input).apply(context, fence);
|
|
43
|
+
if (["audit", "analyze", "review"].includes(input.stage))
|
|
44
|
+
registerDiagnosticStageGraph(context, input);
|
|
45
|
+
return { ...start, ...coordinator };
|
|
46
|
+
}
|
|
47
|
+
/** Findings are data, not permission to repair. Only registered independent Work
|
|
48
|
+
* may contribute analysis/criticism; terminal acceptance closes runtime only. */
|
|
49
|
+
export function finishDiagnosticStage(context, input) {
|
|
50
|
+
const selected = select(context, input), { bundle, snapshot, scope } = selected;
|
|
51
|
+
const stageInput = readDescriptorStageInput(context, scope, bundle, true, true);
|
|
52
|
+
const previousStage = stageInput.input.predecessor?.stage;
|
|
53
|
+
const previous = previousStage ? readAcceptedStageData(context, { ...scope, stage: previousStage }) : null;
|
|
54
|
+
const prior = previous ? JSON.parse(previous.bytes.toString("utf8")) : null;
|
|
55
|
+
const collection = ["audit", "analyze", "review"].includes(input.stage) ? PreparedDiagnosticWorkCollection.prepare(context, input) : null;
|
|
56
|
+
const candidates = ["audit", "analyze"].includes(input.stage) ? sealDiagnosticCandidateIds(input.bytes, collection.results()) : input.bytes;
|
|
57
|
+
const bytes = sealDiagnosticStageLimitations(candidates, [
|
|
58
|
+
...(prior?.details.limitations ?? []), ...(collection?.results() ?? []).flatMap(work => work.result.limitations)
|
|
59
|
+
], prior?.details.missing_expected_sources ?? []);
|
|
60
|
+
const result = validateDiagnosticStageResult(bytes, bundle.descriptor.stageBlob(input.stage, "result_schema"), {
|
|
61
|
+
flowId: selected.snapshotSelection.flowId, runId: input.runId, stage: input.stage,
|
|
62
|
+
inputSha256: stageInput.inputSha256, snapshotSha256: snapshot.source_sha256, snapshotRoot: diagnosticSnapshotPaths(context, snapshot, input.runId).root,
|
|
63
|
+
predecessors: stageInput.input.predecessor ? [{ stage: stageInput.input.predecessor.stage,
|
|
64
|
+
path: stageInput.input.predecessor.result.path, sha256: stageInput.input.predecessor.result.sha256 }] : []
|
|
65
|
+
});
|
|
66
|
+
if (prior) {
|
|
67
|
+
assertDiagnosticStageScope(result, prior);
|
|
68
|
+
if (prior.details.limitations.some(value => !result.details.limitations.includes(value)))
|
|
69
|
+
refuse("limitation_dropped");
|
|
70
|
+
}
|
|
71
|
+
if (collection) {
|
|
72
|
+
const works = collection.results();
|
|
73
|
+
if (works.some(work => work.result.limitations.some(value => !result.details.limitations.includes(value))))
|
|
74
|
+
refuse("worker_limitation_dropped");
|
|
75
|
+
if (input.stage !== "review") {
|
|
76
|
+
if (hybridDigest(result.details.findings) !== hybridDigest(collectDiagnosticCandidates(works).findings))
|
|
77
|
+
refuse("analysis_not_from_work");
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
if (!prior || hybridDigest(result.details.findings) !== hybridDigest(prior.details.findings))
|
|
81
|
+
refuse("candidate_register_changed");
|
|
82
|
+
for (const decision of result.details.decisions) {
|
|
83
|
+
assertDiagnosticCriticResolution(decision, works.map(work => work.result.decisions));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (input.stage === "report")
|
|
88
|
+
assertDiagnosticReportData(result, prior);
|
|
89
|
+
const analysis = input.stage === "report" ? PreparedDiagnosticWorkCollection.prepare(context, { ...input, stage: snapshot.flowId === "mb-audit" ? "audit" : "analyze" }) : null;
|
|
90
|
+
const critics = input.stage === "report" ? PreparedDiagnosticWorkCollection.prepare(context, { ...input, stage: "review" }) : null;
|
|
91
|
+
const publication = analysis && critics ? prepareDiagnosticReportPublication(context, { ...scope, attempt: stageInput.attempt, inputSha256: stageInput.inputSha256 }, prepareDiagnosticReport(result, analysis.results(), critics.results())) : null;
|
|
92
|
+
publication?.publish();
|
|
93
|
+
const fence = (writer) => {
|
|
94
|
+
if (hybridDigest(readDiagnosticSnapshotCustody(writer, selected.snapshotSelection, input.runId)) !== hybridDigest(snapshot))
|
|
95
|
+
refuse("snapshot_changed");
|
|
96
|
+
if (previous && hybridDigest(readAcceptedStageData(writer, { ...scope, stage: previousStage })) !== hybridDigest(previous))
|
|
97
|
+
refuse("predecessor_changed");
|
|
98
|
+
collection?.assertCustody(writer);
|
|
99
|
+
analysis?.assertCustody(writer);
|
|
100
|
+
critics?.assertCustody(writer);
|
|
101
|
+
publication?.retain(writer);
|
|
102
|
+
};
|
|
103
|
+
const settlement = PreparedDescriptorStageSettlement.prepare(context, { ...input, bytes }).apply(context, fence);
|
|
104
|
+
if (input.stage === "report")
|
|
105
|
+
return { ...settlement,
|
|
106
|
+
...PreparedDescriptorRunSettlement.prepare(context, input).apply(context, fence), reports: publication.manifest.artifacts };
|
|
107
|
+
return settlement;
|
|
108
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
2
|
+
import { diagnosticFlowStages } from "../domain/diagnostic-flows.js";
|
|
3
|
+
import { diagnosticAspects } from "../domain/diagnostic-aspects.js";
|
|
4
|
+
import { AppError } from "../shared/errors.js";
|
|
5
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
6
|
+
import { verifyDiagnosticCoverage, verifyDiagnosticSources } from "./diagnostic-evidence.js";
|
|
7
|
+
const refuse = (reason) => {
|
|
8
|
+
throw new AppError("diagnostic_stage_result_invalid", "Diagnostic result does not match its frozen stage", 2, { reason, effect: "no_effect", ...(reason === "result_schema_invalid" ? { phase: "prepare", recoverable: true } : {}) });
|
|
9
|
+
};
|
|
10
|
+
/** Accepted limitations and missing-source observations belong to predecessor/Work custody, not a coordinator's
|
|
11
|
+
* transcription. Keep its annotations too; validate the complete sealed result
|
|
12
|
+
* with the frozen schema afterwards, without truncating overflowing data. */
|
|
13
|
+
export function sealDiagnosticStageLimitations(bytes, required, acceptedMissingSources = []) {
|
|
14
|
+
if ((!required.length && !acceptedMissingSources.length) || !bytes.length || bytes.length > 1024 * 1024)
|
|
15
|
+
return bytes;
|
|
16
|
+
let value;
|
|
17
|
+
try {
|
|
18
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return bytes;
|
|
22
|
+
}
|
|
23
|
+
let changed = false;
|
|
24
|
+
for (const [key, expected] of [["limitations", required], ["missing_expected_sources", acceptedMissingSources]]) {
|
|
25
|
+
if (!expected.length)
|
|
26
|
+
continue;
|
|
27
|
+
const proposed = value?.details?.[key];
|
|
28
|
+
if (!Array.isArray(proposed) || proposed.some(item => typeof item !== "string"))
|
|
29
|
+
return bytes;
|
|
30
|
+
const missing = [...new Set(expected.filter(item => !proposed.includes(item)))];
|
|
31
|
+
if (missing.length) {
|
|
32
|
+
value.details[key] = [...missing, ...proposed];
|
|
33
|
+
changed = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return changed ? Buffer.from(JSON.stringify(value)) : bytes;
|
|
37
|
+
}
|
|
38
|
+
export function assertDiagnosticStageScope(result, prior) {
|
|
39
|
+
const coverageScope = (value) => value.details.coverage.map(({ id, applicability }) => ({ id, applicability }));
|
|
40
|
+
if (result.details.focus.mode !== prior.details.focus.mode
|
|
41
|
+
// New source gaps are analytical observations, not an expansion of scope.
|
|
42
|
+
// Previously accepted gaps still cannot disappear from the result.
|
|
43
|
+
|| prior.details.missing_expected_sources.some(source => !result.details.missing_expected_sources.includes(source))
|
|
44
|
+
|| hybridDigest(coverageScope(result)) !== hybridDigest(coverageScope(prior)))
|
|
45
|
+
throw new AppError("diagnostic_stage_invalid", "Diagnostic stage cannot accept this result", 2, { reason: "accepted_scope_changed", effect: "no_effect" });
|
|
46
|
+
// Focus prose is retained selection, not a new stage heading. A different
|
|
47
|
+
// proposal is never accepted, but can copy the exact predecessor and retry.
|
|
48
|
+
if (hybridDigest(result.details.focus) !== hybridDigest(prior.details.focus))
|
|
49
|
+
throw new AppError("diagnostic_stage_invalid", "Copy details.focus unchanged from the accepted predecessor; put the stage summary in summary, not the retained focus", 2, { reason: "accepted_focus_changed", effect: "no_effect", phase: "prepare", recoverable: true });
|
|
50
|
+
// Applicability is already accepted. Analytical progress belongs in findings,
|
|
51
|
+
// sources and limitations, not edits to the retained preflight annotations.
|
|
52
|
+
if (hybridDigest(result.details.coverage) !== hybridDigest(prior.details.coverage))
|
|
53
|
+
throw new AppError("diagnostic_stage_invalid", "Copy details.coverage unchanged from the accepted predecessor; put new observations in findings, sources or limitations", 2, { reason: "accepted_coverage_annotations_changed", effect: "no_effect", phase: "prepare", recoverable: true });
|
|
54
|
+
}
|
|
55
|
+
export function assertDiagnosticReportData(result, prior) {
|
|
56
|
+
// Reporting may disclose additional uncertainty, never revise reviewed facts
|
|
57
|
+
// or erase any accepted limitation. This comparison does not rewrite either result.
|
|
58
|
+
if (!prior || prior.details.limitations.some(value => !result.details.limitations.includes(value))
|
|
59
|
+
|| hybridDigest({ ...result.details, limitations: prior.details.limitations }) !== hybridDigest(prior.details))
|
|
60
|
+
throw new AppError("diagnostic_stage_invalid", "Diagnostic stage cannot accept this result", 2, { reason: "report_changed_reviewed_data", effect: "no_effect" });
|
|
61
|
+
}
|
|
62
|
+
export function assertDiagnosticCriticResolution(decision, critics) {
|
|
63
|
+
const selected = decision;
|
|
64
|
+
const votes = critics.flat().filter(item => item.finding_id === decision.finding_id);
|
|
65
|
+
// Duplicate/rejected entries remain trace, not accepted findings. Their
|
|
66
|
+
// supported severity may be reconciled separately without inventing a vote.
|
|
67
|
+
// An accepted finding still requires one critic to endorse the whole pair.
|
|
68
|
+
const nonAccepting = ["duplicate", "rejected"].includes(selected.disposition);
|
|
69
|
+
if (votes.some(item => item.disposition === selected.disposition && item.severity === selected.severity)
|
|
70
|
+
|| nonAccepting && votes.some(item => item.disposition === selected.disposition)
|
|
71
|
+
&& votes.some(item => item.severity === selected.severity))
|
|
72
|
+
return;
|
|
73
|
+
throw new AppError("diagnostic_stage_invalid", "Use a supported critic resolution; preserve all independent critic decisions and explain disagreements", 2, { reason: "unsupported_critic_resolution", effect: "no_effect", phase: "prepare", recoverable: true,
|
|
74
|
+
finding_id: selected.finding_id, supported_resolutions: votes.map(item => ({ disposition: item.disposition, severity: item.severity })) });
|
|
75
|
+
}
|
|
76
|
+
/** Frozen schema and exact CLI-issued identity precede semantic evidence checks.
|
|
77
|
+
* This does not assert that independent Work/critics have settled. */
|
|
78
|
+
export function validateDiagnosticStageResult(bytes, schemaBytes, binding) {
|
|
79
|
+
if (!bytes.length || bytes.length > 1024 * 1024 || schemaBytes.length > 1024 * 1024)
|
|
80
|
+
refuse("result_exceeds_bound");
|
|
81
|
+
const validate = (() => {
|
|
82
|
+
try {
|
|
83
|
+
const schema = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(schemaBytes));
|
|
84
|
+
if (schema.$id !== "dd-flow/diagnostic-stage-result@1")
|
|
85
|
+
refuse("frozen_schema_invalid");
|
|
86
|
+
return new Ajv2020({ strict: false, validateFormats: false }).compile(schema);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return refuse("frozen_schema_invalid");
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
let value;
|
|
93
|
+
try {
|
|
94
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return refuse("result_schema_invalid");
|
|
98
|
+
}
|
|
99
|
+
if (!validate(value))
|
|
100
|
+
refuse("result_schema_invalid");
|
|
101
|
+
if (value.flow_id !== binding.flowId || value.run_id !== binding.runId || value.stage !== binding.stage
|
|
102
|
+
|| !diagnosticFlowStages[binding.flowId].includes(binding.stage)
|
|
103
|
+
|| value.input_sha256 !== binding.inputSha256 || value.snapshot_sha256 !== binding.snapshotSha256
|
|
104
|
+
|| hybridDigest(value.predecessors) !== hybridDigest(binding.predecessors))
|
|
105
|
+
refuse("foreign_result_binding");
|
|
106
|
+
if ((binding.flowId === "mb-audit") !== (value.details.focus.mode === "memory_bank"))
|
|
107
|
+
refuse("foreign_focus");
|
|
108
|
+
verifyDiagnosticCoverage(binding.snapshotRoot, diagnosticAspects[binding.flowId].map(item => item.id), value.details.coverage);
|
|
109
|
+
verifyDiagnosticSources(binding.snapshotRoot, value.details.sources);
|
|
110
|
+
const ids = new Set();
|
|
111
|
+
for (const finding of value.details.findings) {
|
|
112
|
+
if (ids.has(finding.id) || !value.details.coverage.some(item => item.id === finding.aspect_id && item.applicability === "applicable")
|
|
113
|
+
|| !finding.evidence.length)
|
|
114
|
+
refuse("finding_outside_coverage");
|
|
115
|
+
ids.add(finding.id);
|
|
116
|
+
verifyDiagnosticSources(binding.snapshotRoot, finding.evidence);
|
|
117
|
+
}
|
|
118
|
+
const decided = new Set();
|
|
119
|
+
for (const decision of value.details.decisions) {
|
|
120
|
+
if (!ids.has(decision.finding_id) || decided.has(decision.finding_id))
|
|
121
|
+
refuse("foreign_or_duplicate_decision");
|
|
122
|
+
decided.add(decision.finding_id);
|
|
123
|
+
verifyDiagnosticSources(binding.snapshotRoot, decision.evidence);
|
|
124
|
+
}
|
|
125
|
+
if (binding.stage === "preflight" && (ids.size || decided.size))
|
|
126
|
+
refuse("preflight_cannot_claim_analysis");
|
|
127
|
+
if (["audit", "analyze"].includes(binding.stage) && decided.size)
|
|
128
|
+
refuse("analysis_cannot_claim_independent_review");
|
|
129
|
+
if (["review", "report"].includes(binding.stage) && decided.size !== ids.size)
|
|
130
|
+
refuse("unresolved_finding");
|
|
131
|
+
return value;
|
|
132
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { isDiagnosticFlow } from "../domain/diagnostic-flows.js";
|
|
3
|
+
import { PreparedInstalledFlowSource } from "./installed-flow-source.js";
|
|
4
|
+
import { FrozenGenericExecution } from "./generic-execution.js";
|
|
5
|
+
import { AdmittedFrozenEngine } from "./frozen-engine.js";
|
|
6
|
+
import { prepareDiagnosticSnapshot, diagnosticSnapshotRoot } from "./diagnostic-snapshot.js";
|
|
7
|
+
import { prepareDiagnosticRunBundle } from "./diagnostic-run-bundle.js";
|
|
8
|
+
import { PreparedDescriptorRunStart } from "./descriptor-run-start.js";
|
|
9
|
+
import { readRunStartRequest } from "./run-start-custody.js";
|
|
10
|
+
import { requireProjectByRoot } from "./projects.js";
|
|
11
|
+
import { resolveProjectRoot } from "../storage/paths.js";
|
|
12
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
13
|
+
import { appendAudit } from "./audit.js";
|
|
14
|
+
const event = "diagnostic.request";
|
|
15
|
+
function refuse(reason) { throw new AppError("diagnostic_request_invalid", "Diagnostic request requires its original frozen selection", 2, { reason, effect: "no_effect" }); }
|
|
16
|
+
export function readDiagnosticRequest(context, scope) {
|
|
17
|
+
const project = requireProjectByRoot(context, resolveProjectRoot(scope.projectRoot));
|
|
18
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND json_extract(payload_json,'$.scope.requestId')=? LIMIT 2", [project.id, event, scope.requestId]);
|
|
19
|
+
if (!rows.length)
|
|
20
|
+
return null;
|
|
21
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 48 * 1024 * 1024)
|
|
22
|
+
refuse("ambiguous_request");
|
|
23
|
+
const value = JSON.parse(rows[0].payload_json);
|
|
24
|
+
if (value.schema_id !== "dd-flow/diagnostic-request@1" || value.project_id !== project.id
|
|
25
|
+
|| hybridDigest(value.scope) !== hybridDigest(scope) || !isDiagnosticFlow(value.scope.flowId))
|
|
26
|
+
refuse("request_scope_changed");
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
/** Freeze all ambient choices before copying source or allocating a RUN. */
|
|
30
|
+
export function retainDiagnosticRequest(context, input) {
|
|
31
|
+
const { scope, source, execution, engine } = input;
|
|
32
|
+
if (!(source instanceof PreparedInstalledFlowSource) || !(execution instanceof FrozenGenericExecution)
|
|
33
|
+
|| !(engine instanceof AdmittedFrozenEngine) || !isDiagnosticFlow(scope.flowId) || !/^[A-Za-z0-9][A-Za-z0-9_.-]{0,95}$/.test(scope.requestId)
|
|
34
|
+
|| !input.objective.trim() || Buffer.byteLength(input.objective) > 64 * 1024)
|
|
35
|
+
refuse("invalid_selection");
|
|
36
|
+
const project = requireProjectByRoot(context, scope.projectRoot), frozen = execution.snapshot();
|
|
37
|
+
const workspace = diagnosticSnapshotRoot(context, { projectId: project.id, projectRoot: scope.projectRoot, sourceRoot: scope.projectRoot,
|
|
38
|
+
requestId: scope.requestId, flowId: scope.flowId });
|
|
39
|
+
if (frozen.scope.projectRoot !== scope.projectRoot || frozen.scope.requestId !== scope.requestId || frozen.scope.workspace !== workspace
|
|
40
|
+
|| frozen.settings.flow_id !== scope.flowId || frozen.settings.descriptor_sha256 !== source.resolveRegisteredFlow().sha256
|
|
41
|
+
|| frozen.settings.attached_session_receipt || frozen.settings.delegation.native_capacity_receipt)
|
|
42
|
+
refuse("execution_selection_changed");
|
|
43
|
+
source.revalidate();
|
|
44
|
+
engine.admitDiagnosticFlow(source, scope.flowId);
|
|
45
|
+
const manifest = engine.manifest();
|
|
46
|
+
if (typeof manifest.integrity.checksum !== "string")
|
|
47
|
+
refuse("engine_identity_missing");
|
|
48
|
+
const value = { schema_id: "dd-flow/diagnostic-request@1", project_id: project.id, scope: structuredClone(scope),
|
|
49
|
+
created_at: context.now(), objective: input.objective, selection: structuredClone(input.selection),
|
|
50
|
+
source: source.snapshot(), source_sha256: source.sha256, execution: frozen, execution_sha256: execution.sha256,
|
|
51
|
+
engine: { identity: { package_name: manifest.package_name, package_version: manifest.package_version, engine_version: manifest.engine_version,
|
|
52
|
+
integrity_checksum: manifest.integrity.checksum, snapshot_root: manifest.snapshot_root }, manifest_sha256: engine.manifestSha256 } };
|
|
53
|
+
if (Buffer.byteLength(JSON.stringify(value)) > 48 * 1024 * 1024)
|
|
54
|
+
refuse("request_exceeds_bound");
|
|
55
|
+
return context.db.writeTransaction(() => {
|
|
56
|
+
const prior = readDiagnosticRequest(context, scope);
|
|
57
|
+
if (prior) {
|
|
58
|
+
if (hybridDigest({ ...value, created_at: prior.created_at }) !== hybridDigest(prior))
|
|
59
|
+
refuse("request_changed");
|
|
60
|
+
return prior;
|
|
61
|
+
}
|
|
62
|
+
if (readRunStartRequest(context, project.id, scope.requestId))
|
|
63
|
+
refuse("foreign_run_request");
|
|
64
|
+
appendAudit(context, { projectId: project.id, eventType: event, payload: value });
|
|
65
|
+
return value;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export function startDiagnosticRun(context, scope) {
|
|
69
|
+
const retained = readDiagnosticRequest(context, scope);
|
|
70
|
+
if (!retained)
|
|
71
|
+
refuse("original_request_required");
|
|
72
|
+
const project = requireProjectByRoot(context, scope.projectRoot);
|
|
73
|
+
if (readRunStartRequest(context, project.id, scope.requestId))
|
|
74
|
+
return PreparedDescriptorRunStart.restore(context, scope).apply(context);
|
|
75
|
+
const snapshot = prepareDiagnosticSnapshot(context, { projectId: project.id, projectRoot: scope.projectRoot, sourceRoot: scope.projectRoot,
|
|
76
|
+
requestId: scope.requestId, flowId: scope.flowId });
|
|
77
|
+
const source = PreparedInstalledFlowSource.restoreRetained(retained.source, retained.source_sha256);
|
|
78
|
+
const execution = FrozenGenericExecution.restore(retained.execution, retained.execution_sha256, source.resolveRegisteredFlow(), {
|
|
79
|
+
requestId: scope.requestId, projectRoot: scope.projectRoot, workspace: snapshot.root
|
|
80
|
+
});
|
|
81
|
+
const engine = AdmittedFrozenEngine.admitSelection(retained.engine.identity, retained.engine.manifest_sha256);
|
|
82
|
+
const bundle = prepareDiagnosticRunBundle(context, { source, execution, engine, boundAt: retained.created_at });
|
|
83
|
+
return PreparedDescriptorRunStart.prepare(context, { bundle }).apply(context);
|
|
84
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
3
|
+
/** Only applicable aspects receive analytical Work. Critics receive all candidates,
|
|
4
|
+
* including candidates they may reject; no empty pseudo-Work proves coverage. */
|
|
5
|
+
export function diagnosticWorkBatch(input) {
|
|
6
|
+
const review = input.stage === "review";
|
|
7
|
+
if (!review && input.stage !== (input.flow_id === "mb-audit" ? "audit" : "analyze")) {
|
|
8
|
+
throw new AppError("diagnostic_work_batch_invalid", "Diagnostic Work stage belongs to another flow", 2, { effect: "no_effect" });
|
|
9
|
+
}
|
|
10
|
+
const applicable = input.coverage.filter(value => value.applicability === "applicable");
|
|
11
|
+
const architecture = applicable.some(value => value.id ===
|
|
12
|
+
(input.flow_id === "mb-audit" ? "05" : "architecture_harmonization_review"));
|
|
13
|
+
const assignments = review
|
|
14
|
+
? ["universal", ...(architecture ? ["architecture"] : [])].map(id => ({ id, role: "critic" }))
|
|
15
|
+
: applicable.map(value => ({ id: value.id, role: "aspect" }));
|
|
16
|
+
return { works: assignments.map((assignment, index) => {
|
|
17
|
+
const key = `${assignment.role}-${String(index + 1).padStart(3, "0")}`;
|
|
18
|
+
const packet = { schema_id: "dd-flow/diagnostic-work-input@1", flow_id: input.flow_id, run_id: input.run_id,
|
|
19
|
+
stage: input.stage, key, aspect_id: assignment.id, role: assignment.role,
|
|
20
|
+
input_sha256: input.input_sha256, snapshot_sha256: input.snapshot_sha256,
|
|
21
|
+
instruction: input.instruction, coverage: input.coverage, support: input.support ?? [],
|
|
22
|
+
candidates: review ? input.candidates : [] };
|
|
23
|
+
return { key, depends_on: [], launch_policy: "fresh_agent_required",
|
|
24
|
+
result_schema: "dd-flow/diagnostic-work-result@1",
|
|
25
|
+
task: (review
|
|
26
|
+
? `Independently assess every supplied candidate as the ${assignment.id} critic. Read the assigned immutable snapshot. Retain rejected findings and explain disagreement. Do not invent implementation, checks, sources or completion. Return exactly one decision per candidate using the assigned diagnostic result schema. Do not edit project files, repair findings, allocate Work or coordinate the Stage.`
|
|
27
|
+
: `Examine only the assigned aspect ${JSON.stringify(assignment.id)} using the frozen instruction and actual snapshot sources. Distinguish implemented behavior from plans and absent evidence. Cite exact sources for material findings; retain uncertainty and active DEFs. Do not edit project files, execute project setup, repair findings, allocate Work or claim independent review. Return the assigned diagnostic Work result.`)
|
|
28
|
+
+ " Read applicable criterion files in diagnostic.support relative to run_home. They are frozen reference criteria, not executable/manual lifecycle instructions or implemented project facts. Cite snapshot sources as project evidence, not canon references."
|
|
29
|
+
+ " Every sources/evidence path must be relative to the assigned snapshot workspace root, using forward slashes (for example src/index.ts or .memory-bank/index.md), with the SHA256 of its exact snapshot bytes. Never cite absolute paths, .git, intake transport files, RUN packets or canon support as snapshot evidence; never invent a relative path for a file outside the snapshot."
|
|
30
|
+
+ " Files under .dd-flow/review-evidence are CLI-generated observations, not original project sources: do not put them in sources/evidence or infer the original repository's history or unborn state from the working copy's Git metadata. For missing linked targets cite the existing referring project document and describe the absence as a limitation, not as a source file.",
|
|
31
|
+
payload: { kind: review ? "diagnostic-critic" : "diagnostic-aspect", read_only: true,
|
|
32
|
+
diagnostic: { ...packet, packet_sha256: hybridDigest(packet) } } };
|
|
33
|
+
}) };
|
|
34
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { isDiagnosticFlow } from "../domain/diagnostic-flows.js";
|
|
3
|
+
import { readFlowRunExecutionBundle, assertPreparedRunBundleSqlAuthority } from "./runs.js";
|
|
4
|
+
import { requireProjectByRoot } from "./projects.js";
|
|
5
|
+
import { resolveProjectRoot } from "../storage/paths.js";
|
|
6
|
+
import { readRegisteredDiagnosticGraph } from "./diagnostic-work-registration.js";
|
|
7
|
+
import { diagnosticWorkBatch } from "./diagnostic-work-batch.js";
|
|
8
|
+
import { validateDiagnosticWorkResult } from "./diagnostic-work-results.js";
|
|
9
|
+
import { diagnosticSnapshotPaths, readDiagnosticSnapshot, readDiagnosticSnapshotCustody } from "./diagnostic-snapshot.js";
|
|
10
|
+
import { readDescriptorRootWork } from "./descriptor-root-work.js";
|
|
11
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
12
|
+
function refuse(reason) { throw new AppError("diagnostic_work_collection_invalid", "Diagnostic graph is not independently settled", 2, { reason, effect: "no_effect" }); }
|
|
13
|
+
const physicalKey = (session) => `${session.harness}\0${session.provider_session_id}`;
|
|
14
|
+
export function assertDiagnosticSessionIndependence(workers, excluded) {
|
|
15
|
+
const keys = workers.map(physicalKey), excludedKeys = new Set(excluded.map(physicalKey));
|
|
16
|
+
if (workers.some(value => !value.harness || !value.provider_session_id)
|
|
17
|
+
|| new Set(keys).size !== keys.length || keys.some(key => excludedKeys.has(key)))
|
|
18
|
+
refuse("physical_session_reused");
|
|
19
|
+
}
|
|
20
|
+
function completedWork(context, scope, workId) {
|
|
21
|
+
const work = context.db.get("SELECT status,result FROM works WHERE project_id=? AND run_id=? AND work_id=?", [scope.projectId, scope.runId, workId]);
|
|
22
|
+
if (work?.status !== "completed" || !work.result || Buffer.byteLength(work.result) > 1024 * 1024)
|
|
23
|
+
refuse("work_not_completed");
|
|
24
|
+
const sessions = context.db.all("SELECT ws.id,ws.session_id,ws.status,s.harness,s.provider_session_id,ws.hook_event_id FROM work_sessions ws JOIN sessions s ON s.project_id=? AND s.session_id=ws.session_id AND s.run_id=? WHERE ws.work_id=? AND ws.status IN ('running','completed') LIMIT 3", [scope.projectId, scope.runId, workId]);
|
|
25
|
+
if (sessions.length !== 1 || sessions[0].status !== "completed")
|
|
26
|
+
refuse("work_session_not_settled");
|
|
27
|
+
const session = sessions[0];
|
|
28
|
+
const hook = context.db.get("SELECT session_id,harness,provider_session_id,status FROM hook_events WHERE project_id=? AND event_key=?", [scope.projectId, session.hook_event_id]);
|
|
29
|
+
if (!hook || hook.status !== "claimed" || hook.session_id !== session.session_id
|
|
30
|
+
|| physicalKey(hook) !== physicalKey(session))
|
|
31
|
+
refuse("physical_work_owner_missing");
|
|
32
|
+
return { workId, result: work.result, session };
|
|
33
|
+
}
|
|
34
|
+
function collectSql(context, scope, rootId) {
|
|
35
|
+
const graph = readRegisteredDiagnosticGraph(context, scope);
|
|
36
|
+
if (!graph || graph.parent_work_id !== rootId)
|
|
37
|
+
refuse("registration_required");
|
|
38
|
+
const batch = diagnosticWorkBatch(graph.input);
|
|
39
|
+
const works = batch.works.map(item => completedWork(context, scope, graph.work_ids[item.key]));
|
|
40
|
+
const coordinators = context.db.all("SELECT s.harness,s.provider_session_id FROM work_sessions ws JOIN sessions s ON s.project_id=? AND s.run_id=? AND s.session_id=ws.session_id WHERE ws.work_id=?", [scope.projectId, scope.runId, rootId]);
|
|
41
|
+
const authorGraph = scope.stage === "review" ? readRegisteredDiagnosticGraph(context, { ...scope, stage: graph.input.flow_id === "mb-audit" ? "audit" : "analyze" }) : null;
|
|
42
|
+
if (scope.stage === "review" && !authorGraph)
|
|
43
|
+
refuse("author_graph_missing");
|
|
44
|
+
const authors = authorGraph ? Object.values(authorGraph.work_ids).map(id => completedWork(context, scope, id)) : [];
|
|
45
|
+
assertDiagnosticSessionIndependence(works.map(value => value.session), [...coordinators, ...authors.map(value => value.session)]);
|
|
46
|
+
return { graph, works, authors, coordinators };
|
|
47
|
+
}
|
|
48
|
+
/** File/schema/evidence checks occur before settlement. assertCustody is SQL-only
|
|
49
|
+
* and keeps the selected results and physical owners stable in its writer. */
|
|
50
|
+
export class PreparedDiagnosticWorkCollection {
|
|
51
|
+
#scope;
|
|
52
|
+
#rootId;
|
|
53
|
+
#sql;
|
|
54
|
+
#snapshot;
|
|
55
|
+
#results;
|
|
56
|
+
constructor(scope, rootId, sql, snapshot, results) {
|
|
57
|
+
this.#scope = scope;
|
|
58
|
+
this.#rootId = rootId;
|
|
59
|
+
this.#sql = sql;
|
|
60
|
+
this.#snapshot = snapshot;
|
|
61
|
+
this.#results = results;
|
|
62
|
+
Object.freeze(this);
|
|
63
|
+
}
|
|
64
|
+
static prepare(context, input) {
|
|
65
|
+
const bundle = readFlowRunExecutionBundle(context, input), project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
66
|
+
if (!bundle || !isDiagnosticFlow(bundle.manifest.flow_id))
|
|
67
|
+
refuse("diagnostic_bundle_required");
|
|
68
|
+
const scope = { projectId: project.id, runId: input.runId, stage: input.stage };
|
|
69
|
+
const frozen = bundle.execution.snapshot().scope;
|
|
70
|
+
const snapshot = readDiagnosticSnapshot(context, { projectId: project.id, projectRoot: frozen.projectRoot,
|
|
71
|
+
sourceRoot: frozen.projectRoot, requestId: frozen.requestId, flowId: bundle.manifest.flow_id }, input.runId);
|
|
72
|
+
if (!snapshot || snapshot.root !== frozen.workspace)
|
|
73
|
+
refuse("snapshot_required");
|
|
74
|
+
const root = readDescriptorRootWork(context, scope, bundle);
|
|
75
|
+
const sql = context.db.readSnapshot(() => {
|
|
76
|
+
assertPreparedRunBundleSqlAuthority(context, scope, bundle);
|
|
77
|
+
return collectSql(context, scope, root.workId);
|
|
78
|
+
});
|
|
79
|
+
if (sql.graph.bundle_sha256 !== bundle.sha256 || sql.graph.input.snapshot_sha256 !== snapshot.source_sha256)
|
|
80
|
+
refuse("foreign_graph");
|
|
81
|
+
const batch = diagnosticWorkBatch(sql.graph.input), schema = bundle.blob("schemas/diagnostic-work-result.schema.json");
|
|
82
|
+
const results = sql.works.map((work, index) => ({ workId: work.workId,
|
|
83
|
+
result: validateDiagnosticWorkResult(Buffer.from(work.result), schema, diagnosticSnapshotPaths(context, snapshot, input.runId).root, sql.graph.input, {
|
|
84
|
+
workId: work.workId, aspectId: batch.works[index].payload.diagnostic.aspect_id,
|
|
85
|
+
role: batch.works[index].payload.diagnostic.role
|
|
86
|
+
}) }));
|
|
87
|
+
return new PreparedDiagnosticWorkCollection(scope, root.workId, sql, snapshot, results);
|
|
88
|
+
}
|
|
89
|
+
results() { return structuredClone(this.#results); }
|
|
90
|
+
assertCustody(context) {
|
|
91
|
+
const s = this.#snapshot;
|
|
92
|
+
if (hybridDigest(collectSql(context, this.#scope, this.#rootId)) !== hybridDigest(this.#sql)
|
|
93
|
+
|| hybridDigest(readDiagnosticSnapshotCustody(context, { projectId: s.projectId, projectRoot: s.projectRoot,
|
|
94
|
+
sourceRoot: s.sourceRoot, requestId: s.requestId, flowId: s.flowId }, this.#scope.runId)) !== hybridDigest(s))
|
|
95
|
+
refuse("collection_changed");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { isDiagnosticFlow } from "../domain/diagnostic-flows.js";
|
|
3
|
+
import { requireProjectByRoot } from "./projects.js";
|
|
4
|
+
import { resolveProjectRoot } from "../storage/paths.js";
|
|
5
|
+
import { readFlowRunExecutionBundle, assertPreparedRunBundleSqlAuthority } from "./runs.js";
|
|
6
|
+
import { readDescriptorStageInput } from "./descriptor-stage-coordinator.js";
|
|
7
|
+
import { readDescriptorRootWork } from "./descriptor-root-work.js";
|
|
8
|
+
import { diagnosticSnapshotPaths, readDiagnosticSnapshot, readDiagnosticSnapshotCustody } from "./diagnostic-snapshot.js";
|
|
9
|
+
import { readAcceptedStageData } from "./stage-report-renderer.js";
|
|
10
|
+
import { validateDiagnosticStageResult } from "./diagnostic-stage-results.js";
|
|
11
|
+
import { diagnosticWorkBatch } from "./diagnostic-work-batch.js";
|
|
12
|
+
import { addWorkBatch, prepareWorkBatch, readWorkBatchCustody } from "./work-registry.js";
|
|
13
|
+
import { stageGraphScope } from "./stage-work-graph.js";
|
|
14
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
15
|
+
import { appendAudit } from "./audit.js";
|
|
16
|
+
const event = "diagnostic.work_registration";
|
|
17
|
+
function refuse(reason) { throw new AppError("diagnostic_work_registration_invalid", "Diagnostic graph lacks its assigned stage authority", 2, { reason, effect: "no_effect" }); }
|
|
18
|
+
/** SQL-only reader. An explicitly registered empty graph is distinct from no graph. */
|
|
19
|
+
export function readRegisteredDiagnosticGraph(context, scope) {
|
|
20
|
+
const graph = stageGraphScope(context, scope.projectId, scope.runId, scope.stage);
|
|
21
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.stage')=? AND json_extract(payload_json,'$.attempt')=? LIMIT 2", [scope.projectId, event, scope.runId, scope.stage, graph.attempt]);
|
|
22
|
+
if (!rows.length)
|
|
23
|
+
return null;
|
|
24
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 2 * 1024 * 1024)
|
|
25
|
+
refuse("ambiguous_registration");
|
|
26
|
+
const receipt = JSON.parse(rows[0].payload_json);
|
|
27
|
+
if (receipt.schema_id !== "dd-flow/diagnostic-work-registration@1" || receipt.run_id !== scope.runId
|
|
28
|
+
|| receipt.stage !== scope.stage || receipt.attempt !== graph.attempt || !receipt.work_ids
|
|
29
|
+
|| receipt.input.run_id !== scope.runId || receipt.input.stage !== scope.stage
|
|
30
|
+
|| receipt.input.input_sha256 !== receipt.input_sha256)
|
|
31
|
+
refuse("foreign_registration");
|
|
32
|
+
const batch = diagnosticWorkBatch(receipt.input);
|
|
33
|
+
if (receipt.batch_sha256 !== hybridDigest(batch.works) || batch.works.length !== Object.keys(receipt.work_ids).length
|
|
34
|
+
|| new Set(Object.values(receipt.work_ids)).size !== batch.works.length)
|
|
35
|
+
refuse("changed_batch");
|
|
36
|
+
for (const item of batch.works) {
|
|
37
|
+
const id = receipt.work_ids[item.key];
|
|
38
|
+
if (!id)
|
|
39
|
+
refuse("missing_work");
|
|
40
|
+
const custody = readWorkBatchCustody(context, id);
|
|
41
|
+
if (custody.item_key !== item.key || custody.batch_sha256 !== receipt.batch_sha256
|
|
42
|
+
|| hybridDigest(custody.work_ids) !== hybridDigest(receipt.work_ids)
|
|
43
|
+
|| hybridDigest(custody.scope) !== hybridDigest({ ...graph, stage: scope.stage,
|
|
44
|
+
parent_work_id: receipt.parent_work_id, request_key: "diagnostic-graph" }))
|
|
45
|
+
refuse("changed_work_custody");
|
|
46
|
+
}
|
|
47
|
+
return receipt;
|
|
48
|
+
}
|
|
49
|
+
/** The registered handler calls this only after generic Stage entry. Applicability
|
|
50
|
+
* and candidates come from the accepted predecessor, not a caller-owned batch. */
|
|
51
|
+
export function registerDiagnosticStageGraph(context, input) {
|
|
52
|
+
const bundle = readFlowRunExecutionBundle(context, input), project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
53
|
+
if (!bundle || !isDiagnosticFlow(bundle.manifest.flow_id) || !["audit", "analyze", "review"].includes(input.stage))
|
|
54
|
+
refuse("diagnostic_stage_required");
|
|
55
|
+
const flowId = bundle.manifest.flow_id, frozen = bundle.execution.snapshot().scope;
|
|
56
|
+
const scope = { projectId: project.id, runId: input.runId, stage: input.stage };
|
|
57
|
+
const selection = readDescriptorStageInput(context, scope, bundle), root = readDescriptorRootWork(context, scope, bundle);
|
|
58
|
+
const snapshotSelection = { projectId: project.id, projectRoot: frozen.projectRoot, sourceRoot: frozen.projectRoot, requestId: frozen.requestId, flowId };
|
|
59
|
+
const snapshot = readDiagnosticSnapshot(context, snapshotSelection, input.runId);
|
|
60
|
+
if (!snapshot || snapshot.root !== frozen.workspace)
|
|
61
|
+
refuse("snapshot_required");
|
|
62
|
+
const previousStage = input.stage === "review" ? flowId === "mb-audit" ? "audit" : "analyze" : "preflight";
|
|
63
|
+
if (selection.input.predecessor?.stage !== previousStage)
|
|
64
|
+
refuse("predecessor_required");
|
|
65
|
+
const previousScope = { ...scope, stage: previousStage };
|
|
66
|
+
const accepted = readAcceptedStageData(context, previousScope), previousInput = readDescriptorStageInput(context, previousScope, bundle, true, true);
|
|
67
|
+
const previous = validateDiagnosticStageResult(accepted.bytes, bundle.descriptor.stageBlob(previousStage, "result_schema"), {
|
|
68
|
+
flowId, runId: input.runId, stage: previousStage, inputSha256: previousInput.inputSha256,
|
|
69
|
+
snapshotRoot: diagnosticSnapshotPaths(context, snapshot, input.runId).root, snapshotSha256: snapshot.source_sha256,
|
|
70
|
+
predecessors: previousInput.input.predecessor ? [{ stage: previousInput.input.predecessor.stage,
|
|
71
|
+
path: previousInput.input.predecessor.result.path, sha256: previousInput.input.predecessor.result.sha256 }] : []
|
|
72
|
+
});
|
|
73
|
+
const workInput = { flow_id: flowId, run_id: input.runId, stage: input.stage,
|
|
74
|
+
input_sha256: selection.inputSha256, snapshot_sha256: snapshot.source_sha256,
|
|
75
|
+
instruction: bundle.descriptor.stageBlob(input.stage, "instruction").toString("utf8"),
|
|
76
|
+
coverage: previous.details.coverage, candidates: input.stage === "review" ? previous.details.findings : [],
|
|
77
|
+
support: bundle.manifest.inventory.filter(ref => ref.path.startsWith("support/")).map(ref => ({ path: `execution-bundle/${ref.path}`, sha256: ref.sha256 })) };
|
|
78
|
+
const batch = diagnosticWorkBatch(workInput), batchInput = { parentWorkId: root.workId, stage: input.stage, requestKey: "diagnostic-graph", value: batch };
|
|
79
|
+
const prepared = batch.works.length ? prepareWorkBatch(context, batchInput) : [];
|
|
80
|
+
return context.db.writeTransaction(() => {
|
|
81
|
+
assertPreparedRunBundleSqlAuthority(context, scope, bundle);
|
|
82
|
+
if (hybridDigest(readDiagnosticSnapshotCustody(context, snapshotSelection, input.runId)) !== hybridDigest(snapshot)
|
|
83
|
+
|| hybridDigest(readDescriptorStageInput(context, scope, bundle)) !== hybridDigest(selection)
|
|
84
|
+
|| hybridDigest(readAcceptedStageData(context, previousScope)) !== hybridDigest(accepted)
|
|
85
|
+
|| readDescriptorRootWork(context, scope, bundle).workId !== root.workId)
|
|
86
|
+
refuse("stage_authority_changed");
|
|
87
|
+
const expected = { schema_id: "dd-flow/diagnostic-work-registration@1", run_id: input.runId, stage: input.stage,
|
|
88
|
+
attempt: selection.attempt, parent_work_id: root.workId, bundle_sha256: bundle.sha256,
|
|
89
|
+
input_sha256: selection.inputSha256, input: workInput, batch_sha256: hybridDigest(batch.works) };
|
|
90
|
+
const prior = readRegisteredDiagnosticGraph(context, scope);
|
|
91
|
+
if (prior) {
|
|
92
|
+
if (hybridDigest({ ...prior, work_ids: undefined }) !== hybridDigest(expected))
|
|
93
|
+
refuse("registration_changed");
|
|
94
|
+
return prior;
|
|
95
|
+
}
|
|
96
|
+
const workIds = batch.works.length ? addWorkBatch(context, { ...batchInput, prepared }).work_ids : {};
|
|
97
|
+
const receipt = { ...expected, work_ids: workIds };
|
|
98
|
+
appendAudit(context, { projectId: project.id, eventType: event, payload: receipt });
|
|
99
|
+
return readRegisteredDiagnosticGraph(context, scope);
|
|
100
|
+
});
|
|
101
|
+
}
|