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,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CONTAINMENT_PREFLIGHT_STEP = void 0;
|
|
4
|
+
exports.makeUntrustedGateRunner = makeUntrustedGateRunner;
|
|
5
|
+
exports.makeContainmentPreflight = makeContainmentPreflight;
|
|
6
|
+
const toolchain_mirror_1 = require("./toolchain-mirror");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const exec_domains_1 = require("./exec-domains");
|
|
9
|
+
const untrusted_exec_1 = require("./untrusted-exec");
|
|
10
|
+
const shared_grants_1 = require("./shared-grants");
|
|
11
|
+
/**
|
|
12
|
+
* A {@link CommandRunner} that runs each step contained.
|
|
13
|
+
*
|
|
14
|
+
* `projectDir` is both the worktree granted to the container and the cwd the
|
|
15
|
+
* step runs in, so a step can never be executed against a directory other than
|
|
16
|
+
* the one it was written for.
|
|
17
|
+
*/
|
|
18
|
+
function makeUntrustedGateRunner(projectDir, deps = {}) {
|
|
19
|
+
const backend = deps.backend ?? new untrusted_exec_1.AppContainerBackend();
|
|
20
|
+
const now = deps.now ?? (() => Date.now());
|
|
21
|
+
const ensureToolchain = deps.toolchain ?? (() => (0, toolchain_mirror_1.ensureToolchainMirror)());
|
|
22
|
+
const shell = deps.shell ?? (0, node_path_1.join)((0, untrusted_exec_1.systemRoot)(), 'System32', 'cmd.exe');
|
|
23
|
+
return async (cmd, timeoutMs) => {
|
|
24
|
+
const started = now();
|
|
25
|
+
// The runtime the step will use, copied where the container can reach it.
|
|
26
|
+
// Without this there is no `node` inside the container at all, so a
|
|
27
|
+
// toolchain that cannot be mirrored is a step that cannot run — never a
|
|
28
|
+
// step that quietly runs on the host instead.
|
|
29
|
+
const tools = ensureToolchain();
|
|
30
|
+
if (!tools.ok) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
// The step did not run. Not the project's fault, so not the item's bill.
|
|
34
|
+
unavailable: true,
|
|
35
|
+
timedOut: false,
|
|
36
|
+
ms: now() - started,
|
|
37
|
+
output: `this step did not run: no contained toolchain — ${tools.because}`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/*
|
|
41
|
+
* The shared toolchain is granted under the shared-grant lock, before the
|
|
42
|
+
* launch and outside it — the critical section is one ACL write, never a
|
|
43
|
+
* gate step. An identity that already holds it does no work here at all.
|
|
44
|
+
*/
|
|
45
|
+
const shared = await (0, shared_grants_1.ensureSharedAccess)(backend instanceof untrusted_exec_1.AppContainerBackend ? backend : null, (0, untrusted_exec_1.containerName)('gate', projectDir), (0, exec_domains_1.sharedGrantPaths)(tools.path));
|
|
46
|
+
if (!shared.ok) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
// The step did not run, and not for the project's reasons.
|
|
50
|
+
unavailable: true,
|
|
51
|
+
timedOut: false,
|
|
52
|
+
ms: now() - started,
|
|
53
|
+
output: `this step did not run: the shared toolchain grant failed — ${shared.because}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const out = await backend.run({
|
|
57
|
+
kind: 'gate',
|
|
58
|
+
projectKey: projectDir,
|
|
59
|
+
executable: shell,
|
|
60
|
+
// The step is a shell line by contract, so it is handed to the shell as
|
|
61
|
+
// one argument rather than split — splitting it here would change what
|
|
62
|
+
// every existing project's gate means.
|
|
63
|
+
argv: ['/d', '/s', '/c', cmd],
|
|
64
|
+
// `cmd /s /c "<line>"` — one pair of quotes that cmd strips, leaving the
|
|
65
|
+
// line verbatim. Quoting each argument by C-runtime rules would escape
|
|
66
|
+
// the step's own quotes into something cmd cannot read.
|
|
67
|
+
rawCommandLine: `"${shell}" /d /s /c "${cmd}"`,
|
|
68
|
+
cwd: projectDir,
|
|
69
|
+
env: (0, exec_domains_1.buildUntrustedGateEnv)(projectDir, tools.path),
|
|
70
|
+
// Run-OWNED paths only. The shared toolchain was granted above, under the
|
|
71
|
+
// shared-grant lock, so it is not re-granted per launch — that per-launch
|
|
72
|
+
// grant is what accumulated one permanent ACE per identity.
|
|
73
|
+
grants: (0, exec_domains_1.untrustedGrants)('gate', projectDir),
|
|
74
|
+
protect: (0, exec_domains_1.protectedPaths)(projectDir),
|
|
75
|
+
// A test suite that needs the network is reaching outside the change it
|
|
76
|
+
// is meant to be checking.
|
|
77
|
+
network: 'none',
|
|
78
|
+
timeoutMs,
|
|
79
|
+
});
|
|
80
|
+
if (!out.ok) {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
// Same class as the missing toolchain above: containment could not be
|
|
84
|
+
// made, so nothing about the project was measured.
|
|
85
|
+
unavailable: true,
|
|
86
|
+
timedOut: false,
|
|
87
|
+
ms: now() - started,
|
|
88
|
+
output: `this step did not run: untrusted execution was unavailable ` +
|
|
89
|
+
`(${out.reason} at ${out.stage}) — ${out.because}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
ok: out.exitCode === 0 && !out.timedOut,
|
|
94
|
+
// The status itself, not only the verdict folded from it: a rejected
|
|
95
|
+
// candidate's evidence records "exited 2", never just "failed".
|
|
96
|
+
exitCode: out.exitCode,
|
|
97
|
+
timedOut: out.timedOut,
|
|
98
|
+
ms: now() - started,
|
|
99
|
+
// Interleaved the way the previous runner reported it, so existing
|
|
100
|
+
// diagnostics read the same.
|
|
101
|
+
output: `${out.stdout}${out.stderr}`,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The step a containment preflight runs.
|
|
107
|
+
*
|
|
108
|
+
* A `rem` is cmd.exe's comment: it starts, does nothing and exits 0. What is
|
|
109
|
+
* being measured is not the command — it is whether a container could be made
|
|
110
|
+
* to run one in at all.
|
|
111
|
+
*/
|
|
112
|
+
exports.CONTAINMENT_PREFLIGHT_STEP = 'rem looply-containment-preflight';
|
|
113
|
+
/**
|
|
114
|
+
* ASK WHETHER A CONTAINER CAN ACTUALLY BE MADE, BEFORE PAYING FOR A MODEL TURN.
|
|
115
|
+
*
|
|
116
|
+
* `AppContainerBackend.probe()` answers a strictly earlier question. It returns
|
|
117
|
+
* as soon as a profile can be created or derived, and never reaches the grant,
|
|
118
|
+
* protect or launch stages — measured on one machine in one script: `probe`
|
|
119
|
+
* returned ok while a real `run` failed at `grant`, and again at `launch`.
|
|
120
|
+
* So a green probe does not mean a gate step can run.
|
|
121
|
+
*
|
|
122
|
+
* This runs the real thing through the real runner: same backend, same `gate`
|
|
123
|
+
* profile, same `unavailable` flag, same classification. There is no new
|
|
124
|
+
* vocabulary and no second code path to keep honest.
|
|
125
|
+
*
|
|
126
|
+
* ⚠️ THE GRANT SET IS DELIBERATELY SMALL, and this is not a shortcut. Granting
|
|
127
|
+
* the toolchain mirror propagates an inheritable ACE across 166 MB — measured at
|
|
128
|
+
* ~6.5 s against ~0.57 s for the project directory alone — and it proves nothing
|
|
129
|
+
* the small grant does not. Anyone "making the preflight faithful" by reusing
|
|
130
|
+
* `untrustedGrants` buys a 10x cost for no signal.
|
|
131
|
+
*
|
|
132
|
+
* ⚠️ IT COVERS THE `gate` PROFILE ONLY. The tool bridge uses `kind:'agent'`, a
|
|
133
|
+
* different profile from a different `CreateAppContainerProfile` call. A machine
|
|
134
|
+
* that can make neither is caught; one that can make the gate's and not the
|
|
135
|
+
* agent's is not. Closing that needs a second preflight through the bridge's own
|
|
136
|
+
* backend seam, and it is not this change.
|
|
137
|
+
*/
|
|
138
|
+
function makeContainmentPreflight(projectDir, deps = {}) {
|
|
139
|
+
const backend = deps.backend ?? new untrusted_exec_1.AppContainerBackend();
|
|
140
|
+
const now = deps.now ?? (() => Date.now());
|
|
141
|
+
const ensureToolchain = deps.toolchain ?? (() => (0, toolchain_mirror_1.ensureToolchainMirror)());
|
|
142
|
+
const shell =
|
|
143
|
+
// ⚠️ DOUBLED. `'C:\Windows'` is the RELATIVE path `C:Windows` — `\W` is not
|
|
144
|
+
// an escape, so the backslash is dropped and `isAbsolute` is false. This
|
|
145
|
+
// repository has a suite named for that bug, and the first version of this
|
|
146
|
+
// line reintroduced it by copying the one above and losing the escape.
|
|
147
|
+
deps.shell ?? (0, node_path_1.join)((0, untrusted_exec_1.systemRoot)(), 'System32', 'cmd.exe');
|
|
148
|
+
return async () => {
|
|
149
|
+
const started = now();
|
|
150
|
+
// Asked first, exactly as the gate runner asks it: a machine with no
|
|
151
|
+
// mirrored runtime cannot run a step either, and must give the same answer.
|
|
152
|
+
const tools = ensureToolchain();
|
|
153
|
+
if (!tools.ok) {
|
|
154
|
+
return {
|
|
155
|
+
ok: false,
|
|
156
|
+
unavailable: true,
|
|
157
|
+
timedOut: false,
|
|
158
|
+
ms: now() - started,
|
|
159
|
+
output: `containment preflight: no contained toolchain — ${tools.because}`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const out = await backend.run({
|
|
163
|
+
kind: 'gate',
|
|
164
|
+
projectKey: projectDir,
|
|
165
|
+
executable: shell,
|
|
166
|
+
argv: ['/d', '/s', '/c', exports.CONTAINMENT_PREFLIGHT_STEP],
|
|
167
|
+
rawCommandLine: `"${shell}" /d /s /c "${exports.CONTAINMENT_PREFLIGHT_STEP}"`,
|
|
168
|
+
cwd: projectDir,
|
|
169
|
+
env: (0, exec_domains_1.buildUntrustedGateEnv)(projectDir, tools.path),
|
|
170
|
+
/**
|
|
171
|
+
* THE PROJECT DIRECTORY AND THE PROTECT LIST ARE NOT OPTIONAL.
|
|
172
|
+
*
|
|
173
|
+
* The first version granted only the contained root and passed an empty
|
|
174
|
+
* protect list — a directory the daemon had `mkdirSync`'d microseconds
|
|
175
|
+
* earlier under its own `%TEMP%`, which it therefore always owns and can
|
|
176
|
+
* always ACL. So the grant failure this preflight exists to catch was one
|
|
177
|
+
* it could not reproduce, and the protect stage — which fails CLOSED on
|
|
178
|
+
* any path it cannot ACL, and which Phase 0 taught to include the resolved
|
|
179
|
+
* gitdir, `<super>/.git/modules/<name>` for a submodule — was invisible to
|
|
180
|
+
* it.
|
|
181
|
+
*
|
|
182
|
+
* ⚠️ THE TOOLCHAIN MIRROR STAYS OUT, and that is the documented gap
|
|
183
|
+
* rather than a claim of parity: its inheritable ACE propagates across
|
|
184
|
+
* 166 MB, ~6.5 s against ~0.57 s. So `doctor` and `run` CAN still disagree
|
|
185
|
+
* about a machine that fails only on the mirror.
|
|
186
|
+
*/
|
|
187
|
+
grants: [
|
|
188
|
+
{ path: projectDir, write: true },
|
|
189
|
+
{ path: (0, exec_domains_1.containedRoot)('gate', projectDir), write: true },
|
|
190
|
+
],
|
|
191
|
+
protect: (0, exec_domains_1.protectedPaths)(projectDir),
|
|
192
|
+
network: 'none',
|
|
193
|
+
timeoutMs: 30_000,
|
|
194
|
+
});
|
|
195
|
+
if (!out.ok) {
|
|
196
|
+
return {
|
|
197
|
+
ok: false,
|
|
198
|
+
unavailable: true,
|
|
199
|
+
timedOut: false,
|
|
200
|
+
ms: now() - started,
|
|
201
|
+
output: `containment preflight: a container could not be made ` +
|
|
202
|
+
`(${out.reason} at ${out.stage}) — ${out.because}`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* ⚠️ READ `exitCode` AND `timedOut`, exactly as the gate runner above does.
|
|
207
|
+
*
|
|
208
|
+
* The first version returned `{ok:true, timedOut:false}` unconditionally, so
|
|
209
|
+
* a container that launched and was then killed at the child ceiling was
|
|
210
|
+
* reported as a HEALTHY environment — and its timeout was not merely
|
|
211
|
+
* unreported but denied.
|
|
212
|
+
*/
|
|
213
|
+
if (out.exitCode !== 0 || out.timedOut) {
|
|
214
|
+
return {
|
|
215
|
+
ok: false,
|
|
216
|
+
unavailable: true,
|
|
217
|
+
timedOut: out.timedOut,
|
|
218
|
+
ms: now() - started,
|
|
219
|
+
output: `containment preflight: a container was made but its process did not complete ` +
|
|
220
|
+
`(exit ${out.exitCode}${out.timedOut ? ', timed out' : ''})`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return { ok: true, timedOut: false, ms: now() - started };
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=untrusted-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"untrusted-gate.js","sourceRoot":"","sources":["../src/untrusted-gate.ts"],"names":[],"mappings":";;;AAsDA,0DAiGC;AAoCD,4DA6FC;AAxRD,yDAAiF;AACjF,yCAAiC;AAEjC,iDAMwB;AACxB,qDAK0B;AAC1B,mDAAqE;AA+BrE;;;;;;GAMG;AACH,SAAgB,uBAAuB,CACrC,UAAkB,EAClB,OAA0B,EAAE;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,oCAAmB,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAA,wCAAqB,GAAE,CAAC,CAAC;IAC1E,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,IAAI,IAAA,gBAAI,EAAC,IAAA,2BAAU,GAAE,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAE1D,OAAO,KAAK,EAAE,GAAW,EAAE,SAAiB,EAA0B,EAAE;QACtE,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;QACtB,0EAA0E;QAC1E,oEAAoE;QACpE,wEAAwE;QACxE,8CAA8C;QAC9C,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,yEAAyE;gBACzE,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EAAE,mDAAmD,KAAK,CAAC,OAAO,EAAE;aAC3E,CAAC;QACJ,CAAC;QACD;;;;WAIG;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,kCAAkB,EACrC,OAAO,YAAY,oCAAmB,CAAC,CAAC,CAAE,OAAgC,CAAC,CAAC,CAAC,IAAI,EACjF,IAAA,8BAAa,EAAC,MAAM,EAAE,UAAU,CAAC,EACjC,IAAA,+BAAgB,EAAC,KAAK,CAAC,IAAI,CAAC,CAC7B,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,2DAA2D;gBAC3D,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EAAE,8DAA8D,MAAM,CAAC,OAAO,EAAE;aACvF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5B,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,UAAU;YACtB,UAAU,EAAE,KAAK;YACjB,wEAAwE;YACxE,uEAAuE;YACvE,uCAAuC;YACvC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC;YAC7B,yEAAyE;YACzE,uEAAuE;YACvE,wDAAwD;YACxD,cAAc,EAAE,IAAI,KAAK,eAAe,GAAG,GAAG;YAC9C,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,IAAA,oCAAqB,EAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC;YAClD,0EAA0E;YAC1E,0EAA0E;YAC1E,4DAA4D;YAC5D,MAAM,EAAE,IAAA,8BAAe,EAAC,MAAM,EAAE,UAAU,CAAC;YAC3C,OAAO,EAAE,IAAA,6BAAc,EAAC,UAAU,CAAC;YACnC,wEAAwE;YACxE,2BAA2B;YAC3B,OAAO,EAAE,MAAM;YACf,SAAS;SACV,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,sEAAsE;gBACtE,mDAAmD;gBACnD,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EACJ,6DAA6D;oBAC7D,IAAI,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE;aACrD,CAAC;QACJ,CAAC;QACD,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ;YACvC,qEAAqE;YACrE,gEAAgE;YAChE,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;YACnB,mEAAmE;YACnE,6BAA6B;YAC7B,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE;SACrC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACU,QAAA,0BAA0B,GAAG,kCAAkC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,wBAAwB,CACtC,UAAkB,EAClB,OAA0B,EAAE;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,oCAAmB,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC,IAAA,wCAAqB,GAAE,CAAC,CAAC;IAC1E,MAAM,KAAK;IACT,4EAA4E;IAC5E,yEAAyE;IACzE,2EAA2E;IAC3E,uEAAuE;IACvE,IAAI,CAAC,KAAK,IAAI,IAAA,gBAAI,EAAC,IAAA,2BAAU,GAAE,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAE1D,OAAO,KAAK,IAA4B,EAAE;QACxC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;QACtB,qEAAqE;QACrE,4EAA4E;QAC5E,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACd,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EAAE,mDAAmD,KAAK,CAAC,OAAO,EAAE;aAC3E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5B,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,UAAU;YACtB,UAAU,EAAE,KAAK;YACjB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,kCAA0B,CAAC;YACpD,cAAc,EAAE,IAAI,KAAK,eAAe,kCAA0B,GAAG;YACrE,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,IAAA,oCAAqB,EAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC;YAClD;;;;;;;;;;;;;;;;eAgBG;YACH,MAAM,EAAE;gBACN,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE;gBACjC,EAAE,IAAI,EAAE,IAAA,4BAAa,EAAC,MAAM,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE;aACzD;YACD,OAAO,EAAE,IAAA,6BAAc,EAAC,UAAU,CAAC;YACnC,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,KAAK;gBACf,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EACJ,uDAAuD;oBACvD,IAAI,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE;aACrD,CAAC;QACJ,CAAC;QACD;;;;;;;WAOG;QACH,IAAI,GAAG,CAAC,QAAQ,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACvC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO;gBACnB,MAAM,EACJ,+EAA+E;oBAC/E,SAAS,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG;aAC/D,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { type AnyEvent } from '@looply/core';
|
|
2
|
+
/**
|
|
3
|
+
* The event uploader — the machine half of DESIGN §12 case 23: server unreachable
|
|
4
|
+
* for an hour → events buffer locally, replay in order, no gaps.
|
|
5
|
+
*
|
|
6
|
+
* The ledger on disk is the truth; the server is a mirror that may lag. This
|
|
7
|
+
* class owns the lag: events are enqueued as the ledger appends them, and
|
|
8
|
+
* `flush()` ships them in `(runId, seq)` order. A transport failure is an
|
|
9
|
+
* *outcome*, never a throw — the run must keep working while the server is away,
|
|
10
|
+
* so the failed batch and everything after it stay buffered and the next flush
|
|
11
|
+
* resumes exactly where this one stopped.
|
|
12
|
+
*
|
|
13
|
+
* Resume is driven by the server's own acknowledgements: every ingest response
|
|
14
|
+
* carries `cursors`, the highest seq the server now holds per run. Anything at
|
|
15
|
+
* or below that head is dropped locally instead of re-sent. After a process
|
|
16
|
+
* restart the caller primes those cursors (or simply replays the ledger —
|
|
17
|
+
* ingest is idempotent on `(runId, seq)`, so overlap is duplicates, not damage).
|
|
18
|
+
*
|
|
19
|
+
* The buffer is capped (`DEFAULT_BUFFER_LIMIT`): case 23 says an hour offline,
|
|
20
|
+
* not a week, and memory is the one resource whose exhaustion ends the run the
|
|
21
|
+
* buffering was protecting.
|
|
22
|
+
*/
|
|
23
|
+
/** Mirror of the server's `IngestResult` — the ack a successful POST returns. */
|
|
24
|
+
export interface IngestAck {
|
|
25
|
+
accepted: number;
|
|
26
|
+
duplicates: number;
|
|
27
|
+
rejected: number;
|
|
28
|
+
/** Highest seq the server now holds per run — the cursor this class trusts. */
|
|
29
|
+
cursors: Record<string, number>;
|
|
30
|
+
}
|
|
31
|
+
/** Injected transport: one POST to `/v1/projects/:id/events`. Throws on failure. */
|
|
32
|
+
export interface UploadTransport {
|
|
33
|
+
post(projectId: string, events: readonly AnyEvent[]): Promise<IngestAck>;
|
|
34
|
+
}
|
|
35
|
+
export interface FlushResult {
|
|
36
|
+
/** Events the server's ledger now holds — its own `accepted + duplicates`. */
|
|
37
|
+
delivered: number;
|
|
38
|
+
/**
|
|
39
|
+
* Events the server took but did not account for, cumulative.
|
|
40
|
+
*
|
|
41
|
+
* A 200 is not proof of storage. The server drops a malformed event, and
|
|
42
|
+
* silently drops one addressed to a different project than the URL — for a
|
|
43
|
+
* long time that was *every* event a run produced, and this class reported
|
|
44
|
+
* complete delivery of all of them. Anything a POST does not account for
|
|
45
|
+
* lands here so it can be said out loud instead of inferred from a phone that
|
|
46
|
+
* never moves.
|
|
47
|
+
*/
|
|
48
|
+
unacked?: number;
|
|
49
|
+
/** Events dropped locally because the server's head already covers their seq. */
|
|
50
|
+
skipped: number;
|
|
51
|
+
/** Events still waiting after this flush — non-zero only on `error`. */
|
|
52
|
+
buffered: number;
|
|
53
|
+
/** Present when the transport failed; the unsent tail is retained, not lost. */
|
|
54
|
+
error?: string;
|
|
55
|
+
/** Present when the cap has thrown events away; cumulative, not per-flush. */
|
|
56
|
+
dropped?: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* How many events may wait for a server that is not answering.
|
|
60
|
+
*
|
|
61
|
+
* A round emits on the order of tens of events, so this holds a long outage —
|
|
62
|
+
* many hours of running — before anything is thrown away. It exists because
|
|
63
|
+
* "buffer until the server returns" and "never end the run" cannot both be
|
|
64
|
+
* unconditional: an uploader with no ceiling turns a network outage into an
|
|
65
|
+
* out-of-memory kill, which loses the *whole* run rather than a prefix of its
|
|
66
|
+
* mirror. The ledger on disk is still complete either way.
|
|
67
|
+
*/
|
|
68
|
+
export declare const DEFAULT_BUFFER_LIMIT = 5000;
|
|
69
|
+
export declare class EventUploader {
|
|
70
|
+
private readonly projectId;
|
|
71
|
+
private readonly transport;
|
|
72
|
+
/** Server rejects batches over 1000; stay comfortably under it. */
|
|
73
|
+
private readonly batchSize;
|
|
74
|
+
/** Ceiling on buffered events; the oldest go first once it is reached. */
|
|
75
|
+
private readonly capacity;
|
|
76
|
+
private buffer;
|
|
77
|
+
private readonly acked;
|
|
78
|
+
/**
|
|
79
|
+
* The greatest seq per run below which nothing is missing.
|
|
80
|
+
*
|
|
81
|
+
* Deliberately not `acked`. The server's ack reports the highest seq in the
|
|
82
|
+
* batch it just stored, which says nothing about the seqs *before* it — and
|
|
83
|
+
* those can be absent for reasons the server cannot see. The buffer sheds the
|
|
84
|
+
* oldest events when it overflows, so a long outage ships `[3, 4, 5]` and is
|
|
85
|
+
* told "you are up to 5" while 0, 1 and 2 were never sent at all. There is a
|
|
86
|
+
* green test asserting exactly that shape.
|
|
87
|
+
*
|
|
88
|
+
* Persisting `acked` would therefore write down a cursor covering events the
|
|
89
|
+
* server has never seen, and replay would skip them for ever. This head only
|
|
90
|
+
* advances one seq at a time, over a batch the server accounted for in full,
|
|
91
|
+
* and stops dead at the first gap.
|
|
92
|
+
*/
|
|
93
|
+
private readonly durable;
|
|
94
|
+
private droppedCount;
|
|
95
|
+
private unackedCount;
|
|
96
|
+
constructor(projectId: string, transport: UploadTransport,
|
|
97
|
+
/** Server rejects batches over 1000; stay comfortably under it. */
|
|
98
|
+
batchSize?: number,
|
|
99
|
+
/** Ceiling on buffered events; the oldest go first once it is reached. */
|
|
100
|
+
capacity?: number);
|
|
101
|
+
/**
|
|
102
|
+
* Queue one event for the next flush. Cheap; call from the ledger append path.
|
|
103
|
+
*
|
|
104
|
+
* At capacity the *oldest* event goes, not the newest. The phone is watching
|
|
105
|
+
* for what is happening now — the round in flight, a question waiting on an
|
|
106
|
+
* answer — so the tail is what has to survive; and the head is the part a
|
|
107
|
+
* replay of the on-disk ledger can put back, since ingest is idempotent on
|
|
108
|
+
* `(runId, seq)`. Dropping is a reported loss, never a silent one.
|
|
109
|
+
*/
|
|
110
|
+
enqueue(event: AnyEvent): void;
|
|
111
|
+
/** Events thrown away because the buffer was full, since this uploader started. */
|
|
112
|
+
dropped(): number;
|
|
113
|
+
/** Events a POST took but did not account for, since this uploader started. */
|
|
114
|
+
unacked(): number;
|
|
115
|
+
/**
|
|
116
|
+
* Seed the heads after a restart, so a replayed ledger skips what the server
|
|
117
|
+
* already holds.
|
|
118
|
+
*
|
|
119
|
+
* Both heads, from the same number: what came out of `cursor.json` is a
|
|
120
|
+
* durable gapless prefix, so it is simultaneously the last thing known held
|
|
121
|
+
* and a point with nothing missing behind it. Seeding only `acked` would let
|
|
122
|
+
* the next flush advance a durable head from -1 and re-send the whole run;
|
|
123
|
+
* seeding only `durable` would re-send everything the skip filter should drop.
|
|
124
|
+
*/
|
|
125
|
+
prime(cursors: Record<string, number>): void;
|
|
126
|
+
/** Highest seq the server has acknowledged for a run, or -1 when unknown. */
|
|
127
|
+
ackedHead(runId: string): number;
|
|
128
|
+
/** Events waiting for the next flush. */
|
|
129
|
+
pending(): number;
|
|
130
|
+
/**
|
|
131
|
+
* Ship everything buffered, in `(runId, seq)` order, in batches.
|
|
132
|
+
*
|
|
133
|
+
* Order matters even though ingest dedupes: a batch that fails mid-flush must
|
|
134
|
+
* leave the server holding a *prefix* of each run, so the acknowledged head is
|
|
135
|
+
* always an honest resume point. Sending out of order would let a later seq
|
|
136
|
+
* land before an earlier one, and a crash in between would read as a gap.
|
|
137
|
+
*/
|
|
138
|
+
flush(): Promise<FlushResult>;
|
|
139
|
+
private mergeCursor;
|
|
140
|
+
/**
|
|
141
|
+
* Walk a fully-accounted batch and extend each run's gapless head.
|
|
142
|
+
*
|
|
143
|
+
* One seq at a time, in order, stopping at the first number that is not the
|
|
144
|
+
* next one. A batch of `[3, 4, 5]` for a run whose head is -1 moves nothing:
|
|
145
|
+
* 0, 1 and 2 were never sent, and no ack can make it safe to skip them.
|
|
146
|
+
*/
|
|
147
|
+
private advanceDurable;
|
|
148
|
+
/** Highest gapless seq the server is known to hold for a run, or -1. */
|
|
149
|
+
durableHead(runId: string): number;
|
|
150
|
+
/** What is safe to write to `cursor.json`. Never `acked` — see the field. */
|
|
151
|
+
durableCursors(): Record<string, number>;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=uploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../src/uploader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAE1C,qBAAa,aAAa;IAuBtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,QAAQ;IA3B3B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IACnD;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAK;gBAGN,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,eAAe;IAC3C,mEAAmE;IAClD,SAAS,SAAM;IAChC,0EAA0E;IACzD,QAAQ,SAAuB;IAGlD;;;;;;;;OAQG;IACH,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAQ9B,mFAAmF;IACnF,OAAO,IAAI,MAAM;IAIjB,+EAA+E;IAC/E,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;OASG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAO5C,6EAA6E;IAC7E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIhC,yCAAyC;IACzC,OAAO,IAAI,MAAM;IAIjB;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IAiEnC,OAAO,CAAC,WAAW;IAInB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAStB,wEAAwE;IACxE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIlC,6EAA6E;IAC7E,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAGzC"}
|
package/dist/uploader.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventUploader = exports.DEFAULT_BUFFER_LIMIT = void 0;
|
|
4
|
+
const core_1 = require("@looply/core");
|
|
5
|
+
/**
|
|
6
|
+
* How many events may wait for a server that is not answering.
|
|
7
|
+
*
|
|
8
|
+
* A round emits on the order of tens of events, so this holds a long outage —
|
|
9
|
+
* many hours of running — before anything is thrown away. It exists because
|
|
10
|
+
* "buffer until the server returns" and "never end the run" cannot both be
|
|
11
|
+
* unconditional: an uploader with no ceiling turns a network outage into an
|
|
12
|
+
* out-of-memory kill, which loses the *whole* run rather than a prefix of its
|
|
13
|
+
* mirror. The ledger on disk is still complete either way.
|
|
14
|
+
*/
|
|
15
|
+
exports.DEFAULT_BUFFER_LIMIT = 5_000;
|
|
16
|
+
class EventUploader {
|
|
17
|
+
projectId;
|
|
18
|
+
transport;
|
|
19
|
+
batchSize;
|
|
20
|
+
capacity;
|
|
21
|
+
buffer = [];
|
|
22
|
+
acked = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* The greatest seq per run below which nothing is missing.
|
|
25
|
+
*
|
|
26
|
+
* Deliberately not `acked`. The server's ack reports the highest seq in the
|
|
27
|
+
* batch it just stored, which says nothing about the seqs *before* it — and
|
|
28
|
+
* those can be absent for reasons the server cannot see. The buffer sheds the
|
|
29
|
+
* oldest events when it overflows, so a long outage ships `[3, 4, 5]` and is
|
|
30
|
+
* told "you are up to 5" while 0, 1 and 2 were never sent at all. There is a
|
|
31
|
+
* green test asserting exactly that shape.
|
|
32
|
+
*
|
|
33
|
+
* Persisting `acked` would therefore write down a cursor covering events the
|
|
34
|
+
* server has never seen, and replay would skip them for ever. This head only
|
|
35
|
+
* advances one seq at a time, over a batch the server accounted for in full,
|
|
36
|
+
* and stops dead at the first gap.
|
|
37
|
+
*/
|
|
38
|
+
durable = new Map();
|
|
39
|
+
droppedCount = 0;
|
|
40
|
+
unackedCount = 0;
|
|
41
|
+
constructor(projectId, transport,
|
|
42
|
+
/** Server rejects batches over 1000; stay comfortably under it. */
|
|
43
|
+
batchSize = 500,
|
|
44
|
+
/** Ceiling on buffered events; the oldest go first once it is reached. */
|
|
45
|
+
capacity = exports.DEFAULT_BUFFER_LIMIT) {
|
|
46
|
+
this.projectId = projectId;
|
|
47
|
+
this.transport = transport;
|
|
48
|
+
this.batchSize = batchSize;
|
|
49
|
+
this.capacity = capacity;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Queue one event for the next flush. Cheap; call from the ledger append path.
|
|
53
|
+
*
|
|
54
|
+
* At capacity the *oldest* event goes, not the newest. The phone is watching
|
|
55
|
+
* for what is happening now — the round in flight, a question waiting on an
|
|
56
|
+
* answer — so the tail is what has to survive; and the head is the part a
|
|
57
|
+
* replay of the on-disk ledger can put back, since ingest is idempotent on
|
|
58
|
+
* `(runId, seq)`. Dropping is a reported loss, never a silent one.
|
|
59
|
+
*/
|
|
60
|
+
enqueue(event) {
|
|
61
|
+
this.buffer.push(event);
|
|
62
|
+
while (this.buffer.length > this.capacity) {
|
|
63
|
+
this.buffer.shift();
|
|
64
|
+
this.droppedCount += 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Events thrown away because the buffer was full, since this uploader started. */
|
|
68
|
+
dropped() {
|
|
69
|
+
return this.droppedCount;
|
|
70
|
+
}
|
|
71
|
+
/** Events a POST took but did not account for, since this uploader started. */
|
|
72
|
+
unacked() {
|
|
73
|
+
return this.unackedCount;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Seed the heads after a restart, so a replayed ledger skips what the server
|
|
77
|
+
* already holds.
|
|
78
|
+
*
|
|
79
|
+
* Both heads, from the same number: what came out of `cursor.json` is a
|
|
80
|
+
* durable gapless prefix, so it is simultaneously the last thing known held
|
|
81
|
+
* and a point with nothing missing behind it. Seeding only `acked` would let
|
|
82
|
+
* the next flush advance a durable head from -1 and re-send the whole run;
|
|
83
|
+
* seeding only `durable` would re-send everything the skip filter should drop.
|
|
84
|
+
*/
|
|
85
|
+
prime(cursors) {
|
|
86
|
+
for (const [runId, seq] of Object.entries(cursors)) {
|
|
87
|
+
this.mergeCursor(runId, seq);
|
|
88
|
+
if (seq > this.durableHead(runId))
|
|
89
|
+
this.durable.set(runId, seq);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Highest seq the server has acknowledged for a run, or -1 when unknown. */
|
|
93
|
+
ackedHead(runId) {
|
|
94
|
+
return this.acked.get(runId) ?? -1;
|
|
95
|
+
}
|
|
96
|
+
/** Events waiting for the next flush. */
|
|
97
|
+
pending() {
|
|
98
|
+
return this.buffer.length;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Ship everything buffered, in `(runId, seq)` order, in batches.
|
|
102
|
+
*
|
|
103
|
+
* Order matters even though ingest dedupes: a batch that fails mid-flush must
|
|
104
|
+
* leave the server holding a *prefix* of each run, so the acknowledged head is
|
|
105
|
+
* always an honest resume point. Sending out of order would let a later seq
|
|
106
|
+
* land before an earlier one, and a crash in between would read as a gap.
|
|
107
|
+
*/
|
|
108
|
+
async flush() {
|
|
109
|
+
const ordered = (0, core_1.sortEvents)(this.buffer);
|
|
110
|
+
let skipped = 0;
|
|
111
|
+
const fresh = [];
|
|
112
|
+
for (const e of ordered) {
|
|
113
|
+
if (e.seq <= this.ackedHead(e.runId))
|
|
114
|
+
skipped += 1;
|
|
115
|
+
else
|
|
116
|
+
fresh.push(e);
|
|
117
|
+
}
|
|
118
|
+
// Two counters, deliberately. `sent` walks the batches and is the only
|
|
119
|
+
// thing the loop may advance on; `delivered` is how many of those the
|
|
120
|
+
// server accounted for. They were one variable, which was fine only while
|
|
121
|
+
// every batch counted as fully delivered — the moment a batch could be
|
|
122
|
+
// partially accounted for, a server that kept nothing stopped advancing the
|
|
123
|
+
// cursor and this loop re-sent the same batch forever.
|
|
124
|
+
let sent = 0;
|
|
125
|
+
let delivered = 0;
|
|
126
|
+
while (sent < fresh.length) {
|
|
127
|
+
const batch = fresh.slice(sent, sent + this.batchSize);
|
|
128
|
+
let ack;
|
|
129
|
+
try {
|
|
130
|
+
ack = await this.transport.post(this.projectId, batch);
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
// Keep the unsent tail — including this batch — for the next flush.
|
|
134
|
+
// Losing it here is exactly the gap case 23 exists to prevent.
|
|
135
|
+
this.buffer = fresh.slice(sent);
|
|
136
|
+
return {
|
|
137
|
+
delivered,
|
|
138
|
+
skipped,
|
|
139
|
+
buffered: this.buffer.length,
|
|
140
|
+
error: e instanceof Error ? e.message : String(e),
|
|
141
|
+
...(this.droppedCount > 0 ? { dropped: this.droppedCount } : {}),
|
|
142
|
+
...(this.unackedCount > 0 ? { unacked: this.unackedCount } : {}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
for (const [runId, seq] of Object.entries(ack.cursors))
|
|
146
|
+
this.mergeCursor(runId, seq);
|
|
147
|
+
// `accepted + duplicates` is exactly "events the server's ledger now
|
|
148
|
+
// holds": one it stored this time, one it already had. Everything else —
|
|
149
|
+
// malformed, addressed elsewhere, or dropped for a reason the ack does
|
|
150
|
+
// not name — is a loss, and counting it as delivered is how a run could
|
|
151
|
+
// upload its entire life to a server that kept none of it and still
|
|
152
|
+
// report success. `rejected` deliberately does NOT count as delivered:
|
|
153
|
+
// the server telling us it threw something away is not storage.
|
|
154
|
+
const accounted = Math.min(ack.accepted + ack.duplicates, batch.length);
|
|
155
|
+
this.unackedCount += batch.length - accounted;
|
|
156
|
+
delivered += accounted;
|
|
157
|
+
sent += batch.length;
|
|
158
|
+
// Only a batch the server accounted for in full says anything about which
|
|
159
|
+
// individual events landed. A partial one names a count, not a set, so
|
|
160
|
+
// there is no seq it makes safe to skip.
|
|
161
|
+
if (accounted === batch.length)
|
|
162
|
+
this.advanceDurable(batch);
|
|
163
|
+
}
|
|
164
|
+
this.buffer = [];
|
|
165
|
+
return {
|
|
166
|
+
delivered,
|
|
167
|
+
skipped,
|
|
168
|
+
buffered: 0,
|
|
169
|
+
...(this.droppedCount > 0 ? { dropped: this.droppedCount } : {}),
|
|
170
|
+
...(this.unackedCount > 0 ? { unacked: this.unackedCount } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
mergeCursor(runId, seq) {
|
|
174
|
+
if (seq > this.ackedHead(runId))
|
|
175
|
+
this.acked.set(runId, seq);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Walk a fully-accounted batch and extend each run's gapless head.
|
|
179
|
+
*
|
|
180
|
+
* One seq at a time, in order, stopping at the first number that is not the
|
|
181
|
+
* next one. A batch of `[3, 4, 5]` for a run whose head is -1 moves nothing:
|
|
182
|
+
* 0, 1 and 2 were never sent, and no ack can make it safe to skip them.
|
|
183
|
+
*/
|
|
184
|
+
advanceDurable(batch) {
|
|
185
|
+
for (const e of batch) {
|
|
186
|
+
const head = this.durableHead(e.runId);
|
|
187
|
+
if (e.seq <= head)
|
|
188
|
+
continue;
|
|
189
|
+
if (e.seq !== head + 1)
|
|
190
|
+
continue;
|
|
191
|
+
this.durable.set(e.runId, e.seq);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** Highest gapless seq the server is known to hold for a run, or -1. */
|
|
195
|
+
durableHead(runId) {
|
|
196
|
+
return this.durable.get(runId) ?? -1;
|
|
197
|
+
}
|
|
198
|
+
/** What is safe to write to `cursor.json`. Never `acked` — see the field. */
|
|
199
|
+
durableCursors() {
|
|
200
|
+
return Object.fromEntries(this.durable);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
exports.EventUploader = EventUploader;
|
|
204
|
+
//# sourceMappingURL=uploader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../src/uploader.ts"],"names":[],"mappings":"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"}
|