docket-agent 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 +26 -0
- package/package.json +1 -1
- package/spec/SPEC.md +11 -1
- package/src/cli.js +8 -0
- package/src/commands/record.js +3 -0
- package/src/commands/review.js +0 -0
package/README.md
CHANGED
|
@@ -215,6 +215,32 @@ even ask?"* becomes a grep.
|
|
|
215
215
|
Unwritten answers get guessed at. Written answers get enforced — the
|
|
216
216
|
questions *are* the schema: brief, procedure, warrant, reserved, record.
|
|
217
217
|
|
|
218
|
+
## It iterates itself — with a human veto
|
|
219
|
+
|
|
220
|
+
The record knows where the warrant chafes: every time the agent hit an
|
|
221
|
+
unlisted action, a default-ask was logged. `docket review` mines those and
|
|
222
|
+
proposes the exact amendments:
|
|
223
|
+
|
|
224
|
+
```console
|
|
225
|
+
$ docket review
|
|
226
|
+
2 proposed amendments — from repeated asks in the record
|
|
227
|
+
|
|
228
|
+
1. appeal — allow read: "state insurance regulations" (asked 4×)
|
|
229
|
+
2. appeal — allow draft: "timeline summary" (asked 2×)
|
|
230
|
+
|
|
231
|
+
allow read: "state insurance regulations" in appeal? [y/N] y
|
|
232
|
+
✓ appeal: read now covers "state insurance regulations"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Three rules keep it honest: the analysis is automatic but **applying is
|
|
236
|
+
always a human keystroke** (an agent that widens its own permissions is the
|
|
237
|
+
exact failure docket exists to prevent — it's in our red-team suite);
|
|
238
|
+
anything on the `ask` or `never` lists is **never proposed**, however often
|
|
239
|
+
it recurs — those are policy, not friction; and every approved amendment is
|
|
240
|
+
**appended to the record**, so even the evolution of the rules is auditable.
|
|
241
|
+
|
|
242
|
+
Run it weekly, or wire it into a cron — the proposals wait for you.
|
|
243
|
+
|
|
218
244
|
## Starter loops
|
|
219
245
|
|
|
220
246
|
Seven templates, each a complete worked example (`docket templates`):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docket-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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,6 +26,11 @@ ${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]
|
|
@@ -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
|