docket-agent 0.1.0 → 0.2.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.
- package/README.md +72 -2
- package/package.json +1 -1
- package/spec/SPEC.md +11 -1
- package/src/cli.js +9 -1
- package/src/commands/record.js +3 -0
- package/src/commands/review.js +0 -0
package/README.md
CHANGED
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
Before your agent acts, it checks a one-page rule file you wrote: allow, ask,
|
|
8
8
|
or deny. After, it leaves a tamper-evident record. Anything you didn't write
|
|
9
9
|
down, the agent must ask about. Plain Markdown in your repo; works with
|
|
10
|
-
Claude, Codex, Cursor, and any MCP client.
|
|
10
|
+
Claude, ChatGPT/Codex, Gemini, Cursor, OpenClaw, Hermes, and any MCP client.
|
|
11
|
+
|
|
12
|
+
**Install:** `npm install -g docket-agent` · **Docs:**
|
|
13
|
+
[shahcolate.github.io/docket/docs.html](https://shahcolate.github.io/docket/docs.html)
|
|
11
14
|
|
|
12
15
|
Zero dependencies · plain Markdown + JSONL · MIT
|
|
13
16
|
|
|
@@ -202,6 +205,47 @@ The agent gets four tools:
|
|
|
202
205
|
Warrant checks made by the agent land in the record too. *"Did the agent
|
|
203
206
|
even ask?"* becomes a grep.
|
|
204
207
|
|
|
208
|
+
## OpenClaw and Hermes
|
|
209
|
+
|
|
210
|
+
**[OpenClaw](https://docs.openclaw.ai)** injects your workspace's `AGENTS.md`
|
|
211
|
+
into the agent's system prompt at the start of every session — so compile
|
|
212
|
+
straight into the workspace (fitting, given the story that opens this README):
|
|
213
|
+
|
|
214
|
+
```console
|
|
215
|
+
$ cd ~/.openclaw/workspace
|
|
216
|
+
$ npx docket-agent init
|
|
217
|
+
$ npx docket-agent new followup --template client-follow-up
|
|
218
|
+
$ npx docket-agent compile --target agents --write
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Docket only manages its own marked block inside `AGENTS.md` — your existing
|
|
222
|
+
rules, `SOUL.md`, and the rest of the workspace stay untouched. OpenClaw can
|
|
223
|
+
also run the MCP server for native checks and record entries: add `docket`
|
|
224
|
+
as an MCP server in your OpenClaw config with
|
|
225
|
+
`command: npx, args: ["-y", "docket-agent", "mcp", "--dir", "~/.openclaw/workspace"]`.
|
|
226
|
+
|
|
227
|
+
**[Hermes](https://hermes-agent.nousresearch.com/docs/)** (Nous Research)
|
|
228
|
+
reads `AGENTS.md` context files too — run the same three commands in the
|
|
229
|
+
directory Hermes works from. For native tools, add docket under the MCP
|
|
230
|
+
servers section of `~/.hermes/config.yaml`:
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
docket:
|
|
234
|
+
command: npx
|
|
235
|
+
args: ["-y", "docket-agent", "mcp", "--dir", "/path/to/your/project"]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Any other agent that reads `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, or speaks
|
|
239
|
+
MCP gets the same treatment — one loop file, every agent under the same
|
|
240
|
+
warrant.
|
|
241
|
+
|
|
242
|
+
## Documentation
|
|
243
|
+
|
|
244
|
+
The full guide — concepts, loop-file reference, the verdict algorithm,
|
|
245
|
+
matching semantics, record internals, CLI reference, and per-tool setup —
|
|
246
|
+
lives at **[the docs site](https://shahcolate.github.io/docket/docs.html)**.
|
|
247
|
+
The normative format definition is the [Loop File Spec](spec/SPEC.md).
|
|
248
|
+
|
|
205
249
|
## Five questions, then the loop exists
|
|
206
250
|
|
|
207
251
|
`docket new <name>` interviews you:
|
|
@@ -215,6 +259,32 @@ even ask?"* becomes a grep.
|
|
|
215
259
|
Unwritten answers get guessed at. Written answers get enforced — the
|
|
216
260
|
questions *are* the schema: brief, procedure, warrant, reserved, record.
|
|
217
261
|
|
|
262
|
+
## It iterates itself — with a human veto
|
|
263
|
+
|
|
264
|
+
The record knows where the warrant chafes: every time the agent hit an
|
|
265
|
+
unlisted action, a default-ask was logged. `docket review` mines those and
|
|
266
|
+
proposes the exact amendments:
|
|
267
|
+
|
|
268
|
+
```console
|
|
269
|
+
$ docket review
|
|
270
|
+
2 proposed amendments — from repeated asks in the record
|
|
271
|
+
|
|
272
|
+
1. appeal — allow read: "state insurance regulations" (asked 4×)
|
|
273
|
+
2. appeal — allow draft: "timeline summary" (asked 2×)
|
|
274
|
+
|
|
275
|
+
allow read: "state insurance regulations" in appeal? [y/N] y
|
|
276
|
+
✓ appeal: read now covers "state insurance regulations"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Three rules keep it honest: the analysis is automatic but **applying is
|
|
280
|
+
always a human keystroke** (an agent that widens its own permissions is the
|
|
281
|
+
exact failure docket exists to prevent — it's in our red-team suite);
|
|
282
|
+
anything on the `ask` or `never` lists is **never proposed**, however often
|
|
283
|
+
it recurs — those are policy, not friction; and every approved amendment is
|
|
284
|
+
**appended to the record**, so even the evolution of the rules is auditable.
|
|
285
|
+
|
|
286
|
+
Run it weekly, or wire it into a cron — the proposals wait for you.
|
|
287
|
+
|
|
218
288
|
## Starter loops
|
|
219
289
|
|
|
220
290
|
Seven templates, each a complete worked example (`docket templates`):
|
|
@@ -249,7 +319,7 @@ Read the [Loop File Spec](spec/SPEC.md) — it's short on purpose.
|
|
|
249
319
|
- [ ] `docket check` as a Claude Code PreToolUse hook recipe
|
|
250
320
|
- [ ] Loop inheritance (`extends:`) for team baselines
|
|
251
321
|
- [ ] Record export → human-readable work summaries
|
|
252
|
-
- [ ] Adapters: OpenAI custom instructions,
|
|
322
|
+
- [ ] Adapters: OpenAI custom instructions, Windsurf
|
|
253
323
|
|
|
254
324
|
## Contributing
|
|
255
325
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docket-agent",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "The permission layer and paper trail for AI agents. Your agent checks a rule file before it acts - allow, ask, or deny - and leaves a tamper-evident record after.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/spec/SPEC.md
CHANGED
|
@@ -181,12 +181,14 @@ Storage: `.docket/record.jsonl`, one JSON object per line, append-only.
|
|
|
181
181
|
{"seq":3,"ts":"2026-07-03T10:15:00.000Z","loop":"insurance-appeal","kind":"check","action":"send","target":"appeal email to insurer","verdict":"ask","rule":"ask: anything addressed to the insurer","prev":"sha256:…","hash":"sha256:…"}
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
|
|
184
|
+
Three kinds today:
|
|
185
185
|
|
|
186
186
|
- `check` — a warrant check, recorded automatically with its verdict. The
|
|
187
187
|
question "did the agent even ask?" becomes answerable.
|
|
188
188
|
- `note` — a work entry with any of: `saw`, `did`, `skipped`, `stopped`,
|
|
189
189
|
`note`.
|
|
190
|
+
- `amend` — a human-approved warrant widening (`action`, `added`, `asks`),
|
|
191
|
+
written by `docket review`. Rule changes are evidence too.
|
|
190
192
|
|
|
191
193
|
### The hash chain
|
|
192
194
|
|
|
@@ -210,6 +212,14 @@ when the heads disagree. The chain doesn't stop tampering — it's a plain
|
|
|
210
212
|
file — it makes tampering **visible**, which is what an audit trail is for.
|
|
211
213
|
(Cryptographically signing the head is on the roadmap.)
|
|
212
214
|
|
|
215
|
+
## Review
|
|
216
|
+
|
|
217
|
+
`docket review` clusters repeated default-ask checks from the record and
|
|
218
|
+
proposes the corresponding warrant additions. Implementations must not apply
|
|
219
|
+
proposals without explicit human approval, must never propose targets that
|
|
220
|
+
match the loop's `ask` or `never` lists, and must append an `amend` entry to
|
|
221
|
+
the record for every applied change.
|
|
222
|
+
|
|
213
223
|
## Compiled context
|
|
214
224
|
|
|
215
225
|
Loops are the source of truth; assistant-specific files are build artifacts.
|
package/src/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import { cmdList, cmdShow } from './commands/list.js';
|
|
|
6
6
|
import { cmdCheck } from './commands/check.js';
|
|
7
7
|
import { cmdRecord } from './commands/record.js';
|
|
8
8
|
import { cmdCompile } from './commands/compile.js';
|
|
9
|
+
import { cmdReview } from './commands/review.js';
|
|
9
10
|
import { cmdMcp } from './commands/mcp.js';
|
|
10
11
|
|
|
11
12
|
const HELP = `
|
|
@@ -25,13 +26,18 @@ ${bold('Working with loops')}
|
|
|
25
26
|
ask the warrant: allow, ask, or deny?
|
|
26
27
|
(actions: read, draft, change, send)
|
|
27
28
|
|
|
29
|
+
${bold('Iterating')}
|
|
30
|
+
${cyan('review')} [--min 2] [--loop <name>] [--yes]
|
|
31
|
+
propose warrant updates from repeated asks —
|
|
32
|
+
you approve each one; approvals go on the record
|
|
33
|
+
|
|
28
34
|
${bold('The record')}
|
|
29
35
|
${cyan('record add')} <loop> [--did ..] [--saw ..] [--skipped ..] [--stopped ..] [--note ..]
|
|
30
36
|
${cyan('record log')} [loop] [--n 20]
|
|
31
37
|
${cyan('record verify')} verify the hash chain end to end
|
|
32
38
|
|
|
33
39
|
${bold('Portability')}
|
|
34
|
-
${cyan('compile')} [--target claude|agents|cursor|raw] [--loop <name>] [--write]
|
|
40
|
+
${cyan('compile')} [--target claude|agents|gemini|cursor|raw] [--loop <name>] [--write]
|
|
35
41
|
render loops into CLAUDE.md / AGENTS.md / Cursor rules
|
|
36
42
|
${cyan('mcp')} run the MCP server (stdio) for agent integration
|
|
37
43
|
|
|
@@ -70,6 +76,8 @@ export async function main(argv) {
|
|
|
70
76
|
return cmdRecord(rest);
|
|
71
77
|
case 'compile':
|
|
72
78
|
return cmdCompile(rest);
|
|
79
|
+
case 'review':
|
|
80
|
+
return cmdReview(rest);
|
|
73
81
|
case 'mcp':
|
|
74
82
|
return cmdMcp(rest);
|
|
75
83
|
default:
|
package/src/commands/record.js
CHANGED
|
@@ -16,6 +16,9 @@ function formatEntry(e) {
|
|
|
16
16
|
const style = VERDICT_STYLE[e.verdict] ?? { color: (s) => s, badge: e.verdict };
|
|
17
17
|
return `${head} ${style.color(style.badge.toLowerCase())} ${e.action} → "${e.target}" ${dim(`(${e.rule})`)}`;
|
|
18
18
|
}
|
|
19
|
+
if (e.kind === 'amend') {
|
|
20
|
+
return `${head} amended warrant: ${e.action} now covers "${e.added}" ${dim(`(after ${e.asks} asks)`)}`;
|
|
21
|
+
}
|
|
19
22
|
const parts = [];
|
|
20
23
|
if (e.saw) parts.push(`saw: ${e.saw}`);
|
|
21
24
|
if (e.did) parts.push(`did: ${e.did}`);
|
|
Binary file
|