@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +895 -0
- package/README.md +140 -6
- package/dist/build-info.json +8 -8
- package/dist/cli/argument-values.js +38 -0
- package/dist/cli/command-inputs.js +386 -0
- package/dist/cli/command-metadata.js +232 -0
- package/dist/cli/command-option-descriptions.js +192 -0
- package/dist/cli/completion-cli.js +70 -0
- package/dist/cli/completion.js +57 -0
- package/dist/cli/diagnostic-invocation.js +46 -0
- package/dist/cli/diagnostic.js +120 -0
- package/dist/cli/error-output.js +52 -0
- package/dist/cli/executor-onboarding.js +76 -0
- package/dist/cli/flows.js +29 -0
- package/dist/cli/harnesses.js +84 -0
- package/dist/cli/help.js +396 -19
- package/dist/cli/hook-ingress.js +102 -0
- package/dist/cli/input-preparation.js +165 -0
- package/dist/cli/memory-flow-admission.js +50 -0
- package/dist/cli/memory-init-invocation.js +85 -0
- package/dist/cli/memory-init.js +249 -0
- package/dist/cli/memory-storage-admission.js +54 -0
- package/dist/cli/memory-storage-qualification.js +105 -0
- package/dist/cli/memory-storage-transition.js +123 -0
- package/dist/cli/memory-upgrade.js +189 -0
- package/dist/cli/models.js +39 -0
- package/dist/cli/native-hook-ingress.js +90 -0
- package/dist/cli/native-hook-preparation.js +55 -0
- package/dist/cli/operator-profiles.js +61 -0
- package/dist/cli/output-options.js +35 -0
- package/dist/cli/response-file.js +72 -0
- package/dist/cli/run-cli.js +1734 -550
- package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
- package/dist/cli/runtime-maintenance-ingress.js +52 -0
- package/dist/cli/runtime-process.js +153 -0
- package/dist/cli/setup.js +150 -0
- package/dist/cli.js +89 -2
- package/dist/domain/diagnostic-aspects.js +103 -0
- package/dist/domain/diagnostic-flows.js +8 -0
- package/dist/domain/stage-catalog.js +1 -1
- package/dist/domain/stage-handler-identities.js +28 -0
- package/dist/harness-runtime/DD-ZCODE.md +112 -0
- package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
- package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
- package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
- package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
- package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
- package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
- package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
- package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
- package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
- package/dist/harness-runtime/lib/agy-error-boundary.mjs +58 -0
- package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
- package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
- package/dist/harness-runtime/lib/agy-native-inspection.mjs +216 -0
- package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
- package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
- package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
- package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +462 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1096 -0
- package/dist/harness-runtime/lib/dd-agy.mjs +86 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +231 -0
- package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex.mjs +954 -0
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +141 -0
- package/dist/harness-runtime/lib/dd-droid.mjs +626 -0
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +555 -0
- package/dist/harness-runtime/lib/dd-grok.mjs +180 -0
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +622 -0
- package/dist/harness-runtime/lib/dd-opencode.mjs +390 -0
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +752 -0
- package/dist/harness-runtime/lib/dd-zcode.mjs +1175 -0
- package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
- package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
- package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
- package/dist/harness-runtime/lib/driver-recovery.mjs +140 -0
- package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
- package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
- package/dist/harness-runtime/lib/entity-references.mjs +9 -0
- package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
- package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
- package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
- package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
- package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
- package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
- package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
- package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
- package/dist/harness-runtime/lib/model-observations.mjs +101 -0
- package/dist/harness-runtime/lib/native-children.d.mts +23 -0
- package/dist/harness-runtime/lib/native-children.mjs +219 -0
- package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
- package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
- package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
- package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
- package/dist/harness-runtime/lib/native-streams.mjs +45 -0
- package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
- package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
- package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
- package/dist/harness-runtime/lib/operation-context.mjs +5 -0
- package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
- package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
- package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
- package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
- package/dist/harness-runtime/lib/process-json.d.mts +5 -0
- package/dist/harness-runtime/lib/process-json.mjs +201 -0
- package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
- package/dist/harness-runtime/lib/provider-overload-policy.d.mts +15 -0
- package/dist/harness-runtime/lib/provider-overload-policy.mjs +151 -0
- package/dist/harness-runtime/lib/runner-events.mjs +202 -0
- package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
- package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
- package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
- package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
- package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
- package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
- package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
- package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
- package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
- package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
- package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
- package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
- package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
- package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
- package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
- package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
- package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
- package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
- package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
- package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
- package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
- package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
- package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
- package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
- package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
- package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
- package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
- package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
- package/dist/protocol/local-files.js +18 -9
- package/dist/runtime/context.js +8 -4
- package/dist/schemas/agent-profile.schema.json +1 -1
- package/dist/schemas/code-review-decision.schema.json +9 -0
- package/dist/schemas/code-review-result.schema.json +1 -1
- package/dist/schemas/code-verification.schema.json +7 -5
- package/dist/schemas/code-work-batch.schema.json +2 -2
- package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
- package/dist/schemas/diagnostic-work-result.schema.json +296 -0
- package/dist/schemas/discovery-result.schema.json +184 -0
- package/dist/schemas/execution-bundle.schema.json +211 -0
- package/dist/schemas/execution-settings.schema.json +162 -0
- package/dist/schemas/flow-descriptor.schema.json +54 -0
- package/dist/schemas/flow-run.schema.json +29 -0
- package/dist/schemas/harness-catalog.schema.json +80 -0
- package/dist/schemas/mb-init-compose-result.schema.json +457 -0
- package/dist/schemas/mb-init-discover-result.schema.json +500 -0
- package/dist/schemas/mb-init-finish-result.schema.json +422 -0
- package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
- package/dist/schemas/mb-init-review-result.schema.json +396 -0
- package/dist/schemas/mb-init-verify-result.schema.json +391 -0
- package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
- package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
- package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
- package/dist/schemas/memory-composition-work-result.schema.json +38 -0
- package/dist/schemas/memory-repair-work-result.schema.json +56 -0
- package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
- package/dist/schemas/memory-review-work-result.schema.json +43 -0
- package/dist/schemas/model-catalog.schema.json +153 -0
- package/dist/schemas/plan-review-decision.schema.json +12 -3
- package/dist/schemas/plan-review-result.schema.json +2 -2
- package/dist/schemas/profile-settings.schema.json +122 -0
- package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
- package/dist/schemas/release-impact.schema.json +3 -3
- package/dist/schemas/release-manifest.schema.json +291 -0
- package/dist/schemas/run-control-receipt.schema.json +118 -0
- package/dist/schemas/run-control-request.schema.json +36 -0
- package/dist/schemas/run-engine-binding.schema.json +1 -1
- package/dist/schemas/stage-start-response.schema.json +4 -0
- package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
- package/dist/services/accepted-intent.js +139 -0
- package/dist/services/branch-context.js +3 -3
- package/dist/services/canon.js +54 -15
- package/dist/services/check-environment.js +21 -0
- package/dist/services/check-runner-evidence.js +562 -0
- package/dist/services/cleanup.js +133 -40
- package/dist/services/cli-operation-classifier.js +26 -63
- package/dist/services/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +1398 -119
- package/dist/services/codex-hook-delivery.js +32 -0
- package/dist/services/command-context.js +80 -0
- package/dist/services/compatibility-preflight.js +16 -3
- package/dist/services/config.js +11 -8
- package/dist/services/continuation-outcome.js +20 -0
- package/dist/services/controller-child-capacity.js +13 -0
- package/dist/services/controller-child-observer.js +115 -0
- package/dist/services/controller-execution.js +94 -0
- package/dist/services/controller-fanout.js +226 -0
- package/dist/services/controller-memory-task.js +45 -0
- package/dist/services/controller-memory-worker.js +49 -0
- package/dist/services/dashboard.js +143 -58
- package/dist/services/descriptor-coordinator-session.js +35 -0
- package/dist/services/descriptor-root-work.js +53 -0
- package/dist/services/descriptor-run-settlement.js +107 -0
- package/dist/services/descriptor-run-start.js +475 -0
- package/dist/services/descriptor-stage-coordinator.js +250 -0
- package/dist/services/descriptor-stage-settlement.js +223 -0
- package/dist/services/descriptor-stage-start.js +175 -0
- package/dist/services/diagnostic-evidence.js +73 -0
- package/dist/services/diagnostic-report-publication.js +72 -0
- package/dist/services/diagnostic-report.js +67 -0
- package/dist/services/diagnostic-run-bundle.js +74 -0
- package/dist/services/diagnostic-snapshot.js +159 -0
- package/dist/services/diagnostic-stage-handlers.js +108 -0
- package/dist/services/diagnostic-stage-results.js +132 -0
- package/dist/services/diagnostic-start.js +84 -0
- package/dist/services/diagnostic-work-batch.js +34 -0
- package/dist/services/diagnostic-work-collection.js +97 -0
- package/dist/services/diagnostic-work-registration.js +101 -0
- package/dist/services/diagnostic-work-results.js +93 -0
- package/dist/services/discovery/agy-discovery.js +2 -0
- package/dist/services/discovery/codex-discovery.js +2 -0
- package/dist/services/discovery/droid-discovery.js +2 -0
- package/dist/services/discovery/grok-discovery.js +2 -0
- package/dist/services/discovery/opencode-discovery.js +2 -0
- package/dist/services/discovery/static.js +31 -0
- package/dist/services/discovery/zcode-discovery.js +2 -0
- package/dist/services/engines.js +354 -163
- package/dist/services/eval-snapshots.js +1316 -150
- package/dist/services/execution-bundles.js +275 -0
- package/dist/services/execution-policy.js +185 -0
- package/dist/services/executor-onboarding.js +56 -0
- package/dist/services/external-work-launch.js +310 -0
- package/dist/services/flow-catalog.js +30 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +387 -0
- package/dist/services/generic-execution.js +164 -0
- package/dist/services/harness-adapter.js +355 -36
- package/dist/services/harness-config.js +2 -0
- package/dist/services/harness-discovery.js +29 -0
- package/dist/services/harness-doctor.js +75 -0
- package/dist/services/harness-probe-effects.js +51 -0
- package/dist/services/harness-version-probe.js +100 -0
- package/dist/services/hook-memory-routing.js +188 -0
- package/dist/services/hook-recovery-guard.js +14 -0
- package/dist/services/hook-session-observation.js +24 -0
- package/dist/services/hooks.js +791 -326
- package/dist/services/hybrid-contracts.js +474 -0
- package/dist/services/hybrid-digest.js +14 -0
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +95 -0
- package/dist/services/installed-flow-source.js +226 -0
- package/dist/services/lanes.js +78 -65
- package/dist/services/lifecycle-command.js +1 -288
- package/dist/services/lifecycle-contract.js +1 -0
- package/dist/services/lifecycle-invocations.js +2148 -0
- package/dist/services/managed-daemon-binding.js +38 -0
- package/dist/services/managed-lease-monitor.js +133 -0
- package/dist/services/managed-processes.js +449 -69
- package/dist/services/memory-accepted-composition.js +78 -0
- package/dist/services/memory-baseline-preservation.js +65 -0
- package/dist/services/memory-completed-correction-wave.js +328 -0
- package/dist/services/memory-compose-handler.js +400 -0
- package/dist/services/memory-composition-acceptance.js +375 -0
- package/dist/services/memory-composition-graph.js +165 -0
- package/dist/services/memory-composition-registration.js +161 -0
- package/dist/services/memory-composition-work-custody.js +156 -0
- package/dist/services/memory-composition-work-results.js +108 -0
- package/dist/services/memory-corrected-review-acceptance.js +129 -0
- package/dist/services/memory-corrected-review-batch.js +37 -0
- package/dist/services/memory-corrected-review-findings.js +108 -0
- package/dist/services/memory-corrected-review-inputs.js +215 -0
- package/dist/services/memory-corrected-review-projection.js +78 -0
- package/dist/services/memory-corrected-review-receipt.js +178 -0
- package/dist/services/memory-corrected-review-registration.js +192 -0
- package/dist/services/memory-correction-check-receipt.js +235 -0
- package/dist/services/memory-correction-input-owner.js +6 -0
- package/dist/services/memory-custody-snapshot.js +36 -0
- package/dist/services/memory-discover-handler.js +104 -0
- package/dist/services/memory-finish-evidence.js +457 -0
- package/dist/services/memory-finish-handler.js +229 -0
- package/dist/services/memory-finish-integration.js +450 -0
- package/dist/services/memory-finish-readiness.js +169 -0
- package/dist/services/memory-git-integration.js +220 -0
- package/dist/services/memory-historical-corrected-review.js +212 -0
- package/dist/services/memory-historical-original-review.js +143 -0
- package/dist/services/memory-historical-repair-registration.js +105 -0
- package/dist/services/memory-historical-second-review.js +147 -0
- package/dist/services/memory-init-bootstrap-readiness.js +210 -0
- package/dist/services/memory-init-contexts.js +131 -0
- package/dist/services/memory-init-controller-start.js +103 -0
- package/dist/services/memory-init-engine-release.js +223 -0
- package/dist/services/memory-init-git-policy.js +165 -0
- package/dist/services/memory-init-lint-capability.js +203 -0
- package/dist/services/memory-init-native-capacity.js +309 -0
- package/dist/services/memory-init-preflight.js +334 -0
- package/dist/services/memory-init-project-bootstrap.js +599 -0
- package/dist/services/memory-init-request-candidate.js +213 -0
- package/dist/services/memory-init-request-input.js +82 -0
- package/dist/services/memory-init-resource-storage.js +125 -0
- package/dist/services/memory-init-run-allocation.js +81 -0
- package/dist/services/memory-init-run-bundle.js +135 -0
- package/dist/services/memory-init-start.js +181 -0
- package/dist/services/memory-init-startup-custody.js +80 -0
- package/dist/services/memory-init-startup-input.js +240 -0
- package/dist/services/memory-init-storage.js +91 -0
- package/dist/services/memory-init-stores.js +359 -0
- package/dist/services/memory-init-worktrunk-capability.js +174 -0
- package/dist/services/memory-layer-publication.js +611 -0
- package/dist/services/memory-layer.js +221 -0
- package/dist/services/memory-lint-config.js +194 -0
- package/dist/services/memory-native-review-copy.js +103 -0
- package/dist/services/memory-normal-flow-entry.js +87 -0
- package/dist/services/memory-ordinary-defaults.js +129 -0
- package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
- package/dist/services/memory-preflight-handler.js +274 -0
- package/dist/services/memory-repair-current-view.js +299 -0
- package/dist/services/memory-repair-document-delta.js +488 -0
- package/dist/services/memory-repair-history.js +496 -0
- package/dist/services/memory-repair-physical-binding.js +194 -0
- package/dist/services/memory-repair-publication-files.js +152 -0
- package/dist/services/memory-repair-publication-intent.js +27 -0
- package/dist/services/memory-repair-publication-plan.js +162 -0
- package/dist/services/memory-repair-publication-source.js +225 -0
- package/dist/services/memory-repair-publication.js +795 -0
- package/dist/services/memory-repair-registration.js +240 -0
- package/dist/services/memory-repair-work-baseline.js +415 -0
- package/dist/services/memory-repair-work-completion.js +117 -0
- package/dist/services/memory-repair-work-custody.js +73 -0
- package/dist/services/memory-repair-work-results.js +108 -0
- package/dist/services/memory-repair-workspace.js +261 -0
- package/dist/services/memory-repair-writer-copy.js +736 -0
- package/dist/services/memory-result-binding.js +239 -0
- package/dist/services/memory-retained-review-authority.js +138 -0
- package/dist/services/memory-retained-review-results.js +70 -0
- package/dist/services/memory-retained-second-baseline.js +102 -0
- package/dist/services/memory-retained-second-repairs.js +162 -0
- package/dist/services/memory-review-acceptance.js +214 -0
- package/dist/services/memory-review-correction-plan.js +206 -0
- package/dist/services/memory-review-handler.js +585 -0
- package/dist/services/memory-review-inputs.js +246 -0
- package/dist/services/memory-review-limits.js +10 -0
- package/dist/services/memory-review-receipt.js +180 -0
- package/dist/services/memory-review-registration.js +117 -0
- package/dist/services/memory-review-work-custody.js +126 -0
- package/dist/services/memory-review-work-input.js +91 -0
- package/dist/services/memory-review-work-results.js +95 -0
- package/dist/services/memory-second-corrected-review-inputs.js +167 -0
- package/dist/services/memory-second-correction-plan.js +77 -0
- package/dist/services/memory-second-repair-baseline.js +91 -0
- package/dist/services/memory-second-repair-launch.js +614 -0
- package/dist/services/memory-second-repair-registration.js +88 -0
- package/dist/services/memory-second-repair-source.js +187 -0
- package/dist/services/memory-second-review-acceptance.js +115 -0
- package/dist/services/memory-source-observations.js +117 -0
- package/dist/services/memory-stage-dispatch.js +65 -0
- package/dist/services/memory-stage-results.js +290 -0
- package/dist/services/memory-tool-probe.js +25 -0
- package/dist/services/memory-upgrade-analysis-handler.js +243 -0
- package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
- package/dist/services/memory-upgrade-evidence.js +100 -0
- package/dist/services/memory-upgrade-inventory.js +442 -0
- package/dist/services/memory-upgrade-publication-custody.js +73 -0
- package/dist/services/memory-upgrade-publication.js +413 -0
- package/dist/services/memory-upgrade-selection.js +430 -0
- package/dist/services/memory-upgrade-start.js +60 -0
- package/dist/services/memory-upgrade-storage-readiness.js +340 -0
- package/dist/services/memory-verification-acceptance.js +156 -0
- package/dist/services/memory-verification-checks.js +317 -0
- package/dist/services/memory-verification-receipt.js +160 -0
- package/dist/services/memory-verify-handler.js +137 -0
- package/dist/services/memory-work-result-json.js +12 -0
- package/dist/services/memory-work-result-preparation.js +64 -0
- package/dist/services/merge-queue.js +228 -149
- package/dist/services/merge-server.js +163 -35
- package/dist/services/migrations.js +164 -114
- package/dist/services/model-catalog.js +109 -0
- package/dist/services/model-discovery.js +46 -0
- package/dist/services/native-daemon-history.js +50 -0
- package/dist/services/native-session-control.js +39 -0
- package/dist/services/operator-profiles.js +236 -0
- package/dist/services/physical-startup.js +45 -0
- package/dist/services/plan-runtime.js +26 -11
- package/dist/services/plans.js +28 -25
- package/dist/services/project-registry.js +97 -0
- package/dist/services/project-summary.js +1 -1
- package/dist/services/projects.js +17 -87
- package/dist/services/prompt-delivery.js +71 -0
- package/dist/services/prompts.js +28 -17
- package/dist/services/protocols.js +163 -87
- package/dist/services/provider-capacity.js +455 -0
- package/dist/services/recovery-observation-budget.js +121 -0
- package/dist/services/recovery-snapshot-database.js +588 -0
- package/dist/services/release-archive-producer.js +52 -0
- package/dist/services/release-archive.js +143 -0
- package/dist/services/release-cache.js +150 -0
- package/dist/services/release-compatibility.js +18 -0
- package/dist/services/release-download.js +67 -0
- package/dist/services/release-envelope.js +104 -0
- package/dist/services/release-manifest.js +45 -0
- package/dist/services/release-payload.js +114 -0
- package/dist/services/release-producer.js +63 -0
- package/dist/services/release-provenance.js +160 -0
- package/dist/services/release-registry.js +66 -0
- package/dist/services/release-source.js +194 -0
- package/dist/services/repair-intents.js +31 -0
- package/dist/services/repair-receipt.js +13 -0
- package/dist/services/review-copy.js +165 -0
- package/dist/services/review-deferral.js +23 -0
- package/dist/services/run-control-receipt.js +56 -0
- package/dist/services/run-control-worker.js +428 -0
- package/dist/services/run-control.js +1092 -0
- package/dist/services/run-controller-adapter.js +400 -0
- package/dist/services/run-controller-capture.js +186 -0
- package/dist/services/run-controller-process.js +205 -0
- package/dist/services/run-controller-recovery.js +295 -0
- package/dist/services/run-controller-state.js +97 -0
- package/dist/services/run-controller.js +1326 -0
- package/dist/services/run-engine-bindings.js +1 -1
- package/dist/services/run-fork.js +147 -0
- package/dist/services/run-health.js +149 -0
- package/dist/services/run-observations.js +152 -0
- package/dist/services/run-projection.js +22 -64
- package/dist/services/run-recovery-guard.js +107 -0
- package/dist/services/run-recovery-runtime.js +112 -0
- package/dist/services/run-recovery.js +456 -0
- package/dist/services/run-start-custody.js +189 -0
- package/dist/services/runs.js +1023 -246
- package/dist/services/runtime-budget.js +446 -0
- package/dist/services/runtime-command.js +43 -0
- package/dist/services/runtime-scope-capture.js +52 -0
- package/dist/services/runtime-scope-control.js +468 -0
- package/dist/services/runtime-scope-resume.js +605 -0
- package/dist/services/runtime-scope-stop.js +211 -0
- package/dist/services/runtime-scope-worker.js +314 -0
- package/dist/services/runtime-service.js +19 -14
- package/dist/services/schema-validation.js +10 -8
- package/dist/services/scope-writer-cleanup.js +27 -0
- package/dist/services/sessions.js +36 -91
- package/dist/services/setup.js +427 -0
- package/dist/services/stage-blocker.js +17 -7
- package/dist/services/stage-context.js +193 -19
- package/dist/services/stage-handlers.js +89 -0
- package/dist/services/stage-lifecycle.js +152 -116
- package/dist/services/stage-pause.js +202 -91
- package/dist/services/stage-report-renderer.js +234 -6
- package/dist/services/stage-work-graph.js +52 -0
- package/dist/services/tooling.js +41 -30
- package/dist/services/usage.js +49 -101
- package/dist/services/verification-matrix.js +393 -0
- package/dist/services/version-status.js +1 -1
- package/dist/services/vnext-code-review.js +235 -88
- package/dist/services/vnext-code.js +327 -226
- package/dist/services/vnext-contracts.js +10 -1
- package/dist/services/vnext-execution-profile.js +80 -5
- package/dist/services/vnext-fanout.js +355 -21
- package/dist/services/vnext-merge.js +332 -111
- package/dist/services/vnext-plan-review.js +287 -132
- package/dist/services/vnext-plan.js +228 -104
- package/dist/services/vnext-protocolize.js +533 -95
- package/dist/services/vnext-specify.js +123 -81
- package/dist/services/vnext-workspace-policy.js +7 -2
- package/dist/services/work-registry.js +1706 -200
- package/dist/services/workspace-bootstrap.js +53 -15
- package/dist/services/workspace-files.js +85 -0
- package/dist/services/worktrees.js +105 -48
- package/dist/shared/entity-references.js +1 -0
- package/dist/shared/errors.js +27 -0
- package/dist/storage/agent-output.js +26 -0
- package/dist/storage/data-preservation.js +65 -0
- package/dist/storage/database.js +930 -40
- package/dist/storage/foreign-key-transaction.js +39 -0
- package/dist/storage/immutable-input.js +45 -0
- package/dist/storage/import-guard.js +159 -0
- package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
- package/dist/storage/native-cleanup.js +52 -0
- package/dist/storage/paired-writer-migration.js +424 -0
- package/dist/storage/paths.js +17 -4
- package/dist/storage/projection-lock.js +73 -0
- package/dist/storage/work-references.js +23 -0
- package/dist/storage/writer-contract.js +96 -0
- package/dist/storage/writer-migration.js +346 -0
- package/dist/storage/writer-restore.js +217 -0
- package/package.json +50 -13
- package/tools/create-canon-release.mjs +33 -0
- package/tools/probe-codex-history.mjs +37 -0
- package/tools/produce-hybrid-release.mjs +41 -0
- package/tools/repair-paused-run-status.mjs +84 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { AppError } from "../shared/errors.js";
|
|
5
|
+
import { vnextStageDirectory } from "../domain/stage-catalog.js";
|
|
6
|
+
import { checkReceiptEvidenceValid, checkReceipts, effectiveCheckDeclarations } from "./code-checks.js";
|
|
7
|
+
import { acceptStagePacket, prepareStagePacket, publishStagePacket, resolveStagePublicationPath } from "./stage-report-renderer.js";
|
|
8
|
+
import { assertRunMutationAllowed } from "./run-recovery.js";
|
|
9
|
+
import { acceptedIntentContract, acceptedIntentSourceRole, prepareAcceptedIntentSources } from "./accepted-intent.js";
|
|
10
|
+
export const verificationMatrixContract = "dd-flow/verification-matrix@1";
|
|
11
|
+
export const finalCheckCoverageContract = "dd-flow/final-check-coverage@1";
|
|
12
|
+
/** A view of already validated facts: never a gate or a receipt selector. */
|
|
13
|
+
export function buildVerificationMatrix(input) {
|
|
14
|
+
const sourceCatalog = new Map();
|
|
15
|
+
const pathChecksums = new Map();
|
|
16
|
+
for (const source of input.sources) {
|
|
17
|
+
const location = JSON.stringify([source.root, source.path]);
|
|
18
|
+
if (pathChecksums.has(location) && pathChecksums.get(location) !== source.sha256)
|
|
19
|
+
throw new AppError("verification_matrix_source_changed", "Matrix source aliases have conflicting checksums", 1, { root: source.root, path: source.path });
|
|
20
|
+
pathChecksums.set(location, source.sha256);
|
|
21
|
+
const identity = JSON.stringify([source.role, source.root, source.path]);
|
|
22
|
+
const prior = sourceCatalog.get(identity);
|
|
23
|
+
if (prior && prior.sha256 !== source.sha256)
|
|
24
|
+
throw new AppError("verification_matrix_source_changed", "Matrix source identity has conflicting checksums", 1, { role: source.role, root: source.root, path: source.path, expected: prior.sha256, current: source.sha256 });
|
|
25
|
+
sourceCatalog.set(identity, source);
|
|
26
|
+
}
|
|
27
|
+
const sources = [...sourceCatalog.values()].sort((a, b) => compare(`${a.role}:${a.root}:${a.path}`, `${b.role}:${b.root}:${b.path}`));
|
|
28
|
+
const facts = new Map((input.facts ?? []).map(fact => [fact.canonical_ref, fact]));
|
|
29
|
+
const fact = (check, canonicalRef) => facts.get(canonicalRef) ?? { id: check.id, canonical_ref: canonicalRef, declaration: check, result: null, disposition: input.header.completeness === "skeleton" || input.header.completeness === "declared" ? "not_run" : "not_due" };
|
|
30
|
+
const protocols = Object.keys(input.ownership).sort(compare);
|
|
31
|
+
const requirements = protocols.flatMap(protocolId => input.requirements.filter(item => input.ownership[protocolId].includes(item.id)).map(item => {
|
|
32
|
+
const plan = input.plans.find(value => value.protocol_id === protocolId);
|
|
33
|
+
return { protocol_id: protocolId, ...item, plan_items: (plan?.items ?? []).filter(value => value.requirement_refs.includes(item.id)).map(value => ({ id: value.id, check_refs: unique(value.verification.check_refs), work_ids: unique((input.works ?? []).filter(work => work.protocol_id === protocolId && work.plan_item_id === value.id).map(work => work.work_id)) })).sort((a, b) => compare(a.id, b.id)) };
|
|
34
|
+
})).sort((a, b) => compare(`${a.protocol_id}:${a.id}`, `${b.protocol_id}:${b.id}`));
|
|
35
|
+
const criteria = protocols.flatMap(protocolId => input.criteria.filter(item => input.ownership[protocolId].includes(item.id)).flatMap(item => {
|
|
36
|
+
const plan = input.plans.find(value => value.protocol_id === protocolId);
|
|
37
|
+
const entries = plan?.acceptance.filter(value => value.criterion_id === item.id) ?? [];
|
|
38
|
+
return (entries.length ? entries : [null]).map(entry => ({ protocol_id: protocolId, criterion_id: item.id, statement: item.statement, gate: entry?.gate ?? null, check_refs: unique(entry?.check_refs ?? []), declaration: entry, checks: unique(entry?.check_refs ?? []).map(id => {
|
|
39
|
+
const check = plan?.checks.find(value => value.id === id);
|
|
40
|
+
if (!check)
|
|
41
|
+
throw new AppError("verification_matrix_source_invalid", "Validated PLAN references an absent check", 1, { protocol_id: protocolId, check_id: id });
|
|
42
|
+
return fact(check, `${protocolId}/${id}`);
|
|
43
|
+
}) }));
|
|
44
|
+
})).sort((a, b) => compare(`${a.protocol_id}:${a.criterion_id}:${a.gate}`, `${b.protocol_id}:${b.criterion_id}:${b.gate}`));
|
|
45
|
+
const policyChecks = (input.policyChecks ?? []).map(check => fact(check, check.canonical_ref ?? check.id)).sort((a, b) => compare(a.canonical_ref, b.canonical_ref));
|
|
46
|
+
const projectedFacts = [...new Map([...criteria.flatMap(row => row.checks), ...policyChecks].map(fact => [fact.canonical_ref, fact])).values()].sort((a, b) => compare(a.canonical_ref, b.canonical_ref));
|
|
47
|
+
const descriptor = { header: input.header, sources, facts: projectedFacts };
|
|
48
|
+
return canonical({ schema_id: verificationMatrixContract, header: { ...input.header, source_fingerprint: digest(stableJson(descriptor)) }, sources, requirements, criteria, policy_checks: policyChecks, ...(input.semanticAssessment ? { semantic_assessment: input.semanticAssessment } : {}) });
|
|
49
|
+
}
|
|
50
|
+
export function renderVerificationMatrix(matrix) {
|
|
51
|
+
const h = matrix.header;
|
|
52
|
+
const status = (check) => check.disposition === "unavailable" ? `unavailable (reported native status: ${check.result?.status ?? "none"}; ${check.reason ?? "missing exact proof"})` : String(check.result?.status ?? check.disposition);
|
|
53
|
+
return [`# Verification matrix`, "", `RUN: ${escape(h.run_id)}; stage: ${escape(h.stage)} / ${escape(h.stage_attempt)}; role: ${h.role}; completeness: ${h.completeness}.`, "", "This generated view is not semantic acceptance. A retained passed check proves only its declared contour and proof limits.", "", "## Requirements", "", "| Protocol | Requirement | Statement | PLAN items / checks |", "| --- | --- | --- | --- |", ...matrix.requirements.map(row => `| ${escape(row.protocol_id)} | ${escape(row.id)} | ${escape(row.statement)} | ${escape(row.plan_items.map(item => `${item.id}: ${item.check_refs.join(", ")}`).join("; "))} |`), "", "## Acceptance criteria", "", "| Protocol | Criterion | Gate | Checks / native results | Proof limits |", "| --- | --- | --- | --- | --- |", ...matrix.criteria.map(row => `| ${escape(row.protocol_id)} | ${escape(row.criterion_id)} | ${escape(row.gate ?? "not declared")} | ${escape(row.checks.map(check => `${check.canonical_ref}: ${status(check)}`).join("; "))} | ${escape(JSON.stringify(row.declaration?.proof_limits ?? []))} |`), "", "## Policy checks", "", ...matrix.policy_checks.map(check => `- ${escape(check.canonical_ref)}: ${escape(status(check))}`), "", "## Sources", "", ...matrix.sources.map(source => `- ${escape(source.role)}: ${escape(`${source.root}:${source.path}`)} (${source.sha256})`), ""].join("\n");
|
|
54
|
+
}
|
|
55
|
+
export function verificationMatrixInstruction(metadata, runHome, task) {
|
|
56
|
+
const contract = `<verification_evidence_contract>\nCheck prerequisites must be executable in the check command or supported project policy; purpose prose and list order do not prepare an environment. A readiness gate is final verification, not implicit setup before the first CODE Work. PLAN and PLAN-REVIEW must compare claimed prerequisites with the actual launch path: a description saying migrate-before-check cannot repair a command that checks before migration. Prefer the existing self-contained project verification alias.\nBrowser checks must prove the expected surface exists and the measured set is nonempty before asserting layout geometry. An empty DOM is not evidence of no overlap. Derive navigation from the actual UI and accepted specification. Review whether the test can fail for the intended defect; a green named contour does not prove complete product semantics. Keep native test outcome separate from observation/cleanup: passed assertions with unknown cleanup are neither PASS nor a product assertion failure. Use retained native diagnostics and proof limits; generic timeouts or infrastructure errors do not authorize source repair. Do not patch the candidate product outside the assigned flow Work.\n</verification_evidence_contract>\n`;
|
|
57
|
+
if (!metadata)
|
|
58
|
+
return contract;
|
|
59
|
+
const originals = metadata.accepted_sources?.length ? ["Original accepted inputs (ordered intake, then question/answer pairs):", "A question is retained only to interpret its delivered user answer. Agent recommendations and options are not accepted decisions unless that answer explicitly adopts them.", ...metadata.accepted_sources.map(source => `- ${source.role}: ${safePath(runHome, source.path, false)} (sha256 ${source.sha256})`)].join("\n") : "Original accepted-input coverage is unavailable for this historical RUN. Do not treat SPECIFY as the original user input or claim that semantic preservation was verified.";
|
|
60
|
+
const originalContract = `<accepted_intent_sources>\n${originals}\nCompare original accepted inputs with SPECIFY, effective amendments, PLAN and observable implementation. Preserve material actors, operations, UI/API surfaces, state transitions and exceptions when applicable. API evidence does not prove UI behavior. Later text supersedes an earlier accepted decision only when explicitly accepted as such; unresolved conflicts are material questions, not last-text-wins. Report lost obligations with source and R/AC references. Never edit immutable accepted SPECIFY to conceal a finding. Use the supported upstream correction route; if unavailable or a wholly missing R/AC needs a new accepted revision, report an actionable blocker rather than repairing only PLAN. Do not fabricate HITL references. A structurally complete matrix is not semantic acceptance.\n</accepted_intent_sources>\n`;
|
|
61
|
+
return `${contract}${originalContract}<verification_matrix>\nRuntime generated the technical verification matrix: ${safePath(runHome, metadata.markdown.path, false)}; structured data: ${safePath(runHome, metadata.json.path, false)}. Source fingerprint: ${metadata.source_fingerprint}; completeness: ${metadata.completeness}. Read it before ${task}. This is a derived view of the named accepted requirements, PLAN and receipts, not semantic acceptance. Do not edit these generated files or manually duplicate receipt IDs/hashes/results. Record insufficient proof or violated criteria in the ordinary Stage/Work result with evidence references; modify only your assigned source/test/result documents. Review inputs remain read-only. A passed check proves only its named contour and limits, not all business semantics or production readiness.\n</verification_matrix>\n`;
|
|
62
|
+
}
|
|
63
|
+
/** Attachment and packet authority share a short transaction, then both files
|
|
64
|
+
* must be visible before the prompt claims they are ready. */
|
|
65
|
+
export function commitVerificationMatrixStart(context, prepared, attach) {
|
|
66
|
+
context.db.writeTransaction(() => { attach(); acceptVerificationMatrix(context, prepared); });
|
|
67
|
+
publishVerificationMatrix(context, prepared);
|
|
68
|
+
}
|
|
69
|
+
export function resumeVerificationMatrix(context, projectId, runId, stage) {
|
|
70
|
+
const retained = latestRunVerificationMatrix(context, projectId, runId, stage, "input");
|
|
71
|
+
const run = context.db.get("SELECT index_json FROM runs WHERE project_id = ? AND id = ?", [projectId, runId]);
|
|
72
|
+
if (run && JSON.parse(run.index_json).verification_matrix_contract === verificationMatrixContract && !retained)
|
|
73
|
+
throw new AppError("verification_matrix_packet_missing", "Marked Stage has no retained input matrix", 1, { stage, run_id: runId });
|
|
74
|
+
publishVerificationMatrix(context, retained);
|
|
75
|
+
return retained;
|
|
76
|
+
}
|
|
77
|
+
/** Resolve bounded authority outside the owning write transaction. */
|
|
78
|
+
export function prepareRunVerificationMatrix(context, input) {
|
|
79
|
+
const run = context.db.get("SELECT run_root, workspace_root, index_json FROM runs WHERE project_id = ? AND id = ?", [input.projectId, input.runId]);
|
|
80
|
+
if (!run)
|
|
81
|
+
throw new AppError("not_found", "Matrix RUN is missing", 1);
|
|
82
|
+
const index = JSON.parse(run.index_json);
|
|
83
|
+
if (index.verification_matrix_contract !== verificationMatrixContract)
|
|
84
|
+
return null;
|
|
85
|
+
const generation = assertRunMutationAllowed(context, input.projectId, input.runId);
|
|
86
|
+
if (!run.run_root)
|
|
87
|
+
throw new AppError("runtime_missing", "Matrix RUN home is missing", 1);
|
|
88
|
+
const home = run.run_root, workspace = run.workspace_root;
|
|
89
|
+
const owning = index.stage_runs?.find(item => item.stage === input.stage);
|
|
90
|
+
const attempt = input.stageAttempt ?? owning?.attempt ?? "try-001";
|
|
91
|
+
const sources = [], packets = [];
|
|
92
|
+
const intentContract = index.accepted_intent_contract;
|
|
93
|
+
if (intentContract !== undefined && intentContract !== acceptedIntentContract)
|
|
94
|
+
throw new AppError("accepted_intent_contract_unsupported", "Unknown accepted-input custody contract", 1, { contract: intentContract });
|
|
95
|
+
const intent = prepareAcceptedIntentSources(context, { projectId: input.projectId, runId: input.runId, home, stageDirectory: vnextStageDirectory(input.stage), marked: index.accepted_intent_contract === acceptedIntentContract });
|
|
96
|
+
sources.push(...intent.sources);
|
|
97
|
+
packets.push(...intent.packets);
|
|
98
|
+
const readSource = (role, root, relative, expected) => {
|
|
99
|
+
const file = safePath(root === "run" ? home : workspace, relative), bytes = fs.readFileSync(file), sha = digest(bytes);
|
|
100
|
+
if (expected && sha !== expected)
|
|
101
|
+
throw new AppError("verification_matrix_source_changed", "Matrix source differs from accepted bytes", 1, { role, path: relative, expected, current: sha });
|
|
102
|
+
sources.push({ role, root, path: slash(relative), sha256: sha });
|
|
103
|
+
return JSON.parse(bytes.toString("utf8"));
|
|
104
|
+
};
|
|
105
|
+
const specifySha = index.stage_runs?.find(item => item.stage === "specify")?.data_sha256;
|
|
106
|
+
const protocolizeSha = index.stage_runs?.find(item => item.stage === "protocolize")?.data_sha256;
|
|
107
|
+
if (!specifySha || !protocolizeSha)
|
|
108
|
+
throw new AppError("verification_matrix_source_unbound", "Marked matrix needs accepted SPECIFY and PROTOCOLIZE source checksums", 1);
|
|
109
|
+
const specify = readSource("specify", "run", "01-specify/specify.json", specifySha);
|
|
110
|
+
const protocolize = readSource("protocolize", "run", "02-protocolize/protocolize-result.json", protocolizeSha);
|
|
111
|
+
const amendments = new Map((protocolize.obligation_amendments ?? []).map(item => [item.target_id, item.replacement]));
|
|
112
|
+
const effective = (items) => items.map(item => ({ ...item, statement: amendments.get(item.id) ?? item.statement }));
|
|
113
|
+
// PROTOCOLIZE data_sha256 binds protocolize-result.json, not its derived
|
|
114
|
+
// Stage report. The report has a separate exact publication receipt.
|
|
115
|
+
const reportReceipts = context.db.all("SELECT payload_json FROM audit_events WHERE project_id = ? AND event_type = 'flow_run.stage_report' ORDER BY id DESC", [input.projectId]);
|
|
116
|
+
const protocolPublication = reportReceipts.map(row => JSON.parse(row.payload_json)).find(item => item.run_id === input.runId && item.stage === "protocolize" && item.attempt === index.stage_runs?.find(stage => stage.stage === "protocolize")?.attempt);
|
|
117
|
+
if (!protocolPublication)
|
|
118
|
+
throw new AppError("verification_matrix_source_unbound", "Marked matrix needs the retained PROTOCOLIZE report receipt", 1);
|
|
119
|
+
const protocolReport = readSource("protocolize_report", "run", "02-protocolize/stage-report.json", protocolPublication?.sha256);
|
|
120
|
+
const protocols = protocolReport.semantic.acceptance;
|
|
121
|
+
const ownership = Object.fromEntries(protocols.map((protocol, i) => [protocol, protocolize.obligation_ownership.filter(item => item.member_keys.includes(protocolize.delivery.members[i].key)).map(item => item.obligation_id)]));
|
|
122
|
+
const skeleton = input.stage === "plan" && input.role === "input";
|
|
123
|
+
const plans = [];
|
|
124
|
+
const reviewSkipped = index.settings?.code_review?.mode === "off" && Boolean(index.settings.code_review.reason?.trim()) && !index.stage_runs?.some(item => item.stage === "code-review");
|
|
125
|
+
const predecessor = input.stage === "plan-review" ? "plan" : input.stage === "code" ? "plan-review" : input.stage === "code-review" ? "code" : input.stage === "merge" ? reviewSkipped ? "code" : "code-review" : null;
|
|
126
|
+
const priorMatrix = input.role === "input" && predecessor ? latestRunVerificationMatrix(context, input.projectId, input.runId, predecessor, "output") : null;
|
|
127
|
+
if (input.role === "input" && predecessor && !priorMatrix)
|
|
128
|
+
throw new AppError("verification_matrix_packet_missing", "Marked Stage requires its accepted predecessor output matrix", 1, { stage: input.stage, predecessor });
|
|
129
|
+
if (!skeleton) {
|
|
130
|
+
const batchPath = "03-plan/code-work-batch.json", batchFile = safePath(home, batchPath);
|
|
131
|
+
if (!fs.existsSync(batchFile))
|
|
132
|
+
throw new AppError("verification_matrix_source_missing", "Marked matrix requires its generated CODE batch", 1, { path: batchPath });
|
|
133
|
+
const batchBytes = fs.readFileSync(batchFile), batchSha = digest(batchBytes);
|
|
134
|
+
const acceptedBatch = priorMatrix?.matrix.sources.find(source => source.role === "code_work_batch");
|
|
135
|
+
if (acceptedBatch && acceptedBatch.sha256 !== batchSha)
|
|
136
|
+
throw new AppError("verification_matrix_source_changed", "CODE batch differs from accepted predecessor matrix", 1, { path: batchPath, expected: acceptedBatch.sha256, current: batchSha });
|
|
137
|
+
const batchSnapshot = `${vnextStageDirectory(input.stage)}/verification/sources/${batchSha}/code-work-batch.json`;
|
|
138
|
+
packets.push(prepareStagePacket(safePath(home, batchSnapshot), batchBytes));
|
|
139
|
+
sources.push({ role: "code_work_batch", root: "run", path: batchSnapshot, sha256: batchSha });
|
|
140
|
+
if (input.stage === "merge" && input.role === "output")
|
|
141
|
+
sources.push({ role: "code_work_batch_current", root: "run", path: batchPath, sha256: batchSha });
|
|
142
|
+
for (const protocol of protocols) {
|
|
143
|
+
const relative = `.memory-bank/protocol/${protocol}/plan.json`, file = safePath(workspace, relative);
|
|
144
|
+
// PLAN bytes are retained before MERGE cleanup; later recovery does not
|
|
145
|
+
// depend on a feature checkout remaining on disk.
|
|
146
|
+
let bytes;
|
|
147
|
+
if (fs.existsSync(file))
|
|
148
|
+
bytes = fs.readFileSync(file);
|
|
149
|
+
else {
|
|
150
|
+
const retained = latestRunVerificationMatrix(context, input.projectId, input.runId, "merge", "input");
|
|
151
|
+
const prior = retained?.matrix.sources.find(source => source.role === `plan:${protocol}` && source.root === "run");
|
|
152
|
+
if (!prior)
|
|
153
|
+
throw new AppError("verification_matrix_source_missing", "Accepted PLAN was removed without retained source", 1, { protocol_id: protocol });
|
|
154
|
+
bytes = fs.readFileSync(safePath(home, prior.path));
|
|
155
|
+
if (digest(bytes) !== prior.sha256)
|
|
156
|
+
throw new AppError("verification_matrix_source_changed", "Retained PLAN checksum differs", 1, { protocol_id: protocol });
|
|
157
|
+
}
|
|
158
|
+
const plan = JSON.parse(bytes.toString("utf8"));
|
|
159
|
+
const acceptedSource = priorMatrix?.matrix.sources.find(source => source.role === `plan:${protocol}`);
|
|
160
|
+
if (acceptedSource && digest(bytes) !== acceptedSource.sha256)
|
|
161
|
+
throw new AppError("verification_matrix_source_changed", "PLAN differs from accepted predecessor matrix", 1, { protocol_id: protocol, expected: acceptedSource.sha256, current: digest(bytes) });
|
|
162
|
+
if (plan.protocol_id !== protocol || !Array.isArray(plan.checks) || !Array.isArray(plan.items) || !Array.isArray(plan.acceptance))
|
|
163
|
+
throw new AppError("verification_matrix_source_invalid", "Matrix requires a validated structured PLAN", 1, { protocol_id: protocol });
|
|
164
|
+
const sha = digest(bytes), snapshot = `${vnextStageDirectory(input.stage)}/verification/sources/${sha}/plan.json`;
|
|
165
|
+
packets.push(prepareStagePacket(safePath(home, snapshot), bytes));
|
|
166
|
+
sources.push({ role: `plan:${protocol}`, root: "run", path: snapshot, sha256: sha });
|
|
167
|
+
plans.push(plan);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const semanticFile = input.semanticFile;
|
|
171
|
+
let semanticAssessment;
|
|
172
|
+
if (semanticFile && fs.existsSync(semanticFile)) {
|
|
173
|
+
const relative = path.relative(home, semanticFile);
|
|
174
|
+
readSource("semantic_assessment", "run", relative);
|
|
175
|
+
const source = sources[sources.length - 1];
|
|
176
|
+
semanticAssessment = { root: source.root, path: source.path, sha256: source.sha256 };
|
|
177
|
+
}
|
|
178
|
+
const mergeAcceptanceFile = path.join(home, "07-merge", "merge-gate-acceptance.json");
|
|
179
|
+
const final = input.stage === "merge" && input.role === "output";
|
|
180
|
+
let merge;
|
|
181
|
+
let policyChecks = [];
|
|
182
|
+
if (!skeleton && input.stage !== "merge")
|
|
183
|
+
policyChecks = effectiveCheckDeclarations(workspace, [], ["work", "code", "readiness", "merge", "release"]);
|
|
184
|
+
let selected = input.receipts ?? [];
|
|
185
|
+
if (!input.receipts && priorMatrix && ["code-review", "merge"].includes(input.stage)) {
|
|
186
|
+
const ids = new Set([...priorMatrix.matrix.criteria.flatMap(row => row.checks), ...priorMatrix.matrix.policy_checks].flatMap(fact => typeof fact.result?.id === "string" ? [fact.result.id] : []));
|
|
187
|
+
selected = checkReceipts(context, { projectId: input.projectId, runId: input.runId }).filter(receipt => ids.has(receipt.id));
|
|
188
|
+
}
|
|
189
|
+
let finalBindings;
|
|
190
|
+
if (input.stage === "merge") {
|
|
191
|
+
const gate = readSource("merge_gate", "run", "07-merge/merge-gate.json");
|
|
192
|
+
if (index.final_check_coverage_contract === finalCheckCoverageContract) {
|
|
193
|
+
for (const role of final ? ["baseline", "source", "target"] : ["baseline", "source"])
|
|
194
|
+
readSource(`check_profile_${role}`, "run", `07-merge/check-profile-${role}.json`);
|
|
195
|
+
}
|
|
196
|
+
const semanticRefs = new Set(plans.flatMap(plan => plan.acceptance.flatMap(entry => entry.check_refs.map(id => `${plan.protocol_id}/${id}`))));
|
|
197
|
+
policyChecks = gate.checks.filter(check => !semanticRefs.has(check.canonical_ref ?? check.id));
|
|
198
|
+
if (final) {
|
|
199
|
+
const acceptance = readSource("merge_acceptance", "run", "07-merge/merge-gate-acceptance.json");
|
|
200
|
+
if (acceptance.run_id !== input.runId || acceptance.gate_hash !== gate.gate_hash || acceptance.profile_hash !== gate.profile_hash || !acceptance.accepted_tree)
|
|
201
|
+
throw new AppError("verification_matrix_binding_invalid", "Final matrix has foreign MERGE acceptance", 1);
|
|
202
|
+
finalBindings = new Map();
|
|
203
|
+
for (const binding of acceptance.receipts)
|
|
204
|
+
for (const ref of binding.binding_refs) {
|
|
205
|
+
if (finalBindings.has(ref))
|
|
206
|
+
throw new AppError("verification_matrix_binding_ambiguous", "Final acceptance repeats a check binding", 1, { check_ref: ref });
|
|
207
|
+
finalBindings.set(ref, binding.id);
|
|
208
|
+
}
|
|
209
|
+
const persisted = checkReceipts(context, { projectId: input.projectId, runId: input.runId });
|
|
210
|
+
selected = acceptance.receipts.map(binding => {
|
|
211
|
+
const receipt = selected.find(item => item.id === binding.id && item.input_hash === binding.input_hash);
|
|
212
|
+
if (!receipt)
|
|
213
|
+
throw new AppError("verification_matrix_binding_invalid", "Final matrix lacks bound receipt", 1, { receipt_id: binding.id });
|
|
214
|
+
const original = persisted.find(item => item.id === binding.id && item.input_hash === binding.input_hash);
|
|
215
|
+
if (!original)
|
|
216
|
+
throw new AppError("verification_matrix_binding_invalid", "Final matrix lacks retained native execution receipt", 1, { receipt_id: binding.id });
|
|
217
|
+
return original;
|
|
218
|
+
});
|
|
219
|
+
merge = { merge_request_id: acceptance.merge_request_id, work_id: acceptance.work_id, gate_hash: acceptance.gate_hash, profile_hash: acceptance.profile_hash, accepted_tree: acceptance.accepted_tree, acceptance_ref: { root: "run", path: "07-merge/merge-gate-acceptance.json", sha256: digest(fs.readFileSync(mergeAcceptanceFile)) } };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const declarations = [...plans.flatMap(plan => plan.checks.map(check => ({ ...check, canonical_ref: `${plan.protocol_id}/${check.id}` }))), ...policyChecks];
|
|
223
|
+
const facts = declarations.map(check => {
|
|
224
|
+
const ref = check.canonical_ref ?? check.id;
|
|
225
|
+
// Unscoped CODE IDs are permitted only by the accepted PSET validator's
|
|
226
|
+
// uniqueness rule. Never silently alias the same short ID across sources.
|
|
227
|
+
const uniqueShortId = plans.filter(plan => plan.checks.some(candidate => candidate.id === check.id)).length === 1;
|
|
228
|
+
const matches = selected.filter(receipt => finalBindings ? finalBindings.get(ref) === receipt.id : receipt.check_refs.includes(ref) || (input.stage !== "merge" && uniqueShortId && receipt.check_refs.includes(check.id)));
|
|
229
|
+
if (matches.length > 1)
|
|
230
|
+
throw new AppError("verification_matrix_binding_ambiguous", "Matrix was supplied multiple current receipts for one declaration", 1, { check_ref: ref });
|
|
231
|
+
const receipt = matches[0];
|
|
232
|
+
const due = input.stage === "merge" ? check.run_at !== "release" : ["work", "code", "readiness"].includes(check.run_at);
|
|
233
|
+
if (!receipt)
|
|
234
|
+
return { id: check.id, canonical_ref: ref, declaration: check, result: null, disposition: skeleton || input.stage.startsWith("plan") ? "not_run" : due && input.role === "output" ? "unavailable" : "not_due" };
|
|
235
|
+
const valid = receipt.status !== "passed" || checkReceiptEvidenceValid(receipt);
|
|
236
|
+
const portable = portableReceipt(receipt, home);
|
|
237
|
+
const receiptFile = safePath(home, portable.receipt_path);
|
|
238
|
+
if (!fs.existsSync(receiptFile))
|
|
239
|
+
return { id: check.id, canonical_ref: ref, declaration: check, result: portable, disposition: "unavailable", reason: "receipt_file_missing" };
|
|
240
|
+
const bytes = fs.readFileSync(receiptFile);
|
|
241
|
+
sources.push({ role: `receipt:${ref}`, root: "run", path: portable.receipt_path, sha256: digest(bytes) });
|
|
242
|
+
const retainedReceipt = JSON.parse(bytes.toString("utf8"));
|
|
243
|
+
for (const artifact of retainedReceipt.artifacts ?? []) {
|
|
244
|
+
if (path.isAbsolute(artifact.path) || artifact.path.includes("\0") || artifact.path.split(/[\\/]/).includes(".."))
|
|
245
|
+
throw new AppError("verification_matrix_path_invalid", "Native artifact must remain inside its evidence directory", 1, { path: artifact.path });
|
|
246
|
+
const artifactPath = slash(path.join(path.dirname(portable.receipt_path), "artifacts", artifact.path));
|
|
247
|
+
const artifactFile = safePath(home, artifactPath);
|
|
248
|
+
if (fs.existsSync(artifactFile))
|
|
249
|
+
sources.push({ role: `artifact:${ref}:${artifact.path}`, root: "run", path: artifactPath, sha256: digest(fs.readFileSync(artifactFile)) });
|
|
250
|
+
}
|
|
251
|
+
if (receipt.status !== "aborted" && fs.existsSync(receipt.completion_path)) {
|
|
252
|
+
const completionPath = portable.completion_path;
|
|
253
|
+
const completionFile = safePath(home, completionPath);
|
|
254
|
+
sources.push({ role: `completion:${ref}`, root: "run", path: completionPath, sha256: digest(fs.readFileSync(completionFile)) });
|
|
255
|
+
}
|
|
256
|
+
return { id: check.id, canonical_ref: ref, declaration: check, result: portable, disposition: valid ? "retained" : "unavailable", ...(!valid ? { reason: "receipt_evidence_invalid" } : {}) };
|
|
257
|
+
});
|
|
258
|
+
const works = context.db.all("SELECT work_id, payload_json FROM works WHERE project_id = ? AND run_id = ?", [input.projectId, input.runId]).flatMap(work => {
|
|
259
|
+
const source = work.payload_json ? JSON.parse(work.payload_json).source : null;
|
|
260
|
+
return source ? [{ work_id: work.work_id, protocol_id: source.protocol_id, plan_item_id: source.plan_item_id }] : [];
|
|
261
|
+
});
|
|
262
|
+
const repair = index.variables?.["merge.source_repair"];
|
|
263
|
+
const header = { project_id: input.projectId, run_id: input.runId, stage: input.stage, stage_attempt: attempt, role: input.role, completeness: input.completeness ?? (skeleton ? "skeleton" : input.stage.startsWith("plan") ? "declared" : final ? "final" : "execution"), ...(repair?.cycle ? { review_cycle: repair.cycle } : {}), ...(merge ? { merge } : {}) };
|
|
264
|
+
const matrix = buildVerificationMatrix({ header, sources, requirements: effective(specify.requirements), criteria: effective(specify.acceptance_criteria), ownership, plans, policyChecks, facts, works, ...(semanticAssessment ? { semanticAssessment } : {}) });
|
|
265
|
+
const root = `${vnextStageDirectory(input.stage)}/verification/${matrix.header.source_fingerprint}`;
|
|
266
|
+
const json = prepareStagePacket(safePath(home, `${root}/verification-matrix.json`), Buffer.from(stableJson(matrix)));
|
|
267
|
+
const markdown = prepareStagePacket(safePath(home, `${root}/verification-matrix.md`), Buffer.from(renderVerificationMatrix(matrix)));
|
|
268
|
+
packets.push(json, markdown);
|
|
269
|
+
const metadata = { contract: verificationMatrixContract, role: header.role, completeness: header.completeness, source_fingerprint: matrix.header.source_fingerprint, json: { path: slash(path.relative(home, json.file)), sha256: json.sha256 }, markdown: { path: slash(path.relative(home, markdown.file)), sha256: markdown.sha256 } };
|
|
270
|
+
if (intent.sources.length)
|
|
271
|
+
metadata.accepted_sources = intent.sources;
|
|
272
|
+
if (index.final_check_coverage_contract === finalCheckCoverageContract)
|
|
273
|
+
metadata.coverage_contract = finalCheckCoverageContract;
|
|
274
|
+
const predecessors = (index.stage_runs ?? []).filter(item => item.stage !== input.stage && item.status === "done").map(item => ({ stage: item.stage, ...(item.attempt ? { attempt: item.attempt } : {}), ...(item.data_sha256 ? { data_sha256: item.data_sha256 } : {}) }));
|
|
275
|
+
return { projectId: input.projectId, runId: input.runId, stage: input.stage, home, attempt, generation, packets, matrix, metadata, predecessors };
|
|
276
|
+
}
|
|
277
|
+
/** Called inside the existing owning settlement; publication is after COMMIT. */
|
|
278
|
+
export function acceptVerificationMatrix(context, prepared) {
|
|
279
|
+
if (!prepared)
|
|
280
|
+
return;
|
|
281
|
+
assertRunMutationAllowed(context, prepared.projectId, prepared.runId, prepared.generation);
|
|
282
|
+
const run = context.db.get("SELECT index_json FROM runs WHERE project_id = ? AND id = ?", [prepared.projectId, prepared.runId]);
|
|
283
|
+
const index = JSON.parse(run.index_json);
|
|
284
|
+
if (index.stage_runs?.find(item => item.stage === prepared.stage)?.attempt !== prepared.attempt)
|
|
285
|
+
throw new AppError("verification_matrix_owner_changed", "Matrix owning attempt changed during preparation", 1, { stage: prepared.stage, expected_attempt: prepared.attempt });
|
|
286
|
+
for (const source of prepared.predecessors ?? []) {
|
|
287
|
+
const current = index.stage_runs?.find(item => item.stage === source.stage);
|
|
288
|
+
if (current?.attempt !== source.attempt || current?.data_sha256 !== source.data_sha256)
|
|
289
|
+
throw new AppError("verification_matrix_source_changed", "Accepted predecessor changed after matrix preparation", 1, { stage: source.stage });
|
|
290
|
+
}
|
|
291
|
+
for (const packet of prepared.packets)
|
|
292
|
+
acceptStagePacket(context, { projectId: prepared.projectId, runId: prepared.runId, stage: prepared.stage, prepared: packet });
|
|
293
|
+
}
|
|
294
|
+
export function publishVerificationMatrix(context, prepared) {
|
|
295
|
+
if (!prepared)
|
|
296
|
+
return;
|
|
297
|
+
for (const packet of prepared.packets) {
|
|
298
|
+
publishStagePacket(context, prepared.projectId, prepared.runId, prepared.stage, packet.file);
|
|
299
|
+
if (!fs.existsSync(packet.file) || digest(fs.readFileSync(packet.file)) !== packet.sha256)
|
|
300
|
+
throw new AppError("publication_pending", "Matrix packet is not published with its accepted checksum", 1, { file: packet.file, effect: "committed" });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export function latestRunVerificationMatrix(context, projectId, runId, stage, role) {
|
|
304
|
+
const run = context.db.get("SELECT run_root, index_json FROM runs WHERE project_id = ? AND id = ?", [projectId, runId]);
|
|
305
|
+
if (!run?.run_root)
|
|
306
|
+
return null;
|
|
307
|
+
const index = JSON.parse(run.index_json);
|
|
308
|
+
if (index.accepted_intent_contract !== undefined && index.accepted_intent_contract !== acceptedIntentContract)
|
|
309
|
+
throw new AppError("accepted_intent_contract_unsupported", "Unknown accepted-input custody contract", 1, { contract: index.accepted_intent_contract });
|
|
310
|
+
const attempt = index.stage_runs?.find(item => item.stage === stage)?.attempt;
|
|
311
|
+
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id = ? AND event_type = 'flow_run.stage_packet' ORDER BY id DESC", [projectId]);
|
|
312
|
+
for (const row of rows) {
|
|
313
|
+
const packet = JSON.parse(row.payload_json);
|
|
314
|
+
if (packet.run_id !== runId || packet.stage !== stage || packet.attempt !== attempt || !packet.file.endsWith("/verification-matrix.json"))
|
|
315
|
+
continue;
|
|
316
|
+
const bytes = Buffer.from(packet.base64, "base64");
|
|
317
|
+
if (digest(bytes) !== packet.sha256)
|
|
318
|
+
throw new AppError("stage_packet_invalid", "Retained matrix packet is corrupt", 1);
|
|
319
|
+
const matrix = JSON.parse(bytes.toString("utf8"));
|
|
320
|
+
if (role && matrix.header.role !== role)
|
|
321
|
+
continue;
|
|
322
|
+
if (matrix.schema_id !== verificationMatrixContract || matrix.header.run_id !== runId || matrix.header.stage !== stage || matrix.header.stage_attempt !== attempt)
|
|
323
|
+
throw new AppError("stage_packet_invalid", "Retained matrix owner differs from its packet", 1);
|
|
324
|
+
packet.file = resolveStagePublicationPath(context, projectId, runId, packet.file);
|
|
325
|
+
const mdFile = packet.file.replace(/\.json$/, ".md");
|
|
326
|
+
const paired = rows.map(row => JSON.parse(row.payload_json)).find(item => item.run_id === runId && item.stage === stage && item.attempt === attempt && resolveStagePublicationPath(context, projectId, runId, item.file) === mdFile);
|
|
327
|
+
if (!paired)
|
|
328
|
+
throw new AppError("stage_packet_invalid", "Retained matrix lacks its exact Markdown packet", 1);
|
|
329
|
+
const mdBytes = Buffer.from(paired.base64, "base64");
|
|
330
|
+
if (digest(mdBytes) !== paired.sha256)
|
|
331
|
+
throw new AppError("stage_packet_invalid", "Retained matrix Markdown checksum differs", 1);
|
|
332
|
+
const md = { file: mdFile, bytes: mdBytes, sha256: paired.sha256 };
|
|
333
|
+
const json = { file: packet.file, bytes, sha256: packet.sha256 };
|
|
334
|
+
const metadata = { contract: verificationMatrixContract, role: matrix.header.role, completeness: matrix.header.completeness, source_fingerprint: matrix.header.source_fingerprint, json: { path: slash(path.relative(run.run_root, packet.file)), sha256: packet.sha256 }, markdown: { path: slash(path.relative(run.run_root, mdFile)), sha256: md.sha256 } };
|
|
335
|
+
const acceptedSources = matrix.sources.filter(source => acceptedIntentSourceRole(source.role)).sort((a, b) => a.role === "accepted_intake" ? -1 : b.role === "accepted_intake" ? 1 : compare(a.role, b.role));
|
|
336
|
+
if (index.accepted_intent_contract === acceptedIntentContract && !acceptedSources.some(source => source.role === "accepted_intake"))
|
|
337
|
+
throw new AppError("accepted_intent_source_gap", "Marked matrix is missing its original accepted intake", 1, { stage, run_id: runId });
|
|
338
|
+
if (acceptedSources.length)
|
|
339
|
+
metadata.accepted_sources = acceptedSources;
|
|
340
|
+
if (index.final_check_coverage_contract === finalCheckCoverageContract)
|
|
341
|
+
metadata.coverage_contract = finalCheckCoverageContract;
|
|
342
|
+
const sourcePackets = matrix.sources.filter(source => (source.role.startsWith("plan:") || source.role === "code_work_batch" || acceptedIntentSourceRole(source.role)) && source.root === "run").map(source => {
|
|
343
|
+
const file = safePath(run.run_root, source.path, false);
|
|
344
|
+
const retained = rows.map(row => JSON.parse(row.payload_json)).find(item => item.run_id === runId && item.stage === stage && item.attempt === attempt && resolveStagePublicationPath(context, projectId, runId, item.file) === file && item.sha256 === source.sha256);
|
|
345
|
+
if (!retained)
|
|
346
|
+
throw new AppError("stage_packet_invalid", "Matrix PLAN source lacks retained bytes", 1, { path: source.path });
|
|
347
|
+
const bytes = Buffer.from(retained.base64, "base64");
|
|
348
|
+
if (digest(bytes) !== source.sha256)
|
|
349
|
+
throw new AppError("stage_packet_invalid", "Matrix PLAN source checksum differs", 1, { path: source.path });
|
|
350
|
+
return { file, bytes, sha256: source.sha256 };
|
|
351
|
+
});
|
|
352
|
+
const prepared = { projectId, runId, stage, home: run.run_root, attempt: packet.attempt, packets: [...sourcePackets, json, md], matrix, metadata };
|
|
353
|
+
return prepared;
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
function portableReceipt(receipt, home) {
|
|
358
|
+
const relative = (file) => slash(path.relative(home, safePath(home, path.relative(home, file))));
|
|
359
|
+
return { ...receipt, receipt_path: relative(receipt.receipt_path), completion_path: relative(receipt.completion_path), stdout_path: relative(receipt.stdout_path), stderr_path: relative(receipt.stderr_path), artifacts: receipt.artifacts.map(item => {
|
|
360
|
+
const artifactPath = path.isAbsolute(item.path) ? path.relative(path.join(path.dirname(receipt.receipt_path), "artifacts"), item.path) : item.path;
|
|
361
|
+
if (path.isAbsolute(artifactPath) || artifactPath.includes("\0") || artifactPath.split(/[\\/]/).includes(".."))
|
|
362
|
+
throw new AppError("verification_matrix_path_invalid", "Native artifact must remain inside its evidence directory", 1, { path: item.path });
|
|
363
|
+
safePath(home, path.join(path.dirname(relative(receipt.receipt_path)), "artifacts", artifactPath));
|
|
364
|
+
return { ...item, path: slash(artifactPath) };
|
|
365
|
+
}) };
|
|
366
|
+
}
|
|
367
|
+
function safePath(root, relative, inspectFilesystem = true) {
|
|
368
|
+
if (path.isAbsolute(relative) || relative.split(/[\\/]/).includes(".."))
|
|
369
|
+
throw new AppError("verification_matrix_path_invalid", "Matrix reference must remain inside its declared root", 1, { path: relative });
|
|
370
|
+
const resolved = path.resolve(root, relative);
|
|
371
|
+
// Retained packet resolution is SQL-only and can run in a settlement writer.
|
|
372
|
+
// Publication and all new filesystem inputs enforce realpath containment.
|
|
373
|
+
if (!inspectFilesystem)
|
|
374
|
+
return resolved;
|
|
375
|
+
let ancestor = resolved;
|
|
376
|
+
while (!fs.existsSync(ancestor) && path.dirname(ancestor) !== ancestor)
|
|
377
|
+
ancestor = path.dirname(ancestor);
|
|
378
|
+
if (fs.existsSync(ancestor)) {
|
|
379
|
+
const actual = fs.realpathSync(ancestor), realRoot = fs.realpathSync(root);
|
|
380
|
+
if (actual !== realRoot && !actual.startsWith(`${realRoot}${path.sep}`))
|
|
381
|
+
throw new AppError("verification_matrix_path_invalid", "Matrix source escapes its root through a symlink", 1, { path: relative });
|
|
382
|
+
}
|
|
383
|
+
return resolved;
|
|
384
|
+
}
|
|
385
|
+
function digest(value) { return crypto.createHash("sha256").update(value).digest("hex"); }
|
|
386
|
+
function compare(a, b) { return a < b ? -1 : a > b ? 1 : 0; }
|
|
387
|
+
function unique(items) { return [...new Set(items)].sort(compare); }
|
|
388
|
+
function slash(value) { return value.split(path.sep).join("/"); }
|
|
389
|
+
function escape(value) { return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\|/g, "|").replace(/[\r\n]+/g, "<br>").replace(/`/g, "`"); }
|
|
390
|
+
function canonical(value) { if (Array.isArray(value))
|
|
391
|
+
return value.map(canonical); if (value && typeof value === "object")
|
|
392
|
+
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => compare(a, b)).map(([key, item]) => [key, canonical(item)])); return value; }
|
|
393
|
+
function stableJson(value) { return `${JSON.stringify(canonical(value), null, 2)}\n`; }
|
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { parse as parseYaml } from "yaml";
|
|
5
|
-
const canonicalOnlyFlowNames = ["mb-init.md", "mb-upgrade.md", "mb-distill.md"];
|
|
5
|
+
export const canonicalOnlyFlowNames = Object.freeze(["mb-init.md", "mb-upgrade.md", "mb-distill.md", "mb-audit.md", "review.md"]);
|
|
6
6
|
export function resolveStatusProjectRoot(input) {
|
|
7
7
|
if (input.requestedRoot) {
|
|
8
8
|
const absolute = path.resolve(input.requestedRoot);
|