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,487 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop safety (SPEC.md §10.2): "three consecutive `execution.failed` events for
|
|
3
|
+
* one task escalate to `manual` regardless of policy".
|
|
4
|
+
*
|
|
5
|
+
* This is a **pure projection over the log** and nothing else. It reads records,
|
|
6
|
+
* counts, and returns; it never appends, never reads the clock, and never
|
|
7
|
+
* consults the policy. Two very different consumers need the same answer and
|
|
8
|
+
* must not be allowed to disagree about it:
|
|
9
|
+
*
|
|
10
|
+
* - `core/gate.ts` refuses to admit a *new* non-manual request for an escalated
|
|
11
|
+
* task (the `loop-escalated` refusal);
|
|
12
|
+
* - `core/execute.ts` refuses to *start* a supervised/autonomous execution for
|
|
13
|
+
* one, directing the caller to the manual path.
|
|
14
|
+
*
|
|
15
|
+
* It lives in its own module rather than inside `core/execute.ts` for a boring
|
|
16
|
+
* structural reason: `execute.ts` imports the gate, so the gate cannot import
|
|
17
|
+
* `execute.ts` back without a cycle. `core/execute.ts` re-exports these names, so
|
|
18
|
+
* the documented home of the projection is still the execution module.
|
|
19
|
+
*
|
|
20
|
+
* ## What "consecutive" means here, stated exactly
|
|
21
|
+
*
|
|
22
|
+
* The streak is **per task**, not per action key — SPEC.md §10.2 says "for one
|
|
23
|
+
* task", and an agent that fails three different actions of the same task in a
|
|
24
|
+
* row is exactly the runaway loop the rule exists to stop.
|
|
25
|
+
*
|
|
26
|
+
* Only two event types move the counter:
|
|
27
|
+
*
|
|
28
|
+
* - `execution.failed` increments it;
|
|
29
|
+
* - `execution.completed` resets it to zero.
|
|
30
|
+
*
|
|
31
|
+
* Everything else — `execution.started`, approvals, budget events, another
|
|
32
|
+
* task's failures — is transparent. In particular a *retry* is not a reset: a
|
|
33
|
+
* failed action that is started again and fails again is two consecutive
|
|
34
|
+
* failures, which is the entire point. Only a successful completion is evidence
|
|
35
|
+
* that the loop broke, so only a completion clears the count.
|
|
36
|
+
*
|
|
37
|
+
* ## Escalation is a floor, never a ban
|
|
38
|
+
*
|
|
39
|
+
* An escalated task is escalated **to manual**, not to refused. Its manual
|
|
40
|
+
* actions still request, still grant, and still execute with a token — a human
|
|
41
|
+
* is now in the loop for every one of them, which is what "escalate to manual"
|
|
42
|
+
* means. Escalation is also **not** cleared by a human decision, only by an
|
|
43
|
+
* `execution.completed`: the log records the recovery, or the escalation stands.
|
|
44
|
+
*
|
|
45
|
+
* ## The harness scopes (APRV-145)
|
|
46
|
+
*
|
|
47
|
+
* Everything above is the per-task streak of SPEC.md §10.2 and is unchanged. A
|
|
48
|
+
* harness adapter (§10.1) mints a fresh task id for every tool call, so that
|
|
49
|
+
* streak cannot leave zero on that surface however wedged the session is. The
|
|
50
|
+
* amended §10.2 answers it with two more streaks, both derived here and both
|
|
51
|
+
* counted in TOOL CALLS rather than in events:
|
|
52
|
+
*
|
|
53
|
+
* - the **session**, `hook:<session id>`, which is a real prefix of every task
|
|
54
|
+
* id the adapter mints, so the scope is recovered from a string the runtime
|
|
55
|
+
* itself wrote rather than from a field an agent hands the gate;
|
|
56
|
+
* - the **actor**, the identity the adapter runs as, because a session id is
|
|
57
|
+
* authored by the party under oversight and a scope key the subject can
|
|
58
|
+
* rotate is a streak the subject can clear (§11.1 invariant 4).
|
|
59
|
+
*
|
|
60
|
+
* A command is escalated when EITHER reaches {@link LOOP_ESCALATION_THRESHOLD}.
|
|
61
|
+
*
|
|
62
|
+
* ## Only side effects accrue (APRV-280, amended SPEC.md §10.2)
|
|
63
|
+
*
|
|
64
|
+
* The streak counts failed executions of classes that DO something. A
|
|
65
|
+
* `read.*` command that exits non-zero has not failed a side effect: a `grep`
|
|
66
|
+
* that matches nothing and an `ls` of a path that is not there both exit 1, and
|
|
67
|
+
* that exit IS the command's answer. Counting those escalated whole sessions to
|
|
68
|
+
* manual over nothing, which is the incident APRV-280 was filed on: forty-eight
|
|
69
|
+
* requests queued in an hour behind three failed greps.
|
|
70
|
+
*
|
|
71
|
+
* The predicate is {@link isSideEffectingClass} and it is stated once. What it
|
|
72
|
+
* does NOT do is let a read clear anything: a tool call whose classes are all
|
|
73
|
+
* reads is transparent to the streak in both directions, so a failing write
|
|
74
|
+
* streak is not cleared by a successful `ls` in between. The strict direction is
|
|
75
|
+
* kept everywhere else too — a class this projection cannot resolve from the log
|
|
76
|
+
* counts as side-effecting, because "we could not establish what this was" is
|
|
77
|
+
* not "this was harmless".
|
|
78
|
+
*
|
|
79
|
+
* The class is read from the `execution.started` record the RUNTIME wrote for
|
|
80
|
+
* the action key (its `payload.class`), never from anything the reporter said
|
|
81
|
+
* (§11.1 invariants 1 and 4). The report chooses the outcome; it does not get to
|
|
82
|
+
* choose the bucket.
|
|
83
|
+
*
|
|
84
|
+
* ## Escalation raises scrutiny on side effects only (APRV-297, amended §10.2)
|
|
85
|
+
*
|
|
86
|
+
* APRV-280 above says what a read does not ACCRUE. This says what a tripped
|
|
87
|
+
* floor does not ROUTE, and it is the same sentence read forward: a tool call
|
|
88
|
+
* whose classes are all `read.*` is answered by the policy under a tripped floor
|
|
89
|
+
* exactly as it is under a clear one.
|
|
90
|
+
*
|
|
91
|
+
* The floor bounds a harm a read cannot cause. It exists to stop an agent
|
|
92
|
+
* retrying a side effect that keeps failing, so routing a `grep` to a phone buys
|
|
93
|
+
* no safety at all, and it costs the thing the floor is spending: a human's
|
|
94
|
+
* attention, once per read, plus the wait the agent spends before it is refused.
|
|
95
|
+
* On 2026-09-06/07 a floor tripped and a session that could not get an answer
|
|
96
|
+
* could not read a file either, which is the state this removes.
|
|
97
|
+
*
|
|
98
|
+
* Two edges, both narrow. A MIXED tool call is routed whole, as one question,
|
|
99
|
+
* because the side-effecting half of it is exactly what the floor is for; its
|
|
100
|
+
* read classes are neither counted nor separately raised, so the approver sees
|
|
101
|
+
* one prompt for the command's effects and none for its looking. And the
|
|
102
|
+
* exemption is about ROUTING alone: a read still clears nothing, so a session
|
|
103
|
+
* cannot read its way out from under a floor.
|
|
104
|
+
*
|
|
105
|
+
* This module states the fact; the two surfaces that apply it are the harness
|
|
106
|
+
* adapter's verdict (`cli/hook.ts`) and the write boundary that re-checks it
|
|
107
|
+
* (`core/gate.ts`'s `startHarnessExecution`), and both use
|
|
108
|
+
* {@link isSideEffectingClass} so neither can drift from the other.
|
|
109
|
+
*/
|
|
110
|
+
import { payloadOf } from "./state.js";
|
|
111
|
+
/**
|
|
112
|
+
* Consecutive failures that force a task to manual (SPEC.md §10.2). Three, and
|
|
113
|
+
* the number is spelled here once so the gate, the executor, and the CLI cannot
|
|
114
|
+
* hold three opinions about it.
|
|
115
|
+
*/
|
|
116
|
+
export const LOOP_ESCALATION_THRESHOLD = 3;
|
|
117
|
+
/**
|
|
118
|
+
* Does an action in this class have a side effect the loop rule is about?
|
|
119
|
+
* (APRV-280, amended SPEC.md §10.2.)
|
|
120
|
+
*
|
|
121
|
+
* THE PREDICATE, exactly: a class is side-effecting unless it is `read` itself
|
|
122
|
+
* or sits under the `read.` namespace. Everything else — `files.write.*`,
|
|
123
|
+
* `files.delete.*`, `vcs.*`, `deps.*`, `network.*`, `communicate.*`,
|
|
124
|
+
* `policy.*`, `log.*`, a routed `policy.edit.*`, and any class this build has
|
|
125
|
+
* never heard of — is side-effecting. The unknown falls on the strict side by
|
|
126
|
+
* construction, which is the whole reason the predicate is written as a
|
|
127
|
+
* carve-OUT of `read.*` rather than as a list of the namespaces that act.
|
|
128
|
+
*
|
|
129
|
+
* `core/command-class.ts` already reads `read.*` this way when it decides which
|
|
130
|
+
* command substitutions may run unattended, and this is deliberately the same
|
|
131
|
+
* sentence: one reading of "this command only looks at things", used by the
|
|
132
|
+
* classifier and by loop safety alike.
|
|
133
|
+
*/
|
|
134
|
+
export function isSideEffectingClass(cls) {
|
|
135
|
+
return !(cls === "read" || cls.startsWith("read."));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The class the RUNTIME recorded for each action key, from the
|
|
139
|
+
* `execution.started` it wrote.
|
|
140
|
+
*
|
|
141
|
+
* A key with no start, or a start whose payload carries no `class` string, maps
|
|
142
|
+
* to `null`, and every caller reads `null` as side-effecting. The map is built
|
|
143
|
+
* in one forward pass and later starts overwrite earlier ones, which cannot
|
|
144
|
+
* happen for a single-use key and is the harmless reading if it ever does.
|
|
145
|
+
*/
|
|
146
|
+
function classByActionKey(records) {
|
|
147
|
+
const classes = new Map();
|
|
148
|
+
for (const record of records) {
|
|
149
|
+
if (record.event !== "execution.started")
|
|
150
|
+
continue;
|
|
151
|
+
const key = record.action_key;
|
|
152
|
+
if (typeof key !== "string" || key.length === 0)
|
|
153
|
+
continue;
|
|
154
|
+
const cls = payloadOf(record)["class"];
|
|
155
|
+
if (typeof cls === "string" && cls.length > 0)
|
|
156
|
+
classes.set(key, cls);
|
|
157
|
+
}
|
|
158
|
+
return classes;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Does this outcome record belong to a class the streak counts?
|
|
162
|
+
*
|
|
163
|
+
* Fail closed twice over: an outcome whose key names no start, and a start that
|
|
164
|
+
* recorded no class, both answer `true`.
|
|
165
|
+
*/
|
|
166
|
+
function outcomeIsSideEffecting(record, classes) {
|
|
167
|
+
const key = record.action_key;
|
|
168
|
+
if (typeof key !== "string" || key.length === 0)
|
|
169
|
+
return true;
|
|
170
|
+
const cls = classes.get(key);
|
|
171
|
+
return cls === undefined ? true : isSideEffectingClass(cls);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Loop state for every task that has recorded an execution outcome.
|
|
175
|
+
*
|
|
176
|
+
* Returned sorted by task id so the projection is byte-stable: two runs over
|
|
177
|
+
* the same log produce the same list in the same order, which is what lets
|
|
178
|
+
* `approval status --json` be pinned by a `deepEqual` test.
|
|
179
|
+
*
|
|
180
|
+
* Tasks with side-effecting executions but no failures are included with
|
|
181
|
+
* `consecutiveFailures: 0` — a caller rendering health wants to know the task
|
|
182
|
+
* was seen and is clean, and filtering is the caller's business, not this
|
|
183
|
+
* function's.
|
|
184
|
+
*
|
|
185
|
+
* APRV-280: outcomes of `read.*` actions are skipped entirely, so a task whose
|
|
186
|
+
* every execution was a read appears here not at all. That is the transparency
|
|
187
|
+
* the amended §10.2 asks for, read in both directions: a failed read accrues
|
|
188
|
+
* nothing, and a completed read clears nothing either.
|
|
189
|
+
*/
|
|
190
|
+
export function loopEscalation(records) {
|
|
191
|
+
const states = new Map();
|
|
192
|
+
const classes = classByActionKey(records);
|
|
193
|
+
const stateFor = (task) => {
|
|
194
|
+
const existing = states.get(task);
|
|
195
|
+
if (existing !== undefined)
|
|
196
|
+
return existing;
|
|
197
|
+
const created = {
|
|
198
|
+
task,
|
|
199
|
+
consecutiveFailures: 0,
|
|
200
|
+
escalated: false,
|
|
201
|
+
streakStartSeq: null,
|
|
202
|
+
lastFailureSeq: null,
|
|
203
|
+
};
|
|
204
|
+
states.set(task, created);
|
|
205
|
+
return created;
|
|
206
|
+
};
|
|
207
|
+
for (const record of records) {
|
|
208
|
+
const task = record.task;
|
|
209
|
+
if (typeof task !== "string" || task.length === 0)
|
|
210
|
+
continue;
|
|
211
|
+
if (record.event !== "execution.failed" && record.event !== "execution.completed")
|
|
212
|
+
continue;
|
|
213
|
+
// APRV-280. Checked before the counter moves and before the task is even
|
|
214
|
+
// registered: a read is transparent, not a zero.
|
|
215
|
+
if (!outcomeIsSideEffecting(record, classes))
|
|
216
|
+
continue;
|
|
217
|
+
if (record.event === "execution.failed") {
|
|
218
|
+
const state = stateFor(task);
|
|
219
|
+
state.consecutiveFailures += 1;
|
|
220
|
+
state.escalated = state.consecutiveFailures >= LOOP_ESCALATION_THRESHOLD;
|
|
221
|
+
if (state.streakStartSeq === null)
|
|
222
|
+
state.streakStartSeq = record.seq;
|
|
223
|
+
state.lastFailureSeq = record.seq;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (record.event === "execution.completed") {
|
|
227
|
+
const state = stateFor(task);
|
|
228
|
+
state.consecutiveFailures = 0;
|
|
229
|
+
state.escalated = false;
|
|
230
|
+
state.streakStartSeq = null;
|
|
231
|
+
state.lastFailureSeq = null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return [...states.values()].sort((a, b) => (a.task < b.task ? -1 : a.task > b.task ? 1 : 0));
|
|
235
|
+
}
|
|
236
|
+
/** Is `task` escalated to manual by loop safety right now? */
|
|
237
|
+
export function isLoopEscalated(records, task) {
|
|
238
|
+
for (const state of loopEscalation(records)) {
|
|
239
|
+
if (state.task === task)
|
|
240
|
+
return state.escalated;
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
// The harness scopes (APRV-145, amended SPEC.md §10.2)
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
/** The prefix every harness adapter task id carries (`src/cli/hook.ts`). */
|
|
248
|
+
export const HARNESS_TASK_PREFIX = "hook:";
|
|
249
|
+
/**
|
|
250
|
+
* The bucket every unreadable session identifier lands in.
|
|
251
|
+
*
|
|
252
|
+
* ONE shared bucket, not a fresh one per unreadable id, and the difference is
|
|
253
|
+
* the whole rule: absence must accrue FASTER and never slower. `parseHookInput`
|
|
254
|
+
* already substitutes this literal for an absent `session_id`, so the two halves
|
|
255
|
+
* of the runtime spell it the same way.
|
|
256
|
+
*/
|
|
257
|
+
export const UNKNOWN_SESSION = "unknown-session";
|
|
258
|
+
/**
|
|
259
|
+
* The session scope key of a harness task id, or `null` for a task no harness
|
|
260
|
+
* adapter minted.
|
|
261
|
+
*
|
|
262
|
+
* DERIVED, never declared. The id is `hook:<session>:<tool-use id>` and this
|
|
263
|
+
* reads its middle segment back out; nothing here reads a scope an agent named.
|
|
264
|
+
* A `hook:` task that does not split into exactly three colon-separated parts is
|
|
265
|
+
* an id this runtime cannot read, so it lands in {@link UNKNOWN_SESSION} with
|
|
266
|
+
* every other unreadable one.
|
|
267
|
+
*/
|
|
268
|
+
export function harnessSessionOf(task) {
|
|
269
|
+
if (!task.startsWith(HARNESS_TASK_PREFIX))
|
|
270
|
+
return null;
|
|
271
|
+
const parts = task.split(":");
|
|
272
|
+
// APRV-311: Codex native ids may themselves contain colons, so the adapter
|
|
273
|
+
// writes fixed-width digests as `hook:codex:<session-digest>:<call-digest>`.
|
|
274
|
+
// Preserve the session digest as the loop bucket. This arm is deliberately
|
|
275
|
+
// exact; malformed Codex-shaped tasks fall through to the legacy unknown
|
|
276
|
+
// bucket rather than selecting a scope from attacker-authored fragments.
|
|
277
|
+
if (parts.length === 4 &&
|
|
278
|
+
parts[1] === "codex" &&
|
|
279
|
+
/^[a-f0-9]{64}$/u.test(parts[2] ?? "") &&
|
|
280
|
+
/^[a-f0-9]{64}$/u.test(parts[3] ?? "")) {
|
|
281
|
+
return `${HARNESS_TASK_PREFIX}codex:${parts[2]}`;
|
|
282
|
+
}
|
|
283
|
+
if (parts.length !== 3)
|
|
284
|
+
return `${HARNESS_TASK_PREFIX}${UNKNOWN_SESSION}`;
|
|
285
|
+
const session = parts[1];
|
|
286
|
+
if (session === undefined || session.length === 0) {
|
|
287
|
+
return `${HARNESS_TASK_PREFIX}${UNKNOWN_SESSION}`;
|
|
288
|
+
}
|
|
289
|
+
return `${HARNESS_TASK_PREFIX}${session}`;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Fold every harness task in the log to at most one outcome.
|
|
293
|
+
*
|
|
294
|
+
* THE UNIT IS THE TOOL CALL. One tool call is one task id and may declare
|
|
295
|
+
* several classes, each with its own action key and its own outcome record;
|
|
296
|
+
* counting events would let a three-class command trip the threshold on a single
|
|
297
|
+
* failure. So a task folds first: any `execution.failed` under it makes it a
|
|
298
|
+
* failed tool call, and only a task whose outcomes are all completions counts as
|
|
299
|
+
* a completed one. A task whose classes disagree is a FAILURE, because ambiguity
|
|
300
|
+
* resolves stricter.
|
|
301
|
+
*
|
|
302
|
+
* The outcome is placed at the seq of the task's LAST outcome record, so
|
|
303
|
+
* interleaved sessions and a late-arriving counterpart order deterministically
|
|
304
|
+
* in log order. Never by timestamp.
|
|
305
|
+
*
|
|
306
|
+
* APRV-280 subtracts the reads BEFORE the fold: an outcome whose class is
|
|
307
|
+
* `read.*` is not part of the tool call as loop safety sees it, so a tool call
|
|
308
|
+
* that declared nothing else produces no outcome here at all and is transparent
|
|
309
|
+
* to every streak. A mixed command still folds strictly — its side-effecting
|
|
310
|
+
* halves decide it — because the reads are simply not in the fold.
|
|
311
|
+
*/
|
|
312
|
+
function toolCallOutcomes(records) {
|
|
313
|
+
const byTask = new Map();
|
|
314
|
+
const classes = classByActionKey(records);
|
|
315
|
+
for (const record of records) {
|
|
316
|
+
if (record.event !== "execution.failed" && record.event !== "execution.completed")
|
|
317
|
+
continue;
|
|
318
|
+
const task = record.task;
|
|
319
|
+
if (typeof task !== "string" || task.length === 0)
|
|
320
|
+
continue;
|
|
321
|
+
const session = harnessSessionOf(task);
|
|
322
|
+
if (session === null)
|
|
323
|
+
continue;
|
|
324
|
+
if (!outcomeIsSideEffecting(record, classes))
|
|
325
|
+
continue;
|
|
326
|
+
const existing = byTask.get(task);
|
|
327
|
+
const failed = record.event === "execution.failed";
|
|
328
|
+
if (existing === undefined) {
|
|
329
|
+
byTask.set(task, { session, actor: record.actor, failed, seq: record.seq });
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
existing.actor = record.actor;
|
|
333
|
+
existing.seq = record.seq;
|
|
334
|
+
// Sticky: one failure anywhere under the task makes the tool call a failure,
|
|
335
|
+
// whatever its other classes reported.
|
|
336
|
+
existing.failed = existing.failed || failed;
|
|
337
|
+
}
|
|
338
|
+
return [...byTask.values()].sort((a, b) => a.seq - b.seq);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Loop state for every harness session and every harness actor the log has seen
|
|
342
|
+
* an outcome for.
|
|
343
|
+
*
|
|
344
|
+
* Sorted by scope then key so the projection is byte-stable, exactly as
|
|
345
|
+
* {@link loopEscalation} is, which is what lets `approval status --json` be
|
|
346
|
+
* pinned by a `deepEqual` test.
|
|
347
|
+
*
|
|
348
|
+
* What resets a streak is unchanged and deliberately not widened: only an
|
|
349
|
+
* `execution.completed` in the same scope, of a SIDE-EFFECTING class since
|
|
350
|
+
* APRV-280. A hook timeout, a deny, a withdrawn request, a granted approval, a
|
|
351
|
+
* fresh tool call, a successful `grep`, a restarted process and elapsed time all
|
|
352
|
+
* leave the streak where they found it. Silence is not evidence of recovery, and
|
|
353
|
+
* neither is a command that did nothing.
|
|
354
|
+
*/
|
|
355
|
+
export function harnessLoopEscalation(records) {
|
|
356
|
+
const states = new Map();
|
|
357
|
+
const stateFor = (scope, key) => {
|
|
358
|
+
const id = `${scope}${key}`;
|
|
359
|
+
const existing = states.get(id);
|
|
360
|
+
if (existing !== undefined)
|
|
361
|
+
return existing;
|
|
362
|
+
const created = {
|
|
363
|
+
scope,
|
|
364
|
+
key,
|
|
365
|
+
consecutiveFailures: 0,
|
|
366
|
+
escalated: false,
|
|
367
|
+
streakStartSeq: null,
|
|
368
|
+
lastFailureSeq: null,
|
|
369
|
+
};
|
|
370
|
+
states.set(id, created);
|
|
371
|
+
return created;
|
|
372
|
+
};
|
|
373
|
+
for (const call of toolCallOutcomes(records)) {
|
|
374
|
+
for (const state of [stateFor("session", call.session), stateFor("actor", call.actor)]) {
|
|
375
|
+
if (call.failed) {
|
|
376
|
+
state.consecutiveFailures += 1;
|
|
377
|
+
state.escalated = state.consecutiveFailures >= LOOP_ESCALATION_THRESHOLD;
|
|
378
|
+
if (state.streakStartSeq === null)
|
|
379
|
+
state.streakStartSeq = call.seq;
|
|
380
|
+
state.lastFailureSeq = call.seq;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
state.consecutiveFailures = 0;
|
|
384
|
+
state.escalated = false;
|
|
385
|
+
state.streakStartSeq = null;
|
|
386
|
+
state.lastFailureSeq = null;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return [...states.values()].sort((a, b) => {
|
|
390
|
+
const left = `${a.scope}${a.key}`;
|
|
391
|
+
const right = `${b.scope}${b.key}`;
|
|
392
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* The harness scope that escalated this tool call, or `null` for a command no
|
|
397
|
+
* streak has floored.
|
|
398
|
+
*
|
|
399
|
+
* EITHER scope escalates (amended SPEC.md §10.2). The session is the smallest
|
|
400
|
+
* scope a runaway actually runs away in; the actor is the backstop, because the
|
|
401
|
+
* session id is authored by the party under oversight and a scope it can rotate
|
|
402
|
+
* is a streak it can shed. The session is reported in preference to the actor
|
|
403
|
+
* where both are tripped, because it is the narrower fact and names the run an
|
|
404
|
+
* operator has to go and look at.
|
|
405
|
+
*/
|
|
406
|
+
export function harnessLoopFloor(records, task, actor) {
|
|
407
|
+
const session = harnessSessionOf(task);
|
|
408
|
+
const states = harnessLoopEscalation(records);
|
|
409
|
+
const bySession = session === null
|
|
410
|
+
? undefined
|
|
411
|
+
: states.find((state) => state.scope === "session" && state.key === session);
|
|
412
|
+
if (bySession?.escalated === true)
|
|
413
|
+
return bySession;
|
|
414
|
+
const byActor = states.find((state) => state.scope === "actor" && state.key === actor);
|
|
415
|
+
return byActor?.escalated === true ? byActor : null;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* What clears this streak, in one sentence, for the surface that has to say so
|
|
419
|
+
* (APRV-280).
|
|
420
|
+
*
|
|
421
|
+
* Written here rather than at each call site because three surfaces print it —
|
|
422
|
+
* the gate's `loop-escalated` refusals, the hook's denies, and `approval
|
|
423
|
+
* status` — and three copies of a sentence about how to get out of a floor are
|
|
424
|
+
* three chances to tell an operator something that is not true. Everything in
|
|
425
|
+
* it is a fact of this module: a completion of a SIDE-EFFECTING class in the
|
|
426
|
+
* same scope, and nothing else, resets the counter.
|
|
427
|
+
*
|
|
428
|
+
* The gate window is named for the harness scopes only, because that is the
|
|
429
|
+
* surface it reaches: an open window routes every gated tool call through the
|
|
430
|
+
* bypass path before the floor is ever consulted (SPEC.md §5.2, APRV-214). It is
|
|
431
|
+
* named as the human's ceremony, which is what it is — it needs a terminal and a
|
|
432
|
+
* typed `understood`, and an agent may not run it.
|
|
433
|
+
*
|
|
434
|
+
* The harness sentence also states the routing exemption of APRV-297, and states
|
|
435
|
+
* it here for the same reason the clearance is here: the operator reading it in
|
|
436
|
+
* `approval status` and the agent reading it in a deny need the same account of
|
|
437
|
+
* what a floor does and does not reach, and two copies would eventually give two.
|
|
438
|
+
*/
|
|
439
|
+
export function loopClearance(scope, key) {
|
|
440
|
+
if (scope === "task") {
|
|
441
|
+
return `an execution.completed for task ${key} in a class that has side effects clears it; a read that succeeds clears nothing (amended SPEC.md §10.2)`;
|
|
442
|
+
}
|
|
443
|
+
return `one side-effecting tool call completing in this ${scope} scope (${key}) clears it — a human granting any request this floor routes to them, and the command then running, is that completion — or a human opening the gate window (\`approval gate open\`, the human's own ceremony), which bypasses the floor entirely. read.* commands are outside this floor in both directions (amended SPEC.md §10.2): the floor does not route them to a human, so reading and searching keep working while it stands, and a read that succeeds clears nothing.`;
|
|
444
|
+
}
|
|
445
|
+
/** Is this harness tool call floored to manual by either scope right now? */
|
|
446
|
+
export function isHarnessLoopEscalated(records, task, actor) {
|
|
447
|
+
return harnessLoopFloor(records, task, actor) !== null;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Coverage of the completion counterpart, for `approval status`.
|
|
451
|
+
*
|
|
452
|
+
* INFORMATIONAL. It moves no health verdict and no exit code, for the reason
|
|
453
|
+
* §8's timestamp anomalies move neither: it is a coverage measurement rather
|
|
454
|
+
* than an integrity verdict, and a control an operator learns to silence is
|
|
455
|
+
* worse than one that reports beside the verdict. A persistently high
|
|
456
|
+
* `unreported` is how an operator learns the post-execution hook is not
|
|
457
|
+
* installed or not firing.
|
|
458
|
+
*/
|
|
459
|
+
export function harnessOutcomeCoverage(records) {
|
|
460
|
+
/** Action keys whose latest `execution.started` carried the harness marker. */
|
|
461
|
+
const open = new Set();
|
|
462
|
+
let started = 0;
|
|
463
|
+
let reported = 0;
|
|
464
|
+
for (const record of records) {
|
|
465
|
+
const key = record.action_key;
|
|
466
|
+
if (typeof key !== "string" || key.length === 0)
|
|
467
|
+
continue;
|
|
468
|
+
if (record.event === "execution.started") {
|
|
469
|
+
if (payloadOf(record)["execution"] === "harness") {
|
|
470
|
+
started += 1;
|
|
471
|
+
open.add(key);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
open.delete(key);
|
|
475
|
+
}
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
if (record.event === "execution.completed" ||
|
|
479
|
+
record.event === "execution.failed" ||
|
|
480
|
+
record.event === "execution.indeterminate") {
|
|
481
|
+
if (open.delete(key))
|
|
482
|
+
reported += 1;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return { started, reported, unreported: started - reported };
|
|
486
|
+
}
|
|
487
|
+
//# sourceMappingURL=loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../../src/core/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommonMark fenced-block scanning, as a leaf module.
|
|
3
|
+
*
|
|
4
|
+
* `APPROVAL.md` is prose for humans plus fenced blocks for machines: exactly
|
|
5
|
+
* one ` ```yaml approval-policy ` block (SPEC.md §5) and at most one optional
|
|
6
|
+
* ` ```yaml approval-values ` block (SPEC.md §5.3). Two readers, two info
|
|
7
|
+
* strings, one question: which fenced blocks in this markdown carry that label,
|
|
8
|
+
* and was one of them left open at end of file.
|
|
9
|
+
*
|
|
10
|
+
* This module answers that question and nothing else. It was lifted out of
|
|
11
|
+
* `policy-load.ts` unchanged (APRV-238) so the values reader could ask it too
|
|
12
|
+
* without importing the policy loader, which is the module a values reader must
|
|
13
|
+
* stay clear of (SPEC.md §11.1 invariant 10, `tests/values-inert.test.ts`). The
|
|
14
|
+
* splitter is the one place allowed to know both info strings, because knowing
|
|
15
|
+
* a label is not reading a block: what it returns is text, and what a caller
|
|
16
|
+
* does with the text is the caller's whole subject.
|
|
17
|
+
*
|
|
18
|
+
* Pure function of the markdown and the info string. No filesystem, no clock,
|
|
19
|
+
* no schema, no YAML.
|
|
20
|
+
*/
|
|
21
|
+
/** The blocks a scan found, and whether one was left open at end of file. */
|
|
22
|
+
export interface FenceScan {
|
|
23
|
+
/** Bodies of every block whose info string matched, in document order. */
|
|
24
|
+
blocks: string[];
|
|
25
|
+
/** True when a MATCHING fence was opened and never closed before EOF. */
|
|
26
|
+
unterminated: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Scan CommonMark fenced code blocks and collect the bodies of those whose info
|
|
30
|
+
* string is `infoString` (compared after {@link normaliseInfoString}).
|
|
31
|
+
*
|
|
32
|
+
* CommonMark rules honoured, because they decide what is and is not a fence:
|
|
33
|
+
* an opening fence is 3+ backticks indented at most 3 spaces; its info string
|
|
34
|
+
* may not contain a backtick; the closing fence is at least as long as the
|
|
35
|
+
* opener and carries nothing but whitespace. Every non-matching fenced block
|
|
36
|
+
* (```js, ```yaml, …) is still scanned as a block, so text *inside* it can
|
|
37
|
+
* never be mistaken for a matching fence. Everything outside a fence — including
|
|
38
|
+
* yaml-looking prose and 4-space-indented code blocks, which are not fences —
|
|
39
|
+
* is ignored entirely.
|
|
40
|
+
*/
|
|
41
|
+
export declare function scanFences(markdown: string, infoString: string): FenceScan;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommonMark fenced-block scanning, as a leaf module.
|
|
3
|
+
*
|
|
4
|
+
* `APPROVAL.md` is prose for humans plus fenced blocks for machines: exactly
|
|
5
|
+
* one ` ```yaml approval-policy ` block (SPEC.md §5) and at most one optional
|
|
6
|
+
* ` ```yaml approval-values ` block (SPEC.md §5.3). Two readers, two info
|
|
7
|
+
* strings, one question: which fenced blocks in this markdown carry that label,
|
|
8
|
+
* and was one of them left open at end of file.
|
|
9
|
+
*
|
|
10
|
+
* This module answers that question and nothing else. It was lifted out of
|
|
11
|
+
* `policy-load.ts` unchanged (APRV-238) so the values reader could ask it too
|
|
12
|
+
* without importing the policy loader, which is the module a values reader must
|
|
13
|
+
* stay clear of (SPEC.md §11.1 invariant 10, `tests/values-inert.test.ts`). The
|
|
14
|
+
* splitter is the one place allowed to know both info strings, because knowing
|
|
15
|
+
* a label is not reading a block: what it returns is text, and what a caller
|
|
16
|
+
* does with the text is the caller's whole subject.
|
|
17
|
+
*
|
|
18
|
+
* Pure function of the markdown and the info string. No filesystem, no clock,
|
|
19
|
+
* no schema, no YAML.
|
|
20
|
+
*/
|
|
21
|
+
/** Normalise a fence info string: trim ends, collapse internal whitespace. */
|
|
22
|
+
function normaliseInfoString(info) {
|
|
23
|
+
return info.trim().replace(/\s+/gu, " ");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Scan CommonMark fenced code blocks and collect the bodies of those whose info
|
|
27
|
+
* string is `infoString` (compared after {@link normaliseInfoString}).
|
|
28
|
+
*
|
|
29
|
+
* CommonMark rules honoured, because they decide what is and is not a fence:
|
|
30
|
+
* an opening fence is 3+ backticks indented at most 3 spaces; its info string
|
|
31
|
+
* may not contain a backtick; the closing fence is at least as long as the
|
|
32
|
+
* opener and carries nothing but whitespace. Every non-matching fenced block
|
|
33
|
+
* (```js, ```yaml, …) is still scanned as a block, so text *inside* it can
|
|
34
|
+
* never be mistaken for a matching fence. Everything outside a fence — including
|
|
35
|
+
* yaml-looking prose and 4-space-indented code blocks, which are not fences —
|
|
36
|
+
* is ignored entirely.
|
|
37
|
+
*/
|
|
38
|
+
export function scanFences(markdown, infoString) {
|
|
39
|
+
const wanted = normaliseInfoString(infoString);
|
|
40
|
+
const lines = markdown.split(/\r\n|\n|\r/u);
|
|
41
|
+
const blocks = [];
|
|
42
|
+
let openLength = 0;
|
|
43
|
+
let openMatches = false;
|
|
44
|
+
let body = [];
|
|
45
|
+
let inFence = false;
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
if (!inFence) {
|
|
48
|
+
const open = /^ {0,3}(`{3,})(.*)$/u.exec(line);
|
|
49
|
+
if (open === null)
|
|
50
|
+
continue;
|
|
51
|
+
const info = open[2] ?? "";
|
|
52
|
+
// CommonMark: a backtick fence's info string may not contain a backtick.
|
|
53
|
+
if (info.includes("`"))
|
|
54
|
+
continue;
|
|
55
|
+
inFence = true;
|
|
56
|
+
openLength = (open[1] ?? "").length;
|
|
57
|
+
openMatches = normaliseInfoString(info) === wanted;
|
|
58
|
+
body = [];
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const close = /^ {0,3}(`{3,})[ \t]*$/u.exec(line);
|
|
62
|
+
if (close !== null && (close[1] ?? "").length >= openLength) {
|
|
63
|
+
if (openMatches)
|
|
64
|
+
blocks.push(body.join("\n"));
|
|
65
|
+
inFence = false;
|
|
66
|
+
openMatches = false;
|
|
67
|
+
body = [];
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
body.push(line);
|
|
71
|
+
}
|
|
72
|
+
return { blocks, unterminated: inFence && openMatches };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=md-fence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md-fence.js","sourceRoot":"","sources":["../../../src/core/md-fence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAUH,8EAA8E;AAC9E,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,UAAkB;IAC7D,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,IAAI,GAAa,EAAE,CAAC;IACxB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,IAAI,KAAK,IAAI;gBAAE,SAAS;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3B,yEAAyE;YACzE,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,SAAS;YACjC,OAAO,GAAG,IAAI,CAAC;YACf,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACpC,WAAW,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC;YACnD,IAAI,GAAG,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;YAC5D,IAAI,WAAW;gBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9C,OAAO,GAAG,KAAK,CAAC;YAChB,WAAW,GAAG,KAAK,CAAC;YACpB,IAAI,GAAG,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,CAAC;AAC1D,CAAC"}
|