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,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The task-file writer: round-trip rewriting that preserves everything it does
|
|
3
|
+
* not own (SPEC.md §6, APRV-61).
|
|
4
|
+
*
|
|
5
|
+
* SPEC.md §6 is a MUST: "Implementations MUST preserve unknown frontmatter keys
|
|
6
|
+
* when rewriting files." `core/frontmatter.ts` is the reader and is read-only in
|
|
7
|
+
* the strongest sense; this module is its counterpart, and the only place in the
|
|
8
|
+
* codebase that produces new task-file bytes.
|
|
9
|
+
*
|
|
10
|
+
* The bar is not "preserve the keys we can think of". Backlog.md 1.49.3 itself
|
|
11
|
+
* fails this MUST — the `envelope-edit-before` / `envelope-edit-after` fixtures
|
|
12
|
+
* record it dropping our whole `approval:` key on an unrelated `task edit` — and
|
|
13
|
+
* we extend that convention rather than fork it, so the writer that has to be
|
|
14
|
+
* trustworthy is ours.
|
|
15
|
+
*
|
|
16
|
+
* ## Why lines, not a YAML document
|
|
17
|
+
*
|
|
18
|
+
* The obvious implementation reserialises the frontmatter through the `yaml`
|
|
19
|
+
* library's Document API. It preserves more than a naive `parse`/`stringify`
|
|
20
|
+
* round trip, but it does not preserve *bytes*: quoting style, intra-line
|
|
21
|
+
* spacing, comment placement, and blank-line runs are all reconstructed from the
|
|
22
|
+
* library's own defaults. Every one of those is a spurious diff in a user's git
|
|
23
|
+
* history, and a diff nobody can explain is how a board tool's metadata gets
|
|
24
|
+
* quietly eaten.
|
|
25
|
+
*
|
|
26
|
+
* So this module treats the frontmatter as **lines with their terminators**, and
|
|
27
|
+
* the parsed YAML only as an oracle:
|
|
28
|
+
*
|
|
29
|
+
* - the hardened parser decides whether the block is *structurally* valid at
|
|
30
|
+
* all (and, being hardened, rejects duplicate keys, tags, and unbounded
|
|
31
|
+
* aliases before any of them can reach a rewrite);
|
|
32
|
+
* - a column-0 line scan finds the `approval:` key's line range;
|
|
33
|
+
* - only that range is rewritten, and for a state-only edit only the single
|
|
34
|
+
* `state:` line inside it;
|
|
35
|
+
* - every other line — every other key, its order, its quoting, its comments,
|
|
36
|
+
* the blank lines between them, both `---` delimiters, and the entire body
|
|
37
|
+
* after the closing delimiter — is re-emitted as the exact bytes that came
|
|
38
|
+
* in, terminator included.
|
|
39
|
+
*
|
|
40
|
+
* Byte-identity is therefore a property of the construction, not of a
|
|
41
|
+
* comparison performed afterwards: untouched lines are never parsed and never
|
|
42
|
+
* rebuilt. The corpus test (`tests/task-file.test.ts`) still asserts it against
|
|
43
|
+
* every real Backlog.md fixture, because a construction argument that is not
|
|
44
|
+
* checked is a construction argument that has already drifted.
|
|
45
|
+
*
|
|
46
|
+
* ## What "unknown key" means here
|
|
47
|
+
*
|
|
48
|
+
* Every frontmatter key except `approval:` is unknown to this writer, and that
|
|
49
|
+
* is deliberate. `id`, `title`, `status`, `milestone`, `ordinal`,
|
|
50
|
+
* `parent_task_id` and the rest belong to Backlog.md; a key some future board
|
|
51
|
+
* tool invents belongs to it. This module has no allow-list of keys it tolerates
|
|
52
|
+
* — it has one key it owns and rewrites, and it cannot express a change to
|
|
53
|
+
* anything else. There is no edit in {@link TaskFileEdit} that removes a key,
|
|
54
|
+
* reorders keys, or touches the body.
|
|
55
|
+
*
|
|
56
|
+
* ## This writer never touches the log
|
|
57
|
+
*
|
|
58
|
+
* A task file is a **projection** (SPEC.md §6.3): the daemon writes `state:`
|
|
59
|
+
* into the file *after* the event is appended, never the reverse. Nothing here
|
|
60
|
+
* opens `.approval/`, appends to `events.jsonl`, or computes a hash chain.
|
|
61
|
+
* {@link rewriteTaskFile} is a pure function of (bytes, edit) with no clock, no
|
|
62
|
+
* network, and no filesystem access at all; {@link writeTaskFileAtomic} writes
|
|
63
|
+
* exactly the one path it is handed.
|
|
64
|
+
*
|
|
65
|
+
* Determinism: same input bytes and same edit, same output bytes, always. Never
|
|
66
|
+
* throws — every failure is a structured result carrying one of the codes in
|
|
67
|
+
* {@link TaskFileErrorCode}.
|
|
68
|
+
*/
|
|
69
|
+
import type { EnvelopeState } from "../daemon/projection.js";
|
|
70
|
+
/** The frontmatter key this module owns. Everything else is preserved verbatim. */
|
|
71
|
+
export declare const ENVELOPE_KEY = "approval";
|
|
72
|
+
/** The schema id (`schema/envelope.schema.json`) the result is validated against. */
|
|
73
|
+
export declare const ENVELOPE_SCHEMA_ID = "envelope";
|
|
74
|
+
/**
|
|
75
|
+
* Why a rewrite was refused. Closed union, pinned by `tests/task-file.test.ts`:
|
|
76
|
+
* a caller distinguishing "this file has no envelope yet" from "this file is
|
|
77
|
+
* corrupt" must be able to do so mechanically.
|
|
78
|
+
*/
|
|
79
|
+
export type TaskFileErrorCode =
|
|
80
|
+
/** The file does not begin with a `---` line: no frontmatter to rewrite. */
|
|
81
|
+
"no-frontmatter"
|
|
82
|
+
/** An opening `---` with no closing `---` before end of file. */
|
|
83
|
+
| "unterminated"
|
|
84
|
+
/** The frontmatter is not parseable under the hardened YAML settings. */
|
|
85
|
+
| "yaml-error"
|
|
86
|
+
/** The frontmatter parsed, but not to a mapping. */
|
|
87
|
+
| "not-a-map"
|
|
88
|
+
/** A state edit was asked for and the file carries no `approval:` key. */
|
|
89
|
+
| "no-envelope"
|
|
90
|
+
/** An `approval:` key exists and its value is not a mapping. */
|
|
91
|
+
| "envelope-not-a-map"
|
|
92
|
+
/** The `approval:` block is not block-style mapping this writer can line-edit. */
|
|
93
|
+
| "unsupported-shape"
|
|
94
|
+
/** The envelope the edit would produce fails `envelope.schema.json`. */
|
|
95
|
+
| "invalid-envelope"
|
|
96
|
+
/** The envelope could not be serialised to YAML. */
|
|
97
|
+
| "serialize-failed"
|
|
98
|
+
/** Self-check: the rewritten bytes did not re-read as the intended document. */
|
|
99
|
+
| "round-trip-failed"
|
|
100
|
+
/** An unexpected throw, converted rather than propagated. */
|
|
101
|
+
| "internal-error"
|
|
102
|
+
/** {@link writeTaskFileAtomic} only: the bytes did not reach the disk. */
|
|
103
|
+
| "write-failed";
|
|
104
|
+
/** Outcome of {@link rewriteTaskFile}. */
|
|
105
|
+
export type RewriteResult = {
|
|
106
|
+
ok: true;
|
|
107
|
+
bytes: string;
|
|
108
|
+
changed: boolean;
|
|
109
|
+
} | {
|
|
110
|
+
ok: false;
|
|
111
|
+
code: TaskFileErrorCode;
|
|
112
|
+
message: string;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* The changes this writer can express. Deliberately tiny, and deliberately
|
|
116
|
+
* additive: there is no edit that removes the envelope, removes any other key,
|
|
117
|
+
* reorders keys, or reaches the body.
|
|
118
|
+
*
|
|
119
|
+
* - `none` — rewrite nothing. The output is the input, byte for byte, once the
|
|
120
|
+
* frontmatter has been confirmed structurally sound. Used to prove the reader
|
|
121
|
+
* and the writer agree on a file before anything is changed.
|
|
122
|
+
* - `set-state` — replace the value on the envelope's direct `state:` line
|
|
123
|
+
* (SPEC.md §6.3). Exactly one line of the file changes.
|
|
124
|
+
* - `set-envelope` — write the whole `approval:` subtree, inserting the key when
|
|
125
|
+
* the file has none.
|
|
126
|
+
*/
|
|
127
|
+
export type TaskFileEdit = {
|
|
128
|
+
kind: "none";
|
|
129
|
+
} | {
|
|
130
|
+
kind: "set-state";
|
|
131
|
+
state: EnvelopeState;
|
|
132
|
+
} | {
|
|
133
|
+
kind: "set-envelope";
|
|
134
|
+
envelope: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
/** Options accepted by {@link rewriteTaskFile}. */
|
|
137
|
+
export interface RewriteOptions {
|
|
138
|
+
/** Schema directory, forwarded to {@link validate}. Injectable for tests. */
|
|
139
|
+
schemaDir?: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Rewrite a task file's `approval:` subtree, preserving everything else byte for
|
|
143
|
+
* byte.
|
|
144
|
+
*
|
|
145
|
+
* Returns the new bytes, plus `changed` so a caller can skip a pointless write.
|
|
146
|
+
* On any refusal the input is untouched and nothing has been written anywhere:
|
|
147
|
+
* this function does not touch the filesystem at all.
|
|
148
|
+
*
|
|
149
|
+
* Insertion position (`set-envelope` on a file with no `approval:` key): the key
|
|
150
|
+
* is appended as the **last** top-level key, immediately before the closing
|
|
151
|
+
* delimiter. The corpus is the reason this needed a decision rather than a
|
|
152
|
+
* default. Backlog.md does not append its own new keys — in `milestone-assign/`
|
|
153
|
+
* the CLI put `milestone:` between `labels:` and `dependencies:`, because it
|
|
154
|
+
* rewrites frontmatter from its own model in its own canonical order — and at
|
|
155
|
+
* 1.49.3 it does not preserve unknown keys at all, so no position we pick
|
|
156
|
+
* survives its next edit. Given that no position is safe from the CLI, the
|
|
157
|
+
* choice is made on the diff: last keeps a multi-line block out of the middle of
|
|
158
|
+
* the board's short scalar keys, so inserting it moves no existing line, and it
|
|
159
|
+
* matches where the hand-written `envelope-edit-before` fixture put the envelope.
|
|
160
|
+
*/
|
|
161
|
+
export declare function rewriteTaskFile(text: string, edit: TaskFileEdit, options?: RewriteOptions): RewriteResult;
|
|
162
|
+
/** Outcome of {@link writeTaskFileAtomic}. */
|
|
163
|
+
export type WriteTaskFileResult = {
|
|
164
|
+
ok: true;
|
|
165
|
+
path: string;
|
|
166
|
+
bytes: number;
|
|
167
|
+
} | {
|
|
168
|
+
ok: false;
|
|
169
|
+
code: TaskFileErrorCode;
|
|
170
|
+
message: string;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Write task-file bytes atomically: temp file in the destination directory, then
|
|
174
|
+
* rename.
|
|
175
|
+
*
|
|
176
|
+
* The same idiom as `core/payload-store.ts` and `channels/render-queue.ts`, for
|
|
177
|
+
* the same reason: a reader — a board tool, an editor, the next agent — sees
|
|
178
|
+
* either the previous complete file or the new one, never a half-written task.
|
|
179
|
+
* The temp name is the only non-deterministic thing here and it never reaches
|
|
180
|
+
* the file's contents; it is removed on every failure path, so a failed write
|
|
181
|
+
* leaves no debris beside the task.
|
|
182
|
+
*
|
|
183
|
+
* Writes this one path and nothing else. It does not open the log.
|
|
184
|
+
*/
|
|
185
|
+
export declare function writeTaskFileAtomic(path: string, bytes: string): WriteTaskFileResult;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram configuration NAMES (SPEC.md §5.1 `channels.telegram.token_env` /
|
|
3
|
+
* `chat_id_env`, amended §5.2 by APRV-72).
|
|
4
|
+
*
|
|
5
|
+
* Constants and resolvers live in core, not in `channels/`, because more than
|
|
6
|
+
* one layer needs them: the Telegram CLI, doctor, and `approval env` (APRV-73)
|
|
7
|
+
* all ask "which variable holds the token?" and none of them may answer it
|
|
8
|
+
* differently. Placing them here also keeps `core/` free of any import from
|
|
9
|
+
* `channels/`, in the spirit of `tests/layering.test.ts`.
|
|
10
|
+
*
|
|
11
|
+
* NAMES only, in both directions: a policy that carried the token would be a
|
|
12
|
+
* bot credential in a file agents may read, which is exactly what §5.1's
|
|
13
|
+
* name-indirection exists to prevent. A policy that failed to load names
|
|
14
|
+
* nothing, so the default applies: a variable name is not a permission, and
|
|
15
|
+
* treating it as one would mean an unrelated policy typo locked the operator
|
|
16
|
+
* out of their own channel. This is `passphraseEnvFor`'s argument, verbatim,
|
|
17
|
+
* for the same reason: these are the same kind of key.
|
|
18
|
+
*
|
|
19
|
+
* Nothing here reads `process.env`. The CLI layer takes the name and looks
|
|
20
|
+
* the value up.
|
|
21
|
+
*/
|
|
22
|
+
import type { CredentialSpec } from "./credential-spec.js";
|
|
23
|
+
import type { PolicyLoadResult } from "./policy-load.js";
|
|
24
|
+
/**
|
|
25
|
+
* The environment variable the bot token is read from when the policy declares
|
|
26
|
+
* no `channels.telegram.token_env`. A DEFAULT, not a fixed name: see
|
|
27
|
+
* {@link telegramTokenEnvFor}.
|
|
28
|
+
*/
|
|
29
|
+
export declare const TELEGRAM_TOKEN_ENV = "APPROVAL_TG_TOKEN";
|
|
30
|
+
/**
|
|
31
|
+
* The environment variable the approver chat id is read from when the policy
|
|
32
|
+
* declares no `channels.telegram.chat_id_env`. Also a default.
|
|
33
|
+
*/
|
|
34
|
+
export declare const TELEGRAM_CHAT_ENV = "APPROVAL_TG_CHAT";
|
|
35
|
+
/** The NAME of the variable this policy says the bot token lives in. */
|
|
36
|
+
export declare function telegramTokenEnvFor(load: PolicyLoadResult): string;
|
|
37
|
+
/** The NAME of the variable this policy says the approver chat id lives in. */
|
|
38
|
+
export declare function telegramChatEnvFor(load: PolicyLoadResult): string;
|
|
39
|
+
/**
|
|
40
|
+
* How a listener puts the pending set in front of the approver (APRV-216).
|
|
41
|
+
*
|
|
42
|
+
* `paced` sends one summary line and the oldest pending request, and the next
|
|
43
|
+
* one only once that request is decided, skipped, or passed over. `burst` is
|
|
44
|
+
* the pre-APRV-216 behaviour: every pending request this process has not sent
|
|
45
|
+
* yet, on every cycle, behind the APRV-196 re-delivery banner.
|
|
46
|
+
*
|
|
47
|
+
* Not a credential and not a name, so it sits beside the two that are for one
|
|
48
|
+
* reason: it is the third thing a caller asks the policy about the Telegram
|
|
49
|
+
* channel, and a second resolver module would be a second place for the
|
|
50
|
+
* fallback rule to drift.
|
|
51
|
+
*/
|
|
52
|
+
export type TelegramDelivery = "paced" | "burst";
|
|
53
|
+
/**
|
|
54
|
+
* What an absent `channels.telegram.delivery` means.
|
|
55
|
+
*
|
|
56
|
+
* Paced, since APRV-216. The incident behind it is the one APRV-196 softened
|
|
57
|
+
* rather than closed: a restart with six pending policy edits put six prompts
|
|
58
|
+
* on a phone at once, and an approver reading a wall of near-identical
|
|
59
|
+
* questions is an approver who taps rather than reads. A default is a claim
|
|
60
|
+
* about which failure is worse, and the worse one here is inattentive approval
|
|
61
|
+
* rather than a slower queue: pacing withholds nothing, because every request
|
|
62
|
+
* stays pending in the log whether or not it has been shown, and `/queue`
|
|
63
|
+
* lists the whole set on demand.
|
|
64
|
+
*/
|
|
65
|
+
export declare const TELEGRAM_DEFAULT_DELIVERY: TelegramDelivery;
|
|
66
|
+
/**
|
|
67
|
+
* The delivery mode this policy declares, or the default.
|
|
68
|
+
*
|
|
69
|
+
* Fail-soft in the same direction as the two name resolvers above: a policy
|
|
70
|
+
* that did not load declares nothing, and a delivery mode is not a permission,
|
|
71
|
+
* so an unrelated policy typo must not decide how requests are shown. The
|
|
72
|
+
* schema closes the enum, so a policy that LOADED can only carry one of the
|
|
73
|
+
* two; anything else reaching here (a hand-built load result, a key from a
|
|
74
|
+
* later version) falls back rather than being guessed at.
|
|
75
|
+
*/
|
|
76
|
+
export declare function telegramDeliveryFor(load: PolicyLoadResult): TelegramDelivery;
|
|
77
|
+
/**
|
|
78
|
+
* The Telegram channel's credential manifest (APRV-79).
|
|
79
|
+
*
|
|
80
|
+
* The same shape an adapter declares (`core/credential-spec.ts`), for the same
|
|
81
|
+
* reason: `approval setup channel telegram` runs the shared conversation in
|
|
82
|
+
* `cli/setup-flow.ts`, and that conversation is DERIVED from a manifest. What
|
|
83
|
+
* differs from an adapter's is the destination and not the vocabulary — a
|
|
84
|
+
* channel's two values go to the OS keystore and `.approval/env`, because a
|
|
85
|
+
* channel holds no state and its token is what unlocks the machine, while an
|
|
86
|
+
* adapter's go to the vault (SPEC.md §4, §10.3, §10.4).
|
|
87
|
+
*
|
|
88
|
+
* The NAMES are the policy's, resolved through the two functions above, so the
|
|
89
|
+
* checklist an operator reads names the variables their own policy declares.
|
|
90
|
+
* A spec carries no value and no default on either entry: the token is the
|
|
91
|
+
* operator's and the chat id is discovered.
|
|
92
|
+
*/
|
|
93
|
+
export declare function telegramCredentialSpecs(load: PolicyLoadResult): CredentialSpec[];
|