Skip to content

Commit 8ab6462

Browse files
ndemiancclaude
andcommitted
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>
1 parent 7c09baa commit 8ab6462

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

docs/levelcode-sessions-experience.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,36 @@ Awwwards juries read the empty states. Ours have quiet personality without cuten
218218

219219
---
220220

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+
221251
## 5. Signature interactions & motion (the differentiators)
222252

223253
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
293323
| `⌃⌘P` | switcher (fuzzy jump) |
294324
| `↑ ↓` | move selection |
295325
| `` | resume · `⇧⏎` fork · `⌘⏎` split |
326+
| `d` | mark **done** (archive) · `⇧d` un-archive |
296327
| `r` `f` `e` `` | rename · fork · export · delete (on focused card) |
297328
| `⌘F` | focus search · `⌘\` compact toggle |
298329
| `esc` | close (restores composer focus) |

0 commit comments

Comments
 (0)