approval-md 0.1.0 → 0.3.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/README.md +629 -559
- package/SPEC.md +99 -24
- package/dist/src/adapters/agentmail.d.ts +426 -0
- package/dist/src/adapters/agentmail.js +2 -2
- package/dist/src/adapters/conformance.d.ts +149 -0
- package/dist/src/adapters/contract.d.ts +628 -0
- package/dist/src/adapters/contract.js +110 -16
- package/dist/src/adapters/contract.js.map +1 -1
- package/dist/src/adapters/email.d.ts +324 -0
- package/dist/src/adapters/env-passphrase.d.ts +93 -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 +2 -1
- package/dist/src/adapters/registry.js.map +1 -1
- package/dist/src/adapters/smtp.d.ts +213 -0
- package/dist/src/adapters/vault-provider.d.ts +114 -0
- package/dist/src/adapters/vault-provider.js +3 -3
- 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/cli.d.ts +193 -0
- package/dist/src/channels/conformance.d.ts +92 -0
- package/dist/src/channels/contract.d.ts +656 -0
- package/dist/src/channels/contract.js +200 -7
- package/dist/src/channels/contract.js.map +1 -1
- package/dist/src/channels/payload-view.d.ts +35 -0
- package/dist/src/channels/render-queue.d.ts +149 -0
- package/dist/src/channels/tagging.d.ts +196 -0
- package/dist/src/channels/telegram.d.ts +1944 -0
- package/dist/src/channels/telegram.js +218 -23
- package/dist/src/channels/telegram.js.map +1 -1
- package/dist/src/channels/web.d.ts +350 -0
- package/dist/src/channels/web.js +17 -0
- package/dist/src/channels/web.js.map +1 -1
- package/dist/src/cli/adapter.d.ts +90 -0
- package/dist/src/cli/adapter.js +25 -15
- package/dist/src/cli/adapter.js.map +1 -1
- package/dist/src/cli/amend.d.ts +59 -0
- package/dist/src/cli/amend.js +214 -30
- package/dist/src/cli/amend.js.map +1 -1
- package/dist/src/cli/args.d.ts +43 -0
- package/dist/src/cli/attest.d.ts +50 -0
- package/dist/src/cli/attest.js +134 -7
- package/dist/src/cli/attest.js.map +1 -1
- package/dist/src/cli/audit-card.d.ts +62 -0
- package/dist/src/cli/audit.d.ts +59 -0
- package/dist/src/cli/channel-telegram.d.ts +879 -0
- package/dist/src/cli/channel-telegram.js +311 -13
- package/dist/src/cli/channel-telegram.js.map +1 -1
- package/dist/src/cli/channel-web.d.ts +131 -0
- package/dist/src/cli/channel.d.ts +80 -0
- package/dist/src/cli/channel.js +9 -0
- package/dist/src/cli/channel.js.map +1 -1
- package/dist/src/cli/checkpoint-tap.d.ts +169 -0
- package/dist/src/cli/codex-bridge.d.ts +819 -0
- package/dist/src/cli/codex-bridge.js +1607 -0
- package/dist/src/cli/codex-bridge.js.map +1 -0
- package/dist/src/cli/codex.d.ts +2 -0
- package/dist/src/cli/codex.js +469 -0
- package/dist/src/cli/codex.js.map +1 -0
- package/dist/src/cli/coverage.d.ts +61 -0
- package/dist/src/cli/daemon.d.ts +120 -0
- package/dist/src/cli/daemon.js +4 -1
- package/dist/src/cli/daemon.js.map +1 -1
- package/dist/src/cli/doctor.d.ts +129 -0
- package/dist/src/cli/doctor.js +586 -17
- package/dist/src/cli/doctor.js.map +1 -1
- package/dist/src/cli/env.d.ts +65 -0
- package/dist/src/cli/execute.d.ts +202 -0
- package/dist/src/cli/execute.js +25 -2
- package/dist/src/cli/execute.js.map +1 -1
- package/dist/src/cli/exit-codes.d.ts +73 -0
- package/dist/src/cli/feedback.d.ts +60 -0
- package/dist/src/cli/gate-window.d.ts +40 -0
- package/dist/src/cli/gate.d.ts +68 -0
- package/dist/src/cli/git-scope.d.ts +190 -0
- package/dist/src/cli/gloss-attach.d.ts +85 -0
- package/dist/src/cli/gloss-codex-child.d.ts +9 -0
- package/dist/src/cli/gloss-codex.d.ts +24 -0
- package/dist/src/cli/gloss-options.d.ts +42 -0
- package/dist/src/cli/gloss.d.ts +265 -0
- package/dist/src/cli/help.d.ts +107 -0
- package/dist/src/cli/help.js +320 -93
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/hook-codex.d.ts +126 -0
- package/dist/src/cli/hook-codex.js +226 -0
- package/dist/src/cli/hook-codex.js.map +1 -0
- package/dist/src/cli/hook.d.ts +787 -0
- package/dist/src/cli/hook.js +1235 -181
- package/dist/src/cli/hook.js.map +1 -1
- package/dist/src/cli/import.d.ts +35 -0
- package/dist/src/cli/import.js +1 -1
- package/dist/src/cli/import.js.map +1 -1
- package/dist/src/cli/init.d.ts +84 -0
- package/dist/src/cli/init.js +2 -2
- package/dist/src/cli/init.js.map +1 -1
- package/dist/src/cli/instructions.d.ts +23 -0
- package/dist/src/cli/journal.d.ts +41 -0
- package/dist/src/cli/log-advance.d.ts +287 -0
- package/dist/src/cli/log-advance.js +102 -11
- package/dist/src/cli/log-advance.js.map +1 -1
- package/dist/src/cli/log-anchor.d.ts +176 -0
- package/dist/src/cli/log-checkpoint.d.ts +22 -0
- package/dist/src/cli/log-sync.d.ts +243 -0
- package/dist/src/cli/log-verbs.d.ts +16 -0
- package/dist/src/cli/log-verbs.js +7 -1
- package/dist/src/cli/log-verbs.js.map +1 -1
- package/dist/src/cli/long-help.d.ts +70 -0
- package/dist/src/cli/main.d.ts +77 -0
- package/dist/src/cli/main.js +159 -7
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/mcp.d.ts +52 -0
- package/dist/src/cli/paths.d.ts +56 -0
- package/dist/src/cli/payload.d.ts +58 -0
- package/dist/src/cli/policy-apply.d.ts +195 -0
- package/dist/src/cli/policy-apply.js +573 -0
- package/dist/src/cli/policy-apply.js.map +1 -0
- package/dist/src/cli/policy.d.ts +43 -0
- package/dist/src/cli/policy.js +14 -1
- package/dist/src/cli/policy.js.map +1 -1
- package/dist/src/cli/preflight.d.ts +501 -0
- package/dist/src/cli/preflight.js +689 -45
- package/dist/src/cli/preflight.js.map +1 -1
- package/dist/src/cli/progress.d.ts +78 -0
- package/dist/src/cli/prompt.d.ts +209 -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/render.d.ts +22 -0
- package/dist/src/cli/sandbox.d.ts +51 -0
- package/dist/src/cli/sandbox.js +17 -1
- package/dist/src/cli/sandbox.js.map +1 -1
- package/dist/src/cli/scaffold.d.ts +79 -0
- package/dist/src/cli/scaffold.js +1 -1
- package/dist/src/cli/setup-adapter.d.ts +137 -0
- package/dist/src/cli/setup-adapter.js +38 -4
- package/dist/src/cli/setup-adapter.js.map +1 -1
- package/dist/src/cli/setup-channel.d.ts +126 -0
- package/dist/src/cli/setup-channel.js +28 -1
- package/dist/src/cli/setup-channel.js.map +1 -1
- package/dist/src/cli/setup-checkpoint.d.ts +57 -0
- package/dist/src/cli/setup-common.d.ts +277 -0
- package/dist/src/cli/setup-common.js +3 -2
- package/dist/src/cli/setup-common.js.map +1 -1
- package/dist/src/cli/setup-flow.d.ts +287 -0
- package/dist/src/cli/setup-service.d.ts +96 -0
- package/dist/src/cli/setup.d.ts +204 -0
- package/dist/src/cli/setup.js +94 -2
- package/dist/src/cli/setup.js.map +1 -1
- package/dist/src/cli/style.d.ts +320 -0
- package/dist/src/cli/token.d.ts +39 -0
- package/dist/src/cli/up.d.ts +155 -0
- package/dist/src/cli/up.js +119 -53
- package/dist/src/cli/up.js.map +1 -1
- package/dist/src/cli/usage.d.ts +37 -0
- package/dist/src/cli/values.d.ts +40 -0
- package/dist/src/cli/values.js +3 -4
- package/dist/src/cli/values.js.map +1 -1
- package/dist/src/cli/vault.d.ts +59 -0
- package/dist/src/cli/vault.js +2 -2
- package/dist/src/cli/vault.js.map +1 -1
- package/dist/src/cli/verb-registry.d.ts +76 -0
- package/dist/src/cli/verb-registry.js +344 -11
- package/dist/src/cli/verb-registry.js.map +1 -1
- package/dist/src/cli/wordmark.d.ts +31 -0
- package/dist/src/cli/wordmark.js +2 -2
- package/dist/src/codex/broker.d.ts +229 -0
- package/dist/src/codex/broker.js +548 -0
- package/dist/src/codex/broker.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/runner.d.ts +178 -0
- package/dist/src/codex/runner.js +231 -0
- package/dist/src/codex/runner.js.map +1 -0
- package/dist/src/codex/serve.d.ts +56 -0
- package/dist/src/codex/serve.js +98 -0
- package/dist/src/codex/serve.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-commit.d.ts +219 -0
- package/dist/src/codex/workspace-commit.js +549 -0
- package/dist/src/codex/workspace-commit.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 +221 -0
- package/dist/src/core/advance-cycle.js +66 -2
- package/dist/src/core/advance-cycle.js.map +1 -1
- package/dist/src/core/agents-md.d.ts +278 -0
- package/dist/src/core/agents-md.js +33 -31
- package/dist/src/core/agents-md.js.map +1 -1
- 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 +635 -0
- package/dist/src/core/attest.js +326 -4
- package/dist/src/core/attest.js.map +1 -1
- package/dist/src/core/audit.d.ts +510 -0
- package/dist/src/core/audit.js +13 -0
- package/dist/src/core/audit.js.map +1 -1
- package/dist/src/core/budgets.d.ts +238 -0
- package/dist/src/core/channel-owner.d.ts +213 -0
- package/dist/src/core/channel-owner.js +358 -0
- package/dist/src/core/channel-owner.js.map +1 -0
- package/dist/src/core/checkpoint.d.ts +500 -0
- package/dist/src/core/child-env.d.ts +88 -0
- package/dist/src/core/clock.d.ts +52 -0
- package/dist/src/core/command-class.d.ts +697 -0
- package/dist/src/core/command-class.js +713 -25
- package/dist/src/core/command-class.js.map +1 -1
- package/dist/src/core/commit-guard.d.ts +272 -0
- package/dist/src/core/commit-guard.js +424 -0
- package/dist/src/core/commit-guard.js.map +1 -0
- package/dist/src/core/coverage-sources/adapter.d.ts +40 -0
- package/dist/src/core/coverage-sources/gh.d.ts +48 -0
- package/dist/src/core/coverage-sources/git.d.ts +101 -0
- package/dist/src/core/coverage.d.ts +217 -0
- package/dist/src/core/credential-spec.d.ts +72 -0
- package/dist/src/core/daemon-actor.d.ts +45 -0
- package/dist/src/core/daemon-actor.js +54 -0
- package/dist/src/core/daemon-actor.js.map +1 -0
- package/dist/src/core/dark-session.d.ts +432 -0
- package/dist/src/core/dark-session.js +266 -82
- package/dist/src/core/dark-session.js.map +1 -1
- package/dist/src/core/decision-refusal.d.ts +206 -0
- package/dist/src/core/decision-refusal.js +24 -2
- package/dist/src/core/decision-refusal.js.map +1 -1
- package/dist/src/core/env-file.d.ts +455 -0
- package/dist/src/core/env-file.js +60 -1
- package/dist/src/core/env-file.js.map +1 -1
- package/dist/src/core/execute.d.ts +871 -0
- package/dist/src/core/execute.js +59 -8
- package/dist/src/core/execute.js.map +1 -1
- package/dist/src/core/frontmatter.d.ts +78 -0
- package/dist/src/core/gate-window.d.ts +312 -0
- package/dist/src/core/gate.d.ts +1449 -0
- package/dist/src/core/gate.js +149 -14
- package/dist/src/core/gate.js.map +1 -1
- package/dist/src/core/gesture-refusal.d.ts +166 -0
- package/dist/src/core/gesture-refusal.js +188 -0
- package/dist/src/core/gesture-refusal.js.map +1 -0
- package/dist/src/core/git-run.d.ts +73 -0
- package/dist/src/core/harness-version.d.ts +157 -0
- package/dist/src/core/harness-version.js +4 -1
- package/dist/src/core/harness-version.js.map +1 -1
- package/dist/src/core/harness-wait.d.ts +55 -0
- package/dist/src/core/head-retry.d.ts +107 -0
- package/dist/src/core/instance.d.ts +310 -0
- package/dist/src/core/instance.js +113 -0
- package/dist/src/core/instance.js.map +1 -1
- package/dist/src/core/intake-limits.d.ts +247 -0
- package/dist/src/core/jcs.d.ts +52 -0
- package/dist/src/core/journal.d.ts +144 -0
- package/dist/src/core/live-draw.d.ts +436 -0
- package/dist/src/core/log-reconcile.d.ts +89 -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 +316 -0
- package/dist/src/core/log.js.map +1 -1
- package/dist/src/core/loop.d.ts +274 -0
- package/dist/src/core/loop.js +11 -0
- package/dist/src/core/loop.js.map +1 -1
- package/dist/src/core/md-fence.d.ts +41 -0
- package/dist/src/core/money.d.ts +147 -0
- package/dist/src/core/payload-census.d.ts +74 -0
- package/dist/src/core/payload-store.d.ts +175 -0
- package/dist/src/core/payload.d.ts +71 -0
- package/dist/src/core/policy-diff.d.ts +292 -0
- package/dist/src/core/policy-diff.js +27 -4
- package/dist/src/core/policy-diff.js.map +1 -1
- package/dist/src/core/policy-expectations.d.ts +199 -0
- package/dist/src/core/policy-explain.d.ts +160 -0
- package/dist/src/core/policy-explain.js +63 -3
- package/dist/src/core/policy-explain.js.map +1 -1
- package/dist/src/core/policy-load.d.ts +567 -0
- package/dist/src/core/policy-load.js +36 -6
- package/dist/src/core/policy-load.js.map +1 -1
- package/dist/src/core/policy-match.d.ts +324 -0
- package/dist/src/core/policy-match.js +72 -9
- package/dist/src/core/policy-match.js.map +1 -1
- package/dist/src/core/policy-proposal.d.ts +317 -0
- package/dist/src/core/policy-proposal.js +102 -2
- package/dist/src/core/policy-proposal.js.map +1 -1
- package/dist/src/core/prompt-layout.d.ts +221 -0
- package/dist/src/core/protected-path-guard.d.ts +566 -0
- package/dist/src/core/protected-path-guard.js +848 -55
- package/dist/src/core/protected-path-guard.js.map +1 -1
- package/dist/src/core/question-preempted.d.ts +141 -0
- package/dist/src/core/question-preempted.js +152 -0
- package/dist/src/core/question-preempted.js.map +1 -0
- package/dist/src/core/read-scope.d.ts +172 -0
- package/dist/src/core/read-scope.js +252 -0
- package/dist/src/core/read-scope.js.map +1 -0
- package/dist/src/core/registration.d.ts +25 -0
- package/dist/src/core/reindex.d.ts +99 -0
- package/dist/src/core/sampler.d.ts +313 -0
- package/dist/src/core/sandbox.d.ts +371 -0
- package/dist/src/core/sandbox.js +190 -1
- package/dist/src/core/sandbox.js.map +1 -1
- package/dist/src/core/seal.d.ts +165 -0
- package/dist/src/core/sender-identity.d.ts +476 -0
- package/dist/src/core/sender-identity.js +572 -0
- package/dist/src/core/sender-identity.js.map +1 -0
- package/dist/src/core/shlex.d.ts +102 -0
- package/dist/src/core/shlex.js +159 -0
- package/dist/src/core/shlex.js.map +1 -0
- package/dist/src/core/state.d.ts +505 -0
- package/dist/src/core/task-file.d.ts +185 -0
- package/dist/src/core/telegram-config.d.ts +93 -0
- package/dist/src/core/token.d.ts +409 -0
- package/dist/src/core/token.js +21 -38
- package/dist/src/core/token.js.map +1 -1
- package/dist/src/core/validate.d.ts +138 -0
- package/dist/src/core/values.d.ts +147 -0
- package/dist/src/core/values.js +36 -1
- package/dist/src/core/values.js.map +1 -1
- package/dist/src/core/vault.d.ts +291 -0
- package/dist/src/core/verified-snapshot.d.ts +204 -0
- package/dist/src/core/verify.d.ts +336 -0
- package/dist/src/core/version.d.ts +8 -0
- package/dist/src/core/wysiwys.d.ts +370 -0
- package/dist/src/daemon/advance-child.d.ts +39 -0
- package/dist/src/daemon/advance.d.ts +476 -0
- package/dist/src/daemon/advance.js +25 -4
- package/dist/src/daemon/advance.js.map +1 -1
- package/dist/src/daemon/audit.d.ts +87 -0
- package/dist/src/daemon/daemon.d.ts +1180 -0
- package/dist/src/daemon/daemon.js +9 -0
- package/dist/src/daemon/daemon.js.map +1 -1
- package/dist/src/daemon/dark-session.d.ts +64 -0
- package/dist/src/daemon/draw-child.d.ts +36 -0
- package/dist/src/daemon/draw.d.ts +154 -0
- package/dist/src/daemon/git-evidence.d.ts +173 -0
- package/dist/src/daemon/git-evidence.js +1 -1
- package/dist/src/daemon/projection.d.ts +180 -0
- package/dist/src/daemon/prune.d.ts +207 -0
- package/dist/src/mcp/http.d.ts +113 -0
- package/dist/src/mcp/server.d.ts +265 -0
- package/dist/src/mcp/server.js +17 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/docs/adapter-api.md +106 -0
- package/docs/cli-reference.md +1316 -63
- package/docs/codex-enforced-session.md +103 -0
- package/docs/codex-workspace-broker.md +118 -0
- package/package.json +14 -2
- package/schema/codex-instance.schema.json +82 -0
- package/schema/event.schema.json +539 -9
- 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/event/invalid/approval-granted-sender-hashed-false.json +20 -0
- package/schema/fixtures/event/invalid/approval-granted-sender-hashed-raw-id.json +20 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-human-actor.json +16 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-no-actor-no-sender.json +15 -0
- package/schema/fixtures/event/invalid/audit-gesture-refused-unknown-gesture.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-agent-actor.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-no-question-id.json +16 -0
- package/schema/fixtures/event/invalid/audit-question-preempted-unknown-source.json +15 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-absolute-path.json +14 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-agent-actor.json +14 -0
- package/schema/fixtures/event/invalid/gate-path-signed-off-missing-path.json +13 -0
- package/schema/fixtures/event/valid/approval-granted-sender-hashed.json +20 -0
- package/schema/fixtures/event/valid/audit-gesture-refused-review-note.json +21 -0
- package/schema/fixtures/event/valid/audit-gesture-refused-sender-key-unavailable.json +19 -0
- package/schema/fixtures/event/valid/audit-gesture-refused.json +19 -0
- package/schema/fixtures/event/valid/audit-question-preempted-no-verdict.json +16 -0
- package/schema/fixtures/event/valid/audit-question-preempted.json +20 -0
- package/schema/fixtures/event/valid/gate-path-signed-off.json +14 -0
- package/schema/fixtures/event/valid/harness-kind-claude-code.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-codex.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-cursor.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-grok.json +23 -0
- package/schema/fixtures/event/valid/harness-kind-muse.json +23 -0
- package/schema/fixtures/policy/invalid/senders-half-keyed.json +20 -0
- package/schema/fixtures/policy/valid/canonical.json +1 -1
- package/schema/fixtures/policy/valid/senders-keyed.json +24 -0
- package/schema/fixtures/policy-md/valid/canonical.md +1 -1
- package/schema/fixtures/policy-md/valid/with-values.md +5 -7
- package/schema/fixtures/values/invalid/class-shaped.json +1 -1
- package/schema/fixtures/values/invalid/duplicate-entry.json +1 -1
- package/schema/fixtures/values/invalid/non-string-item.json +1 -1
- package/schema/fixtures/values/invalid/over-cap.json +1 -1
- package/schema/fixtures/values/invalid/unknown-key.json +1 -1
- package/schema/fixtures/values/invalid/version-float.json +1 -0
- package/schema/fixtures/values/invalid/version-integer.json +1 -0
- package/schema/fixtures/values/invalid/version-wrong-string.json +1 -0
- package/schema/fixtures/values/valid/empty-lists.json +2 -3
- package/schema/fixtures/values/valid/full.json +5 -7
- package/schema/fixtures/values/valid/minimal.json +1 -1
- package/schema/fixtures/values-md/invalid/schema-invalid.md +5 -3
- package/schema/fixtures/values-md/invalid/two-blocks.md +3 -3
- package/schema/fixtures/values-md/invalid/unterminated.md +2 -2
- package/schema/fixtures/values-md/invalid/version-1.md +69 -0
- package/schema/fixtures/values-md/invalid/version-unquoted.md +64 -0
- package/schema/fixtures/values-md/invalid/yaml-error.md +2 -2
- package/schema/fixtures/values-md/valid/absent.md +1 -1
- package/schema/fixtures/values-md/valid/with-values.md +5 -7
- package/schema/policy.schema.json +75 -3
- package/schema/values.schema.json +7 -11
- package/templates/codex/README.md +9 -0
- package/schema/fixtures/values/invalid/version-string.json +0 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bits of git the CLI needs, run the way `cli/amend.ts` has always run
|
|
3
|
+
* them: `spawnSync`, no shell, and every failure is a value rather than a throw.
|
|
4
|
+
*
|
|
5
|
+
* This module exists because APRV-125 gave a second and a third caller to the
|
|
6
|
+
* primary-checkout resolution APRV-101 wrote for the hook. `approval log sync`
|
|
7
|
+
* and `approval log advance` operate on the committed log, and the committed log
|
|
8
|
+
* has exactly one home: the primary checkout. A copy of `primaryRoot` per caller
|
|
9
|
+
* would be three chances for the three of them to disagree about where that is.
|
|
10
|
+
*
|
|
11
|
+
* Nothing here decides anything. It answers questions about a repository, and
|
|
12
|
+
* the verbs decide what the answers mean.
|
|
13
|
+
*/
|
|
14
|
+
import { GIT_OUTPUT_LIMIT_BYTES, gh, git, type GitRun } from "../core/git-run.js";
|
|
15
|
+
/**
|
|
16
|
+
* The two runners moved to `core/git-run.ts` in APRV-245 and are re-exported
|
|
17
|
+
* here unchanged. The coverage sources are core code and shell out to git, and
|
|
18
|
+
* core reaching into `src/cli/` for the runner would invert the direction
|
|
19
|
+
* `tests/layering.test.ts` keeps. Every existing caller of `git-scope.ts` is
|
|
20
|
+
* untouched, and there is still one spelling of "run git" in the repository.
|
|
21
|
+
*/
|
|
22
|
+
export { GIT_OUTPUT_LIMIT_BYTES, gh, git, type GitRun };
|
|
23
|
+
/** The repository root containing `dir`, or `null` when there is none. */
|
|
24
|
+
export declare function repoRoot(dir: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* The primary checkout containing `cwd`, or `null` when git cannot say.
|
|
27
|
+
*
|
|
28
|
+
* `git rev-parse --git-common-dir` names the SHARED git directory: in a linked
|
|
29
|
+
* worktree it is the primary checkout's `.git`, in a plain checkout it is this
|
|
30
|
+
* checkout's own (printed as bare `.git` at the top level, absolute from a
|
|
31
|
+
* subdirectory). Either way the primary root is its parent, so a plain checkout
|
|
32
|
+
* resolves to itself.
|
|
33
|
+
*
|
|
34
|
+
* When git is absent, or `cwd` is not a repository at all, this returns `null`.
|
|
35
|
+
* What that means is the caller's business: the hook falls back to `cwd`
|
|
36
|
+
* (APRV-101), and the log verbs refuse, because a log ritual with no repository
|
|
37
|
+
* to run it in has nothing to synchronize.
|
|
38
|
+
*/
|
|
39
|
+
export declare function primaryRoot(cwd: string): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* The primary checkout, but only when `cwd` is standing in it.
|
|
42
|
+
*
|
|
43
|
+
* A linked worktree's toplevel is the worktree; its common git directory
|
|
44
|
+
* belongs to the primary. So the two agree in the primary checkout and differ
|
|
45
|
+
* in every linked one, which is the whole distinction. Symlinks are resolved on
|
|
46
|
+
* both sides, because `/tmp` is `/private/tmp` on macOS and a checkout reached
|
|
47
|
+
* through one spelling must not read as a different checkout from the other.
|
|
48
|
+
*/
|
|
49
|
+
export declare function primaryCheckout(cwd: string): {
|
|
50
|
+
ok: true;
|
|
51
|
+
root: string;
|
|
52
|
+
} | {
|
|
53
|
+
ok: false;
|
|
54
|
+
reason: string;
|
|
55
|
+
worktreeRoot: string | null;
|
|
56
|
+
primary: string | null;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* A repo-relative, forward-slashed path, as git spells one.
|
|
60
|
+
*
|
|
61
|
+
* BOTH sides are resolved through `realpath` first (APRV-210). `git rev-parse
|
|
62
|
+
* --show-toplevel` prints the physical path, so a checkout reached through a
|
|
63
|
+
* symlinked spelling (`/tmp/x` for `/private/tmp/x` on macOS, a symlinked home
|
|
64
|
+
* directory, a bind mount) hands this function a root and a path that live in
|
|
65
|
+
* different spellings of the same place. `relative()` on those two produces a
|
|
66
|
+
* path that climbs out of the repository (`../../private/tmp/…`), git has no
|
|
67
|
+
* blob at `HEAD:<that>`, and the caller concludes the file has never been
|
|
68
|
+
* committed. That is the misread APRV-210 recorded on a log with thousands of
|
|
69
|
+
* committed records.
|
|
70
|
+
*/
|
|
71
|
+
export declare function repoPath(root: string, path: string): string;
|
|
72
|
+
/** The checked-out branch, or `null` on a detached HEAD. */
|
|
73
|
+
export declare function currentBranch(root: string): string | null;
|
|
74
|
+
/**
|
|
75
|
+
* One attempt at reading `<rev>:<relative>` out of the object store.
|
|
76
|
+
*
|
|
77
|
+
* The failure half carries the command and what the runner said, because the
|
|
78
|
+
* two ways this can fail need telling apart and neither is visible in a `null`:
|
|
79
|
+
* git answering "no such path in that rev" (ordinary, and the reason most
|
|
80
|
+
* callers move on to the next rev), and the read itself breaking — git absent,
|
|
81
|
+
* the object store unreadable, or output past
|
|
82
|
+
* {@link GIT_OUTPUT_LIMIT_BYTES}. A caller that reports "no committed copy"
|
|
83
|
+
* for the second case is telling an operator something false.
|
|
84
|
+
*/
|
|
85
|
+
export type BlobRead = {
|
|
86
|
+
ok: true;
|
|
87
|
+
bytes: Buffer;
|
|
88
|
+
} | {
|
|
89
|
+
ok: false;
|
|
90
|
+
command: string;
|
|
91
|
+
status: number | null;
|
|
92
|
+
detail: string;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* The bytes of `<rev>:<relative>`, with the reason when there are none.
|
|
96
|
+
*
|
|
97
|
+
* Read as a Buffer, never as text: callers hash and compare these bytes, and an
|
|
98
|
+
* encoding round-trip would silently change what is being compared. That is
|
|
99
|
+
* also why this is `spawnSync` directly rather than {@link git}, which decodes
|
|
100
|
+
* to a string — and why the buffer limit has to be repeated here rather than
|
|
101
|
+
* inherited from the runner.
|
|
102
|
+
*/
|
|
103
|
+
export declare function readBlob(root: string, rev: string, relative_: string): BlobRead;
|
|
104
|
+
/**
|
|
105
|
+
* The bytes of `<rev>:<relative>`, or `null` when there are none.
|
|
106
|
+
*
|
|
107
|
+
* The shape every caller predating {@link readBlob} expects. Callers that owe
|
|
108
|
+
* an operator a diagnostic when the read fails should reach for `readBlob`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function showBlob(root: string, rev: string, relative_: string): Buffer | null;
|
|
111
|
+
/** Everything git said about a run, as trimmed non-empty lines. */
|
|
112
|
+
export declare function outputLines(...texts: readonly string[]): string[];
|
|
113
|
+
/**
|
|
114
|
+
* Fetch one branch from one remote and answer the sha it now points at.
|
|
115
|
+
*
|
|
116
|
+
* The ceremony verbs (`policy amend`, `log advance`) own this step rather than
|
|
117
|
+
* asking the operator to run it first (APRV-203). The failure that made it
|
|
118
|
+
* theirs: a ceremony run in a checkout whose local `main` was behind origin
|
|
119
|
+
* built its commit on the stale tip, so the pull request carried a parent that
|
|
120
|
+
* was missing everything main had merged since, and CI went red for reasons
|
|
121
|
+
* that had nothing to do with the amendment.
|
|
122
|
+
*
|
|
123
|
+
* `FETCH_HEAD` is read rather than `refs/remotes/<remote>/<branch>`, because a
|
|
124
|
+
* fetch of an explicit refspec always writes the former and a repository
|
|
125
|
+
* configured without remote-tracking refs would not have the latter.
|
|
126
|
+
*/
|
|
127
|
+
export declare function fetchBase(root: string, remote: string, branch: string): {
|
|
128
|
+
ok: true;
|
|
129
|
+
sha: string;
|
|
130
|
+
} | {
|
|
131
|
+
ok: false;
|
|
132
|
+
message: string;
|
|
133
|
+
quote: readonly string[];
|
|
134
|
+
};
|
|
135
|
+
/** What {@link commitOnBase} is asked to build. */
|
|
136
|
+
export interface CommitOnBase {
|
|
137
|
+
/** The commit the new one is parented on, as a sha. */
|
|
138
|
+
base: string;
|
|
139
|
+
/** Repo-relative paths taken from the WORKING TREE, laid over the base tree. */
|
|
140
|
+
paths: readonly string[];
|
|
141
|
+
message: string;
|
|
142
|
+
/**
|
|
143
|
+
* Blobs forced into the index after the working-tree paths are laid over it,
|
|
144
|
+
* as `{path, sha}` (APRV-233).
|
|
145
|
+
*
|
|
146
|
+
* For a caller whose file is being written to concurrently and that has
|
|
147
|
+
* already pinned the bytes it means. `approval log advance` hashes the log
|
|
148
|
+
* under the append lock and then releases it for the slow half of the verb,
|
|
149
|
+
* so the commit must carry the object it VERIFIED rather than whatever the
|
|
150
|
+
* file grew into while `git fetch` was talking to the network. The blob has
|
|
151
|
+
* to be in the object store already; `git hash-object -w` is how the caller
|
|
152
|
+
* puts it there.
|
|
153
|
+
*/
|
|
154
|
+
blobs?: readonly {
|
|
155
|
+
path: string;
|
|
156
|
+
sha: string;
|
|
157
|
+
}[];
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build a commit on `base` carrying the working-tree state of `paths`, without
|
|
161
|
+
* checking anything out (APRV-203).
|
|
162
|
+
*
|
|
163
|
+
* The whole method is one scratch index: `GIT_INDEX_FILE` points at a temporary
|
|
164
|
+
* file, `read-tree` fills it from the base commit's tree, `add -A` lays the
|
|
165
|
+
* named working-tree paths over it, and `write-tree` plus `commit-tree` turn
|
|
166
|
+
* that into an object. HEAD never moves, the operator's index is never read or
|
|
167
|
+
* written, and no file in the working tree is touched — which is what lets a
|
|
168
|
+
* verb that MUST NOT check anything out (a branch switch rewinds `events.jsonl`
|
|
169
|
+
* underneath whatever holds it open) still base its commit on the remote.
|
|
170
|
+
*
|
|
171
|
+
* `unchanged` is the honest answer when the base tree already carries exactly
|
|
172
|
+
* these bytes: there is nothing to commit, and inventing an empty commit would
|
|
173
|
+
* be the verb narrating its own no-op.
|
|
174
|
+
*/
|
|
175
|
+
export declare function commitOnBase(root: string, request: CommitOnBase): {
|
|
176
|
+
ok: true;
|
|
177
|
+
sha: string;
|
|
178
|
+
unchanged: false;
|
|
179
|
+
} | {
|
|
180
|
+
ok: true;
|
|
181
|
+
sha: null;
|
|
182
|
+
unchanged: true;
|
|
183
|
+
} | {
|
|
184
|
+
ok: false;
|
|
185
|
+
step: string;
|
|
186
|
+
message: string;
|
|
187
|
+
quote: readonly string[];
|
|
188
|
+
};
|
|
189
|
+
/** The same, folded onto one line for a `--json` message string. */
|
|
190
|
+
export declare function failureText(run: GitRun): string;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attaching the model gloss to a request, for every channel that renders one
|
|
3
|
+
* (APRV-144, APRV-164, APRV-197).
|
|
4
|
+
*
|
|
5
|
+
* `cli/gloss.ts` decides how a sentence is obtained; this decides which
|
|
6
|
+
* material is worth asking about and where the answer is hung. It lived inside
|
|
7
|
+
* `cli/channel-telegram.ts` until APRV-197, when a second surface needed it:
|
|
8
|
+
* Carter, deciding requests on the CLI channel, read the raw claimed summary
|
|
9
|
+
* and nothing else, because the only code that had ever attached a gloss was
|
|
10
|
+
* the Telegram listener. One reading aid implemented twice would be two reading
|
|
11
|
+
* aids that drift, so the listener and the terminal walker now call the same
|
|
12
|
+
* function over the same payload views.
|
|
13
|
+
*
|
|
14
|
+
* The safety argument is unchanged and belongs here rather than at either call
|
|
15
|
+
* site. This runs at RENDER time, on a `ChannelRequest` the tagger has already
|
|
16
|
+
* finished building: the gate resolved the class, the budgets and the payload
|
|
17
|
+
* binding without this field existing, the payload hash was computed over bytes
|
|
18
|
+
* that do not contain it, and the log will record a decision that never
|
|
19
|
+
* mentions it. Nothing anywhere branches on the content of a gloss; the only
|
|
20
|
+
* thing that turns on it is whether one more line appears.
|
|
21
|
+
*
|
|
22
|
+
* What APRV-197 adds is an {@link GlossOutcome}. Absence used to be silent by
|
|
23
|
+
* design, and that was right for one request and wrong for a thousand: with the
|
|
24
|
+
* timeout set where APRV-144 set it, the subprocess missed EVERY time and the
|
|
25
|
+
* result was indistinguishable from the feature never having shipped. The
|
|
26
|
+
* outcome is returned so a caller can count, and count is all it is for — no
|
|
27
|
+
* caller retries, waits longer, or renders anything different because of it.
|
|
28
|
+
*/
|
|
29
|
+
import { type ChannelRequest } from "../channels/contract.js";
|
|
30
|
+
import { type GlossRunner } from "./gloss.js";
|
|
31
|
+
/**
|
|
32
|
+
* What one attempt did. Counted by the caller, read by nobody else.
|
|
33
|
+
*
|
|
34
|
+
* `opaque` and `absent` are kept apart because they mean different things to an
|
|
35
|
+
* operator: a payload with no describable material was never going to get a
|
|
36
|
+
* sentence (there is nothing the canonical JSON does not already show), while
|
|
37
|
+
* `absent` means a model was asked and did not answer in time. Only the second
|
|
38
|
+
* is a fault, and a counter that added them together would report a fault every
|
|
39
|
+
* time an opaque payload went by.
|
|
40
|
+
*/
|
|
41
|
+
export type GlossOutcome = "attached" | "absent" | "opaque";
|
|
42
|
+
export interface GlossAttachment {
|
|
43
|
+
/** The request, with a `gloss` field when there is one and unchanged otherwise. */
|
|
44
|
+
request: ChannelRequest;
|
|
45
|
+
outcome: GlossOutcome;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The request, plus a model's one-sentence gloss of its payload when one can be
|
|
49
|
+
* had.
|
|
50
|
+
*
|
|
51
|
+
* Every payload kind the renderer can read gets one (APRV-164): a command, a
|
|
52
|
+
* file change, an email. The kind is derived exactly as the WYSIWYS rendering
|
|
53
|
+
* derives it, from the structure of the bytes, so the sentence is about the
|
|
54
|
+
* material the approver is being shown and the two can never be about different
|
|
55
|
+
* payloads. An opaque payload gets none.
|
|
56
|
+
*
|
|
57
|
+
* Returns the request UNCHANGED for every flavour of "no answer". Losing the
|
|
58
|
+
* gloss costs one line on a prompt, which is why no failure here is allowed to
|
|
59
|
+
* cost anything more.
|
|
60
|
+
*/
|
|
61
|
+
export declare function attachGloss(request: ChannelRequest, run: GlossRunner): GlossAttachment;
|
|
62
|
+
/**
|
|
63
|
+
* The instruction and the material for one payload, or `null` for an opaque one.
|
|
64
|
+
*
|
|
65
|
+
* The material is assembled from the same structural views the canonical
|
|
66
|
+
* rendering is built from, and it is deliberately plain: labelled lines and the
|
|
67
|
+
* text itself, in the order the prompt shows them. Nothing here reads a
|
|
68
|
+
* self-declared kind field, for the reason `core/wysiwys.ts` gives at length —
|
|
69
|
+
* a payload that chose its own presentation would have chosen its own gloss too.
|
|
70
|
+
*/
|
|
71
|
+
export declare function glossMaterial(value: unknown): {
|
|
72
|
+
instruction: string;
|
|
73
|
+
material: string;
|
|
74
|
+
} | null;
|
|
75
|
+
/**
|
|
76
|
+
* The stderr line that turns chronic silence into a visible fault (APRV-197 #3).
|
|
77
|
+
*
|
|
78
|
+
* One line, at the end of a walk or a dispatch cycle, and only when a model was
|
|
79
|
+
* actually asked and did not answer. It names the ceiling because that is the
|
|
80
|
+
* number an operator can act on, and it says the decision is unaffected because
|
|
81
|
+
* the first thing a reader of an approval tool's stderr needs to know is
|
|
82
|
+
* whether the thing they just approved was compromised by this. It was not:
|
|
83
|
+
* nothing downstream of a gloss exists.
|
|
84
|
+
*/
|
|
85
|
+
export declare function glossAbsenceLine(surface: string, absent: number, asked: number, timeoutMs: number): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-group supervisor for the synchronous Codex gloss runner (APRV-254).
|
|
3
|
+
*
|
|
4
|
+
* The public runner waits synchronously because GlossRunner is synchronous.
|
|
5
|
+
* This small child can still supervise Codex asynchronously, which lets it
|
|
6
|
+
* terminate the complete detached process group when the CLI times out or
|
|
7
|
+
* exceeds its output allowance. It never prints stderr or process errors.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Provider-specific Codex CLI runner for optional model glosses (APRV-254). */
|
|
2
|
+
import { type GlossRunner } from "./gloss.js";
|
|
3
|
+
export type CodexGlossUnavailableReason = "invalid-model" | "invalid-prompt" | "unsupported-platform" | "spawn-error" | "timeout" | "output-too-large" | "nonzero-exit" | "invalid-output" | "unsafe-output" | "cleanup-failed";
|
|
4
|
+
export interface CodexGlossRunnerOptions {
|
|
5
|
+
/** Test seam. Production callers omit this and run the installed `codex`. */
|
|
6
|
+
readonly executable?: string;
|
|
7
|
+
/** Test seam. Production callers always receive the shared 20-second cap. */
|
|
8
|
+
readonly timeoutMs?: number;
|
|
9
|
+
/** Receives only a fixed reason code, never subprocess output. */
|
|
10
|
+
readonly diagnostic?: (reason: CodexGlossUnavailableReason) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build a synchronous Codex gloss runner using the CLI's saved authentication.
|
|
14
|
+
*
|
|
15
|
+
* The invocation starts in a new empty directory with a named read-only
|
|
16
|
+
* permission profile, command network disabled, project instructions
|
|
17
|
+
* suppressed, host skill discovery skipped, and selected known
|
|
18
|
+
* tool/integration features disabled.
|
|
19
|
+
* Codex 0.152.1 has no universal deny-all tool switch: host-managed and global
|
|
20
|
+
* base instructions still apply, the under-development discovery switch is
|
|
21
|
+
* version-specific, and the CLI owns any auth-state maintenance.
|
|
22
|
+
* The caller must present that practical isolation boundary to the operator.
|
|
23
|
+
*/
|
|
24
|
+
export declare function codexGlossRunnerFor(model: string, passphraseEnv?: string | null, options?: CodexGlossRunnerOptions): GlossRunner;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Shared provider selection for the three optional gloss surfaces (APRV-255). */
|
|
2
|
+
import { type ParsedFlags } from "./args.js";
|
|
3
|
+
import { codexGlossRunnerFor, type CodexGlossUnavailableReason } from "./gloss-codex.js";
|
|
4
|
+
import { type GlossProvider, type GlossRunner } from "./gloss.js";
|
|
5
|
+
/** A validated operator selection. It is safe to hand directly to a runner factory. */
|
|
6
|
+
export interface GlossOptions {
|
|
7
|
+
readonly enabled: boolean;
|
|
8
|
+
readonly provider: GlossProvider;
|
|
9
|
+
readonly model: string;
|
|
10
|
+
}
|
|
11
|
+
export type GlossOptionsResult = {
|
|
12
|
+
readonly ok: true;
|
|
13
|
+
readonly options: GlossOptions;
|
|
14
|
+
} | {
|
|
15
|
+
readonly ok: false;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the flags shared by `up`, Telegram listen and the terminal channel.
|
|
20
|
+
*
|
|
21
|
+
* The caller supplies its historical default: Telegram and `up` pass `true`,
|
|
22
|
+
* while the terminal channel passes `false`. `--no-gloss` wins a tie so an
|
|
23
|
+
* explicit request to remove a model from the path can never accidentally
|
|
24
|
+
* spawn one. Provider and model values are validated even when disabled;
|
|
25
|
+
* otherwise a typo could wait unnoticed until a later invocation adds
|
|
26
|
+
* `--gloss`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseGlossOptions(flags: ParsedFlags, enabledByDefault: boolean): GlossOptionsResult;
|
|
29
|
+
type ClaudeRunnerFactory = (passphraseEnv: string | null, model: string) => GlossRunner;
|
|
30
|
+
type CodexRunnerFactory = typeof codexGlossRunnerFor;
|
|
31
|
+
/** Fixed reason codes only; subprocess output must never reach this callback. */
|
|
32
|
+
export type GlossDiagnostic = (reason: CodexGlossUnavailableReason) => void;
|
|
33
|
+
export interface GlossRunnerFactoryOptions {
|
|
34
|
+
readonly passphraseEnv?: string | null;
|
|
35
|
+
readonly diagnostic?: GlossDiagnostic;
|
|
36
|
+
/** Test seams. Production callers use the provider implementations above. */
|
|
37
|
+
readonly claudeRunnerFor?: ClaudeRunnerFactory;
|
|
38
|
+
readonly codexRunnerFor?: CodexRunnerFactory;
|
|
39
|
+
}
|
|
40
|
+
/** Construct exactly the selected runner, or no runner when glossing is disabled. */
|
|
41
|
+
export declare function glossRunnerFromOptions(selection: GlossOptions, factoryOptions?: GlossRunnerFactoryOptions): GlossRunner | undefined;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The model gloss: one sentence saying what a payload does, attached to a
|
|
3
|
+
* prompt at render time and to nothing else (APRV-144, APRV-164).
|
|
4
|
+
*
|
|
5
|
+
* The observed complaint (Carter, 2026-08-25): "the claimed isn't very useful —
|
|
6
|
+
* I mostly see the path, not a readable claim of what is happening". The
|
|
7
|
+
* deterministic half of the answer is `channels/payload-view.ts`'s command
|
|
8
|
+
* breakdown, which is derived from the classifier's own parse and is COMPUTED.
|
|
9
|
+
* This is the other half, and it is the opposite kind of thing: a sentence from
|
|
10
|
+
* a language model, which no party vouches for and which the runtime must
|
|
11
|
+
* therefore treat as decoration.
|
|
12
|
+
*
|
|
13
|
+
* Four properties hold the design together, and every one of them is about
|
|
14
|
+
* keeping a model out of the decision.
|
|
15
|
+
*
|
|
16
|
+
* **The gate never sees it.** This runs in the LISTENER, at the moment a
|
|
17
|
+
* message is about to be sent, on a `ChannelRequest` the tagger has already
|
|
18
|
+
* finished building. The payload hash covers the bytes and not this; the log
|
|
19
|
+
* records the approval lifecycle and not this; a restart forgets it. Nothing
|
|
20
|
+
* here writes anything anywhere.
|
|
21
|
+
*
|
|
22
|
+
* **It is never load-bearing.** No code path branches on the content of a
|
|
23
|
+
* gloss. The only thing that turns on it at all is whether one more line
|
|
24
|
+
* appears in the CLAIMED block, which is why every failure mode below resolves
|
|
25
|
+
* to ABSENCE rather than to a placeholder, an error line, or a retry: a prompt
|
|
26
|
+
* with no gloss is the prompt approval.md shipped for its whole life so far,
|
|
27
|
+
* and a listener that waited on a model would have made a language model part
|
|
28
|
+
* of the availability of the gate.
|
|
29
|
+
*
|
|
30
|
+
* **It fails toward absence, fast.** A hard timeout (default
|
|
31
|
+
* {@link GLOSS_TIMEOUT_MS}), a non-zero exit, empty output, a binary that is
|
|
32
|
+
* not installed, a spawn that throws: all `null`. The timeout is bounded on
|
|
33
|
+
* purpose — this sits in a dispatch cycle that an approver is waiting on — and
|
|
34
|
+
* since APRV-197 it is bounded by a MEASUREMENT rather than by a guess, because
|
|
35
|
+
* a ceiling the model cannot meet is not a fast failure, it is a feature that
|
|
36
|
+
* never runs. See {@link GLOSS_TIMEOUT_MS}. Absences are counted and reported
|
|
37
|
+
* by the caller (`cli/gloss-attach.ts`), so a ceiling that is wrong again
|
|
38
|
+
* announces itself instead of looking like silence.
|
|
39
|
+
*
|
|
40
|
+
* **Its output is untrusted text.** Whatever comes back is collapsed to a
|
|
41
|
+
* single line, capped at {@link GLOSS_MAX_CHARS}, and handed to the channel as
|
|
42
|
+
* a CLAIMED field, which means it goes through the same `escapeHtml` every
|
|
43
|
+
* other claimed value does. It is treated exactly like a summary an agent
|
|
44
|
+
* wrote, because that is precisely what it is a cousin of.
|
|
45
|
+
*
|
|
46
|
+
* The subprocess is injectable ({@link GlossRunner}) so the tests drive both
|
|
47
|
+
* branches without a model ever being invoked: the suite never spawns
|
|
48
|
+
* anything, and the default runner below is exercised only in production.
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* How long the subprocess gets before it is killed and the gloss is dropped.
|
|
52
|
+
*
|
|
53
|
+
* **Measured, not guessed (APRV-197).** APRV-144 chose 2s on the reasoning that
|
|
54
|
+
* "a slow reading aid is worse than no reading aid", which is true and was the
|
|
55
|
+
* wrong number: five fresh `claude -p --model haiku` spawns of this module's
|
|
56
|
+
* own command instruction, timed on the author's machine on 2026-09-01, came
|
|
57
|
+
* back in 10.2s, 11.3s, 13.5s, 14.6s and 14.9s. Every one of them would have
|
|
58
|
+
* been killed. The gloss was therefore not "occasionally absent"; it was
|
|
59
|
+
* absent every single time, and because absence is silent by design that was
|
|
60
|
+
* indistinguishable from the feature never having shipped — which is exactly
|
|
61
|
+
* how it was reported (Carter, 2026-09-01: "i thought we implemented a change
|
|
62
|
+
* so that the claim would be an llm summary").
|
|
63
|
+
*
|
|
64
|
+
* A pre-warm was the other option on the table and the measurement rules it
|
|
65
|
+
* out: the runs above were consecutive, so runs two through five were warm in
|
|
66
|
+
* every sense a second process can be (page cache, module cache), and they took
|
|
67
|
+
* 10s to 15s all the same. What is being waited on is inference, not start-up,
|
|
68
|
+
* and nothing a listener does once at boot shortens it.
|
|
69
|
+
*
|
|
70
|
+
* So the ceiling is set above the slowest observed run with headroom, and the
|
|
71
|
+
* price of that honesty is made explicit rather than hidden. A gloss is now
|
|
72
|
+
* asked for only under `--gloss` (on `channel cli`, `channel telegram listen`
|
|
73
|
+
* and `up` alike): an operator who wants the sentence spends the seconds
|
|
74
|
+
* knowingly, one who does not is never made to wait, and the reading aid that
|
|
75
|
+
* is always present is the deterministic `command_breakdown` the classifier
|
|
76
|
+
* derives from the same bytes for free.
|
|
77
|
+
*/
|
|
78
|
+
export declare const GLOSS_TIMEOUT_MS = 20000;
|
|
79
|
+
/** The most characters a gloss may occupy on the prompt. */
|
|
80
|
+
export declare const GLOSS_MAX_CHARS = 200;
|
|
81
|
+
/** Maximum length of an exact provider-supplied model identifier. */
|
|
82
|
+
export declare const GLOSS_MODEL_ID_MAX_CHARS = 100;
|
|
83
|
+
/**
|
|
84
|
+
* The model tier this spends: the cheap one.
|
|
85
|
+
*
|
|
86
|
+
* CLAUDE.md's model tiers put "cheap classification" on a `claude -p` haiku
|
|
87
|
+
* subprocess, and a one-sentence paraphrase of a command line is the cheapest
|
|
88
|
+
* kind of language task there is. Nothing about the prompt or the gate changes
|
|
89
|
+
* if the flag is unrecognised by the installed CLI: an unusable invocation
|
|
90
|
+
* exits non-zero and the gloss is absent.
|
|
91
|
+
*/
|
|
92
|
+
export declare const GLOSS_MODEL = "haiku";
|
|
93
|
+
/**
|
|
94
|
+
* The historical author label for legacy string-valued test runners.
|
|
95
|
+
*
|
|
96
|
+
* Production runners return explicit provenance. Keeping this constant is a
|
|
97
|
+
* compatibility bridge for callers whose injected seam predates APRV-253; it
|
|
98
|
+
* must never be used to guess the provenance of a typed production result.
|
|
99
|
+
*/
|
|
100
|
+
export declare const GLOSS_AUTHOR = "model:haiku";
|
|
101
|
+
/**
|
|
102
|
+
* The instruction the model is given.
|
|
103
|
+
*
|
|
104
|
+
* Deliberately narrow: describe, do not judge. A model asked whether a command
|
|
105
|
+
* is safe would produce a sentence an approver could read as a recommendation,
|
|
106
|
+
* and a recommendation from an unverified party sitting beside an Approve
|
|
107
|
+
* button is the failure this whole codebase is arranged to prevent. It is
|
|
108
|
+
* asked what the command DOES, and the answer is labelled as a model's on the
|
|
109
|
+
* line where it appears.
|
|
110
|
+
*/
|
|
111
|
+
export declare const GLOSS_INSTRUCTION: string;
|
|
112
|
+
/**
|
|
113
|
+
* The same instruction for a file change (APRV-164).
|
|
114
|
+
*
|
|
115
|
+
* A payload kind gets its own wording because "what this shell command does" is
|
|
116
|
+
* the wrong question to ask about a diff, and a model handed the wrong question
|
|
117
|
+
* answers a question nobody asked. The discipline is identical: describe the
|
|
118
|
+
* change, do not rate it, and above all do not say whether the edit looks
|
|
119
|
+
* correct — a judgement of a diff sitting beside an Approve button is the same
|
|
120
|
+
* failure as a judgement of a command.
|
|
121
|
+
*/
|
|
122
|
+
export declare const GLOSS_EDIT_INSTRUCTION: string;
|
|
123
|
+
/** The same instruction for an email (APRV-164): what it says, and to whom. */
|
|
124
|
+
export declare const GLOSS_EMAIL_INSTRUCTION: string;
|
|
125
|
+
/**
|
|
126
|
+
* The most material a gloss may hand the subprocess.
|
|
127
|
+
*
|
|
128
|
+
* A whole-file `Write` payload is megabytes, and a reading aid must not turn a
|
|
129
|
+
* dispatch cycle into a megabyte of argv and a model reading it. The cap is on
|
|
130
|
+
* the INPUT only: {@link GLOSS_MAX_CHARS} still bounds what comes back.
|
|
131
|
+
*/
|
|
132
|
+
export declare const GLOSS_MAX_INPUT_CHARS = 8192;
|
|
133
|
+
/**
|
|
134
|
+
* What the model is told when the cap bit.
|
|
135
|
+
*
|
|
136
|
+
* Announced rather than silent, for the reason every other fold in this
|
|
137
|
+
* codebase is announced: a model describing a prefix as if it were the whole
|
|
138
|
+
* would produce a confident sentence about a change the approver is not being
|
|
139
|
+
* shown. The line is for the model; the approver's own evidence is the PAYLOAD
|
|
140
|
+
* block, which is never folded.
|
|
141
|
+
*/
|
|
142
|
+
export declare const GLOSS_TRUNCATION_NOTE = "(input truncated; describe what is shown)";
|
|
143
|
+
/** A summarizer implementation the listener may explicitly select. */
|
|
144
|
+
export type GlossProvider = "claude" | "codex";
|
|
145
|
+
/**
|
|
146
|
+
* The model identity a runner can honestly establish.
|
|
147
|
+
*
|
|
148
|
+
* `requestedModel` is always present because it is controlled by the
|
|
149
|
+
* invocation. `confirmedModel` is present only when machine-readable process
|
|
150
|
+
* output identifies the model that actually served the request. A successful
|
|
151
|
+
* process exit alone does not confirm that identity.
|
|
152
|
+
*/
|
|
153
|
+
export interface GlossProvenance {
|
|
154
|
+
provider: GlossProvider;
|
|
155
|
+
requestedModel: string;
|
|
156
|
+
confirmedModel?: string;
|
|
157
|
+
}
|
|
158
|
+
/** One raw model answer together with runner-supplied provenance. */
|
|
159
|
+
export interface GlossResult {
|
|
160
|
+
text: string;
|
|
161
|
+
provenance: GlossProvenance;
|
|
162
|
+
/** Compatibility marker for the pre-APRV-253 injected string seam. */
|
|
163
|
+
legacy?: true;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* How a gloss is obtained.
|
|
167
|
+
*
|
|
168
|
+
* New runners return a {@link GlossResult}. A raw string remains accepted only
|
|
169
|
+
* so existing injected stubs keep working; it is explicitly interpreted as
|
|
170
|
+
* the historical Claude/Haiku seam. Every flavour of "no answer" is `null`.
|
|
171
|
+
*
|
|
172
|
+
* MUST NOT throw: a runner that raised would put a language model on the
|
|
173
|
+
* failure path of the listener's dispatch cycle.
|
|
174
|
+
*/
|
|
175
|
+
export type GlossRunnerOutput = GlossResult | string | null;
|
|
176
|
+
export type GlossRunner = (prompt: string) => GlossRunnerOutput;
|
|
177
|
+
/**
|
|
178
|
+
* One line, capped, or `null`.
|
|
179
|
+
*
|
|
180
|
+
* Newlines are stripped rather than escaped because the prompt renders this as
|
|
181
|
+
* a single bullet, and a multi-line value would break the one-fact-per-line
|
|
182
|
+
* shape the whole COMPUTED/CLAIMED split relies on to stay legible. Truncation
|
|
183
|
+
* is marked, for the same reason every other fold in this codebase is.
|
|
184
|
+
*/
|
|
185
|
+
export declare function tidyGloss(raw: string | null): string | null;
|
|
186
|
+
/**
|
|
187
|
+
* Normalize a runner answer without inventing provenance.
|
|
188
|
+
*
|
|
189
|
+
* Objects with incomplete metadata fail toward absence. Raw strings take the
|
|
190
|
+
* one narrowly documented legacy path and retain the historical Haiku label.
|
|
191
|
+
*/
|
|
192
|
+
export declare function tidyGlossResult(raw: unknown): GlossResult | null;
|
|
193
|
+
/** A bounded, single-line identifier, or `null` rather than a misleading fold. */
|
|
194
|
+
export declare function normalizeGlossModelId(raw: unknown): string | null;
|
|
195
|
+
/**
|
|
196
|
+
* The claimed author rendered beside one gloss.
|
|
197
|
+
*
|
|
198
|
+
* Requested and confirmed identities are deliberately distinct. The default
|
|
199
|
+
* subprocess knows what it asked Claude for, but its plain stdout does not
|
|
200
|
+
* prove which model served the request, so it renders as requested.
|
|
201
|
+
*/
|
|
202
|
+
export declare function glossAuthor(result: GlossResult): string;
|
|
203
|
+
/**
|
|
204
|
+
* The production runner: `claude -p --model haiku`, with a hard timeout.
|
|
205
|
+
*
|
|
206
|
+
* `spawnSync` with no shell, in the manner of `cli/hook.ts`'s git calls: the
|
|
207
|
+
* prompt is an argument and never a string a shell re-parses. Every failure is
|
|
208
|
+
* a value rather than an exception — `spawnSync` reports a missing binary and a
|
|
209
|
+
* timeout kill on the result object, and both are simply "no gloss".
|
|
210
|
+
*
|
|
211
|
+
* **Starved, like a granted child (APRV-207).** The environment is built by
|
|
212
|
+
* APRV-205's scrub rather than inherited: this is a third-party CLI that talks
|
|
213
|
+
* to the network on every prompt render, spawned by the listener, which is the
|
|
214
|
+
* process holding the Telegram bot token and the vault passphrase. It has no
|
|
215
|
+
* use for either, and a gate that hands its own credentials to a convenience is
|
|
216
|
+
* a gate whose custody claim is decorative. No credential is DECLARED here,
|
|
217
|
+
* because a gloss is not a granted action and no adapter asked for one.
|
|
218
|
+
*
|
|
219
|
+
* What passes is what the scrub does not take: the model's own auth
|
|
220
|
+
* (`ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, `CLAUDE_CODE_OAUTH_TOKEN`,
|
|
221
|
+
* `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL` and kin), `PATH`, `HOME`, `TMPDIR`
|
|
222
|
+
* and the locale. None of them is under the gate's credential-bearing prefixes,
|
|
223
|
+
* so none of them needs a list of its own: a second list here is a second list
|
|
224
|
+
* to drift, and the CLI's ability to reach its own model is not this gate's
|
|
225
|
+
* secret to keep.
|
|
226
|
+
*
|
|
227
|
+
* `passphraseEnv` is the name the policy's `vault.passphrase_env` gives, for
|
|
228
|
+
* the deployment that renamed it out from under the prefixes. Omitted, the
|
|
229
|
+
* default (`APPROVAL_VAULT_PASSPHRASE`) is removed by the prefix rule anyway.
|
|
230
|
+
*/
|
|
231
|
+
export declare function spawnGloss(prompt: string, passphraseEnv?: string | null, model?: string): GlossResult | null;
|
|
232
|
+
/**
|
|
233
|
+
* {@link spawnGloss} bound to one policy's passphrase variable (APRV-207).
|
|
234
|
+
*
|
|
235
|
+
* The verbs that wire a runner (`channel cli`, `channel telegram listen`, `up`)
|
|
236
|
+
* have a policy load in hand already, and this is the only thing the scrub
|
|
237
|
+
* needs from it. A runner is still a `(prompt) => string | null`, so nothing
|
|
238
|
+
* downstream learns that a policy exists.
|
|
239
|
+
*/
|
|
240
|
+
export declare function glossRunnerFor(passphraseEnv: string | null, model?: string): GlossRunner;
|
|
241
|
+
/**
|
|
242
|
+
* `material`, capped at {@link GLOSS_MAX_INPUT_CHARS} and marked when it was.
|
|
243
|
+
*
|
|
244
|
+
* The marker precedes the material rather than trailing it, so a model reading
|
|
245
|
+
* a long prefix meets the caveat before the text it is about to describe.
|
|
246
|
+
*/
|
|
247
|
+
export declare function glossPrompt(instruction: string, material: string): string;
|
|
248
|
+
/**
|
|
249
|
+
* A gloss for one payload's material, or `null`.
|
|
250
|
+
*
|
|
251
|
+
* The material is passed to the model as data inside the prompt. It is
|
|
252
|
+
* agent-authored text, and it is worth being explicit about what that does and
|
|
253
|
+
* does not mean here: a command (or a diff, or a body) crafted to talk the
|
|
254
|
+
* model into writing "harmless cleanup" gets that sentence onto the prompt,
|
|
255
|
+
* labelled `(model, unverified)`, next to a COMPUTED breakdown derived from the
|
|
256
|
+
* same bytes by code and a PAYLOAD block carrying the canonical rendering verbatim. It
|
|
257
|
+
* cannot change the class, the autonomy, the budget verdicts or the payload
|
|
258
|
+
* hash, because nothing downstream reads it. That is the whole reason this is
|
|
259
|
+
* allowed to exist on the prompt at all.
|
|
260
|
+
*
|
|
261
|
+
* The caller chooses the instruction, which is the only thing that varies by
|
|
262
|
+
* payload kind: the bounds, the failure modes and the author label are one
|
|
263
|
+
* pipeline for every kind (APRV-164).
|
|
264
|
+
*/
|
|
265
|
+
export declare function glossFor(instruction: string, material: string, run?: GlossRunner): GlossResult | null;
|