approval-md 0.1.0 → 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/README.md +584 -553
- package/SPEC.md +42 -13
- 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 +623 -0
- 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 +1832 -0
- package/dist/src/channels/web.d.ts +341 -0
- 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/args.d.ts +43 -0
- package/dist/src/cli/attest.d.ts +41 -0
- 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 +806 -0
- package/dist/src/cli/channel-web.d.ts +131 -0
- package/dist/src/cli/channel.d.ts +71 -0
- package/dist/src/cli/checkpoint-tap.d.ts +169 -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/daemon.d.ts +120 -0
- package/dist/src/cli/doctor.d.ts +129 -0
- package/dist/src/cli/doctor.js +119 -5
- 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/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 +103 -0
- package/dist/src/cli/help.js +173 -51
- package/dist/src/cli/help.js.map +1 -1
- 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 +186 -80
- package/dist/src/cli/hook.js.map +1 -1
- package/dist/src/cli/import.d.ts +35 -0
- 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 +155 -5
- 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.d.ts +43 -0
- package/dist/src/cli/preflight.d.ts +363 -0
- package/dist/src/cli/preflight.js +294 -7
- 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/scaffold.d.ts +79 -0
- 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 +117 -0
- package/dist/src/cli/setup-checkpoint.d.ts +57 -0
- package/dist/src/cli/setup-common.d.ts +275 -0
- 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 +202 -0
- 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 +4 -2
- 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/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 +176 -8
- 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/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/agents-md.d.ts +276 -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 +13 -1
- package/dist/src/core/attest.js.map +1 -1
- package/dist/src/core/audit.d.ts +492 -0
- package/dist/src/core/budgets.d.ts +238 -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 +543 -0
- package/dist/src/core/command-class.js +43 -8
- package/dist/src/core/command-class.js.map +1 -1
- 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/dark-session.d.ts +331 -0
- package/dist/src/core/decision-refusal.d.ts +185 -0
- package/dist/src/core/env-file.d.ts +450 -0
- package/dist/src/core/execute.d.ts +858 -0
- package/dist/src/core/execute.js +44 -6
- 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 +1364 -0
- package/dist/src/core/gate.js +68 -13
- package/dist/src/core/gate.js.map +1 -1
- 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 +2 -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 +253 -0
- 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 +278 -0
- 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 +150 -0
- package/dist/src/core/policy-explain.js +31 -3
- package/dist/src/core/policy-explain.js.map +1 -1
- package/dist/src/core/policy-load.d.ts +527 -0
- package/dist/src/core/policy-load.js +15 -3
- package/dist/src/core/policy-load.js.map +1 -1
- package/dist/src/core/policy-match.d.ts +281 -0
- package/dist/src/core/policy-match.js +20 -9
- package/dist/src/core/policy-match.js.map +1 -1
- package/dist/src/core/policy-proposal.d.ts +265 -0
- package/dist/src/core/prompt-layout.d.ts +221 -0
- package/dist/src/core/protected-path-guard.d.ts +453 -0
- package/dist/src/core/protected-path-guard.js +514 -35
- package/dist/src/core/protected-path-guard.js.map +1 -1
- 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 +290 -0
- package/dist/src/core/seal.d.ts +165 -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 +137 -0
- 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 +466 -0
- package/dist/src/daemon/audit.d.ts +87 -0
- package/dist/src/daemon/daemon.d.ts +1180 -0
- 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 +9 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/docs/adapter-api.md +106 -0
- package/docs/cli-reference.md +389 -36
- package/docs/codex-enforced-session.md +30 -0
- package/package.json +12 -2
- package/schema/codex-instance.schema.json +82 -0
- package/schema/event.schema.json +2 -1
- package/schema/fixtures/codex-instance/invalid/unpinned-codex-version.json +40 -0
- package/schema/fixtures/codex-instance/valid/canonical.json +40 -0
- package/schema/policy.schema.json +21 -1
- package/templates/codex/README.md +9 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process exit codes for the `approval` CLI — **frozen public API**.
|
|
3
|
+
*
|
|
4
|
+
* SPEC.md §10.1 makes the CLI the primary interface for humans *and* agents.
|
|
5
|
+
* An agent branches on the exit code before it ever looks at stdout, so these
|
|
6
|
+
* five numbers are part of the contract: they are defined once, here, and every
|
|
7
|
+
* `--help` text prints them. Adding a code is a spec change; changing the
|
|
8
|
+
* meaning of an existing one is a breaking change.
|
|
9
|
+
*
|
|
10
|
+
* The distinction that matters most is {@link EXIT_INTEGRITY} vs
|
|
11
|
+
* {@link EXIT_IO}. "I could not read the file" and "the file has been tampered
|
|
12
|
+
* with" are different facts about the world, and conflating them either cries
|
|
13
|
+
* wolf over a permission bit or — far worse — lets real tampering read as a
|
|
14
|
+
* transient filesystem hiccup. The core `verify()` reports a non-ENOENT read
|
|
15
|
+
* failure as `corrupt`, because from inside the chain walker an unreadable log
|
|
16
|
+
* is indistinguishable from a broken one; the CLI boundary therefore checks
|
|
17
|
+
* readability *itself* before calling core, and reports I/O as I/O. Messages on
|
|
18
|
+
* this path must never use the word "corrupt".
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Success. `verify`: the chain is clean. `tail`/`export`: the requested records
|
|
22
|
+
* were produced — including the torn-tail case, where the intact prefix is
|
|
23
|
+
* printed and the tear is a stderr warning. `reindex`: the index was built.
|
|
24
|
+
*/
|
|
25
|
+
export declare const EXIT_OK = 0;
|
|
26
|
+
/**
|
|
27
|
+
* Integrity failure. `verify`: the log is corrupt. `tail`/`export`: refused to
|
|
28
|
+
* print records from a corrupt log. `reindex`: refused to index one
|
|
29
|
+
* (`not-clean`).
|
|
30
|
+
*/
|
|
31
|
+
export declare const EXIT_INTEGRITY = 1;
|
|
32
|
+
/** Usage error: unknown command, unknown flag, missing or invalid value. */
|
|
33
|
+
export declare const EXIT_USAGE = 2;
|
|
34
|
+
/**
|
|
35
|
+
* Torn tail — the log's final line is unterminated, the signature of a crashed
|
|
36
|
+
* write rather than of tampering. `verify` reports it; `reindex` refuses
|
|
37
|
+
* without `--force`. Nothing is ever repaired: truncating a torn line is a
|
|
38
|
+
* human decision.
|
|
39
|
+
*/
|
|
40
|
+
export declare const EXIT_TORN_TAIL = 3;
|
|
41
|
+
/**
|
|
42
|
+
* I/O error: the log or the index path could not be read, created, or
|
|
43
|
+
* replaced. Never used for anything the log itself says about its own
|
|
44
|
+
* contents.
|
|
45
|
+
*/
|
|
46
|
+
export declare const EXIT_IO = 4;
|
|
47
|
+
/**
|
|
48
|
+
* No valid execution token — **`approval run` only** (APRV-18, human-settled
|
|
49
|
+
* 2026-08-06: "refuses without a valid token at a distinct exit code").
|
|
50
|
+
*
|
|
51
|
+
* An addition to the table above, not a redefinition of anything in it: every
|
|
52
|
+
* command that existed before APRV-18 still uses 0–4 and none of them can emit
|
|
53
|
+
* 5. It is distinct from {@link EXIT_INTEGRITY} because the repair is distinct.
|
|
54
|
+
* A generic gate refusal means "ask a human what to do"; a 5 means "you are
|
|
55
|
+
* holding no key to this door" — request the action, get it granted, and pass
|
|
56
|
+
* the token that grant printed. An agent that could not tell those apart would
|
|
57
|
+
* escalate when it should retry with a token, or retry forever when it should
|
|
58
|
+
* escalate.
|
|
59
|
+
*/
|
|
60
|
+
export declare const EXIT_NO_TOKEN = 5;
|
|
61
|
+
/**
|
|
62
|
+
* Timeout — **`approval wait` only** (APRV-18). The wait elapsed with the
|
|
63
|
+
* task's requests still undecided. Nothing was appended and nothing is implied
|
|
64
|
+
* about the request: it is still live, and waiting again is legitimate.
|
|
65
|
+
*
|
|
66
|
+
* Distinct from every decision code, because "no answer yet" is not an answer.
|
|
67
|
+
* `wait` is the one verb whose exit code encodes a *decision* rather than a
|
|
68
|
+
* runtime outcome (SPEC.md §10.1: "exit code = decision"), so its mapping is
|
|
69
|
+
* documented in full in its own `--help`.
|
|
70
|
+
*/
|
|
71
|
+
export declare const EXIT_TIMEOUT = 6;
|
|
72
|
+
/** The frozen table, for help text and for tests that pin it. */
|
|
73
|
+
export declare const EXIT_CODE_TABLE: ReadonlyArray<readonly [number, string]>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval feedback` (APRV-239) — what the operator thought, read back.
|
|
3
|
+
*
|
|
4
|
+
* The HUMAN-TO-AGENT direction of the log, at the CLI. Two records can carry a
|
|
5
|
+
* human's own words about an action: `approval.granted`, where a person answered
|
|
6
|
+
* the gate, and `audit.reviewed`, where a person looked at a sampled action
|
|
7
|
+
* afterwards. Both may carry a graded `reaction` and both may carry a `note`.
|
|
8
|
+
* This verb collects them, joins each to the class, the task, the action key and
|
|
9
|
+
* the AGENT whose work it was, and prints them behind a banner.
|
|
10
|
+
*
|
|
11
|
+
* Three properties are the whole design, and each is enforced somewhere in this
|
|
12
|
+
* file rather than asserted in prose:
|
|
13
|
+
*
|
|
14
|
+
* - **It is guidance, and it says so on every output form.** {@link FEEDBACK_BANNER}
|
|
15
|
+
* leads the human rendering and rides in the `note` field of the JSON. A
|
|
16
|
+
* surface that printed reactions without labelling them would be handing an
|
|
17
|
+
* agent free-text human prose in the shape of a rule (SPEC.md §11.1
|
|
18
|
+
* invariant 10 requires the label; the invariant's substance is that nothing
|
|
19
|
+
* in the runtime reads any of this).
|
|
20
|
+
* - **It is symmetric with `journal`, deliberately.** `journal read` is the
|
|
21
|
+
* operator reading what the agents said; this is the agents reading what the
|
|
22
|
+
* operator said. Same shape of entry, same delimiters, same `--since` and
|
|
23
|
+
* `--limit`. The one difference is that no entry here is marked `[claimed]`:
|
|
24
|
+
* these are the overseer's words, appended under a `human:` actor to a
|
|
25
|
+
* hash-chained log, which is precisely the thing `[claimed]` exists to
|
|
26
|
+
* distinguish journal text FROM.
|
|
27
|
+
* - **It reads verified records and nothing else.** No policy is resolved, no
|
|
28
|
+
* clock is read, nothing is appended. A log that does not verify refuses with
|
|
29
|
+
* the log-* exit codes rather than showing a partial list, because a reaction
|
|
30
|
+
* read out of an unverifiable log is a sentence attributed to a person who may
|
|
31
|
+
* not have written it.
|
|
32
|
+
*
|
|
33
|
+
* `--actor` filters on the AGENT the feedback is about, not on the human who
|
|
34
|
+
* wrote it. That is the question an agent reading this actually has ("what has
|
|
35
|
+
* the operator said about my work"), and the human side is a small closed set
|
|
36
|
+
* that a `--source` filter already separates usefully.
|
|
37
|
+
*/
|
|
38
|
+
import type { Streams } from "./main.js";
|
|
39
|
+
/**
|
|
40
|
+
* The one line every output form carries.
|
|
41
|
+
*
|
|
42
|
+
* Exported because the guard tests assert it is on both renderings. A surface
|
|
43
|
+
* that stopped saying what these words are would be offering an agent a
|
|
44
|
+
* human's after-the-fact opinion in the same register as a policy rule, and the
|
|
45
|
+
* agent's correct reading of a policy rule is "this binds me". Nothing here
|
|
46
|
+
* binds anything: SPEC.md §11.1 invariant 10 says no enforcement path reads a
|
|
47
|
+
* reaction, and this sentence is how a reader learns that without going to the
|
|
48
|
+
* spec.
|
|
49
|
+
*/
|
|
50
|
+
export declare const FEEDBACK_BANNER = "HUMAN-AUTHORED GUIDANCE, not policy. A reaction records what the operator thought of an action after the fact; it grants nothing, forbids nothing, and changes no verdict, sampling probability or budget.";
|
|
51
|
+
/**
|
|
52
|
+
* `approval feedback [filters] [--log <path>] [--json]`.
|
|
53
|
+
*
|
|
54
|
+
* Reads and prints. There is no write half and there will not be one: the two
|
|
55
|
+
* verbs that record a reaction are `approval grant` and `approval audit review`,
|
|
56
|
+
* both human-only, and a third path into the same field that was not one of
|
|
57
|
+
* those would be a way for the party under oversight to author the operator's
|
|
58
|
+
* opinion of it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function commandFeedback(argv: string[], streams: Streams, cwd: string): number;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval gate open|close|status` — the open window's CLI (APRV-214, amended
|
|
3
|
+
* SPEC.md §5.2).
|
|
4
|
+
*
|
|
5
|
+
* As everywhere else in this CLI, no logic lives here. Deriving the window,
|
|
6
|
+
* checking the actor, the cap and the window state, and every append are
|
|
7
|
+
* `core/gate-window.ts`; this file resolves paths and identity, runs the
|
|
8
|
+
* ceremony, chooses an exit code, and formats output.
|
|
9
|
+
*
|
|
10
|
+
* ## The ceremony, and why it is shaped like this
|
|
11
|
+
*
|
|
12
|
+
* `open` suspends the harness gate's policy for every tool call under the root.
|
|
13
|
+
* Three locks stand between an agent and that, and they are independent:
|
|
14
|
+
*
|
|
15
|
+
* 1. **The class.** `approval gate open` classifies `policy.core`
|
|
16
|
+
* (`core/command-class.ts`), which APPROVAL.md holds human-only, so the
|
|
17
|
+
* harness hook denies the command before it ever runs.
|
|
18
|
+
* 2. **The terminal.** `createPrompter` returns `null` unless `process.stdin`
|
|
19
|
+
* is a TTY, and a harness shell tool has no TTY. `--json` refuses for the
|
|
20
|
+
* same reason: a machine-readable answer implies a machine asking.
|
|
21
|
+
* 3. **The word.** One line is read and only exactly `understood` proceeds.
|
|
22
|
+
* There is deliberately NO `--yes` and no `--force`: a flag that answers
|
|
23
|
+
* the question is a way for something that cannot type to type.
|
|
24
|
+
*
|
|
25
|
+
* `close` has none of it beyond the human actor, because closing only ever
|
|
26
|
+
* tightens, and a ceremony guarding the safe direction is one people learn to
|
|
27
|
+
* type past. `status` decides nothing and writes nothing.
|
|
28
|
+
*/
|
|
29
|
+
import type { Streams } from "./main.js";
|
|
30
|
+
import { type Prompter } from "./prompt.js";
|
|
31
|
+
/**
|
|
32
|
+
* Injected seams. `prompter` is the terminal, exactly as `commandSetup`'s is:
|
|
33
|
+
* a test passes a scripted one and asserts on what was asked as well as on what
|
|
34
|
+
* was done, and passing `null` is how "there is no terminal" becomes a test
|
|
35
|
+
* rather than a claim.
|
|
36
|
+
*/
|
|
37
|
+
export interface GateWindowDeps {
|
|
38
|
+
prompter?: Prompter | null;
|
|
39
|
+
}
|
|
40
|
+
export declare function commandGate(argv: string[], streams: Streams, cwd: string, deps?: GateWindowDeps): number;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate verbs of SPEC.md §10.1: `approval register`, `approval request`,
|
|
3
|
+
* `approval grant|reject|revoke`, and `approval expire`.
|
|
4
|
+
*
|
|
5
|
+
* As everywhere else in this CLI, **no logic lives here.** State derivation,
|
|
6
|
+
* transition legality, TTL arithmetic, attestation, and budgets are all
|
|
7
|
+
* `core/gate.ts`; frontmatter reading is `core/frontmatter.ts`; the append is
|
|
8
|
+
* `core/log.ts`. This file resolves paths and identity, chooses an exit code,
|
|
9
|
+
* and formats output.
|
|
10
|
+
*
|
|
11
|
+
* Four choices are load-bearing enough to state plainly.
|
|
12
|
+
*
|
|
13
|
+
* **A gate refusal is exit 1, not exit 2.** "You may not do that" is not a
|
|
14
|
+
* usage error — the command was well-formed, the runtime understood it, and the
|
|
15
|
+
* answer is no. Grouping refusals with typos would train agents to retry with
|
|
16
|
+
* different flags when the correct response is to ask a human. Exit 2 stays what
|
|
17
|
+
* it has always been: an unknown flag, a missing argument, an unresolvable
|
|
18
|
+
* identity. The frozen `error.code` inside `--json` is what a caller branches on
|
|
19
|
+
* to tell *which* refusal it was.
|
|
20
|
+
*
|
|
21
|
+
* **The log supplies the action's declaration, not flags.** `approval request
|
|
22
|
+
* <task> --action <key>` reads the action's class, cost, reversibility and
|
|
23
|
+
* summary from the `task.registered` record in the log — the same record
|
|
24
|
+
* `approval register` wrote from the envelope. There are no `--class` /
|
|
25
|
+
* `--cost` flags, deliberately: an agent that could name its own class at
|
|
26
|
+
* request time could declare `read.web` for an action registered as
|
|
27
|
+
* `financial.spend`, and SPEC.md §7's "class MUST be declared before a token can
|
|
28
|
+
* be requested" would mean nothing. Register once from the file; request against
|
|
29
|
+
* what was registered. A task file edited after registration is `envelope.drift`
|
|
30
|
+
* (M5), not a silent re-declaration.
|
|
31
|
+
*
|
|
32
|
+
* **`register` reads task files but never writes them.** Unknown frontmatter
|
|
33
|
+
* keys are preserved trivially here because nothing is rewritten at all;
|
|
34
|
+
* round-trip rewriting is M6.
|
|
35
|
+
*
|
|
36
|
+
* **grant / reject / revoke are human-only**, via `resolveHumanActor` — `--as
|
|
37
|
+
* human:<id>` or `APPROVAL_HUMAN`, refused at exit 2 when absent or when it
|
|
38
|
+
* names an agent. `expire` takes no identity at all: it is the system verb, and
|
|
39
|
+
* `core/gate.ts` stamps `system:gate`.
|
|
40
|
+
*
|
|
41
|
+
* **This layer no longer reads the clock.** It used to pass `new Date()` into
|
|
42
|
+
* every gate call; under amended SPEC.md §8 (A2) a gate-typed event's `ts` is
|
|
43
|
+
* assigned inside core at the write boundary, and there is no parameter here to
|
|
44
|
+
* pass one through. Nothing about determinism is lost — core reads an injected
|
|
45
|
+
* clock — and one caller-supplied-timestamp seam is gone.
|
|
46
|
+
*/
|
|
47
|
+
import { type Decision } from "../core/gate.js";
|
|
48
|
+
import type { Streams } from "./main.js";
|
|
49
|
+
export declare function commandRegister(argv: string[], streams: Streams, cwd: string): number;
|
|
50
|
+
export declare function commandRequest(argv: string[], streams: Streams, cwd: string): number;
|
|
51
|
+
export declare function commandDecide(decision: Decision, argv: string[], streams: Streams, cwd: string): number;
|
|
52
|
+
/**
|
|
53
|
+
* `approval withdraw <task> --action <key>` — the requester takes its own
|
|
54
|
+
* pending request back (APRV-106).
|
|
55
|
+
*
|
|
56
|
+
* Agent-facing, unlike every other terminal verb here: the whole point is that
|
|
57
|
+
* the party who asked can stop asking, and the party who asks is usually an
|
|
58
|
+
* agent. Identity resolves through {@link resolvePrincipalActor}, and the gate
|
|
59
|
+
* then checks it against the actor on the `approval.requested` record — so
|
|
60
|
+
* passing `--as` does not let a caller withdraw someone else's request, it only
|
|
61
|
+
* lets the caller say who it is.
|
|
62
|
+
*
|
|
63
|
+
* The task id is positional and the action key is a flag, matching
|
|
64
|
+
* `approval request` exactly: the two verbs are the open and the close of one
|
|
65
|
+
* gesture, and an agent that can spell one can spell the other.
|
|
66
|
+
*/
|
|
67
|
+
export declare function commandWithdraw(argv: string[], streams: Streams, cwd: string): number;
|
|
68
|
+
export declare function commandExpire(argv: string[], streams: Streams, cwd: string): number;
|
|
@@ -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 {};
|