loki-mode 7.13.0 → 7.14.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.
@@ -0,0 +1,107 @@
1
+ # R6: 1-Click Rollback + Checkpoint UX (Design Note)
2
+
3
+ Status: implemented in this worktree (not committed to main). For integrator cherry-pick.
4
+ Goal: make Loki's existing checkpoint/rollback infra EXCELLENT and OBVIOUS so users
5
+ run autonomous work boldly, knowing a mistake is one action from undone.
6
+
7
+ ## 1. Verified existing code (read, not assumed)
8
+
9
+ ### Checkpoint writers (THREE divergent formats, one shared index.jsonl)
10
+
11
+ | Writer | ID format | Files captured | Source |
12
+ |---|---|---|---|
13
+ | `create_checkpoint()` (automatic, per iteration) | `cp-{iter}-{epoch}` | `state/orchestrator.json`, `autonomy-state.json`, `queue/{pending,completed,in-progress,current-task}.json` | `autonomy/run.sh:7373` |
14
+ | `cmd_checkpoint create` (manual CLI) | `cp-{ts}` | `session.json`, `dashboard-state.json`, `queue/`, `memory/`, `metrics/`, `council/` (recursive copy) | `autonomy/loki:16122` |
15
+ | `POST /api/checkpoints` (dashboard) | `chk-{ts}` | `dashboard-state.json`, `session.json`, `queue/` | `dashboard/server.py:5085` |
16
+
17
+ All three append to `.loki/state/checkpoints/index.jsonl` (field names differ; the
18
+ dashboard `GET /api/checkpoints` normalizes them).
19
+
20
+ ### Restore (rollback) paths
21
+
22
+ | Path | Restores | Source |
23
+ |---|---|---|
24
+ | `rollback_to_checkpoint()` (internal, run.sh) | state + queue json (NOT autonomy-state) | `autonomy/run.sh:7473` |
25
+ | `loki checkpoint rollback <id>` (bash CLI) | glob-restores whatever is in the cp dir | `autonomy/loki:16263` |
26
+ | `loki rollback to|latest <id>` (Bun) | the 5 RESTORE_FILES | `loki-ts/src/commands/rollback.ts` + `loki-ts/src/runner/checkpoint.ts:632` |
27
+
28
+ ### Bun runner checkpoint API (`loki-ts/src/runner/checkpoint.ts`, 700 lines)
29
+ - `createCheckpoint`, `listCheckpoints`, `readCheckpoint`, `rollbackToCheckpoint` (planner),
30
+ `executeRollback` (copier). Byte-for-byte parity with bash `create_checkpoint`.
31
+ - `metadata.json` keys are pinned by `loki-ts/tests/runner/checkpoint.test.ts:62-91`
32
+ (`Object.keys(m).sort()`) -- they MUST NOT change.
33
+
34
+ ### Dashboard
35
+ - `GET /api/checkpoints`, `GET /api/checkpoints/{id}`, `POST /api/checkpoints` exist.
36
+ - The UI component `dashboard-ui/components/loki-checkpoint-viewer.js` (601 lines) ALREADY
37
+ renders list + create + rollback-with-two-step-confirm and POSTs to
38
+ `POST /api/checkpoints/{id}/rollback` -- but that endpoint **did not exist**. The
39
+ dashboard rollback button was DEAD.
40
+
41
+ ## 2. Three decisions (verified facts, not assumptions)
42
+
43
+ ### Decision A: what "truly undo an iteration" restores
44
+ Verified fact: Loki does NOT commit per iteration (`grep "git commit" autonomy/run.sh`
45
+ finds only merge-conflict `git add`, no per-iteration commit). Therefore the captured
46
+ `git_sha` is HEAD (the last commit), and `git reset --hard <git_sha>` would discard the
47
+ iteration's work PLUS anything since the last commit -- it cannot reconstruct a specific
48
+ iteration's working tree. The pre-existing printed hint `git reset --hard <git_sha>`
49
+ (run.sh:7541, loki:16314) was therefore actively MISLEADING.
50
+
51
+ Resolution: capture a real working-tree snapshot at checkpoint time via `git stash create`
52
+ (captures tracked changes without disturbing the tree), then ANCHOR it with
53
+ `git update-ref refs/loki/cp/<id> <sha>` so `git gc` cannot prune the dangling commit.
54
+ The snapshot sha is written to a SIDECAR file `worktree-snapshot.txt` in the checkpoint
55
+ dir (NOT metadata.json, to preserve byte parity). Restore of code is opt-in
56
+ (`loki rollback to <id> --code`) because it overwrites tracked files; by default the
57
+ durable, correct recovery command is printed: `git stash apply refs/loki/cp/<id>`.
58
+
59
+ State + `.loki/CONTINUITY.md` (the iteration/conversation handoff context) are
60
+ auto-restored -- this is the always-on "undo the iteration's state + context".
61
+
62
+ Honest gap: `git stash create` captures tracked changes only; it does NOT capture
63
+ untracked or ignored files. Files the iteration newly ADDED and never committed are not in
64
+ the snapshot, and an apply will not delete them. Documented, not hidden.
65
+
66
+ ### Decision B: re-undoability invariant
67
+ Every restore path FORCES a pre-rollback snapshot of current state before overwriting, so
68
+ a rollback is itself trivially undoable. The Bun `executePlan`, the dashboard endpoint, and
69
+ bash `cmd_rollback` all create a forced checkpoint first (bash `create_checkpoint`
70
+ early-returns on a clean tree, so the new code path forces it). The human dashboard path
71
+ ALSO keeps the existing two-step confirm. Autonomous paths never block on a prompt.
72
+
73
+ ### Decision C: do not add a 4th format, do not unify the 3
74
+ Unifying would break the byte-for-byte parity test; a 4th compounds the problem. The new
75
+ dashboard restore endpoint GLOB-restores whatever the checkpoint dir contains (mirrors bash
76
+ `cmd_checkpoint rollback`), so it works for all three writers. New fields go in sidecars.
77
+
78
+ ## 3. Changes (parity-organized)
79
+
80
+ - **bash `autonomy/loki`**: add top-level `rollback)` dispatch + `cmd_rollback`
81
+ (`list|show|to|latest`, `--code` flag). `to|latest` delegate to the existing
82
+ `cmd_checkpoint rollback` restore body after forcing a pre-rollback snapshot, then
83
+ optionally apply the anchored code snapshot. Prominent "you can undo this" output.
84
+ - **bash `autonomy/run.sh`**: `create_checkpoint` also copies `CONTINUITY.md`, creates +
85
+ anchors the worktree snapshot (sidecar), echoes the checkpoint id; `rollback_to_checkpoint`
86
+ also restores `CONTINUITY.md` and forces the pre-rollback snapshot. The per-iteration call
87
+ site emits a prominent "Checkpoint <id> created -- undo with `loki rollback to <id>`".
88
+ The misleading `git reset --hard` hint replaced with `git stash apply refs/loki/cp/<id>`.
89
+ - **Bun `loki-ts/src/runner/checkpoint.ts`**: copy `CONTINUITY.md` into the checkpoint
90
+ (additive, parity-safe), add `CONTINUITY.md` to RESTORE_FILES, expose
91
+ `executeRollbackWithSnapshot` that forces a pre-rollback snapshot before restoring.
92
+ metadata.json keys unchanged.
93
+ - **Bun `loki-ts/src/commands/rollback.ts`**: `executePlan` forces a pre-rollback snapshot
94
+ before restoring; HELP text made honest about state+context restore and the printed code
95
+ command.
96
+ - **dashboard `dashboard/server.py`**: add `POST /api/checkpoints/{id}/rollback`
97
+ (`require_scope("control")`, `_sanitize_checkpoint_id`, forced pre-snapshot, glob-restore).
98
+ Un-deads the existing UI button.
99
+
100
+ ## 4. Tests (extend existing suites, no parallels)
101
+ - `loki-ts/tests/runner/checkpoint.test.ts`: CONTINUITY round-trip restore + forced
102
+ pre-rollback snapshot.
103
+ - `loki-ts/tests/commands/rollback.test.ts`: `to` forces a pre-rollback snapshot (re-undo).
104
+ - `tests/test-checkpoint-cli.sh`: top-level `loki rollback list|to|latest`, restore actually
105
+ reverts, pre-rollback snapshot exists.
106
+ - `dashboard/tests/test_rollback_endpoint.py`: POST rollback reverts, scope, 404.
107
+ No paid model calls anywhere.