looply-cli 0.0.0-stage → 0.3.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 +2727 -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/serve-cmd.d.ts +115 -0
- package/dist/serve-cmd.d.ts.map +1 -0
- package/dist/serve-cmd.js +505 -0
- package/dist/serve-cmd.js.map +1 -0
- package/dist/serve.d.ts +167 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +336 -0
- package/dist/serve.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 +52 -4
- 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,152 @@
|
|
|
1
|
+
import type { AttemptFs } from './start-attempts';
|
|
2
|
+
/**
|
|
3
|
+
* ONE START CARRIES ONE APPROVED ACTION, AND THE KEY IT USES SURVIVES A CRASH.
|
|
4
|
+
*
|
|
5
|
+
* When an owner approves a consequential action, the pursuit does not resume by
|
|
6
|
+
* itself — a person's next Start picks it up, claims the authority on the
|
|
7
|
+
* server, and drives the one execution it buys. Two Starts could arrive for the
|
|
8
|
+
* same approval, so one of them has to win, and this is where.
|
|
9
|
+
*
|
|
10
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
* THE SAME MECHANISM AS `ApprovalResumes`, AND THE OPPOSITE ANSWER FOR THE LOSER
|
|
12
|
+
*
|
|
13
|
+
* A resume claim that loses is not a refusal: the other Start has the answer, so
|
|
14
|
+
* this one carries on as an ordinary Start. That is right for a DENIAL, where
|
|
15
|
+
* carrying on means planning around something.
|
|
16
|
+
*
|
|
17
|
+
* It is wrong here. A Start that lost the reservation for an APPROVED action and
|
|
18
|
+
* carried on as ordinary would be a run doing everything except the one thing
|
|
19
|
+
* the person authorised, while another run does that thing — two runs, one of
|
|
20
|
+
* them pointless, both holding budget. So the loser is REFUSED, and told why.
|
|
21
|
+
*
|
|
22
|
+
* The server's claim is still what makes a second EFFECT impossible; this only
|
|
23
|
+
* decides which Start is worth spending. Security below, liveness here, and
|
|
24
|
+
* neither pretending to be the other.
|
|
25
|
+
*
|
|
26
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
* WHY THE FILE IS READ BY THE LOSER RATHER THAN JUST REFUSING IT
|
|
28
|
+
*
|
|
29
|
+
* A machine can claim an approval and then die before recording an attempt, and
|
|
30
|
+
* the claim is not a lease — nothing takes it back. The only way that authority
|
|
31
|
+
* ever completes is if a later process can present the SAME claim key and reach
|
|
32
|
+
* the idempotent arm of the server's claim rules, which match on machine AND
|
|
33
|
+
* key. So the key can never be derived from anything belonging to the process
|
|
34
|
+
* that happened to go first.
|
|
35
|
+
*
|
|
36
|
+
* That rules out the run id: a recovering run is a new run, would present a new
|
|
37
|
+
* key, and would be told `already_claimed` — a dead claim, which is the one
|
|
38
|
+
* outcome the claim design exists to avoid. It rules out randomness and memory
|
|
39
|
+
* for the same reason.
|
|
40
|
+
*
|
|
41
|
+
* So the key derives from the RESERVATION: the Start that first reserved this
|
|
42
|
+
* approval, written down durably at the moment it reserved. A recovery Start
|
|
43
|
+
* reads the record, re-derives a byte-identical key, and continues the same
|
|
44
|
+
* authority instead of asking for a second one.
|
|
45
|
+
*
|
|
46
|
+
* NOTE THE CONTRAST WITH `approvalClientRef`, which is deliberately run-scoped
|
|
47
|
+
* so that the same action asked for on Monday and on Thursday is two questions.
|
|
48
|
+
* Asking for authority and taking it are different operations, and the schema
|
|
49
|
+
* keeps their keys apart for exactly this reason: they need opposite properties.
|
|
50
|
+
*/
|
|
51
|
+
export declare const GOVERNED_APPROVALS_SCHEMA = 1;
|
|
52
|
+
export interface GovernedReservation {
|
|
53
|
+
/** The approval this Start took responsibility for. */
|
|
54
|
+
approvalId: string;
|
|
55
|
+
/** The Start that took it. The claim key derives from this, for ever. */
|
|
56
|
+
requestId: string;
|
|
57
|
+
/** ISO, from the reserving process's own clock. */
|
|
58
|
+
reservedAt: string;
|
|
59
|
+
}
|
|
60
|
+
export type ReserveOutcome =
|
|
61
|
+
/** This Start holds it. Use `claimRefFor(reservation)`. */
|
|
62
|
+
{
|
|
63
|
+
readonly ok: true;
|
|
64
|
+
readonly reservation: GovernedReservation;
|
|
65
|
+
readonly fresh: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Somebody else holds it.
|
|
69
|
+
*
|
|
70
|
+
* The record comes back anyway, because whether this is a race or a recovery
|
|
71
|
+
* is not a question this file can answer — it depends on what the SERVER says
|
|
72
|
+
* about the approval, which only the caller can ask. What is guaranteed is
|
|
73
|
+
* that the key in hand is the one the original Start used.
|
|
74
|
+
*/
|
|
75
|
+
| {
|
|
76
|
+
readonly ok: false;
|
|
77
|
+
readonly held: GovernedReservation;
|
|
78
|
+
readonly because: string;
|
|
79
|
+
}
|
|
80
|
+
/** The record exists and cannot be read. Never treated as absent. */
|
|
81
|
+
| {
|
|
82
|
+
readonly ok: false;
|
|
83
|
+
readonly held: null;
|
|
84
|
+
readonly because: string;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* THE CLAIM KEY, DERIVED AND NEVER CHOSEN.
|
|
88
|
+
*
|
|
89
|
+
* Two durable values and nothing else. Both are written down before any claim
|
|
90
|
+
* is attempted, so any later process holding the reservation computes the same
|
|
91
|
+
* string — which is precisely what the server's idempotent claim arm needs.
|
|
92
|
+
*
|
|
93
|
+
* The model reaches neither half.
|
|
94
|
+
*/
|
|
95
|
+
export declare function claimRefFor(reservation: GovernedReservation): string;
|
|
96
|
+
export declare class GovernedApprovals {
|
|
97
|
+
private readonly stateDir;
|
|
98
|
+
private readonly fs;
|
|
99
|
+
private readonly deps;
|
|
100
|
+
/** Distinguishes two temp files written by one process. See `takeOver`. */
|
|
101
|
+
private static writes;
|
|
102
|
+
constructor(stateDir: string, fs: AttemptFs, deps?: {
|
|
103
|
+
now?: () => number;
|
|
104
|
+
});
|
|
105
|
+
private get dir();
|
|
106
|
+
private path;
|
|
107
|
+
/**
|
|
108
|
+
* Take responsibility for carrying this approved action out, if nobody has.
|
|
109
|
+
*
|
|
110
|
+
* `createExclusive` is the whole mechanism: the operating system hands the
|
|
111
|
+
* file to exactly one caller, and the loser finds out from the filesystem
|
|
112
|
+
* rather than from a read it took a moment earlier. An in-process guard would
|
|
113
|
+
* not survive two daemons, or one daemon and a person at a terminal.
|
|
114
|
+
*/
|
|
115
|
+
reserve(approvalId: string, requestId: string): Promise<ReserveOutcome>;
|
|
116
|
+
/**
|
|
117
|
+
* TAKE A RESERVATION OVER FOR A LATER START, WHEN THE SERVER SAYS THE FIRST
|
|
118
|
+
* ONE IS GONE.
|
|
119
|
+
*
|
|
120
|
+
* `reserve` is one-shot on purpose: a second Start finding a record is
|
|
121
|
+
* normally a RACE, and letting it win would mean two runs carrying one
|
|
122
|
+
* authority. But the same one-shot record also wedged every recovery. A Start
|
|
123
|
+
* that reserved an approval and died left a record no later Start could
|
|
124
|
+
* satisfy, `runGovernedAction` refuses a reservation naming a different Start,
|
|
125
|
+
* and the approval stayed `claimed` for ever — so nothing could ever go and
|
|
126
|
+
* look at an attempt nobody finished.
|
|
127
|
+
*
|
|
128
|
+
* 🔴 THE CALLER MUST HAVE ASKED THE SERVER FIRST. This is only correct where
|
|
129
|
+
* the gate says `claimed`, `executing` or `result-pending` — i.e. where the
|
|
130
|
+
* server has ALREADY recorded that authority was taken. That is not a
|
|
131
|
+
* courtesy; it is what makes the rewrite harmless:
|
|
132
|
+
*
|
|
133
|
+
* - the claim key derives from the reservation, and it MUST stay
|
|
134
|
+
* byte-identical for the server's idempotent claim arm;
|
|
135
|
+
* - but `runGovernedAction` only ever computes that key on the `approved`
|
|
136
|
+
* branch. Where the approval is already `claimed` it takes `claimId` from
|
|
137
|
+
* the SERVER and never looks at the derived one.
|
|
138
|
+
*
|
|
139
|
+
* So on exactly the arms this is allowed for, the key it changes is a key
|
|
140
|
+
* nothing reads. On the arm where the key matters, `reserve` still refuses.
|
|
141
|
+
*
|
|
142
|
+
* ⚠️ AND IT DOES NOT WEAKEN THE C5 CHAIN. The chain is "the DAEMON wrote a
|
|
143
|
+
* reservation naming the Start it is about to spawn"; argv still proves
|
|
144
|
+
* nothing, and the boundary being defended — the MODEL, which cannot reach
|
|
145
|
+
* `.looply/state`, cannot spawn a run and cannot see this file — is untouched.
|
|
146
|
+
* What changes is only that the daemon may write that record twice.
|
|
147
|
+
*/
|
|
148
|
+
takeOver(approvalId: string, requestId: string): Promise<ReserveOutcome>;
|
|
149
|
+
/** What was reserved for this approval, or null. Unreadable is null, not a throw. */
|
|
150
|
+
reservationOf(approvalId: string): Promise<GovernedReservation | null>;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=governed-approvals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governed-approvals.d.ts","sourceRoot":"","sources":["../src/governed-approvals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAK3C,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,MAAM,MAAM,cAAc;AACxB,2DAA2D;AACzD;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AAC3F;;;;;;;GAOG;GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACtF,qEAAqE;GACnE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAEpE;AAED,qBAAa,iBAAiB;IAK1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANvB,2EAA2E;IAC3E,OAAO,CAAC,MAAM,CAAC,MAAM,CAAK;gBAGP,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,SAAS,EACb,IAAI,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;KAAO;IAGpD,OAAO,KAAK,GAAG,GAEd;IAED,OAAO,CAAC,IAAI;IAIZ;;;;;;;OAOG;IACG,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6C7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmC9E,qFAAqF;IAC/E,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;CAK7E"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GovernedApprovals = exports.GOVERNED_APPROVALS_SCHEMA = void 0;
|
|
4
|
+
exports.claimRefFor = claimRefFor;
|
|
5
|
+
/**
|
|
6
|
+
* ONE START CARRIES ONE APPROVED ACTION, AND THE KEY IT USES SURVIVES A CRASH.
|
|
7
|
+
*
|
|
8
|
+
* When an owner approves a consequential action, the pursuit does not resume by
|
|
9
|
+
* itself — a person's next Start picks it up, claims the authority on the
|
|
10
|
+
* server, and drives the one execution it buys. Two Starts could arrive for the
|
|
11
|
+
* same approval, so one of them has to win, and this is where.
|
|
12
|
+
*
|
|
13
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
* THE SAME MECHANISM AS `ApprovalResumes`, AND THE OPPOSITE ANSWER FOR THE LOSER
|
|
15
|
+
*
|
|
16
|
+
* A resume claim that loses is not a refusal: the other Start has the answer, so
|
|
17
|
+
* this one carries on as an ordinary Start. That is right for a DENIAL, where
|
|
18
|
+
* carrying on means planning around something.
|
|
19
|
+
*
|
|
20
|
+
* It is wrong here. A Start that lost the reservation for an APPROVED action and
|
|
21
|
+
* carried on as ordinary would be a run doing everything except the one thing
|
|
22
|
+
* the person authorised, while another run does that thing — two runs, one of
|
|
23
|
+
* them pointless, both holding budget. So the loser is REFUSED, and told why.
|
|
24
|
+
*
|
|
25
|
+
* The server's claim is still what makes a second EFFECT impossible; this only
|
|
26
|
+
* decides which Start is worth spending. Security below, liveness here, and
|
|
27
|
+
* neither pretending to be the other.
|
|
28
|
+
*
|
|
29
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
30
|
+
* WHY THE FILE IS READ BY THE LOSER RATHER THAN JUST REFUSING IT
|
|
31
|
+
*
|
|
32
|
+
* A machine can claim an approval and then die before recording an attempt, and
|
|
33
|
+
* the claim is not a lease — nothing takes it back. The only way that authority
|
|
34
|
+
* ever completes is if a later process can present the SAME claim key and reach
|
|
35
|
+
* the idempotent arm of the server's claim rules, which match on machine AND
|
|
36
|
+
* key. So the key can never be derived from anything belonging to the process
|
|
37
|
+
* that happened to go first.
|
|
38
|
+
*
|
|
39
|
+
* That rules out the run id: a recovering run is a new run, would present a new
|
|
40
|
+
* key, and would be told `already_claimed` — a dead claim, which is the one
|
|
41
|
+
* outcome the claim design exists to avoid. It rules out randomness and memory
|
|
42
|
+
* for the same reason.
|
|
43
|
+
*
|
|
44
|
+
* So the key derives from the RESERVATION: the Start that first reserved this
|
|
45
|
+
* approval, written down durably at the moment it reserved. A recovery Start
|
|
46
|
+
* reads the record, re-derives a byte-identical key, and continues the same
|
|
47
|
+
* authority instead of asking for a second one.
|
|
48
|
+
*
|
|
49
|
+
* NOTE THE CONTRAST WITH `approvalClientRef`, which is deliberately run-scoped
|
|
50
|
+
* so that the same action asked for on Monday and on Thursday is two questions.
|
|
51
|
+
* Asking for authority and taking it are different operations, and the schema
|
|
52
|
+
* keeps their keys apart for exactly this reason: they need opposite properties.
|
|
53
|
+
*/
|
|
54
|
+
exports.GOVERNED_APPROVALS_SCHEMA = 1;
|
|
55
|
+
/** One trailing newline, spelled once so no template mangles the escape. */
|
|
56
|
+
const NEWLINE = String.fromCharCode(10);
|
|
57
|
+
/**
|
|
58
|
+
* THE CLAIM KEY, DERIVED AND NEVER CHOSEN.
|
|
59
|
+
*
|
|
60
|
+
* Two durable values and nothing else. Both are written down before any claim
|
|
61
|
+
* is attempted, so any later process holding the reservation computes the same
|
|
62
|
+
* string — which is precisely what the server's idempotent claim arm needs.
|
|
63
|
+
*
|
|
64
|
+
* The model reaches neither half.
|
|
65
|
+
*/
|
|
66
|
+
function claimRefFor(reservation) {
|
|
67
|
+
return `govern:${reservation.requestId}:${reservation.approvalId}`;
|
|
68
|
+
}
|
|
69
|
+
class GovernedApprovals {
|
|
70
|
+
stateDir;
|
|
71
|
+
fs;
|
|
72
|
+
deps;
|
|
73
|
+
/** Distinguishes two temp files written by one process. See `takeOver`. */
|
|
74
|
+
static writes = 0;
|
|
75
|
+
constructor(stateDir, fs, deps = {}) {
|
|
76
|
+
this.stateDir = stateDir;
|
|
77
|
+
this.fs = fs;
|
|
78
|
+
this.deps = deps;
|
|
79
|
+
}
|
|
80
|
+
get dir() {
|
|
81
|
+
return `${this.stateDir}/governed-approvals`;
|
|
82
|
+
}
|
|
83
|
+
path(approvalId) {
|
|
84
|
+
return `${this.dir}/${approvalId}.json`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Take responsibility for carrying this approved action out, if nobody has.
|
|
88
|
+
*
|
|
89
|
+
* `createExclusive` is the whole mechanism: the operating system hands the
|
|
90
|
+
* file to exactly one caller, and the loser finds out from the filesystem
|
|
91
|
+
* rather than from a read it took a moment earlier. An in-process guard would
|
|
92
|
+
* not survive two daemons, or one daemon and a person at a terminal.
|
|
93
|
+
*/
|
|
94
|
+
async reserve(approvalId, requestId) {
|
|
95
|
+
if (approvalId.length === 0)
|
|
96
|
+
return { ok: false, held: null, because: 'no approval was named' };
|
|
97
|
+
// Path safety, not validation theatre: the id becomes a filename, and an id
|
|
98
|
+
// carrying a separator would write outside the directory this owns.
|
|
99
|
+
if (/[^A-Za-z0-9_-]/.test(approvalId)) {
|
|
100
|
+
return { ok: false, held: null, because: `${approvalId} is not a usable approval id` };
|
|
101
|
+
}
|
|
102
|
+
if (requestId.length === 0) {
|
|
103
|
+
return { ok: false, held: null, because: 'no Start was named' };
|
|
104
|
+
}
|
|
105
|
+
const reservation = {
|
|
106
|
+
approvalId,
|
|
107
|
+
requestId,
|
|
108
|
+
reservedAt: new Date(this.deps.now?.() ?? Date.now()).toISOString(),
|
|
109
|
+
};
|
|
110
|
+
const body = { schema: exports.GOVERNED_APPROVALS_SCHEMA, reservation };
|
|
111
|
+
await this.fs.mkdir(this.dir);
|
|
112
|
+
try {
|
|
113
|
+
await this.fs.createExclusive(this.path(approvalId), JSON.stringify(body, null, 2) + '\n');
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
if (e.code !== 'EEXIST')
|
|
117
|
+
throw e;
|
|
118
|
+
const held = await this.reservationOf(approvalId);
|
|
119
|
+
if (held === null) {
|
|
120
|
+
// Present and unreadable. NOT treated as absent, and not overwritten:
|
|
121
|
+
// the file may name the key an in-flight claim is using, and inventing
|
|
122
|
+
// a new one would ask the server for a second authority.
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
held: null,
|
|
126
|
+
because: 'another Start holds this action and its record cannot be read',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (held.requestId === requestId) {
|
|
130
|
+
// This very Start, asking again. A dropped response, not a race.
|
|
131
|
+
return { ok: true, reservation: held, fresh: false };
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
held,
|
|
136
|
+
because: 'another Start is already carrying this action out',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return { ok: true, reservation, fresh: true };
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* TAKE A RESERVATION OVER FOR A LATER START, WHEN THE SERVER SAYS THE FIRST
|
|
143
|
+
* ONE IS GONE.
|
|
144
|
+
*
|
|
145
|
+
* `reserve` is one-shot on purpose: a second Start finding a record is
|
|
146
|
+
* normally a RACE, and letting it win would mean two runs carrying one
|
|
147
|
+
* authority. But the same one-shot record also wedged every recovery. A Start
|
|
148
|
+
* that reserved an approval and died left a record no later Start could
|
|
149
|
+
* satisfy, `runGovernedAction` refuses a reservation naming a different Start,
|
|
150
|
+
* and the approval stayed `claimed` for ever — so nothing could ever go and
|
|
151
|
+
* look at an attempt nobody finished.
|
|
152
|
+
*
|
|
153
|
+
* 🔴 THE CALLER MUST HAVE ASKED THE SERVER FIRST. This is only correct where
|
|
154
|
+
* the gate says `claimed`, `executing` or `result-pending` — i.e. where the
|
|
155
|
+
* server has ALREADY recorded that authority was taken. That is not a
|
|
156
|
+
* courtesy; it is what makes the rewrite harmless:
|
|
157
|
+
*
|
|
158
|
+
* - the claim key derives from the reservation, and it MUST stay
|
|
159
|
+
* byte-identical for the server's idempotent claim arm;
|
|
160
|
+
* - but `runGovernedAction` only ever computes that key on the `approved`
|
|
161
|
+
* branch. Where the approval is already `claimed` it takes `claimId` from
|
|
162
|
+
* the SERVER and never looks at the derived one.
|
|
163
|
+
*
|
|
164
|
+
* So on exactly the arms this is allowed for, the key it changes is a key
|
|
165
|
+
* nothing reads. On the arm where the key matters, `reserve` still refuses.
|
|
166
|
+
*
|
|
167
|
+
* ⚠️ AND IT DOES NOT WEAKEN THE C5 CHAIN. The chain is "the DAEMON wrote a
|
|
168
|
+
* reservation naming the Start it is about to spawn"; argv still proves
|
|
169
|
+
* nothing, and the boundary being defended — the MODEL, which cannot reach
|
|
170
|
+
* `.looply/state`, cannot spawn a run and cannot see this file — is untouched.
|
|
171
|
+
* What changes is only that the daemon may write that record twice.
|
|
172
|
+
*/
|
|
173
|
+
async takeOver(approvalId, requestId) {
|
|
174
|
+
const first = await this.reserve(approvalId, requestId);
|
|
175
|
+
// Free, or already ours. Nothing to take over, and no rewrite.
|
|
176
|
+
if (first.ok)
|
|
177
|
+
return first;
|
|
178
|
+
// Present and UNREADABLE is not taken over. It may name the key an
|
|
179
|
+
// in-flight claim is using, and this cannot tell that from a corrupt file.
|
|
180
|
+
if (first.held === null)
|
|
181
|
+
return first;
|
|
182
|
+
if (first.held.requestId === requestId)
|
|
183
|
+
return { ok: true, reservation: first.held, fresh: false };
|
|
184
|
+
const reservation = {
|
|
185
|
+
approvalId,
|
|
186
|
+
requestId,
|
|
187
|
+
reservedAt: new Date(this.deps.now?.() ?? Date.now()).toISOString(),
|
|
188
|
+
};
|
|
189
|
+
const body = { schema: exports.GOVERNED_APPROVALS_SCHEMA, reservation };
|
|
190
|
+
/**
|
|
191
|
+
* WRITTEN ASIDE AND RENAMED, NEVER IN PLACE.
|
|
192
|
+
*
|
|
193
|
+
* `writeFile` onto the live path truncates first, so a crash, a full disk or
|
|
194
|
+
* a killed daemon mid-write leaves a TORN reservation — and a torn one is
|
|
195
|
+
* unreadable, which both `reserve` and `takeOver` refuse for ever. The one
|
|
196
|
+
* operation added to recover a wedged approval would otherwise have been
|
|
197
|
+
* able to create a worse wedge than the one it fixes.
|
|
198
|
+
*
|
|
199
|
+
* The temp name is PRIVATE TO THIS WRITER, for the same reason
|
|
200
|
+
* `LedgerStore` makes its own: a shared `.tmp` is some other writer's
|
|
201
|
+
* half-written file, and renaming that over the real one is precisely the
|
|
202
|
+
* failure this exists to prevent.
|
|
203
|
+
*/
|
|
204
|
+
const tmp = `${this.path(approvalId)}.${process.pid}.${(GovernedApprovals.writes += 1)}.tmp`;
|
|
205
|
+
await this.fs.writeFile(tmp, JSON.stringify(body, null, 2) + NEWLINE);
|
|
206
|
+
await this.fs.rename(tmp, this.path(approvalId));
|
|
207
|
+
return { ok: true, reservation, fresh: true };
|
|
208
|
+
}
|
|
209
|
+
/** What was reserved for this approval, or null. Unreadable is null, not a throw. */
|
|
210
|
+
async reservationOf(approvalId) {
|
|
211
|
+
const text = await this.fs.readFile(this.path(approvalId));
|
|
212
|
+
if (text === null)
|
|
213
|
+
return null;
|
|
214
|
+
return readReservation(text);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.GovernedApprovals = GovernedApprovals;
|
|
218
|
+
function readReservation(text) {
|
|
219
|
+
let parsed;
|
|
220
|
+
try {
|
|
221
|
+
parsed = JSON.parse(text);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const file = parsed;
|
|
227
|
+
if (typeof file !== 'object' || file === null)
|
|
228
|
+
return null;
|
|
229
|
+
if (file.schema !== exports.GOVERNED_APPROVALS_SCHEMA)
|
|
230
|
+
return null;
|
|
231
|
+
const r = file.reservation;
|
|
232
|
+
if (typeof r !== 'object' || r === null)
|
|
233
|
+
return null;
|
|
234
|
+
if (typeof r['approvalId'] !== 'string' || r['approvalId'] === '')
|
|
235
|
+
return null;
|
|
236
|
+
if (typeof r['requestId'] !== 'string' || r['requestId'] === '')
|
|
237
|
+
return null;
|
|
238
|
+
if (typeof r['reservedAt'] !== 'string')
|
|
239
|
+
return null;
|
|
240
|
+
return {
|
|
241
|
+
approvalId: r['approvalId'],
|
|
242
|
+
requestId: r['requestId'],
|
|
243
|
+
reservedAt: r['reservedAt'],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=governed-approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governed-approvals.js","sourceRoot":"","sources":["../src/governed-approvals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { type ActionRequest, type BrokerOutcome, type ReconcileObservation } from '@looply/core';
|
|
2
|
+
import type { AttemptFs } from './start-attempts';
|
|
3
|
+
/**
|
|
4
|
+
* THE ONE THING IN LOOPLY THAT MAY CAUSE A CONSEQUENTIAL EFFECT.
|
|
5
|
+
*
|
|
6
|
+
* Everything before this point is about deciding: a model proposed an exact
|
|
7
|
+
* action, a person authorised it, one machine took the right to try, and the
|
|
8
|
+
* server minted one execution identity for that try. This is the try.
|
|
9
|
+
*
|
|
10
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
* IT TAKES AN ENVELOPE, AND AN ENVELOPE IS NOT AN ACTION
|
|
12
|
+
*
|
|
13
|
+
* The only input is what the SERVER returned when the execution was created:
|
|
14
|
+
* the action it holds, re-parsed and re-verified against the fingerprint a
|
|
15
|
+
* person approved. There is deliberately no overload that accepts an
|
|
16
|
+
* `ActionRequest`, a `PendingActionSignal`, or anything a run assembled — the
|
|
17
|
+
* signature is the boundary. A broker that could be handed an action by its
|
|
18
|
+
* caller is a broker that can be handed one action wearing the fingerprint of
|
|
19
|
+
* another, and every check upstream would still have passed.
|
|
20
|
+
*
|
|
21
|
+
* IT IS NOT MODEL-CALLABLE. There is no MCP tool for it, no tool name, and no
|
|
22
|
+
* path from `tool-bridge` to here. The model's entire surface is read, glob,
|
|
23
|
+
* grep, edit and write, inside a container, and none of those can reach this
|
|
24
|
+
* module or the place it writes.
|
|
25
|
+
*
|
|
26
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
* THREE ANSWERS, AND THE THIRD IS THE IMPORTANT ONE
|
|
28
|
+
*
|
|
29
|
+
* `success` means the effect is proven to exist. `failure` means it is proven
|
|
30
|
+
* NOT to exist. `ambiguous` means nobody can tell, and it is the honest answer
|
|
31
|
+
* to a timeout, a killed process, a connection that died mid-response, and any
|
|
32
|
+
* result this build does not recognise.
|
|
33
|
+
*
|
|
34
|
+
* Recording an ambiguous outcome as a failure is the single most dangerous lie
|
|
35
|
+
* available here, because a failure invites a retry and a retry of something
|
|
36
|
+
* that already happened is the duplicate effect this whole phase exists to
|
|
37
|
+
* prevent. No code path below produces `failure` from the absence of evidence.
|
|
38
|
+
*/
|
|
39
|
+
/** What the server said this execution is. Never assembled locally. */
|
|
40
|
+
export interface GovernedExecutionEnvelope {
|
|
41
|
+
executionId: string;
|
|
42
|
+
approvalId: string;
|
|
43
|
+
claimId: string;
|
|
44
|
+
projectId: string;
|
|
45
|
+
machineId: string;
|
|
46
|
+
actionFingerprint: string;
|
|
47
|
+
actionRequest: ActionRequest;
|
|
48
|
+
actionType: string;
|
|
49
|
+
display: string;
|
|
50
|
+
executionVersion: number;
|
|
51
|
+
executionState: string;
|
|
52
|
+
}
|
|
53
|
+
/** Bounded, deterministic where possible, and never secret. */
|
|
54
|
+
export interface BrokerEvidence {
|
|
55
|
+
readonly [key: string]: string | number | boolean;
|
|
56
|
+
}
|
|
57
|
+
export type BrokerResult = {
|
|
58
|
+
readonly kind: 'success';
|
|
59
|
+
readonly evidence: BrokerEvidence;
|
|
60
|
+
}
|
|
61
|
+
/** PROVEN not to have happened. Never inferred from silence. */
|
|
62
|
+
| {
|
|
63
|
+
readonly kind: 'failure';
|
|
64
|
+
readonly safeReason: string;
|
|
65
|
+
readonly evidence: BrokerEvidence;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: 'ambiguous';
|
|
68
|
+
readonly safeReason: string;
|
|
69
|
+
readonly evidence: BrokerEvidence;
|
|
70
|
+
};
|
|
71
|
+
export type ReconcileResult = {
|
|
72
|
+
readonly kind: 'observed-success';
|
|
73
|
+
readonly evidence: BrokerEvidence;
|
|
74
|
+
}
|
|
75
|
+
/** The executor's own evidence shows no effect. The ONLY arm that permits a retry. */
|
|
76
|
+
| {
|
|
77
|
+
readonly kind: 'observed-not-executed';
|
|
78
|
+
} | {
|
|
79
|
+
readonly kind: 'observed-failure';
|
|
80
|
+
readonly safeReason: string;
|
|
81
|
+
} | {
|
|
82
|
+
readonly kind: 'ambiguous';
|
|
83
|
+
readonly safeReason: string;
|
|
84
|
+
};
|
|
85
|
+
export declare function outcomeOf(result: BrokerResult): BrokerOutcome;
|
|
86
|
+
export declare function observationOf(result: ReconcileResult): ReconcileObservation;
|
|
87
|
+
/**
|
|
88
|
+
* One kind of consequential action, and how to do it.
|
|
89
|
+
*
|
|
90
|
+
* `reconcile` is not optional and is not a courtesy. A broker call that does not
|
|
91
|
+
* come back leaves exactly one question — did it happen — and an executor with
|
|
92
|
+
* no way to answer it can only ever produce `ambiguous`, which holds the pursuit
|
|
93
|
+
* for a person for ever. Any action type added here must be able to look.
|
|
94
|
+
*/
|
|
95
|
+
export interface ActionExecutor {
|
|
96
|
+
readonly type: string;
|
|
97
|
+
execute(env: GovernedExecutionEnvelope): Promise<BrokerResult>;
|
|
98
|
+
reconcile(env: GovernedExecutionEnvelope): Promise<ReconcileResult>;
|
|
99
|
+
}
|
|
100
|
+
export interface GovernedActionBroker {
|
|
101
|
+
execute(env: GovernedExecutionEnvelope): Promise<BrokerResult>;
|
|
102
|
+
reconcile(env: GovernedExecutionEnvelope): Promise<ReconcileResult>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* WHERE A BROKER-OWNED EFFECT LIVES.
|
|
106
|
+
*
|
|
107
|
+
* Under the machine's own Looply home, which is outside every project worktree
|
|
108
|
+
* and is one of the roots contained execution may never be granted. The
|
|
109
|
+
* contained tool worker confines every path to the project root — lexically and
|
|
110
|
+
* physically, resolving reparse points — so a model cannot read this, write it,
|
|
111
|
+
* or delete it, whatever it asks for.
|
|
112
|
+
*
|
|
113
|
+
* That is what makes the tests worth anything. A fixture effect written inside
|
|
114
|
+
* the repository would be an effect the thing under test can forge, and
|
|
115
|
+
* "exactly one effect happened" would be a claim about a file the model could
|
|
116
|
+
* have produced itself.
|
|
117
|
+
*/
|
|
118
|
+
export declare function fixtureEffectDir(home?: string): string;
|
|
119
|
+
/**
|
|
120
|
+
* ONE FILE PER EXECUTION, CREATED IF ABSENT, NEVER APPENDED TO.
|
|
121
|
+
*
|
|
122
|
+
* The idempotency primitive is `createExclusive`, the same one the Start
|
|
123
|
+
* reservation and the resume claim use, and the reason is the same: the
|
|
124
|
+
* operating system hands the file to exactly one caller.
|
|
125
|
+
*
|
|
126
|
+
* A SHARED LEDGER WOULD NOT DO. Two processes appending to one file both
|
|
127
|
+
* succeed, and the duplicate is discovered afterwards by reading it back —
|
|
128
|
+
* which is a check, not a constraint, and it is exactly the check a crashed
|
|
129
|
+
* process never runs. Here the second attempt is refused by the filesystem
|
|
130
|
+
* before it writes a byte.
|
|
131
|
+
*/
|
|
132
|
+
export interface FixtureEffectRecord {
|
|
133
|
+
executionId: string;
|
|
134
|
+
approvalId: string;
|
|
135
|
+
claimId: string;
|
|
136
|
+
actionFingerprint: string;
|
|
137
|
+
/** Deterministic from the action, so a reconciliation can recognise its own work. */
|
|
138
|
+
effect: string;
|
|
139
|
+
at: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The fixture executor for `fixture.publish`.
|
|
143
|
+
*
|
|
144
|
+
* Inert in the world and real on this machine: it produces a durable artifact
|
|
145
|
+
* outside the model's reach, which is exactly the property a real executor will
|
|
146
|
+
* need and the only one the tests can check independently.
|
|
147
|
+
*/
|
|
148
|
+
export declare function fixturePublishExecutor(deps: {
|
|
149
|
+
fs: AttemptFs;
|
|
150
|
+
home?: string;
|
|
151
|
+
now?: () => number;
|
|
152
|
+
/** Injected so a test can make the effect fail or hang without faking the result. */
|
|
153
|
+
attempt?: (record: FixtureEffectRecord) => Promise<void>;
|
|
154
|
+
}): ActionExecutor;
|
|
155
|
+
/**
|
|
156
|
+
* Route an envelope to the executor for its action, or refuse it.
|
|
157
|
+
*
|
|
158
|
+
* FAILS CLOSED THREE TIMES OVER. The action type must be one Looply has
|
|
159
|
+
* registered, it must classify as consequential, and the stored request must
|
|
160
|
+
* still verify against its own fingerprint. An unregistered type is refused
|
|
161
|
+
* rather than assumed harmless — that is the branch that stops a tool added
|
|
162
|
+
* next year from executing simply because nothing has classified it yet.
|
|
163
|
+
*
|
|
164
|
+
* A refusal here is `failure`, not `ambiguous`, and that is correct rather than
|
|
165
|
+
* convenient: nothing was attempted, so no effect can exist, and saying so
|
|
166
|
+
* definitely is what lets the pursuit plan around it instead of holding.
|
|
167
|
+
*/
|
|
168
|
+
export declare function createGovernedBroker(executors: readonly ActionExecutor[]): GovernedActionBroker;
|
|
169
|
+
//# sourceMappingURL=governed-broker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governed-broker.d.ts","sourceRoot":"","sources":["../src/governed-broker.ts"],"names":[],"mappings":"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"}
|