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,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The daemon's pure projections (SPEC.md §6.3, §10.2).
|
|
3
|
+
*
|
|
4
|
+
* Everything the daemon *decides* lives here, and everything it *does* lives in
|
|
5
|
+
* `daemon.ts`. The split is the same one `core/loop.ts` draws for loop safety:
|
|
6
|
+
* a projection over verified records is a pure function of (records, instant,
|
|
7
|
+
* TTL), so it can be replayed, unit-tested against an injected clock, and never
|
|
8
|
+
* disagrees with itself between two callers.
|
|
9
|
+
*
|
|
10
|
+
* Nothing here reads the clock, the filesystem, or the network, and nothing
|
|
11
|
+
* here appends. Three questions are answered:
|
|
12
|
+
*
|
|
13
|
+
* 1. **What does the log say a task's envelope `state:` should be?**
|
|
14
|
+
* {@link taskEnvelopeState}. §6.3: "`state` is a projection of log events;
|
|
15
|
+
* the file is updated by the daemon after the event is appended, never the
|
|
16
|
+
* reverse." The daemon compares the file's claim against this answer, and a
|
|
17
|
+
* file that contradicts it is `envelope.drift`.
|
|
18
|
+
* 2. **Which live requests have lapsed with no `approval.expired` on record?**
|
|
19
|
+
* {@link lapsedRequests}. The gate already judges TTL lazily at decision
|
|
20
|
+
* time (a late grant is refused whether or not an expiry event exists), so
|
|
21
|
+
* the sweep changes no verdict; it makes the verdict *visible* in the log
|
|
22
|
+
* and in every projection built from it.
|
|
23
|
+
* 3. **Has this exact drift already been recorded?** {@link driftAlreadyLogged}.
|
|
24
|
+
* A watcher fires on every save and the periodic tick re-scans regardless,
|
|
25
|
+
* so without a dedupe rule one unfixed file would append an unbounded run of
|
|
26
|
+
* identical events. The rule is stated on that function.
|
|
27
|
+
*
|
|
28
|
+
* The state derivation itself is NOT reimplemented here: every action's state
|
|
29
|
+
* comes from `core/state.ts`'s `requestState`, the same derivation the gate,
|
|
30
|
+
* the token module, and the executor read. This module only rolls action states
|
|
31
|
+
* up to the task level, and that rollup is the one new rule it owns.
|
|
32
|
+
*/
|
|
33
|
+
import { payloadOf, requestState } from "../core/state.js";
|
|
34
|
+
/**
|
|
35
|
+
* The envelope's `state:` vocabulary (`envelope.schema.json`, SPEC.md §6.3).
|
|
36
|
+
*
|
|
37
|
+
* Spelled here rather than imported from the schema because the schema is data
|
|
38
|
+
* read at runtime and this is a type; `tests/daemon-projection.test.ts` pins the
|
|
39
|
+
* two against each other so they cannot drift apart.
|
|
40
|
+
*/
|
|
41
|
+
export const ENVELOPE_STATES = [
|
|
42
|
+
"proposed",
|
|
43
|
+
"awaiting",
|
|
44
|
+
"approved",
|
|
45
|
+
"executed",
|
|
46
|
+
"rejected",
|
|
47
|
+
"expired",
|
|
48
|
+
"revoked",
|
|
49
|
+
];
|
|
50
|
+
/** Is this the envelope's `state:` value? Used to read an untrusted file. */
|
|
51
|
+
export function isEnvelopeState(value) {
|
|
52
|
+
return typeof value === "string" && ENVELOPE_STATES.includes(value);
|
|
53
|
+
}
|
|
54
|
+
/** Every action key the latest `task.registered` for `task` declared, in order. */
|
|
55
|
+
export function registeredActionKeys(records, task) {
|
|
56
|
+
let latest = null;
|
|
57
|
+
for (const record of records) {
|
|
58
|
+
if (record.event === "task.registered" && record.task === task)
|
|
59
|
+
latest = record;
|
|
60
|
+
}
|
|
61
|
+
if (latest === null)
|
|
62
|
+
return [];
|
|
63
|
+
const declared = payloadOf(latest)["actions"];
|
|
64
|
+
if (!Array.isArray(declared))
|
|
65
|
+
return [];
|
|
66
|
+
const keys = [];
|
|
67
|
+
for (const entry of declared) {
|
|
68
|
+
if (typeof entry !== "object" || entry === null)
|
|
69
|
+
continue;
|
|
70
|
+
const key = entry["idempotency_key"];
|
|
71
|
+
if (typeof key === "string" && key.length > 0 && !keys.includes(key))
|
|
72
|
+
keys.push(key);
|
|
73
|
+
}
|
|
74
|
+
return keys;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The envelope `state:` the log implies for `task`, at instant `ts`.
|
|
78
|
+
*
|
|
79
|
+
* ## The rollup rule, stated once
|
|
80
|
+
*
|
|
81
|
+
* §6.3's lifecycle is drawn for one action; a task may declare several, so the
|
|
82
|
+
* projection needs a rule for a task whose actions disagree. It is this, in
|
|
83
|
+
* order, and the order is the point:
|
|
84
|
+
*
|
|
85
|
+
* 1. any action with a live request → **awaiting**. A human owes an answer, and
|
|
86
|
+
* that fact outranks every other, because it is the only state that asks
|
|
87
|
+
* something of a person.
|
|
88
|
+
* 2. else any granted action that has not executed → **approved**.
|
|
89
|
+
* 3. else any action with an `execution.completed` → **executed**.
|
|
90
|
+
* 4. else **revoked**, then **rejected**, then **expired** — human decisions
|
|
91
|
+
* outrank a runtime lapse, so a task with one revoked and one expired action
|
|
92
|
+
* reads as revoked, naming the decision a person actually made.
|
|
93
|
+
* 5. else **proposed**: registered (or not) and nothing has happened.
|
|
94
|
+
*
|
|
95
|
+
* A task with exactly one action — the common case — collapses to §6.3's
|
|
96
|
+
* lifecycle exactly, which is the property the rule was chosen for.
|
|
97
|
+
*
|
|
98
|
+
* An unregistered task projects to `proposed`: the log knows of no declaration,
|
|
99
|
+
* so nothing has been proposed *to the gate* yet. A file claiming `approved`
|
|
100
|
+
* for a task the log never registered therefore contradicts the log, which is
|
|
101
|
+
* exactly the reading §6.3 wants.
|
|
102
|
+
*/
|
|
103
|
+
export function taskEnvelopeState(records, task, ts, ttlMs) {
|
|
104
|
+
const keys = registeredActionKeys(records, task);
|
|
105
|
+
const registered = keys.length > 0 || records.some((record) => record.event === "task.registered" && record.task === task);
|
|
106
|
+
const actions = keys.map((actionKey) => ({
|
|
107
|
+
actionKey,
|
|
108
|
+
derivation: requestState(records, actionKey, ts, ttlMs),
|
|
109
|
+
}));
|
|
110
|
+
const any = (predicate) => actions.some(predicate);
|
|
111
|
+
let state = "proposed";
|
|
112
|
+
if (any((entry) => entry.derivation.state === "requested"))
|
|
113
|
+
state = "awaiting";
|
|
114
|
+
else if (any((entry) => entry.derivation.state === "granted" && entry.derivation.execution.completed === null)) {
|
|
115
|
+
state = "approved";
|
|
116
|
+
}
|
|
117
|
+
else if (any((entry) => entry.derivation.execution.completed !== null))
|
|
118
|
+
state = "executed";
|
|
119
|
+
else if (any((entry) => entry.derivation.state === "revoked"))
|
|
120
|
+
state = "revoked";
|
|
121
|
+
else if (any((entry) => entry.derivation.state === "rejected"))
|
|
122
|
+
state = "rejected";
|
|
123
|
+
else if (any((entry) => entry.derivation.state === "expired"))
|
|
124
|
+
state = "expired";
|
|
125
|
+
return { task, registered, state, actions };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Live requests whose TTL has lapsed and which carry no `approval.expired`.
|
|
129
|
+
*
|
|
130
|
+
* Idempotence is structural rather than remembered: the answer is re-derived
|
|
131
|
+
* from the verified log every sweep, and an action whose expiry has been
|
|
132
|
+
* appended no longer satisfies the predicate. Two sweeps over the same log
|
|
133
|
+
* therefore produce the same list, and a sweep that follows a successful one
|
|
134
|
+
* produces an empty list — with no state carried between them, and no way for a
|
|
135
|
+
* restarted daemon to expire something twice.
|
|
136
|
+
*
|
|
137
|
+
* `ttlMs === null` (a policy that declares no `defaults.approval_ttl`) yields no
|
|
138
|
+
* candidates at all: nothing lapses when nothing was bounded, and inventing a
|
|
139
|
+
* deadline is not the daemon's to invent.
|
|
140
|
+
*
|
|
141
|
+
* Returned in first-request order, so a sweep's appends land in a deterministic
|
|
142
|
+
* sequence.
|
|
143
|
+
*/
|
|
144
|
+
export function lapsedRequests(records, ts, ttlMs) {
|
|
145
|
+
if (ttlMs === null)
|
|
146
|
+
return [];
|
|
147
|
+
const keys = [];
|
|
148
|
+
for (const record of records) {
|
|
149
|
+
if (record.event !== "approval.requested")
|
|
150
|
+
continue;
|
|
151
|
+
const key = record.action_key;
|
|
152
|
+
if (typeof key === "string" && key.length > 0 && !keys.includes(key))
|
|
153
|
+
keys.push(key);
|
|
154
|
+
}
|
|
155
|
+
const lapsed = [];
|
|
156
|
+
for (const actionKey of keys) {
|
|
157
|
+
const derivation = requestState(records, actionKey, ts, ttlMs);
|
|
158
|
+
// `expiredLazily` is precisely "the TTL has passed and no event says so".
|
|
159
|
+
// Anything decided, revoked, or already expired by event fails it.
|
|
160
|
+
if (derivation.state === "expired" && derivation.expiredLazily && !derivation.expiredByEvent) {
|
|
161
|
+
lapsed.push({
|
|
162
|
+
actionKey,
|
|
163
|
+
task: derivation.task,
|
|
164
|
+
requestedTs: derivation.requestTs,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return lapsed;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Why an `envelope.drift` record was written (APRV-63).
|
|
172
|
+
*
|
|
173
|
+
* `state-mismatch` is the original reading of SPEC.md §6.3: the file makes a
|
|
174
|
+
* claim about `state:` and the log implies another one. `envelope-missing` is
|
|
175
|
+
* the loss case observed live in APRV-60: the log holds a `task.registered` for
|
|
176
|
+
* the task, and the file that declared it now carries no `approval:` key at all.
|
|
177
|
+
* They are separated because they call for different human actions — one is an
|
|
178
|
+
* edit to reconcile, the other is a *deletion to restore* — and a reader who
|
|
179
|
+
* could not tell them apart would treat a lost envelope as a stale one.
|
|
180
|
+
*
|
|
181
|
+
* `reason` is absent from records written before this vocabulary existed;
|
|
182
|
+
* readers (including {@link driftAlreadyLogged}) treat absence as
|
|
183
|
+
* `state-mismatch`, which is what every such record was.
|
|
184
|
+
*/
|
|
185
|
+
export const DRIFT_REASONS = ["state-mismatch", "envelope-missing"];
|
|
186
|
+
/** What an `envelope.drift` payload's `reason` says, defaulting for old records. */
|
|
187
|
+
function reasonOf(payload) {
|
|
188
|
+
const value = payload["reason"];
|
|
189
|
+
return typeof value === "string" ? value : "state-mismatch";
|
|
190
|
+
}
|
|
191
|
+
export { latestRegistration } from "../core/registration.js";
|
|
192
|
+
/**
|
|
193
|
+
* Has this exact drift already been recorded for `task`?
|
|
194
|
+
*
|
|
195
|
+
* The rule: compare against the **latest** `envelope.drift` for the task. Equal
|
|
196
|
+
* `(reason, declared_state, derived_state, envelope_sha256)` means the situation
|
|
197
|
+
* the log already describes is the situation now, so nothing is appended. Any
|
|
198
|
+
* difference
|
|
199
|
+
* — the human edited the file again, or the log moved and the derived state
|
|
200
|
+
* changed — is a new fact and is recorded.
|
|
201
|
+
*
|
|
202
|
+
* Comparing against the latest record rather than against any record is
|
|
203
|
+
* deliberate: a task that drifts, is repaired, and drifts the same way again has
|
|
204
|
+
* genuinely drifted twice, and an audit that collapsed those into one would be
|
|
205
|
+
* hiding a repetition from the person whose attention this system spends.
|
|
206
|
+
*
|
|
207
|
+
* For `envelope-missing` (APRV-63) the same rule reads as: one record per
|
|
208
|
+
* episode of loss, re-derived every tick from the file and the log rather than
|
|
209
|
+
* remembered, and a new record when the derived state moves underneath a file
|
|
210
|
+
* that is still stripped. Its limit is stated where it is felt: a file whose
|
|
211
|
+
* envelope is restored by hand *in agreement with the log* leaves no record of
|
|
212
|
+
* the restoration, so a second loss at the same derived state reads as the same
|
|
213
|
+
* episode and is not appended twice. Recording the restoration would need an
|
|
214
|
+
* event nobody has specified; detection does not invent one.
|
|
215
|
+
*/
|
|
216
|
+
export function driftAlreadyLogged(records, task, facts) {
|
|
217
|
+
let latest = null;
|
|
218
|
+
for (const record of records) {
|
|
219
|
+
if (record.event === "envelope.drift" && record.task === task)
|
|
220
|
+
latest = record;
|
|
221
|
+
}
|
|
222
|
+
if (latest === null)
|
|
223
|
+
return false;
|
|
224
|
+
const payload = payloadOf(latest);
|
|
225
|
+
const declared = payload["declared_state"];
|
|
226
|
+
const derived = payload["derived_state"];
|
|
227
|
+
const digest = payload["envelope_sha256"];
|
|
228
|
+
return (reasonOf(payload) === (facts.reason ?? "state-mismatch") &&
|
|
229
|
+
(declared === undefined ? null : declared) === facts.declaredState &&
|
|
230
|
+
derived === facts.derivedState &&
|
|
231
|
+
(digest === undefined ? null : digest) === facts.envelopeDigest);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../../../src/daemon/projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload retention pruning — the enforcement half of amended SPEC.md §5.2
|
|
3
|
+
* (APRV-38's vocabulary, APRV-41's daemon).
|
|
4
|
+
*
|
|
5
|
+
* > "A payload is prunable once the action it is bound to has been in a terminal
|
|
6
|
+
* > state (`executed`, `rejected`, `expired`, `revoked`) for longer than the
|
|
7
|
+
* > duration. A payload whose action is not terminal is never prunable, at any
|
|
8
|
+
* > age […]. Orphaned payloads (bytes with no recorded binding) are prunable
|
|
9
|
+
* > regardless of the key. […] Pruning is performed by the daemon and by nothing
|
|
10
|
+
* > else, and each removal appends a `payload.pruned` event, so a log states what
|
|
11
|
+
* > its store no longer holds."
|
|
12
|
+
*
|
|
13
|
+
* ## Write-ahead, always in that order
|
|
14
|
+
*
|
|
15
|
+
* For every file this module removes, the `payload.pruned` event lands in the
|
|
16
|
+
* log **first** and the `unlink` follows. The ordering is the whole design: a
|
|
17
|
+
* crash between the two leaves a file on disk that the log already says is gone,
|
|
18
|
+
* which the next tick completes by unlinking it and appending nothing further
|
|
19
|
+
* ({@link PrunePlan.completions}). The opposite order would leave the other
|
|
20
|
+
* failure — bytes deleted with no record of the deletion — which is the one
|
|
21
|
+
* outcome a store holding the material evidence of what a human approved cannot
|
|
22
|
+
* afford. Deleting evidence is acceptable; deleting it silently is not.
|
|
23
|
+
*
|
|
24
|
+
* Idempotence needs no remembered state: a hash that already carries a
|
|
25
|
+
* `payload.pruned` event is never given a second one, and the plan is re-derived
|
|
26
|
+
* from the verified log on every tick.
|
|
27
|
+
*
|
|
28
|
+
* ## Terminal time comes from the log, never from the filesystem
|
|
29
|
+
*
|
|
30
|
+
* The clock that decides whether retention has elapsed reads the timestamp of the
|
|
31
|
+
* event that made the action terminal (`execution.completed`, `approval.rejected`,
|
|
32
|
+
* `approval.revoked`, `approval.expired`). File mtimes are not evidence: they are
|
|
33
|
+
* rewritten by a copy, a checkout, a backup restore, or an `rsync`, and pruning on
|
|
34
|
+
* them would let a routine filesystem operation decide when approval evidence
|
|
35
|
+
* disappears.
|
|
36
|
+
*
|
|
37
|
+
* A **lazily** expired request (the TTL has arithmetically lapsed but no
|
|
38
|
+
* `approval.expired` record exists) is deliberately not terminal here. The
|
|
39
|
+
* daemon's own TTL sweep appends that event on the same tick; the payload becomes
|
|
40
|
+
* prunable once the log says so, and retention is then measured from the recorded
|
|
41
|
+
* moment rather than from one this module computed for itself.
|
|
42
|
+
*
|
|
43
|
+
* `execution.failed` is likewise not terminal: a failed action may be retried
|
|
44
|
+
* against the very bytes in question, and loop escalation (SPEC.md §10.2) exists
|
|
45
|
+
* precisely because failures recur.
|
|
46
|
+
*
|
|
47
|
+
* ## The orphan rule, resolved conservatively (flagged for review)
|
|
48
|
+
*
|
|
49
|
+
* §5.2 says orphaned payloads are "prunable regardless of the key", which reads
|
|
50
|
+
* as though orphans could be swept even with `payload_retention` absent. APRV-41's
|
|
51
|
+
* acceptance criteria say the absent key means no pruning at all. This module
|
|
52
|
+
* takes the strictest reading that satisfies both:
|
|
53
|
+
*
|
|
54
|
+
* - **`payload_retention` absent: the pruning subsystem does not run.** Nothing is
|
|
55
|
+
* deleted, orphan or not, and no `payload.pruned` is appended. Retention is an
|
|
56
|
+
* operator's explicit choice to forget, and an operator who never made it never
|
|
57
|
+
* asked this runtime to delete anything.
|
|
58
|
+
* - **`payload_retention` present: orphans are prunable at any age**, which is
|
|
59
|
+
* what "regardless of the key" then means — the duration governs bound payloads
|
|
60
|
+
* and does not gate residue nothing ever bound.
|
|
61
|
+
*
|
|
62
|
+
* An orphan is a file whose hash appears in **no** log record other than a
|
|
63
|
+
* `payload.pruned` (head-moved residue: the gate stored the bytes, its append was
|
|
64
|
+
* refused, and no request ever declared them). A hash mentioned by any other
|
|
65
|
+
* record is bound, and a binding this module cannot attribute to an action key is
|
|
66
|
+
* treated as live rather than as an orphan — fail closed in both directions.
|
|
67
|
+
*
|
|
68
|
+
* ## Nothing else here decides anything
|
|
69
|
+
*
|
|
70
|
+
* Which hashes the log already binds, and which it already says are pruned, is
|
|
71
|
+
* `core/payload-census.ts`'s — the same computation the reporting surfaces read,
|
|
72
|
+
* so what a reader is shown and what this module would delete can never drift
|
|
73
|
+
* apart. Approval state per action is `core/state.ts`'s `requestState`; the append is
|
|
74
|
+
* `core/log.ts`'s `appendEvent` with `expectedHead` (compare-and-append, SPEC.md
|
|
75
|
+
* §11.1 invariant 5); the unlink is `core/payload-store.ts`'s. The timestamp on
|
|
76
|
+
* every `payload.pruned` is the runtime's, read from the injected clock at the
|
|
77
|
+
* write boundary, and the actor is `system:daemon` — a party under oversight must
|
|
78
|
+
* never be able to author either.
|
|
79
|
+
*/
|
|
80
|
+
import { type Clock } from "../core/clock.js";
|
|
81
|
+
import { type EventRecord } from "../core/log.js";
|
|
82
|
+
/**
|
|
83
|
+
* SPEC.md §8 and `event.schema.json`: `payload.pruned` carries a `system:` actor.
|
|
84
|
+
* Declared here rather than imported from `daemon.ts` so the pruner has no
|
|
85
|
+
* dependency on the loop that calls it.
|
|
86
|
+
*/
|
|
87
|
+
export declare const PRUNE_ACTOR = "system:daemon";
|
|
88
|
+
/** The terminal states of amended SPEC.md §5.2, and nothing beyond them. */
|
|
89
|
+
export type TerminalState = "executed" | "rejected" | "revoked" | "expired";
|
|
90
|
+
/** Why a payload is prunable. Mirrors `payload.pruned`'s `reason`. */
|
|
91
|
+
export type PruneReason = "payload_retention" | "orphaned";
|
|
92
|
+
/** One file the plan says may go, and the evidence for saying so. */
|
|
93
|
+
export interface PruneCandidate {
|
|
94
|
+
hash: string;
|
|
95
|
+
reason: PruneReason;
|
|
96
|
+
/** The action whose terminal state released the bytes; `null` for an orphan. */
|
|
97
|
+
actionKey: string | null;
|
|
98
|
+
task: string | null;
|
|
99
|
+
terminalState: TerminalState | null;
|
|
100
|
+
/** The `ts` of the event that made it terminal; retention is measured from it. */
|
|
101
|
+
terminalTs: string | null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* What one tick would do.
|
|
105
|
+
*
|
|
106
|
+
* `completions` are hashes whose `payload.pruned` is already in the log while the
|
|
107
|
+
* file is still on disk — a crash between the append and the unlink, or a store
|
|
108
|
+
* that was restored from a backup taken before the prune. They are unlinked and
|
|
109
|
+
* **no second event is appended**: the log already states the fact.
|
|
110
|
+
*/
|
|
111
|
+
export interface PrunePlan {
|
|
112
|
+
candidates: PruneCandidate[];
|
|
113
|
+
completions: string[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* What may be pruned right now. Pure: no I/O, no clock, no policy loading.
|
|
117
|
+
*
|
|
118
|
+
* `retentionMs` is `null` when the policy declares no `payload_retention` — or
|
|
119
|
+
* when the policy could not be loaded at all, which fails closed to the same
|
|
120
|
+
* answer. Either way the plan is empty: the subsystem does not run.
|
|
121
|
+
*
|
|
122
|
+
* `nowIso` is the evaluation moment, injected. A pruner that read the clock
|
|
123
|
+
* itself could not be replayed, and retention arithmetic that cannot be replayed
|
|
124
|
+
* cannot be audited.
|
|
125
|
+
*/
|
|
126
|
+
export declare function planPrune(records: EventRecord[], presentHashes: string[], nowIso: string, retentionMs: number | null): PrunePlan;
|
|
127
|
+
/** Why a prune pass complained. Reported to the caller; never thrown. */
|
|
128
|
+
export type PruneWarningCode =
|
|
129
|
+
/** The verified read refused, so nothing was planned this pass. */
|
|
130
|
+
"log-unreadable"
|
|
131
|
+
/** A `payload.pruned` append was refused; the file stays, untouched. */
|
|
132
|
+
| "append-refused"
|
|
133
|
+
/** The event landed but the file could not be removed. The next tick retries. */
|
|
134
|
+
| "unlink-failed";
|
|
135
|
+
export interface PruneWarning {
|
|
136
|
+
code: PruneWarningCode;
|
|
137
|
+
message: string;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* One prune that completed: the event landed AND the bytes went (APRV-57).
|
|
141
|
+
*
|
|
142
|
+
* Reported separately from {@link PruneReport.appended} because only these carry
|
|
143
|
+
* a `seq` and only these are finished. A candidate whose append landed and whose
|
|
144
|
+
* unlink FAILED appears in `appended` and in `warnings`, never here: the store
|
|
145
|
+
* still holds the bytes, and a success line for it would say otherwise.
|
|
146
|
+
*
|
|
147
|
+
* Crash-window completions ({@link PrunePlan.completions}) are absent for the
|
|
148
|
+
* opposite reason: they append nothing, so there is no record for a `seq` to
|
|
149
|
+
* name, and the log said the file was gone on some earlier tick already.
|
|
150
|
+
*/
|
|
151
|
+
export interface PrunedRecord {
|
|
152
|
+
candidate: PruneCandidate;
|
|
153
|
+
/** `seq` of the appended `payload.pruned` record. */
|
|
154
|
+
seq: number;
|
|
155
|
+
}
|
|
156
|
+
export interface PruneReport {
|
|
157
|
+
/** `payload_retention` in milliseconds, or `null` when the subsystem is off. */
|
|
158
|
+
retentionMs: number | null;
|
|
159
|
+
/** Hashes for which a `payload.pruned` was appended this pass. */
|
|
160
|
+
appended: PruneCandidate[];
|
|
161
|
+
/** Appended-and-unlinked prunes, with the seq of each event (APRV-57). */
|
|
162
|
+
pruned: PrunedRecord[];
|
|
163
|
+
/** Hashes whose file was removed (appended-then-unlinked, plus completions). */
|
|
164
|
+
removed: string[];
|
|
165
|
+
/** Crash-window files finished without a second event. */
|
|
166
|
+
completed: string[];
|
|
167
|
+
warnings: PruneWarning[];
|
|
168
|
+
}
|
|
169
|
+
export interface PruneOptions {
|
|
170
|
+
/** The append-only log. Re-read before every append. */
|
|
171
|
+
logPath: string;
|
|
172
|
+
/** The payload store. Defaults to the store beside `logPath`. */
|
|
173
|
+
storeDir?: string;
|
|
174
|
+
/** Policy location, with `loadPolicy`'s semantics. */
|
|
175
|
+
policy: {
|
|
176
|
+
dir?: string;
|
|
177
|
+
file?: string;
|
|
178
|
+
};
|
|
179
|
+
schemaDir?: string;
|
|
180
|
+
/** The write-boundary clock (amended SPEC.md §8). Tests inject; production does not. */
|
|
181
|
+
clock?: Clock;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Read `payload_retention` from the policy in force right now.
|
|
185
|
+
*
|
|
186
|
+
* Fails closed to `null` exactly as the daemon's TTL read does: a policy that
|
|
187
|
+
* cannot be loaded declares no retention, so nothing is pruned on its behalf. An
|
|
188
|
+
* unparseable duration is likewise `null` — the schema's duration pattern makes
|
|
189
|
+
* that unreachable through a validated policy, and a retention rule this module
|
|
190
|
+
* cannot read is not one it may guess at.
|
|
191
|
+
*/
|
|
192
|
+
export declare function retentionMsOf(policy: {
|
|
193
|
+
dir?: string;
|
|
194
|
+
file?: string;
|
|
195
|
+
}, schemaDir?: string): number | null;
|
|
196
|
+
/**
|
|
197
|
+
* One pruning pass: plan, append, unlink, repeat.
|
|
198
|
+
*
|
|
199
|
+
* The log is re-read before each append rather than once for the pass, because
|
|
200
|
+
* each append moves the head the next one is compared against and because a CLI
|
|
201
|
+
* verb may have appended in between. `expectedHead` therefore always names the
|
|
202
|
+
* head the decision was made from; a `head-moved` refusal drops the candidate and
|
|
203
|
+
* the next tick re-derives it.
|
|
204
|
+
*
|
|
205
|
+
* Nothing is retried in place, and no state survives the call.
|
|
206
|
+
*/
|
|
207
|
+
export declare function prunePayloads(options: PruneOptions): PruneReport;
|