docs: add/update ADRs for H1-as-title and Trash removal (guard — from commits d50f3479, 9c87eca2, d0c3a6b8)
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
type: ADR
|
||||
id: "0007"
|
||||
title: "Title equals filename (slug sync)"
|
||||
status: active
|
||||
status: superseded
|
||||
date: 2026-03-15
|
||||
superseded_by: "0044"
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
type: ADR
|
||||
id: "0042"
|
||||
title: "Trash auto-purge safety model"
|
||||
status: active
|
||||
status: superseded
|
||||
date: 2026-04-05
|
||||
superseded_by: "0045"
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
46
docs/adr/0044-h1-as-title-primary-source.md
Normal file
46
docs/adr/0044-h1-as-title-primary-source.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0044"
|
||||
title: "H1 as primary title source — filename as stable identifier"
|
||||
status: active
|
||||
date: 2026-04-07
|
||||
supersedes: "0007"
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0007 established that the `title:` frontmatter field is the source of truth for display titles, with filenames derived from it via slugification and kept in sync bidirectionally. This model had a key assumption: the user explicitly types a title before writing content.
|
||||
|
||||
In practice this created friction: new notes required a title upfront, the TitleField was always visible cluttering the editor, and the "title = filename slug" contract was fragile when users renamed files externally. The team wanted a more natural writing flow where you just start writing — like most text editors — and the title emerges from the document.
|
||||
|
||||
A pair of commits on 2026-04-06 (`377a3f8d`, `7daf6898`) implemented a fundamentally different model.
|
||||
|
||||
## Decision
|
||||
|
||||
**The first `# H1` heading in the note body is the canonical display title. The `title:` frontmatter field is legacy/backward-compat only. New notes are created with filename `untitled-{type}-{timestamp}.md` and no `title:` in frontmatter. On save, if the note has an H1, the file is auto-renamed to a slug derived from it (collision-safe with `-2`, `-3` suffixes).**
|
||||
|
||||
Title resolution priority (Rust `extract_title`):
|
||||
1. H1 on the first non-empty line of the body
|
||||
2. Frontmatter `title:` field (legacy, backward-compat)
|
||||
3. Slug-to-title derivation from filename stem
|
||||
|
||||
The `has_h1: bool` field on `VaultEntry` signals the frontend to hide `TitleField` and the icon picker when an H1 is present, since the H1 serves as the title surface.
|
||||
|
||||
The breadcrumb bar shows the **filename stem** (not display title) so users always know the actual file identifier.
|
||||
|
||||
Auto-rename (`auto_rename_untitled` Tauri command) fires on save for `untitled-*` files that gain an H1, converting them to a human-readable slug.
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A — H1 as primary title + auto-rename on save** (chosen): natural writing flow, filename eventually reflects content, TitleField hidden when H1 present. Downside: auto-rename can surprise users; breadcrumb must show filename to stay honest.
|
||||
- **Option B — Keep `title:` frontmatter as source of truth** (ADR-0007, now superseded): explicit, deterministic. Downside: forces upfront titling, TitleField always visible, friction for quick capture.
|
||||
- **Option C — UUID-based filenames, title only in H1**: filenames never change, no rename logic needed. Downside: vault unreadable in Finder/terminal, breaks the plain-files principle (ADR-0002).
|
||||
|
||||
## Consequences
|
||||
|
||||
- New notes start as `untitled-note-{timestamp}.md` — the vault may accumulate untitled files if users abandon drafts without writing an H1
|
||||
- `TitleField` component is hidden when `has_h1 = true`; icon picker is also hidden (icons only make sense on titled notes)
|
||||
- Frontmatter `title:` still parsed for backward-compat; existing vaults with explicit titles continue to work
|
||||
- Auto-rename on save introduces a file rename side-effect during editing — wikilinks pointing to the old filename may break until the rename propagates
|
||||
- The breadcrumb filename display makes the system more honest but slightly more technical for non-power users
|
||||
- Re-evaluate if users find auto-rename disorienting or if wikilink breakage during rename becomes a reliability concern
|
||||
37
docs/adr/0045-permanent-delete-no-trash.md
Normal file
37
docs/adr/0045-permanent-delete-no-trash.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0045"
|
||||
title: "Permanent delete with confirm modal — no Trash system"
|
||||
status: active
|
||||
date: 2026-04-07
|
||||
supersedes: "0042"
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0042 designed a Trash auto-purge safety model (soft-delete with 30-day retention, OS trash via `trash` crate, audit log). This was built on top of a Trash system that treated deletion as a two-phase operation: move to trash → auto-purge after 30 days.
|
||||
|
||||
The Trash system was subsequently identified as unnecessary complexity: it required `trashed`/`trashedAt` frontmatter fields, sidebar filtering, editor banners, inspector components, dedicated smoke tests, and a `trash` crate dependency. The safety guarantee users actually need is a **confirmation prompt before irreversible action**, not a soft-delete buffer — especially given notes live in a git repo (vault git history is already a recovery mechanism per ADR-0034 and ADR-0014).
|
||||
|
||||
Commit `e581ad36` on 2026-04-06 removed the entire Trash system (123 files changed, ~3164 lines deleted).
|
||||
|
||||
## Decision
|
||||
|
||||
**Delete is permanent and immediate, gated only by a confirmation modal (`useDeleteActions`). Notes with `trashed: true` in existing vault frontmatter are treated as normal notes (the flag is ignored by the parser). The `trash` crate dependency is removed.**
|
||||
|
||||
The confirmation modal is the sole safety gate. No soft-delete, no Trash view, no auto-purge scheduler, no `.laputa/purge.log`.
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A — Permanent delete + confirm modal** (chosen): simple, honest, no hidden state. Git history provides recovery. Removes ~3000 lines of code and a platform-specific dependency. Downside: no in-app recovery path for users who don't know about git.
|
||||
- **Option B — OS Trash via `trash` crate** (ADR-0042, now superseded): soft-delete to OS Trash, user can recover from macOS Trash app. Downside: additional dependency, complex auto-purge scheduler, misleading "auto-purge" promise that was never actually implemented.
|
||||
- **Option C — `.laputa/deleted/` archive folder**: custom recovery mechanism inside vault. Downside: clutters vault, users wouldn't know to look there, still requires manual cleanup.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Users who accidentally delete a note must recover from git history (`git checkout HEAD -- path/to/note.md`) — this is a power-user action
|
||||
- `trashed`/`trashedAt` frontmatter fields in existing vaults are silently ignored — no migration needed, no data loss
|
||||
- The `trash` crate is removed from `Cargo.toml` — build times improve marginally
|
||||
- Smoke tests for trash flows are deleted; delete-related test coverage is now purely the confirm modal behavior
|
||||
- The Trash view, sidebar filter, note banners, and bulk-trash actions are all gone — simpler UI surface
|
||||
- Re-evaluate if user feedback shows significant accidental deletion incidents, or if git-based recovery proves too inaccessible for non-technical users
|
||||
@@ -97,4 +97,7 @@ proposed → active → superseded
|
||||
| [0039](0039-git-history-for-note-dates.md) | Git history as source of truth for note creation/modification dates | active |
|
||||
| [0040](0040-custom-views-yml-filter-engine.md) | Custom Views — .laputa/views/*.yml with YAML filter engine | active |
|
||||
| [0041](0041-filekind-all-files-in-vault-scanner.md) | fileKind field — scan all vault files, not just markdown | active |
|
||||
| [0042](0042-trash-auto-purge-safety-model.md) | Trash auto-purge safety model | active |
|
||||
| [0042](0042-trash-auto-purge-safety-model.md) | Trash auto-purge safety model | superseded → [0045](0045-permanent-delete-no-trash.md) |
|
||||
| [0043](0043-reactive-vault-state-on-save.md) | Reactive vault state: editor changes propagate immediately to all UI | active |
|
||||
| [0044](0044-h1-as-title-primary-source.md) | H1 as primary title source — filename as stable identifier | active |
|
||||
| [0045](0045-permanent-delete-no-trash.md) | Permanent delete with confirm modal — no Trash system | active |
|
||||
|
||||
Reference in New Issue
Block a user