artshelf 0.4.1 → 0.6.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/CHANGELOG.md CHANGED
@@ -51,6 +51,29 @@
51
51
  available below the lead.
52
52
  - Tightened the portable agent skill description so the completion-gate trigger
53
53
  is visible before final responses, status updates, handoffs, and done reports.
54
+ - Added packaged `ArtshelfReviewReport` schema and canonical example files for
55
+ deterministic agent review reports, plus deterministic footnote guidance for
56
+ `artshelf put --json` registrations.
57
+
58
+ ## [0.6.0](https://github.com/calvinnwq/artshelf/compare/artshelf-v0.5.0...artshelf-v0.6.0) (2026-06-07)
59
+
60
+
61
+ ### Features
62
+
63
+ * **artshelf:** add public review report assets ([6bc89ae](https://github.com/calvinnwq/artshelf/commit/6bc89ae78150bbb161a387f844f32c7ac23f30da))
64
+
65
+
66
+ ### Bug Fixes
67
+
68
+ * **docs:** constrain review approval targets ([eccc16d](https://github.com/calvinnwq/artshelf/commit/eccc16d019f1245a9ab052db51137654a2c3363b))
69
+
70
+ ## [0.5.0](https://github.com/calvinnwq/artshelf/compare/artshelf-v0.4.1...artshelf-v0.5.0) (2026-06-05)
71
+
72
+
73
+ ### Features
74
+
75
+ * default storage to .artshelf paths ([95ef94e](https://github.com/calvinnwq/artshelf/commit/95ef94edef5862c45e5526a27c4adf0bf40306ca))
76
+ * default storage to .artshelf paths ([0da2cda](https://github.com/calvinnwq/artshelf/commit/0da2cda19ff56f78f203840ed71c2379f533750b))
54
77
 
55
78
  ## [0.4.1](https://github.com/calvinnwq/artshelf/compare/artshelf-v0.4.0...artshelf-v0.4.1) (2026-06-05)
56
79
 
package/README.md CHANGED
@@ -116,8 +116,8 @@ This adds a separate approval boundary between quarantine and destructive deleti
116
116
 
117
117
  ## Explicit Ledgers
118
118
 
119
- By default, Artshelf writes repo-local `.shelf/ledger.jsonl` inside a git repo and
120
- `~/.shelf/ledger.jsonl` outside one. Use `--ledger <path>` and an isolated
119
+ By default, Artshelf writes repo-local `.artshelf/ledger.jsonl` inside a git repo and
120
+ `~/.artshelf/ledger.jsonl` outside one. Use `--ledger <path>` and an isolated
121
121
  `--registry <path>` for tests, demos, and unusual workflows:
122
122
 
123
123
  ```bash
@@ -126,16 +126,21 @@ artshelf list --ledger /tmp/artshelf-ledger.jsonl
126
126
  ```
127
127
 
128
128
  Artshelf also keeps a small global registry of known ledgers at
129
- `~/.shelf/ledgers.json`. Override it with `--registry <path>` or
129
+ `~/.artshelf/ledgers.json`. Override it with `--registry <path>` or
130
130
  `ARTSHELF_REGISTRY`; renamed installs still honor legacy `SHELF_REGISTRY` when
131
131
  `ARTSHELF_REGISTRY` is unset. `put` registers its ledger automatically, and you
132
132
  can register an existing ledger explicitly:
133
133
 
134
134
  ```bash
135
135
  artshelf ledgers list
136
- artshelf ledgers add --ledger /path/to/repo/.shelf/ledger.jsonl --name my-repo
136
+ artshelf ledgers add --ledger /path/to/repo/.artshelf/ledger.jsonl --name my-repo
137
137
  ```
138
138
 
139
+ Renamed installs before `0.5.0` used `.shelf` storage paths. Migrate by copying
140
+ each ledger directory to `.artshelf`, rewriting registry paths to the copied
141
+ ledgers, validating with `artshelf ledgers list --json`, and keeping the old
142
+ `.shelf` directories until rollback is no longer needed.
143
+
139
144
  `artshelf ledgers list` validates each registered ledger by default — reporting
140
145
  ok/missing/invalid status with entry counts, and exiting non-zero when the
141
146
  registry or any ledger is broken — so it doubles as a stale-entry check. Add
@@ -238,15 +243,18 @@ quickstart, agent usage, and CLI reference. The source repo also keeps the
238
243
 
239
244
  The package includes an agent-facing skill at `skills/artshelf/SKILL.md`. Agents
240
245
  that support local skills can copy or reference this file to learn when to call
241
- `artshelf put`, how to report Artshelf ids in handoffs and issue comments, why
242
- `artshelf find` / `artshelf get` are the read-only idempotency lookup surface, why
243
- `cleanup --execute` requires explicit approval for a reviewed plan id, how to
244
- review trashed records with `artshelf trash list` before a separately approved trash
245
- purge, and when `artshelf resolve <id> --status resolved --reason <text>` may mark
246
- confirmed handled, missing, or no-longer-needed records without moving or
247
- deleting files.
248
-
249
- The same skill ships in the npm package. From a source checkout, use
246
+ `artshelf put`, how to report deterministic Artshelf footnotes after JSON
247
+ registration, why `artshelf find` / `artshelf get` are the read-only idempotency
248
+ lookup surface, why `cleanup --execute` requires explicit approval for a
249
+ reviewed plan id, how to render dry-run cleanup and trash purge plans as
250
+ review-report decision packets, how to review trashed records with
251
+ `artshelf trash list` before a separately approved trash purge, and when
252
+ `artshelf resolve <id> --status resolved --reason <text>` may mark confirmed
253
+ handled, missing, or no-longer-needed records without moving or deleting files.
254
+
255
+ The same skill ships in the npm package alongside
256
+ `schemas/artshelf-review-report.schema.json` and the canonical
257
+ `examples/artshelf-review-report.json` packet. From a source checkout, use
250
258
  `skills/artshelf/SKILL.md` directly. Agents should ask where the user wants
251
259
  Artshelf cloned before installing or linking it.
252
260
 
package/SPEC.md CHANGED
@@ -428,8 +428,8 @@ Rules:
428
428
 
429
429
  V1 supports two scopes:
430
430
 
431
- - repo-local: `.shelf/ledger.jsonl`
432
- - user-global: `~/.shelf/ledger.jsonl`
431
+ - repo-local: `.artshelf/ledger.jsonl`
432
+ - user-global: `~/.artshelf/ledger.jsonl`
433
433
 
434
434
  Default behavior:
435
435
 
@@ -439,10 +439,14 @@ Default behavior:
439
439
 
440
440
  V1 also supports a user-level registry of known ledgers:
441
441
 
442
- - registry: `~/.shelf/ledgers.json`
442
+ - registry: `~/.artshelf/ledgers.json`
443
443
  - `--registry <path>` overrides the registry path. Without it,
444
444
  `ARTSHELF_REGISTRY` is read first, then legacy `SHELF_REGISTRY`, then the
445
445
  default registry path.
446
+ - Legacy `.shelf` ledgers are not deleted or moved automatically. Migration is
447
+ copy-first: copy ledger directories to `.artshelf`, rewrite registry entries,
448
+ validate the new registry, and retain the old `.shelf` directories for
449
+ rollback until the new paths are proven quiet.
446
450
  - Retention and due calculations use wall-clock time by default. `ARTSHELF_NOW`
447
451
  overrides it for tests and controlled runs; legacy `SHELF_NOW` is read only
448
452
  when `ARTSHELF_NOW` is unset.
@@ -462,7 +466,7 @@ V1 also supports a user-level registry of known ledgers:
462
466
  "ledgers": [
463
467
  {
464
468
  "name": "my-repo",
465
- "path": "/absolute/path/to/repo/.shelf/ledger.jsonl",
469
+ "path": "/absolute/path/to/repo/.artshelf/ledger.jsonl",
466
470
  "scope": "repo",
467
471
  "createdAt": "2026-06-01T05:42:00Z",
468
472
  "updatedAt": "2026-06-01T05:42:00Z"
@@ -506,9 +510,9 @@ Handled records may include cleanup outcome fields:
506
510
  ```json
507
511
  {
508
512
  "cleanupPlanId": "plan_20260601_154200_cd34",
509
- "receiptPath": "/absolute/path/.shelf/receipts/plan_20260601_154200_cd34.json",
513
+ "receiptPath": "/absolute/path/.artshelf/receipts/plan_20260601_154200_cd34.json",
510
514
  "cleanedAt": "2026-06-01T05:45:00Z",
511
- "targetPath": "/absolute/path/.shelf/trash/plan_20260601_154200_cd34/shf_20260601_154200_ab12-artifact",
515
+ "targetPath": "/absolute/path/.artshelf/trash/plan_20260601_154200_cd34/shf_20260601_154200_ab12-artifact",
512
516
  "cleanupReason": "delete is disabled in v1"
513
517
  }
514
518
  ```
@@ -531,7 +535,7 @@ the purge provenance:
531
535
  "resolutionReason": "trash purge completed",
532
536
  "purgedAt": "2026-06-01T06:10:00Z",
533
537
  "purgePlanId": "purge_20260601_061000_ef56",
534
- "purgeReceiptPath": "/absolute/path/.shelf/purge-receipts/purge_20260601_061000_ef56.json"
538
+ "purgeReceiptPath": "/absolute/path/.artshelf/purge-receipts/purge_20260601_061000_ef56.json"
535
539
  }
536
540
  ```
537
541
 
@@ -593,11 +597,26 @@ Agents may run `artshelf find` and `artshelf get` before `put` to avoid duplicat
593
597
  registrations. `find`/`get` are read-only ledger queries; they must not be used
594
598
  as permission to clean up or resolve a record.
595
599
 
600
+ When `artshelf put --json` succeeds, agents should include a deterministic
601
+ Artshelf footnote in the same handoff, status, final response, or run summary
602
+ that mentions the artifact:
603
+
604
+ ```text
605
+ Artshelf footnote: registered <artifact-path> as <artshelf-id>; reason: <short reason>; due: <YYYY-MM-DD|manual-review>; cleanup=<cleanup-mode>.
606
+ ```
607
+
596
608
  Agents may run `artshelf resolve <id> --status resolved --reason <text>` only
597
609
  after explicit confirmation that the record has been handled, is missing, or is
598
610
  no longer needed. The reason must be specific; resolve does not move or delete
599
611
  files.
600
612
 
613
+ For batches of missing-path records, agents should ask for exact approval before
614
+ resolving:
615
+
616
+ ```text
617
+ approve artshelf resolve missing ledger <ledger-path> ids <id...>
618
+ ```
619
+
601
620
  Scheduled jobs may run:
602
621
 
603
622
  ```bash
@@ -622,6 +641,15 @@ registered-ledger discovery and should include trashed record counts and target
622
641
  ages. Purge dry-runs stay scoped to one explicit ledger and should report any
623
642
  plan id, matching entries, and skipped entries.
624
643
 
644
+ When a scheduled review or dry-run produces cleanup or trash purge plans,
645
+ deterministic integrations should build an `ArtshelfReviewReport` packet first,
646
+ then render a compact decision report from it. The packet schema is
647
+ `schemas/artshelf-review-report.schema.json`, the canonical example is
648
+ `examples/artshelf-review-report.json`, and packaged docs/skills carry matching
649
+ copies for browsable docs and portable agent installs. The report groups
650
+ decisions into ready-for-approval, needs-review-first, and blocked sections, and
651
+ must still include exact approval targets in the message body.
652
+
625
653
  Scheduled jobs must never run `artshelf cleanup --execute` or
626
654
  `artshelf trash purge --execute`; they may only dry-run and report plans for later
627
655
  human review.
@@ -662,6 +690,8 @@ human review.
662
690
  - CLI can list trashed records (single ledger or `--all`) and purge them through
663
691
  an approval-first, ledger-scoped dry-run/execute boundary that writes a purge
664
692
  receipt; purge refuses `--all` and never deletes without a reviewed plan id.
693
+ - Package includes the deterministic `ArtshelfReviewReport` schema and canonical
694
+ example for agent-rendered review reports.
665
695
  - All core commands support `--json`.
666
696
  - Tests cover record/list/find/get/status-filter/due/validate/resolve/registry,
667
697
  `artshelf doctor`, the `artshelf status` dashboard, `--all` review, stale-registry,
@@ -18,8 +18,8 @@ const RESOLVE_STATUSES = new Set(["resolved"]);
18
18
  export function defaultLedgerPath(cwd = process.cwd()) {
19
19
  const repoRoot = findGitRoot(cwd);
20
20
  if (repoRoot)
21
- return join(repoRoot, ".shelf", "ledger.jsonl");
22
- return join(homedir(), ".shelf", "ledger.jsonl");
21
+ return join(repoRoot, ".artshelf", "ledger.jsonl");
22
+ return join(homedir(), ".artshelf", "ledger.jsonl");
23
23
  }
24
24
  export function normalizeLedgerPath(path) {
25
25
  return resolve(path ?? defaultLedgerPath());
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
4
  import { now, toIso } from "./time.js";
5
5
  export function defaultRegistryPath() {
6
- return process.env.ARTSHELF_REGISTRY ?? process.env.SHELF_REGISTRY ?? join(homedir(), ".shelf", "ledgers.json");
6
+ return process.env.ARTSHELF_REGISTRY ?? process.env.SHELF_REGISTRY ?? join(homedir(), ".artshelf", "ledgers.json");
7
7
  }
8
8
  export function normalizeRegistryPath(path) {
9
9
  return resolve(path ?? defaultRegistryPath());
@@ -116,17 +116,17 @@ function normalizeName(name) {
116
116
  }
117
117
  function inferLedgerName(ledgerPath) {
118
118
  const normalized = resolve(ledgerPath);
119
- if (normalized === join(homedir(), ".shelf", "ledger.jsonl"))
119
+ if (normalized === join(homedir(), ".artshelf", "ledger.jsonl"))
120
120
  return "global";
121
- if (basename(dirname(normalized)) === ".shelf")
121
+ if (basename(dirname(normalized)) === ".artshelf")
122
122
  return basename(dirname(dirname(normalized))) || "repo";
123
123
  return basename(dirname(normalized)) || "ledger";
124
124
  }
125
125
  function inferLedgerScope(ledgerPath) {
126
126
  const normalized = resolve(ledgerPath);
127
- if (normalized.startsWith(join(homedir(), ".shelf")))
127
+ if (normalized.startsWith(join(homedir(), ".artshelf")))
128
128
  return "user";
129
- if (basename(dirname(normalized)) === ".shelf")
129
+ if (basename(dirname(normalized)) === ".artshelf")
130
130
  return "repo";
131
131
  return "other";
132
132
  }
@@ -143,16 +143,22 @@ artshelf get &lt;id&gt; --json</code></pre>
143
143
  <section>
144
144
  <h2>Ledger Registry</h2>
145
145
  <p>
146
- Artshelf keeps a user-level registry at `~/.shelf/ledgers.json` so one CLI can
146
+ Artshelf keeps a user-level registry at `~/.artshelf/ledgers.json` so one CLI can
147
147
  review all known ledgers without moving project records into one global file.
148
148
  <code>put</code> registers the ledger it writes to.
149
149
  </p>
150
- <pre><code>artshelf ledgers add --ledger &lt;repo&gt;/.shelf/ledger.jsonl --name &lt;project&gt; --scope repo
150
+ <pre><code>artshelf ledgers add --ledger &lt;repo&gt;/.artshelf/ledger.jsonl --name &lt;project&gt; --scope repo
151
151
  artshelf ledgers list --json
152
152
  artshelf review --all --json
153
153
  artshelf status --all --json
154
154
  artshelf find --all --owner &lt;agent-or-runtime&gt; --json
155
155
  artshelf trash list --all --json</code></pre>
156
+ <p>
157
+ Renamed installs before <code>0.5.0</code> used <code>.shelf</code> paths. For migration,
158
+ copy the old ledger directories into <code>.artshelf</code>, rewrite registry entries,
159
+ validate the new registry, and keep the <code>.shelf</code> copies until rollback is no
160
+ longer needed.
161
+ </p>
156
162
  <p>
157
163
  <code>artshelf ledgers list --json</code> validates each registered ledger and reports
158
164
  ok/missing/invalid status with entry and warning/error counts, so agents can detect
@@ -187,8 +193,79 @@ artshelf trash list --all --json</code></pre>
187
193
  <pre><code>artshelf trash list --ledger &lt;ledger-path&gt;
188
194
  artshelf trash purge --older-than 7d --dry-run --ledger &lt;ledger-path&gt; --json
189
195
  artshelf trash purge --execute --plan-id &lt;purge-plan-id&gt; --ledger &lt;ledger-path&gt; --json</code></pre>
196
+ <h3>Review Plan Report Schema</h3>
197
+ <p>
198
+ When a dry-run creates or reuses a cleanup or trash purge plan, surface the
199
+ plan in a compact human-readable report. The report should let the user
200
+ approve, ask for changes, or request alternatives without opening the plan
201
+ file.
202
+ </p>
203
+ <p>
204
+ For deterministic agent integrations, construct an
205
+ <code>ArtshelfReviewReport</code> JSON object first, then render it to text.
206
+ Use <a href="schemas/artshelf-review-report.schema.json">schemas/artshelf-review-report.schema.json</a>
207
+ for the packet shape and
208
+ <a href="examples/artshelf-review-report.json">examples/artshelf-review-report.json</a>
209
+ as the canonical example. The schema locks report structure; the CLI output
210
+ and approval rules still define cleanup safety.
211
+ </p>
212
+ <p>
213
+ Render the JSON packet as a compact decision card using
214
+ <code>decisionSummary</code> and <code>decisionGroups</code>. Lead with
215
+ counts, then show exactly what is ready for approval and what needs review
216
+ first. Emojis are encouraged when the host renders them well because they
217
+ make review groups scannable; omit them only for plain-text or
218
+ accessibility-constrained surfaces.
219
+ </p>
220
+ <pre><code>Artshelf daily review
221
+ Status: &lt;ok|attention needed&gt;; registry &lt;ok|attention&gt;
222
+
223
+ ✅ Ready for approval: &lt;n&gt;
224
+ 👀 Needs review first: &lt;n&gt;
225
+ ⚠️ Blocked: &lt;n&gt;
226
+
227
+ Recommendation
228
+ &lt;one short sentence with the next safest action&gt;.
229
+
230
+ Ready for approval
231
+ 1. &lt;short item label&gt;
232
+ Why: &lt;short reason&gt;
233
+ Action: &lt;what approval will do&gt;
234
+ approve artshelf cleanup ledger &lt;ledger-path&gt; plan &lt;plan-id&gt;
235
+
236
+ 2. &lt;short item label&gt;
237
+ Why: &lt;short reason&gt;
238
+ Action: &lt;ledger-only update, no file changes&gt;
239
+ approve artshelf resolve missing ledger &lt;ledger-path&gt; ids &lt;id...&gt;
240
+
241
+ Needs review first
242
+ 1. &lt;short item label&gt;
243
+ Why: &lt;short reason&gt;
244
+ Suggested next step: inspect path, then choose keep, change retention, resolve, or clean up later
245
+ Path: &lt;path&gt;
246
+
247
+ Blocked
248
+ &lt;none, or the registry/refused/missing-path blocker and next repair step&gt;
249
+
250
+ Safety
251
+ Dry-run only. No execute, resolve, or delete ran.</code></pre>
252
+ <p>
253
+ Keep the full <code>ArtshelfReviewReport</code> JSON as the audit packet
254
+ and include it as an attachment, linked file, or expandable detail when the
255
+ host supports that. Do not paste the whole packet into chat unless the user
256
+ asks for it. For long plans, show only the first 3 to 5 decisions under
257
+ each visible group, then state the hidden count by group and classification.
258
+ Do not hide refused, registry-problem, or missing-path items.
259
+ </p>
260
+ <p>
261
+ If the host supports buttons, menus, or other interactive controls, they
262
+ should emit exact text commands such as the approval targets below. Always
263
+ include the exact approval target in the message body as a fallback for
264
+ clients where those controls do not render.
265
+ </p>
190
266
  <pre><code>approve artshelf cleanup ledger &lt;ledger-path&gt; plan &lt;plan-id&gt;
191
- approve artshelf trash purge ledger &lt;ledger-path&gt; plan &lt;purge-plan-id&gt;</code></pre>
267
+ approve artshelf trash purge ledger &lt;ledger-path&gt; plan &lt;purge-plan-id&gt;
268
+ approve artshelf resolve missing ledger &lt;ledger-path&gt; ids &lt;id...&gt;</code></pre>
192
269
  <div class="note">
193
270
  Never execute from a read-only preview id. Never generate a fresh plan and execute
194
271
  it in the same step. <code>trash</code> moves artifacts into Artshelf trash; physical
@@ -210,6 +287,12 @@ approve artshelf trash purge ledger &lt;ledger-path&gt; plan &lt;purge-plan-id&g
210
287
  skipped instead of registered, include the brief skip reason from the
211
288
  completion checklist.
212
289
  </p>
290
+ <p>
291
+ When <code>artshelf put --json</code> succeeds, include a deterministic Artshelf
292
+ footnote in the same handoff, status, final response, or run summary that
293
+ mentions the artifact.
294
+ </p>
295
+ <pre><code>Artshelf footnote: registered &lt;artifact-path&gt; as &lt;artshelf-id&gt;; reason: &lt;short reason&gt;; due: &lt;YYYY-MM-DD|manual-review&gt;; cleanup=&lt;cleanup-mode&gt;.</code></pre>
213
296
  </section>
214
297
 
215
298
  <section>
@@ -244,8 +327,14 @@ artshelf trash purge --execute --plan-id &lt;purge-plan-id&gt; --ledger &lt;ledg
244
327
  <pre><code>artshelf resolve &lt;id&gt; --status resolved --reason &lt;text&gt;</code></pre>
245
328
  <p>
246
329
  Use a specific reason. <code>resolve</code> only updates the ledger; it does not
247
- move or delete files. Resolved records stop reappearing in future due and
248
- dry-run cleanup output while remaining visible through
330
+ move or delete files. For batches of missing-path records, ask for approval that
331
+ names the exact ledger and ids.
332
+ </p>
333
+ <pre><code>approve artshelf resolve missing ledger &lt;ledger-path&gt; ids &lt;id...&gt;</code></pre>
334
+ <p>
335
+ After resolution, verify with <code>artshelf review --all --json</code> and report
336
+ whether the review is quiet or what remains. Resolved records stop reappearing
337
+ in future due and dry-run cleanup output while remaining visible through
249
338
  <code>artshelf list --status resolved</code>.
250
339
  </p>
251
340
  </section>
@@ -92,6 +92,13 @@ Useful defaults for agents:
92
92
  repo, PR, issue, workflow id, or run id.
93
93
 
94
94
  Use `--json` when another tool needs to capture the Artshelf entry id.
95
+ When `artshelf put --json` succeeds, include a deterministic Artshelf footnote in
96
+ the same handoff, status, final response, or run summary that mentions the
97
+ artifact:
98
+
99
+ ```text
100
+ Artshelf footnote: registered <artifact-path> as <artshelf-id>; reason: <short reason>; due: <YYYY-MM-DD|manual-review>; cleanup=<cleanup-mode>.
101
+ ```
95
102
 
96
103
  ## Idempotent Lookup
97
104
 
@@ -110,16 +117,20 @@ returns no entries, call `put` and record the new id.
110
117
 
111
118
  ## Ledger Registry
112
119
 
113
- Artshelf keeps a user-level registry at `~/.shelf/ledgers.json` so one CLI can
120
+ Artshelf keeps a user-level registry at `~/.artshelf/ledgers.json` so one CLI can
114
121
  review all known ledgers without moving project records into one global file.
115
122
  `put` registers the ledger it writes to. Register existing ledgers explicitly
116
123
  when adopting Artshelf for an existing project:
117
124
 
118
125
  ```bash
119
- artshelf ledgers add --ledger <repo>/.shelf/ledger.jsonl --name <project> --scope repo
126
+ artshelf ledgers add --ledger <repo>/.artshelf/ledger.jsonl --name <project> --scope repo
120
127
  artshelf ledgers list --json
121
128
  ```
122
129
 
130
+ Renamed installs before `0.5.0` used `.shelf` paths. For migration, copy the old
131
+ ledger directories into `.artshelf`, rewrite registry entries, validate the new
132
+ registry, and keep the `.shelf` copies until rollback is no longer needed.
133
+
123
134
  `artshelf ledgers list --json` validates each registered ledger and reports
124
135
  ok/missing/invalid status with entry and warning/error counts, so agents can
125
136
  detect stale registry entries without a separate validate pass. Add `--plain`
@@ -190,11 +201,79 @@ artshelf trash purge --execute --plan-id <purge-plan-id> --ledger <ledger-path>
190
201
  `artshelf review --all --json`, plus `artshelf trash list --ledger <ledger-path> --json`
191
202
  and purge receipt evidence after purge, or explain what remains.
192
203
 
204
+ ### Review Plan Report Schema
205
+
206
+ When a dry-run creates or reuses a cleanup or trash purge plan, surface the plan
207
+ in a compact human-readable report. The report should let the user approve, ask
208
+ for changes, or request alternatives without opening the plan file.
209
+
210
+ For deterministic agent integrations, construct an `ArtshelfReviewReport` JSON
211
+ object first, then render it to text. Use
212
+ [`schemas/artshelf-review-report.schema.json`](schemas/artshelf-review-report.schema.json)
213
+ for the packet shape and
214
+ [`examples/artshelf-review-report.json`](examples/artshelf-review-report.json)
215
+ as the canonical example. The schema locks report structure; the CLI output and
216
+ approval rules still define cleanup safety.
217
+
218
+ Render the JSON packet as a compact decision card using `decisionSummary` and
219
+ `decisionGroups`. Lead with counts, then show exactly what is ready for approval
220
+ and what needs review first. Emojis are encouraged when the host renders them
221
+ well because they make the groups scannable; omit them only for plain-text or
222
+ accessibility-constrained surfaces.
223
+
224
+ ```text
225
+ Artshelf daily review
226
+ Status: <ok|attention needed>; registry <ok|attention>
227
+
228
+ ✅ Ready for approval: <n>
229
+ 👀 Needs review first: <n>
230
+ ⚠️ Blocked: <n>
231
+
232
+ Recommendation
233
+ <one short sentence with the next safest action>.
234
+
235
+ Ready for approval
236
+ 1. <short item label>
237
+ Why: <short reason>
238
+ Action: <what approval will do>
239
+ approve artshelf cleanup ledger <ledger-path> plan <plan-id>
240
+
241
+ 2. <short item label>
242
+ Why: <short reason>
243
+ Action: <ledger-only update, no file changes>
244
+ approve artshelf resolve missing ledger <ledger-path> ids <id...>
245
+
246
+ Needs review first
247
+ 1. <short item label>
248
+ Why: <short reason>
249
+ Suggested next step: inspect path, then choose keep, change retention, resolve, or clean up later
250
+ Path: <path>
251
+
252
+ Blocked
253
+ <none, or the registry/refused/missing-path blocker and next repair step>
254
+
255
+ Safety
256
+ Dry-run only. No execute, resolve, or delete ran.
257
+ ```
258
+
259
+ Keep the full `ArtshelfReviewReport` JSON as the audit packet and include it as
260
+ an attachment, linked file, or expandable detail when the host supports that.
261
+ Do not paste the whole packet into chat unless the user asks for it. For long
262
+ plans, show only the first 3 to 5 decisions under each visible group, then state
263
+ the hidden count by group and classification. Do not hide refused,
264
+ registry-problem, or missing-path items.
265
+
266
+ If the host supports buttons, menus, or other interactive controls, they should
267
+ emit exact text commands such as the approval targets below. Always include the
268
+ exact approval target in the message body as a fallback for clients where those
269
+ controls do not render.
270
+
193
271
  Approval wording should be exact:
194
272
 
195
273
  ```text
196
274
  approve artshelf cleanup ledger <ledger-path> plan <plan-id>
197
275
  approve artshelf trash purge ledger <ledger-path> plan <purge-plan-id>
276
+ approve artshelf resolve missing ledger <ledger-path> ids <id...>
198
277
  ```
199
278
 
200
279
  Never execute from a read-only preview id. Never generate a fresh plan and
@@ -305,8 +384,17 @@ artshelf resolve <id> --status resolved --reason <text>
305
384
  ```
306
385
 
307
386
  Use a specific reason. `resolve` only updates the ledger; it does not move or
308
- delete files. Resolved records stop reappearing in future due and dry-run
309
- cleanup output while remaining visible in `artshelf list --status resolved`.
387
+ delete files. For batches of missing-path records, ask for approval that names
388
+ the exact ledger and ids:
389
+
390
+ ```text
391
+ approve artshelf resolve missing ledger <ledger-path> ids <id...>
392
+ ```
393
+
394
+ After resolution, verify with `artshelf review --all --json` and report whether
395
+ the review is quiet or what remains. Resolved records stop reappearing in future
396
+ due and dry-run cleanup output while remaining visible in
397
+ `artshelf list --status resolved`.
310
398
 
311
399
  ## Scheduled Review
312
400
 
@@ -0,0 +1,116 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "scope": {
4
+ "registryPath": "~/.artshelf/ledgers.json",
5
+ "ledgerCount": 3,
6
+ "health": "attention",
7
+ "registryHealth": "ok",
8
+ "affectedLedgers": [
9
+ {
10
+ "name": "example-project",
11
+ "ledgerPath": "/path/to/example-project/.artshelf/ledger.jsonl",
12
+ "validationStatus": "ok"
13
+ }
14
+ ]
15
+ },
16
+ "plans": [
17
+ {
18
+ "type": "cleanup",
19
+ "ledgerPath": "/path/to/example-project/.artshelf/ledger.jsonl",
20
+ "planId": "plan_20260606_120000_ab12",
21
+ "planPath": "/path/to/example-project/.artshelf/plans/plan_20260606_120000_ab12.json",
22
+ "approvalTarget": "approve artshelf cleanup ledger /path/to/example-project/.artshelf/ledger.jsonl plan plan_20260606_120000_ab12"
23
+ }
24
+ ],
25
+ "summary": {
26
+ "executable": 1,
27
+ "skipped": 2,
28
+ "refused": 0,
29
+ "manualReview": 1,
30
+ "missingPath": 1,
31
+ "trashed": 0
32
+ },
33
+ "decisionSummary": {
34
+ "readyForApproval": 2,
35
+ "needsReviewFirst": 1,
36
+ "blocked": 0
37
+ },
38
+ "decisionGroups": {
39
+ "readyForApproval": [
40
+ {
41
+ "label": "Clean up temp debug output",
42
+ "itemIds": ["shf_20260606_120000_ab12"],
43
+ "actionType": "cleanup",
44
+ "approvalTarget": "approve artshelf cleanup ledger /path/to/example-project/.artshelf/ledger.jsonl plan plan_20260606_120000_ab12",
45
+ "reason": "Disposable temp artifact has a reviewed cleanup plan.",
46
+ "nextStep": "Approve the exact cleanup plan to move the artifact into Artshelf trash."
47
+ },
48
+ {
49
+ "label": "Resolve missing report record",
50
+ "itemIds": ["shf_20260606_120500_cd34"],
51
+ "actionType": "resolve-missing",
52
+ "approvalTarget": "approve artshelf resolve missing ledger /path/to/example-project/.artshelf/ledger.jsonl ids shf_20260606_120500_cd34",
53
+ "reason": "The report path is already missing.",
54
+ "nextStep": "Approve the ledger-only resolve command after confirming the report is no longer needed."
55
+ }
56
+ ],
57
+ "needsReviewFirst": [
58
+ {
59
+ "label": "Inspect lifecycle smoke report",
60
+ "itemIds": ["shf_20260606_121000_ef56"],
61
+ "actionType": "inspect",
62
+ "approvalTarget": null,
63
+ "reason": "cleanup=review means the artifact should be inspected before closing.",
64
+ "nextStep": "Inspect the path, then choose keep, change retention, resolve, or clean up later."
65
+ }
66
+ ],
67
+ "blocked": []
68
+ },
69
+ "recommendation": "Approve the reviewed cleanup plan for the disposable temp directory, then resolve the missing record after confirming it is no longer needed.",
70
+ "items": [
71
+ {
72
+ "id": "shf_20260606_120000_ab12",
73
+ "path": "/tmp/example-debug-output",
74
+ "classification": "trash-safe",
75
+ "proposedAction": "execute reviewed cleanup plan",
76
+ "dueStatus": "due",
77
+ "reason": "temporary debug output retained for 3 days",
78
+ "note": "The path exists, cleanup=trash, and the dry-run plan moves it into Artshelf trash."
79
+ },
80
+ {
81
+ "id": "shf_20260606_120500_cd34",
82
+ "path": "/tmp/missing-report.json",
83
+ "classification": "resolve-candidate",
84
+ "proposedAction": "resolve ledger-only after confirmation",
85
+ "dueStatus": "missing-path",
86
+ "reason": "report path is already missing",
87
+ "note": "Resolution updates only the ledger and does not move or delete files."
88
+ },
89
+ {
90
+ "id": "shf_20260606_121000_ef56",
91
+ "path": "/tmp/lifecycle-smoke-report.json",
92
+ "classification": "needs-human-review",
93
+ "proposedAction": "inspect before choosing cleanup or retention",
94
+ "dueStatus": "manual-review",
95
+ "reason": "cleanup=review artifact retained for manual inspection",
96
+ "note": "No approval target is shown until the review decision is known."
97
+ }
98
+ ],
99
+ "alternatives": [
100
+ "keep the artifact and change retention",
101
+ "inspect the path before approving cleanup",
102
+ "regenerate the plan after edits",
103
+ "resolve missing records ledger-only"
104
+ ],
105
+ "safety": {
106
+ "dryRunOnly": true,
107
+ "executeAllRefused": true,
108
+ "noExecuteRan": true,
109
+ "noResolveRan": true,
110
+ "noDeleteRan": true
111
+ },
112
+ "verification": {
113
+ "command": "artshelf review --all --json",
114
+ "successCondition": "no due, manual-review, missing-path, executable, or refused entries remain unless explicitly reported"
115
+ }
116
+ }
@@ -94,7 +94,7 @@ artshelf validate --ledger /tmp/artshelf-ledger.jsonl --json
94
94
  artshelf due --ledger /tmp/artshelf-ledger.jsonl --json
95
95
  artshelf cleanup --dry-run --ledger /tmp/artshelf-ledger.jsonl --json</code></pre>
96
96
  <p>
97
- Dry-run writes a plan under the ledger's `.shelf` directory only when
97
+ Dry-run writes a plan under the ledger's `.artshelf` directory only when
98
98
  cleanup entries exist. If there is nothing to clean up, it reports
99
99
  <code>not-created</code> and writes no plan file. Review any generated
100
100
  plan id before an execute step.
@@ -119,7 +119,7 @@ artshelf cleanup --dry-run --ledger /tmp/artshelf-ledger.jsonl --json</code></pr
119
119
  <h2>4. Purge old trashed records explicitly</h2>
120
120
  <p>
121
121
  After cleanup execution, trashed files are quarantined under the ledger's
122
- <code>.shelf/trash</code> folder. Before physical deletion, run an explicit
122
+ <code>.artshelf/trash</code> folder. Before physical deletion, run an explicit
123
123
  reviewed trash purge plan:
124
124
  </p>
125
125
  <pre><code>artshelf trash list --ledger /tmp/artshelf-ledger.jsonl