approval-md 0.0.1

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.
Files changed (4) hide show
  1. package/README.md +6 -0
  2. package/SPEC.md +340 -0
  3. package/cli.js +4 -0
  4. package/package.json +10 -0
package/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # approval-md
2
+
3
+ Human approval for agent actions: pre-release placeholder for the
4
+ approval.md runtime. The full specification is in SPEC.md.
5
+
6
+ Spec site: https://approval.md
package/SPEC.md ADDED
@@ -0,0 +1,340 @@
1
+ # approval.md
2
+
3
+ **Human approval for agent actions.**
4
+
5
+ Version: 0.1.0-draft · Status: Draft · License: MIT · Canonical URL: https://approval.md
6
+
7
+ > Your AGENTS.md says "require approval first." approval.md enforces it, and puts the approve button on your phone.
8
+
9
+ ---
10
+
11
+ ## 1. Abstract
12
+
13
+ approval.md is a file-based convention and reference runtime for gating AI agent actions that have real-world side effects: sending messages, spending money, deleting data, posting publicly, writing to calendars. It defines:
14
+
15
+ 1. **`APPROVAL.md`**, a human-authored policy file that declares which classes of side effect an agent may perform autonomously, which require human sign-off, and under what budgets.
16
+ 2. **An agentic envelope**, a namespaced YAML frontmatter extension for markdown task files (compatible with [Backlog.md](https://github.com/MrLesk/Backlog.md)) declaring a task's origin, routing, side effects, budget, and approval state.
17
+ 3. **An append-only event log** (JSONL, hash-chained) as the tamper-evident source of truth for every proposal, decision, and execution.
18
+ 4. **A daemon and CLI** that watch a task folder, route tasks by declared side effects, push approval requests to pluggable channels (Telegram is the reference adapter), and gate execution on granted approvals.
19
+
20
+ Design mantra: **files are the interface, the log is the truth, the database is a cache.**
21
+
22
+ ## 2. Motivation and gap
23
+
24
+ Agents now produce more actions than a human can review. The coding world solved its version of this problem: [Backlog.md](https://github.com/MrLesk/Backlog.md), Taskmaster, and Vibe Kanban let you review an agent's *intent* (acceptance criteria before, implementation notes after) instead of every diff, and a bad merge is revertible anyway.
25
+
26
+ Once agents leave the repo, that safety net disappears. A sent email, a payment, a deleted account, a public post: there is no diff to revert. The artifact that must be reviewed *before* execution stops being the plan and becomes the **side-effect declaration**.
27
+
28
+ The ecosystem has converged on prose versions of this idea without an enforcement layer:
29
+
30
+ - [AGENTS.md](https://agents.md) files routinely contain permissions sections splitting actions into "allowed without prompting" and "require approval first" (package installs, `git push`, file deletion, `terraform apply`). These lists are instructions the agent is trusted to obey. Nothing checks.
31
+ - [HumanLayer](https://github.com/humanlayer/humanlayer) provides approval-as-a-service SDKs (`require_approval()` routed to Slack/email/SMS), but couples approval to a hosted service and an in-process decorator rather than a portable, inspectable file convention.
32
+ - [LangGraph interrupts](https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/) and the [OpenAI Agents SDK human-in-the-loop flow](https://openai.github.io/openai-agents-js/guides/human-in-the-loop/) pause a graph for approval, but the approval state lives inside one framework's runtime and dies at its boundary.
33
+ - [Google's A2A protocol](https://a2a-protocol.org) models an `input-required` task state, and [MCP](https://modelcontextprotocol.io) has elicitation and an experimental tasks extension, but neither defines what *deserves* escalation, budgets, or a durable audit record.
34
+ - [mission-control](https://github.com/MeisnerDan/mission-control) ships autonomy levels, spend limits, and an approval inbox, but as a closed-world product with its own mutable JSON store: no interchange, and an audit trail that anything with file access can rewrite.
35
+ - Task data standards ([RFC 8984 jsCalendar](https://www.rfc-editor.org/rfc/rfc8984), [RFC 5545 iCalendar VTODO](https://www.rfc-editor.org/rfc/rfc5545)) model due dates and recurrence, and predate the questions "which agent may do this, what will it cost, and who signed off?"
36
+
37
+ The gap: **a portable, file-based, framework-agnostic layer that turns "ask first" from prose into a checked invariant, with a tamper-evident record of who approved what.** approval.md fills exactly that gap and nothing more.
38
+
39
+ ## 3. Design principles
40
+
41
+ 1. **Files are the interface.** Policy, tasks, and rendered views are markdown a human can read in any editor and an agent can read with `cat`. No required server to inspect state.
42
+ 2. **The log is the truth.** All state transitions are immutable events in an append-only, hash-chained JSONL log. Markdown files and databases are projections rebuilt from it.
43
+ 3. **Approval state is data; channels are transport.** A pending approval is a fact in the log. Telegram, the local web queue, and the CLI are interchangeable notifiers, never owners of state.
44
+ 4. **Deterministic logic in code, LLMs for language only.** Routing, gating, budget math, and log verification are deterministic. Models may *propose* (draft an email, suggest a route); the runtime *decides* per policy.
45
+ 5. **CLI-first agent interface.** Agents interact through a CLI whose schemas and instructions ship in `--help` (a lesson from Backlog.md's [MCP retreat](https://mrlesk.dev)). MCP is a thin optional wrapper over the same commands.
46
+ 6. **Extend, don't replace.** Task files are Backlog.md-format markdown; the envelope is one namespaced frontmatter key. AGENTS.md permissions sections import as policy. No new task format is invented.
47
+ 7. **Honest security.** This is an oversight layer for broadly cooperative agents, with hard enforcement only at adapter boundaries that hold the credentials. The threat model (§11) says exactly what is and is not defended.
48
+
49
+ The keywords MUST, SHOULD, MAY are per [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119).
50
+
51
+ ## 4. Terminology
52
+
53
+ | Term | Meaning |
54
+ |---|---|
55
+ | **Action** | A single side-effecting operation an agent wants to perform (send one email, make one payment). |
56
+ | **Task** | A markdown file describing work; may spawn multiple actions. |
57
+ | **Side-effect class** | A dotted-namespace label for a category of action, e.g. `communicate.email.external`. |
58
+ | **Policy** | The rules in `APPROVAL.md` mapping classes to autonomy levels, approvers, and budgets. |
59
+ | **Autonomy level** | `manual` (approval required per action), `supervised` (proceed, but sampled for retrospective review), `autonomous` (proceed silently). |
60
+ | **Approval** | A recorded human decision (`granted` / `rejected`) on a specific requested action. |
61
+ | **Execution token** | A single-use token minted on grant, required by adapters to execute. |
62
+ | **Channel** | A transport plugin that surfaces requests and collects decisions (Telegram, local web, CLI). |
63
+ | **Adapter** | A side-effect executor (email sender, calendar writer) that holds credentials and refuses to act without a valid token. |
64
+ | **Projection** | Any derived view of the log: the queue file, the SQLite index, the web UI. |
65
+
66
+ ## 5. The `APPROVAL.md` policy file
67
+
68
+ `APPROVAL.md` lives at the root of a project (or `~/.approval/APPROVAL.md` for a global personal policy). It is prose for humans plus exactly one fenced ` ```yaml approval-policy ` block for machines. Implementations MUST parse the fenced block and MUST ignore surrounding prose. Implementations MUST also accept the filename `APPROVALS.md` as a fallback, with `APPROVAL.md` taking precedence when both exist.
69
+
70
+ ### 5.1 Canonical example
71
+
72
+ ````markdown
73
+ # Approval Policy
74
+
75
+ Agents working in this project handle my life admin. Anything that leaves
76
+ the machine gets declared, and the classes below say what I sign off on.
77
+
78
+ ```yaml approval-policy
79
+ version: "0.1"
80
+
81
+ defaults:
82
+ autonomy: manual # unknown/undeclared classes require sign-off
83
+ channel: telegram
84
+ approval_ttl: 24h # pending requests expire
85
+ on_expiry: reject
86
+
87
+ approvers:
88
+ carter:
89
+ channels: [telegram, cli]
90
+
91
+ classes:
92
+ read.*: { autonomy: autonomous }
93
+ files.write.workspace: { autonomy: autonomous }
94
+ calendar.write.own: { autonomy: supervised }
95
+ communicate.email.draft: { autonomy: autonomous }
96
+ communicate.email.external:
97
+ autonomy: manual
98
+ approvers: [carter]
99
+ financial.spend:
100
+ autonomy: manual
101
+ approvers: [carter]
102
+ limits: { per_action_usd: 25, daily_usd: 100 }
103
+ public.post: { autonomy: manual }
104
+ data.delete: { autonomy: manual }
105
+ account.auth: { autonomy: manual }
106
+
107
+ budgets:
108
+ global: { daily_usd: 100, daily_actions: 200 }
109
+
110
+ audit:
111
+ supervised_sample_rate: 0.10 # fraction of supervised actions escalated
112
+ # for retrospective human review
113
+
114
+ channels:
115
+ telegram:
116
+ chat_id_env: APPROVAL_TG_CHAT
117
+ token_env: APPROVAL_TG_TOKEN
118
+ web:
119
+ port: 4680
120
+ ```
121
+ ````
122
+
123
+ ### 5.2 Policy semantics
124
+
125
+ - **Matching.** Classes match most-specific-first; `*` is a single-segment wildcard, a trailing `.*` matches any depth. An action whose class matches no rule takes `defaults.autonomy`. Implementations MUST fail closed: unparseable policy means everything is `manual`.
126
+ - **Deny beats allow.** If multiple rules match at equal specificity, the strictest autonomy wins (`manual` > `supervised` > `autonomous`).
127
+ - **Budgets are conjunctive.** An action must pass its class limits AND global budgets. Budget consumption is computed from the log, never from a mutable counter.
128
+ - **`supervised_sample_rate`** implements auditing under a budget: supervised actions execute immediately, and a deterministic pseudo-random sample (seeded from the event hash, so it is reproducible and unguessable in advance by the agent) is queued for after-the-fact human review. See §11 for why.
129
+ - **Agents MUST NOT be able to modify `APPROVAL.md`, the log, or channel credentials.** The reference runtime refuses to mint tokens if the policy file's mtime/hash changed without a signed `policy.updated` event from a human session.
130
+
131
+ ## 6. The task envelope
132
+
133
+ Task files are ordinary Backlog.md-style markdown (`backlog/task-042 - Chase-deposit.md` and similar). approval.md adds one frontmatter key, `approval:`, holding the entire envelope. Implementations MUST preserve unknown frontmatter keys when rewriting files, and MUST tolerate tasks with no envelope (they simply cannot request side-effecting execution).
134
+
135
+ ### 6.1 Canonical example
136
+
137
+ Note the canonical example is an email, deliberately. This spec governs agent actions in the world; it is unrelated to PR review, CODEOWNERS, or release sign-off.
138
+
139
+ ```yaml
140
+ ---
141
+ id: task-042
142
+ title: Chase deposit refund from letting agency
143
+ status: In Progress # owned by Backlog.md / your board
144
+ approval:
145
+ origin:
146
+ app: cartsos # provenance: which system created this
147
+ created_by: "human:carter" # or "agent:<id>"
148
+ route:
149
+ assignee: "agent:claude-admin"
150
+ confidence: 0.82
151
+ rationale: "templated chaser, known counterparty, no negotiation"
152
+ state: awaiting # see §6.3
153
+ actions:
154
+ - class: communicate.email.external
155
+ summary: "Send deposit chaser to agency@example.co.uk"
156
+ reversible: false
157
+ est_cost_usd: 0.02
158
+ idempotency_key: "task-042:chaser:2026-08-04"
159
+ budget:
160
+ max_cost_usd: 0.50
161
+ max_latency: 6h
162
+ ---
163
+
164
+ ## Description
165
+ Deposit (£1,200) due back since 12 July. One polite chaser sent by me on
166
+ 21 July, no reply. Agent should send a firmer follow-up citing the
167
+ deposit-protection scheme deadline.
168
+
169
+ ## Acceptance Criteria
170
+ - [ ] Email sent to the agency referencing scheme deadline
171
+ - [ ] Reply, if any, filed back onto this task
172
+ ```
173
+
174
+ ### 6.2 Envelope fields
175
+
176
+ | Field | Req | Meaning |
177
+ |---|---|---|
178
+ | `origin.app` | MUST | Source system (`cartsos`, `jobmaxxing`, `manual`, …). |
179
+ | `origin.created_by` | MUST | `human:<id>` or `agent:<id>`. |
180
+ | `route.assignee` | SHOULD | `human` or `agent:<id>`. Routing proposals from agents are events, never silent edits. |
181
+ | `route.confidence` | MAY | 0.0–1.0; used as a monitoring signal (§11). |
182
+ | `state` | MUST | Approval lifecycle state (§6.3), distinct from board `status`. |
183
+ | `actions[]` | MUST for execution | Each declared action: `class`, `summary`, `reversible`, `est_cost_usd`, `idempotency_key`. |
184
+ | `budget` | MAY | Task-level caps, conjunctive with policy budgets. |
185
+ | `idempotency_key` | MUST per action | Stable string; adapters MUST refuse to execute the same key twice. |
186
+
187
+ ### 6.3 Approval lifecycle
188
+
189
+ ```
190
+ proposed ──▶ awaiting ──▶ approved ──▶ executed
191
+ │ │
192
+ │ └─▶ revoked (human, before execution)
193
+ ├─▶ rejected
194
+ └─▶ expired (TTL, per on_expiry)
195
+ ```
196
+
197
+ `state` is a **projection** of log events; the file is updated by the daemon after the event is appended, never the reverse. A file edit that contradicts the log is itself logged (`envelope.drift`) and surfaced.
198
+
199
+ ## 7. Side-effect taxonomy (v0.1)
200
+
201
+ Dotted, hierarchical, extensible. Top-level namespaces are reserved by this spec; implementations MAY add sub-classes freely and SHOULD upstream common ones.
202
+
203
+ | Namespace | Examples | Default gravity |
204
+ |---|---|---|
205
+ | `read.*` | web fetch, file read, API GET | autonomous |
206
+ | `files.write.*` | workspace writes, repo commits | autonomous/supervised |
207
+ | `communicate.*` | `.email.external`, `.message.telegram`, `.email.draft` | manual for external sends |
208
+ | `calendar.write.*` | own calendar, shared calendar | supervised |
209
+ | `financial.*` | `.spend`, `.transfer`, `.subscribe` | manual, always |
210
+ | `public.*` | `.post` (X, forums), `.publish` | manual, always |
211
+ | `data.delete` | destructive deletes outside workspace | manual, always |
212
+ | `account.*` | `.auth`, `.create`, `.credential` | manual, always |
213
+ | `physical.*` | orders, bookings with cancellation cost | manual |
214
+
215
+ Two invariants: an action's class MUST be declared before an execution token can be requested for it, and `reversible: false` actions MUST NOT be eligible for `autonomous` regardless of policy (the runtime enforces this floor).
216
+
217
+ ## 8. The event log
218
+
219
+ `.approval/log/events.jsonl`, append-only. One JSON object per line:
220
+
221
+ ```json
222
+ {"seq":17,"ts":"2026-08-04T09:14:02Z","event":"approval.granted",
223
+ "task":"task-042","action_key":"task-042:chaser:2026-08-04",
224
+ "actor":"human:carter","channel":"telegram",
225
+ "payload":{"note":"go, but cc me"},
226
+ "prev":"b3c9…","hash":"a41f…"}
227
+ ```
228
+
229
+ - `hash` = SHA-256 over the canonical serialization of the record with `prev` included; `prev` = previous record's hash. `approval log verify` MUST detect any mutation or truncation. Optionally, the log directory is a git repo and the daemon commits per event with its own identity, giving signed, distributed tamper evidence for free (the [TaskChampion operation log](https://github.com/GothenburgBitFactory/taskchampion) and [Automerge](https://automerge.org) both converged on op-logs for related reasons; see also Ink & Switch's [local-first task framework](https://www.inkandswitch.com/patchwork/notebook/tasks-01/)).
230
+ - **Event types (v0.1):** `task.registered`, `route.proposed`, `route.accepted`, `approval.requested`, `approval.granted`, `approval.rejected`, `approval.expired`, `approval.revoked`, `execution.started`, `execution.completed`, `execution.failed`, `budget.exceeded`, `policy.updated`, `envelope.drift`, `audit.sampled`, `audit.reviewed`.
231
+ - Events MUST validate against the JSON Schemas in `schema/` before append. Validation at the write boundary is itself a control: an agent physically cannot request execution without declaring a class, key, and cost estimate.
232
+
233
+ ## 9. Projections
234
+
235
+ 1. **The queue** (`.approval/QUEUE.md`): a rendered, read-only markdown view of pending requests (task, actions, declared effects, cost, TTL countdown) plus the sampled-audit backlog. Regenerated on every relevant event. This is the screenshot; it is never the truth.
236
+ 2. **The index** (`.approval/index.sqlite`): rebuilt from the log (`approval reindex`), used for queries like "pending manual approvals touching `financial.*`, oldest first." Any SQLite client, including DuckDB, can read it; deleting it loses nothing.
237
+
238
+ ## 10. Runtime
239
+
240
+ ### 10.1 CLI (primary interface, for humans and agents)
241
+
242
+ ```
243
+ approval init # scaffold APPROVAL.md, .approval/, schemas
244
+ approval instructions # full agent-facing usage guide (also in --help)
245
+ approval register <task-file> # validate envelope, append task.registered
246
+ approval request <task> [--action <key>] # -> approval.requested (or auto-grant
247
+ # per policy for supervised/autonomous)
248
+ approval wait <task> --timeout 6h # block until decided; exit code = decision
249
+ approval grant|reject|revoke <request-id> [--note …] # human-only verbs
250
+ approval token <action-key> # print single-use execution token if granted
251
+ approval run -- <cmd…> # gate arbitrary commands: mints token, runs, logs
252
+ approval queue [--json] # pending requests
253
+ approval log verify | tail | export
254
+ approval policy check|test <class> # explain what policy does with a class
255
+ approval reindex | render
256
+ ```
257
+
258
+ Machine-readable output: every command supports `--json`; schemas for inputs and outputs are printed by `approval instructions --schemas`.
259
+
260
+ ### 10.2 Daemon
261
+
262
+ `approvald` watches the backlog folder and the log: validates new/changed envelopes, applies policy, dispatches channel notifications, expires TTLs, samples supervised actions for audit, re-renders projections, and (optionally) polls upstream sources. Loop safety: three consecutive `execution.failed` events for one task escalate to `manual` regardless of policy.
263
+
264
+ ### 10.3 Channels
265
+
266
+ Interface: `notify(request) -> delivery_id`, `poll()/webhook() -> decision`. Decisions become log events; channels hold no state. v0.1 ships **cli** (zero-config prompt), **web** (local queue page with grant/reject), and **telegram** (reference push channel: message with declared effects + inline Approve/Reject buttons; callback verified against approver identity). Channel breadth is explicitly out of scope; HumanLayer exists for Slack/email/SMS enterprises.
267
+
268
+ ### 10.4 Adapters and hard enforcement
269
+
270
+ Adapters (e.g. `adapter-email`, `adapter-gcal`) hold the actual credentials in an encrypted vault and MUST require a valid, unexpired, single-use execution token bound to the action's `idempotency_key`. This is the hard boundary: an agent that bypasses the CLI still cannot send, spend, or delete, because the credentials only answer to tokens. (Same architectural intuition as mission-control's vault + "agents cannot modify security settings.")
271
+
272
+ ### 10.5 MCP wrapper (optional)
273
+
274
+ A thin MCP server exposing the same verbs as tools (`request_approval`, `wait_decision`, `get_queue`, …) for clients where MCP is more ergonomic than shelling out. It shares the CLI's code paths; the [MCP tasks extension](https://modelcontextprotocol.io) MAY be mapped onto `awaiting` when client support stabilizes, and A2A's `input-required` maps cleanly for agent-to-agent deployments.
275
+
276
+ ## 11. Security and control model
277
+
278
+ approval.md operationalizes, at consumer scale, the structure of trusted monitoring with limited auditing from the AI-control literature ([Greenblatt et al., 2023](https://arxiv.org/abs/2312.06942)):
279
+
280
+ - The **untrusted policy** is the agent proposing actions.
281
+ - **Affordance restrictions** are the adapter/token boundary plus the taxonomy: undeclared classes cannot execute.
282
+ - The **trusted, expensive overseer** is the human, whose limited attention is the audit budget; `manual` classes spend it before execution, `supervised_sample_rate` spends it retrospectively.
283
+ - The **monitoring signal** is deterministic policy (class, cost, reversibility) plus `route.confidence`; escalation is triggered by the runtime, never self-assessed by the executing agent at execution time.
284
+ - The **audit trail** is the hash-chained log, which the agent cannot rewrite undetected.
285
+
286
+ **Defended:** honest-mistake side effects, prompt-injected instructions that try to escalate side effects silently, retries double-executing (idempotency keys), quiet budget creep, after-the-fact disputes about who approved what, tampering with history.
287
+
288
+ **Not defended, stated plainly:** an agent with direct credential access outside adapters; a compromised host; deceptive *content* inside an approved action (you approve "send email," the runtime does not verify the prose is honest, though channels SHOULD display full content for `manual` actions); collusion between agent and a careless approver; and this is engineering informed by control research, offering no guarantees against a schemer that control protocols proper are designed to stress-test. Keep `manual` floors on irreversible classes.
289
+
290
+ ## 12. Interoperability
291
+
292
+ - **Backlog.md:** native. Tasks live in `backlog/`, the envelope is one preserved frontmatter key, board `status` and approval `state` are independent. approval.md ships no board; use Backlog.md's.
293
+ - **AGENTS.md import:** `approval import agents-md` parses "require approval first / allowed without prompting" permissions sections into draft policy classes for human confirmation, turning existing prose conventions into enforced policy.
294
+ - **Inbound adapters (post-v1):** CartsOS/Telegram capture, arbitrary apps via `approval register --json`.
295
+ - **Outbound sinks (post-v1):** approved+scheduled tasks mirrored to TickTick / Google Tasks / Google Calendar as views, never sources of truth. Mapping via [RFC 8984 jsCalendar Task](https://www.rfc-editor.org/rfc/rfc8984) with the envelope as a vendor extension, `X-APPROVAL-*` in [VTODO](https://www.rfc-editor.org/rfc/rfc5545).
296
+
297
+ ## 13. Non-goals
298
+
299
+ No new task file format. No kanban UI. No agent framework or orchestration platform. No hosted service (local-first; a sync story can come later). No channel breadth beyond the three shipped. No claim of scheming-robustness (§11).
300
+
301
+ ## 14. Repository layout and roadmap
302
+
303
+ ```
304
+ approval.md/
305
+ ├── SPEC.md # this file
306
+ ├── APPROVAL.md # this repo's own policy (dogfood from day one)
307
+ ├── schema/ # JSON Schemas: policy, envelope, each event type
308
+ ├── src/ # runtime: core/ (log, policy, gate), cli/, daemon/,
309
+ │ # channels/{cli,web,telegram}/, adapters/, mcp/
310
+ ├── examples/ # personal-admin/, backlog-md-project/, agents-md-import/
311
+ └── tests/ # log verification, policy matching, gating, TTL, idempotency
312
+ ```
313
+
314
+ Milestones sized for agent-driven development (each = one reviewable task):
315
+
316
+ - **M0** Schemas for policy, envelope, events + fixtures.
317
+ - **M1** Log: append, hash-chain, verify, reindex.
318
+ - **M2** Policy engine: parse, match, explain (`policy test`), fail-closed.
319
+ - **M3** Gate: request/grant/reject/expire, tokens, idempotency, `approval run`.
320
+ - **M4** Channels: cli, web queue, Telegram; QUEUE.md renderer.
321
+ - **M5** Daemon: watch, TTL, sampling, loop-escalation.
322
+ - **M6** Backlog.md round-trip + AGENTS.md import.
323
+ - **M7** First adapter (email) + vault; end-to-end demo: agent drafts chaser → Telegram ping → approve from phone → sent → log verifies.
324
+ - **M8** MCP wrapper. Post-v1: TickTick/GCal sinks, CartsOS inbound.
325
+
326
+ ## 15. References
327
+
328
+ Backlog.md · https://github.com/MrLesk/Backlog.md — the markdown-task convention this extends
329
+ AGENTS.md · https://agents.md — the prose permissions this enforces
330
+ HumanLayer · https://github.com/humanlayer/humanlayer — approval-as-a-service (SDK/hosted counterpart)
331
+ LangGraph HITL · https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/
332
+ OpenAI Agents SDK HITL · https://openai.github.io/openai-agents-js/guides/human-in-the-loop/
333
+ A2A protocol · https://a2a-protocol.org — `input-required` lifecycle state
334
+ Model Context Protocol · https://modelcontextprotocol.io
335
+ mission-control · https://github.com/MeisnerDan/mission-control — autonomy levels, vault, spend limits
336
+ AI Control (Greenblatt et al., 2023) · https://arxiv.org/abs/2312.06942 — trusted monitoring under an audit budget
337
+ TaskChampion · https://github.com/GothenburgBitFactory/taskchampion — operation-log task storage
338
+ Ink & Switch, A Local-First Task Framework · https://www.inkandswitch.com/patchwork/notebook/tasks-01/
339
+ jsCalendar · https://www.rfc-editor.org/rfc/rfc8984 · iCalendar · https://www.rfc-editor.org/rfc/rfc5545
340
+ RFC 2119 · https://www.rfc-editor.org/rfc/rfc2119
package/cli.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ console.log("approval.md: human approval for agent actions.");
3
+ console.log("Pre-release. Spec: https://approval.md");
4
+ console.log("Repo: https://github.com/approval-md");
package/package.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "approval-md",
3
+ "version": "0.0.1",
4
+ "description": "Human approval for agent actions. CLI runtime for the approval.md convention (pre-release).",
5
+ "bin": { "approval": "./cli.js" },
6
+ "files": ["cli.js", "SPEC.md", "README.md"],
7
+ "repository": "github:approval-md/approval.md",
8
+ "homepage": "https://approval.md",
9
+ "license": "MIT"
10
+ }