@deksden-com/dd-flow-cli 0.9.0-beta.16 → 0.9.0-beta.160
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 +959 -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 +230 -106
- 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,55 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
import { AppError } from "../shared/errors.js";
|
|
5
|
+
import { managedDaemonExecutionAbsent } from "./managed-daemon-binding.js";
|
|
6
|
+
export const retryCorrectionFile = "retry-correction.json";
|
|
7
|
+
export const retryReceiptFile = "retry-receipt.json";
|
|
8
|
+
const hash = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex");
|
|
9
|
+
export function prepareRetryCorrection(input, work, runHome) {
|
|
10
|
+
if (!input || typeof input.episode_id !== "string" || !input.episode_id.trim() || typeof input.correction !== "string" || !input.correction.trim()
|
|
11
|
+
|| typeof input.decision_ref !== "string" || !path.isAbsolute(input.decision_ref) || input.failed_result_sha256 !== hash(work.result ?? ""))
|
|
12
|
+
throw new AppError("work_retry_correction_invalid", "Retry correction does not identify the retained failed Work", 1);
|
|
13
|
+
const home = fs.realpathSync(runHome), decision = fs.realpathSync(input.decision_ref);
|
|
14
|
+
if (!decision.startsWith(`${home}${path.sep}`) || !fs.statSync(decision).isFile())
|
|
15
|
+
throw new AppError("work_retry_correction_invalid", "Retry decision must be a retained file inside this RUN", 1);
|
|
16
|
+
const bytes = fs.readFileSync(decision), accepted = JSON.parse(bytes.toString("utf8"));
|
|
17
|
+
if (accepted.schema_id !== "work-failure-decision@1" || accepted.action !== "retry" || accepted.episode_id !== input.episode_id || accepted.correction !== input.correction)
|
|
18
|
+
throw new AppError("work_retry_correction_invalid", "Retry correction differs from the retained coordinator decision", 1);
|
|
19
|
+
return { ...input, decision_ref: decision, decision_sha256: hash(bytes), work_id: work.work_id, project_id: work.project_id, run_id: work.run_id };
|
|
20
|
+
}
|
|
21
|
+
/** Snapshot the old launch before its current-row slot is reused; no process I/O in SQL. */
|
|
22
|
+
export function prepareExternalRetry(context, work) {
|
|
23
|
+
if (!context.db.get("SELECT 1 FROM sqlite_master WHERE type='table' AND name='work_launches'"))
|
|
24
|
+
return null;
|
|
25
|
+
const launch = context.db.get("SELECT * FROM work_launches WHERE work_id=?", [work.work_id]);
|
|
26
|
+
if (!launch)
|
|
27
|
+
return null;
|
|
28
|
+
if (!["start_requested", "completed", "failed", "cancelled"].includes(launch.status)
|
|
29
|
+
|| !managedDaemonExecutionAbsent(context, { stateDir: launch.state_dir, projectId: work.project_id, runId: work.run_id }))
|
|
30
|
+
throw new AppError("work_retry_external_unsettled", "Previous external Work launch still has unknown or live execution; reconcile it before retry", 1, { work_id: work.work_id, operation_id: launch.operation_id, state_dir: launch.state_dir });
|
|
31
|
+
return launch;
|
|
32
|
+
}
|
|
33
|
+
export function renderRetryCorrection(context, work, runHome) {
|
|
34
|
+
const directory = path.join(runHome, "works", work.work_id), file = path.join(directory, retryCorrectionFile);
|
|
35
|
+
if (!fs.existsSync(file))
|
|
36
|
+
return "";
|
|
37
|
+
const value = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
38
|
+
const receipt = JSON.parse(fs.readFileSync(path.join(directory, retryReceiptFile), "utf8"));
|
|
39
|
+
const current = context.db.get("SELECT current_start_invocation_id FROM works WHERE work_id=?", [work.work_id]);
|
|
40
|
+
const realHome = fs.realpathSync(runHome), realDecision = fs.realpathSync(value.decision_ref);
|
|
41
|
+
if (value.work_id !== work.work_id || value.project_id !== work.project_id || value.run_id !== work.run_id
|
|
42
|
+
|| receipt.work_id !== work.work_id || receipt.episode_id !== value.episode_id || receipt.current_start_invocation_id !== current?.current_start_invocation_id
|
|
43
|
+
|| !realDecision.startsWith(`${realHome}${path.sep}`))
|
|
44
|
+
throw new AppError("work_retry_correction_invalid", "Retained retry correction no longer matches this Work attempt", 1);
|
|
45
|
+
const decisionBytes = fs.readFileSync(realDecision);
|
|
46
|
+
if (value.decision_sha256 !== hash(decisionBytes))
|
|
47
|
+
throw new AppError("work_retry_correction_invalid", "Retained retry decision changed", 1);
|
|
48
|
+
const accepted = JSON.parse(decisionBytes.toString("utf8"));
|
|
49
|
+
if (accepted.schema_id !== "work-failure-decision@1" || accepted.action !== "retry"
|
|
50
|
+
|| accepted.episode_id !== value.episode_id || accepted.correction !== value.correction)
|
|
51
|
+
throw new AppError("work_retry_correction_invalid", "Retained retry correction no longer matches this Work attempt", 1);
|
|
52
|
+
return ["<accepted_work_retry_correction>", `- failed-result sha256: ${value.failed_result_sha256}`, `- retained decision: ${value.decision_ref}`,
|
|
53
|
+
`- episode: ${value.episode_id}`, value.correction,
|
|
54
|
+
"This is the coordinator's correction for this fresh attempt, not a new user requirement or permission to widen accepted scope. Read the retained decision. Apply its interpretation to the historical stop conditions; preserve accepted requirements, non-goals and previous receipts. Do not repeat an accepted predecessor Work.", "</accepted_work_retry_correction>", ""].join("\n");
|
|
55
|
+
}
|
|
@@ -2,39 +2,66 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { AppError } from "../shared/errors.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { retainedBrowserEnvironment } from "./check-environment.js";
|
|
6
|
+
import { assertRunMutationAllowed } from "./run-recovery.js";
|
|
7
|
+
import { codeExecutionEnvironment, reconcileWorkspaceOwnership, runCheck, workspaceOperationId } from "./code-checks.js";
|
|
8
|
+
import { confirmManagedProcess, finishManagedProcess, renewManagedProcess, managedOwnerIsAlive, managedProcessStatus, processTreeIsAlive, registerManagedProcess } from "./managed-processes.js";
|
|
7
9
|
/** CODE and MERGE prepare their own checkout through the same managed executor.
|
|
8
10
|
* Bootstrap is a project operation, not an alias classified by the engine as a test. */
|
|
9
11
|
export async function runWorkspaceBootstrap(context, input) {
|
|
10
|
-
|
|
12
|
+
reconcileWorkspaceOwnership(context, input.workspaceRoot);
|
|
13
|
+
const generation = assertRunMutationAllowed(context, input.projectId, input.runId);
|
|
14
|
+
const operationId = workspaceOperationId(input.workspaceRoot);
|
|
15
|
+
const identity = crypto.createHash("sha256").update(JSON.stringify([input.projectId, input.runId, generation, path.resolve(input.workspaceRoot), input.command])).digest("hex");
|
|
11
16
|
const pending = managedProcessStatus(context).find(item => item.operation_id === operationId && ["starting", "running", "stopping"].includes(item.state));
|
|
12
17
|
if (pending) {
|
|
18
|
+
if (pending.kind !== "workspace-bootstrap")
|
|
19
|
+
throw new AppError("bootstrap_in_progress", "A check currently owns this workspace; wait for it before bootstrapping", 2, { process_id: pending.id, stdout_path: pending.stdout_path, stderr_path: pending.stderr_path });
|
|
13
20
|
if (processTreeIsAlive(pending) || (pending.state === "starting" && managedOwnerIsAlive(pending) !== false)) {
|
|
14
21
|
throw new AppError("bootstrap_in_progress", "Workspace preparation is still running; inspect its logs and wait for the existing process, do not launch another copy", 2, { process_id: pending.id, stdout_path: pending.stdout_path, stderr_path: pending.stderr_path });
|
|
15
22
|
}
|
|
16
|
-
|
|
17
|
-
let completion = null;
|
|
23
|
+
let pendingIdentity = null;
|
|
18
24
|
try {
|
|
19
|
-
|
|
25
|
+
const metadata = JSON.parse(pending.metadata_json);
|
|
26
|
+
pendingIdentity = typeof metadata.bootstrap_identity === "string" ? metadata.bootstrap_identity : null;
|
|
27
|
+
}
|
|
28
|
+
catch { /* Legacy records have no usable identity. */ }
|
|
29
|
+
if (pendingIdentity !== identity) {
|
|
30
|
+
finishManagedProcess(context, { id: pending.id, leaseToken: pending.lease_token, state: "failed", reason: "bootstrap_identity_superseded" });
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const completionPath = path.join(path.dirname(pending.stdout_path), "completion.json");
|
|
34
|
+
let completion = null;
|
|
35
|
+
try {
|
|
36
|
+
completion = JSON.parse(fs.readFileSync(completionPath, "utf8"));
|
|
37
|
+
}
|
|
38
|
+
catch { /* Interrupted shell has no terminal marker. */ }
|
|
39
|
+
const exitCode = typeof completion?.exit_code === "number" ? completion.exit_code : null;
|
|
40
|
+
const error = exitCode === null ? "bootstrap ended without a completion marker; inspect retained logs before retrying" : null;
|
|
41
|
+
finishManagedProcess(context, { id: pending.id, leaseToken: pending.lease_token, state: exitCode === 0 ? "stopped" : "failed", reason: error ?? "bootstrap_completion_reconciled" });
|
|
42
|
+
assertRunMutationAllowed(context, input.projectId, input.runId, generation);
|
|
43
|
+
return result(pending.id, pending.stdout_path, pending.stderr_path, completionPath, exitCode, error);
|
|
20
44
|
}
|
|
21
|
-
catch { /* Interrupted shell has no terminal marker. */ }
|
|
22
|
-
const exitCode = typeof completion?.exit_code === "number" ? completion.exit_code : null;
|
|
23
|
-
const error = exitCode === null ? "bootstrap ended without a completion marker; inspect retained logs before retrying" : null;
|
|
24
|
-
finishManagedProcess(context, { id: pending.id, leaseToken: pending.lease_token, state: exitCode === 0 ? "stopped" : "failed", reason: error ?? "bootstrap_completion_reconciled" });
|
|
25
|
-
return result(pending.id, pending.stdout_path, pending.stderr_path, completionPath, exitCode, error);
|
|
26
45
|
}
|
|
27
46
|
const directory = path.join(input.runHome, input.artifactDir, `bootstrap-${crypto.randomUUID()}`);
|
|
28
47
|
fs.mkdirSync(directory, { recursive: true });
|
|
29
48
|
const stdoutPath = path.join(directory, "stdout.log"), stderrPath = path.join(directory, "stderr.log"), completionPath = path.join(directory, "completion.json");
|
|
30
|
-
const managed = registerManagedProcess(context, { kind: "workspace-bootstrap", ownerId: operationId
|
|
49
|
+
const managed = registerManagedProcess(context, { kind: "workspace-bootstrap", ownerId: `${operationId}:${identity}`, ownerPid: process.pid, operationId, uniqueActiveOperation: true, projectId: input.projectId, runId: input.runId, stdoutPath, stderrPath, metadata: { command: input.command, workspace_root: input.workspaceRoot, bootstrap_identity: identity } });
|
|
31
50
|
const stdout = fs.openSync(stdoutPath, "a"), stderr = fs.openSync(stderrPath, "a");
|
|
32
51
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
try {
|
|
53
|
+
input.progress?.(`workspace bootstrap preparing: ${input.command}; logs: ${directory}`);
|
|
54
|
+
assertRunMutationAllowed(context, input.projectId, input.runId, generation);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
finishManagedProcess(context, { id: managed.id, leaseToken: managed.lease_token, state: "failed", reason: "dispatch_fenced_before_spawn" });
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
const completed = await runCheck(input.command, input.workspaceRoot, { ...codeExecutionEnvironment(input.workspaceRoot, retainedBrowserEnvironment(context.env)), DD_FLOW_CHECK_COMPLETION_FILE: completionPath }, stdout, stderr, elapsed => input.progress?.(`workspace bootstrap still running (${elapsed}s); logs: ${directory}; next report in 15s`), pid => confirmManagedProcess(context, { id: managed.id, leaseToken: managed.lease_token, pid, processGroupId: process.platform === "win32" ? null : pid }), attemptMs => renewManagedProcess({ ...context, resourceDatabaseMode: "prepared_existing", databaseDeadlineAt: Date.now() + attemptMs }, { id: managed.id, leaseToken: managed.lease_token }));
|
|
35
61
|
const current = managedProcessStatus(context).find(item => item.id === managed.id);
|
|
36
62
|
if (processTreeIsAlive(current))
|
|
37
63
|
throw new AppError("bootstrap_tree_not_settled", "Bootstrap shell exited but still owns live processes; resources were retained for inspection", 2, { process_id: managed.id, stdout_path: stdoutPath, stderr_path: stderrPath });
|
|
64
|
+
assertRunMutationAllowed(context, input.projectId, input.runId, generation);
|
|
38
65
|
finishManagedProcess(context, { id: managed.id, leaseToken: managed.lease_token, state: completed.exitCode === 0 && !completed.error ? "stopped" : "failed", reason: completed.error });
|
|
39
66
|
return result(managed.id, stdoutPath, stderrPath, completionPath, completed.exitCode, completed.error);
|
|
40
67
|
}
|
|
@@ -45,6 +72,17 @@ export async function runWorkspaceBootstrap(context, input) {
|
|
|
45
72
|
}
|
|
46
73
|
function result(id, stdout, stderr, completion, exitCode, error) {
|
|
47
74
|
// Full logs remain on disk; keep the returned prompt bounded.
|
|
48
|
-
const excerpt = (file) =>
|
|
75
|
+
const excerpt = (file) => {
|
|
76
|
+
if (!fs.existsSync(file))
|
|
77
|
+
return "";
|
|
78
|
+
const fd = fs.openSync(file, "r");
|
|
79
|
+
try {
|
|
80
|
+
const size = fs.fstatSync(fd).size, bytes = Buffer.alloc(Math.min(size, 64_000));
|
|
81
|
+
return bytes.subarray(0, fs.readSync(fd, bytes, 0, bytes.length, Math.max(0, size - bytes.length))).toString("utf8");
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
fs.closeSync(fd);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
49
87
|
return { exit_code: exitCode, stdout: excerpt(stdout), stderr: excerpt(stderr), error, process_id: id, stdout_path: stdout, stderr_path: stderr, completion_path: completion };
|
|
50
88
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
|
+
import { AppError } from "../shared/errors.js";
|
|
6
|
+
import { agyWorkspaceHooks } from "../harness-runtime/lib/agy-hooks.mjs";
|
|
7
|
+
/** Local environment/credential files are never an exported reviewer or EVAL input. */
|
|
8
|
+
export function localEnvironmentAllowed(source) {
|
|
9
|
+
const name = path.basename(source).normalize("NFC").toLowerCase();
|
|
10
|
+
return name === ".env.example" || (name !== ".env" && !name.startsWith(".env."));
|
|
11
|
+
}
|
|
12
|
+
/** A damaged/inaccessible repository is not an intentional gitless workspace. */
|
|
13
|
+
export function isGitlessWorkspace(root, result) {
|
|
14
|
+
// git check-ignore can exit 128 before consuming --stdin, yielding EPIPE
|
|
15
|
+
// alongside the authoritative "not a git repository" diagnostic.
|
|
16
|
+
if ((result.error && result.error.code !== "EPIPE") || result.status !== 128 || !/not a git repository|outside a repository/i.test(result.stderr ?? ""))
|
|
17
|
+
return false;
|
|
18
|
+
for (let directory = path.resolve(root);; directory = path.dirname(directory)) {
|
|
19
|
+
try {
|
|
20
|
+
fs.lstatSync(path.join(directory, ".git"));
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error.code !== "ENOENT")
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (path.dirname(directory) === directory)
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function workspaceGitFiles(root, args) {
|
|
32
|
+
const result = spawnSync("git", ["ls-files", "-z", ...args], { cwd: root, env: { ...process.env, LC_ALL: "C" }, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
|
|
33
|
+
if (isGitlessWorkspace(root, result))
|
|
34
|
+
return null;
|
|
35
|
+
if (result.status !== 0 || result.error)
|
|
36
|
+
throw new AppError("workspace_status_failed", "Could not determine workspace file inventory", 1, { workspace_root: root, stderr: result.stderr || null, cause: result.error?.message ?? null });
|
|
37
|
+
return [...new Set(result.stdout.split("\0").filter(Boolean))];
|
|
38
|
+
}
|
|
39
|
+
/** The exact qualified AGY file is infrastructure only while untracked.
|
|
40
|
+
* Never write a shared worktree exclude: that would hide a sibling's mixed
|
|
41
|
+
* user hooks. Snapshots still retain this qualification input. */
|
|
42
|
+
export function ownedWorkspaceHookPath(root, trackedFiles) {
|
|
43
|
+
const relative = ".agents/hooks.json", file = path.join(root, relative);
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.lstatSync(path.dirname(file)).isDirectory() || !fs.lstatSync(file).isFile() || !isDeepStrictEqual(JSON.parse(fs.readFileSync(file, "utf8")), agyWorkspaceHooks()))
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code === "ENOENT" || error instanceof SyntaxError)
|
|
50
|
+
return null;
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
const tracked = trackedFiles ?? workspaceGitFiles(root, ["--cached", "--", relative]) ?? [];
|
|
54
|
+
return tracked.includes(relative) ? null : relative;
|
|
55
|
+
}
|
|
56
|
+
/** New feature worktrees do not inherit untracked qualified hooks via Git. */
|
|
57
|
+
export function propagateOwnedWorkspaceHooks(sourceRoot, targetRoot) {
|
|
58
|
+
const relative = ownedWorkspaceHookPath(sourceRoot);
|
|
59
|
+
if (!relative || path.resolve(sourceRoot) === path.resolve(targetRoot))
|
|
60
|
+
return null;
|
|
61
|
+
const target = path.join(targetRoot, relative), directory = path.dirname(target);
|
|
62
|
+
if (fs.lstatSync(target, { throwIfNoEntry: false }))
|
|
63
|
+
return null; // User/tracked target wins; daemon checks qualification.
|
|
64
|
+
if (workspaceGitFiles(targetRoot, ["--cached", "--", relative])?.includes(relative))
|
|
65
|
+
return null;
|
|
66
|
+
if (fs.lstatSync(directory, { throwIfNoEntry: false }) && !fs.lstatSync(directory).isDirectory())
|
|
67
|
+
throw new AppError("workspace_hooks_unqualified", "AGY hook directory is not an owned directory", 1, { path: directory });
|
|
68
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
69
|
+
fs.copyFileSync(path.join(sourceRoot, relative), target, fs.constants.COPYFILE_EXCL);
|
|
70
|
+
fs.chmodSync(target, 0o600);
|
|
71
|
+
return target;
|
|
72
|
+
}
|
|
73
|
+
/** Ignore only provider-owned service files. Tracked/explicit inputs win;
|
|
74
|
+
* other ignored and untracked product/task files remain snapshot payload. */
|
|
75
|
+
export function projectServicePathFilter(root, explicitInputs = [], trackedFiles) {
|
|
76
|
+
const retained = new Set([...(trackedFiles ?? workspaceGitFiles(root, ["--cached"]) ?? []), ...explicitInputs].map(file => path.resolve(root, file)));
|
|
77
|
+
const branches = new Set();
|
|
78
|
+
for (const file of retained)
|
|
79
|
+
for (let directory = path.dirname(file); directory !== path.dirname(directory); directory = path.dirname(directory))
|
|
80
|
+
branches.add(directory);
|
|
81
|
+
return file => {
|
|
82
|
+
const absolute = path.resolve(file), relative = path.relative(root, absolute);
|
|
83
|
+
return !relative.split(path.sep).includes(".zcode") || retained.has(absolute) || branches.has(absolute);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -3,12 +3,15 @@ import path from "node:path";
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { flowContractForState } from "../domain/flow-contract.js";
|
|
5
5
|
import { requireStage } from "../domain/validation.js";
|
|
6
|
-
import { AppError } from "../shared/errors.js";
|
|
7
|
-
import { projectCheckoutRoot, resolveProjectRoot } from "../storage/paths.js";
|
|
6
|
+
import { AppError, processEvidence, redactDiagnostic } from "../shared/errors.js";
|
|
7
|
+
import { canonicalPath, projectCheckoutRoot, resolveProjectRoot } from "../storage/paths.js";
|
|
8
8
|
import { appendAudit } from "./audit.js";
|
|
9
9
|
import { persistProtocolState, readProtocolRuntimeState, requireProtocol } from "./protocols.js";
|
|
10
10
|
import { requireProjectByRoot } from "./projects.js";
|
|
11
11
|
import { ensureManagedWorktrunk, inspectManagedWorktrunk } from "./tooling.js";
|
|
12
|
+
import { propagateOwnedWorkspaceHooks } from "./workspace-files.js";
|
|
13
|
+
import { commandResult } from '../harness-runtime/lib/process-json.mjs';
|
|
14
|
+
import { SETUP_STARTUP_MS } from '../harness-runtime/lib/setup-progress.mjs';
|
|
12
15
|
export function planWorktree(context, input) {
|
|
13
16
|
const protocol = scopedProtocol(context, input.projectRoot, input.protocolId);
|
|
14
17
|
const state = readProtocolRuntimeState(context, protocol).state;
|
|
@@ -28,7 +31,7 @@ export function planWorktree(context, input) {
|
|
|
28
31
|
worktrunk: inspectManagedWorktrunk(context)
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
|
-
export function
|
|
34
|
+
export function prepareWorktreeCreate(context, input) {
|
|
32
35
|
const protocol = scopedProtocol(context, input.projectRoot, input.protocolId);
|
|
33
36
|
const existing = activeWorktreeRecord(context, protocol.project_id, protocol.id);
|
|
34
37
|
if (existing) {
|
|
@@ -37,18 +40,60 @@ export function createWorktreeRecord(context, input) {
|
|
|
37
40
|
worktree_path: existing.worktree_path
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
return prepareManagedWorktree({ ...input, projectRoot: protocol.project_root });
|
|
44
|
+
}
|
|
45
|
+
export async function createWorktreeRecord(context, input, prepared = prepareWorktreeCreate(context, input)) {
|
|
46
|
+
const protocol = scopedProtocol(context, input.projectRoot, input.protocolId);
|
|
47
|
+
if (activeWorktreeRecord(context, protocol.project_id, protocol.id))
|
|
48
|
+
throw new AppError("worktree_already_exists", "Protocol already has an active worktree record", 1);
|
|
49
|
+
const created = await createManagedWorktree(context, prepared, prepared);
|
|
50
|
+
recordManagedWorktree(context, { protocolId: protocol.id, projectRoot: protocol.project_root, branch: prepared.branch, base: prepared.base, created });
|
|
42
51
|
return { ok: true, worktree: activeWorktreeRecord(context, protocol.project_id, protocol.id) };
|
|
43
52
|
}
|
|
44
|
-
|
|
45
|
-
export function createManagedWorktree(context, input) {
|
|
53
|
+
export function prepareManagedWorktree(input) {
|
|
46
54
|
const projectRoot = resolveProjectRoot(input.projectRoot);
|
|
47
|
-
const
|
|
55
|
+
const invalid = (message) => { throw new AppError("validation", message, 2, { phase: "prepare", effect: "no_effect", recoverable: true }); };
|
|
56
|
+
for (const key of ["branch", "base", "path"])
|
|
57
|
+
if (typeof input[key] !== "string" || !input[key].trim() || input[key].includes("\0"))
|
|
58
|
+
invalid(`--${key} must be a non-empty value without NUL`);
|
|
59
|
+
const git = (args) => {
|
|
60
|
+
const result = spawnSync("git", ["-C", projectRoot, ...args], { encoding: "utf8",
|
|
61
|
+
env: { ...Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.startsWith("GIT_"))), GIT_OPTIONAL_LOCKS: "0" } });
|
|
62
|
+
if (result.error)
|
|
63
|
+
throw result.error;
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
const branch = git(["check-ref-format", "--branch", input.branch]);
|
|
67
|
+
if (input.branch.startsWith("-") || branch.status !== 0 || branch.stdout.trim() !== input.branch)
|
|
68
|
+
invalid("--branch must be a literal valid Git branch name");
|
|
69
|
+
const base = git(["rev-parse", "--verify", "--end-of-options", `${input.base}^{commit}`]);
|
|
70
|
+
if (base.status !== 0)
|
|
71
|
+
invalid("--base must resolve to an existing Git commit");
|
|
72
|
+
if (git(["show-ref", "--verify", "--quiet", `refs/heads/${input.branch}`]).status === 0)
|
|
73
|
+
invalid("--branch already exists; choose a new feature branch");
|
|
74
|
+
const destination = canonicalPath(input.path, false);
|
|
75
|
+
if (isTrackedProjectPath(canonicalPath(projectRoot), destination))
|
|
76
|
+
invalid("--path must be outside the project checkout");
|
|
77
|
+
if (fs.existsSync(destination) && (!fs.statSync(destination).isDirectory() || fs.readdirSync(destination).length))
|
|
78
|
+
invalid("--path must be an absent or empty directory");
|
|
79
|
+
let parent = path.dirname(destination);
|
|
80
|
+
while (!fs.existsSync(parent) && path.dirname(parent) !== parent)
|
|
81
|
+
parent = path.dirname(parent);
|
|
82
|
+
if (!fs.statSync(parent).isDirectory())
|
|
83
|
+
invalid("--path has a parent that is not a directory");
|
|
84
|
+
fs.accessSync(parent, fs.constants.W_OK | fs.constants.X_OK);
|
|
85
|
+
return { projectRoot, branch: input.branch, base: base.stdout.trim(), path: destination };
|
|
86
|
+
}
|
|
87
|
+
/** Creates the checkout before a PRT exists. PROTOCOLIZE materializes the PRT only inside this checkout. */
|
|
88
|
+
export async function createManagedWorktree(context, input, prepared = prepareManagedWorktree(input)) {
|
|
89
|
+
const { projectRoot } = prepared;
|
|
90
|
+
const worktrunk = await ensureManagedWorktrunk(context);
|
|
48
91
|
// Worktrunk owns creation; the CLI supplies its project-scoped service path
|
|
49
92
|
// as a one-shot config override rather than relying on a developer's user config.
|
|
50
|
-
const command = [worktrunk.bin, "-C", projectRoot, "--config-set", `worktree-path = ${JSON.stringify(
|
|
51
|
-
|
|
93
|
+
const command = [worktrunk.bin, "-C", projectRoot, "--config-set", `worktree-path = ${JSON.stringify(prepared.path)}`, "switch", "--create", prepared.branch, "--base", prepared.base, "--no-cd", "--format=json", "-y"];
|
|
94
|
+
// commandResult overlays process.env, so explicitly clear inherited Git
|
|
95
|
+
// redirection instead of merely omitting it from the override object.
|
|
96
|
+
const result = await runExternal(command, Object.fromEntries(Object.keys(process.env).filter(key => key.startsWith("GIT_")).map(key => [key, undefined])));
|
|
52
97
|
if (result.exit_code !== 0)
|
|
53
98
|
throw new AppError("worktrunk_command_unavailable", "Worktrunk switch failed", 1, { command: sanitizeCommand(command), result });
|
|
54
99
|
const response = parseWorktrunkResponse(result.stdout, command);
|
|
@@ -76,65 +121,73 @@ export function recordManagedWorktree(context, input) {
|
|
|
76
121
|
appendAudit(context, { protocolId: protocol.id, projectId: protocol.project_id, eventType: "worktree.created", payload: { protocol_id: protocol.id, feature_branch: input.branch, base: input.base, path: input.created.worktreePath } });
|
|
77
122
|
}
|
|
78
123
|
/** Bootstrap a just-created RUN workspace before a durable PRT exists. */
|
|
79
|
-
export function
|
|
80
|
-
const projectRoot = resolveProjectRoot(
|
|
81
|
-
const worktreePath = path.resolve(input.worktreePath);
|
|
124
|
+
export function prepareManagedWorktreeBootstrapSources(root) {
|
|
125
|
+
const projectRoot = resolveProjectRoot(root);
|
|
82
126
|
const includeFile = path.join(projectRoot, ".worktreeinclude");
|
|
83
127
|
const configFile = path.join(projectRoot, ".config", "wt.toml");
|
|
84
128
|
if (!fs.existsSync(includeFile) || !fs.existsSync(configFile)) {
|
|
85
129
|
throw new AppError("bootstrap_unavailable", "Project-owned Worktrunk bootstrap files are required", 1, { include_file: includeFile, config_file: configFile });
|
|
86
130
|
}
|
|
87
|
-
const
|
|
131
|
+
for (const file of [includeFile, configFile]) {
|
|
132
|
+
if (!fs.statSync(file).isFile())
|
|
133
|
+
throw new AppError("bootstrap_unavailable", "Project-owned bootstrap inputs must be regular files", 1, { file });
|
|
134
|
+
fs.accessSync(file, fs.constants.R_OK);
|
|
135
|
+
}
|
|
136
|
+
return projectRoot;
|
|
137
|
+
}
|
|
138
|
+
export function prepareManagedWorktreeBootstrap(input) {
|
|
139
|
+
const projectRoot = prepareManagedWorktreeBootstrapSources(input.projectRoot);
|
|
140
|
+
const worktreePath = path.resolve(input.worktreePath);
|
|
141
|
+
if (!fs.statSync(worktreePath).isDirectory())
|
|
142
|
+
throw new AppError("bootstrap_unavailable", "Bootstrap worktree must be a directory", 1, { worktree_path: worktreePath });
|
|
143
|
+
return { projectRoot, worktreePath };
|
|
144
|
+
}
|
|
145
|
+
export async function bootstrapManagedWorktree(context, input, prepared = prepareManagedWorktreeBootstrap(input)) {
|
|
146
|
+
const { worktreePath } = prepared;
|
|
147
|
+
const worktrunk = await ensureManagedWorktrunk(context);
|
|
88
148
|
const commands = [
|
|
89
149
|
[worktrunk.bin, "-C", worktreePath, "step", "copy-ignored", "--require-include"],
|
|
90
150
|
[worktrunk.bin, "-C", worktreePath, "hook", "pre-start", "--yes"]
|
|
91
151
|
];
|
|
92
152
|
const results = [];
|
|
93
153
|
for (const command of commands) {
|
|
94
|
-
const result = runExternal(command);
|
|
154
|
+
const result = await runExternal(command);
|
|
95
155
|
results.push({ command: sanitizeCommand(command), ...result });
|
|
96
156
|
if (result.exit_code !== 0) {
|
|
97
157
|
throw new AppError("bootstrap_failed", "Project-owned Worktrunk bootstrap failed", 1, { command: sanitizeCommand(command), result, results });
|
|
98
158
|
}
|
|
99
159
|
}
|
|
100
|
-
|
|
160
|
+
const qualifiedHook = propagateOwnedWorkspaceHooks(prepared.projectRoot, worktreePath);
|
|
161
|
+
return { status: "succeeded", commands: results, ...(qualifiedHook ? { qualified_hook: qualifiedHook } : {}) };
|
|
101
162
|
}
|
|
102
163
|
export function getWorktreeStatus(context, input) {
|
|
103
164
|
const protocol = scopedProtocol(context, input.projectRoot, input.protocolId);
|
|
104
165
|
return { ok: true, protocol_id: protocol.id, worktree: worktreeRecord(context, protocol.project_id, protocol.id), worktrunk: inspectManagedWorktrunk(context) };
|
|
105
166
|
}
|
|
106
|
-
export function
|
|
167
|
+
export function prepareWorktreeBootstrap(context, input) {
|
|
107
168
|
const protocol = scopedProtocol(context, input.projectRoot, input.protocolId);
|
|
108
169
|
const record = activeWorktreeRecord(context, protocol.project_id, protocol.id);
|
|
109
170
|
if (!record) {
|
|
110
171
|
throw new AppError("not_found", `Worktree record is not active for protocol: ${protocol.id}`, 1);
|
|
111
172
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
173
|
+
return { protocol, record, managed: prepareManagedWorktreeBootstrap({ projectRoot: protocol.project_root, worktreePath: record.worktree_path }) };
|
|
174
|
+
}
|
|
175
|
+
export async function bootstrapWorktree(context, input, prepared = prepareWorktreeBootstrap(context, input)) {
|
|
176
|
+
const { protocol, record } = prepared;
|
|
177
|
+
const active = activeWorktreeRecord(context, protocol.project_id, protocol.id);
|
|
178
|
+
if (!active || active.worktree_path !== record.worktree_path)
|
|
179
|
+
throw new AppError("worktree_active", "Worktree changed after bootstrap preparation", 1);
|
|
180
|
+
let result;
|
|
181
|
+
try {
|
|
182
|
+
result = await bootstrapManagedWorktree(context, prepared.managed, prepared.managed);
|
|
120
183
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
];
|
|
126
|
-
const results = [];
|
|
127
|
-
for (const command of commands) {
|
|
128
|
-
const result = runExternal(command);
|
|
129
|
-
results.push({ command: sanitizeCommand(command), ...result });
|
|
130
|
-
if (result.exit_code !== 0) {
|
|
131
|
-
const failed = { command: sanitizeCommand(command), result, results };
|
|
132
|
-
markBootstrapFailed(context, protocol, record, failed);
|
|
133
|
-
throw new AppError("bootstrap_failed", "Project-owned Worktrunk bootstrap failed", 1, failed);
|
|
134
|
-
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (error instanceof AppError && error.code === "bootstrap_failed")
|
|
186
|
+
markBootstrapFailed(context, protocol, record, error.details);
|
|
187
|
+
throw error;
|
|
135
188
|
}
|
|
136
189
|
const now = context.now();
|
|
137
|
-
const
|
|
190
|
+
const results = result.commands;
|
|
138
191
|
context.db.run(`UPDATE worktree_records
|
|
139
192
|
SET bootstrap_status = 'succeeded', last_command_result_json = ?, updated_at = ?
|
|
140
193
|
WHERE project_id = ? AND protocol_id = ?`, [JSON.stringify(result), now, protocol.project_id, protocol.id]);
|
|
@@ -155,7 +208,7 @@ export function bootstrapWorktree(context, input) {
|
|
|
155
208
|
});
|
|
156
209
|
return { ok: true, worktree: worktreeRecord(context, protocol.project_id, protocol.id) };
|
|
157
210
|
}
|
|
158
|
-
export function
|
|
211
|
+
export function prepareWorktreeClose(context, input) {
|
|
159
212
|
if (!["keep", "remove"].includes(input.mode)) {
|
|
160
213
|
throw new AppError("validation", "--mode must be keep or remove", 2);
|
|
161
214
|
}
|
|
@@ -171,6 +224,10 @@ export function closeWorktree(context, input) {
|
|
|
171
224
|
stage: state.stage
|
|
172
225
|
});
|
|
173
226
|
}
|
|
227
|
+
return { protocol, record };
|
|
228
|
+
}
|
|
229
|
+
export function closeWorktree(context, input) {
|
|
230
|
+
const { protocol, record } = prepareWorktreeClose(context, input);
|
|
174
231
|
const now = context.now();
|
|
175
232
|
const nextStatus = input.mode === "keep" ? "kept" : fs.existsSync(record.worktree_path) ? "kept" : "removed";
|
|
176
233
|
context.db.run(`UPDATE worktree_records SET status = ?, updated_at = ?, closed_at = ? WHERE project_id = ? AND protocol_id = ?`, [nextStatus, now, now, protocol.project_id, protocol.id]);
|
|
@@ -202,23 +259,26 @@ export function worktreeRecord(context, projectId, protocolId) {
|
|
|
202
259
|
function activeWorktreeRecord(context, projectId, protocolId) {
|
|
203
260
|
return context.db.get("SELECT * FROM worktree_records WHERE project_id = ? AND protocol_id = ? AND status = 'active'", [projectId, protocolId]);
|
|
204
261
|
}
|
|
205
|
-
function runExternal(command) {
|
|
262
|
+
async function runExternal(command, env = {}) {
|
|
206
263
|
const [bin, ...args] = command;
|
|
207
264
|
if (!bin) {
|
|
208
|
-
return { exit_code: null, stdout: "", stderr: "Missing executable." };
|
|
265
|
+
return { exit_code: null, signal: null, stdout: "", stderr: "Missing executable." };
|
|
209
266
|
}
|
|
210
|
-
const result =
|
|
267
|
+
const result = await commandResult(bin, args, { startupMs: SETUP_STARTUP_MS, env });
|
|
268
|
+
const evidence = processEvidence(result);
|
|
211
269
|
return {
|
|
212
|
-
exit_code:
|
|
213
|
-
|
|
214
|
-
|
|
270
|
+
exit_code: result.exit_code,
|
|
271
|
+
signal: result.signal,
|
|
272
|
+
stdout: result.exit_code === 0 && !result.signal ? sanitizeOutput(result.stdout) : evidence.stdout.text,
|
|
273
|
+
stderr: evidence.stderr.text,
|
|
274
|
+
output_truncated: { stdout: result.exit_code !== 0 && evidence.stdout.truncated, stderr: evidence.stderr.truncated }
|
|
215
275
|
};
|
|
216
276
|
}
|
|
217
277
|
function sanitizeCommand(command) {
|
|
218
278
|
return command.map((part) => (part.includes("=") ? part.replace(/=.*/, "=<redacted>") : part));
|
|
219
279
|
}
|
|
220
280
|
function sanitizeOutput(value) {
|
|
221
|
-
return value
|
|
281
|
+
return redactDiagnostic(value);
|
|
222
282
|
}
|
|
223
283
|
function parseWorktrunkResponse(stdout, command) {
|
|
224
284
|
let parsed;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { shortEntityReference, entityReferenceVariants } from "../harness-runtime/lib/entity-references.mjs";
|
package/dist/shared/errors.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { errorRecord as nativeErrorRecord, redactDiagnostic } from "../harness-runtime/lib/operation-errors.mjs";
|
|
2
|
+
export { redactDiagnostic, diagnosticJson } from "../harness-runtime/lib/operation-errors.mjs";
|
|
1
3
|
export class AppError extends Error {
|
|
2
4
|
code;
|
|
3
5
|
exitCode;
|
|
@@ -9,6 +11,31 @@ export class AppError extends Error {
|
|
|
9
11
|
this.details = details;
|
|
10
12
|
}
|
|
11
13
|
}
|
|
14
|
+
/** Error fields must cross JSON boundaries as data: Error.message is not enumerable. */
|
|
15
|
+
export function errorRecord(error, depth = 0) {
|
|
16
|
+
const value = nativeErrorRecord(error, depth);
|
|
17
|
+
const details = value.details && typeof value.details === "object" && !Array.isArray(value.details) ? value.details : {};
|
|
18
|
+
let typed = false;
|
|
19
|
+
try {
|
|
20
|
+
typed = typeof error?.code === "string";
|
|
21
|
+
}
|
|
22
|
+
catch { /* Diagnostic access cannot replace the primary failure. */ }
|
|
23
|
+
return {
|
|
24
|
+
...value,
|
|
25
|
+
code: typed ? value.code : "unexpected",
|
|
26
|
+
exitCode: value.exitCode ?? 1,
|
|
27
|
+
details,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
12
30
|
export function isAppError(error) {
|
|
13
31
|
return error instanceof AppError;
|
|
14
32
|
}
|
|
33
|
+
/** Bounded process diagnostics are observations, never command/retry authority. */
|
|
34
|
+
export function processEvidence(result) {
|
|
35
|
+
const excerpt = (value, limit) => {
|
|
36
|
+
const safe = redactDiagnostic(value), bytes = Buffer.from(safe);
|
|
37
|
+
return { text: new TextDecoder().decode(bytes.subarray(0, limit), { stream: true }), truncated: bytes.length > limit, bytes: bytes.length };
|
|
38
|
+
};
|
|
39
|
+
return { exit_code: result.exit_code, signal: result.signal ?? null,
|
|
40
|
+
stdout: excerpt(result.stdout, 8192), stderr: excerpt(result.stderr, 16384) };
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
/** Execution only: prepare an agent's write destination without creating or replacing its payload. */
|
|
5
|
+
export function prepareAgentOutputFile(file) {
|
|
6
|
+
const absolute = path.resolve(file);
|
|
7
|
+
try {
|
|
8
|
+
const parent = path.dirname(absolute);
|
|
9
|
+
fs.mkdirSync(parent, { recursive: true });
|
|
10
|
+
fs.accessSync(parent, fs.constants.W_OK | fs.constants.X_OK);
|
|
11
|
+
// lstat also rejects dangling links: an advertised output must not silently
|
|
12
|
+
// redirect a write to another authority or overwrite a retained input.
|
|
13
|
+
const existing = fs.lstatSync(absolute, { throwIfNoEntry: false });
|
|
14
|
+
if (existing) {
|
|
15
|
+
if (!existing.isFile())
|
|
16
|
+
throw new Error("Output must be a regular file, not a directory or link");
|
|
17
|
+
fs.accessSync(absolute, fs.constants.W_OK);
|
|
18
|
+
}
|
|
19
|
+
return absolute;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new AppError("agent_output_unavailable", "Agent output destination is not writable", 1, {
|
|
23
|
+
file: absolute, cause: error instanceof Error ? error.message : String(error)
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { AppError } from "../shared/errors.js";
|
|
3
|
+
const quote = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
4
|
+
const digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
5
|
+
function value(input) {
|
|
6
|
+
if (input === null)
|
|
7
|
+
return ["null"];
|
|
8
|
+
if (typeof input === "bigint")
|
|
9
|
+
return ["integer", input.toString()];
|
|
10
|
+
if (typeof input === "number")
|
|
11
|
+
return ["real", Object.is(input, -0) ? "-0" : input.toString()];
|
|
12
|
+
if (typeof input === "string")
|
|
13
|
+
return ["text", input];
|
|
14
|
+
if (input instanceof Uint8Array)
|
|
15
|
+
return ["blob", Buffer.from(input).toString("base64")];
|
|
16
|
+
throw new AppError("store_preservation_unsupported", "Cannot capture this SQLite value type", 1);
|
|
17
|
+
}
|
|
18
|
+
function tableData(db, table, columns) {
|
|
19
|
+
const statement = db.prepare(`SELECT ${columns.map(quote).join(",")} FROM ${quote(table)}`);
|
|
20
|
+
statement.setReadBigInts(true);
|
|
21
|
+
// ponytail: row digests use O(rows) memory; external sorting is needed only
|
|
22
|
+
// if a supported runtime store exceeds the in-memory migration contour.
|
|
23
|
+
const rows = [];
|
|
24
|
+
for (const row of statement.iterate())
|
|
25
|
+
rows.push(digest(JSON.stringify(columns.map(column => value(row[column])))));
|
|
26
|
+
rows.sort();
|
|
27
|
+
const hash = createHash("sha256");
|
|
28
|
+
for (const row of rows)
|
|
29
|
+
hash.update(row);
|
|
30
|
+
return { table, columns: [...columns], row_count: rows.length, sha256: hash.digest("hex") };
|
|
31
|
+
}
|
|
32
|
+
/** Logical old values/identities, not physical row order or implicit rowids.
|
|
33
|
+
* Capture under the migration writer barrier; backup readback uses the same
|
|
34
|
+
* columns, so additive tables/columns do not hide loss of existing data.
|
|
35
|
+
* Writer-contract and migration-receipt tables are operation-owned metadata,
|
|
36
|
+
* not application invariants; all other old tables remain covered.
|
|
37
|
+
*/
|
|
38
|
+
export function captureStoreData(db) {
|
|
39
|
+
const tables = db.prepare("SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT IN ('dd_flow_writer_contract','dd_flow_writer_migrations') ORDER BY name").all();
|
|
40
|
+
if (db.prepare("SELECT 1 FROM sqlite_schema WHERE type='table' AND name='sqlite_sequence'").get())
|
|
41
|
+
tables.push({ name: "sqlite_sequence" });
|
|
42
|
+
return tables.map(row => {
|
|
43
|
+
const name = String(row.name);
|
|
44
|
+
const columns = db.prepare(`PRAGMA table_info(${quote(name)})`).all().map(column => String(column.name));
|
|
45
|
+
if (!columns.length)
|
|
46
|
+
throw new AppError("store_preservation_unsupported", "Cannot capture an empty column inventory", 1, { table: name });
|
|
47
|
+
return tableData(db, name, columns);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function verifyStoreData(db, expected) {
|
|
51
|
+
for (const original of expected) {
|
|
52
|
+
let actual;
|
|
53
|
+
try {
|
|
54
|
+
const columns = new Set(db.prepare(`PRAGMA table_info(${quote(original.table)})`).all().map(column => String(column.name)));
|
|
55
|
+
if (original.columns.some(column => !columns.has(column)))
|
|
56
|
+
throw new Error("Original column missing");
|
|
57
|
+
actual = tableData(db, original.table, original.columns);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new AppError("store_data_not_preserved", "Migration lost an original table or column", 1, { table: original.table });
|
|
61
|
+
}
|
|
62
|
+
if (actual.row_count !== original.row_count || actual.sha256 !== original.sha256)
|
|
63
|
+
throw new AppError("store_data_not_preserved", "Migration changed original values or logical identities", 1, { table: original.table, expected_rows: original.row_count, actual_rows: actual.row_count });
|
|
64
|
+
}
|
|
65
|
+
}
|