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 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.1.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
- Two kinds today:
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:
@@ -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