looply-cli 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +137 -3
- package/dist/.src-hash +1 -0
- package/dist/acceptance-observe.d.ts +108 -0
- package/dist/acceptance-observe.d.ts.map +1 -0
- package/dist/acceptance-observe.js +152 -0
- package/dist/acceptance-observe.js.map +1 -0
- package/dist/agent-cmd.d.ts +131 -0
- package/dist/agent-cmd.d.ts.map +1 -0
- package/dist/agent-cmd.js +154 -0
- package/dist/agent-cmd.js.map +1 -0
- package/dist/agent-contained.d.ts +114 -0
- package/dist/agent-contained.d.ts.map +1 -0
- package/dist/agent-contained.js +292 -0
- package/dist/agent-contained.js.map +1 -0
- package/dist/agent-driver.d.ts +130 -0
- package/dist/agent-driver.d.ts.map +1 -0
- package/dist/agent-driver.js +170 -0
- package/dist/agent-driver.js.map +1 -0
- package/dist/agent-envelope.d.ts +94 -0
- package/dist/agent-envelope.d.ts.map +1 -0
- package/dist/agent-envelope.js +214 -0
- package/dist/agent-envelope.js.map +1 -0
- package/dist/agent-exec.d.ts +182 -0
- package/dist/agent-exec.d.ts.map +1 -0
- package/dist/agent-exec.js +125 -0
- package/dist/agent-exec.js.map +1 -0
- package/dist/agent-runtime.d.ts +23 -0
- package/dist/agent-runtime.d.ts.map +1 -0
- package/dist/agent-runtime.js +143 -0
- package/dist/agent-runtime.js.map +1 -0
- package/dist/approval-gate-read.d.ts +66 -0
- package/dist/approval-gate-read.d.ts.map +1 -0
- package/dist/approval-gate-read.js +138 -0
- package/dist/approval-gate-read.js.map +1 -0
- package/dist/approval-resolution.d.ts +87 -0
- package/dist/approval-resolution.d.ts.map +1 -0
- package/dist/approval-resolution.js +100 -0
- package/dist/approval-resolution.js.map +1 -0
- package/dist/approval-resumes.d.ts +102 -0
- package/dist/approval-resumes.d.ts.map +1 -0
- package/dist/approval-resumes.js +167 -0
- package/dist/approval-resumes.js.map +1 -0
- package/dist/ask-brain.d.ts +167 -0
- package/dist/ask-brain.d.ts.map +1 -0
- package/dist/ask-brain.js +355 -0
- package/dist/ask-brain.js.map +1 -0
- package/dist/autonomy-authority.d.ts +80 -0
- package/dist/autonomy-authority.d.ts.map +1 -0
- package/dist/autonomy-authority.js +82 -0
- package/dist/autonomy-authority.js.map +1 -0
- package/dist/autonomy-controller.d.ts +321 -0
- package/dist/autonomy-controller.d.ts.map +1 -0
- package/dist/autonomy-controller.js +517 -0
- package/dist/autonomy-controller.js.map +1 -0
- package/dist/autonomy-store.d.ts +327 -0
- package/dist/autonomy-store.d.ts.map +1 -0
- package/dist/autonomy-store.js +581 -0
- package/dist/autonomy-store.js.map +1 -0
- package/dist/autonomy-tick.d.ts +257 -0
- package/dist/autonomy-tick.d.ts.map +1 -0
- package/dist/autonomy-tick.js +616 -0
- package/dist/autonomy-tick.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +2719 -0
- package/dist/bin.js.map +1 -0
- package/dist/brain-advice.d.ts +21 -0
- package/dist/brain-advice.d.ts.map +1 -0
- package/dist/brain-advice.js +51 -0
- package/dist/brain-advice.js.map +1 -0
- package/dist/candidate-replay-runtime.d.ts +125 -0
- package/dist/candidate-replay-runtime.d.ts.map +1 -0
- package/dist/candidate-replay-runtime.js +188 -0
- package/dist/candidate-replay-runtime.js.map +1 -0
- package/dist/checkout-carry.d.ts +76 -0
- package/dist/checkout-carry.d.ts.map +1 -0
- package/dist/checkout-carry.js +125 -0
- package/dist/checkout-carry.js.map +1 -0
- package/dist/citation-readers.d.ts +26 -0
- package/dist/citation-readers.d.ts.map +1 -0
- package/dist/citation-readers.js +102 -0
- package/dist/citation-readers.js.map +1 -0
- package/dist/command-receipts.d.ts +79 -0
- package/dist/command-receipts.d.ts.map +1 -0
- package/dist/command-receipts.js +143 -0
- package/dist/command-receipts.js.map +1 -0
- package/dist/command-runner.d.ts +32 -0
- package/dist/command-runner.d.ts.map +1 -0
- package/dist/command-runner.js +108 -0
- package/dist/command-runner.js.map +1 -0
- package/dist/compatible-sets.d.ts +67 -0
- package/dist/compatible-sets.d.ts.map +1 -0
- package/dist/compatible-sets.js +81 -0
- package/dist/compatible-sets.js.map +1 -0
- package/dist/compile-check.d.ts +31 -0
- package/dist/compile-check.d.ts.map +1 -0
- package/dist/compile-check.js +34 -0
- package/dist/compile-check.js.map +1 -0
- package/dist/compile-store.d.ts +16 -0
- package/dist/compile-store.d.ts.map +1 -0
- package/dist/compile-store.js +21 -0
- package/dist/compile-store.js.map +1 -0
- package/dist/completion.d.ts +106 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +131 -0
- package/dist/completion.js.map +1 -0
- package/dist/config.d.ts +549 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +763 -0
- package/dist/config.js.map +1 -0
- package/dist/control-file.d.ts +142 -0
- package/dist/control-file.d.ts.map +1 -0
- package/dist/control-file.js +144 -0
- package/dist/control-file.js.map +1 -0
- package/dist/coordinator-state.d.ts +131 -0
- package/dist/coordinator-state.d.ts.map +1 -0
- package/dist/coordinator-state.js +380 -0
- package/dist/coordinator-state.js.map +1 -0
- package/dist/coordinator.d.ts +95 -0
- package/dist/coordinator.d.ts.map +1 -0
- package/dist/coordinator.js +97 -0
- package/dist/coordinator.js.map +1 -0
- package/dist/cursor-store.d.ts +53 -0
- package/dist/cursor-store.d.ts.map +1 -0
- package/dist/cursor-store.js +98 -0
- package/dist/cursor-store.js.map +1 -0
- package/dist/daemon-cmd.d.ts +239 -0
- package/dist/daemon-cmd.d.ts.map +1 -0
- package/dist/daemon-cmd.js +1751 -0
- package/dist/daemon-cmd.js.map +1 -0
- package/dist/daemon-lock.d.ts +140 -0
- package/dist/daemon-lock.d.ts.map +1 -0
- package/dist/daemon-lock.js +352 -0
- package/dist/daemon-lock.js.map +1 -0
- package/dist/daemon-recovery.d.ts +78 -0
- package/dist/daemon-recovery.d.ts.map +1 -0
- package/dist/daemon-recovery.js +161 -0
- package/dist/daemon-recovery.js.map +1 -0
- package/dist/daemon.d.ts +368 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +601 -0
- package/dist/daemon.js.map +1 -0
- package/dist/declared-response-shape.d.ts +93 -0
- package/dist/declared-response-shape.d.ts.map +1 -0
- package/dist/declared-response-shape.js +200 -0
- package/dist/declared-response-shape.js.map +1 -0
- package/dist/declared-surfaces.d.ts +16 -0
- package/dist/declared-surfaces.d.ts.map +1 -0
- package/dist/declared-surfaces.js +19 -0
- package/dist/declared-surfaces.js.map +1 -0
- package/dist/depends-review.d.ts +113 -0
- package/dist/depends-review.d.ts.map +1 -0
- package/dist/depends-review.js +110 -0
- package/dist/depends-review.js.map +1 -0
- package/dist/doctor.d.ts +91 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +71 -0
- package/dist/doctor.js.map +1 -0
- package/dist/edge-approval.d.ts +105 -0
- package/dist/edge-approval.d.ts.map +1 -0
- package/dist/edge-approval.js +100 -0
- package/dist/edge-approval.js.map +1 -0
- package/dist/evidence-cache.d.ts +45 -0
- package/dist/evidence-cache.d.ts.map +1 -0
- package/dist/evidence-cache.js +90 -0
- package/dist/evidence-cache.js.map +1 -0
- package/dist/evidence-cmd.d.ts +133 -0
- package/dist/evidence-cmd.d.ts.map +1 -0
- package/dist/evidence-cmd.js +347 -0
- package/dist/evidence-cmd.js.map +1 -0
- package/dist/evidence-facts.d.ts +40 -0
- package/dist/evidence-facts.d.ts.map +1 -0
- package/dist/evidence-facts.js +114 -0
- package/dist/evidence-facts.js.map +1 -0
- package/dist/exclusive-lock.d.ts +52 -0
- package/dist/exclusive-lock.d.ts.map +1 -0
- package/dist/exclusive-lock.js +150 -0
- package/dist/exclusive-lock.js.map +1 -0
- package/dist/exec-domains.d.ts +140 -0
- package/dist/exec-domains.d.ts.map +1 -0
- package/dist/exec-domains.js +287 -0
- package/dist/exec-domains.js.map +1 -0
- package/dist/exemption-store.d.ts +197 -0
- package/dist/exemption-store.d.ts.map +1 -0
- package/dist/exemption-store.js +266 -0
- package/dist/exemption-store.js.map +1 -0
- package/dist/explicit-start-gate.d.ts +96 -0
- package/dist/explicit-start-gate.d.ts.map +1 -0
- package/dist/explicit-start-gate.js +103 -0
- package/dist/explicit-start-gate.js.map +1 -0
- package/dist/fs-trouble.d.ts +70 -0
- package/dist/fs-trouble.d.ts.map +1 -0
- package/dist/fs-trouble.js +98 -0
- package/dist/fs-trouble.js.map +1 -0
- package/dist/gate.d.ts +278 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +278 -0
- package/dist/gate.js.map +1 -0
- package/dist/git-driver.d.ts +519 -0
- package/dist/git-driver.d.ts.map +1 -0
- package/dist/git-driver.js +900 -0
- package/dist/git-driver.js.map +1 -0
- package/dist/git-push-executor.d.ts +41 -0
- package/dist/git-push-executor.d.ts.map +1 -0
- package/dist/git-push-executor.js +142 -0
- package/dist/git-push-executor.js.map +1 -0
- package/dist/glob.d.ts +26 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +93 -0
- package/dist/glob.js.map +1 -0
- package/dist/goal-adaptive.d.ts +295 -0
- package/dist/goal-adaptive.d.ts.map +1 -0
- package/dist/goal-adaptive.js +393 -0
- package/dist/goal-adaptive.js.map +1 -0
- package/dist/goal-compile.d.ts +342 -0
- package/dist/goal-compile.d.ts.map +1 -0
- package/dist/goal-compile.js +444 -0
- package/dist/goal-compile.js.map +1 -0
- package/dist/goal-depends-executor.d.ts +55 -0
- package/dist/goal-depends-executor.d.ts.map +1 -0
- package/dist/goal-depends-executor.js +202 -0
- package/dist/goal-depends-executor.js.map +1 -0
- package/dist/goal-execution-evidence.d.ts +135 -0
- package/dist/goal-execution-evidence.d.ts.map +1 -0
- package/dist/goal-execution-evidence.js +159 -0
- package/dist/goal-execution-evidence.js.map +1 -0
- package/dist/goal-gap.d.ts +140 -0
- package/dist/goal-gap.d.ts.map +1 -0
- package/dist/goal-gap.js +197 -0
- package/dist/goal-gap.js.map +1 -0
- package/dist/goal-met-target.d.ts +98 -0
- package/dist/goal-met-target.d.ts.map +1 -0
- package/dist/goal-met-target.js +92 -0
- package/dist/goal-met-target.js.map +1 -0
- package/dist/goal-ownership.d.ts +416 -0
- package/dist/goal-ownership.d.ts.map +1 -0
- package/dist/goal-ownership.js +576 -0
- package/dist/goal-ownership.js.map +1 -0
- package/dist/goal-runs.d.ts +82 -0
- package/dist/goal-runs.d.ts.map +1 -0
- package/dist/goal-runs.js +120 -0
- package/dist/goal-runs.js.map +1 -0
- package/dist/goal-store.d.ts +146 -0
- package/dist/goal-store.d.ts.map +1 -0
- package/dist/goal-store.js +294 -0
- package/dist/goal-store.js.map +1 -0
- package/dist/goal-view.d.ts +156 -0
- package/dist/goal-view.d.ts.map +1 -0
- package/dist/goal-view.js +499 -0
- package/dist/goal-view.js.map +1 -0
- package/dist/governed-approvals.d.ts +152 -0
- package/dist/governed-approvals.d.ts.map +1 -0
- package/dist/governed-approvals.js +246 -0
- package/dist/governed-approvals.js.map +1 -0
- package/dist/governed-broker.d.ts +169 -0
- package/dist/governed-broker.d.ts.map +1 -0
- package/dist/governed-broker.js +196 -0
- package/dist/governed-broker.js.map +1 -0
- package/dist/governed-run.d.ts +220 -0
- package/dist/governed-run.d.ts.map +1 -0
- package/dist/governed-run.js +406 -0
- package/dist/governed-run.js.map +1 -0
- package/dist/grant-reconcile.d.ts +63 -0
- package/dist/grant-reconcile.d.ts.map +1 -0
- package/dist/grant-reconcile.js +121 -0
- package/dist/grant-reconcile.js.map +1 -0
- package/dist/index-for-head.d.ts +56 -0
- package/dist/index-for-head.d.ts.map +1 -0
- package/dist/index-for-head.js +103 -0
- package/dist/index-for-head.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/init-detect.d.ts +39 -0
- package/dist/init-detect.d.ts.map +1 -0
- package/dist/init-detect.js +188 -0
- package/dist/init-detect.js.map +1 -0
- package/dist/integration-deps.d.ts +62 -0
- package/dist/integration-deps.d.ts.map +1 -0
- package/dist/integration-deps.js +251 -0
- package/dist/integration-deps.js.map +1 -0
- package/dist/integration-runtime.d.ts +458 -0
- package/dist/integration-runtime.d.ts.map +1 -0
- package/dist/integration-runtime.js +681 -0
- package/dist/integration-runtime.js.map +1 -0
- package/dist/integration.d.ts +45 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +87 -0
- package/dist/integration.js.map +1 -0
- package/dist/integrator.d.ts +84 -0
- package/dist/integrator.d.ts.map +1 -0
- package/dist/integrator.js +193 -0
- package/dist/integrator.js.map +1 -0
- package/dist/lane-claims.d.ts +174 -0
- package/dist/lane-claims.d.ts.map +1 -0
- package/dist/lane-claims.js +218 -0
- package/dist/lane-claims.js.map +1 -0
- package/dist/lane-coverage.d.ts +87 -0
- package/dist/lane-coverage.d.ts.map +1 -0
- package/dist/lane-coverage.js +129 -0
- package/dist/lane-coverage.js.map +1 -0
- package/dist/ledger-replay.d.ts +115 -0
- package/dist/ledger-replay.d.ts.map +1 -0
- package/dist/ledger-replay.js +155 -0
- package/dist/ledger-replay.js.map +1 -0
- package/dist/ledger-store.d.ts +68 -0
- package/dist/ledger-store.d.ts.map +1 -0
- package/dist/ledger-store.js +111 -0
- package/dist/ledger-store.js.map +1 -0
- package/dist/loop-safety-observer.d.ts +132 -0
- package/dist/loop-safety-observer.d.ts.map +1 -0
- package/dist/loop-safety-observer.js +76 -0
- package/dist/loop-safety-observer.js.map +1 -0
- package/dist/loop-safety-store.d.ts +339 -0
- package/dist/loop-safety-store.d.ts.map +1 -0
- package/dist/loop-safety-store.js +800 -0
- package/dist/loop-safety-store.js.map +1 -0
- package/dist/machine-store.d.ts +54 -0
- package/dist/machine-store.d.ts.map +1 -0
- package/dist/machine-store.js +149 -0
- package/dist/machine-store.js.map +1 -0
- package/dist/mcp-main.d.ts +2 -0
- package/dist/mcp-main.d.ts.map +1 -0
- package/dist/mcp-main.js +116 -0
- package/dist/mcp-main.js.map +1 -0
- package/dist/mcp-server.d.ts +72 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +259 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/model-routing.d.ts +75 -0
- package/dist/model-routing.d.ts.map +1 -0
- package/dist/model-routing.js +108 -0
- package/dist/model-routing.js.map +1 -0
- package/dist/model-transport.d.ts +188 -0
- package/dist/model-transport.d.ts.map +1 -0
- package/dist/model-transport.js +625 -0
- package/dist/model-transport.js.map +1 -0
- package/dist/notify-cadence.d.ts +55 -0
- package/dist/notify-cadence.d.ts.map +1 -0
- package/dist/notify-cadence.js +68 -0
- package/dist/notify-cadence.js.map +1 -0
- package/dist/notify-channel.d.ts +69 -0
- package/dist/notify-channel.d.ts.map +1 -0
- package/dist/notify-channel.js +151 -0
- package/dist/notify-channel.js.map +1 -0
- package/dist/notify.d.ts +71 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +125 -0
- package/dist/notify.js.map +1 -0
- package/dist/observation-inventory.d.ts +65 -0
- package/dist/observation-inventory.d.ts.map +1 -0
- package/dist/observation-inventory.js +139 -0
- package/dist/observation-inventory.js.map +1 -0
- package/dist/owned-children.d.ts +45 -0
- package/dist/owned-children.d.ts.map +1 -0
- package/dist/owned-children.js +64 -0
- package/dist/owned-children.js.map +1 -0
- package/dist/packet-for-goal.d.ts +19 -0
- package/dist/packet-for-goal.d.ts.map +1 -0
- package/dist/packet-for-goal.js +32 -0
- package/dist/packet-for-goal.js.map +1 -0
- package/dist/pair-cmd.d.ts +85 -0
- package/dist/pair-cmd.d.ts.map +1 -0
- package/dist/pair-cmd.js +205 -0
- package/dist/pair-cmd.js.map +1 -0
- package/dist/partial-asker.d.ts +96 -0
- package/dist/partial-asker.d.ts.map +1 -0
- package/dist/partial-asker.js +117 -0
- package/dist/partial-asker.js.map +1 -0
- package/dist/pdf-text-lines.d.ts +17 -0
- package/dist/pdf-text-lines.d.ts.map +1 -0
- package/dist/pdf-text-lines.js +70 -0
- package/dist/pdf-text-lines.js.map +1 -0
- package/dist/pdf-text-worker.d.ts +2 -0
- package/dist/pdf-text-worker.d.ts.map +1 -0
- package/dist/pdf-text-worker.js +81 -0
- package/dist/pdf-text-worker.js.map +1 -0
- package/dist/pdf-text.d.ts +56 -0
- package/dist/pdf-text.d.ts.map +1 -0
- package/dist/pdf-text.js +64 -0
- package/dist/pdf-text.js.map +1 -0
- package/dist/pending-action.d.ts +154 -0
- package/dist/pending-action.d.ts.map +1 -0
- package/dist/pending-action.js +148 -0
- package/dist/pending-action.js.map +1 -0
- package/dist/preemptor.d.ts +40 -0
- package/dist/preemptor.d.ts.map +1 -0
- package/dist/preemptor.js +49 -0
- package/dist/preemptor.js.map +1 -0
- package/dist/programme-mode.d.ts +29 -0
- package/dist/programme-mode.d.ts.map +1 -0
- package/dist/programme-mode.js +50 -0
- package/dist/programme-mode.js.map +1 -0
- package/dist/progress-view.d.ts +14 -0
- package/dist/progress-view.d.ts.map +1 -0
- package/dist/progress-view.js +114 -0
- package/dist/progress-view.js.map +1 -0
- package/dist/project-graph-builder.d.ts +81 -0
- package/dist/project-graph-builder.d.ts.map +1 -0
- package/dist/project-graph-builder.js +246 -0
- package/dist/project-graph-builder.js.map +1 -0
- package/dist/project-graph-runtime.d.ts +86 -0
- package/dist/project-graph-runtime.d.ts.map +1 -0
- package/dist/project-graph-runtime.js +112 -0
- package/dist/project-graph-runtime.js.map +1 -0
- package/dist/project-index-builder.d.ts +96 -0
- package/dist/project-index-builder.d.ts.map +1 -0
- package/dist/project-index-builder.js +298 -0
- package/dist/project-index-builder.js.map +1 -0
- package/dist/project-index-facts.d.ts +51 -0
- package/dist/project-index-facts.d.ts.map +1 -0
- package/dist/project-index-facts.js +117 -0
- package/dist/project-index-facts.js.map +1 -0
- package/dist/project-index-store.d.ts +97 -0
- package/dist/project-index-store.d.ts.map +1 -0
- package/dist/project-index-store.js +140 -0
- package/dist/project-index-store.js.map +1 -0
- package/dist/project-memory-store.d.ts +127 -0
- package/dist/project-memory-store.d.ts.map +1 -0
- package/dist/project-memory-store.js +302 -0
- package/dist/project-memory-store.js.map +1 -0
- package/dist/proposal-store.d.ts +14 -0
- package/dist/proposal-store.d.ts.map +1 -0
- package/dist/proposal-store.js +19 -0
- package/dist/proposal-store.js.map +1 -0
- package/dist/prover.d.ts +80 -0
- package/dist/prover.d.ts.map +1 -0
- package/dist/prover.js +137 -0
- package/dist/prover.js.map +1 -0
- package/dist/provider-identity-store.d.ts +34 -0
- package/dist/provider-identity-store.d.ts.map +1 -0
- package/dist/provider-identity-store.js +72 -0
- package/dist/provider-identity-store.js.map +1 -0
- package/dist/provider-identity.d.ts +104 -0
- package/dist/provider-identity.d.ts.map +1 -0
- package/dist/provider-identity.js +167 -0
- package/dist/provider-identity.js.map +1 -0
- package/dist/provider-limit.d.ts +79 -0
- package/dist/provider-limit.d.ts.map +1 -0
- package/dist/provider-limit.js +148 -0
- package/dist/provider-limit.js.map +1 -0
- package/dist/provider-preflight.d.ts +171 -0
- package/dist/provider-preflight.d.ts.map +1 -0
- package/dist/provider-preflight.js +395 -0
- package/dist/provider-preflight.js.map +1 -0
- package/dist/provider-state.d.ts +120 -0
- package/dist/provider-state.d.ts.map +1 -0
- package/dist/provider-state.js +182 -0
- package/dist/provider-state.js.map +1 -0
- package/dist/providers.d.ts +132 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +161 -0
- package/dist/providers.js.map +1 -0
- package/dist/publication-recorder.d.ts +117 -0
- package/dist/publication-recorder.d.ts.map +1 -0
- package/dist/publication-recorder.js +124 -0
- package/dist/publication-recorder.js.map +1 -0
- package/dist/pursuit-delivery.d.ts +24 -0
- package/dist/pursuit-delivery.d.ts.map +1 -0
- package/dist/pursuit-delivery.js +38 -0
- package/dist/pursuit-delivery.js.map +1 -0
- package/dist/queue-store.d.ts +132 -0
- package/dist/queue-store.d.ts.map +1 -0
- package/dist/queue-store.js +185 -0
- package/dist/queue-store.js.map +1 -0
- package/dist/queue-summary.d.ts +14 -0
- package/dist/queue-summary.d.ts.map +1 -0
- package/dist/queue-summary.js +82 -0
- package/dist/queue-summary.js.map +1 -0
- package/dist/queue-view.d.ts +20 -0
- package/dist/queue-view.d.ts.map +1 -0
- package/dist/queue-view.js +163 -0
- package/dist/queue-view.js.map +1 -0
- package/dist/queue-write-lease.d.ts +106 -0
- package/dist/queue-write-lease.d.ts.map +1 -0
- package/dist/queue-write-lease.js +282 -0
- package/dist/queue-write-lease.js.map +1 -0
- package/dist/rails-home.d.ts +162 -0
- package/dist/rails-home.d.ts.map +1 -0
- package/dist/rails-home.js +452 -0
- package/dist/rails-home.js.map +1 -0
- package/dist/rails-migrations.d.ts +75 -0
- package/dist/rails-migrations.d.ts.map +1 -0
- package/dist/rails-migrations.js +199 -0
- package/dist/rails-migrations.js.map +1 -0
- package/dist/rails-stores.d.ts +49 -0
- package/dist/rails-stores.d.ts.map +1 -0
- package/dist/rails-stores.js +100 -0
- package/dist/rails-stores.js.map +1 -0
- package/dist/reaper.d.ts +69 -0
- package/dist/reaper.d.ts.map +1 -0
- package/dist/reaper.js +152 -0
- package/dist/reaper.js.map +1 -0
- package/dist/record-store.d.ts +36 -0
- package/dist/record-store.d.ts.map +1 -0
- package/dist/record-store.js +78 -0
- package/dist/record-store.js.map +1 -0
- package/dist/recovery-io.d.ts +50 -0
- package/dist/recovery-io.d.ts.map +1 -0
- package/dist/recovery-io.js +122 -0
- package/dist/recovery-io.js.map +1 -0
- package/dist/recovery.d.ts +146 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +110 -0
- package/dist/recovery.js.map +1 -0
- package/dist/redraw.d.ts +34 -0
- package/dist/redraw.d.ts.map +1 -0
- package/dist/redraw.js +62 -0
- package/dist/redraw.js.map +1 -0
- package/dist/rejected-evidence.d.ts +255 -0
- package/dist/rejected-evidence.d.ts.map +1 -0
- package/dist/rejected-evidence.js +324 -0
- package/dist/rejected-evidence.js.map +1 -0
- package/dist/report-cmd.d.ts +32 -0
- package/dist/report-cmd.d.ts.map +1 -0
- package/dist/report-cmd.js +201 -0
- package/dist/report-cmd.js.map +1 -0
- package/dist/repos-cmd.d.ts +80 -0
- package/dist/repos-cmd.d.ts.map +1 -0
- package/dist/repos-cmd.js +240 -0
- package/dist/repos-cmd.js.map +1 -0
- package/dist/request-body-shape.d.ts +93 -0
- package/dist/request-body-shape.d.ts.map +1 -0
- package/dist/request-body-shape.js +407 -0
- package/dist/request-body-shape.js.map +1 -0
- package/dist/requirement-claims.d.ts +89 -0
- package/dist/requirement-claims.d.ts.map +1 -0
- package/dist/requirement-claims.js +92 -0
- package/dist/requirement-claims.js.map +1 -0
- package/dist/retention-apply-runtime.d.ts +105 -0
- package/dist/retention-apply-runtime.d.ts.map +1 -0
- package/dist/retention-apply-runtime.js +269 -0
- package/dist/retention-apply-runtime.js.map +1 -0
- package/dist/reverify.d.ts +41 -0
- package/dist/reverify.d.ts.map +1 -0
- package/dist/reverify.js +69 -0
- package/dist/reverify.js.map +1 -0
- package/dist/round-records.d.ts +65 -0
- package/dist/round-records.d.ts.map +1 -0
- package/dist/round-records.js +61 -0
- package/dist/round-records.js.map +1 -0
- package/dist/round-runner.d.ts +924 -0
- package/dist/round-runner.d.ts.map +1 -0
- package/dist/round-runner.js +1693 -0
- package/dist/round-runner.js.map +1 -0
- package/dist/run-approval.d.ts +180 -0
- package/dist/run-approval.d.ts.map +1 -0
- package/dist/run-approval.js +199 -0
- package/dist/run-approval.js.map +1 -0
- package/dist/run-cmd.d.ts +359 -0
- package/dist/run-cmd.d.ts.map +1 -0
- package/dist/run-cmd.js +4418 -0
- package/dist/run-cmd.js.map +1 -0
- package/dist/run-delivery.d.ts +71 -0
- package/dist/run-delivery.d.ts.map +1 -0
- package/dist/run-delivery.js +104 -0
- package/dist/run-delivery.js.map +1 -0
- package/dist/run-ended.d.ts +75 -0
- package/dist/run-ended.d.ts.map +1 -0
- package/dist/run-ended.js +27 -0
- package/dist/run-ended.js.map +1 -0
- package/dist/run-ending-locator.d.ts +125 -0
- package/dist/run-ending-locator.d.ts.map +1 -0
- package/dist/run-ending-locator.js +133 -0
- package/dist/run-ending-locator.js.map +1 -0
- package/dist/run-launcher.d.ts +459 -0
- package/dist/run-launcher.d.ts.map +1 -0
- package/dist/run-launcher.js +652 -0
- package/dist/run-launcher.js.map +1 -0
- package/dist/run-lease.d.ts +208 -0
- package/dist/run-lease.d.ts.map +1 -0
- package/dist/run-lease.js +301 -0
- package/dist/run-lease.js.map +1 -0
- package/dist/run-refusal-marks.d.ts +189 -0
- package/dist/run-refusal-marks.d.ts.map +1 -0
- package/dist/run-refusal-marks.js +249 -0
- package/dist/run-refusal-marks.js.map +1 -0
- package/dist/run-start-marks.d.ts +153 -0
- package/dist/run-start-marks.d.ts.map +1 -0
- package/dist/run-start-marks.js +269 -0
- package/dist/run-start-marks.js.map +1 -0
- package/dist/scan-cmd.d.ts +14 -0
- package/dist/scan-cmd.d.ts.map +1 -0
- package/dist/scan-cmd.js +270 -0
- package/dist/scan-cmd.js.map +1 -0
- package/dist/scan-events.d.ts +50 -0
- package/dist/scan-events.d.ts.map +1 -0
- package/dist/scan-events.js +91 -0
- package/dist/scan-events.js.map +1 -0
- package/dist/scan.d.ts +191 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +417 -0
- package/dist/scan.js.map +1 -0
- package/dist/scope-rule.d.ts +148 -0
- package/dist/scope-rule.d.ts.map +1 -0
- package/dist/scope-rule.js +121 -0
- package/dist/scope-rule.js.map +1 -0
- package/dist/self-repo-id.d.ts +18 -0
- package/dist/self-repo-id.d.ts.map +1 -0
- package/dist/self-repo-id.js +70 -0
- package/dist/self-repo-id.js.map +1 -0
- package/dist/server-client.d.ts +766 -0
- package/dist/server-client.d.ts.map +1 -0
- package/dist/server-client.js +475 -0
- package/dist/server-client.js.map +1 -0
- package/dist/session-adapter-runtime.d.ts +195 -0
- package/dist/session-adapter-runtime.d.ts.map +1 -0
- package/dist/session-adapter-runtime.js +373 -0
- package/dist/session-adapter-runtime.js.map +1 -0
- package/dist/session-checkpoint-runtime.d.ts +62 -0
- package/dist/session-checkpoint-runtime.d.ts.map +1 -0
- package/dist/session-checkpoint-runtime.js +268 -0
- package/dist/session-checkpoint-runtime.js.map +1 -0
- package/dist/session-control-transport.d.ts +106 -0
- package/dist/session-control-transport.d.ts.map +1 -0
- package/dist/session-control-transport.js +232 -0
- package/dist/session-control-transport.js.map +1 -0
- package/dist/session-observation-store.d.ts +98 -0
- package/dist/session-observation-store.d.ts.map +1 -0
- package/dist/session-observation-store.js +155 -0
- package/dist/session-observation-store.js.map +1 -0
- package/dist/session-observe-runtime.d.ts +123 -0
- package/dist/session-observe-runtime.d.ts.map +1 -0
- package/dist/session-observe-runtime.js +317 -0
- package/dist/session-observe-runtime.js.map +1 -0
- package/dist/session-store.d.ts +98 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +116 -0
- package/dist/session-store.js.map +1 -0
- package/dist/sessions-cmd.d.ts +202 -0
- package/dist/sessions-cmd.d.ts.map +1 -0
- package/dist/sessions-cmd.js +609 -0
- package/dist/sessions-cmd.js.map +1 -0
- package/dist/settings-overlay.d.ts +53 -0
- package/dist/settings-overlay.d.ts.map +1 -0
- package/dist/settings-overlay.js +175 -0
- package/dist/settings-overlay.js.map +1 -0
- package/dist/setup-prompt.d.ts +34 -0
- package/dist/setup-prompt.d.ts.map +1 -0
- package/dist/setup-prompt.js +92 -0
- package/dist/setup-prompt.js.map +1 -0
- package/dist/setup.d.ts +103 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +283 -0
- package/dist/setup.js.map +1 -0
- package/dist/shared-grants.d.ts +164 -0
- package/dist/shared-grants.d.ts.map +1 -0
- package/dist/shared-grants.js +242 -0
- package/dist/shared-grants.js.map +1 -0
- package/dist/signals.d.ts +55 -0
- package/dist/signals.d.ts.map +1 -0
- package/dist/signals.js +85 -0
- package/dist/signals.js.map +1 -0
- package/dist/source-cmd.d.ts +201 -0
- package/dist/source-cmd.d.ts.map +1 -0
- package/dist/source-cmd.js +684 -0
- package/dist/source-cmd.js.map +1 -0
- package/dist/source-verdict.d.ts +99 -0
- package/dist/source-verdict.d.ts.map +1 -0
- package/dist/source-verdict.js +182 -0
- package/dist/source-verdict.js.map +1 -0
- package/dist/spend-ledger.d.ts +350 -0
- package/dist/spend-ledger.d.ts.map +1 -0
- package/dist/spend-ledger.js +546 -0
- package/dist/spend-ledger.js.map +1 -0
- package/dist/stale-run-sweep.d.ts +79 -0
- package/dist/stale-run-sweep.d.ts.map +1 -0
- package/dist/stale-run-sweep.js +116 -0
- package/dist/stale-run-sweep.js.map +1 -0
- package/dist/start-attempts.d.ts +385 -0
- package/dist/start-attempts.d.ts.map +1 -0
- package/dist/start-attempts.js +613 -0
- package/dist/start-attempts.js.map +1 -0
- package/dist/status-cmd.d.ts +28 -0
- package/dist/status-cmd.d.ts.map +1 -0
- package/dist/status-cmd.js +116 -0
- package/dist/status-cmd.js.map +1 -0
- package/dist/stop-follow-up.d.ts +107 -0
- package/dist/stop-follow-up.d.ts.map +1 -0
- package/dist/stop-follow-up.js +172 -0
- package/dist/stop-follow-up.js.map +1 -0
- package/dist/surface-lease.d.ts +118 -0
- package/dist/surface-lease.d.ts.map +1 -0
- package/dist/surface-lease.js +485 -0
- package/dist/surface-lease.js.map +1 -0
- package/dist/sync.d.ts +54 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +93 -0
- package/dist/sync.js.map +1 -0
- package/dist/syncing-ledger.d.ts +45 -0
- package/dist/syncing-ledger.d.ts.map +1 -0
- package/dist/syncing-ledger.js +53 -0
- package/dist/syncing-ledger.js.map +1 -0
- package/dist/temp-fixtures.d.ts +68 -0
- package/dist/temp-fixtures.d.ts.map +1 -0
- package/dist/temp-fixtures.js +38 -0
- package/dist/temp-fixtures.js.map +1 -0
- package/dist/token-window.d.ts +84 -0
- package/dist/token-window.d.ts.map +1 -0
- package/dist/token-window.js +143 -0
- package/dist/token-window.js.map +1 -0
- package/dist/tool-bridge.d.ts +177 -0
- package/dist/tool-bridge.d.ts.map +1 -0
- package/dist/tool-bridge.js +329 -0
- package/dist/tool-bridge.js.map +1 -0
- package/dist/tool-call-record.d.ts +197 -0
- package/dist/tool-call-record.d.ts.map +1 -0
- package/dist/tool-call-record.js +276 -0
- package/dist/tool-call-record.js.map +1 -0
- package/dist/tool-protocol.d.ts +135 -0
- package/dist/tool-protocol.d.ts.map +1 -0
- package/dist/tool-protocol.js +104 -0
- package/dist/tool-protocol.js.map +1 -0
- package/dist/tool-worker.d.ts +3 -0
- package/dist/tool-worker.d.ts.map +1 -0
- package/dist/tool-worker.js +478 -0
- package/dist/tool-worker.js.map +1 -0
- package/dist/toolchain-mirror.d.ts +86 -0
- package/dist/toolchain-mirror.d.ts.map +1 -0
- package/dist/toolchain-mirror.js +307 -0
- package/dist/toolchain-mirror.js.map +1 -0
- package/dist/trusted-git.d.ts +243 -0
- package/dist/trusted-git.d.ts.map +1 -0
- package/dist/trusted-git.js +920 -0
- package/dist/trusted-git.js.map +1 -0
- package/dist/ui.d.ts +76 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +118 -0
- package/dist/ui.js.map +1 -0
- package/dist/untrusted-exec.d.ts +275 -0
- package/dist/untrusted-exec.d.ts.map +1 -0
- package/dist/untrusted-exec.js +479 -0
- package/dist/untrusted-exec.js.map +1 -0
- package/dist/untrusted-gate.d.ts +73 -0
- package/dist/untrusted-gate.d.ts.map +1 -0
- package/dist/untrusted-gate.js +226 -0
- package/dist/untrusted-gate.js.map +1 -0
- package/dist/uploader.d.ts +153 -0
- package/dist/uploader.d.ts.map +1 -0
- package/dist/uploader.js +204 -0
- package/dist/uploader.js.map +1 -0
- package/dist/verifier.d.ts +66 -0
- package/dist/verifier.d.ts.map +1 -0
- package/dist/verifier.js +170 -0
- package/dist/verifier.js.map +1 -0
- package/dist/verify-apply.d.ts +26 -0
- package/dist/verify-apply.d.ts.map +1 -0
- package/dist/verify-apply.js +36 -0
- package/dist/verify-apply.js.map +1 -0
- package/dist/verify-cmd.d.ts +44 -0
- package/dist/verify-cmd.d.ts.map +1 -0
- package/dist/verify-cmd.js +125 -0
- package/dist/verify-cmd.js.map +1 -0
- package/dist/verify-pass.d.ts +73 -0
- package/dist/verify-pass.d.ts.map +1 -0
- package/dist/verify-pass.js +103 -0
- package/dist/verify-pass.js.map +1 -0
- package/dist/welcome.d.ts +43 -0
- package/dist/welcome.d.ts.map +1 -0
- package/dist/welcome.js +116 -0
- package/dist/welcome.js.map +1 -0
- package/dist/workspace-provisioner.d.ts +65 -0
- package/dist/workspace-provisioner.d.ts.map +1 -0
- package/dist/workspace-provisioner.js +66 -0
- package/dist/workspace-provisioner.js.map +1 -0
- package/dist/workspace-quarantine.d.ts +64 -0
- package/dist/workspace-quarantine.d.ts.map +1 -0
- package/dist/workspace-quarantine.js +156 -0
- package/dist/workspace-quarantine.js.map +1 -0
- package/dist/workspace-residue-sweep.d.ts +113 -0
- package/dist/workspace-residue-sweep.d.ts.map +1 -0
- package/dist/workspace-residue-sweep.js +158 -0
- package/dist/workspace-residue-sweep.js.map +1 -0
- package/dist/workspace.d.ts +639 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +2026 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +54 -6
- package/win/CredProbe.cs +64 -0
- package/win/FakeClaude.cs +56 -0
- package/win/HandleProbe.cs +116 -0
- package/win/TokenProbe.cs +53 -0
- package/win/appcontainer.ps1 +500 -0
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_ADOPTED_ITEMS = exports.RunLauncher = exports.DEFAULT_SETTLE_MS = void 0;
|
|
4
|
+
exports.asStartResult = asStartResult;
|
|
5
|
+
exports.refuseStart = refuseStart;
|
|
6
|
+
exports.readStartPayload = readStartPayload;
|
|
7
|
+
exports.hoursFromPayload = hoursFromPayload;
|
|
8
|
+
exports.nodeRunLauncher = nodeRunLauncher;
|
|
9
|
+
const node_child_process_1 = require("node:child_process");
|
|
10
|
+
const node_path_1 = require("node:path");
|
|
11
|
+
const run_lease_1 = require("./run-lease");
|
|
12
|
+
const git_driver_1 = require("./git-driver");
|
|
13
|
+
const run_start_marks_1 = require("./run-start-marks");
|
|
14
|
+
const run_refusal_marks_1 = require("./run-refusal-marks");
|
|
15
|
+
const ledger_store_1 = require("./ledger-store");
|
|
16
|
+
/**
|
|
17
|
+
* The same answer, restated for a caller that must decide rather than report.
|
|
18
|
+
*
|
|
19
|
+
* A pure projection, so there is exactly one implementation of "what happened"
|
|
20
|
+
* and this is a view onto it — not a second opinion. The daemon's command
|
|
21
|
+
* handler keeps reading {@link LaunchResult} directly and is untouched.
|
|
22
|
+
*
|
|
23
|
+
* The two rules worth stating out loud:
|
|
24
|
+
*
|
|
25
|
+
* A terminal result with NO code is `blocked`, never `refused`. That covers
|
|
26
|
+
* every contention case and also the case where the run did refuse but its
|
|
27
|
+
* mark could not be read — in which case the honest answer is "I do not know
|
|
28
|
+
* why", and a caller that may end a person's grant on the strength of this
|
|
29
|
+
* must not be handed a guess.
|
|
30
|
+
*
|
|
31
|
+
* `started: true` without a runId is `pending`, not `run-started`. For a run
|
|
32
|
+
* that can only ever be true of a job held to no proof contract, and a
|
|
33
|
+
* controller that treated it as a Run would wait for an ending that no
|
|
34
|
+
* ledger will ever carry.
|
|
35
|
+
*/
|
|
36
|
+
function asStartResult(r) {
|
|
37
|
+
if (r.started) {
|
|
38
|
+
return r.runId === undefined
|
|
39
|
+
? { kind: 'pending', reason: 'a run is going here but has not proven itself yet' }
|
|
40
|
+
: { kind: 'run-started', runId: r.runId };
|
|
41
|
+
}
|
|
42
|
+
if ('waiting' in r)
|
|
43
|
+
return { kind: 'pending', reason: r.reason };
|
|
44
|
+
if ('terminal' in r) {
|
|
45
|
+
return r.code === undefined
|
|
46
|
+
? { kind: 'blocked', reason: r.reason }
|
|
47
|
+
: { kind: 'refused', code: r.code, reason: r.reason };
|
|
48
|
+
}
|
|
49
|
+
return { kind: 'failed', reason: r.reason };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Long enough for an ENOENT or an argument the CLI refuses outright to come
|
|
53
|
+
* back, short enough that the phone's tap still feels answered.
|
|
54
|
+
*/
|
|
55
|
+
exports.DEFAULT_SETTLE_MS = 750;
|
|
56
|
+
/**
|
|
57
|
+
* The exit code `looply run` uses for a refusal retrying cannot fix.
|
|
58
|
+
*
|
|
59
|
+
* A second declaration of run-cmd's `EXIT_REFUSED`, on purpose and not
|
|
60
|
+
* exported: the daemon's spawner must not import the composition root of the
|
|
61
|
+
* thing it spawns to read one number. The pairing is covered by tests on both
|
|
62
|
+
* sides — that run-cmd's constant is 3, and that a child exiting 3 is reported
|
|
63
|
+
* terminal here.
|
|
64
|
+
*/
|
|
65
|
+
const EXIT_REFUSED = 3;
|
|
66
|
+
/**
|
|
67
|
+
* The child's door for "another process already owns this exact attempt".
|
|
68
|
+
*
|
|
69
|
+
* A second declaration of run-cmd's `EXIT_ATTEMPT_CLAIMED`, on purpose and for
|
|
70
|
+
* the same reason `EXIT_REFUSED` is one: the spawner must not import the
|
|
71
|
+
* composition root of the thing it spawns to read a number. Both sides are
|
|
72
|
+
* pinned.
|
|
73
|
+
*
|
|
74
|
+
* Reported terminal for this poll but WITHOUT a code, so it reads as `blocked`
|
|
75
|
+
* and never as a statement about the goal. Nothing happened to the work; two
|
|
76
|
+
* processes simply arrived at the same instant.
|
|
77
|
+
*/
|
|
78
|
+
const EXIT_ATTEMPT_CLAIMED = 4;
|
|
79
|
+
class RunLauncher {
|
|
80
|
+
deps;
|
|
81
|
+
/**
|
|
82
|
+
* Job name → the child believed to still be running. Absent once it exits.
|
|
83
|
+
*
|
|
84
|
+
* It remembers `goalId` because "a run is already going" is no longer a
|
|
85
|
+
* complete answer: a second start-run naming a DIFFERENT goal is a different
|
|
86
|
+
* request, and answering it with the run that is already here would ack a goal
|
|
87
|
+
* that never ran.
|
|
88
|
+
*/
|
|
89
|
+
live = new Map();
|
|
90
|
+
/**
|
|
91
|
+
* How a child this launcher spawned actually ended, by the command that asked
|
|
92
|
+
* for it.
|
|
93
|
+
*
|
|
94
|
+
* The child is detached and unref'd, so `launch` has long returned by the time
|
|
95
|
+
* it exits — and under the old contract nobody ever read the exit code again.
|
|
96
|
+
* A run that refuses its goal after a second of preflight exits 3, and this is
|
|
97
|
+
* what carries that answer to the next poll.
|
|
98
|
+
*
|
|
99
|
+
* In memory only, and deliberately: it is an optimisation, not the record. A
|
|
100
|
+
* daemon restart forgets, relaunches once, and the child refuses again — one
|
|
101
|
+
* wasted spawn rather than a wrong ack.
|
|
102
|
+
*/
|
|
103
|
+
ended = new Map();
|
|
104
|
+
constructor(deps) {
|
|
105
|
+
this.deps = deps;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* What to tell the daemon a terminal refusal was, given what this process saw.
|
|
109
|
+
*
|
|
110
|
+
* `fallback` is what the launcher can see by itself — an exit code — and it
|
|
111
|
+
* is what shipped before the run could say more. The run's own reason is
|
|
112
|
+
* preferred whenever it left one for THIS command: the whole point is that
|
|
113
|
+
* "the run exited — exit 3" and "this goal's work is done" are not the same
|
|
114
|
+
* answer to somebody waiting on their phone.
|
|
115
|
+
*
|
|
116
|
+
* Keyed by command id, so a refusal can only ever be reported against the
|
|
117
|
+
* request that produced it. Never throws: a reason that cannot be read leaves
|
|
118
|
+
* the refusal exactly as truthful as it was, just less specific.
|
|
119
|
+
*/
|
|
120
|
+
async refusalMark(requestId) {
|
|
121
|
+
if (requestId === undefined || !this.deps.refusalOf)
|
|
122
|
+
return null;
|
|
123
|
+
try {
|
|
124
|
+
return await this.deps.refusalOf(requestId);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Never throws. A reason that cannot be read leaves the refusal exactly
|
|
128
|
+
// as truthful as it was, just less specific — and, importantly, without a
|
|
129
|
+
// code, so nothing downstream may conclude anything from it.
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Is any run live in this process?
|
|
135
|
+
*
|
|
136
|
+
* ⚠️ ANY CHECKOUT, NOT ONLY THE MAIN ONE. Job keys are `run` for an unplaced
|
|
137
|
+
* run and `run:<workspace>` for one a coordinator placed, and a caller asking
|
|
138
|
+
* "is a run going" means any of them.
|
|
139
|
+
*/
|
|
140
|
+
isRunning() {
|
|
141
|
+
return [...this.live.keys()].some((k) => k === 'run' || k.startsWith('run:'));
|
|
142
|
+
}
|
|
143
|
+
async start(req) {
|
|
144
|
+
const { requestId } = req;
|
|
145
|
+
/**
|
|
146
|
+
* 🔴 A REFUSAL OUTRANKS A RECEIPT, AND IT HAS TO NOW THAT THE RECEIPT IS
|
|
147
|
+
* HONEST ABOUT WHEN A RUN BEGAN.
|
|
148
|
+
*
|
|
149
|
+
* The receipt used to be written at `run.started`, which is after every
|
|
150
|
+
* refusal that can still speak for the goal — so nothing could ever hold
|
|
151
|
+
* both. It is now written when the run REGISTERS (see `run-cmd`, at
|
|
152
|
+
* `registry.register`), because that is when "a Run exists" becomes true,
|
|
153
|
+
* and six terminal refusals live downstream of it: a superseded goal, an
|
|
154
|
+
* adoption failure, a finished work set, a stalled one.
|
|
155
|
+
*
|
|
156
|
+
* Read in this order, a run that registered and then refused reports the
|
|
157
|
+
* REFUSAL — the more specific statement, and the only arm that may ever
|
|
158
|
+
* end a person's grant. Read the other way round it would report
|
|
159
|
+
* `run-started`, and a goal that asked for a human would be quietly
|
|
160
|
+
* retried instead.
|
|
161
|
+
*
|
|
162
|
+
* ⚠️ AND IT IS CORRECT IN EVERY ORDER. A refusal before registration has
|
|
163
|
+
* no receipt to outrank; a receipt with no refusal is a run that began and
|
|
164
|
+
* did not decide, which is exactly `run-started`.
|
|
165
|
+
*/
|
|
166
|
+
const refusedFirst = await this.refusalMark(requestId);
|
|
167
|
+
if (refusedFirst?.code !== undefined)
|
|
168
|
+
return terminalOf(refusedFirst, refusedFirst.reason);
|
|
169
|
+
// Proven next, and durably. This is the only thing that may report
|
|
170
|
+
// `started`, and it is also what makes a repeat of the SAME request
|
|
171
|
+
// idempotent after the child has gone: no lease, no live child, but the run
|
|
172
|
+
// it asked for demonstrably happened.
|
|
173
|
+
if (this.deps.provenStart) {
|
|
174
|
+
const mark = await this.deps.provenStart(requestId);
|
|
175
|
+
if (mark)
|
|
176
|
+
return { started: true, already: true, pid: undefined, runId: mark.runId };
|
|
177
|
+
}
|
|
178
|
+
// How the child this request already spawned ended, if it has. Read before
|
|
179
|
+
// the lease, because a child that refused has released whatever it held and
|
|
180
|
+
// would otherwise look like a free tree to relaunch into.
|
|
181
|
+
const ended = this.ended.get(requestId);
|
|
182
|
+
if (ended) {
|
|
183
|
+
return ended.terminal
|
|
184
|
+
? terminalOf(await this.refusalMark(requestId), ended.reason)
|
|
185
|
+
: { started: false, reason: ended.reason };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 🔴 THE JOB KEY IS THE CHECKOUT, NOT THE WORD "run".
|
|
189
|
+
*
|
|
190
|
+
* `live` was keyed by the literal `'run'`, so the SECOND launch of a cadence
|
|
191
|
+
* found the first and reported "the run this asked for is still starting" —
|
|
192
|
+
* one run per daemon, for ever, whatever the scheduler decided. The
|
|
193
|
+
* contended resource is a WORKING TREE, and two runs in two trees contend
|
|
194
|
+
* over nothing.
|
|
195
|
+
*
|
|
196
|
+
* ⚠️ WITH NO WORKSPACE THE KEY IS STILL EXACTLY `'run'`, so the phone's
|
|
197
|
+
* Start and a single-checkout daemon keep the one-run-per-project behaviour
|
|
198
|
+
* they have always had.
|
|
199
|
+
*/
|
|
200
|
+
const job = req.workspace === undefined ? 'run' : `run:${req.workspace}`;
|
|
201
|
+
return this.launch(job, [
|
|
202
|
+
'run',
|
|
203
|
+
...(req.hours !== undefined ? ['--hours', String(req.hours)] : []),
|
|
204
|
+
// WHERE THIS EXECUTION RUNS — Phase 1's own parallel interface, used by
|
|
205
|
+
// the coordinator exactly as a person uses it: a second isolated
|
|
206
|
+
// execution is a second `looply run` in a second workspace.
|
|
207
|
+
...(req.workspace === undefined ? [] : ['--in', req.workspace]),
|
|
208
|
+
// Carried into the run's lease, so a repeated Start can be told apart
|
|
209
|
+
// from a second request for another run.
|
|
210
|
+
//
|
|
211
|
+
// The FLAG keeps its name while the value generalises, for the same
|
|
212
|
+
// reason the mark files keep theirs: it is the established wire between
|
|
213
|
+
// this daemon and the child it spawns, renaming it buys nothing a
|
|
214
|
+
// comment cannot, and every durable record already written is keyed
|
|
215
|
+
// this way.
|
|
216
|
+
'--command-id',
|
|
217
|
+
requestId,
|
|
218
|
+
// The goal this run is for, on the same argv channel. The daemon only
|
|
219
|
+
// CARRIES these three; the run process is what resolves the goal,
|
|
220
|
+
// decides whether the mirrored version is fresh enough to act on, and
|
|
221
|
+
// adopts the items. Splitting that judgement across two processes is
|
|
222
|
+
// how the two would come to disagree.
|
|
223
|
+
// Only an autonomous Start counts its tries, so only an autonomous
|
|
224
|
+
// Start carries the number. A human Start's argv is byte-identical to
|
|
225
|
+
// what it has always been.
|
|
226
|
+
//
|
|
227
|
+
// `--autonomous` carries the ONE fact the run needs about who asked:
|
|
228
|
+
// whether beginning it counts as a person saying go. Not the
|
|
229
|
+
// controller id, not the ordinal, not the grant — none of that is the
|
|
230
|
+
// run's business, and sending it would put controller vocabulary
|
|
231
|
+
// inside a process that must stay blind to it.
|
|
232
|
+
...(req.origin.kind === 'autonomy'
|
|
233
|
+
? ['--request-attempt', String(req.origin.attempt), '--autonomous']
|
|
234
|
+
: []),
|
|
235
|
+
...(req.resumedFromApprovalId !== undefined
|
|
236
|
+
? ['--resumed-from-approval', req.resumedFromApprovalId]
|
|
237
|
+
: []),
|
|
238
|
+
// The exact approved action this Start was accepted to carry out. The
|
|
239
|
+
// daemon CARRIES it and proves nothing about it; the run checks it
|
|
240
|
+
// against the reservation the Start gate wrote.
|
|
241
|
+
...(req.governedApprovalId !== undefined
|
|
242
|
+
? ['--governed-approval', req.governedApprovalId]
|
|
243
|
+
: []),
|
|
244
|
+
...(req.goalId !== undefined ? ['--goal-id', req.goalId] : []),
|
|
245
|
+
...(req.goalVersion !== undefined ? ['--goal-version', String(req.goalVersion)] : []),
|
|
246
|
+
...(req.itemIds !== undefined ? ['--item-ids', req.itemIds.join(',')] : []),
|
|
247
|
+
], { commandId: requestId, goalId: req.goalId },
|
|
248
|
+
// A run has a start boundary that can be proven — `run.started` in the
|
|
249
|
+
// ledger — so it is held to it.
|
|
250
|
+
true, req.workspace);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* `looply scan`, as a child, so the lens passes stream into the ledger and
|
|
254
|
+
* reach the phone rather than being twenty silent minutes.
|
|
255
|
+
*/
|
|
256
|
+
async scan() {
|
|
257
|
+
// Deliberately NOT held to the proof contract, and the one place the two
|
|
258
|
+
// protocols differ. A scan has no start boundary to prove: it emits
|
|
259
|
+
// `scan.started` but nothing downstream binds a command to it, and unlike a
|
|
260
|
+
// run it leaves nothing half-done — a scan that dies writes no items, and
|
|
261
|
+
// the next one simply does the work again. Holding it to a proof it cannot
|
|
262
|
+
// produce would leave every scan command unacked until it expired.
|
|
263
|
+
return this.launch('scan', ['scan']);
|
|
264
|
+
}
|
|
265
|
+
async launch(job, args, want = {},
|
|
266
|
+
/** Whether this job can produce durable evidence that it started. */
|
|
267
|
+
provable = false,
|
|
268
|
+
/** The checkout this run is for, when a coordinator placed it there. */
|
|
269
|
+
workspace) {
|
|
270
|
+
// Two of the same job on one repo would fight over the same files: two runs
|
|
271
|
+
// over one branch and working tree, two scans over one queue.json. This
|
|
272
|
+
// reports started rather than refusing: the phone asked for the job to be in
|
|
273
|
+
// progress and it is, and a refusal would leave the command unacked to be
|
|
274
|
+
// retried against the job already doing what was asked.
|
|
275
|
+
const running = this.live.get(job);
|
|
276
|
+
if (running) {
|
|
277
|
+
const clash = refuseStart(want, running);
|
|
278
|
+
if (clash)
|
|
279
|
+
return { started: false, terminal: true, reason: clash };
|
|
280
|
+
// A child for this same request is already going and has not proven
|
|
281
|
+
// itself yet — the proven check above would have caught it if it had.
|
|
282
|
+
// Waiting, NOT started: this is exactly the moment the old contract lied.
|
|
283
|
+
return provable
|
|
284
|
+
? { started: false, waiting: true, reason: `the ${job} this asked for is still starting` }
|
|
285
|
+
: { started: true, already: true, pid: running.pid };
|
|
286
|
+
}
|
|
287
|
+
// The durable half of the same question. The map above only remembers what
|
|
288
|
+
// *this* daemon started; after a restart it is empty, and a redelivered
|
|
289
|
+
// start-run would spawn a second runner over a tree the first is still
|
|
290
|
+
// editing. The lease outlives the daemon, so it answers correctly.
|
|
291
|
+
/**
|
|
292
|
+
* ⚠️ THE LEASE OF THE CHECKOUT THIS RUN IS FOR. With no workspace that is
|
|
293
|
+
* the project's own, which is exactly what it has always been — and asking
|
|
294
|
+
* the project's lease about a second workspace is asking the wrong file: a
|
|
295
|
+
* live run in the main checkout refused a launch into an empty workspace
|
|
296
|
+
* beside it, which is the single-run behaviour that made N-way scheduling
|
|
297
|
+
* impossible however the scheduler decided.
|
|
298
|
+
*/
|
|
299
|
+
const peek = workspace !== undefined && this.deps.peekLeaseAt
|
|
300
|
+
? () => this.deps.peekLeaseAt(workspace)
|
|
301
|
+
: this.deps.peekLease;
|
|
302
|
+
if (job.startsWith('run') && peek) {
|
|
303
|
+
const state = await peek();
|
|
304
|
+
if (state.kind === 'active') {
|
|
305
|
+
// Already doing what the phone asked. Reported as started rather than
|
|
306
|
+
// refused, so the command is acknowledged instead of retried against
|
|
307
|
+
// the very run that is already satisfying it.
|
|
308
|
+
//
|
|
309
|
+
// Unless it is NOT what was asked. The lease records the goal the live
|
|
310
|
+
// run is bound to and it outlives this daemon, so this is the answer
|
|
311
|
+
// that still works after a restart, when the map above is empty.
|
|
312
|
+
const clash = refuseStart(want, {
|
|
313
|
+
commandId: state.lease.startedByCommandId,
|
|
314
|
+
goalId: state.lease.goalId,
|
|
315
|
+
});
|
|
316
|
+
if (clash)
|
|
317
|
+
return { started: false, terminal: true, reason: clash };
|
|
318
|
+
// The lease says a run for this request holds the tree. That is NOT
|
|
319
|
+
// proof it started: the lease is taken before adoption and before
|
|
320
|
+
// verification, either of which can still end the process without a
|
|
321
|
+
// Run. Only the mark above proves it, and it did not.
|
|
322
|
+
return {
|
|
323
|
+
started: false,
|
|
324
|
+
waiting: true,
|
|
325
|
+
reason: `a run for this request holds the tree and has not started yet`,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (state.kind === 'ambiguous') {
|
|
329
|
+
// Cannot prove nothing is running here. Terminal, not retryable: an
|
|
330
|
+
// hour of three-second retries would not make it any more decidable,
|
|
331
|
+
// and starting anyway is the failure this whole mechanism prevents.
|
|
332
|
+
return { started: false, terminal: true, reason: (0, run_lease_1.describeLease)(state) };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
let failure = null;
|
|
336
|
+
let refused = false;
|
|
337
|
+
/** The child lost the attempt race. Terminal for this poll, never semantic. */
|
|
338
|
+
let claimed = false;
|
|
339
|
+
/** Keep the child's answer for the next poll, since `launch` has returned by then. */
|
|
340
|
+
const remember = (terminal, reason) => {
|
|
341
|
+
if (want.commandId !== undefined && !this.ended.has(want.commandId)) {
|
|
342
|
+
this.ended.set(want.commandId, { terminal, reason });
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const handle = this.deps.spawn(args);
|
|
346
|
+
const live = { pid: handle.pid, ...want };
|
|
347
|
+
this.live.set(job, live);
|
|
348
|
+
const clear = () => {
|
|
349
|
+
// Only if it is still *this* child: a late exit from a previous job must
|
|
350
|
+
// not clear the slot a newer one is holding.
|
|
351
|
+
if (this.live.get(job) === live)
|
|
352
|
+
this.live.delete(job);
|
|
353
|
+
};
|
|
354
|
+
// First reason wins — error-then-exit is one failure, reported once.
|
|
355
|
+
handle.onError((e) => {
|
|
356
|
+
failure ??= `could not start the ${job}: ${e.message}`;
|
|
357
|
+
remember(false, failure);
|
|
358
|
+
clear();
|
|
359
|
+
});
|
|
360
|
+
handle.onExit((code) => {
|
|
361
|
+
// Not a refusal, and not a failure worth retrying on its own: the winner
|
|
362
|
+
// is doing the work right now. Terminal for this poll, uncoded, so the
|
|
363
|
+
// caller reads `blocked` and asks again later about the request rather
|
|
364
|
+
// than about this attempt.
|
|
365
|
+
if (code === EXIT_ATTEMPT_CLAIMED) {
|
|
366
|
+
claimed = true;
|
|
367
|
+
failure ??= `another process is already executing this attempt`;
|
|
368
|
+
remember(true, failure);
|
|
369
|
+
clear();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
// The child's own door for a refusal it will not take back: a goal that
|
|
373
|
+
// was abandoned, a version that moved on, items that cannot be adopted.
|
|
374
|
+
// Retrying those every three seconds for the rest of the redelivery
|
|
375
|
+
// window is noise, so this is reported terminal rather than failed.
|
|
376
|
+
if (code === EXIT_REFUSED)
|
|
377
|
+
refused = true;
|
|
378
|
+
// Not "immediately" any more: this fires whenever the child ends, which
|
|
379
|
+
// may be long after the settle window. That is the whole point — the
|
|
380
|
+
// answer is kept for the next poll instead of being thrown away.
|
|
381
|
+
failure ??= `the ${job} exited — ${code === null ? 'killed by a signal' : `exit ${code}`}`;
|
|
382
|
+
remember(code === EXIT_REFUSED, failure);
|
|
383
|
+
clear();
|
|
384
|
+
});
|
|
385
|
+
// Still a wait, and still worth having: an ENOENT or a config the CLI
|
|
386
|
+
// refuses outright comes back inside it, and answering the phone in one
|
|
387
|
+
// tick beats answering in the next poll. But NOTHING depends on it any
|
|
388
|
+
// more. Surviving it is not evidence of anything; it only means no answer
|
|
389
|
+
// has arrived yet.
|
|
390
|
+
await this.deps.sleep(this.deps.settleMs ?? exports.DEFAULT_SETTLE_MS);
|
|
391
|
+
if (failure !== null) {
|
|
392
|
+
// Both doors reach the same answer. A run that refuses fast — an
|
|
393
|
+
// abandoned goal, a stale version — exits inside the settle window and
|
|
394
|
+
// returns here; one that refuses after preflight returns through the
|
|
395
|
+
// remembered path above. Enriching only one of them would make the
|
|
396
|
+
// reason depend on how quickly the child made up its mind.
|
|
397
|
+
// A lost attempt is terminal for this poll and carries NO code, so it
|
|
398
|
+
// reads as blocked rather than as anything about the goal. It is checked
|
|
399
|
+
// before the refusal path because the loser wrote no mark to read.
|
|
400
|
+
if (claimed)
|
|
401
|
+
return { started: false, terminal: true, reason: failure };
|
|
402
|
+
return refused
|
|
403
|
+
? terminalOf(await this.refusalMark(want.commandId), failure)
|
|
404
|
+
: { started: false, reason: failure };
|
|
405
|
+
}
|
|
406
|
+
if (handle.pid === undefined) {
|
|
407
|
+
// No pid and no error: nothing to point at, so nothing to claim.
|
|
408
|
+
clear();
|
|
409
|
+
return { started: false, reason: `the ${job} process never started` };
|
|
410
|
+
}
|
|
411
|
+
handle.release();
|
|
412
|
+
return provable
|
|
413
|
+
? { started: false, waiting: true, reason: `the ${job} is starting`, spawnedPid: handle.pid }
|
|
414
|
+
: { started: true, already: false, pid: handle.pid };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
exports.RunLauncher = RunLauncher;
|
|
418
|
+
/**
|
|
419
|
+
* The run budget the phone asked for, if it asked for a sane one.
|
|
420
|
+
*
|
|
421
|
+
* The payload comes off the wire as `unknown` and goes onto a command line, so
|
|
422
|
+
* anything that is not a positive finite number is dropped in favour of the
|
|
423
|
+
* config's own budget rather than passed through to be refused by the child.
|
|
424
|
+
*/
|
|
425
|
+
/**
|
|
426
|
+
* A terminal LaunchResult built from whatever the run left behind.
|
|
427
|
+
*
|
|
428
|
+
* ONE place decides how a mark becomes a result, so the two paths that reach a
|
|
429
|
+
* terminal refusal — the child that exits inside the settle window and the one
|
|
430
|
+
* that exits long after it — cannot come to different answers. Enriching only
|
|
431
|
+
* one of them would make the reason a person reads depend on how quickly the
|
|
432
|
+
* child made up its mind.
|
|
433
|
+
*
|
|
434
|
+
* An empty reason is not a reason: it falls back to what the launcher itself
|
|
435
|
+
* could see. The CODE does not fall back, because there is nothing to fall back
|
|
436
|
+
* to — its absence is the honest report that this process cannot say which
|
|
437
|
+
* refusal happened.
|
|
438
|
+
*/
|
|
439
|
+
function terminalOf(mark, fallback) {
|
|
440
|
+
const reason = mark && mark.reason.trim() !== '' ? mark.reason : fallback;
|
|
441
|
+
return {
|
|
442
|
+
started: false,
|
|
443
|
+
terminal: true,
|
|
444
|
+
reason,
|
|
445
|
+
...(mark?.code === undefined ? {} : { code: mark.code }),
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Whether an already-running job answers the Start that just arrived.
|
|
450
|
+
*
|
|
451
|
+
* "A run is already going here" used to be a complete answer, and it was: both
|
|
452
|
+
* callers had asked for a run to be in progress, and one was. A goal makes it
|
|
453
|
+
* incomplete, and `itemIds` makes goal identity insufficient too — these are
|
|
454
|
+
* DIFFERENT requests:
|
|
455
|
+
*
|
|
456
|
+
* C1 goal G, items [A] C2 goal G, items [B]
|
|
457
|
+
*
|
|
458
|
+
* C2 is not satisfied because a G-bound run happens to exist; it asked for work
|
|
459
|
+
* that run will never pick. So the identity of a Start is its REQUEST, not its
|
|
460
|
+
* goal.
|
|
461
|
+
*
|
|
462
|
+
* That is sound for a human Start because the command row is durable and its
|
|
463
|
+
* payload cannot mutate after creation — the only writes to an existing row are
|
|
464
|
+
* the ack and the expiry sweep — so one command id means one unchanging request.
|
|
465
|
+
* It is sound for an autonomous Start for a different reason with the same
|
|
466
|
+
* force: `autonomyStartId(C, N)` is derived from a controller id and an ordinal
|
|
467
|
+
* whose reservation receipt is created with O_EXCL and never rewritten, so one
|
|
468
|
+
* request id there also means one unchanging request. Neither depends on the
|
|
469
|
+
* other, and the launcher does not need to know which it is holding.
|
|
470
|
+
*
|
|
471
|
+
* Returns the refusal text, or `null` when the live run genuinely satisfies it.
|
|
472
|
+
*/
|
|
473
|
+
function refuseStart(want, live) {
|
|
474
|
+
// Two unbound Starts are still the request they always were — "have a run in
|
|
475
|
+
// progress" — and one is. Left exactly as it was, so nothing about a manual
|
|
476
|
+
// or legacy run changes.
|
|
477
|
+
if (want.goalId === undefined && live.goalId === undefined)
|
|
478
|
+
return null;
|
|
479
|
+
// Same command: a redelivery of one durable row. Idempotent by construction.
|
|
480
|
+
if (want.commandId !== undefined && want.commandId === live.commandId)
|
|
481
|
+
return null;
|
|
482
|
+
const describe = (r) => (r.goalId === undefined ? 'no goal' : `goal ${r.goalId}`);
|
|
483
|
+
if (want.goalId !== live.goalId) {
|
|
484
|
+
return `a run is already going here for ${describe(live)}, and this asked for ${describe(want)} — stop it first`;
|
|
485
|
+
}
|
|
486
|
+
// Same goal, different command. The live run is bound to whatever items its
|
|
487
|
+
// own Start named, and will pick nothing else — so acking this one would
|
|
488
|
+
// promise work that is never going to happen.
|
|
489
|
+
return `a different run for ${describe(live)} is already going here — it will not pick this request's items, so stop it first`;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* How many items one Start may adopt.
|
|
493
|
+
*
|
|
494
|
+
* The adoption list travels to the run process on its command line, and an
|
|
495
|
+
* argv that exceeds the OS limit produces a spawn failure rather than a
|
|
496
|
+
* refusal — a command nobody can carry out and nobody can read. A bound the
|
|
497
|
+
* daemon states is better than one the kernel enforces.
|
|
498
|
+
*/
|
|
499
|
+
exports.MAX_ADOPTED_ITEMS = 200;
|
|
500
|
+
function readStartPayload(payload) {
|
|
501
|
+
const p = typeof payload === 'object' && payload !== null ? payload : {};
|
|
502
|
+
const hours = hoursFromPayload(payload);
|
|
503
|
+
const budget = hours === undefined ? {} : { hours };
|
|
504
|
+
if (p['goalId'] === undefined) {
|
|
505
|
+
// A legacy Start. Goal-shaped fields beside no goal are a payload this
|
|
506
|
+
// build cannot honour, not one it may quietly ignore: running them as an
|
|
507
|
+
// unbound run is exactly the silent widening this reader exists to stop.
|
|
508
|
+
if (p['goalVersion'] !== undefined || p['itemIds'] !== undefined) {
|
|
509
|
+
return { ok: false, problem: 'carries goal fields but names no goal' };
|
|
510
|
+
}
|
|
511
|
+
return { ok: true, start: budget };
|
|
512
|
+
}
|
|
513
|
+
const goalId = p['goalId'];
|
|
514
|
+
if (typeof goalId !== 'string' || goalId.length === 0) {
|
|
515
|
+
return { ok: false, problem: 'names a goal this build cannot read' };
|
|
516
|
+
}
|
|
517
|
+
// Required, not optional. The server stamps it on every goal-bound Start, so
|
|
518
|
+
// a payload naming a goal without one did not come from a server this build
|
|
519
|
+
// can reason about — and accepting it would mean running with no way to tell
|
|
520
|
+
// whether the local mirror of the goal is the one the phone was looking at.
|
|
521
|
+
const version = p['goalVersion'];
|
|
522
|
+
if (typeof version !== 'number' || !Number.isInteger(version) || version < 0) {
|
|
523
|
+
return { ok: false, problem: `names goal ${goalId} without a version this build can read` };
|
|
524
|
+
}
|
|
525
|
+
let itemIds;
|
|
526
|
+
if (p['itemIds'] !== undefined) {
|
|
527
|
+
const ids = p['itemIds'];
|
|
528
|
+
if (!Array.isArray(ids) || ids.some((i) => typeof i !== 'string' || i.length === 0)) {
|
|
529
|
+
return { ok: false, problem: `names items for goal ${goalId} this build cannot read` };
|
|
530
|
+
}
|
|
531
|
+
if (ids.length > exports.MAX_ADOPTED_ITEMS) {
|
|
532
|
+
return { ok: false, problem: `names ${ids.length} items for goal ${goalId}, more than the ${exports.MAX_ADOPTED_ITEMS} one start may adopt` };
|
|
533
|
+
}
|
|
534
|
+
// The list crosses to the run process comma-separated. Ids are minted
|
|
535
|
+
// without commas, but this reader does not get to assume what some other
|
|
536
|
+
// process minted — a comma inside one id would silently become two ids,
|
|
537
|
+
// and adopting an item nobody named is worse than refusing.
|
|
538
|
+
if (ids.some((i) => i.includes(','))) {
|
|
539
|
+
return { ok: false, problem: `names an item id for goal ${goalId} this build cannot carry` };
|
|
540
|
+
}
|
|
541
|
+
if (new Set(ids).size !== ids.length) {
|
|
542
|
+
return { ok: false, problem: `names the same item twice for goal ${goalId}` };
|
|
543
|
+
}
|
|
544
|
+
itemIds = ids;
|
|
545
|
+
}
|
|
546
|
+
return { ok: true, start: { ...budget, goalId, goalVersion: version, ...(itemIds === undefined ? {} : { itemIds }) } };
|
|
547
|
+
}
|
|
548
|
+
function hoursFromPayload(payload) {
|
|
549
|
+
if (typeof payload !== 'object' || payload === null || !('hours' in payload))
|
|
550
|
+
return undefined;
|
|
551
|
+
const h = payload.hours;
|
|
552
|
+
if (typeof h !== 'number' || !Number.isFinite(h) || h <= 0)
|
|
553
|
+
return undefined;
|
|
554
|
+
return h;
|
|
555
|
+
}
|
|
556
|
+
/* istanbul ignore next — real child processes; the logic lives in RunLauncher */
|
|
557
|
+
function nodeRunLauncher(cwd, stateDir) {
|
|
558
|
+
const leases = stateDir ? new run_lease_1.RunLeaseStore(stateDir, run_lease_1.nodeLeaseFs) : null;
|
|
559
|
+
/**
|
|
560
|
+
* 🔴 PROJECT-SCOPED, BECAUSE THESE ARE THE DAEMON↔RUN WIRE — AND EXECUTION
|
|
561
|
+
* SCOPING THEM ESCALATED EVERY COORDINATED GOAL TO A HUMAN.
|
|
562
|
+
*
|
|
563
|
+
* A LEASE is about a CHECKOUT: one run per working tree, so it belongs beside
|
|
564
|
+
* the tree, and `peekLeaseAt` below reads whichever tree is being launched
|
|
565
|
+
* into. A START MARK is about a REQUEST — durable proof that the Start the
|
|
566
|
+
* daemon asked for produced a Run — and the daemon is its only reader.
|
|
567
|
+
*
|
|
568
|
+
* MEASURED end to end: a coordinator-placed run wrote `run-starts.json` into
|
|
569
|
+
* its WORKSPACE, and the daemon read it from its own checkout. `provenStart`
|
|
570
|
+
* therefore answered null for every placed run, the launcher never reported
|
|
571
|
+
* `started`, and `autonomy-controller` concluded
|
|
572
|
+
*
|
|
573
|
+
* Start 1 was attempted 3 times and never began
|
|
574
|
+
*
|
|
575
|
+
* escalating a perfectly healthy goal to `human_required` — three cadences
|
|
576
|
+
* into every night, for every goal the coordinator placed.
|
|
577
|
+
*
|
|
578
|
+
* ⚠️ INVISIBLE IN A SINGLE CHECKOUT, which is why nothing caught it: there
|
|
579
|
+
* the project and execution state directories ARE the same path, so writer
|
|
580
|
+
* and reader agree by accident. It appears only once a run is placed
|
|
581
|
+
* somewhere else, which is the entire point of a coordinator.
|
|
582
|
+
*/
|
|
583
|
+
const project = (0, git_driver_1.projectStateDir)(cwd);
|
|
584
|
+
const marks = new run_start_marks_1.RunStartMarks(project, ledger_store_1.nodeLedgerFs);
|
|
585
|
+
const refusals = new run_refusal_marks_1.RunRefusalMarks(project, ledger_store_1.nodeLedgerFs);
|
|
586
|
+
return new RunLauncher({
|
|
587
|
+
...(leases ? { peekLease: () => leases.inspect() } : {}),
|
|
588
|
+
/**
|
|
589
|
+
* 🔴 THE LEASE OF THE CHECKOUT BEING LAUNCHED INTO.
|
|
590
|
+
*
|
|
591
|
+
* `peekLease` above answers about the project's own state directory and
|
|
592
|
+
* nothing else, so a live run in the main checkout refused every launch
|
|
593
|
+
* into an idle workspace beside it — the single-run behaviour that made
|
|
594
|
+
* N-way scheduling impossible however the scheduler decided.
|
|
595
|
+
*
|
|
596
|
+
* ⚠️ THE SAME `STATE_DIR` LAYOUT, addressed at another root: a workspace is
|
|
597
|
+
* a checkout, and a checkout's lease lives where every checkout's does.
|
|
598
|
+
*/
|
|
599
|
+
peekLeaseAt: (workspace) => new run_lease_1.RunLeaseStore((0, node_path_1.join)(workspace, git_driver_1.STATE_DIR, 'state'), run_lease_1.nodeLeaseFs).inspect(),
|
|
600
|
+
...(refusals
|
|
601
|
+
? {
|
|
602
|
+
// Re-read every time, for the same reason `provenStart` does: the
|
|
603
|
+
// file is written by another process, and the thing this is looking
|
|
604
|
+
// for happens after any snapshot taken before it.
|
|
605
|
+
refusalOf: async (requestId) => {
|
|
606
|
+
await refusals.load();
|
|
607
|
+
const mark = refusals.find(requestId);
|
|
608
|
+
if (mark === null)
|
|
609
|
+
return null;
|
|
610
|
+
// Reason AND code. The code is what lets a caller act on the
|
|
611
|
+
// refusal instead of merely reporting it.
|
|
612
|
+
return {
|
|
613
|
+
reason: mark.reason,
|
|
614
|
+
...(mark.code === undefined ? {} : { code: mark.code }),
|
|
615
|
+
};
|
|
616
|
+
},
|
|
617
|
+
}
|
|
618
|
+
: {}),
|
|
619
|
+
...(marks
|
|
620
|
+
? {
|
|
621
|
+
// Re-read every time. The file is written by another process — the run
|
|
622
|
+
// itself — so anything cached here would be a snapshot of the moment
|
|
623
|
+
// before the very thing it is looking for happened.
|
|
624
|
+
provenStart: async (requestId) => {
|
|
625
|
+
await marks.load();
|
|
626
|
+
return marks.find(requestId);
|
|
627
|
+
},
|
|
628
|
+
}
|
|
629
|
+
: {}),
|
|
630
|
+
spawn: (args) => {
|
|
631
|
+
// Re-invoke this same CLI rather than resolving `looply` on PATH: the
|
|
632
|
+
// daemon may well have been started through npx or a workspace link, and
|
|
633
|
+
// the child must be the same build as the daemon that spawned it.
|
|
634
|
+
const entry = process.argv[1];
|
|
635
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, entry ? [entry, ...args] : [...args], {
|
|
636
|
+
cwd,
|
|
637
|
+
// Detached and released, so Ctrl-C on the daemon does not take down a
|
|
638
|
+
// run mid-round and leave a half-built tree behind.
|
|
639
|
+
detached: true,
|
|
640
|
+
stdio: 'ignore',
|
|
641
|
+
});
|
|
642
|
+
return {
|
|
643
|
+
pid: child.pid,
|
|
644
|
+
onExit: (cb) => child.on('exit', (code) => cb(code)),
|
|
645
|
+
onError: (cb) => child.on('error', cb),
|
|
646
|
+
release: () => child.unref(),
|
|
647
|
+
};
|
|
648
|
+
},
|
|
649
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
//# sourceMappingURL=run-launcher.js.map
|