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,631 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval daemon run` — the foreground daemon verb (SPEC.md §10.2, APRV-39).
|
|
3
|
+
*
|
|
4
|
+
* As everywhere else in this CLI, **no logic lives here**. The loop, the drift
|
|
5
|
+
* comparison, the TTL sweep, and the queue regeneration are `daemon/daemon.ts`
|
|
6
|
+
* and `daemon/projection.ts`; every append they make goes through the same
|
|
7
|
+
* `core/gate.ts` and `core/log.ts` paths every other verb uses. This file
|
|
8
|
+
* resolves paths, validates two durations, renders the daemon's event stream as
|
|
9
|
+
* text or JSON, installs the signal handlers, and chooses an exit code.
|
|
10
|
+
*
|
|
11
|
+
* ## Foreground, deliberately
|
|
12
|
+
*
|
|
13
|
+
* `approval daemon run` runs in the foreground and stops on SIGINT/SIGTERM. It
|
|
14
|
+
* does not fork, write a pidfile, or manage its own lifecycle: in v0.1
|
|
15
|
+
* backgrounding is the operator's business, and `systemd`, `launchd`, `tmux`,
|
|
16
|
+
* and `&` all already do it better than a bespoke daemonizer would. That is
|
|
17
|
+
* stated in `--help` because an operator has to know it before they type it, and
|
|
18
|
+
* it is exactly the stance `approval channel telegram listen` takes for the same
|
|
19
|
+
* reason.
|
|
20
|
+
*
|
|
21
|
+
* ## What the exit code means
|
|
22
|
+
*
|
|
23
|
+
* A clean stop is 0 — a signal is how this verb is *supposed* to end. The three
|
|
24
|
+
* non-zero endings are the log's, mapped onto the frozen table exactly as every
|
|
25
|
+
* other verb maps them: 4 when the log cannot be read, 3 when its tail is torn,
|
|
26
|
+
* 1 when the chain does not verify. The daemon stops rather than degrades on all
|
|
27
|
+
* three, because nothing may be appended onto a log that does not verify and a
|
|
28
|
+
* projection of one would be a screenshot of something nobody should read.
|
|
29
|
+
*/
|
|
30
|
+
import { isAbsolute, resolve as resolvePathSegments } from "node:path";
|
|
31
|
+
import { DEFAULT_DEBOUNCE_MS, DEFAULT_INTERVAL_MS, DEFAULT_TASKS_DIR, Daemon, isDirectory, } from "../daemon/daemon.js";
|
|
32
|
+
import { defaultCadence } from "../daemon/advance.js";
|
|
33
|
+
import { drawServerFor } from "../daemon/draw.js";
|
|
34
|
+
import { enableGitEvidence } from "../daemon/git-evidence.js";
|
|
35
|
+
import { DEFAULT_DARK_INTERVAL_MS, DEFAULT_DARK_WINDOW_MS, } from "../daemon/dark-session.js";
|
|
36
|
+
import { DEFAULT_POLICY_DAEMON_READ, loadPolicy, parseDuration, } from "../core/policy-load.js";
|
|
37
|
+
import { boolFlag, parseFlags, stringFlag } from "./args.js";
|
|
38
|
+
import { EXIT_INTEGRITY, EXIT_IO, EXIT_OK, EXIT_TORN_TAIL, EXIT_USAGE, } from "./exit-codes.js";
|
|
39
|
+
import { DAEMON_HELP, DAEMON_RUN_HELP } from "./help.js";
|
|
40
|
+
import { useReadProof } from "../core/state.js";
|
|
41
|
+
import { DEFAULT_LOG_PATH, preflightLog, resolvePath } from "./paths.js";
|
|
42
|
+
import { describePreflightEvent, reexecFreshBuild, startupPreflight, } from "./preflight.js";
|
|
43
|
+
import { DEFAULT_QUEUE_PATH } from "./render.js";
|
|
44
|
+
import { refusal as renderRefusal, style } from "./style.js";
|
|
45
|
+
import { usageErrorText } from "./usage.js";
|
|
46
|
+
const RUN_FLAGS = {
|
|
47
|
+
"--log": "string",
|
|
48
|
+
"--tasks": "string",
|
|
49
|
+
"--out": "string",
|
|
50
|
+
"--policy": "string",
|
|
51
|
+
"--dir": "string",
|
|
52
|
+
"--interval": "string",
|
|
53
|
+
"--debounce": "string",
|
|
54
|
+
"--once": "boolean",
|
|
55
|
+
// The watcher trace (APRV-230). A diagnostic: it prints one line per
|
|
56
|
+
// filesystem event, ignored ones included, and changes nothing else.
|
|
57
|
+
"--trace-watch": "boolean",
|
|
58
|
+
"--git-evidence": "boolean",
|
|
59
|
+
// The cadence advance (APRV-204). Opt-in, like `--git-evidence`: it pushes to
|
|
60
|
+
// a remote and opens pull requests, which a daemon must never start doing
|
|
61
|
+
// because a default moved under an operator who did not ask.
|
|
62
|
+
"--advance": "boolean",
|
|
63
|
+
"--advance-interval": "string",
|
|
64
|
+
"--advance-after": "string",
|
|
65
|
+
"--advance-remote": "string",
|
|
66
|
+
"--advance-base": "string",
|
|
67
|
+
"--no-advance-pr": "boolean",
|
|
68
|
+
"--no-advance-auto-merge": "boolean",
|
|
69
|
+
// The dark-session sweep (APRV-192). Opt-in for the reason above, in a milder
|
|
70
|
+
// form: it runs `git log` over every worktree of the checkout on a cadence.
|
|
71
|
+
"--dark-sessions": "boolean",
|
|
72
|
+
// The live draw (APRV-208). A way OUT only: serving draws needs the sampling
|
|
73
|
+
// secret in this process's environment, which is already an operator's
|
|
74
|
+
// deliberate act, so there is nothing to opt into. This is here so an operator
|
|
75
|
+
// can take the control back without unsetting a variable their shell profile
|
|
76
|
+
// exports.
|
|
77
|
+
"--no-draw": "boolean",
|
|
78
|
+
"--dark-window": "string",
|
|
79
|
+
"--dark-interval": "string",
|
|
80
|
+
// The prefix proof (APRV-217). A flag here beats the `daemon` policy block
|
|
81
|
+
// for this run and nothing else; the policy is what an unattended service
|
|
82
|
+
// reads.
|
|
83
|
+
"--read-proof": "string",
|
|
84
|
+
"--full-reproof-every": "string",
|
|
85
|
+
"--full-reproof-after": "string",
|
|
86
|
+
// The startup preflight (APRV-215), spelled identically on `approval up`.
|
|
87
|
+
"--no-preflight": "boolean",
|
|
88
|
+
"--preflight-remote": "string",
|
|
89
|
+
"--preflight-base": "string",
|
|
90
|
+
// The rebuild half of it, alone (APRV-301), spelled identically on `up`.
|
|
91
|
+
"--no-build": "boolean",
|
|
92
|
+
// Test-only, spelled exactly as doctor's and `up`'s.
|
|
93
|
+
"--root": "string",
|
|
94
|
+
"--json": "boolean",
|
|
95
|
+
"--help": "boolean",
|
|
96
|
+
"-h": "boolean",
|
|
97
|
+
};
|
|
98
|
+
function absolute(value, cwd) {
|
|
99
|
+
return isAbsolute(value) ? value : resolvePathSegments(cwd, value);
|
|
100
|
+
}
|
|
101
|
+
function usageError(streams, json, message, help) {
|
|
102
|
+
if (json)
|
|
103
|
+
streams.err(`${JSON.stringify({ error: { code: "usage", message } })}\n`);
|
|
104
|
+
else
|
|
105
|
+
streams.err(usageErrorText(message, help));
|
|
106
|
+
return EXIT_USAGE;
|
|
107
|
+
}
|
|
108
|
+
function ioError(streams, json, message) {
|
|
109
|
+
if (json)
|
|
110
|
+
streams.err(`${JSON.stringify({ error: { code: "io", message } })}\n`);
|
|
111
|
+
else
|
|
112
|
+
streams.err(`approval: ${message}\n`);
|
|
113
|
+
return EXIT_IO;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A duration flag, in the policy's own `<n><unit>` vocabulary (SPEC.md §5.2).
|
|
117
|
+
*
|
|
118
|
+
* Exported for `approval up` (APRV-110), which accepts the same three durations
|
|
119
|
+
* and must refuse a typo in exactly the same words.
|
|
120
|
+
*/
|
|
121
|
+
export function durationFlag(flags, name, fallback) {
|
|
122
|
+
const raw = stringFlag(flags, name);
|
|
123
|
+
if (raw === null)
|
|
124
|
+
return { ok: true, ms: fallback };
|
|
125
|
+
const ms = parseDuration(raw);
|
|
126
|
+
if (ms === null || ms <= 0) {
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
message: `${name} expects a duration like 30s, 5m or 250ms (a positive integer and one unit of ms|s|m|h|d|w), got ${JSON.stringify(raw)}`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { ok: true, ms };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The cadence-advance flags, as one cadence or none (APRV-204).
|
|
136
|
+
*
|
|
137
|
+
* Exported for `approval up`, which accepts every `daemon run` flag and must
|
|
138
|
+
* refuse a typo in exactly the same words — the reason {@link durationFlag} is
|
|
139
|
+
* exported, and the reason this parsing is not written twice.
|
|
140
|
+
*
|
|
141
|
+
* Every duration and count is judged HERE, before the first tick: a daemon that
|
|
142
|
+
* accepted `--advance-after twenty` and quietly advanced on the default would be
|
|
143
|
+
* lying about its own configuration for as long as it ran.
|
|
144
|
+
*/
|
|
145
|
+
export function advanceFlags(flags) {
|
|
146
|
+
if (!boolFlag(flags, "--advance"))
|
|
147
|
+
return { ok: true, cadence: null };
|
|
148
|
+
const fallback = defaultCadence();
|
|
149
|
+
const interval = durationFlag(flags, "--advance-interval", fallback.intervalMs);
|
|
150
|
+
if (!interval.ok)
|
|
151
|
+
return { ok: false, message: interval.message };
|
|
152
|
+
const afterRaw = stringFlag(flags, "--advance-after");
|
|
153
|
+
const after = afterRaw === null ? fallback.afterRecords : Number.parseInt(afterRaw, 10);
|
|
154
|
+
if (!Number.isInteger(after) || after < 1) {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
message: `--advance-after expects a positive whole number of records, got ${JSON.stringify(afterRaw)}`,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
ok: true,
|
|
162
|
+
cadence: {
|
|
163
|
+
intervalMs: interval.ms,
|
|
164
|
+
afterRecords: after,
|
|
165
|
+
remote: stringFlag(flags, "--advance-remote") ?? fallback.remote,
|
|
166
|
+
base: stringFlag(flags, "--advance-base"),
|
|
167
|
+
pr: !boolFlag(flags, "--no-advance-pr"),
|
|
168
|
+
// APRV-284. Armed by default: a records pull request nobody arms is a
|
|
169
|
+
// pull request sitting at CLEAN waiting for a click that was never a
|
|
170
|
+
// review. `--no-advance-auto-merge` puts it back on a person.
|
|
171
|
+
autoMerge: !boolFlag(flags, "--no-advance-auto-merge"),
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The prefix-proof flags, resolved against the policy (APRV-217).
|
|
177
|
+
*
|
|
178
|
+
* Precedence is the one every override in this CLI uses: the flag wins for this
|
|
179
|
+
* run, the policy governs when no flag was typed, and an unloadable policy
|
|
180
|
+
* yields the default — which here is `full`, the strictest and most expensive
|
|
181
|
+
* proof, so a policy nobody could read cannot buy a cheaper one.
|
|
182
|
+
*
|
|
183
|
+
* Exported for `approval up`, which accepts every `daemon run` flag and must
|
|
184
|
+
* refuse a typo in exactly the same words — the reason {@link durationFlag} and
|
|
185
|
+
* {@link advanceFlags} are exported.
|
|
186
|
+
*/
|
|
187
|
+
export function readProofFlags(flags, policy) {
|
|
188
|
+
const loaded = loadPolicy(policy);
|
|
189
|
+
const configured = loaded.ok ? loaded.daemon : DEFAULT_POLICY_DAEMON_READ;
|
|
190
|
+
const modeRaw = stringFlag(flags, "--read-proof");
|
|
191
|
+
if (modeRaw !== null && modeRaw !== "full" && modeRaw !== "incremental") {
|
|
192
|
+
return {
|
|
193
|
+
ok: false,
|
|
194
|
+
message: `--read-proof expects full or incremental, got ${JSON.stringify(modeRaw)}`,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const mode = modeRaw === null ? configured.readProof : modeRaw;
|
|
198
|
+
const everyRaw = stringFlag(flags, "--full-reproof-every");
|
|
199
|
+
const everyReads = everyRaw === null ? configured.fullReproofEvery : Number.parseInt(everyRaw, 10);
|
|
200
|
+
if (!Number.isInteger(everyReads) || everyReads < 1) {
|
|
201
|
+
return {
|
|
202
|
+
ok: false,
|
|
203
|
+
message: `--full-reproof-every expects a positive whole number of reads, got ${JSON.stringify(everyRaw)}`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const after = durationFlag(flags, "--full-reproof-after", configured.fullReproofAfterMs);
|
|
207
|
+
if (!after.ok)
|
|
208
|
+
return { ok: false, message: after.message };
|
|
209
|
+
return { ok: true, readProof: { mode, everyReads, afterMs: after.ms } };
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* One daemon event as a human sentence.
|
|
213
|
+
*
|
|
214
|
+
* Warnings go to stderr and everything else to stdout, so `approval daemon run >
|
|
215
|
+
* daemon.log` keeps the narrative and leaves the complaints on the terminal.
|
|
216
|
+
*/
|
|
217
|
+
export function describeDaemonEvent(event) {
|
|
218
|
+
switch (event.event) {
|
|
219
|
+
case "started":
|
|
220
|
+
return {
|
|
221
|
+
// The prefix proof is named on the line an operator already reads
|
|
222
|
+
// (APRV-217): which proof the reads of this run pay is configuration,
|
|
223
|
+
// and configuration nobody is told about is the failure mode this
|
|
224
|
+
// project exists to prevent.
|
|
225
|
+
text: `daemon: watching ${event.tasks} and ${event.log}; queue ${event.queue}; tick every ${String(event.interval_ms)}ms; read proof ${event.read_proof}; anchor ${
|
|
226
|
+
// APRV-219: named for the reason the prefix proof is. Which external
|
|
227
|
+
// witness this run holds its log to is not something an operator
|
|
228
|
+
// should have to ask a running process about, and "none" is a fact
|
|
229
|
+
// worth printing rather than a blank.
|
|
230
|
+
event.anchor.rev === null
|
|
231
|
+
? `none (${event.anchor.reason ?? "no committed copy of the log"})`
|
|
232
|
+
: `${event.anchor.rev} seq ${String(event.anchor.seq ?? 0)}`}${event.watching ? "" : " (fs watch unavailable — polling only)"}`,
|
|
233
|
+
stderr: false,
|
|
234
|
+
};
|
|
235
|
+
case "drift":
|
|
236
|
+
// The envelope-missing case (APRV-63) reads differently on purpose: there
|
|
237
|
+
// is no claim to quote, and the repair is a restoration a human makes.
|
|
238
|
+
if (event.reason === "envelope-missing") {
|
|
239
|
+
return {
|
|
240
|
+
text: `envelope.drift: ${event.task} (${event.file}) has NO approval: envelope, but the log registered it — the log says state ${event.derived_state}; recorded at seq ${String(event.seq)}. Restore the envelope by hand from the log; the runtime never rewrites the file`,
|
|
241
|
+
stderr: false,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
text: `envelope.drift: ${event.task} (${event.file}) claims state ${event.declared_state === null ? "<none>" : event.declared_state}, the log says ${event.derived_state} — recorded at seq ${String(event.seq)}; the file is repaired to match the log later in this tick`,
|
|
246
|
+
stderr: false,
|
|
247
|
+
};
|
|
248
|
+
case "write_back":
|
|
249
|
+
return {
|
|
250
|
+
text: `write-back: ${event.task} (${event.file}) state ${event.from === null ? "<none>" : event.from} -> ${event.to}, ${String(event.bytes)} bytes; the file now says what the log says`,
|
|
251
|
+
stderr: false,
|
|
252
|
+
};
|
|
253
|
+
case "expired":
|
|
254
|
+
return {
|
|
255
|
+
text: `approval.expired: ${event.action_key} lapsed its TTL — recorded at seq ${String(event.seq)}`,
|
|
256
|
+
stderr: false,
|
|
257
|
+
};
|
|
258
|
+
case "sampled":
|
|
259
|
+
return {
|
|
260
|
+
text: `audit.sampled: ${event.action_key} drawn for review (execution.started at seq ${String(event.subject_seq)}) — recorded at seq ${String(event.seq)}`,
|
|
261
|
+
stderr: false,
|
|
262
|
+
};
|
|
263
|
+
case "pruned":
|
|
264
|
+
return {
|
|
265
|
+
text: `payload.pruned: ${event.payload_hash} removed (${event.reason}${event.action_key === null ? "" : `, ${event.action_key}`}) — recorded at seq ${String(event.seq)}`,
|
|
266
|
+
stderr: false,
|
|
267
|
+
};
|
|
268
|
+
case "rendered":
|
|
269
|
+
return {
|
|
270
|
+
text: `queue: ${event.path} regenerated (${String(event.bytes)} bytes, ${String(event.pending)} pending, ${String(event.skipped)} not summarized, ${String(event.audit_backlog)} awaiting audit review)`,
|
|
271
|
+
stderr: false,
|
|
272
|
+
};
|
|
273
|
+
case "advance":
|
|
274
|
+
// The refused and gated outcomes go to stderr beside their warning, for
|
|
275
|
+
// the reason every warning does: a records branch that did not move is a
|
|
276
|
+
// complaint, and a complaint belongs where an operator's eye is.
|
|
277
|
+
return {
|
|
278
|
+
text: event.outcome === "advanced"
|
|
279
|
+
? `log advance: ${event.message}${event.flush ? " (shutdown flush)" : ""}${event.pr_created ? " — pull request opened" : ""}`
|
|
280
|
+
: `log advance ${event.outcome}${event.code === null ? "" : ` (${event.code})`}: ${event.message} — ${String(event.records_pending)} record(s) still off ${event.records_branch ?? "any records branch"}`,
|
|
281
|
+
stderr: event.outcome !== "advanced",
|
|
282
|
+
};
|
|
283
|
+
case "dark_session":
|
|
284
|
+
// Both verdicts go to stderr. A dark session is the loudest thing this
|
|
285
|
+
// loop can say — git activity nobody was told about — and an undetermined
|
|
286
|
+
// one is a gap in the detector's own sight; neither belongs in the stream
|
|
287
|
+
// an operator scrolls past.
|
|
288
|
+
return {
|
|
289
|
+
text: renderRefusal(style(), event.verdict === "dark" ? `dark-session:${event.code}` : `dark-session-undetermined:${event.code}`, `${event.subject}${event.branch === null ? "" : ` (branch ${event.branch})`}: ${event.message}${event.seq === null
|
|
290
|
+
? event.already_recorded
|
|
291
|
+
? " — already recorded in this log; nothing appended"
|
|
292
|
+
: ""
|
|
293
|
+
: ` — recorded at seq ${String(event.seq)}`}`),
|
|
294
|
+
stderr: true,
|
|
295
|
+
};
|
|
296
|
+
case "escalated":
|
|
297
|
+
return {
|
|
298
|
+
text: `loop escalation: ${event.task} has ${String(event.consecutive_failures)} consecutive execution.failed and is escalated to manual; its supervised and autonomous actions are refused until an execution.completed lands`,
|
|
299
|
+
stderr: false,
|
|
300
|
+
};
|
|
301
|
+
case "escalation_cleared":
|
|
302
|
+
return {
|
|
303
|
+
text: `loop escalation cleared: ${event.task} recorded an execution.completed`,
|
|
304
|
+
stderr: false,
|
|
305
|
+
};
|
|
306
|
+
case "watch":
|
|
307
|
+
// APRV-230's trace, off unless the operator asked for it. On stdout with
|
|
308
|
+
// the rest of the narrative: it is an observation, not a complaint, and an
|
|
309
|
+
// operator who turned it on is reading it.
|
|
310
|
+
return {
|
|
311
|
+
text: `watch: ${event.watcher} ${event.type} ${event.file ?? "<unnamed>"} — ${event.action === "scheduled" ? "tick scheduled" : `ignored (${event.reason ?? "?"})`}`,
|
|
312
|
+
stderr: false,
|
|
313
|
+
};
|
|
314
|
+
case "tick":
|
|
315
|
+
return {
|
|
316
|
+
// The cost of the tick is on the line an operator already reads
|
|
317
|
+
// (APRV-211): a tick that takes seconds, or that reads the log dozens of
|
|
318
|
+
// times, is the shape of the incident this field exists to make obvious.
|
|
319
|
+
// What WOKE it is on the same line for the same reason (APRV-230): a
|
|
320
|
+
// tick nobody asked for costs exactly as much as one somebody did.
|
|
321
|
+
text: `tick ${String(event.n)}: head ${event.head === null ? "none" : `seq ${String(event.head)}`}, ${String(event.drift)} drift, ${String(event.expired)} expired, ${String(event.escalated)} escalated (${String(event.ms)} ms, ${String(event.reads)} reads, woke by ${event.woke_by}${event.woke_file === undefined ? "" : ` ${event.woke_file}`})`,
|
|
322
|
+
stderr: false,
|
|
323
|
+
};
|
|
324
|
+
case "warning":
|
|
325
|
+
return { text: renderRefusal(style(), event.code, event.message), stderr: true };
|
|
326
|
+
case "stopped":
|
|
327
|
+
return {
|
|
328
|
+
text: `daemon: stopped (${event.reason}) after ${String(event.ticks)} tick(s): ${String(event.drift)} drift, ${String(event.expired)} expired, ${String(event.renders)} render(s)`,
|
|
329
|
+
stderr: false,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* One git-evidence line as a human sentence (APRV-42).
|
|
335
|
+
*
|
|
336
|
+
* Its own function rather than a branch of {@link describe}, because the
|
|
337
|
+
* hardening layer has its own frozen event shape and `daemon/daemon.ts`'s union
|
|
338
|
+
* is untouched by the opt-in. Failures go to stderr with everything else that
|
|
339
|
+
* complains.
|
|
340
|
+
*/
|
|
341
|
+
export function describeGitEvidence(event) {
|
|
342
|
+
if (event.event === "git_evidence_failed") {
|
|
343
|
+
return { text: renderRefusal(style(), "git-evidence", event.message), stderr: true };
|
|
344
|
+
}
|
|
345
|
+
const covered = event.records === null
|
|
346
|
+
? "the log as it stands"
|
|
347
|
+
: `${String(event.records)} record(s) since the previous commit`;
|
|
348
|
+
return {
|
|
349
|
+
text: `git evidence: commit ${event.commit} witnesses seq ${String(event.seq)} (${covered})`,
|
|
350
|
+
stderr: false,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
/** The outcome → frozen exit code mapping, drawn where every other verb draws it. */
|
|
354
|
+
export function exitForDaemonOutcome(outcome) {
|
|
355
|
+
switch (outcome.kind) {
|
|
356
|
+
case "stopped":
|
|
357
|
+
return EXIT_OK;
|
|
358
|
+
case "log-unreadable":
|
|
359
|
+
return EXIT_IO;
|
|
360
|
+
case "log-torn-tail":
|
|
361
|
+
return EXIT_TORN_TAIL;
|
|
362
|
+
case "log-corrupt":
|
|
363
|
+
return EXIT_INTEGRITY;
|
|
364
|
+
// APRV-219. Drawn where `log-corrupt` is drawn, and for the same reason: a
|
|
365
|
+
// log that contradicts its own committed copy is an integrity failure, and
|
|
366
|
+
// a supervisor that restarts on 4 and stops on 1 must stop on this.
|
|
367
|
+
case "anchor-diverged":
|
|
368
|
+
return EXIT_INTEGRITY;
|
|
369
|
+
// APRV-220. The same place again, for the third witness: a log that
|
|
370
|
+
// contradicts a signature a human made over it is an integrity failure,
|
|
371
|
+
// whatever the chain walk and the committed copy say about it.
|
|
372
|
+
case "checkpoint-invalid":
|
|
373
|
+
return EXIT_INTEGRITY;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* `approval daemon run`. Returns a promise, so `main` treats `daemon` the way it
|
|
378
|
+
* treats `channel`: the CLI is synchronous by contract, and the two long-lived
|
|
379
|
+
* verbs report their eventual code through `process.exitCode`.
|
|
380
|
+
*/
|
|
381
|
+
export function commandDaemonRun(argv, streams, cwd) {
|
|
382
|
+
// APRV-110. `--with-channels` is the same verb as `approval up`, spelled from
|
|
383
|
+
// the daemon's side for an operator who already has the daemon invocation in a
|
|
384
|
+
// unit file. Answered BEFORE the flag table below, because the ambient runtime
|
|
385
|
+
// accepts flags this one does not (an approver identity, a Bot API base, a
|
|
386
|
+
// port), and a parse against this table would refuse them first. The import is
|
|
387
|
+
// dynamic so that `cli/up.ts` can go on statically importing this module for
|
|
388
|
+
// its daemon-event renderers without an ESM cycle between the two.
|
|
389
|
+
if (argv.includes("--with-channels")) {
|
|
390
|
+
const rest = argv.filter((word) => word !== "--with-channels");
|
|
391
|
+
return import("./up.js").then((module) => module.commandUp(rest, streams, cwd));
|
|
392
|
+
}
|
|
393
|
+
const json = argv.includes("--json");
|
|
394
|
+
const parsed = parseFlags(argv, RUN_FLAGS);
|
|
395
|
+
if (!parsed.ok)
|
|
396
|
+
return usageError(streams, json, parsed.message, DAEMON_RUN_HELP);
|
|
397
|
+
if (boolFlag(parsed.flags, "--help") || boolFlag(parsed.flags, "-h")) {
|
|
398
|
+
streams.out(`${DAEMON_RUN_HELP}\n`);
|
|
399
|
+
return EXIT_OK;
|
|
400
|
+
}
|
|
401
|
+
const extra = parsed.positionals[0];
|
|
402
|
+
if (extra !== undefined) {
|
|
403
|
+
return usageError(streams, json, `unexpected argument ${JSON.stringify(extra)}`, DAEMON_RUN_HELP);
|
|
404
|
+
}
|
|
405
|
+
const flags = parsed.flags;
|
|
406
|
+
const interval = durationFlag(flags, "--interval", DEFAULT_INTERVAL_MS);
|
|
407
|
+
if (!interval.ok)
|
|
408
|
+
return usageError(streams, json, interval.message, DAEMON_RUN_HELP);
|
|
409
|
+
const debounce = durationFlag(flags, "--debounce", DEFAULT_DEBOUNCE_MS);
|
|
410
|
+
if (!debounce.ok)
|
|
411
|
+
return usageError(streams, json, debounce.message, DAEMON_RUN_HELP);
|
|
412
|
+
const logPath = resolvePath(stringFlag(flags, "--log"), DEFAULT_LOG_PATH, cwd);
|
|
413
|
+
const queuePath = resolvePath(stringFlag(flags, "--out"), DEFAULT_QUEUE_PATH, cwd);
|
|
414
|
+
const tasksFlag = stringFlag(flags, "--tasks");
|
|
415
|
+
const tasksDir = resolvePath(tasksFlag, DEFAULT_TASKS_DIR, cwd);
|
|
416
|
+
// The startup preflight (APRV-215), the same one `approval up` runs, from the
|
|
417
|
+
// same module, printing the same two lines. It is here as well as there
|
|
418
|
+
// because the daemon is the writer: a daemon started against a stale checkout
|
|
419
|
+
// is the failure this preflight exists to catch, and `--with-channels` is not
|
|
420
|
+
// the only way an operator reaches it. `--no-preflight` opts out on both.
|
|
421
|
+
if (!boolFlag(flags, "--no-preflight")) {
|
|
422
|
+
const rootFlag = stringFlag(flags, "--root");
|
|
423
|
+
const cleared = startupPreflight({
|
|
424
|
+
logPath,
|
|
425
|
+
queuePath,
|
|
426
|
+
root: rootFlag === null ? null : absolute(rootFlag, cwd),
|
|
427
|
+
remote: stringFlag(flags, "--preflight-remote"),
|
|
428
|
+
branch: stringFlag(flags, "--preflight-base"),
|
|
429
|
+
build: !boolFlag(flags, "--no-build"),
|
|
430
|
+
json,
|
|
431
|
+
emit: (event) => {
|
|
432
|
+
if (json) {
|
|
433
|
+
const line = `${JSON.stringify(event)}\n`;
|
|
434
|
+
if (event.event === "preflight_warning")
|
|
435
|
+
streams.err(line);
|
|
436
|
+
else
|
|
437
|
+
streams.out(line);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const rendered = describePreflightEvent(event);
|
|
441
|
+
if (rendered.stderr)
|
|
442
|
+
streams.err(`${rendered.text}\n`);
|
|
443
|
+
else
|
|
444
|
+
streams.out(`${rendered.text}\n`);
|
|
445
|
+
},
|
|
446
|
+
refuse: (text) => streams.err(text),
|
|
447
|
+
});
|
|
448
|
+
// Exit 1, "the runtime decided": nothing failed to read or write, and a
|
|
449
|
+
// supervisor that read this as an I/O fault would retry a checkout state
|
|
450
|
+
// only a human can resolve.
|
|
451
|
+
if (!cleared.ok)
|
|
452
|
+
return EXIT_INTEGRITY;
|
|
453
|
+
// The same handover `approval up` makes, for the same reason: a rebuild
|
|
454
|
+
// means this process is the stale build, and the daemon is the writer. See
|
|
455
|
+
// `cli/preflight.ts`'s `reexecFreshBuild`.
|
|
456
|
+
if (cleared.reexec !== null)
|
|
457
|
+
return reexecFreshBuild(cleared.reexec, cwd);
|
|
458
|
+
}
|
|
459
|
+
const check = preflightLog(logPath);
|
|
460
|
+
if (!check.ok)
|
|
461
|
+
return ioError(streams, json, check.message);
|
|
462
|
+
// An explicitly named task folder that does not exist is a typo, and a daemon
|
|
463
|
+
// that watched nothing while reporting success would hide it. The DEFAULT
|
|
464
|
+
// folder is allowed to be absent: a repository with no `backlog/` is a
|
|
465
|
+
// legitimate log-only deployment, and it is warned about, not refused.
|
|
466
|
+
if (!isDirectory(tasksDir)) {
|
|
467
|
+
if (tasksFlag !== null) {
|
|
468
|
+
return ioError(streams, json, `--tasks ${tasksDir} is not a directory; nothing would be watched for envelope drift`);
|
|
469
|
+
}
|
|
470
|
+
streams.err(`approval: task folder ${tasksDir} does not exist, so no envelope drift can be detected; the TTL sweep and the queue projection run anyway (pass --tasks <dir> if your task files live elsewhere)\n`);
|
|
471
|
+
}
|
|
472
|
+
const policyFlag = stringFlag(flags, "--policy");
|
|
473
|
+
const dirFlag = stringFlag(flags, "--dir");
|
|
474
|
+
const policy = policyFlag !== null
|
|
475
|
+
? { file: absolute(policyFlag, cwd) }
|
|
476
|
+
: { dir: dirFlag === null ? cwd : absolute(dirFlag, cwd) };
|
|
477
|
+
const options = {
|
|
478
|
+
logPath,
|
|
479
|
+
tasksDir,
|
|
480
|
+
queuePath,
|
|
481
|
+
policy,
|
|
482
|
+
cwd,
|
|
483
|
+
intervalMs: interval.ms,
|
|
484
|
+
debounceMs: debounce.ms,
|
|
485
|
+
once: boolFlag(flags, "--once"),
|
|
486
|
+
traceWatch: boolFlag(flags, "--trace-watch"),
|
|
487
|
+
sink: {
|
|
488
|
+
emit: (event) => {
|
|
489
|
+
if (json) {
|
|
490
|
+
const line = `${JSON.stringify(event)}\n`;
|
|
491
|
+
if (event.event === "warning")
|
|
492
|
+
streams.err(line);
|
|
493
|
+
else
|
|
494
|
+
streams.out(line);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const rendered = describeDaemonEvent(event);
|
|
498
|
+
if (rendered.stderr)
|
|
499
|
+
streams.err(`${rendered.text}\n`);
|
|
500
|
+
else
|
|
501
|
+
streams.out(`${rendered.text}\n`);
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
};
|
|
505
|
+
const cadence = advanceFlags(flags);
|
|
506
|
+
if (!cadence.ok)
|
|
507
|
+
return usageError(streams, json, cadence.message, DAEMON_RUN_HELP);
|
|
508
|
+
if (cadence.cadence !== null)
|
|
509
|
+
options.advance = cadence.cadence;
|
|
510
|
+
// APRV-217. Resolved here, before the first tick, for the reason every other
|
|
511
|
+
// configuration is: a daemon that accepted `--read-proof incrementel` and
|
|
512
|
+
// quietly ran the default would be lying about its own proof for as long as
|
|
513
|
+
// it ran, and the mode it resolves to is printed on its first line.
|
|
514
|
+
const proof = readProofFlags(flags, policy);
|
|
515
|
+
if (!proof.ok)
|
|
516
|
+
return usageError(streams, json, proof.message, DAEMON_RUN_HELP);
|
|
517
|
+
options.readProof = proof.readProof;
|
|
518
|
+
// Process-wide as well as per-read: the loop's own reads carry the option,
|
|
519
|
+
// and the queue renderer's reads — same process, same log, no options of
|
|
520
|
+
// their own — pick it up from here. Set only in this long-lived operator
|
|
521
|
+
// process, and never by a CLI verb an agent runs.
|
|
522
|
+
useReadProof(proof.readProof);
|
|
523
|
+
// The dark-session sweep (APRV-192). Its two durations are refused for a typo
|
|
524
|
+
// in exactly the words every other duration flag is, for the reason
|
|
525
|
+
// `advanceFlags` states: a daemon that accepted `--dark-window twelve` and
|
|
526
|
+
// quietly swept the default would be lying about what it looked at.
|
|
527
|
+
const darkWindow = durationFlag(flags, "--dark-window", DEFAULT_DARK_WINDOW_MS);
|
|
528
|
+
if (!darkWindow.ok)
|
|
529
|
+
return usageError(streams, json, darkWindow.message, DAEMON_RUN_HELP);
|
|
530
|
+
const darkInterval = durationFlag(flags, "--dark-interval", DEFAULT_DARK_INTERVAL_MS);
|
|
531
|
+
if (!darkInterval.ok)
|
|
532
|
+
return usageError(streams, json, darkInterval.message, DAEMON_RUN_HELP);
|
|
533
|
+
if (boolFlag(flags, "--dark-sessions")) {
|
|
534
|
+
options.darkSessions = { windowMs: darkWindow.ms, intervalMs: darkInterval.ms };
|
|
535
|
+
}
|
|
536
|
+
// SPEC.md §8's optional git hardening (APRV-42). Opt-in, checked here and
|
|
537
|
+
// never later: an operator who asked for a second evidence layer and silently
|
|
538
|
+
// did not get one is worse off than one who was refused at startup, so every
|
|
539
|
+
// precondition is judged before the first tick and a failure ends the verb.
|
|
540
|
+
if (boolFlag(flags, "--git-evidence")) {
|
|
541
|
+
const enabled = enableGitEvidence(logPath, (event) => {
|
|
542
|
+
if (json) {
|
|
543
|
+
const line = `${JSON.stringify(event)}\n`;
|
|
544
|
+
if (event.event === "git_evidence_failed")
|
|
545
|
+
streams.err(line);
|
|
546
|
+
else
|
|
547
|
+
streams.out(line);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const rendered = describeGitEvidence(event);
|
|
551
|
+
if (rendered.stderr)
|
|
552
|
+
streams.err(`${rendered.text}\n`);
|
|
553
|
+
else
|
|
554
|
+
streams.out(`${rendered.text}\n`);
|
|
555
|
+
});
|
|
556
|
+
if (!enabled.ok) {
|
|
557
|
+
if (json) {
|
|
558
|
+
streams.err(`${JSON.stringify({ error: { code: enabled.code, message: enabled.message } })}\n`);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
streams.err(`approval: ${enabled.message}\n`);
|
|
562
|
+
}
|
|
563
|
+
// A missing binary or a missing directory is the environment failing to
|
|
564
|
+
// match the request (I/O); a repository in the wrong shape is the request
|
|
565
|
+
// failing to match a valid deployment (usage). The repair differs, and so
|
|
566
|
+
// does the code an operator's supervisor branches on.
|
|
567
|
+
return enabled.code === "git-unavailable" || enabled.code === "log-dir-missing"
|
|
568
|
+
? EXIT_IO
|
|
569
|
+
: EXIT_USAGE;
|
|
570
|
+
}
|
|
571
|
+
options.gitEvidence = enabled.recorder;
|
|
572
|
+
}
|
|
573
|
+
// APRV-208. The live draw, served over an owner-only socket under the
|
|
574
|
+
// approval home so a hook that holds no sampling secret can ask the process
|
|
575
|
+
// that does. Attempted whenever the secret resolves in THIS process's
|
|
576
|
+
// environment — the operator's own act, `eval "$(approval env)"` in the
|
|
577
|
+
// terminal they start the daemon from — and skipped, with a line saying so,
|
|
578
|
+
// when it does not. `--no-draw` is the way out; there is no way in other than
|
|
579
|
+
// holding the secret, which is the point.
|
|
580
|
+
if (!boolFlag(flags, "--no-draw")) {
|
|
581
|
+
const draw = drawServerFor({ logPath, policy });
|
|
582
|
+
if (draw.ok)
|
|
583
|
+
options.draw = draw.server;
|
|
584
|
+
// `no-live-class` is silent: the policy declares nothing live, so nothing is
|
|
585
|
+
// gating that would not have gated anyway and there is no operator decision
|
|
586
|
+
// to inform. Every other refusal names a class this policy declared live and
|
|
587
|
+
// is now gating at 100%, which is a thing to be told once at startup rather
|
|
588
|
+
// than to infer from a month of taps.
|
|
589
|
+
else if (draw.reason !== "no-live-class") {
|
|
590
|
+
streams.err(`approval: live draws will not be served (${draw.reason}): ${draw.message} Every supervised-live action gates to a human until the sampling secret resolves in this daemon's own environment.\n`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const daemon = new Daemon(options);
|
|
594
|
+
const stop = (signal) => daemon.stop(signal);
|
|
595
|
+
process.on("SIGINT", stop);
|
|
596
|
+
process.on("SIGTERM", stop);
|
|
597
|
+
return daemon.run().then((outcome) => {
|
|
598
|
+
process.off("SIGINT", stop);
|
|
599
|
+
process.off("SIGTERM", stop);
|
|
600
|
+
if (outcome.kind !== "stopped") {
|
|
601
|
+
if (json) {
|
|
602
|
+
streams.err(`${JSON.stringify({ error: { code: outcome.kind, message: outcome.message } })}\n`);
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
streams.err(`approval: ${outcome.message}\n`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return exitForDaemonOutcome(outcome);
|
|
609
|
+
}, (cause) => {
|
|
610
|
+
process.off("SIGINT", stop);
|
|
611
|
+
process.off("SIGTERM", stop);
|
|
612
|
+
throw cause;
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
/** `approval daemon <subcommand>` — `run`, and nothing else at v0.1. */
|
|
616
|
+
export function commandDaemon(argv, streams, cwd) {
|
|
617
|
+
const sub = argv[0];
|
|
618
|
+
const rest = argv.slice(1);
|
|
619
|
+
const json = argv.includes("--json");
|
|
620
|
+
if (sub === undefined) {
|
|
621
|
+
return usageError(streams, json, "missing subcommand for `approval daemon`", DAEMON_HELP);
|
|
622
|
+
}
|
|
623
|
+
if (sub === "--help" || sub === "-h" || sub === "help") {
|
|
624
|
+
streams.out(`${DAEMON_HELP}\n`);
|
|
625
|
+
return EXIT_OK;
|
|
626
|
+
}
|
|
627
|
+
if (sub === "run")
|
|
628
|
+
return commandDaemonRun(rest, streams, cwd);
|
|
629
|
+
return usageError(streams, json, `unknown subcommand ${JSON.stringify(sub)} for \`approval daemon\``, DAEMON_HELP);
|
|
630
|
+
}
|
|
631
|
+
//# sourceMappingURL=daemon.js.map
|