You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(sessions): add the completion/lifecycle model — archive, don't remove
Answer the 'how does a session get completed, and remove or archive?'
question as its own section (§4.9). Key decisions:
- Two independent axes: run-state (derived: done/interrupted/error) vs
lifecycle-state (user intent: active/archived/trashed). Never conflate.
- Completion = ARCHIVE (reversible, still searchable + resumable), never
remove. Delete is a separate, heavier, recoverable act (OS trash, not
unlink). Removing on complete destroys the exact value the feature exists
for, and irreversible completion makes users afraid to declutter.
- Manual Done (d) + opt-in auto-archive (30d, exempts pinned, never deletes);
never auto-delete. Append-only 'label' event, consistent with the spine.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/levelcode-sessions-experience.md
+31Lines changed: 31 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -218,6 +218,36 @@ Awwwards juries read the empty states. Ours have quiet personality without cuten
218
218
219
219
---
220
220
221
+
### 4.9 Lifecycle — seal · done · archive · delete (and why never "remove on complete")
222
+
223
+
Completion is where a naïve design does real harm, so it gets its own model. **Two independent axes, and conflating them is the trap:**
224
+
225
+
-**Run state** (derived, automatic) — what the *agent* did last: `done · interrupted · error · resumed-from-summary`. This is the state pill (§4.2). Never user-set.
226
+
-**Lifecycle state** (user intent) — what *you* decided about the session: `active → done/archived → trashed`. This is "completion."
227
+
228
+
A session can be run-state `interrupted` yet lifecycle `done` (you gave up on it and filed it away). The two are drawn differently and never merged into one chip.
229
+
230
+
**Four verbs, three of them cheap:**
231
+
232
+
1.**Seal** (automatic — *not* completion). New Chat finalizes the *live* session (index write, async title). A sealed session is still **Active**. Seal just means "no longer the one you're typing into"; it is not a judgment that the work is done.
233
+
2.**Done / Archive** (the completion action). You mark a session complete: it **leaves the Active list** — the decluttering that is the entire point — and enters **Archive**, where it stays **fully searchable and resumable**. Reversible in one click. Implemented as a `{"kind":"label","lifecycle":"archived","t":…}` event **appended** to the JSONL — no file move, no rewrite — so it is crash-safe and greppable like everything else.
234
+
3.**Delete** (separate, heavier, recoverable). Moves the file to the **OS trash** — never `unlink` — and drops it from the index. For junk or privacy. Rare, because Archive already absorbs the clutter.
235
+
4.**Pin** (orthogonal). Keep a session prominent regardless of age; a pinned session is **exempt from auto-archive**.
236
+
237
+
**The best-practice call: archive on complete, never remove.** Removing a session when a user "finishes" it destroys the one thing the feature exists to provide — the ability to return to *how* you solved something. "I shipped the fix" is not "erase the record of it." Worse, an *irreversible* completion makes people afraid to mark done, so they never declutter and the feature fails at its single job. Storage is plain text and effectively free; there is no space pressure to delete. Every mature analog agrees: Gmail archives and trashes as separate acts; Arc auto-archives tabs; Linear and Things keep a completed view rather than deleting. So — **Done = archive (reversible); Delete = a deliberate, separate, recoverable act.**
238
+
239
+
**Manual, plus opt-in smart-auto:**
240
+
241
+
-**Manual Done** is primary — a checkmark on the card (`d`), a **bulk archive** for a day of one-offs, and a gentle offer at New-Chat seal *only* for short, clearly-finished one-offs (*"Archive this quick one?"* — dismissible, never forced).
242
+
-**Auto-archive** (`sessions.autoArchiveDays`, default **30**, `0` = off) — a session untouched for the window auto-archives, Arc-style, keeping Active fresh with zero janitorial work. It is **honest** (the card reads `archived · inactive 30d`), **exempts pinned**, and **never deletes**.
243
+
-**Never auto-delete.** Automatic destruction without consent is the one thing we don't do. An optional `sessions.trashArchivedAfterDays` (default `0` / off) exists for the rare aggressive-cleanup user — and even it only *trashes* (recoverable), only *archived*, never *pinned*.
244
+
245
+
**Reversibility everywhere:** archiving raises a toast with **Undo** (`⌘Z`); resuming an archived session offers *"reopen"* (un-archive); delete is trash, not unlink (spine §retention — one level of oops-protection).
246
+
247
+
**UI:** the panel shows **Active** by default; a scope pill toggles **Archive** (with its count — *"142 archived"*) and **Trash**. Archived cards render dimmed and re-activate inline. Card actions become **Resume · Done · Rename · Fork · Export · Delete** (`⏎ · d · r · f · e · ⌫`). The run-state pill and a small lifecycle glyph (active / archived) stay visually distinct.
248
+
249
+
**The one call that is genuinely yours:** whether auto-archive ships **on at 30 days** (my recommendation — it is the Arc magic that keeps the list alive for free) or **opt-in, off** (more conservative). And the verb: I lean **"Done"** (the decluttering framing users reach for) with *archive* as the mechanism underneath.
250
+
221
251
## 5. Signature interactions & motion (the differentiators)
222
252
223
253
Each is specific, cheap, and reduced-motion-safe:
@@ -293,6 +323,7 @@ The webview never reads JSONL directly for the list — it reads this index (fas
0 commit comments