feat: editor improvements and architectural grid prototype

Multiple feature additions and improvements across the application:

- NextGen Editor: drag handles, smart paste, block actions
- Structured views: Kanban and table layouts for notes
- Architectural Grid: new brainstorming/agent interface prototype
- Flashcards: SM-2 revision algorithm with AI generation
- MCP server: robustness improvements
- Graph/PDF chat: fix click propagation and copy behavior
- Various UI/UX enhancements and bug fixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antigravity
2026-05-27 19:45:15 +00:00
parent 2de66a863d
commit f46654f574
99 changed files with 29948 additions and 919 deletions

View File

@@ -12,7 +12,13 @@
- **AC5 anonymousAnalytics DB sync** — La synchronisation de `anonymousAnalytics` vers `UserAISettings` via `updateAISettings()` n'a pas été implémentée. Contrainte utilisateur : zéro écriture DB en 4.1, consentement 100 % client. À implémenter dans une story ultérieure si la cohérence DB devient requise.
## Deferred from: chart suggestions feature (2026-05-23)
## Deferred from: unified tasks view study (2026-05-24)
- **Vue agrégée Notes/Tâches (Markdown scrape)** — Retirée volontairement (option A produit) : surcharge UX, chevauchement avec vues structurées Kanban. Spec `spec-unified-tasks-view.md` abandonnée ; pas dunification TipTap/Checklist pour cette vue.
## Deferred from: US-TEMPORAL product decision (2026-05-24)
- **Prédictions d'accès temporelles** — Reporté : chevauche rappels + flashcards SM-2 + Memory Echo ; heuristique prototype peu fiable ; `NoteAccessLog` non prioritaire. Voir `docs/user-stories.md` § US-TEMPORAL.
- **Build error in note-graph-view.tsx** — Variable `plainText` définie plusieurs fois (ligne 238). Fichier préexistant modifié hors de cette tâche. À corriger indépendamment.

View File

