@deksden-com/dd-flow-cli 0.9.0-beta.16 → 0.9.0-beta.161
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 +965 -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 +417 -0
- package/dist/cli/command-metadata.js +303 -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/delivery.js +108 -0
- package/dist/cli/diagnostic-invocation.js +62 -0
- package/dist/cli/diagnostic.js +131 -0
- package/dist/cli/error-output.js +62 -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 +521 -19
- package/dist/cli/hook-ingress.js +89 -0
- package/dist/cli/input-preparation.js +193 -0
- package/dist/cli/interactive-invocation.js +33 -0
- package/dist/cli/interactive.js +114 -0
- package/dist/cli/memory-fix-invocation.js +52 -0
- package/dist/cli/memory-fix.js +100 -0
- package/dist/cli/memory-flow-admission.js +54 -0
- package/dist/cli/memory-init-invocation.js +85 -0
- package/dist/cli/memory-init.js +250 -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 +94 -0
- package/dist/cli/native-hook-preparation.js +82 -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 +2020 -555
- 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 +103 -2
- package/dist/domain/delivery-flows.js +8 -0
- package/dist/domain/diagnostic-aspects.js +103 -0
- package/dist/domain/diagnostic-flows.js +8 -0
- package/dist/domain/distill-flow.js +20 -0
- package/dist/domain/interactive-flow.js +1 -0
- package/dist/domain/memory-fix-flow.js +2 -0
- package/dist/domain/review-fix-flow.js +2 -0
- package/dist/domain/source-snapshot-flows.js +4 -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 +71 -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 +50 -0
- package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
- package/dist/harness-runtime/bin/dd-zcode.mjs +95 -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 +87 -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 +225 -0
- package/dist/harness-runtime/lib/agy-native-inventory.mjs +19 -0
- package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
- package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +74 -0
- package/dist/harness-runtime/lib/agy-transcript-stream.mjs +54 -0
- package/dist/harness-runtime/lib/daemon-observation.d.mts +3 -0
- package/dist/harness-runtime/lib/daemon-observation.mjs +171 -0
- package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +512 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +7 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1362 -0
- package/dist/harness-runtime/lib/dd-agy.mjs +105 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +271 -0
- package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-codex.mjs +986 -0
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +155 -0
- package/dist/harness-runtime/lib/dd-droid.mjs +739 -0
- package/dist/harness-runtime/lib/dd-grok-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +667 -0
- package/dist/harness-runtime/lib/dd-grok.mjs +182 -0
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +772 -0
- package/dist/harness-runtime/lib/dd-opencode.mjs +411 -0
- package/dist/harness-runtime/lib/dd-zcode-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +845 -0
- package/dist/harness-runtime/lib/dd-zcode.mjs +1239 -0
- package/dist/harness-runtime/lib/delegation-instructions.d.mts +16 -0
- package/dist/harness-runtime/lib/delegation-instructions.mjs +179 -0
- package/dist/harness-runtime/lib/delivery-command.mjs +84 -0
- package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
- package/dist/harness-runtime/lib/driver-recovery.mjs +121 -0
- package/dist/harness-runtime/lib/droid-observation.mjs +70 -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 +11 -0
- package/dist/harness-runtime/lib/lifecycle-contract.mjs +20 -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 +8 -0
- package/dist/harness-runtime/lib/native-hook-command.mjs +306 -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 +38 -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 +112 -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 +140 -0
- package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
- package/dist/harness-runtime/lib/operation-progress.mjs +118 -0
- package/dist/harness-runtime/lib/process-json.d.mts +5 -0
- package/dist/harness-runtime/lib/process-json.mjs +200 -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 +238 -0
- package/dist/harness-runtime/lib/zcode-native-hook-ownership.mjs +109 -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/code-work-result.schema.json +2 -1
- package/dist/schemas/delivery-stage-result.schema.json +286 -0
- 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/distill-stage-result.schema.json +667 -0
- package/dist/schemas/distill-work-result.schema.json +428 -0
- package/dist/schemas/execution-bundle.schema.json +215 -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/interactive-stage-result.schema.json +47 -0
- package/dist/schemas/interactive-work-result.schema.json +63 -0
- package/dist/schemas/mb-fix-stage-result.schema.json +93 -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 +2 -2
- package/dist/schemas/release-impact.schema.json +3 -3
- package/dist/schemas/release-manifest.schema.json +291 -0
- package/dist/schemas/review-fix-stage-result.schema.json +210 -0
- package/dist/schemas/run-control-receipt.schema.json +119 -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 +3 -3
- package/dist/services/accepted-intent.js +139 -0
- package/dist/services/assigned-lifecycle.js +382 -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 +344 -0
- package/dist/services/check-runner-proof.js +373 -0
- package/dist/services/cleanup.js +133 -40
- package/dist/services/cli-operation-classifier.js +32 -64
- package/dist/services/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +1426 -121
- package/dist/services/codex-capacity.js +367 -0
- package/dist/services/codex-hook-delivery.js +41 -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 +25 -0
- package/dist/services/controller-child-capacity.js +71 -0
- package/dist/services/controller-child-observer.js +121 -0
- package/dist/services/controller-child-repair.js +117 -0
- package/dist/services/controller-execution.js +97 -0
- package/dist/services/controller-fanout.js +277 -0
- package/dist/services/controller-memory-task.js +45 -0
- package/dist/services/controller-memory-worker.js +51 -0
- package/dist/services/controller-result-authority.js +127 -0
- package/dist/services/controller-work-failure.js +198 -0
- package/dist/services/dashboard.js +145 -58
- package/dist/services/delivery-access.js +123 -0
- package/dist/services/delivery-approval.js +68 -0
- package/dist/services/delivery-artifact.js +86 -0
- package/dist/services/delivery-checks.js +178 -0
- package/dist/services/delivery-execution.js +181 -0
- package/dist/services/delivery-intents.js +212 -0
- package/dist/services/delivery-operation.js +81 -0
- package/dist/services/delivery-policy.js +91 -0
- package/dist/services/delivery-procedures.js +43 -0
- package/dist/services/delivery-request.js +99 -0
- package/dist/services/delivery-result.js +144 -0
- package/dist/services/delivery-stage-commands.js +26 -0
- package/dist/services/delivery-stage-entry.js +56 -0
- package/dist/services/delivery-stage-handlers.js +135 -0
- package/dist/services/delivery-stage-results.js +94 -0
- package/dist/services/descriptor-coordinator-session.js +37 -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 +495 -0
- package/dist/services/descriptor-stage-coordinator.js +318 -0
- package/dist/services/descriptor-stage-settlement.js +268 -0
- package/dist/services/descriptor-stage-start.js +175 -0
- package/dist/services/diagnostic-evidence.js +73 -0
- package/dist/services/diagnostic-repair-intake.js +123 -0
- package/dist/services/diagnostic-repair-source-intake.js +102 -0
- package/dist/services/diagnostic-report-publication.js +72 -0
- package/dist/services/diagnostic-report.js +97 -0
- package/dist/services/diagnostic-run-bundle.js +113 -0
- package/dist/services/diagnostic-snapshot.js +159 -0
- package/dist/services/diagnostic-stage-handlers.js +109 -0
- package/dist/services/diagnostic-stage-results.js +158 -0
- package/dist/services/diagnostic-start.js +134 -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/distill-document-publication.js +280 -0
- package/dist/services/distill-promotion.js +197 -0
- package/dist/services/distill-publication-custody.js +162 -0
- package/dist/services/distill-stage-handlers.js +249 -0
- package/dist/services/distill-stage-results.js +105 -0
- package/dist/services/distill-user-inputs.js +4 -0
- package/dist/services/distill-work-batch.js +42 -0
- package/dist/services/distill-work-collection.js +74 -0
- package/dist/services/distill-work-registration.js +93 -0
- package/dist/services/distill-work-results.js +98 -0
- package/dist/services/engines.js +354 -163
- package/dist/services/eval-snapshots.js +1326 -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 +316 -0
- package/dist/services/flow-catalog.js +54 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +404 -0
- package/dist/services/generic-execution.js +165 -0
- package/dist/services/harness-adapter.js +342 -35
- 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 +813 -327
- package/dist/services/hybrid-contracts.js +479 -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 +261 -0
- package/dist/services/interactive-attached-session.js +215 -0
- package/dist/services/interactive-baseline-custody.js +54 -0
- package/dist/services/interactive-before-versions.js +148 -0
- package/dist/services/interactive-bundle-data.js +85 -0
- package/dist/services/interactive-checks.js +179 -0
- package/dist/services/interactive-execution.js +33 -0
- package/dist/services/interactive-finish-integration.js +236 -0
- package/dist/services/interactive-git-baseline.js +230 -0
- package/dist/services/interactive-git-dispatch.js +278 -0
- package/dist/services/interactive-input-delivery.js +82 -0
- package/dist/services/interactive-mutation-scope.js +231 -0
- package/dist/services/interactive-request.js +287 -0
- package/dist/services/interactive-run-bundle.js +109 -0
- package/dist/services/interactive-stage-entry.js +41 -0
- package/dist/services/interactive-stage-handlers.js +289 -0
- package/dist/services/interactive-stage-observation.js +136 -0
- package/dist/services/interactive-stage-results.js +111 -0
- package/dist/services/interactive-user-inputs.js +142 -0
- package/dist/services/interactive-work-batch.js +43 -0
- package/dist/services/interactive-work-collection.js +119 -0
- package/dist/services/interactive-work-completion.js +180 -0
- package/dist/services/interactive-work-context.js +249 -0
- package/dist/services/interactive-work-history.js +112 -0
- package/dist/services/interactive-work-registration.js +124 -0
- package/dist/services/interactive-work-results.js +115 -0
- package/dist/services/interactive-work-start.js +155 -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 +2549 -0
- package/dist/services/managed-daemon-binding.js +129 -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 +380 -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 +491 -0
- package/dist/services/memory-finish-readiness.js +169 -0
- package/dist/services/memory-fix-finish-integration.js +129 -0
- package/dist/services/memory-fix-git-dispatch.js +139 -0
- package/dist/services/memory-fix-intake-custody.js +11 -0
- package/dist/services/memory-fix-intake-settlement.js +127 -0
- package/dist/services/memory-fix-publication.js +196 -0
- package/dist/services/memory-fix-repair-admission.js +116 -0
- package/dist/services/memory-fix-request.js +141 -0
- package/dist/services/memory-fix-run-bundle.js +83 -0
- package/dist/services/memory-fix-scope.js +78 -0
- package/dist/services/memory-fix-sources.js +85 -0
- package/dist/services/memory-fix-stage-entry.js +24 -0
- package/dist/services/memory-fix-stage-handlers.js +282 -0
- package/dist/services/memory-fix-stage-results.js +106 -0
- package/dist/services/memory-fix-workspace.js +127 -0
- package/dist/services/memory-flow-user-inputs.js +88 -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 +181 -0
- package/dist/services/memory-init-controller-start.js +119 -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 +225 -0
- package/dist/services/memory-lint-config.js +194 -0
- package/dist/services/memory-native-review-copy.js +127 -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 +489 -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-flow-source.js +195 -0
- package/dist/services/project-git-integration.js +92 -0
- 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 +29 -0
- package/dist/services/repair-receipt.js +13 -0
- package/dist/services/retained-native-hook.js +274 -0
- package/dist/services/review-copy.js +165 -0
- package/dist/services/review-deferral.js +23 -0
- package/dist/services/review-fix-handoff.js +82 -0
- package/dist/services/review-fix-intake-custody.js +17 -0
- package/dist/services/review-fix-stage-entry.js +43 -0
- package/dist/services/review-fix-stage-handlers.js +176 -0
- package/dist/services/review-fix-stage-results.js +86 -0
- package/dist/services/run-control-receipt.js +56 -0
- package/dist/services/run-control-worker.js +469 -0
- package/dist/services/run-control.js +1109 -0
- package/dist/services/run-controller-adapter.js +434 -0
- package/dist/services/run-controller-capture.js +186 -0
- package/dist/services/run-controller-process.js +226 -0
- package/dist/services/run-controller-recovery.js +335 -0
- package/dist/services/run-controller-state.js +106 -0
- package/dist/services/run-controller.js +1717 -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 +485 -0
- package/dist/services/run-start-custody.js +189 -0
- package/dist/services/run-timeline.js +59 -0
- package/dist/services/runs.js +996 -271
- 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 +37 -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 +141 -0
- package/dist/services/stage-lifecycle.js +156 -119
- package/dist/services/stage-pause.js +222 -94
- package/dist/services/stage-report-renderer.js +230 -6
- package/dist/services/stage-work-graph.js +52 -0
- package/dist/services/technical-notes.js +31 -0
- package/dist/services/tooling.js +111 -44
- 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 +302 -91
- package/dist/services/vnext-code.js +325 -251
- package/dist/services/vnext-contracts.js +10 -1
- package/dist/services/vnext-execution-profile.js +80 -5
- package/dist/services/vnext-fanout.js +399 -20
- package/dist/services/vnext-merge.js +336 -114
- package/dist/services/vnext-plan-review.js +288 -133
- package/dist/services/vnext-plan.js +257 -110
- package/dist/services/vnext-protocolize.js +534 -96
- package/dist/services/vnext-specify.js +131 -84
- package/dist/services/vnext-workspace-policy.js +7 -2
- package/dist/services/work-registry.js +1950 -215
- package/dist/services/work-retry-context.js +55 -0
- package/dist/services/workspace-bootstrap.js +53 -15
- package/dist/services/workspace-files.js +85 -0
- package/dist/services/worktrees.js +108 -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 +931 -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 +384 -0
- package/package.json +52 -13
- package/tools/create-canon-release.mjs +33 -0
- package/tools/probe-codex-history.mjs +37 -0
- package/tools/produce-hybrid-release.mjs +41 -0
- package/tools/repair-paused-run-status.mjs +84 -0
- package/tools/verification-jobs.mjs +342 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
import { publishImmutableInput } from "../storage/immutable-input.js";
|
|
5
|
+
import { prepareAgentOutputFile } from "../storage/agent-output.js";
|
|
6
|
+
import { parseLifecycleCommand } from "./lifecycle-command.js";
|
|
7
|
+
import { stageAttempt, stageCycle, stageWorkIds } from "./stage-work-graph.js";
|
|
8
|
+
import { assertRunMutationAllowed } from "./run-recovery.js";
|
|
9
|
+
import { appendEvent, digest } from "./run-controller-state.js";
|
|
10
|
+
import { retryWork } from "./work-registry.js";
|
|
11
|
+
import { blockStageForRuntime } from "./stage-blocker.js";
|
|
12
|
+
import { pauseStageForUser } from "./stage-pause.js";
|
|
13
|
+
/** SQL settlement provenance, never the worker's prose, distinguishes a semantic refusal. */
|
|
14
|
+
export function explicitWorkFailure(context, projectId, runId, workId) {
|
|
15
|
+
const work = context.db.get("SELECT w.status,w.result,w.parent_work_id,w.payload_json,r.run_root FROM works w JOIN runs r ON r.project_id=w.project_id AND r.id=w.run_id WHERE w.project_id=? AND w.run_id=? AND w.work_id=?", [projectId, runId, workId]);
|
|
16
|
+
if (!work || work.status !== "failed" || !work.parent_work_id || work.result === null || !work.run_root)
|
|
17
|
+
return null;
|
|
18
|
+
const payload = JSON.parse(work.payload_json ?? "null");
|
|
19
|
+
if (typeof payload?.kind === "string" && /^(memory|interactive)/.test(payload.kind))
|
|
20
|
+
return null;
|
|
21
|
+
if (!context.db.get("SELECT 1 FROM sqlite_schema WHERE name='audit_events'") || !context.db.get("SELECT 1 FROM sqlite_schema WHERE name='lifecycle_invocations'"))
|
|
22
|
+
return null;
|
|
23
|
+
const resultHash = digestBytes(work.result);
|
|
24
|
+
const receipts = context.db.all(`SELECT a.payload_json,l.command,l.status AS invocation_status FROM audit_events a JOIN lifecycle_invocations l ON l.id=json_extract(a.payload_json,'$.invocation_id')
|
|
25
|
+
WHERE a.project_id=? AND a.event_type='lifecycle.work_settlement' AND json_extract(a.payload_json,'$.run_id')=? AND json_extract(a.payload_json,'$.work_id')=? ORDER BY a.rowid DESC`, [projectId, runId, workId]);
|
|
26
|
+
for (const row of receipts) {
|
|
27
|
+
const receipt = JSON.parse(row.payload_json), parsed = parseLifecycleCommand(row.command);
|
|
28
|
+
if (row.invocation_status !== "settled" || parsed.kind !== "standalone" || parsed.invocation.operation !== "work_fail" || receipt.result_sha256 !== resultHash || receipt.response?.status !== "failed")
|
|
29
|
+
continue;
|
|
30
|
+
if (!context.db.get("SELECT 1 FROM work_sessions WHERE id=? AND work_id=? AND status='failed'", [receipt.work_session_id, workId]))
|
|
31
|
+
continue;
|
|
32
|
+
return { work_id: workId, work_session_id: receipt.work_session_id, parent_work_id: work.parent_work_id, result_sha256: resultHash, primary_reason: work.result, result_ref: path.join(work.run_root, "works", workId, "result.json") };
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
import { createHash } from "node:crypto";
|
|
37
|
+
const digestBytes = (text) => createHash("sha256").update(text).digest("hex");
|
|
38
|
+
function events(context, row, type) {
|
|
39
|
+
return context.db.all(`SELECT e.data_json FROM run_controller_events e JOIN run_controllers c ON c.controller_id=e.controller_id WHERE c.project_id=? AND c.run_id=? AND e.event_type=? ORDER BY e.rowid`, [row.project_id, row.run_id, type]).map(e => JSON.parse(e.data_json));
|
|
40
|
+
}
|
|
41
|
+
export function prepareWorkFailureResolution(context, row, stage, failure) {
|
|
42
|
+
if (!stageWorkIds(context, row.project_id, row.run_id, stage).has(failure.work_id))
|
|
43
|
+
throw new AppError("work_failure_scope_changed", "Failed Work no longer belongs to this Stage", 1);
|
|
44
|
+
const current = explicitWorkFailure(context, row.project_id, row.run_id, failure.work_id);
|
|
45
|
+
if (!current || current.work_session_id !== failure.work_session_id || current.result_sha256 !== failure.result_sha256)
|
|
46
|
+
throw new AppError("work_failure_scope_changed", "Failed Work receipt changed before resolution", 1);
|
|
47
|
+
const attempt = stageAttempt(context, row.project_id, row.run_id, stage), cycle = stageCycle(context, row.project_id, row.run_id, stage);
|
|
48
|
+
const episode = digest([row.project_id, row.run_id, stage, attempt, cycle, failure.work_id, failure.work_session_id, failure.result_sha256]);
|
|
49
|
+
const run = context.db.get("SELECT run_root FROM runs WHERE project_id=? AND id=?", [row.project_id, row.run_id]);
|
|
50
|
+
const round = events(context, row, "work_failure_action_applied").filter(e => e.episode_id === episode).length;
|
|
51
|
+
const root = path.join(run.run_root, "work-failure-resolutions", episode, `round-${round}`);
|
|
52
|
+
const resolution = { ...failure, episode_id: episode, stage, attempt, cycle, decision_file: path.join(root, "decision-input.json"), accepted_file: path.join(root, "decision.json"), diagnostic_file: path.join(root, "failure.json"),
|
|
53
|
+
retry_used: events(context, row, "work_failure_action_reserved").some(e => e.action === "retry" && e.work_id === failure.work_id) };
|
|
54
|
+
fs.mkdirSync(root, { recursive: true });
|
|
55
|
+
publishImmutableInput(resolution.diagnostic_file, Buffer.from(JSON.stringify({ schema_id: "work-failure-context@1", ...failure, episode_id: episode, stage, attempt, cycle, packet: path.join(run.run_root, "works", failure.work_id, "starts") }, null, 2)), "work_failure_context_changed");
|
|
56
|
+
if (!fs.existsSync(resolution.decision_file)) {
|
|
57
|
+
prepareAgentOutputFile(resolution.decision_file);
|
|
58
|
+
fs.writeFileSync(resolution.decision_file, "", { flag: "wx", mode: 0o600 });
|
|
59
|
+
}
|
|
60
|
+
return resolution;
|
|
61
|
+
}
|
|
62
|
+
const text = (value) => typeof value === "string" && value.trim().length > 0;
|
|
63
|
+
export function readFailureDecision(resolution) {
|
|
64
|
+
const file = fs.existsSync(resolution.accepted_file) ? resolution.accepted_file : resolution.decision_file;
|
|
65
|
+
const stat = fs.lstatSync(file);
|
|
66
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024)
|
|
67
|
+
throw new AppError("work_failure_decision_invalid", "Expected a regular decision JSON file", 2);
|
|
68
|
+
let value;
|
|
69
|
+
try {
|
|
70
|
+
value = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
throw new AppError("work_failure_decision_invalid", "Write one complete decision JSON object", 2);
|
|
74
|
+
}
|
|
75
|
+
const keys = ["schema_id", "episode_id", "action", "reason", "evidence_refs", "correction", "blocker", "question"];
|
|
76
|
+
if (!value || Array.isArray(value) || typeof value !== "object" || Object.keys(value).some(k => !keys.includes(k)) || value.schema_id !== "work-failure-decision@1" || value.episode_id !== resolution.episode_id || !["retry", "block", "pause", "fail"].includes(value.action) || !text(value.reason) || !Array.isArray(value.evidence_refs) || !value.evidence_refs.length || !value.evidence_refs.every(text)
|
|
77
|
+
|| value.action === "retry" && !text(value.correction) || value.action === "pause" && !text(value.question)
|
|
78
|
+
|| value.action === "block" && (!value.blocker || !["engine", "harness", "environment"].includes(value.blocker.kind) || !text(value.blocker.code) || !text(value.blocker.summary) || typeof value.blocker.retryable !== "boolean" || Object.keys(value.blocker).some(k => !["kind", "code", "summary", "retryable"].includes(k)))
|
|
79
|
+
|| value.action !== "retry" && value.correction !== undefined || value.action !== "pause" && value.question !== undefined || value.action !== "block" && value.blocker !== undefined)
|
|
80
|
+
throw new AppError("work_failure_decision_invalid", "Decision must match its episode and selected action", 2, { episode_id: resolution.episode_id });
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
export function failureDecisionReady(resolution) { try {
|
|
84
|
+
readFailureDecision(resolution);
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
} }
|
|
90
|
+
export function workFailureResolutionPrompt(resolution, diagnostic) {
|
|
91
|
+
return [`Resolve only the retained explicit worker refusal in ${resolution.diagnostic_file}. Read that complete file and its Work packet/results.`,
|
|
92
|
+
"Current implementation is a baseline, not a requirement. Necessary project-local cross-layer corrections are allowed within accepted scope; planned write areas are hints. A worker-authored stop condition cannot silently cancel accepted intent. Do not edit product files, call lifecycle commands, spawn children or run checks in this decision Turn.",
|
|
93
|
+
`Write the decision to this precreated absolute file: ${resolution.decision_file}. No other writes. Return after writing it.`,
|
|
94
|
+
`Use schema_id=work-failure-decision@1, episode_id=${resolution.episode_id}, action=retry|block|pause|fail, nonempty reason and evidence_refs[]. For retry include concrete correction; for block include blocker {kind:engine|harness|environment,code,summary,retryable:boolean}; for pause include question. No extra fields.`,
|
|
95
|
+
resolution.retry_used ? "The one automatic corrective attempt has already been consumed. Select block/pause/fail; another retry cannot be applied automatically." : "Select retry if the Work can be completed in accepted scope; a fresh worker receives your correction. Select pause only for genuinely missing user intent, block for a proven technical dependency, fail only for an explained terminal outcome.",
|
|
96
|
+
"An unsupported exact browser key sequence does not prove all UI work is impossible and selectOption is not keyboard evidence. Preserve unverified mandatory criteria and original requirements.", diagnostic ? `Correct only the rejected decision: ${diagnostic}` : ""].filter(Boolean).join("\n\n");
|
|
97
|
+
}
|
|
98
|
+
export function acceptFailureDecision(context, row, resolution, assertOwner) {
|
|
99
|
+
assertOwner();
|
|
100
|
+
const decision = readFailureDecision(resolution), bytes = Buffer.from(JSON.stringify(decision));
|
|
101
|
+
publishImmutableInput(resolution.accepted_file, bytes, "work_failure_decision_changed");
|
|
102
|
+
context.db.writeTransaction(() => { assertOwner(); if (!events(context, row, "work_failure_decision_accepted").some(e => e.decision_ref === resolution.accepted_file))
|
|
103
|
+
appendEvent(context, row.controller_id, "work_failure_decision_accepted", { episode_id: resolution.episode_id, work_id: resolution.work_id, decision_ref: resolution.accepted_file, decision }); });
|
|
104
|
+
return decision;
|
|
105
|
+
}
|
|
106
|
+
export function workFailureDiagnostic(resolution, decision) {
|
|
107
|
+
return { source: "explicit_work_failure", episode_id: resolution.episode_id, work_id: resolution.work_id, work_session_id: resolution.work_session_id, result_ref: resolution.diagnostic_file, primary_reason: resolution.primary_reason, ...(decision ? { disposition: decision } : {}) };
|
|
108
|
+
}
|
|
109
|
+
/** Repair file-before-event and mutation-before-ack crash windows before HITL delivery. */
|
|
110
|
+
export async function reconcilePendingWorkFailure(context, row, state, continuationKind, projectRoot, assertOwner, writerSettled) {
|
|
111
|
+
const resolution = state.work_failure;
|
|
112
|
+
if (!resolution || resolution.deferred || !fs.existsSync(resolution.accepted_file) || continuationKind === "terminal")
|
|
113
|
+
return "none";
|
|
114
|
+
const session = state.current_session === null ? undefined : state.sessions[state.current_session];
|
|
115
|
+
if (!session)
|
|
116
|
+
throw new AppError("work_failure_scope_changed", "Failure resolution lost its coordinator", 1);
|
|
117
|
+
if (!await writerSettled(session))
|
|
118
|
+
return "waiting";
|
|
119
|
+
const decision = acceptFailureDecision(context, row, resolution, assertOwner);
|
|
120
|
+
applyWorkFailureDecision(context, row, resolution, decision, projectRoot, assertOwner);
|
|
121
|
+
delete state.work_failure;
|
|
122
|
+
state.last_continuation = null;
|
|
123
|
+
return "applied";
|
|
124
|
+
}
|
|
125
|
+
/** Reserve first; a committed retry is recovered through its start authority, never replayed blindly. */
|
|
126
|
+
export function applyWorkFailureDecision(context, row, resolution, decision, projectRoot, assertOwner) {
|
|
127
|
+
assertOwner();
|
|
128
|
+
assertRunMutationAllowed(context, row.project_id, row.run_id, row.generation);
|
|
129
|
+
const index = JSON.parse(context.db.get("SELECT index_json FROM runs WHERE project_id=? AND id=?", [row.project_id, row.run_id])?.index_json ?? "{}");
|
|
130
|
+
if (resolution.stage !== index.current_stage
|
|
131
|
+
|| resolution.attempt !== stageAttempt(context, row.project_id, row.run_id, resolution.stage) || resolution.cycle !== stageCycle(context, row.project_id, row.run_id, resolution.stage)
|
|
132
|
+
|| !stageWorkIds(context, row.project_id, row.run_id, resolution.stage).has(resolution.work_id))
|
|
133
|
+
throw new AppError("work_failure_scope_changed", "Failure resolution belongs to a stale Stage attempt", 1);
|
|
134
|
+
const applied = events(context, row, "work_failure_action_applied").find(e => e.decision_ref === resolution.accepted_file);
|
|
135
|
+
if (applied)
|
|
136
|
+
return applied;
|
|
137
|
+
const reserved = events(context, row, "work_failure_action_reserved").find(e => e.decision_ref === resolution.accepted_file);
|
|
138
|
+
const current = context.db.get("SELECT status,current_start_invocation_id FROM works WHERE project_id=? AND run_id=? AND work_id=?", [row.project_id, row.run_id, resolution.work_id]);
|
|
139
|
+
if (!current)
|
|
140
|
+
throw new AppError("work_failure_scope_changed", "Work disappeared before resolution", 1);
|
|
141
|
+
let action = decision.action;
|
|
142
|
+
const used = events(context, row, "work_failure_action_reserved").some(e => e.action === "retry" && e.work_id === resolution.work_id && e.decision_ref !== resolution.accepted_file);
|
|
143
|
+
const retainedDecision = events(context, row, "work_failure_decision_accepted").find(e => e.decision_ref === resolution.accepted_file);
|
|
144
|
+
if (!retainedDecision || JSON.stringify(retainedDecision.decision) !== JSON.stringify(decision))
|
|
145
|
+
throw new AppError("work_failure_scope_changed", "Failure decision was not accepted or changed after acceptance", 1);
|
|
146
|
+
const exhausted = action === "retry" && used;
|
|
147
|
+
if (exhausted)
|
|
148
|
+
action = "block";
|
|
149
|
+
if (!reserved) {
|
|
150
|
+
if (current.status !== "failed" || explicitWorkFailure(context, row.project_id, row.run_id, resolution.work_id)?.work_session_id !== resolution.work_session_id)
|
|
151
|
+
throw new AppError("work_failure_scope_changed", "Failure changed before action reservation", 1);
|
|
152
|
+
context.db.writeTransaction(() => { assertOwner(); appendEvent(context, row.controller_id, "work_failure_action_reserved", { episode_id: resolution.episode_id, work_id: resolution.work_id, work_session_id: resolution.work_session_id, action, decision_ref: resolution.accepted_file }); });
|
|
153
|
+
}
|
|
154
|
+
else if (reserved.action !== action)
|
|
155
|
+
throw new AppError("work_failure_scope_changed", "Reserved failure action differs", 1);
|
|
156
|
+
let receipt;
|
|
157
|
+
if (action === "retry") {
|
|
158
|
+
receipt = retryWork(context, resolution.work_id, decision.reason, { episode_id: resolution.episode_id, decision_ref: resolution.accepted_file, correction: decision.correction, failed_result_sha256: resolution.result_sha256 });
|
|
159
|
+
}
|
|
160
|
+
else if (action === "fail")
|
|
161
|
+
throw new AppError("work_failure_unresolved", decision.reason, 1, workFailureDiagnostic(resolution, decision));
|
|
162
|
+
else {
|
|
163
|
+
const coordinator = context.db.get("SELECT status FROM works WHERE project_id=? AND run_id=? AND work_id=?", [row.project_id, row.run_id, resolution.parent_work_id]);
|
|
164
|
+
const blocker = exhausted ? { kind: "engine", code: "work_resolution_exhausted", summary: JSON.stringify(workFailureDiagnostic(resolution, decision)), retryable: false } : decision.blocker;
|
|
165
|
+
const boundBlocker = blocker ? { ...blocker, summary: `${blocker.summary}\n[work-failure:${resolution.episode_id}:${digest(resolution.accepted_file)}]` } : undefined;
|
|
166
|
+
if (coordinator?.status === "paused" && reserved) {
|
|
167
|
+
const stage = index.stage_runs?.find((s) => s.stage === resolution.stage);
|
|
168
|
+
const matches = action === "pause" ? stage?.pause?.work_id === resolution.parent_work_id && typeof stage.pause.question_path === "string" && fs.readFileSync(stage.pause.question_path, "utf8") === decision.question
|
|
169
|
+
: stage?.blocker?.work_id === resolution.parent_work_id && stage.blocker.code === boundBlocker?.code && stage.blocker.kind === boundBlocker?.kind && stage.blocker.summary === boundBlocker?.summary;
|
|
170
|
+
if (!matches)
|
|
171
|
+
throw new AppError("work_failure_scope_changed", "Coordinator pause belongs to another failure action", 1);
|
|
172
|
+
receipt = { ok: true, reconciled: true, outcome: action === "pause" ? "paused" : "blocked", run_id: row.run_id, stage: resolution.stage, work_id: resolution.parent_work_id, ...(boundBlocker ? { blocker: boundBlocker } : {}) };
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
if (coordinator?.status !== "running")
|
|
176
|
+
throw new AppError("work_failure_scope_changed", "Failure resolution needs the running coordinator Work", 1);
|
|
177
|
+
const scope = { projectRoot, runId: row.run_id, stage: resolution.stage, workId: resolution.parent_work_id };
|
|
178
|
+
receipt = action === "pause" ? pauseStageForUser(context, { ...scope, question: decision.question }) : blockStageForRuntime(context, { ...scope, ...boundBlocker });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const outcome = { episode_id: resolution.episode_id, decision_ref: resolution.accepted_file, stage: resolution.stage, attempt: resolution.attempt, cycle: resolution.cycle, work_id: resolution.work_id, work_session_id: resolution.work_session_id, action, receipt };
|
|
182
|
+
context.db.writeTransaction(() => { assertOwner(); appendEvent(context, row.controller_id, "work_failure_action_applied", outcome); });
|
|
183
|
+
return outcome;
|
|
184
|
+
}
|
|
185
|
+
/** Match only this current bound block; an old unrelated pause must not be hidden. */
|
|
186
|
+
export function workFailureBlockActive(context, row, index) {
|
|
187
|
+
const stage = index.current_stage;
|
|
188
|
+
const blocker = index.stage_runs?.find(s => s.stage === stage)?.blocker;
|
|
189
|
+
if (!stage || !blocker)
|
|
190
|
+
return false;
|
|
191
|
+
return events(context, row, "work_failure_action_applied").some(e => {
|
|
192
|
+
const receipt = e.receipt;
|
|
193
|
+
if (!receipt)
|
|
194
|
+
return false;
|
|
195
|
+
return e.action === "block" && e.stage === stage && e.attempt === stageAttempt(context, row.project_id, row.run_id, stage) && e.cycle === stageCycle(context, row.project_id, row.run_id, stage)
|
|
196
|
+
&& receipt?.work_id === blocker.work_id && receipt.blocker?.summary === blocker.summary && receipt.blocker?.code === blocker.code && receipt.blocker?.kind === blocker.kind;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { commandResult } from '../harness-runtime/lib/process-json.mjs';
|
|
4
|
+
import { SETUP_STARTUP_MS } from '../harness-runtime/lib/setup-progress.mjs';
|
|
4
5
|
import { isActiveProtocolStatus, isActiveQueueStatus, isQueueHistoryStatus } from "../domain/contracts.js";
|
|
5
6
|
import { AppError } from "../shared/errors.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { prepareOutputFile } from "../cli/input-preparation.js";
|
|
8
|
+
import { ensureDir, resolveProjectRoot, resolveProtocolPlanPath } from "../storage/paths.js";
|
|
9
|
+
import { dashboardMarkdownPath, globalDashboardHtmlPath, globalDashboardJsonPath, globalDashboardMarkdownPath, projectDashboardHtmlPath, projectDashboardJsonPath, projectDashboardDir, projectSummaryJsonPath, protocolDashboardHtmlPath, protocolDashboardJsonPath, readProjectConfig } from "./config.js";
|
|
8
10
|
import { queueForProject } from "./merge-queue.js";
|
|
9
11
|
import { publishProjectSummary } from "./project-summary.js";
|
|
10
12
|
import { requireProjectByRoot } from "./projects.js";
|
|
@@ -13,70 +15,82 @@ import { activeFlowSessionsForProject } from "./sessions.js";
|
|
|
13
15
|
import { usageForRun } from "./usage.js";
|
|
14
16
|
import { normalizeProtocolLifecycle } from "./protocol-lifecycle.js";
|
|
15
17
|
import { planSummary, planWithProgress } from "./plan-runtime.js";
|
|
16
|
-
export function getCmuxStatus(context, input) {
|
|
18
|
+
export async function getCmuxStatus(context, input) {
|
|
17
19
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
18
|
-
return { ok: true, project_root: project.root, cmux: detectCmux(context) };
|
|
20
|
+
return { ok: true, project_root: project.root, cmux: await detectCmux(context) };
|
|
19
21
|
}
|
|
20
|
-
export function
|
|
22
|
+
export function prepareDashboardRender(context, input) {
|
|
21
23
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
24
|
+
if (projectRecoveryGuarded(context, project.id))
|
|
25
|
+
throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
|
|
22
26
|
const format = parseDashboardFormat(input.format);
|
|
27
|
+
if (input.protocol)
|
|
28
|
+
requireProtocol(context, input.protocol, project.id);
|
|
29
|
+
const config = readProjectConfig(context, project.id);
|
|
30
|
+
const output = input.output
|
|
31
|
+
? path.resolve(project.root, input.output)
|
|
32
|
+
: format === "html"
|
|
33
|
+
? input.protocol ? protocolDashboardHtmlPath(context, project.id, input.protocol) : projectDashboardHtmlPath(context, project.id)
|
|
34
|
+
: dashboardMarkdownPath(project.root, config);
|
|
35
|
+
prepareOutputFile(output);
|
|
36
|
+
if (format === "html")
|
|
37
|
+
prepareOutputFile(input.protocol ? protocolDashboardJsonPath(context, project.id, input.protocol) : projectDashboardJsonPath(context, project.id));
|
|
38
|
+
return { project, format, output };
|
|
39
|
+
}
|
|
40
|
+
export function renderDashboard(context, input) {
|
|
41
|
+
const { project, format, output } = prepareDashboardRender(context, input);
|
|
23
42
|
if (format === "html") {
|
|
24
43
|
if (input.protocol) {
|
|
25
44
|
return renderProtocolDashboardHtml(context, project, input.protocol, input.output);
|
|
26
45
|
}
|
|
27
46
|
return renderProjectDashboardHtml(context, project, input.output);
|
|
28
47
|
}
|
|
29
|
-
const config = readProjectConfig(context, project.id);
|
|
30
|
-
const output = input.output
|
|
31
|
-
? path.resolve(path.isAbsolute(input.output) ? input.output : path.join(project.root, input.output))
|
|
32
|
-
: dashboardMarkdownPath(project.root, config);
|
|
33
48
|
const markdown = renderProjectDashboardMarkdown(context, project, output);
|
|
34
49
|
writeMarkdown(output, markdown);
|
|
35
50
|
return { ok: true, project_root: project.root, dashboard: { path: output, bytes: Buffer.byteLength(markdown) } };
|
|
36
51
|
}
|
|
37
|
-
export function
|
|
52
|
+
export function prepareGlobalDashboardRender(context, input = {}) {
|
|
38
53
|
const format = parseDashboardFormat(input.format);
|
|
54
|
+
const output = input.output ? path.resolve(input.output) : format === "html" ? globalDashboardHtmlPath(context) : globalDashboardMarkdownPath(context);
|
|
55
|
+
prepareOutputFile(output);
|
|
56
|
+
if (format === "html")
|
|
57
|
+
prepareOutputFile(globalDashboardJsonPath(context));
|
|
58
|
+
return { format, output };
|
|
59
|
+
}
|
|
60
|
+
export function renderGlobalDashboard(context, input = {}) {
|
|
61
|
+
const { format, output } = prepareGlobalDashboardRender(context, input);
|
|
39
62
|
if (format === "html") {
|
|
40
63
|
return renderGlobalDashboardHtml(context, input.output);
|
|
41
64
|
}
|
|
42
|
-
const output = input.output
|
|
43
|
-
? path.resolve(input.output)
|
|
44
|
-
: globalDashboardMarkdownPath(context);
|
|
45
65
|
const markdown = renderGlobalDashboardMarkdown(context, output);
|
|
46
66
|
writeMarkdown(output, markdown);
|
|
47
67
|
return { ok: true, dashboard: { path: output, bytes: Buffer.byteLength(markdown) } };
|
|
48
68
|
}
|
|
49
|
-
export function openDashboard(context, input) {
|
|
69
|
+
export async function openDashboard(context, input) {
|
|
70
|
+
prepareDashboardOptions(input);
|
|
50
71
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
51
72
|
const config = readProjectConfig(context, project.id);
|
|
52
73
|
const format = parseDashboardFormat(input.format, "html");
|
|
53
|
-
if (input.viewer && input.viewer !== "cmux") {
|
|
54
|
-
throw new AppError("validation", "--viewer must be cmux", 2);
|
|
55
|
-
}
|
|
56
74
|
const dashboardPath = format === "html" ? projectDashboardHtmlPath(context, project.id) : dashboardMarkdownPath(project.root, config);
|
|
57
75
|
return {
|
|
58
76
|
ok: true,
|
|
59
77
|
project_root: project.root,
|
|
60
78
|
dashboard: { path: dashboardPath },
|
|
61
|
-
open: openCmuxDashboard(context, project.root, dashboardPath, format)
|
|
79
|
+
open: await openCmuxDashboard(context, project.root, dashboardPath, format)
|
|
62
80
|
};
|
|
63
81
|
}
|
|
64
|
-
export function openGlobalDashboard(context, input = {}) {
|
|
65
|
-
|
|
66
|
-
throw new AppError("validation", "--viewer must be cmux", 2);
|
|
67
|
-
}
|
|
82
|
+
export async function openGlobalDashboard(context, input = {}) {
|
|
83
|
+
prepareDashboardOptions(input);
|
|
68
84
|
const format = parseDashboardFormat(input.format, "html");
|
|
69
85
|
const rendered = renderGlobalDashboard(context, { format });
|
|
70
86
|
return {
|
|
71
87
|
ok: true,
|
|
72
88
|
dashboard: rendered.dashboard,
|
|
73
|
-
open: openDashboardPath(context, rendered.dashboard.path, format)
|
|
89
|
+
open: await openDashboardPath(context, rendered.dashboard.path, format)
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
|
-
export function openProtocolDashboard(context, input) {
|
|
77
|
-
|
|
78
|
-
throw new AppError("validation", "--viewer must be cmux", 2);
|
|
79
|
-
}
|
|
92
|
+
export async function openProtocolDashboard(context, input) {
|
|
93
|
+
prepareDashboardOptions(input);
|
|
80
94
|
const format = parseDashboardFormat(input.format, "html");
|
|
81
95
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
82
96
|
if (format !== "html") {
|
|
@@ -90,17 +104,43 @@ export function openProtocolDashboard(context, input) {
|
|
|
90
104
|
project_root: project.root,
|
|
91
105
|
protocol_id: input.protocol,
|
|
92
106
|
dashboard: rendered.dashboard,
|
|
93
|
-
open: openCmuxDashboard(context, project.root, rendered.dashboard.path, format)
|
|
107
|
+
open: await openCmuxDashboard(context, project.root, rendered.dashboard.path, format)
|
|
94
108
|
};
|
|
95
109
|
}
|
|
96
|
-
export function
|
|
110
|
+
export function prepareDashboardRefresh(context, input) {
|
|
111
|
+
prepareDashboardOptions(input);
|
|
97
112
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
98
113
|
const config = readProjectConfig(context, project.id);
|
|
99
114
|
const format = parseDashboardFormat(input.format);
|
|
100
115
|
const openMode = input.open ?? "auto";
|
|
101
|
-
if (
|
|
102
|
-
|
|
116
|
+
if (config.dashboard.project) {
|
|
117
|
+
if (projectRecoveryGuarded(context, project.id))
|
|
118
|
+
throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
|
|
119
|
+
if (input.protocol)
|
|
120
|
+
requireProtocol(context, input.protocol, project.id);
|
|
121
|
+
prepareRefreshOutputs(context, project, config, format, input.protocol);
|
|
103
122
|
}
|
|
123
|
+
return { project, config, format, openMode };
|
|
124
|
+
}
|
|
125
|
+
function prepareRefreshOutputs(context, project, config, format, protocol) {
|
|
126
|
+
if (config.dashboard.project) {
|
|
127
|
+
if (!protocol)
|
|
128
|
+
prepareOutputFile(projectSummaryJsonPath(context, project.id));
|
|
129
|
+
if (format === "html") {
|
|
130
|
+
prepareOutputFile(protocol ? protocolDashboardHtmlPath(context, project.id, protocol) : projectDashboardHtmlPath(context, project.id));
|
|
131
|
+
prepareOutputFile(protocol ? protocolDashboardJsonPath(context, project.id, protocol) : projectDashboardJsonPath(context, project.id));
|
|
132
|
+
}
|
|
133
|
+
else
|
|
134
|
+
prepareOutputFile(dashboardMarkdownPath(project.root, config));
|
|
135
|
+
}
|
|
136
|
+
if (config.dashboard.global) {
|
|
137
|
+
prepareOutputFile(format === "html" ? globalDashboardHtmlPath(context) : globalDashboardMarkdownPath(context, config));
|
|
138
|
+
if (format === "html")
|
|
139
|
+
prepareOutputFile(globalDashboardJsonPath(context));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export async function refreshDashboard(context, input) {
|
|
143
|
+
const { project, config, format, openMode } = prepareDashboardRefresh(context, input);
|
|
104
144
|
if (!config.dashboard.project) {
|
|
105
145
|
return {
|
|
106
146
|
ok: true,
|
|
@@ -124,7 +164,7 @@ export function refreshDashboard(context, input) {
|
|
|
124
164
|
dashboard: rendered.dashboard,
|
|
125
165
|
project_summary: projectSummary,
|
|
126
166
|
global_dashboard: global.dashboard,
|
|
127
|
-
open: shouldOpen ? openCmuxDashboard(context, project.root, rendered.dashboard.path, format) : { ok: true, skipped: true, reason: "open_disabled" }
|
|
167
|
+
open: shouldOpen ? await openCmuxDashboard(context, project.root, rendered.dashboard.path, format) : { ok: true, skipped: true, reason: "open_disabled" }
|
|
128
168
|
};
|
|
129
169
|
}
|
|
130
170
|
export function refreshGlobalDashboard(context, input = {}) {
|
|
@@ -143,8 +183,9 @@ export function refreshAllDashboards(context, input = {}) {
|
|
|
143
183
|
return { ok: true, project_id: project.id, project_root: project.root, skipped: true, reason: "dashboard_project_disabled" };
|
|
144
184
|
}
|
|
145
185
|
try {
|
|
146
|
-
|
|
186
|
+
prepareRefreshOutputs(context, project, { ...config, dashboard: { ...config.dashboard, global: false } }, format);
|
|
147
187
|
const rendered = renderDashboard(context, { projectRoot: project.root, format });
|
|
188
|
+
const projectSummary = publishProjectSummary(context, { project });
|
|
148
189
|
return { ok: true, project_id: project.id, project_root: project.root, dashboard: rendered.dashboard, project_summary: projectSummary };
|
|
149
190
|
}
|
|
150
191
|
catch (error) {
|
|
@@ -170,10 +211,22 @@ export function refreshAllDashboards(context, input = {}) {
|
|
|
170
211
|
}
|
|
171
212
|
export function autoRefreshDashboards(context, input) {
|
|
172
213
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
173
|
-
|
|
214
|
+
// Hooks and usage ingestion continue to record receipts after capture.
|
|
215
|
+
// Their derived timestamp must not mutate the captured workspace.
|
|
216
|
+
if (projectRecoveryGuarded(context, project.id))
|
|
217
|
+
return { ok: true, skipped: true, reason: "run_recovery_guarded" };
|
|
218
|
+
const configured = readProjectConfig(context, project.id);
|
|
219
|
+
// Automatic observation must not change a memory/diagnostic baseline or
|
|
220
|
+
// invalidate accepted delivery checks by rewriting workspace projections.
|
|
221
|
+
// Keep projections in Home; do not hide runtime-created paths in Git or
|
|
222
|
+
// weaken source preservation by excluding user-owned .tasks directories.
|
|
223
|
+
const initializing = context.db.get("SELECT 1 FROM runs WHERE project_id=? AND (flow_kind IN ('mb-init','mb-upgrade','mb-fix','mb-audit','project-review','review-fix','interactive') OR flow_kind='mb-distill' AND json_extract(index_json,'$.execution_bundle.flow_id')='mb-distill' OR flow_kind IN ('release','deploy','publish') AND json_extract(index_json,'$.execution_bundle.flow_id')=flow_kind) AND (id=? OR status IN ('created','running','paused','waiting_for_user','blocked')) LIMIT 1", [project.id, input.runId ?? null]);
|
|
224
|
+
const config = initializing ? { ...configured, dashboard: { ...configured.dashboard,
|
|
225
|
+
markdown_path: path.join(projectDashboardDir(context.ddFlowHome, project.id), "project-dashboard.md") } } : configured;
|
|
174
226
|
if (!config.dashboard.auto_refresh) {
|
|
175
227
|
return { ok: true, skipped: true, reason: "dashboard_auto_refresh_disabled" };
|
|
176
228
|
}
|
|
229
|
+
prepareRefreshOutputs(context, project, config, "markdown");
|
|
177
230
|
const result = { ok: true, project_root: project.root };
|
|
178
231
|
if (config.dashboard.project) {
|
|
179
232
|
publishProjectSummary(context, { project });
|
|
@@ -196,6 +249,9 @@ export function autoRefreshDashboards(context, input) {
|
|
|
196
249
|
}
|
|
197
250
|
return result;
|
|
198
251
|
}
|
|
252
|
+
function projectRecoveryGuarded(context, projectId) {
|
|
253
|
+
return Boolean(context.db.get("SELECT 1 FROM run_recovery_guards WHERE project_id = ? AND status IN ('draining', 'sealed', 'resuming') LIMIT 1", [projectId]));
|
|
254
|
+
}
|
|
199
255
|
export function dashboardSummary(context, projectId, projectRoot) {
|
|
200
256
|
const config = readProjectConfig(context, projectId);
|
|
201
257
|
return {
|
|
@@ -221,13 +277,13 @@ export function dashboardData(context, input) {
|
|
|
221
277
|
}
|
|
222
278
|
return { ok: true, dashboard: buildProjectDashboardData(context, project, projectDashboardHtmlPath(context, project.id)) };
|
|
223
279
|
}
|
|
224
|
-
function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdown") {
|
|
280
|
+
async function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdown") {
|
|
225
281
|
const project = requireProjectByRoot(context, resolveProjectRoot(projectRoot));
|
|
226
282
|
const config = readProjectConfig(context, project.id);
|
|
227
283
|
if (config.integrations.cmux.mode === "off") {
|
|
228
284
|
return { ok: true, skipped: true, reason: "cmux_off" };
|
|
229
285
|
}
|
|
230
|
-
const cmux = detectCmux(context);
|
|
286
|
+
const cmux = await detectCmux(context);
|
|
231
287
|
if (!cmux.available) {
|
|
232
288
|
if (config.integrations.cmux.mode === "required") {
|
|
233
289
|
throw new AppError("cmux_unavailable", "cmux is required by project config but is unavailable", 1, { cmux });
|
|
@@ -238,20 +294,20 @@ function openCmuxDashboard(context, projectRoot, dashboardPath, format = "markdo
|
|
|
238
294
|
return { ok: true, opened: false, dry_run: true, command: cmuxOpenCommand(format, dashboardPath) };
|
|
239
295
|
}
|
|
240
296
|
const command = cmuxOpenCommand(format, dashboardPath);
|
|
241
|
-
const result =
|
|
242
|
-
if (result.
|
|
297
|
+
const result = await commandResult(command[0], command.slice(1), { startupMs: SETUP_STARTUP_MS });
|
|
298
|
+
if (result.exit_code !== 0) {
|
|
243
299
|
if (config.integrations.cmux.mode === "required") {
|
|
244
300
|
throw new AppError("cmux_open_failed", "cmux markdown open failed", 1, {
|
|
245
|
-
status: result.
|
|
301
|
+
status: result.exit_code,
|
|
246
302
|
stderr: result.stderr.trim()
|
|
247
303
|
});
|
|
248
304
|
}
|
|
249
|
-
return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.
|
|
305
|
+
return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.exit_code, stderr: result.stderr.trim() };
|
|
250
306
|
}
|
|
251
307
|
return { ok: true, opened: true, command };
|
|
252
308
|
}
|
|
253
|
-
function openDashboardPath(context, dashboardPath, format) {
|
|
254
|
-
const cmux = detectCmux(context);
|
|
309
|
+
async function openDashboardPath(context, dashboardPath, format) {
|
|
310
|
+
const cmux = await detectCmux(context);
|
|
255
311
|
if (!cmux.available) {
|
|
256
312
|
return { ok: true, skipped: true, reason: "cmux_unavailable", cmux };
|
|
257
313
|
}
|
|
@@ -259,9 +315,9 @@ function openDashboardPath(context, dashboardPath, format) {
|
|
|
259
315
|
return { ok: true, opened: false, dry_run: true, command: cmuxOpenCommand(format, dashboardPath) };
|
|
260
316
|
}
|
|
261
317
|
const command = cmuxOpenCommand(format, dashboardPath);
|
|
262
|
-
const result =
|
|
263
|
-
if (result.
|
|
264
|
-
return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.
|
|
318
|
+
const result = await commandResult(command[0], command.slice(1), { startupMs: SETUP_STARTUP_MS });
|
|
319
|
+
if (result.exit_code !== 0) {
|
|
320
|
+
return { ok: true, skipped: true, reason: "cmux_open_failed", status: result.exit_code, stderr: result.stderr.trim() };
|
|
265
321
|
}
|
|
266
322
|
return { ok: true, opened: true, command };
|
|
267
323
|
}
|
|
@@ -270,17 +326,31 @@ function cmuxOpenCommand(format, dashboardPath) {
|
|
|
270
326
|
? ["cmux", "browser", "open", pathToFileUrl(dashboardPath)]
|
|
271
327
|
: ["cmux", "markdown", "open", dashboardPath];
|
|
272
328
|
}
|
|
273
|
-
function detectCmux(context) {
|
|
329
|
+
async function detectCmux(context) {
|
|
274
330
|
if (context.env.DD_FLOW_CMUX_AVAILABLE === "true") {
|
|
275
331
|
return { available: true, source: "env" };
|
|
276
332
|
}
|
|
277
333
|
if (context.env.DD_FLOW_CMUX_AVAILABLE === "false") {
|
|
278
334
|
return { available: false, source: "env", reason: "forced_unavailable" };
|
|
279
335
|
}
|
|
280
|
-
|
|
281
|
-
|
|
336
|
+
let result;
|
|
337
|
+
try {
|
|
338
|
+
result = await commandResult("cmux", ["--version"], { startupMs: SETUP_STARTUP_MS, phase: 'native-version' });
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
return { available: false, source: 'path', reason: error instanceof Error ? error.message : String(error) };
|
|
342
|
+
}
|
|
343
|
+
return result.exit_code === 0
|
|
282
344
|
? { available: true, source: "path", version: result.stdout.trim() }
|
|
283
|
-
: { available: false, source: "path", reason: result.
|
|
345
|
+
: { available: false, source: "path", reason: result.stderr.trim() || "cmux not found" };
|
|
346
|
+
}
|
|
347
|
+
export function prepareDashboardOptions(input) {
|
|
348
|
+
if (input.format !== undefined)
|
|
349
|
+
parseDashboardFormat(input.format);
|
|
350
|
+
if (input.viewer !== undefined && input.viewer !== "cmux")
|
|
351
|
+
throw new AppError("validation", "--viewer must be cmux", 2);
|
|
352
|
+
if (input.open !== undefined && !["auto", "true", "false"].includes(input.open))
|
|
353
|
+
throw new AppError("validation", "--open must be auto, true, or false", 2);
|
|
284
354
|
}
|
|
285
355
|
function parseDashboardFormat(value, defaultFormat = "markdown") {
|
|
286
356
|
const format = value ?? defaultFormat;
|
|
@@ -294,15 +364,18 @@ function renderProjectDashboardHtml(context, project, output) {
|
|
|
294
364
|
? path.resolve(path.isAbsolute(output) ? output : path.join(project.root, output))
|
|
295
365
|
: projectDashboardHtmlPath(context, project.id);
|
|
296
366
|
const jsonPath = projectDashboardJsonPath(context, project.id);
|
|
367
|
+
prepareOutputFile(htmlPath);
|
|
368
|
+
prepareOutputFile(jsonPath);
|
|
297
369
|
const data = buildProjectDashboardData(context, project, htmlPath);
|
|
298
370
|
const html = renderDashboardHtmlPage(data);
|
|
299
|
-
writeJsonFile(jsonPath, data);
|
|
300
|
-
writeTextFile(htmlPath, html);
|
|
301
371
|
const protocolCards = Array.isArray(data.protocol_cards) ? data.protocol_cards : [];
|
|
302
|
-
const
|
|
372
|
+
const preparedPages = protocolCards
|
|
303
373
|
.filter((card) => card.generate_page !== false)
|
|
304
374
|
.slice(0, 24)
|
|
305
|
-
.map((card) =>
|
|
375
|
+
.map((card) => prepareProtocolDashboardHtml(context, project, String(card.id)));
|
|
376
|
+
writeJsonFile(jsonPath, data);
|
|
377
|
+
writeTextFile(htmlPath, html);
|
|
378
|
+
const protocolPages = preparedPages.map(writeProtocolDashboardHtml)
|
|
306
379
|
.map((result) => ({
|
|
307
380
|
id: String(result.protocol_id),
|
|
308
381
|
path: result.dashboard.path,
|
|
@@ -321,12 +394,23 @@ function renderProjectDashboardHtml(context, project, output) {
|
|
|
321
394
|
};
|
|
322
395
|
}
|
|
323
396
|
function renderProtocolDashboardHtml(context, project, protocolId, output) {
|
|
397
|
+
return writeProtocolDashboardHtml(prepareProtocolDashboardHtml(context, project, protocolId, output));
|
|
398
|
+
}
|
|
399
|
+
function prepareProtocolDashboardHtml(context, project, protocolId, output) {
|
|
400
|
+
if (projectRecoveryGuarded(context, project.id))
|
|
401
|
+
throw new AppError("run_recovery_guarded", "Project dashboard is frozen while its RUN is retained for recovery", 1);
|
|
324
402
|
const htmlPath = output
|
|
325
403
|
? path.resolve(path.isAbsolute(output) ? output : path.join(project.root, output))
|
|
326
404
|
: protocolDashboardHtmlPath(context, project.id, protocolId);
|
|
327
405
|
const jsonPath = protocolDashboardJsonPath(context, project.id, protocolId);
|
|
406
|
+
prepareOutputFile(htmlPath);
|
|
407
|
+
prepareOutputFile(jsonPath);
|
|
328
408
|
const data = buildProtocolDashboardData(context, project, protocolId, htmlPath);
|
|
329
409
|
const html = renderDashboardHtmlPage(data);
|
|
410
|
+
return { project, protocolId, htmlPath, jsonPath, data, html };
|
|
411
|
+
}
|
|
412
|
+
function writeProtocolDashboardHtml(prepared) {
|
|
413
|
+
const { project, protocolId, htmlPath, jsonPath, data, html } = prepared;
|
|
330
414
|
writeJsonFile(jsonPath, data);
|
|
331
415
|
writeTextFile(htmlPath, html);
|
|
332
416
|
return {
|
|
@@ -344,6 +428,8 @@ function renderProtocolDashboardHtml(context, project, protocolId, output) {
|
|
|
344
428
|
function renderGlobalDashboardHtml(context, output) {
|
|
345
429
|
const htmlPath = output ? path.resolve(output) : globalDashboardHtmlPath(context);
|
|
346
430
|
const jsonPath = globalDashboardJsonPath(context);
|
|
431
|
+
prepareOutputFile(htmlPath);
|
|
432
|
+
prepareOutputFile(jsonPath);
|
|
347
433
|
const data = buildGlobalDashboardData(context, htmlPath);
|
|
348
434
|
const html = renderDashboardHtmlPage(data);
|
|
349
435
|
writeJsonFile(jsonPath, data);
|
|
@@ -888,12 +974,12 @@ function protocolsForProject(context, projectId) {
|
|
|
888
974
|
FROM protocols WHERE project_id = ? ORDER BY updated_at DESC`, [projectId]);
|
|
889
975
|
}
|
|
890
976
|
function planSummaryForProtocol(context, projectId, protocolId) {
|
|
891
|
-
const protocol = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocolId]);
|
|
977
|
+
const protocol = context.db.get("SELECT plan_path, project_root FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocolId]);
|
|
892
978
|
if (!protocol) {
|
|
893
979
|
return { plan_id: "none", total: 0, done: 0, blocked: 0 };
|
|
894
980
|
}
|
|
895
981
|
try {
|
|
896
|
-
const summary = planSummary(context, { projectId, protocolId, planPath: protocol.plan_path }, { bind: false });
|
|
982
|
+
const summary = planSummary(context, { projectId, protocolId, planPath: resolveProtocolPlanPath(protocol.project_root, protocolId, protocol.plan_path) }, { bind: false });
|
|
897
983
|
return { plan_id: summary.plan_id, total: summary.total, done: summary.done, blocked: summary.blocked };
|
|
898
984
|
}
|
|
899
985
|
catch {
|
|
@@ -903,13 +989,13 @@ function planSummaryForProtocol(context, projectId, protocolId) {
|
|
|
903
989
|
function activePlanItems(context, projectId, protocols) {
|
|
904
990
|
const items = [];
|
|
905
991
|
for (const protocol of protocols) {
|
|
906
|
-
const record = context.db.get("SELECT plan_path FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocol.id]);
|
|
992
|
+
const record = context.db.get("SELECT plan_path, project_root FROM protocols WHERE project_id = ? AND id = ?", [projectId, protocol.id]);
|
|
907
993
|
if (!record) {
|
|
908
994
|
continue;
|
|
909
995
|
}
|
|
910
996
|
let plan;
|
|
911
997
|
try {
|
|
912
|
-
plan = planWithProgress(context, { projectId, protocolId: protocol.id, planPath: record.plan_path }, { bind: false }).plan;
|
|
998
|
+
plan = planWithProgress(context, { projectId, protocolId: protocol.id, planPath: resolveProtocolPlanPath(record.project_root, protocol.id, record.plan_path) }, { bind: false }).plan;
|
|
913
999
|
}
|
|
914
1000
|
catch {
|
|
915
1001
|
continue;
|
|
@@ -1222,6 +1308,7 @@ function normalizeFlowKind(flowKind) {
|
|
|
1222
1308
|
"mb-upgrade",
|
|
1223
1309
|
"mb-audit",
|
|
1224
1310
|
"mb-fix",
|
|
1311
|
+
"review-fix",
|
|
1225
1312
|
"mb-distill",
|
|
1226
1313
|
"mb-upgrade-review",
|
|
1227
1314
|
"mb-sdlc-review",
|