approval-md 0.0.1 → 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 +176 -0
- package/NOTICE +5 -0
- package/README.md +940 -4
- package/SPEC.md +476 -34
- package/cli.js +29 -3
- package/dist/src/adapters/agentmail.d.ts +426 -0
- package/dist/src/adapters/agentmail.js +1200 -0
- package/dist/src/adapters/agentmail.js.map +1 -0
- package/dist/src/adapters/conformance.d.ts +149 -0
- package/dist/src/adapters/conformance.js +461 -0
- package/dist/src/adapters/conformance.js.map +1 -0
- package/dist/src/adapters/contract.d.ts +628 -0
- package/dist/src/adapters/contract.js +1035 -0
- package/dist/src/adapters/contract.js.map +1 -0
- package/dist/src/adapters/email.d.ts +324 -0
- package/dist/src/adapters/email.js +749 -0
- package/dist/src/adapters/email.js.map +1 -0
- package/dist/src/adapters/env-passphrase.d.ts +93 -0
- package/dist/src/adapters/env-passphrase.js +132 -0
- package/dist/src/adapters/env-passphrase.js.map +1 -0
- package/dist/src/adapters/public.d.ts +11 -0
- package/dist/src/adapters/public.js +11 -0
- package/dist/src/adapters/public.js.map +1 -0
- package/dist/src/adapters/registry.d.ts +59 -0
- package/dist/src/adapters/registry.js +77 -0
- package/dist/src/adapters/registry.js.map +1 -0
- package/dist/src/adapters/smtp.d.ts +213 -0
- package/dist/src/adapters/smtp.js +499 -0
- package/dist/src/adapters/smtp.js.map +1 -0
- package/dist/src/adapters/vault-provider.d.ts +114 -0
- package/dist/src/adapters/vault-provider.js +161 -0
- package/dist/src/adapters/vault-provider.js.map +1 -0
- package/dist/src/adapters/zzz.d.ts +66 -0
- package/dist/src/adapters/zzz.js +299 -0
- package/dist/src/adapters/zzz.js.map +1 -0
- package/dist/src/channels/batch.d.ts +109 -0
- package/dist/src/channels/batch.js +121 -0
- package/dist/src/channels/batch.js.map +1 -0
- package/dist/src/channels/cli.d.ts +193 -0
- package/dist/src/channels/cli.js +468 -0
- package/dist/src/channels/cli.js.map +1 -0
- package/dist/src/channels/conformance.d.ts +92 -0
- package/dist/src/channels/conformance.js +445 -0
- package/dist/src/channels/conformance.js.map +1 -0
- package/dist/src/channels/contract.d.ts +623 -0
- package/dist/src/channels/contract.js +494 -0
- package/dist/src/channels/contract.js.map +1 -0
- package/dist/src/channels/payload-view.d.ts +35 -0
- package/dist/src/channels/payload-view.js +43 -0
- package/dist/src/channels/payload-view.js.map +1 -0
- package/dist/src/channels/render-queue.d.ts +149 -0
- package/dist/src/channels/render-queue.js +564 -0
- package/dist/src/channels/render-queue.js.map +1 -0
- package/dist/src/channels/tagging.d.ts +196 -0
- package/dist/src/channels/tagging.js +723 -0
- package/dist/src/channels/tagging.js.map +1 -0
- package/dist/src/channels/telegram.d.ts +1832 -0
- package/dist/src/channels/telegram.js +3190 -0
- package/dist/src/channels/telegram.js.map +1 -0
- package/dist/src/channels/web.d.ts +341 -0
- package/dist/src/channels/web.js +903 -0
- package/dist/src/channels/web.js.map +1 -0
- package/dist/src/cli/adapter.d.ts +90 -0
- package/dist/src/cli/adapter.js +288 -0
- package/dist/src/cli/adapter.js.map +1 -0
- package/dist/src/cli/amend.d.ts +59 -0
- package/dist/src/cli/amend.js +2171 -0
- package/dist/src/cli/amend.js.map +1 -0
- package/dist/src/cli/args.d.ts +43 -0
- package/dist/src/cli/args.js +86 -0
- package/dist/src/cli/args.js.map +1 -0
- package/dist/src/cli/attest.d.ts +41 -0
- package/dist/src/cli/attest.js +307 -0
- package/dist/src/cli/attest.js.map +1 -0
- package/dist/src/cli/audit-card.d.ts +62 -0
- package/dist/src/cli/audit-card.js +201 -0
- package/dist/src/cli/audit-card.js.map +1 -0
- package/dist/src/cli/audit.d.ts +59 -0
- package/dist/src/cli/audit.js +460 -0
- package/dist/src/cli/audit.js.map +1 -0
- package/dist/src/cli/channel-telegram.d.ts +806 -0
- package/dist/src/cli/channel-telegram.js +2063 -0
- package/dist/src/cli/channel-telegram.js.map +1 -0
- package/dist/src/cli/channel-web.d.ts +131 -0
- package/dist/src/cli/channel-web.js +357 -0
- package/dist/src/cli/channel-web.js.map +1 -0
- package/dist/src/cli/channel.d.ts +71 -0
- package/dist/src/cli/channel.js +438 -0
- package/dist/src/cli/channel.js.map +1 -0
- package/dist/src/cli/checkpoint-tap.d.ts +169 -0
- package/dist/src/cli/checkpoint-tap.js +238 -0
- package/dist/src/cli/checkpoint-tap.js.map +1 -0
- package/dist/src/cli/codex.d.ts +2 -0
- package/dist/src/cli/codex.js +172 -0
- package/dist/src/cli/codex.js.map +1 -0
- package/dist/src/cli/coverage.d.ts +61 -0
- package/dist/src/cli/coverage.js +343 -0
- package/dist/src/cli/coverage.js.map +1 -0
- package/dist/src/cli/daemon.d.ts +120 -0
- package/dist/src/cli/daemon.js +631 -0
- package/dist/src/cli/daemon.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +129 -0
- package/dist/src/cli/doctor.js +2762 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/env.d.ts +65 -0
- package/dist/src/cli/env.js +302 -0
- package/dist/src/cli/env.js.map +1 -0
- package/dist/src/cli/execute.d.ts +202 -0
- package/dist/src/cli/execute.js +1682 -0
- package/dist/src/cli/execute.js.map +1 -0
- package/dist/src/cli/exit-codes.d.ts +73 -0
- package/dist/src/cli/exit-codes.js +82 -0
- package/dist/src/cli/exit-codes.js.map +1 -0
- package/dist/src/cli/feedback.d.ts +60 -0
- package/dist/src/cli/feedback.js +205 -0
- package/dist/src/cli/feedback.js.map +1 -0
- package/dist/src/cli/gate-window.d.ts +40 -0
- package/dist/src/cli/gate-window.js +294 -0
- package/dist/src/cli/gate-window.js.map +1 -0
- package/dist/src/cli/gate.d.ts +68 -0
- package/dist/src/cli/gate.js +557 -0
- package/dist/src/cli/gate.js.map +1 -0
- package/dist/src/cli/git-scope.d.ts +190 -0
- package/dist/src/cli/git-scope.js +295 -0
- package/dist/src/cli/git-scope.js.map +1 -0
- package/dist/src/cli/gloss-attach.d.ts +85 -0
- package/dist/src/cli/gloss-attach.js +107 -0
- package/dist/src/cli/gloss-attach.js.map +1 -0
- package/dist/src/cli/gloss-codex-child.d.ts +9 -0
- package/dist/src/cli/gloss-codex-child.js +149 -0
- package/dist/src/cli/gloss-codex-child.js.map +1 -0
- package/dist/src/cli/gloss-codex.d.ts +24 -0
- package/dist/src/cli/gloss-codex.js +255 -0
- package/dist/src/cli/gloss-codex.js.map +1 -0
- package/dist/src/cli/gloss-options.d.ts +42 -0
- package/dist/src/cli/gloss-options.js +79 -0
- package/dist/src/cli/gloss-options.js.map +1 -0
- package/dist/src/cli/gloss.d.ts +265 -0
- package/dist/src/cli/gloss.js +362 -0
- package/dist/src/cli/gloss.js.map +1 -0
- package/dist/src/cli/help.d.ts +103 -0
- package/dist/src/cli/help.js +2339 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hook-codex.d.ts +78 -0
- package/dist/src/cli/hook-codex.js +167 -0
- package/dist/src/cli/hook-codex.js.map +1 -0
- package/dist/src/cli/hook.d.ts +331 -0
- package/dist/src/cli/hook.js +2849 -0
- package/dist/src/cli/hook.js.map +1 -0
- package/dist/src/cli/import.d.ts +35 -0
- package/dist/src/cli/import.js +175 -0
- package/dist/src/cli/import.js.map +1 -0
- package/dist/src/cli/init.d.ts +84 -0
- package/dist/src/cli/init.js +336 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/instructions.d.ts +23 -0
- package/dist/src/cli/instructions.js +262 -0
- package/dist/src/cli/instructions.js.map +1 -0
- package/dist/src/cli/journal.d.ts +41 -0
- package/dist/src/cli/journal.js +238 -0
- package/dist/src/cli/journal.js.map +1 -0
- package/dist/src/cli/log-advance.d.ts +287 -0
- package/dist/src/cli/log-advance.js +840 -0
- package/dist/src/cli/log-advance.js.map +1 -0
- package/dist/src/cli/log-anchor.d.ts +176 -0
- package/dist/src/cli/log-anchor.js +387 -0
- package/dist/src/cli/log-anchor.js.map +1 -0
- package/dist/src/cli/log-checkpoint.d.ts +22 -0
- package/dist/src/cli/log-checkpoint.js +128 -0
- package/dist/src/cli/log-checkpoint.js.map +1 -0
- package/dist/src/cli/log-sync.d.ts +243 -0
- package/dist/src/cli/log-sync.js +849 -0
- package/dist/src/cli/log-sync.js.map +1 -0
- package/dist/src/cli/log-verbs.d.ts +16 -0
- package/dist/src/cli/log-verbs.js +360 -0
- package/dist/src/cli/log-verbs.js.map +1 -0
- package/dist/src/cli/long-help.d.ts +70 -0
- package/dist/src/cli/long-help.js +148 -0
- package/dist/src/cli/long-help.js.map +1 -0
- package/dist/src/cli/main.d.ts +77 -0
- package/dist/src/cli/main.js +1206 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/mcp.d.ts +52 -0
- package/dist/src/cli/mcp.js +306 -0
- package/dist/src/cli/mcp.js.map +1 -0
- package/dist/src/cli/paths.d.ts +56 -0
- package/dist/src/cli/paths.js +79 -0
- package/dist/src/cli/paths.js.map +1 -0
- package/dist/src/cli/payload.d.ts +58 -0
- package/dist/src/cli/payload.js +253 -0
- package/dist/src/cli/payload.js.map +1 -0
- package/dist/src/cli/policy.d.ts +43 -0
- package/dist/src/cli/policy.js +229 -0
- package/dist/src/cli/policy.js.map +1 -0
- package/dist/src/cli/preflight.d.ts +363 -0
- package/dist/src/cli/preflight.js +1175 -0
- package/dist/src/cli/preflight.js.map +1 -0
- package/dist/src/cli/progress.d.ts +78 -0
- package/dist/src/cli/progress.js +112 -0
- package/dist/src/cli/progress.js.map +1 -0
- package/dist/src/cli/prompt.d.ts +209 -0
- package/dist/src/cli/prompt.js +312 -0
- package/dist/src/cli/prompt.js.map +1 -0
- package/dist/src/cli/quickstart.d.ts +46 -0
- package/dist/src/cli/quickstart.js +297 -0
- package/dist/src/cli/quickstart.js.map +1 -0
- package/dist/src/cli/records.d.ts +34 -0
- package/dist/src/cli/records.js +66 -0
- package/dist/src/cli/records.js.map +1 -0
- package/dist/src/cli/render.d.ts +22 -0
- package/dist/src/cli/render.js +132 -0
- package/dist/src/cli/render.js.map +1 -0
- package/dist/src/cli/sandbox.d.ts +51 -0
- package/dist/src/cli/sandbox.js +150 -0
- package/dist/src/cli/sandbox.js.map +1 -0
- package/dist/src/cli/scaffold.d.ts +79 -0
- package/dist/src/cli/scaffold.js +137 -0
- package/dist/src/cli/scaffold.js.map +1 -0
- package/dist/src/cli/setup-adapter.d.ts +137 -0
- package/dist/src/cli/setup-adapter.js +509 -0
- package/dist/src/cli/setup-adapter.js.map +1 -0
- package/dist/src/cli/setup-channel.d.ts +117 -0
- package/dist/src/cli/setup-channel.js +635 -0
- package/dist/src/cli/setup-channel.js.map +1 -0
- package/dist/src/cli/setup-checkpoint.d.ts +57 -0
- package/dist/src/cli/setup-checkpoint.js +196 -0
- package/dist/src/cli/setup-checkpoint.js.map +1 -0
- package/dist/src/cli/setup-common.d.ts +275 -0
- package/dist/src/cli/setup-common.js +376 -0
- package/dist/src/cli/setup-common.js.map +1 -0
- package/dist/src/cli/setup-flow.d.ts +287 -0
- package/dist/src/cli/setup-flow.js +476 -0
- package/dist/src/cli/setup-flow.js.map +1 -0
- package/dist/src/cli/setup-service.d.ts +96 -0
- package/dist/src/cli/setup-service.js +308 -0
- package/dist/src/cli/setup-service.js.map +1 -0
- package/dist/src/cli/setup.d.ts +202 -0
- package/dist/src/cli/setup.js +473 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/style.d.ts +320 -0
- package/dist/src/cli/style.js +469 -0
- package/dist/src/cli/style.js.map +1 -0
- package/dist/src/cli/token.d.ts +39 -0
- package/dist/src/cli/token.js +274 -0
- package/dist/src/cli/token.js.map +1 -0
- package/dist/src/cli/up.d.ts +155 -0
- package/dist/src/cli/up.js +849 -0
- package/dist/src/cli/up.js.map +1 -0
- package/dist/src/cli/usage.d.ts +37 -0
- package/dist/src/cli/usage.js +91 -0
- package/dist/src/cli/usage.js.map +1 -0
- package/dist/src/cli/values.d.ts +40 -0
- package/dist/src/cli/values.js +189 -0
- package/dist/src/cli/values.js.map +1 -0
- package/dist/src/cli/vault.d.ts +59 -0
- package/dist/src/cli/vault.js +362 -0
- package/dist/src/cli/vault.js.map +1 -0
- package/dist/src/cli/verb-registry.d.ts +76 -0
- package/dist/src/cli/verb-registry.js +2341 -0
- package/dist/src/cli/verb-registry.js.map +1 -0
- package/dist/src/cli/wordmark.d.ts +31 -0
- package/dist/src/cli/wordmark.js +52 -0
- package/dist/src/cli/wordmark.js.map +1 -0
- package/dist/src/codex/doctor.d.ts +13 -0
- package/dist/src/codex/doctor.js +41 -0
- package/dist/src/codex/doctor.js.map +1 -0
- package/dist/src/codex/manifest.d.ts +49 -0
- package/dist/src/codex/manifest.js +103 -0
- package/dist/src/codex/manifest.js.map +1 -0
- package/dist/src/codex/templates.d.ts +41 -0
- package/dist/src/codex/templates.js +319 -0
- package/dist/src/codex/templates.js.map +1 -0
- package/dist/src/codex/trust.d.ts +19 -0
- package/dist/src/codex/trust.js +183 -0
- package/dist/src/codex/trust.js.map +1 -0
- package/dist/src/codex/workspace-plan.d.ts +131 -0
- package/dist/src/codex/workspace-plan.js +561 -0
- package/dist/src/codex/workspace-plan.js.map +1 -0
- package/dist/src/core/actor.d.ts +2 -0
- package/dist/src/core/actor.js +5 -0
- package/dist/src/core/actor.js.map +1 -0
- package/dist/src/core/advance-cycle.d.ts +170 -0
- package/dist/src/core/advance-cycle.js +200 -0
- package/dist/src/core/advance-cycle.js.map +1 -0
- package/dist/src/core/agents-md.d.ts +276 -0
- package/dist/src/core/agents-md.js +747 -0
- package/dist/src/core/agents-md.js.map +1 -0
- package/dist/src/core/apply-patch.d.ts +49 -0
- package/dist/src/core/apply-patch.js +266 -0
- package/dist/src/core/apply-patch.js.map +1 -0
- package/dist/src/core/attest.d.ts +420 -0
- package/dist/src/core/attest.js +589 -0
- package/dist/src/core/attest.js.map +1 -0
- package/dist/src/core/audit.d.ts +492 -0
- package/dist/src/core/audit.js +882 -0
- package/dist/src/core/audit.js.map +1 -0
- package/dist/src/core/budgets.d.ts +238 -0
- package/dist/src/core/budgets.js +449 -0
- package/dist/src/core/budgets.js.map +1 -0
- package/dist/src/core/checkpoint.d.ts +500 -0
- package/dist/src/core/checkpoint.js +738 -0
- package/dist/src/core/checkpoint.js.map +1 -0
- package/dist/src/core/child-env.d.ts +88 -0
- package/dist/src/core/child-env.js +86 -0
- package/dist/src/core/child-env.js.map +1 -0
- package/dist/src/core/clock.d.ts +52 -0
- package/dist/src/core/clock.js +43 -0
- package/dist/src/core/clock.js.map +1 -0
- package/dist/src/core/command-class.d.ts +543 -0
- package/dist/src/core/command-class.js +2356 -0
- package/dist/src/core/command-class.js.map +1 -0
- package/dist/src/core/coverage-sources/adapter.d.ts +40 -0
- package/dist/src/core/coverage-sources/adapter.js +71 -0
- package/dist/src/core/coverage-sources/adapter.js.map +1 -0
- package/dist/src/core/coverage-sources/gh.d.ts +48 -0
- package/dist/src/core/coverage-sources/gh.js +136 -0
- package/dist/src/core/coverage-sources/gh.js.map +1 -0
- package/dist/src/core/coverage-sources/git.d.ts +101 -0
- package/dist/src/core/coverage-sources/git.js +269 -0
- package/dist/src/core/coverage-sources/git.js.map +1 -0
- package/dist/src/core/coverage.d.ts +217 -0
- package/dist/src/core/coverage.js +337 -0
- package/dist/src/core/coverage.js.map +1 -0
- package/dist/src/core/credential-spec.d.ts +72 -0
- package/dist/src/core/credential-spec.js +23 -0
- package/dist/src/core/credential-spec.js.map +1 -0
- package/dist/src/core/dark-session.d.ts +331 -0
- package/dist/src/core/dark-session.js +714 -0
- package/dist/src/core/dark-session.js.map +1 -0
- package/dist/src/core/decision-refusal.d.ts +185 -0
- package/dist/src/core/decision-refusal.js +265 -0
- package/dist/src/core/decision-refusal.js.map +1 -0
- package/dist/src/core/env-file.d.ts +450 -0
- package/dist/src/core/env-file.js +837 -0
- package/dist/src/core/env-file.js.map +1 -0
- package/dist/src/core/execute.d.ts +858 -0
- package/dist/src/core/execute.js +1271 -0
- package/dist/src/core/execute.js.map +1 -0
- package/dist/src/core/frontmatter.d.ts +78 -0
- package/dist/src/core/frontmatter.js +100 -0
- package/dist/src/core/frontmatter.js.map +1 -0
- package/dist/src/core/gate-window.d.ts +312 -0
- package/dist/src/core/gate-window.js +506 -0
- package/dist/src/core/gate-window.js.map +1 -0
- package/dist/src/core/gate.d.ts +1364 -0
- package/dist/src/core/gate.js +3002 -0
- package/dist/src/core/gate.js.map +1 -0
- package/dist/src/core/git-run.d.ts +73 -0
- package/dist/src/core/git-run.js +93 -0
- package/dist/src/core/git-run.js.map +1 -0
- package/dist/src/core/harness-version.d.ts +157 -0
- package/dist/src/core/harness-version.js +211 -0
- package/dist/src/core/harness-version.js.map +1 -0
- package/dist/src/core/harness-wait.d.ts +55 -0
- package/dist/src/core/harness-wait.js +58 -0
- package/dist/src/core/harness-wait.js.map +1 -0
- package/dist/src/core/head-retry.d.ts +107 -0
- package/dist/src/core/head-retry.js +121 -0
- package/dist/src/core/head-retry.js.map +1 -0
- package/dist/src/core/instance.d.ts +253 -0
- package/dist/src/core/instance.js +319 -0
- package/dist/src/core/instance.js.map +1 -0
- package/dist/src/core/intake-limits.d.ts +247 -0
- package/dist/src/core/intake-limits.js +350 -0
- package/dist/src/core/intake-limits.js.map +1 -0
- package/dist/src/core/jcs.d.ts +52 -0
- package/dist/src/core/jcs.js +132 -0
- package/dist/src/core/jcs.js.map +1 -0
- package/dist/src/core/journal.d.ts +144 -0
- package/dist/src/core/journal.js +200 -0
- package/dist/src/core/journal.js.map +1 -0
- package/dist/src/core/live-draw.d.ts +436 -0
- package/dist/src/core/live-draw.js +703 -0
- package/dist/src/core/live-draw.js.map +1 -0
- package/dist/src/core/log-reconcile.d.ts +89 -0
- package/dist/src/core/log-reconcile.js +136 -0
- package/dist/src/core/log-reconcile.js.map +1 -0
- package/dist/src/core/log-subscribe.d.ts +36 -0
- package/dist/src/core/log-subscribe.js +162 -0
- package/dist/src/core/log-subscribe.js.map +1 -0
- package/dist/src/core/log.d.ts +278 -0
- package/dist/src/core/log.js +546 -0
- package/dist/src/core/log.js.map +1 -0
- package/dist/src/core/loop.d.ts +274 -0
- package/dist/src/core/loop.js +487 -0
- package/dist/src/core/loop.js.map +1 -0
- package/dist/src/core/md-fence.d.ts +41 -0
- package/dist/src/core/md-fence.js +74 -0
- package/dist/src/core/md-fence.js.map +1 -0
- package/dist/src/core/money.d.ts +147 -0
- package/dist/src/core/money.js +195 -0
- package/dist/src/core/money.js.map +1 -0
- package/dist/src/core/payload-census.d.ts +74 -0
- package/dist/src/core/payload-census.js +146 -0
- package/dist/src/core/payload-census.js.map +1 -0
- package/dist/src/core/payload-store.d.ts +175 -0
- package/dist/src/core/payload-store.js +340 -0
- package/dist/src/core/payload-store.js.map +1 -0
- package/dist/src/core/payload.d.ts +71 -0
- package/dist/src/core/payload.js +80 -0
- package/dist/src/core/payload.js.map +1 -0
- package/dist/src/core/policy-diff.d.ts +292 -0
- package/dist/src/core/policy-diff.js +588 -0
- package/dist/src/core/policy-diff.js.map +1 -0
- package/dist/src/core/policy-expectations.d.ts +199 -0
- package/dist/src/core/policy-expectations.js +394 -0
- package/dist/src/core/policy-expectations.js.map +1 -0
- package/dist/src/core/policy-explain.d.ts +150 -0
- package/dist/src/core/policy-explain.js +258 -0
- package/dist/src/core/policy-explain.js.map +1 -0
- package/dist/src/core/policy-load.d.ts +527 -0
- package/dist/src/core/policy-load.js +536 -0
- package/dist/src/core/policy-load.js.map +1 -0
- package/dist/src/core/policy-match.d.ts +281 -0
- package/dist/src/core/policy-match.js +478 -0
- package/dist/src/core/policy-match.js.map +1 -0
- package/dist/src/core/policy-proposal.d.ts +265 -0
- package/dist/src/core/policy-proposal.js +458 -0
- package/dist/src/core/policy-proposal.js.map +1 -0
- package/dist/src/core/prompt-layout.d.ts +221 -0
- package/dist/src/core/prompt-layout.js +422 -0
- package/dist/src/core/prompt-layout.js.map +1 -0
- package/dist/src/core/protected-path-guard.d.ts +453 -0
- package/dist/src/core/protected-path-guard.js +1566 -0
- package/dist/src/core/protected-path-guard.js.map +1 -0
- package/dist/src/core/registration.d.ts +25 -0
- package/dist/src/core/registration.js +39 -0
- package/dist/src/core/registration.js.map +1 -0
- package/dist/src/core/reindex.d.ts +99 -0
- package/dist/src/core/reindex.js +336 -0
- package/dist/src/core/reindex.js.map +1 -0
- package/dist/src/core/sampler.d.ts +313 -0
- package/dist/src/core/sampler.js +388 -0
- package/dist/src/core/sampler.js.map +1 -0
- package/dist/src/core/sandbox.d.ts +290 -0
- package/dist/src/core/sandbox.js +424 -0
- package/dist/src/core/sandbox.js.map +1 -0
- package/dist/src/core/seal.d.ts +165 -0
- package/dist/src/core/seal.js +290 -0
- package/dist/src/core/seal.js.map +1 -0
- package/dist/src/core/state.d.ts +505 -0
- package/dist/src/core/state.js +1009 -0
- package/dist/src/core/state.js.map +1 -0
- package/dist/src/core/task-file.d.ts +185 -0
- package/dist/src/core/task-file.js +464 -0
- package/dist/src/core/task-file.js.map +1 -0
- package/dist/src/core/telegram-config.d.ts +93 -0
- package/dist/src/core/telegram-config.js +114 -0
- package/dist/src/core/telegram-config.js.map +1 -0
- package/dist/src/core/token.d.ts +409 -0
- package/dist/src/core/token.js +561 -0
- package/dist/src/core/token.js.map +1 -0
- package/dist/src/core/validate.d.ts +138 -0
- package/dist/src/core/validate.js +0 -0
- package/dist/src/core/validate.js.map +1 -0
- package/dist/src/core/values.d.ts +137 -0
- package/dist/src/core/values.js +153 -0
- package/dist/src/core/values.js.map +1 -0
- package/dist/src/core/vault.d.ts +291 -0
- package/dist/src/core/vault.js +612 -0
- package/dist/src/core/vault.js.map +1 -0
- package/dist/src/core/verified-snapshot.d.ts +204 -0
- package/dist/src/core/verified-snapshot.js +506 -0
- package/dist/src/core/verified-snapshot.js.map +1 -0
- package/dist/src/core/verify.d.ts +336 -0
- package/dist/src/core/verify.js +549 -0
- package/dist/src/core/verify.js.map +1 -0
- package/dist/src/core/version.d.ts +8 -0
- package/dist/src/core/version.js +9 -0
- package/dist/src/core/version.js.map +1 -0
- package/dist/src/core/wysiwys.d.ts +370 -0
- package/dist/src/core/wysiwys.js +728 -0
- package/dist/src/core/wysiwys.js.map +1 -0
- package/dist/src/daemon/advance-child.d.ts +39 -0
- package/dist/src/daemon/advance-child.js +78 -0
- package/dist/src/daemon/advance-child.js.map +1 -0
- package/dist/src/daemon/advance.d.ts +466 -0
- package/dist/src/daemon/advance.js +849 -0
- package/dist/src/daemon/advance.js.map +1 -0
- package/dist/src/daemon/audit.d.ts +87 -0
- package/dist/src/daemon/audit.js +90 -0
- package/dist/src/daemon/audit.js.map +1 -0
- package/dist/src/daemon/daemon.d.ts +1180 -0
- package/dist/src/daemon/daemon.js +1988 -0
- package/dist/src/daemon/daemon.js.map +1 -0
- package/dist/src/daemon/dark-session.d.ts +64 -0
- package/dist/src/daemon/dark-session.js +119 -0
- package/dist/src/daemon/dark-session.js.map +1 -0
- package/dist/src/daemon/draw-child.d.ts +36 -0
- package/dist/src/daemon/draw-child.js +132 -0
- package/dist/src/daemon/draw-child.js.map +1 -0
- package/dist/src/daemon/draw.d.ts +154 -0
- package/dist/src/daemon/draw.js +458 -0
- package/dist/src/daemon/draw.js.map +1 -0
- package/dist/src/daemon/git-evidence.d.ts +173 -0
- package/dist/src/daemon/git-evidence.js +345 -0
- package/dist/src/daemon/git-evidence.js.map +1 -0
- package/dist/src/daemon/projection.d.ts +180 -0
- package/dist/src/daemon/projection.js +233 -0
- package/dist/src/daemon/projection.js.map +1 -0
- package/dist/src/daemon/prune.d.ts +207 -0
- package/dist/src/daemon/prune.js +376 -0
- package/dist/src/daemon/prune.js.map +1 -0
- package/dist/src/mcp/http.d.ts +113 -0
- package/dist/src/mcp/http.js +343 -0
- package/dist/src/mcp/http.js.map +1 -0
- package/dist/src/mcp/server.d.ts +265 -0
- package/dist/src/mcp/server.js +602 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/docs/adapter-api.md +106 -0
- package/docs/cli-reference.md +5716 -0
- package/docs/codex-enforced-session.md +30 -0
- package/package.json +53 -4
- package/schema/.gitkeep +0 -0
- package/schema/LICENSE +117 -0
- package/schema/codex-instance.schema.json +82 -0
- package/schema/envelope.schema.json +137 -0
- package/schema/event.schema.json +1811 -0
- package/schema/fixtures/codex-instance/invalid/unpinned-codex-version.json +40 -0
- package/schema/fixtures/codex-instance/valid/canonical.json +40 -0
- package/schema/fixtures/envelope/invalid/action-missing-idempotency-key.json +15 -0
- package/schema/fixtures/envelope/invalid/action-unknown-class-format.json +14 -0
- package/schema/fixtures/envelope/invalid/confidence-out-of-range.json +11 -0
- package/schema/fixtures/envelope/invalid/est-cost-bare-number.json +14 -0
- package/schema/fixtures/envelope/invalid/est-cost-noncanonical-string.json +14 -0
- package/schema/fixtures/envelope/invalid/malformed-assignee.json +10 -0
- package/schema/fixtures/envelope/invalid/malformed-created-by.json +7 -0
- package/schema/fixtures/envelope/invalid/malformed-max-latency.json +11 -0
- package/schema/fixtures/envelope/invalid/malformed-payload-hash.json +14 -0
- package/schema/fixtures/envelope/invalid/max-cost-bare-number.json +11 -0
- package/schema/fixtures/envelope/invalid/missing-origin.json +3 -0
- package/schema/fixtures/envelope/invalid/negative-est-cost.json +14 -0
- package/schema/fixtures/envelope/invalid/unknown-state.json +7 -0
- package/schema/fixtures/envelope/invalid/unknown-top-level-field.json +8 -0
- package/schema/fixtures/envelope/valid/action-payload-hash.json +17 -0
- package/schema/fixtures/envelope/valid/actions-without-budget.json +18 -0
- package/schema/fixtures/envelope/valid/canonical.json +25 -0
- package/schema/fixtures/envelope/valid/minimal.json +7 -0
- package/schema/fixtures/envelope/valid/multi-action-executed.json +30 -0
- package/schema/fixtures/envelope/valid/record-write-stage.json +22 -0
- package/schema/fixtures/event/invalid/approval-granted-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/approval-granted-empty-batch-delivery-id.json +17 -0
- package/schema/fixtures/event/invalid/approval-granted-fifth-reaction.json +16 -0
- package/schema/fixtures/event/invalid/approval-granted-missing-actor.json +14 -0
- package/schema/fixtures/event/invalid/approval-requested-missing-action-key.json +14 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-agent-policy-drift.json +15 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-missing-reason.json +15 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-system-actor.json +15 -0
- package/schema/fixtures/event/invalid/audit-decision-refused-human-actor.json +17 -0
- package/schema/fixtures/event/invalid/audit-decision-refused-missing-code.json +16 -0
- package/schema/fixtures/event/invalid/audit-reviewed-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/audit-reviewed-loved-no-note.json +16 -0
- package/schema/fixtures/event/invalid/audit-reviewed-system-actor.json +15 -0
- package/schema/fixtures/event/invalid/bad-actor-prefix.json +15 -0
- package/schema/fixtures/event/invalid/est-cost-bare-number.json +17 -0
- package/schema/fixtures/event/invalid/execution-completed-fabricated-exit-code.json +16 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-empty-id.json +18 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-extra-field.json +19 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-id-not-string.json +18 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-missing-adapter.json +17 -0
- package/schema/fixtures/event/invalid/execution-failed-open-reported-by.json +16 -0
- package/schema/fixtures/event/invalid/execution-indeterminate-open-reason.json +14 -0
- package/schema/fixtures/event/invalid/execution-reconciled-agent-actor.json +17 -0
- package/schema/fixtures/event/invalid/execution-started-negative-env-stripped.json +16 -0
- package/schema/fixtures/event/invalid/gate-bypassed-missing-opened-seq.json +15 -0
- package/schema/fixtures/event/invalid/gate-closed-non-integer-opened-seq.json +13 -0
- package/schema/fixtures/event/invalid/gate-opened-agent-actor.json +16 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-absolute-path.json +14 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-agent-actor.json +14 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-missing-organ-path.json +13 -0
- package/schema/fixtures/event/invalid/harness-unknown-kind.json +18 -0
- package/schema/fixtures/event/invalid/harness-version-multiline.json +16 -0
- package/schema/fixtures/event/invalid/log-checkpoint-agent-actor.json +17 -0
- package/schema/fixtures/event/invalid/log-checkpoint-missing-signature.json +16 -0
- package/schema/fixtures/event/invalid/log-checkpoint-short-signed-hash.json +17 -0
- package/schema/fixtures/event/invalid/log-checkpoint-unknown-signature-alg.json +17 -0
- package/schema/fixtures/event/invalid/malformed-ts.json +15 -0
- package/schema/fixtures/event/invalid/missing-alg.json +14 -0
- package/schema/fixtures/event/invalid/missing-hash.json +14 -0
- package/schema/fixtures/event/invalid/non-integer-seq.json +15 -0
- package/schema/fixtures/event/invalid/payload-pruned-human-actor.json +14 -0
- package/schema/fixtures/event/invalid/payload-pruned-missing-hash.json +14 -0
- package/schema/fixtures/event/invalid/policy-declined-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/policy-proposed-missing-diff.json +19 -0
- package/schema/fixtures/event/invalid/policy-proposed-system-actor.json +26 -0
- package/schema/fixtures/event/invalid/short-hash.json +15 -0
- package/schema/fixtures/event/invalid/unknown-alg.json +15 -0
- package/schema/fixtures/event/invalid/unknown-event-type.json +15 -0
- package/schema/fixtures/event/invalid/unknown-top-level-field.json +16 -0
- package/schema/fixtures/event/valid/approval-expired.json +15 -0
- package/schema/fixtures/event/valid/approval-granted-batch.json +19 -0
- package/schema/fixtures/event/valid/approval-granted-reaction.json +16 -0
- package/schema/fixtures/event/valid/approval-granted.json +15 -0
- package/schema/fixtures/event/valid/approval-rejected.json +15 -0
- package/schema/fixtures/event/valid/approval-requested.json +19 -0
- package/schema/fixtures/event/valid/approval-revoked.json +15 -0
- package/schema/fixtures/event/valid/approval-withdrawn-policy-drift.json +17 -0
- package/schema/fixtures/event/valid/approval-withdrawn.json +16 -0
- package/schema/fixtures/event/valid/audit-decision-refused.json +20 -0
- package/schema/fixtures/event/valid/audit-reviewed-reaction.json +17 -0
- package/schema/fixtures/event/valid/audit-reviewed.json +15 -0
- package/schema/fixtures/event/valid/audit-sampled.json +14 -0
- package/schema/fixtures/event/valid/budget-exceeded.json +21 -0
- package/schema/fixtures/event/valid/envelope-drift.json +16 -0
- package/schema/fixtures/event/valid/execution-completed-harness-report.json +16 -0
- package/schema/fixtures/event/valid/execution-completed-provider-ref.json +18 -0
- package/schema/fixtures/event/valid/execution-completed.json +15 -0
- package/schema/fixtures/event/valid/execution-failed-harness-report.json +16 -0
- package/schema/fixtures/event/valid/execution-failed.json +15 -0
- package/schema/fixtures/event/valid/execution-indeterminate.json +15 -0
- package/schema/fixtures/event/valid/execution-reconciled.json +17 -0
- package/schema/fixtures/event/valid/execution-started-env-stripped.json +17 -0
- package/schema/fixtures/event/valid/execution-started.json +14 -0
- package/schema/fixtures/event/valid/gate-bypassed-harness-version.json +18 -0
- package/schema/fixtures/event/valid/gate-bypassed.json +19 -0
- package/schema/fixtures/event/valid/gate-closed.json +14 -0
- package/schema/fixtures/event/valid/gate-opened.json +16 -0
- package/schema/fixtures/event/valid/gate-organ-attested.json +14 -0
- package/schema/fixtures/event/valid/genesis-null-prev.json +14 -0
- package/schema/fixtures/event/valid/log-checkpoint.json +17 -0
- package/schema/fixtures/event/valid/payload-pruned-orphan.json +13 -0
- package/schema/fixtures/event/valid/payload-pruned.json +17 -0
- package/schema/fixtures/event/valid/policy-declined.json +16 -0
- package/schema/fixtures/event/valid/policy-proposed.json +35 -0
- package/schema/fixtures/event/valid/policy-updated.json +14 -0
- package/schema/fixtures/event/valid/reconciliation-required.json +18 -0
- package/schema/fixtures/event/valid/reconciliation-satisfied.json +17 -0
- package/schema/fixtures/event/valid/route-accepted.json +15 -0
- package/schema/fixtures/event/valid/route-proposed.json +16 -0
- package/schema/fixtures/event/valid/spec-example.json +15 -0
- package/schema/fixtures/event/valid/task-registered-harness-version.json +23 -0
- package/schema/fixtures/event/valid/task-registered.json +14 -0
- package/schema/fixtures/hash/known-answer-pre-121.json +74 -0
- package/schema/fixtures/hash/known-answer.json +74 -0
- package/schema/fixtures/policy/invalid/bad-approval-ttl.json +7 -0
- package/schema/fixtures/policy/invalid/bad-web-port.json +4 -0
- package/schema/fixtures/policy/invalid/checkpoint-key-not-base64.json +6 -0
- package/schema/fixtures/policy/invalid/class-rule-missing-autonomy.json +9 -0
- package/schema/fixtures/policy/invalid/empty-class-key.json +6 -0
- package/schema/fixtures/policy/invalid/live-rate-on-human-only.json +7 -0
- package/schema/fixtures/policy/invalid/malformed-class-key.json +6 -0
- package/schema/fixtures/policy/invalid/missing-version.json +8 -0
- package/schema/fixtures/policy/invalid/negative-limit.json +9 -0
- package/schema/fixtures/policy/invalid/non-numeric-limit.json +9 -0
- package/schema/fixtures/policy/invalid/non-positive-max-pending.json +9 -0
- package/schema/fixtures/policy/invalid/on-expiry-grant.json +8 -0
- package/schema/fixtures/policy/invalid/payload-retention-bare-number.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-compound.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-fractional.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-zero.json +4 -0
- package/schema/fixtures/policy/invalid/protected-paths-escape.json +4 -0
- package/schema/fixtures/policy/invalid/protected-paths-glob.json +4 -0
- package/schema/fixtures/policy/invalid/retro-rate-on-human-only.json +7 -0
- package/schema/fixtures/policy/invalid/retro-rate-on-manual.json +7 -0
- package/schema/fixtures/policy/invalid/retro-rate-zero.json +7 -0
- package/schema/fixtures/policy/invalid/sample-rate-too-high.json +5 -0
- package/schema/fixtures/policy/invalid/sampling-secret-env-empty.json +7 -0
- package/schema/fixtures/policy/invalid/sampling-secret-env-not-string.json +6 -0
- package/schema/fixtures/policy/invalid/skew-tolerance-compound.json +6 -0
- package/schema/fixtures/policy/invalid/unknown-autonomy.json +7 -0
- package/schema/fixtures/policy/invalid/unknown-class-rule-key.json +6 -0
- package/schema/fixtures/policy/invalid/unknown-top-level-key.json +7 -0
- package/schema/fixtures/policy/invalid/vault-passphrase-env-empty.json +6 -0
- package/schema/fixtures/policy/invalid/vault-passphrase-literal.json +6 -0
- package/schema/fixtures/policy/invalid/version-not-string.json +4 -0
- package/schema/fixtures/policy/valid/canonical.json +47 -0
- package/schema/fixtures/policy/valid/checkpoint-keys.json +18 -0
- package/schema/fixtures/policy/valid/class-approvers-limits.json +25 -0
- package/schema/fixtures/policy/valid/class-retro-rate.json +17 -0
- package/schema/fixtures/policy/valid/global-budgets.json +19 -0
- package/schema/fixtures/policy/valid/human-only.json +9 -0
- package/schema/fixtures/policy/valid/minimal.json +6 -0
- package/schema/fixtures/policy/valid/protected-paths.json +10 -0
- package/schema/fixtures/policy/valid/record-namespace.json +13 -0
- package/schema/fixtures/policy/valid/request-volume-limits.json +26 -0
- package/schema/fixtures/policy/valid/retention-and-sampling-secret.json +16 -0
- package/schema/fixtures/policy/valid/skew-tolerance.json +15 -0
- package/schema/fixtures/policy/valid/vault-passphrase-env.json +14 -0
- package/schema/fixtures/policy/valid/wildcards.json +15 -0
- package/schema/fixtures/policy-md/invalid/alias-bomb.md +15 -0
- package/schema/fixtures/policy-md/invalid/no-fence.md +7 -0
- package/schema/fixtures/policy-md/invalid/protected-route-not-a-subclass.md +16 -0
- package/schema/fixtures/policy-md/invalid/schema-invalid-autonomy.md +16 -0
- package/schema/fixtures/policy-md/invalid/schema-invalid-read-proof.md +17 -0
- package/schema/fixtures/policy-md/invalid/two-fences.md +19 -0
- package/schema/fixtures/policy-md/invalid/unclosed-fence.md +11 -0
- package/schema/fixtures/policy-md/invalid/wrong-info-string.md +11 -0
- package/schema/fixtures/policy-md/invalid/yaml-syntax-error.md +13 -0
- package/schema/fixtures/policy-md/precedence/both/APPROVAL.md +7 -0
- package/schema/fixtures/policy-md/precedence/both/APPROVALS.md +7 -0
- package/schema/fixtures/policy-md/precedence/fallback-only/APPROVALS.md +7 -0
- package/schema/fixtures/policy-md/valid/canonical.md +50 -0
- package/schema/fixtures/policy-md/valid/daemon-read-proof.md +18 -0
- package/schema/fixtures/policy-md/valid/minimal.md +3 -0
- package/schema/fixtures/policy-md/valid/prose-lookalikes.md +54 -0
- package/schema/fixtures/policy-md/valid/routed-protected-paths.md +49 -0
- package/schema/fixtures/policy-md/valid/with-values.md +79 -0
- package/schema/fixtures/sample-record/invalid/bad-date-time.json +4 -0
- package/schema/fixtures/sample-record/invalid/missing-required-field.json +3 -0
- package/schema/fixtures/sample-record/invalid/unknown-top-level-field.json +5 -0
- package/schema/fixtures/sample-record/invalid/wrong-type.json +4 -0
- package/schema/fixtures/sample-record/valid/minimal.json +4 -0
- package/schema/fixtures/sample-record/valid/with-note.json +5 -0
- package/schema/fixtures/values/invalid/class-shaped.json +9 -0
- package/schema/fixtures/values/invalid/duplicate-entry.json +4 -0
- package/schema/fixtures/values/invalid/non-string-item.json +4 -0
- package/schema/fixtures/values/invalid/over-cap.json +26 -0
- package/schema/fixtures/values/invalid/unknown-key.json +5 -0
- package/schema/fixtures/values/invalid/version-string.json +1 -0
- package/schema/fixtures/values/valid/empty-lists.json +7 -0
- package/schema/fixtures/values/valid/full.json +20 -0
- package/schema/fixtures/values/valid/minimal.json +1 -0
- package/schema/fixtures/values-md/invalid/schema-invalid.md +62 -0
- package/schema/fixtures/values-md/invalid/two-blocks.md +69 -0
- package/schema/fixtures/values-md/invalid/unterminated.md +61 -0
- package/schema/fixtures/values-md/invalid/yaml-error.md +63 -0
- package/schema/fixtures/values-md/valid/absent.md +50 -0
- package/schema/fixtures/values-md/valid/with-values.md +79 -0
- package/schema/policy.schema.json +501 -0
- package/schema/sample-record.schema.json +26 -0
- package/schema/values.schema.json +55 -0
- package/templates/codex/README.md +9 -0
|
@@ -0,0 +1,806 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval channel telegram listen | health` — the runtime half of the
|
|
3
|
+
* Telegram channel (SPEC.md §10.3, APRV-26).
|
|
4
|
+
*
|
|
5
|
+
* As everywhere else in this CLI, **no logic lives here**. The rendering and
|
|
6
|
+
* the Bot API are `channels/telegram.ts`; turning a button press into an event
|
|
7
|
+
* is `channels/contract.ts`'s `recordChannelDecision`, which calls the
|
|
8
|
+
* human-only `decide()` in `core/gate.ts`. This file resolves configuration,
|
|
9
|
+
* builds the pending queue, wires the two together, and chooses an exit code.
|
|
10
|
+
*
|
|
11
|
+
* Three things it does that the channel deliberately cannot:
|
|
12
|
+
*
|
|
13
|
+
* 1. **It reads the environment.** `APPROVAL_TG_TOKEN` and `APPROVAL_TG_CHAT`
|
|
14
|
+
* are read here and passed to the channel as values (SPEC.md §5.1: policy
|
|
15
|
+
* carries the env-var *names*, never the secrets). Nothing in `channels/`
|
|
16
|
+
* touches `process.env`.
|
|
17
|
+
* 2. **It declares who is approving.** The decision is recorded against the
|
|
18
|
+
* human actor from `--as` / `APPROVAL_HUMAN`, never against anything the
|
|
19
|
+
* callback carried. SPEC.md §11: identity in v0.1 is config-declared, the
|
|
20
|
+
* trust boundary is the local machine, and everyone who can reach the
|
|
21
|
+
* configured chat can approve as that actor. This is stated in `--help`
|
|
22
|
+
* because an operator has to be able to see it without reading the source.
|
|
23
|
+
* 3. **It holds the token.** A grant mints a single-use execution token;
|
|
24
|
+
* `recordChannelDecision` returns it to *this* handler, which prints it on
|
|
25
|
+
* **stdout** and never hands it back to the channel. It is never sent to
|
|
26
|
+
* Telegram — see the module doc of `channels/telegram.ts` for why a chat
|
|
27
|
+
* transcript is not a credential store, and for the flag on that decision.
|
|
28
|
+
*
|
|
29
|
+
* ## Payload material — the store, and why `--payloads` still exists
|
|
30
|
+
*
|
|
31
|
+
* SPEC.md §6.2 records a `payload_hash` in the log and never the bytes, and
|
|
32
|
+
* §10.4 requires a channel to present the full payload for a manual action. So
|
|
33
|
+
* the bytes must come from somewhere the runtime can reach. Since APRV-28 that
|
|
34
|
+
* somewhere is the payload store beside the log (`.approval/payloads/`, written
|
|
35
|
+
* by `approval request --payload`), and a listener ordinarily needs no payload
|
|
36
|
+
* flag at all. `--payloads` remains an override for bytes an operator holds
|
|
37
|
+
* elsewhere: a JSON file mapping action key to that action's payload value,
|
|
38
|
+
* consulted before the store. The tagger
|
|
39
|
+
* (`channels/tagging.ts`) re-hashes whatever it is given and refuses anything
|
|
40
|
+
* that does not match the recorded binding, so a wrong or stale file cannot put
|
|
41
|
+
* different bytes in front of an approver than the token will execute — it
|
|
42
|
+
* produces a visible skip instead. Requests whose material is missing are
|
|
43
|
+
* reported on stderr and NOT delivered: a manual request rendered without its
|
|
44
|
+
* payload would be exactly the §10.4 violation the contract refuses.
|
|
45
|
+
*
|
|
46
|
+
* ## Dispatch: where it lives, and why it lives here (APRV-55) — flagged
|
|
47
|
+
*
|
|
48
|
+
* SPEC.md §10.2 lists "dispatches channel notifications" among the daemon's
|
|
49
|
+
* jobs. At v0.1 the reference runtime performs that dispatch **in this
|
|
50
|
+
* listener**, on every poll cycle, and the placement is deliberate:
|
|
51
|
+
*
|
|
52
|
+
* 1. The listener already holds the channel connection (the bot token, the
|
|
53
|
+
* chat id) and the approver identity. The daemon holds neither, and giving
|
|
54
|
+
* it either would put a credential and a human identity into a process
|
|
55
|
+
* whose job is to read files and append events.
|
|
56
|
+
* 2. The daemon is the sole writer of the log; dispatch appends nothing. Moving
|
|
57
|
+
* a read-and-send out of the daemon costs the single-writer stance nothing,
|
|
58
|
+
* because dispatch was never a write.
|
|
59
|
+
* 3. A network round-trip inside the daemon's tick couples the projection loop
|
|
60
|
+
* to Telegram's availability. A slow Bot API would delay TTL expiry and
|
|
61
|
+
* write-back, which are the daemon's actual obligations.
|
|
62
|
+
*
|
|
63
|
+
* So this is an implementation placement, not a change to the daemon's stated
|
|
64
|
+
* role: a later build MAY move dispatch into the daemon (or a supervisor) with
|
|
65
|
+
* no change to the log or to any event shape. SPEC.md §10.3 records the same.
|
|
66
|
+
*
|
|
67
|
+
* ### The cycle
|
|
68
|
+
*
|
|
69
|
+
* {@link dispatchPending} runs before every `getUpdates` — the startup send and
|
|
70
|
+
* every later cycle are the same call with the same state, the startup one
|
|
71
|
+
* merely finding an empty delivered set. Each call **re-derives** the pending
|
|
72
|
+
* queue from the verified log ({@link buildPendingQueue}), so which requests
|
|
73
|
+
* are pending is always the log's answer and never this process's memory. A
|
|
74
|
+
* request appended while the listener is running is therefore delivered on the
|
|
75
|
+
* next cycle, without a restart; a request that was decided or whose TTL lapsed
|
|
76
|
+
* simply stops appearing in the derivation and is never sent.
|
|
77
|
+
*
|
|
78
|
+
* What *is* remembered, and only in {@link DispatchState} for this process's
|
|
79
|
+
* lifetime, is which action keys this listener has already put on the phone.
|
|
80
|
+
* Losing that memory (a restart, a crash) re-sends everything still pending:
|
|
81
|
+
* a duplicate on the phone, never silence. That direction is the whole design
|
|
82
|
+
* (SPEC.md §10.3: channels hold no state that is a source of truth).
|
|
83
|
+
*
|
|
84
|
+
* APRV-196 made that re-send legible rather than rarer. The first batch a
|
|
85
|
+
* process sends is preceded by one banner naming how many are coming, the
|
|
86
|
+
* copies already in the chat keep working (`actionRefOf` in
|
|
87
|
+
* `channels/telegram.ts` resolves their buttons to the same request), and the
|
|
88
|
+
* bookkeeping above is pruned as requests settle and age out instead of growing
|
|
89
|
+
* for the life of a listener that `approval up` keeps running for weeks.
|
|
90
|
+
*
|
|
91
|
+
* ### Send failures
|
|
92
|
+
*
|
|
93
|
+
* A key that fails to send stays undelivered, so the next cycle retries it.
|
|
94
|
+
* There is **no attempt limit**: giving up would turn a transient outage into a
|
|
95
|
+
* pending request no human ever sees, which is the one failure this project
|
|
96
|
+
* exists to prevent. The retry rate is bounded by the poll cycle itself (the
|
|
97
|
+
* long-poll timeout, or the channel's doubling backoff after a poll error), and
|
|
98
|
+
* the stderr warnings are throttled after {@link DISPATCH_LOUD_ATTEMPTS}
|
|
99
|
+
* consecutive failures for one key so a long outage cannot bury the terminal.
|
|
100
|
+
* The one exception is the **startup** dispatch, which still exits non-zero on
|
|
101
|
+
* a send failure: an operator who has just mistyped a chat id or a token should
|
|
102
|
+
* learn it immediately rather than watch a listener retry forever.
|
|
103
|
+
*/
|
|
104
|
+
import type { DecideOptions } from "../core/gate.js";
|
|
105
|
+
import { type ChannelRequest, type DeliveryId } from "../channels/contract.js";
|
|
106
|
+
import { type ChannelTagRefusalCode, type TagOptions } from "../channels/tagging.js";
|
|
107
|
+
import { type CheckpointTap } from "./checkpoint-tap.js";
|
|
108
|
+
import { TelegramChannel, type CheckpointTapResponse, type ReviewCard, type ReviewTapResponse, type TelegramCommand, type TelegramTerminalState } from "../channels/telegram.js";
|
|
109
|
+
import { type TelegramDelivery } from "../core/telegram-config.js";
|
|
110
|
+
import { type ParsedFlags } from "./args.js";
|
|
111
|
+
import { type GlossRunner } from "./gloss.js";
|
|
112
|
+
import { type GlossRunnerFactoryOptions } from "./gloss-options.js";
|
|
113
|
+
import type { Streams } from "./main.js";
|
|
114
|
+
/**
|
|
115
|
+
* The gloss runner this listener will use, as a spreadable fragment (APRV-197).
|
|
116
|
+
*
|
|
117
|
+
* ON unless `--no-gloss`. Two flags rather than one because the pair reads
|
|
118
|
+
* honestly next to `channel cli`, where the default is the other way round:
|
|
119
|
+
* `--gloss` is accepted here (and is simply the default restated) so that one
|
|
120
|
+
* command line works on both verbs, and `--no-gloss` wins a tie, because the
|
|
121
|
+
* flag that removes a language model from the path should never lose one.
|
|
122
|
+
*
|
|
123
|
+
* A fragment rather than a value so that "no runner" is the ABSENCE of the
|
|
124
|
+
* key. {@link ListenSetup.gloss} being optional is what lets every
|
|
125
|
+
* programmatic caller of `dispatchPending` spawn nothing without saying so.
|
|
126
|
+
*
|
|
127
|
+
* `passphraseEnv` is the name this policy's `vault.passphrase_env` gives, and
|
|
128
|
+
* the only thing the APRV-207 scrub needs from a policy: the subprocess is
|
|
129
|
+
* spawned starved either way, and naming the variable covers the deployment
|
|
130
|
+
* that renamed it out from under the credential prefixes.
|
|
131
|
+
*/
|
|
132
|
+
export declare function glossWiring(flags: ParsedFlags, passphraseEnv?: string | null, factories?: Omit<GlossRunnerFactoryOptions, "passphraseEnv">): {
|
|
133
|
+
gloss?: GlossRunner;
|
|
134
|
+
};
|
|
135
|
+
export interface ListenSetup {
|
|
136
|
+
channel: TelegramChannel;
|
|
137
|
+
logPath: string;
|
|
138
|
+
actor: string;
|
|
139
|
+
json: boolean;
|
|
140
|
+
once: boolean;
|
|
141
|
+
gateOptions: DecideOptions;
|
|
142
|
+
tagOptions: TagOptions;
|
|
143
|
+
/**
|
|
144
|
+
* How this listener puts the pending set in front of the approver (APRV-216):
|
|
145
|
+
* `paced`, one question at a time, or `burst`, everything not yet sent on
|
|
146
|
+
* every cycle.
|
|
147
|
+
*
|
|
148
|
+
* REQUIRED rather than defaulted, so that every construction site states
|
|
149
|
+
* which of the two it means. The policy's answer is resolved once, in
|
|
150
|
+
* {@link prepareListen}, and the default that answer falls back to lives in
|
|
151
|
+
* `core/telegram-config.ts` beside the other Telegram policy readings.
|
|
152
|
+
*/
|
|
153
|
+
delivery: TelegramDelivery;
|
|
154
|
+
/**
|
|
155
|
+
* How the one-sentence model gloss is obtained (APRV-144).
|
|
156
|
+
*
|
|
157
|
+
* OPT-IN, and absent by default. The verb wires in the production runner
|
|
158
|
+
* (`claude -p --model haiku`, hard timeout, failing toward absence); every
|
|
159
|
+
* other caller — the test suite above all — gets no gloss unless it hands
|
|
160
|
+
* over a runner. A default that spawned would make a subprocess an implicit
|
|
161
|
+
* dependency of anything that drives a dispatch cycle, and would put a model
|
|
162
|
+
* inside a test suite that must never invoke one.
|
|
163
|
+
*
|
|
164
|
+
* Injectable so the tests drive both branches, answered and absent, against
|
|
165
|
+
* a stub.
|
|
166
|
+
*/
|
|
167
|
+
gloss?: GlossRunner;
|
|
168
|
+
/**
|
|
169
|
+
* Where a checkpoint key may come from, and where the cadence is read
|
|
170
|
+
* (APRV-257).
|
|
171
|
+
*
|
|
172
|
+
* Present at every construction site, because every one of them knows a log
|
|
173
|
+
* path and a policy. Whether a checkpoint is ever OFFERED is the policy's
|
|
174
|
+
* answer — `audit.checkpoint_every` plus `audit.checkpoint_keys` — and
|
|
175
|
+
* {@link checkpointOfferFor} gives up before it walks a log when the policy
|
|
176
|
+
* names neither, so a gate that has not turned checkpoints on pays a policy
|
|
177
|
+
* load per cycle and nothing else.
|
|
178
|
+
*/
|
|
179
|
+
checkpoint: CheckpointTap;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Why a listener could not be built. A closed union, because more than one
|
|
183
|
+
* caller now branches on it: the verb turns each into an exit code, and
|
|
184
|
+
* `approval up` turns each into a part it will not start (SPEC.md §11.1
|
|
185
|
+
* invariant 6 — a refusal is machine-readable and distinct).
|
|
186
|
+
*/
|
|
187
|
+
export declare const LISTEN_REFUSAL_CODES: readonly [
|
|
188
|
+
/** A credential variable the policy names is unset or empty. */
|
|
189
|
+
"not-configured",
|
|
190
|
+
/** No `human:<id>` was declared, so nothing could be recorded against one. */
|
|
191
|
+
"no-identity",
|
|
192
|
+
/** `--poll-timeout` was not a whole number of seconds. */
|
|
193
|
+
"poll-timeout",
|
|
194
|
+
/** The log could not be read (or its directory does not exist). */
|
|
195
|
+
"log-unreadable",
|
|
196
|
+
/** `--payloads` did not hold a JSON object of action key -> payload. */
|
|
197
|
+
"payloads-unreadable"];
|
|
198
|
+
export type ListenRefusalCode = (typeof LISTEN_REFUSAL_CODES)[number];
|
|
199
|
+
/** Everything {@link prepareListen} needs, already resolved to absolute paths. */
|
|
200
|
+
export interface ListenRequest {
|
|
201
|
+
/** The log to derive the queue from and append decisions to. */
|
|
202
|
+
logPath: string;
|
|
203
|
+
/** Policy location, with `loadPolicy`'s semantics. */
|
|
204
|
+
policy: {
|
|
205
|
+
dir?: string;
|
|
206
|
+
file?: string;
|
|
207
|
+
};
|
|
208
|
+
/** `--as` as typed, or `null` to fall back to `APPROVAL_HUMAN`. */
|
|
209
|
+
as: string | null;
|
|
210
|
+
/** `--payloads`, already absolute, or `null` for the payload store alone. */
|
|
211
|
+
payloads: string | null;
|
|
212
|
+
/** `--api-base`, or `null` for the Bot API. */
|
|
213
|
+
apiBase: string | null;
|
|
214
|
+
/** `--poll-timeout` as typed, or `null` for the channel's own default. */
|
|
215
|
+
pollTimeout: string | null;
|
|
216
|
+
once: boolean;
|
|
217
|
+
json: boolean;
|
|
218
|
+
/** Where the channel's operational complaints go. Ordinarily stderr. */
|
|
219
|
+
log(message: string): void;
|
|
220
|
+
/** The gloss runner, if the caller wants one. See {@link ListenSetup.gloss}. */
|
|
221
|
+
gloss?: GlossRunner;
|
|
222
|
+
}
|
|
223
|
+
export type ListenPreparation = {
|
|
224
|
+
ok: true;
|
|
225
|
+
setup: ListenSetup;
|
|
226
|
+
} | {
|
|
227
|
+
ok: false;
|
|
228
|
+
code: ListenRefusalCode;
|
|
229
|
+
message: string;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* Everything that can fail without touching the network, in order.
|
|
233
|
+
*
|
|
234
|
+
* Deliberately sequential and deliberately synchronous: an operator who typed
|
|
235
|
+
* the wrong thing learns it before a bot message is sent, and the async half
|
|
236
|
+
* below can then assume its configuration is whole.
|
|
237
|
+
*
|
|
238
|
+
* It PRINTS NOTHING and CHOOSES NO EXIT CODE (APRV-110). The verb below turns
|
|
239
|
+
* each refusal into the usage or I/O error it always was; `approval up` turns
|
|
240
|
+
* the same refusal into a channel it declines to start, reported in doctor's
|
|
241
|
+
* vocabulary while the other parts carry on. Two callers, one set of checks,
|
|
242
|
+
* one set of sentences — which is the only way the two surfaces can agree about
|
|
243
|
+
* what "telegram is not configured" means.
|
|
244
|
+
*/
|
|
245
|
+
export declare function prepareListen(request: ListenRequest): ListenPreparation;
|
|
246
|
+
/**
|
|
247
|
+
* What to tell a human who tapped a button for an action this listener is not
|
|
248
|
+
* holding open (APRV-196).
|
|
249
|
+
*
|
|
250
|
+
* The one place a stale tap gets a real answer instead of a shrug. It reads the
|
|
251
|
+
* VERIFIED log (SPEC.md §11.1(1): a sentence a human reads about what the log
|
|
252
|
+
* says is derived from a log that verified, or it is not derived at all) and
|
|
253
|
+
* answers from `requestState`, the same derivation the gate and the pending
|
|
254
|
+
* queue use. Nothing here decides anything, nothing is appended, and nothing is
|
|
255
|
+
* remembered between calls: an unreadable log answers `null`, which the channel
|
|
256
|
+
* renders as its "not open here" toast.
|
|
257
|
+
*
|
|
258
|
+
* The argument is an action REFERENCE and never a key. The string came off the
|
|
259
|
+
* network, so this hashes the keys the log actually carries and looks for a
|
|
260
|
+
* match; a caller cannot make it describe a request by naming one, and a ref
|
|
261
|
+
* matching nothing simply answers `null`.
|
|
262
|
+
*
|
|
263
|
+
* The walk is over `approval.requested` records, which is the set of things
|
|
264
|
+
* that could ever have had a button. Run only on a stale tap, which is rare by
|
|
265
|
+
* construction.
|
|
266
|
+
*/
|
|
267
|
+
export declare function describeActionFor(logPath: string): (actionRef: string) => string | null;
|
|
268
|
+
/**
|
|
269
|
+
* Consecutive failures for one action key after which stderr warnings thin out.
|
|
270
|
+
*
|
|
271
|
+
* Not an attempt limit: the send is retried on every cycle forever (see the
|
|
272
|
+
* module doc). Only the complaining is throttled, to every tenth attempt.
|
|
273
|
+
*/
|
|
274
|
+
export declare const DISPATCH_LOUD_ATTEMPTS = 3;
|
|
275
|
+
/**
|
|
276
|
+
* How long an unannotated delivery stays in the bookkeeping before it is
|
|
277
|
+
* dropped (APRV-196). Twenty-four hours, matching the channel's own
|
|
278
|
+
* `TELEGRAM_DEFAULT_RETENTION_MS`.
|
|
279
|
+
*
|
|
280
|
+
* It is a floor on forgetting and not a deadline for anything: a request that
|
|
281
|
+
* is still pending is never dropped however old it is, because the pending
|
|
282
|
+
* queue is checked first. What this bounds is the memory a long-lived listener
|
|
283
|
+
* holds for questions the log has finished with.
|
|
284
|
+
*/
|
|
285
|
+
export declare const DISPATCH_RETENTION_MS: number;
|
|
286
|
+
/**
|
|
287
|
+
* The line that introduces the first batch a listener process sends (APRV-196).
|
|
288
|
+
*
|
|
289
|
+
* **Why a banner and not an edit of the earlier copies.** The incident was a
|
|
290
|
+
* restart re-sending five pending requests with no warning, on top of five
|
|
291
|
+
* copies whose buttons had quietly stopped working. Editing those earlier
|
|
292
|
+
* copies to say "superseded" would read better — and it is not a design that
|
|
293
|
+
* can be relied on, because it requires this process to know their message ids,
|
|
294
|
+
* which a restart by definition does not: SPEC.md §10.3 forbids channel state
|
|
295
|
+
* that is a source of truth, and a crash loses a cache whether or not one is
|
|
296
|
+
* allowed. A design that only works when the crash was gentle is a design that
|
|
297
|
+
* fails on the day it is needed. So the banner is unconditional, and the
|
|
298
|
+
* earlier copies are made harmless instead of tidy: their buttons resolve by
|
|
299
|
+
* action reference to the request this process has just re-delivered
|
|
300
|
+
* (`actionRefOf` in `channels/telegram.ts`), so a human who taps the copy they
|
|
301
|
+
* can see decides the request they meant.
|
|
302
|
+
*
|
|
303
|
+
* It says "started" rather than "restarted" because a listener cannot tell the
|
|
304
|
+
* two apart, having deliberately kept nothing that would let it, and a first
|
|
305
|
+
* start that claimed to be a restart would be this channel's own text lying
|
|
306
|
+
* about the system's history.
|
|
307
|
+
*/
|
|
308
|
+
export declare function bannerLines(pending: number): string[];
|
|
309
|
+
/**
|
|
310
|
+
* The summary line that precedes a paced send, and the body of `/queue`.
|
|
311
|
+
*
|
|
312
|
+
* One message, and everything in it is arithmetic on the verified log at the
|
|
313
|
+
* instant it is written: how many requests are pending, how long the oldest has
|
|
314
|
+
* waited, and which classes they are. Nothing is remembered between calls, so
|
|
315
|
+
* two summaries a minute apart can disagree only because the log moved.
|
|
316
|
+
*
|
|
317
|
+
* The class tally is the part worth the space. The count alone says how much
|
|
318
|
+
* work is waiting; the classes say what KIND of work, which is what tells an
|
|
319
|
+
* approver whether the queue is six identical `network.call`s they can walk
|
|
320
|
+
* through or one `policy.edit` they should read carefully.
|
|
321
|
+
*/
|
|
322
|
+
export declare function summaryLines(requests: ChannelRequest[], now: string): string[];
|
|
323
|
+
/**
|
|
324
|
+
* `/queue`'s reply: the summary, then one numbered line per pending request.
|
|
325
|
+
*
|
|
326
|
+
* Derived, like the summary, from the verified log at reply time and not from
|
|
327
|
+
* anything this process is holding: the numbering is positional and names no
|
|
328
|
+
* button, so a stale copy of this list cannot be used to decide anything. The
|
|
329
|
+
* marker says which one this listener has selected and once delivered, because
|
|
330
|
+
* the question `/queue` is usually asked to answer is "what else is there
|
|
331
|
+
* besides the one I am looking at" — and, since APRV-256, its unhappy twin,
|
|
332
|
+
* "where is the one I am supposed to be looking at".
|
|
333
|
+
*
|
|
334
|
+
* The footer answers that second question the only honest way available to a
|
|
335
|
+
* process whose knowledge of the chat ends at "a send returned success": it
|
|
336
|
+
* says what was sent, says it cannot tell whether the card survived, and then
|
|
337
|
+
* spends its remaining words on recovery rather than reassurance.
|
|
338
|
+
*/
|
|
339
|
+
export declare function queueLines(requests: ChannelRequest[], now: string, shown: readonly string[]): string[];
|
|
340
|
+
/**
|
|
341
|
+
* What this process is showing, and in what order (APRV-216). **In memory
|
|
342
|
+
* only**, like every other field of {@link DispatchState} and for the same
|
|
343
|
+
* reason (SPEC.md §10.3).
|
|
344
|
+
*
|
|
345
|
+
* None of this is truth, and the check that proves it is what happens when it
|
|
346
|
+
* is lost: a restarted listener re-derives the pending set from the verified
|
|
347
|
+
* log, rebuilds the order from log order, and shows the oldest — which is
|
|
348
|
+
* exactly what a fresh start does anyway. What a crash costs is the human's
|
|
349
|
+
* place in a walkthrough, never a request that stays pending in the log and is
|
|
350
|
+
* never shown.
|
|
351
|
+
*/
|
|
352
|
+
export interface PacedState {
|
|
353
|
+
/**
|
|
354
|
+
* Every pending action key, in the order this process will show them.
|
|
355
|
+
*
|
|
356
|
+
* Seeded from log order (oldest first, which is what `buildPendingQueue`
|
|
357
|
+
* returns) and rearranged by `/skip` alone. Keys the log no longer calls
|
|
358
|
+
* pending are dropped on every cycle, and newly pending ones join the back.
|
|
359
|
+
*/
|
|
360
|
+
order: string[];
|
|
361
|
+
/**
|
|
362
|
+
* The action keys of the unit in front of the approver, or `null` when
|
|
363
|
+
* nothing is.
|
|
364
|
+
*
|
|
365
|
+
* A unit rather than a key because a digest (APRV-115) is one thing to read
|
|
366
|
+
* and several things to decide. It is released when the log says none of its
|
|
367
|
+
* members is pending any more, which is what makes a decision — at any
|
|
368
|
+
* surface, on any copy — advance the walkthrough.
|
|
369
|
+
*/
|
|
370
|
+
current: string[] | null;
|
|
371
|
+
/** Whether any summary has been sent yet, i.e. whether this is the start. */
|
|
372
|
+
summarySent: boolean;
|
|
373
|
+
/** The pending count the last summary named, so growth can be recognised. */
|
|
374
|
+
announced: number;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* The retrospective walkthrough this process is running (APRV-299). **In memory
|
|
378
|
+
* only**, exactly like {@link PacedState} and under the same rule (SPEC.md
|
|
379
|
+
* §10.3).
|
|
380
|
+
*
|
|
381
|
+
* Its loss is the check that it is not truth: a restarted listener re-derives
|
|
382
|
+
* the open samples from the verified log, rebuilds the order from log order,
|
|
383
|
+
* and offers the oldest — which is what a fresh start does anyway. A card that
|
|
384
|
+
* never arrives, or that a human scrolls past, leaves the sample OPEN: it stays
|
|
385
|
+
* in `approval audit list`, in `.approval/QUEUE.md`, and reviewable with
|
|
386
|
+
* `approval audit review <seq>`. Nothing here can empty the backlog, which is
|
|
387
|
+
* the property a sampled-audit backlog exists to have.
|
|
388
|
+
*/
|
|
389
|
+
export interface ReviewWalkthrough {
|
|
390
|
+
/** Every open sample's seq, in the order this process will show them. */
|
|
391
|
+
order: number[];
|
|
392
|
+
/** The sample whose card is in front of the approver, or `null`. */
|
|
393
|
+
current: number | null;
|
|
394
|
+
/** Sample seq -> the message this process sent the card as. */
|
|
395
|
+
readonly delivered: Map<number, DeliveryId>;
|
|
396
|
+
/** Whether any review summary has been sent yet. */
|
|
397
|
+
summarySent: boolean;
|
|
398
|
+
/** The open count the last summary named, so growth can be recognised. */
|
|
399
|
+
announced: number;
|
|
400
|
+
/**
|
|
401
|
+
* The log's size in bytes when this pass last derived the backlog, or `null`
|
|
402
|
+
* before the first one.
|
|
403
|
+
*
|
|
404
|
+
* A cost guard and nothing else, and it is sound for exactly one reason: the
|
|
405
|
+
* log is APPEND-ONLY, so a size that has not changed is a record set that has
|
|
406
|
+
* not changed. It is read only to skip a full verified walk on the cycle
|
|
407
|
+
* where a card is already in front of the approver and nothing has been
|
|
408
|
+
* written — which, with a 25-second poll and a human who answers in minutes,
|
|
409
|
+
* is most cycles. Every other cycle re-derives from the log as usual, and a
|
|
410
|
+
* lost or stale value costs one extra read rather than a wrong answer.
|
|
411
|
+
*/
|
|
412
|
+
logSize: number | null;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* The summary line that precedes a review card, and `/queue`'s review footer.
|
|
416
|
+
*
|
|
417
|
+
* Arithmetic on the verified log at the instant it is written, exactly as
|
|
418
|
+
* {@link summaryLines} is: how many samples are awaiting review, how old the
|
|
419
|
+
* oldest is, and which classes they are. The last clause is the one that stops
|
|
420
|
+
* a reader treating this like the pending queue: nothing here is waiting on
|
|
421
|
+
* them, because all of it has already happened.
|
|
422
|
+
*/
|
|
423
|
+
export declare function reviewSummaryLines(cards: ReviewCard[], now: string): string[];
|
|
424
|
+
/**
|
|
425
|
+
* What one listener process remembers between cycles. **In memory only.**
|
|
426
|
+
*
|
|
427
|
+
* SPEC.md §10.3: channels hold no state that is a source of truth. Nothing here
|
|
428
|
+
* is truth — the pending set is re-derived from the verified log every cycle,
|
|
429
|
+
* and this only prevents a second copy of a message this process already sent.
|
|
430
|
+
* Its loss (restart, crash) degrades to a re-send, never to a request that is
|
|
431
|
+
* pending in the log and absent from the approver's phone.
|
|
432
|
+
*/
|
|
433
|
+
export interface DispatchState {
|
|
434
|
+
/**
|
|
435
|
+
* action key -> the delivery id this process sent it under.
|
|
436
|
+
*
|
|
437
|
+
* Pruned (APRV-196): an entry goes when the request reaches a terminal state
|
|
438
|
+
* and its message has been annotated, and a straggler goes when it is older
|
|
439
|
+
* than {@link DISPATCH_RETENTION_MS} and the pending queue no longer carries
|
|
440
|
+
* it. Neither prune can cost a re-send, because `buildPendingQueue` only ever
|
|
441
|
+
* returns requests the verified log says are pending — the same reason losing
|
|
442
|
+
* the whole map to a restart is safe.
|
|
443
|
+
*/
|
|
444
|
+
readonly delivered: Map<string, DeliveryId>;
|
|
445
|
+
/** action key -> when this process sent it, ms since epoch (APRV-196). */
|
|
446
|
+
readonly sentAtMs: Map<string, number>;
|
|
447
|
+
/**
|
|
448
|
+
* Whether the re-delivery banner has been sent (APRV-196).
|
|
449
|
+
*
|
|
450
|
+
* A box rather than a field because {@link DispatchState} is `readonly`
|
|
451
|
+
* everywhere else, and for the same reason: a cycle may write what it did,
|
|
452
|
+
* and nothing may swap the state out from under one.
|
|
453
|
+
*/
|
|
454
|
+
readonly banner: {
|
|
455
|
+
sent: boolean;
|
|
456
|
+
};
|
|
457
|
+
/** action key -> consecutive failed send attempts. Cleared on success. */
|
|
458
|
+
readonly attempts: Map<string, number>;
|
|
459
|
+
/** `<action key>:<code>` skips already reported, so cycles do not repeat them. */
|
|
460
|
+
readonly warned: Set<string>;
|
|
461
|
+
/**
|
|
462
|
+
* Keys this process has already annotated on the approver's phone (APRV-106
|
|
463
|
+
* for withdrawal, APRV-113 for every other terminal state). In memory, like
|
|
464
|
+
* `delivered`, and for the same reason: it stops a second edit of the same
|
|
465
|
+
* message, and its loss costs a duplicate edit at worst.
|
|
466
|
+
*
|
|
467
|
+
* The memory that matters here is `delivered`, and losing it degrades to
|
|
468
|
+
* un-annotated messages, NEVER to wrong annotations: a process that does not
|
|
469
|
+
* remember sending a message cannot edit it, and one that does re-reads the
|
|
470
|
+
* outcome from the verified log every cycle. A fresh listener also never
|
|
471
|
+
* sends a settled request in the first place — `buildPendingQueue` re-derives
|
|
472
|
+
* from the verified log and only `requested` is pending — so a restart leaves
|
|
473
|
+
* stale text on old messages whose buttons the gate refuses anyway, and
|
|
474
|
+
* nothing worse.
|
|
475
|
+
*/
|
|
476
|
+
readonly annotated: Set<string>;
|
|
477
|
+
/**
|
|
478
|
+
* The walkthrough this process is running under `delivery: paced`
|
|
479
|
+
* (APRV-216). Present under `burst` too and simply never read there, so that
|
|
480
|
+
* one state shape serves both modes and a policy change between two runs
|
|
481
|
+
* needs no different bookkeeping.
|
|
482
|
+
*/
|
|
483
|
+
readonly paced: PacedState;
|
|
484
|
+
/**
|
|
485
|
+
* The checkpoint prompt this process has outstanding (APRV-257). **In memory
|
|
486
|
+
* only**, like everything else here.
|
|
487
|
+
*
|
|
488
|
+
* `offeredSince` is the newest checkpoint's seq at the moment a prompt went
|
|
489
|
+
* out (`null` for a log that had never been checkpointed), and it is what
|
|
490
|
+
* makes "at most one outstanding, and never a nag" a single condition: a
|
|
491
|
+
* cadence that has lapsed keeps producing an offer on every cycle, and this
|
|
492
|
+
* process asks once per lapse. The value changes only when a checkpoint
|
|
493
|
+
* actually lands, which is also the moment due-ness goes false — so the next
|
|
494
|
+
* prompt comes from the next lapse and never from this one repeating.
|
|
495
|
+
*
|
|
496
|
+
* `offered: false` means nothing is outstanding. Losing the box to a restart
|
|
497
|
+
* costs one duplicate prompt for a checkpoint that is genuinely owed, which
|
|
498
|
+
* is the same direction every other piece of this bookkeeping degrades in.
|
|
499
|
+
*/
|
|
500
|
+
readonly checkpoint: {
|
|
501
|
+
offered: boolean;
|
|
502
|
+
offeredSince: number | null;
|
|
503
|
+
};
|
|
504
|
+
/**
|
|
505
|
+
* The retrospective walkthrough (APRV-299), paced in both delivery modes.
|
|
506
|
+
*
|
|
507
|
+
* Always paced, and deliberately so even under `burst`: a review is never
|
|
508
|
+
* urgent, nobody is blocked on one, and a restart that put sixty of them on a
|
|
509
|
+
* phone at once would be the flood APRV-287 collapsed in the other direction.
|
|
510
|
+
* One card at a time, behind a summary, is the whole of the design.
|
|
511
|
+
*/
|
|
512
|
+
readonly review: ReviewWalkthrough;
|
|
513
|
+
}
|
|
514
|
+
export declare function newDispatchState(): DispatchState;
|
|
515
|
+
/** What one {@link dispatchPending} call did. Total: it never throws. */
|
|
516
|
+
export interface DispatchResult {
|
|
517
|
+
/** Requests put in front of the approver by this cycle. */
|
|
518
|
+
delivered: {
|
|
519
|
+
action_key: string;
|
|
520
|
+
delivery_id: DeliveryId;
|
|
521
|
+
}[];
|
|
522
|
+
/** Sends that failed and will be retried on the next cycle. */
|
|
523
|
+
failed: {
|
|
524
|
+
action_key: string;
|
|
525
|
+
attempts: number;
|
|
526
|
+
message: string;
|
|
527
|
+
}[];
|
|
528
|
+
/**
|
|
529
|
+
* The queue could not be derived at all: the log is unreadable or does not
|
|
530
|
+
* verify. Nothing was sent. Fatal at startup, retried on later cycles.
|
|
531
|
+
*/
|
|
532
|
+
queueError?: {
|
|
533
|
+
code: ChannelTagRefusalCode;
|
|
534
|
+
message: string;
|
|
535
|
+
};
|
|
536
|
+
/**
|
|
537
|
+
* Deliveries annotated with their terminal outcome and disarmed this cycle
|
|
538
|
+
* (APRV-106 for `withdrawn`, APRV-113 for the rest).
|
|
539
|
+
*/
|
|
540
|
+
annotated: {
|
|
541
|
+
action_key: string;
|
|
542
|
+
delivery_id: DeliveryId;
|
|
543
|
+
outcome: TelegramTerminalState;
|
|
544
|
+
}[];
|
|
545
|
+
/**
|
|
546
|
+
* Digests sent this cycle (APRV-115): the message that carries the buttons,
|
|
547
|
+
* the batch delivery id every member's event will carry, and the members.
|
|
548
|
+
* A group that fell back to one message per member produces no entry here.
|
|
549
|
+
*/
|
|
550
|
+
digests: {
|
|
551
|
+
delivery_id: DeliveryId;
|
|
552
|
+
batch_delivery_id: DeliveryId;
|
|
553
|
+
action_keys: string[];
|
|
554
|
+
}[];
|
|
555
|
+
/**
|
|
556
|
+
* The re-delivery banner, when this cycle sent one (APRV-196): the message
|
|
557
|
+
* that precedes a startup batch and says how many requests are coming.
|
|
558
|
+
*/
|
|
559
|
+
banner?: {
|
|
560
|
+
delivery_id: DeliveryId;
|
|
561
|
+
pending: number;
|
|
562
|
+
};
|
|
563
|
+
/**
|
|
564
|
+
* The paced summary this cycle sent, when it sent one (APRV-216): the line
|
|
565
|
+
* that precedes the request being shown and says how many are waiting behind
|
|
566
|
+
* it. Sent by the first paced cycle that has something to show, and again
|
|
567
|
+
* whenever the pending set has grown while nothing was in front of the
|
|
568
|
+
* approver. Never both this and {@link banner}: they are the two modes'
|
|
569
|
+
* openings, and a process runs one mode.
|
|
570
|
+
*/
|
|
571
|
+
summary?: {
|
|
572
|
+
delivery_id: DeliveryId;
|
|
573
|
+
pending: number;
|
|
574
|
+
};
|
|
575
|
+
/**
|
|
576
|
+
* Action keys dropped from the delivery bookkeeping this cycle (APRV-196),
|
|
577
|
+
* with why. Neither kind can cost a re-send: the pending queue is the log's
|
|
578
|
+
* answer, and a dropped key that is still pending is simply re-delivered.
|
|
579
|
+
*/
|
|
580
|
+
pruned: {
|
|
581
|
+
action_key: string;
|
|
582
|
+
reason: "settled" | "stale";
|
|
583
|
+
}[];
|
|
584
|
+
/**
|
|
585
|
+
* The collapsed re-delivery this cycle sent, when it sent one (APRV-287):
|
|
586
|
+
* the one message that stood in for a batch of requests nobody is waiting on
|
|
587
|
+
* any more, and the keys it covers. At most one, on a process's first cycle.
|
|
588
|
+
*/
|
|
589
|
+
collapsed?: {
|
|
590
|
+
delivery_id: DeliveryId;
|
|
591
|
+
action_keys: string[];
|
|
592
|
+
oldest_ms: number;
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* The `CHECKPOINT DUE` prompt this cycle sent, when it sent one (APRV-257):
|
|
596
|
+
* the message it is on and the head it asks about. At most one per lapse.
|
|
597
|
+
*/
|
|
598
|
+
checkpoint?: {
|
|
599
|
+
delivery_id: DeliveryId;
|
|
600
|
+
seq: number;
|
|
601
|
+
hash: string;
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* The review card this cycle sent, when it sent one (APRV-299): the message
|
|
605
|
+
* it is on, the `audit.sampled` seq it is drawn for, and the action it is
|
|
606
|
+
* about. At most one per cycle, and none while a request is in front of the
|
|
607
|
+
* approver.
|
|
608
|
+
*/
|
|
609
|
+
reviewCard?: {
|
|
610
|
+
delivery_id: DeliveryId;
|
|
611
|
+
sample_seq: number;
|
|
612
|
+
action_key: string;
|
|
613
|
+
};
|
|
614
|
+
/**
|
|
615
|
+
* The review summary this cycle sent, when it sent one (APRV-299): the line
|
|
616
|
+
* saying how many samples are awaiting review and how old the oldest is.
|
|
617
|
+
*/
|
|
618
|
+
reviewSummary?: {
|
|
619
|
+
delivery_id: DeliveryId;
|
|
620
|
+
open: number;
|
|
621
|
+
};
|
|
622
|
+
/**
|
|
623
|
+
* The review backlog could not be derived: the log is unreadable or does not
|
|
624
|
+
* verify. No card was sent. Never fatal — a review is not a decision anyone
|
|
625
|
+
* is blocked on — and retried on the next cycle.
|
|
626
|
+
*/
|
|
627
|
+
reviewError?: {
|
|
628
|
+
code: string;
|
|
629
|
+
message: string;
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* One dispatch cycle: re-derive the pending queue from the verified log, send
|
|
634
|
+
* whatever this process has not already sent.
|
|
635
|
+
*
|
|
636
|
+
* `now` is a parameter, not a clock read: TTL judgment inside
|
|
637
|
+
* {@link buildPendingQueue} is deterministic and the tests drive it at chosen
|
|
638
|
+
* instants. Requests that are decided, expired, or not yet requested are absent
|
|
639
|
+
* from the derivation and so are never sent.
|
|
640
|
+
*/
|
|
641
|
+
export declare function dispatchPending(setup: ListenSetup, streams: Streams, state: DispatchState, now: string): Promise<DispatchResult>;
|
|
642
|
+
/**
|
|
643
|
+
* How old a pending request must be, on a listener's first cycle, to be one
|
|
644
|
+
* nobody is waiting on (APRV-287).
|
|
645
|
+
*
|
|
646
|
+
* The hook's own wait PLUS its retry grace, read from the same module the hook
|
|
647
|
+
* reads (`core/harness-wait.ts`), because two numbers would be two answers to
|
|
648
|
+
* "is anybody still holding this". Past the wait alone a hook process has
|
|
649
|
+
* stopped blocking and a retry can still adopt the question, so those are
|
|
650
|
+
* ordinary pending requests. Past the wait and the grace together nothing will
|
|
651
|
+
* adopt it: that is the moment the hook itself takes such a request back, and a
|
|
652
|
+
* request still pending here is one whose session never came back at all —
|
|
653
|
+
* exactly the dozen that arrived on a phone behind a dead daemon on
|
|
654
|
+
* 2026-09-06.
|
|
655
|
+
*
|
|
656
|
+
* Collapsing is not deciding. These stay pending, listable by `/queue`, and
|
|
657
|
+
* decidable from any copy already delivered; what changes is how many messages
|
|
658
|
+
* it takes to say they are there.
|
|
659
|
+
*/
|
|
660
|
+
export declare const COLLAPSE_STALE_AFTER_MS: number;
|
|
661
|
+
/** The computed lines a collapsed re-delivery leads with (APRV-287). */
|
|
662
|
+
export declare function staleLines(requests: ChannelRequest[], now: string): string[];
|
|
663
|
+
/**
|
|
664
|
+
* What a checkpoint tap does, on the machine the listener runs on (APRV-257).
|
|
665
|
+
*
|
|
666
|
+
* The signing happens HERE, in the listener's process, and that is the whole
|
|
667
|
+
* point of the tap: this process holds the vault passphrase because a HUMAN
|
|
668
|
+
* exported it into the shell they started it from, and `core/child-env.ts`
|
|
669
|
+
* strips that variable from every child an agent's session spawns. No agent can
|
|
670
|
+
* arrange for a process that reaches this function with a key.
|
|
671
|
+
*
|
|
672
|
+
* Nothing about the head is re-derived. The `(seq, hash)` comes back from the
|
|
673
|
+
* channel exactly as it was put on the screen, and
|
|
674
|
+
* {@link ../core/checkpoint.js appendCheckpointAt} signs that and checks the
|
|
675
|
+
* log still carries it. A handler that quietly re-read the head would be
|
|
676
|
+
* putting a human's key over bytes nobody looked at.
|
|
677
|
+
*
|
|
678
|
+
* `Not now` appends nothing and says so. It is not a rejection: there is no
|
|
679
|
+
* request here to reject, and a checkpoint that is owed is a warning at every
|
|
680
|
+
* layer and a refusal at none.
|
|
681
|
+
*/
|
|
682
|
+
export declare function checkpointHandlerFor(setup: ListenSetup, streams: Streams): (tap: {
|
|
683
|
+
sign: boolean;
|
|
684
|
+
head: {
|
|
685
|
+
seq: number;
|
|
686
|
+
hash: string;
|
|
687
|
+
};
|
|
688
|
+
}) => CheckpointTapResponse;
|
|
689
|
+
/**
|
|
690
|
+
* What a review tap does: the human-only `reviewSample`, and nothing else
|
|
691
|
+
* (APRV-299).
|
|
692
|
+
*
|
|
693
|
+
* The one path from a button on a phone to an `audit.reviewed`, and it is the
|
|
694
|
+
* SAME path `approval audit review` takes — same function, same refusals, same
|
|
695
|
+
* record shape — so a reaction given on a card and one given at a terminal are
|
|
696
|
+
* indistinguishable to `approval feedback`, which is the whole of AC3.
|
|
697
|
+
*
|
|
698
|
+
* The actor is `setup.actor`, the human identity this listener was configured
|
|
699
|
+
* with (`--as` / `APPROVAL_HUMAN`), exactly as a grant's is. It is never read
|
|
700
|
+
* off the tap, never off the callback, and never out of a payload field: this
|
|
701
|
+
* channel does not authenticate the person who pressed the button, and SPEC.md
|
|
702
|
+
* §11's config-declared identity is what a review is recorded against. Anyone
|
|
703
|
+
* who can reach the configured chat reviews as that actor, which is the same
|
|
704
|
+
* trust boundary a tapped grant already stands on.
|
|
705
|
+
*
|
|
706
|
+
* The reaction is passed through untouched and NOTHING here reads it (SPEC.md
|
|
707
|
+
* §11.1 invariant 10): it is a field on a record, chosen by a human, on its way
|
|
708
|
+
* to the log.
|
|
709
|
+
*/
|
|
710
|
+
export declare function reviewHandlerFor(setup: ListenSetup, streams: Streams): (tap: {
|
|
711
|
+
sampleSeq: number;
|
|
712
|
+
verdict: "ok" | "denied";
|
|
713
|
+
reaction?: "disliked" | "indifferent" | "liked" | "loved";
|
|
714
|
+
note?: string;
|
|
715
|
+
}) => ReviewTapResponse;
|
|
716
|
+
/**
|
|
717
|
+
* `/queue`, `/skip`, `/next` — the paced walkthrough's three verbs (APRV-216).
|
|
718
|
+
*
|
|
719
|
+
* **None of them appends anything**, and the reason is structural rather than
|
|
720
|
+
* careful: this function never touches `recordChannelDecision`, so there is no
|
|
721
|
+
* path from a typed word to the log. A decision is a button, always, because a
|
|
722
|
+
* button carries the nonce and the action reference that bind an answer to the
|
|
723
|
+
* bytes an approver was shown, and a word typed into a chat carries neither.
|
|
724
|
+
*
|
|
725
|
+
* What they do move is process memory:
|
|
726
|
+
*
|
|
727
|
+
* - `/queue` reads the verified log and replies with the summary and a numbered
|
|
728
|
+
* list. It changes nothing, and it works while a request is selected, because
|
|
729
|
+
* the list is derived and not held. The reply says outright that it carries no
|
|
730
|
+
* buttons and that it cannot vouch for a card it once sent (APRV-256).
|
|
731
|
+
* - `/skip` sends the shown unit to the BACK of this process's order and
|
|
732
|
+
* forgets having delivered it, so the next cycle shows the next question and
|
|
733
|
+
* this one comes round again after the rest. The copy already in the chat
|
|
734
|
+
* keeps its buttons, and they still decide the same request by action
|
|
735
|
+
* reference (APRV-196), so a skip is "later", never "gone".
|
|
736
|
+
* - `/next` releases the shown unit without reordering, so this process moves
|
|
737
|
+
* past it and does not show it again. The same copy stays live in the chat:
|
|
738
|
+
* the approver has kept the question and given up their place in the queue,
|
|
739
|
+
* which is the opposite trade from `/skip`.
|
|
740
|
+
*
|
|
741
|
+
* A command that finds nothing to do says so, because silence in a chat window
|
|
742
|
+
* is indistinguishable from a listener that has died.
|
|
743
|
+
*/
|
|
744
|
+
export declare function commandHandlerFor(setup: ListenSetup, streams: Streams, state: DispatchState,
|
|
745
|
+
/**
|
|
746
|
+
* When the command arrived. A clock read in production, because a command is
|
|
747
|
+
* answered when a human types it; injectable for the same reason
|
|
748
|
+
* {@link dispatchPending} takes `now` as a parameter, since the ages a reply
|
|
749
|
+
* states are arithmetic against it and a suite must be able to choose them.
|
|
750
|
+
*/
|
|
751
|
+
clock?: () => string): (command: TelegramCommand) => Promise<void>;
|
|
752
|
+
/**
|
|
753
|
+
* How one run of the listen loop ended (APRV-110).
|
|
754
|
+
*
|
|
755
|
+
* `stopped` is the ordinary ending: a signal, or `--once` completing. The two
|
|
756
|
+
* failures are the ones the startup cycle has always treated as fatal, hoisted
|
|
757
|
+
* out of the verb so that a supervisor can treat them as a part that fell over
|
|
758
|
+
* rather than as a process that must exit.
|
|
759
|
+
*/
|
|
760
|
+
export type ListenerOutcome = {
|
|
761
|
+
kind: "stopped";
|
|
762
|
+
} | {
|
|
763
|
+
kind: "queue-error";
|
|
764
|
+
code: ChannelTagRefusalCode;
|
|
765
|
+
message: string;
|
|
766
|
+
} | {
|
|
767
|
+
kind: "send-failed";
|
|
768
|
+
message: string;
|
|
769
|
+
};
|
|
770
|
+
/** A listen loop that is already running. {@link stop} ends it cleanly. */
|
|
771
|
+
export interface RunningListener {
|
|
772
|
+
/** Settles when the loop ends. Never rejects for a listener-shaped failure. */
|
|
773
|
+
readonly done: Promise<ListenerOutcome>;
|
|
774
|
+
/** Stop the loop, now or as soon as it reaches its first poll. */
|
|
775
|
+
stop(): void;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Start the dispatch-and-poll loop. **Installs no signal handler** and chooses
|
|
779
|
+
* no exit code (APRV-110): both are the caller's, because `approval up` runs
|
|
780
|
+
* this beside a daemon loop and a web server under one set of handlers.
|
|
781
|
+
*
|
|
782
|
+
* A FRESH {@link DispatchState} per call, which is the whole of the restart
|
|
783
|
+
* story: a supervisor that restarts a fallen listener re-derives the pending
|
|
784
|
+
* queue from the verified log and re-sends everything still pending, exactly as
|
|
785
|
+
* a restarted process would. A duplicate on the phone, never a silence.
|
|
786
|
+
*/
|
|
787
|
+
export declare function startListener(setup: ListenSetup, streams: Streams): RunningListener;
|
|
788
|
+
/**
|
|
789
|
+
* The listener verb. Returns a promise, which is why `main` treats `channel`
|
|
790
|
+
* specially: it is the only long-lived command in the CLI.
|
|
791
|
+
*/
|
|
792
|
+
export declare function commandTelegramListen(argv: string[], streams: Streams, cwd: string): number | Promise<number>;
|
|
793
|
+
/**
|
|
794
|
+
* Configuration health, offline.
|
|
795
|
+
*
|
|
796
|
+
* It answers one question — "is this runtime configured to talk to Telegram?"
|
|
797
|
+
* — and deliberately makes no network call: a health check that contacted the
|
|
798
|
+
* Bot API would leak the existence of the bot from any shell, and would fail
|
|
799
|
+
* for reasons (a captive portal, a rate limit) that say nothing about whether
|
|
800
|
+
* the operator's configuration is right. The *live* counters (deliveries,
|
|
801
|
+
* decisions, ignored callbacks, recovered poll errors) belong to a running
|
|
802
|
+
* listener and are surfaced by `TelegramChannel.health()` / `stats()` in
|
|
803
|
+
* process, and on the listener's stderr as they happen.
|
|
804
|
+
*/
|
|
805
|
+
export declare function commandTelegramHealth(argv: string[], streams: Streams, cwd: string): number;
|
|
806
|
+
export declare function commandTelegram(argv: string[], streams: Streams, cwd: string): number | Promise<number>;
|