@@ -0,0 +1,92 @@
---
title: 'Unified Tasks View — cross-format aggregation study'
type: 'feature'
created: '2026-05-24'
status: 'done' # cancelled — product decision option A (2026-05-24): removed aggregated Tasks view; use Structured Kanban instead
context:
- '{project-root}/AGENTS.md'
- '{project-root}/memento-note/components/notes-list-views.tsx'
- '{project-root}/memento-note/lib/types.ts'
---
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
## Intent
**Problem:** The home **Notes / Tasks** toggle only aggregates Markdown `- [ ]` / `- [x]` lines from `Note.content`. Rich-text TipTap task lists (HTML in `content`) and legacy `checklist` notes (`checkItems` JSON) are invisible in Tasks view, stats column, and sort-by-tasks — causing empty or misleading UX when users create to-dos via the editor or legacy data.
**Approach:** Introduce a single extraction layer (`lib/tasks/`) that normalizes tasks from all three sources into a stable `UnifiedTask` model with source-specific stable IDs; update toggle/save paths to write back to the correct storage; refresh i18n to explain supported formats without Markdown-only wording.
## Boundaries & Constraints
**Always:** No DB schema migration in v1 unless human approves; reuse existing `content` / `checkItems` fields; toggle must use optimistic `updateNote` + `onNotePatch`; all user-facing strings via i18n (EN+FR minimum); no new tests unless explicitly requested; do not conflate Structured Views `checkbox` properties with inline note tasks.
**Ask First:** Deprecate vs revive `type: checklist` (dedicated note type); one-way migration of legacy `checkItems` → Markdown or TipTap; nested TipTap task support in aggregated view; scope of 15-locale fill vs EN/FR keys only.
**Never:** Treat Structured View kanban/status as Tasks view; store a parallel tasks table; rewrite entire editor serialization to JSON; run destructive DB commands; claim done without manual verification on markdown + richtext + checklist sample notes.
## I/O & Edge-Case Matrix
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|----------|--------------|---------------------------|----------------|
| Markdown tasks | `type: markdown`, content with `- [ ]` lines | Tasks listed; toggle flips `[ ]``[x]` in content | Skip malformed lines |
| TipTap tasks | `type: richtext`, HTML with `ul[data-type="taskList"]` | Tasks listed with text from `<p>` inside `li`; toggle updates `data-checked` + checkbox | Skip items without parseable text |
| Checklist note | `type: checklist`, `checkItems: [{id,text,checked}]` | All items listed; toggle updates matching item by `id` | Normalize legacy `done``checked` on read |
| Mixed note | Markdown lines + TipTap HTML in same richtext note | Both sources extracted (dedupe by normalized text optional v2) | No double-toggle same semantic item in v1 if ambiguous |
| Empty scope | Notebook with no extractable tasks | Empty state with format-agnostic hint | No errors |
| Toggle race | User toggles in Tasks while note open in editor | Last write wins or editor refresh via `emitNoteChange` | Log + refetch on mismatch |
| API update | `PUT /api/notes` with `checkItems` | Same JSON.stringify behavior as server actions | Align API with actions in same PR |
</frozen-after-approval>
## Code Map
- `memento-note/components/notes-list-views.tsx` — current `extractTasksFromNotes`, `getNoteTasksStats`, `handleToggleTask`, Tasks UI
- `memento-note/components/home-client.tsx` — Notes/Tasks toggle, passes notes into list views
- `memento-note/lib/types.ts``CheckItem`, `NoteType`
- `memento-note/lib/utils.ts``parseNote`, `checkItems` deserialization
- `memento-note/components/rich-text-editor.tsx` — TipTap TaskList/TaskItem extensions
- `memento-note/components/note-editor/note-editor-context.tsx` — save forces `checkItems: null`; dormant checklist handlers
- `memento-note/components/note-checklist.tsx` — checklist UI (legacy card path)
- `memento-note/components/note-card.tsx` — checklist toggle via `updateNote({ checkItems })`
- `memento-note/app/actions/notes.ts` — canonical server update, JSON.stringify checkItems
- `memento-note/app/api/notes/[id]/route.ts` — API checkItems inconsistency
- `memento-note/locales/en.json`, `fr.json``notes.viewTasks`, `tasksEmptyHint`, etc.
- `memento-note/lib/note-preview.ts` — excerpt may leak `[ ]` syntax
## Tasks & Acceptance
**Execution (proposed — after study approval):**
- [ ] `memento-note/lib/tasks/types.ts` — define `UnifiedTask`, `TaskSource`, stable `taskKey` — single contract for UI
- [ ] `memento-note/lib/tasks/extract-tasks.ts` — extract from markdown lines, TipTap HTML (DOMParser or regex+guard), checkItems — replaces inline regex in list views
- [ ] `memento-note/lib/tasks/toggle-task.ts` — source-aware write-back to content or checkItems — replaces fragile lineIndex-only toggle
- [ ] `memento-note/components/notes-list-views.tsx` — wire extract/toggle helpers; show source badge optional — keep UI, fix data layer
- [ ] `memento-note/locales/en.json`, `fr.json` — tasksEmptyHint, tasksHeader, optional `tasksSourceMarkdown` / `tasksSourceRichText` / `tasksSourceChecklist` — honest UX
- [ ] `memento-note/app/api/notes/[id]/route.ts` — stringify checkItems like server actions — fix API drift
**Acceptance Criteria:**
- Given a markdown note with `- [ ] Buy milk`, when user opens Tasks view for that notebook, then the task appears and toggling persists after reload.
- Given a richtext note with TipTap task list in saved HTML, when user opens Tasks view, then tasks appear with correct checked state.
- Given a checklist note with `checkItems`, when user opens Tasks view, then items appear and toggle updates `checkItems` not content.
- Given empty notebook, when user opens Tasks view, then empty state text does not mention Markdown-only format.
- Given user toggles task in aggregated view, when note is reopened, then editor reflects the same checked state.
## Design Notes
**Recommended architecture:** pure functions in `lib/tasks/` — no new DB columns. `UnifiedTask` fields: `taskKey`, `noteId`, `noteTitle`, `text`, `completed`, `source: 'markdown'|'tiptap'|'checklist'`, `locator` (lineIndex | domPath | checkItemId).
**TipTap HTML (observed):** `ul[data-type="taskList"] > li[data-type="taskItem"][data-checked="true|false"]` with label+checkbox and content in nested `div > p`. Toggle: flip `data-checked`, sync `input:checked`, preserve HTML structure.
**Checklist type decision:** AGENTS.md documents type as legacy/semi-dead. v1 should **read** existing `checkItems` in Tasks view; reviving full checklist editor is a separate story.
**i18n:** Replace Markdown-only hint with product copy: tasks are collected from checkboxes in notes (lists in rich text, markdown, or checklist notes). Optional short “How it works” link/tooltip.
**Out of scope v1:** Structured Views checkbox properties; cross-note deduplication; migrating all checklist notes to richtext; nested task hierarchy display.
## Verification
**Commands:**
- `cd memento-note && npm run lint` — expected: no new errors in touched files
**Manual checks:**
- Create 3 notes in one notebook: markdown with `- [ ]`, richtext with TipTap todo block, import/mock checklist with checkItems — all visible in Tasks view, each toggle survives refresh.