DocumentHistoryView.tsxfix: close the findings from reviewing the fixes themselves
A second review pass, this time over the ten fix commits — which were unreviewed
code, and which is where the worst finding was.
Caps enforced in one place each, missing the path their own docstring cites. The
cell-length limit lived only in `applyCellWrites`, so an agent bypassed it by
choosing `add_rows` over `set` — those rows go through `materializeRow`, which
checked the column name and not the value. Both now call one `assertCellLength`.
The column cap lived only in `applyTableOps`, which the import path never reaches:
it goes `writeDocument` → `writeFileAsYjs` → `writeTable`, so the "1,000x300 import"
the docstring describes was still uncapped. Now checked in `table-import.ts`
alongside the row cap.
`rename_column` was the one route left to give a column a reserved label — the
guard was added to `create` and `add_columns` in the same commit and not there, so
the invariant its error message asserts was not actually held.
The invalidation hook in `next-step-sync` fires inside `applyUpdate`'s transaction,
and it detaches a chain that opens its own connection — so it could read the
pre-commit row and cache the stale value back into every bound cell with nothing
left to re-fire. Queued as a `postCommitEffect` instead. The five sibling call
sites added in the same commit are all on auto-commit connections and were already
right.
`focusCellAbove`/`focusCellLeft` were added by the keyboard/ARIA commit and never
wired to anything — arrow-key cell navigation does not exist, so they were dead
code claiming otherwise. Deleted rather than left as a promise. The gutter also
needed `role="gridcell"`: `aria-colcount` counts it as column 1 and the data cells
start at 2, so without it the row declared a cell that did not exist.
And two `_`-prefixed unused bindings in test files I wrote, which the repo forbids
outright.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 15, 2026, 2:24 PMHistoryDiffView.tsxrefactor: consolidate document code into documents/ + add {{ event mention
Frontend: move the editor primitive, file-link/, mention/, yjs/, and history/
under apps/mail/modules/documents/ so every doc-editor concern lives in one
place. Rename AgendaConversationMention -> ConversationMention and generalize
it to take an onSelect callback so the agenda keeps its task-promotion
dispatch while regular docs insert a plain conversationNode chip.
Backend: rename services/document-store/ -> services/documents/ and absorb
services/sse/doc-event-bus.ts + services/sse/doc-events-delta.ts alongside
their tests.
New: {{ event mention in documents. Custom Tiptap suggestion matcher requires
the literal {{ prefix; picker shows a type-icon, title, conversation context,
and relative time; selecting inserts an eventNode chip. New tRPC route
crm.searchEventsForMention runs a global search across the user's crm_events
(emails, slack, meetings, calls, notes, custom) joined to company info.
crm_conversation_updates lives in its own table and stays excluded by design.
Co-Authored-By: Claude Opus 4.7 (1M context) <<email>>May 26, 2026, 9:30 AMHistorySidebar.tsxrefactor: consolidate document code into documents/ + add {{ event mention
Frontend: move the editor primitive, file-link/, mention/, yjs/, and history/
under apps/mail/modules/documents/ so every doc-editor concern lives in one
place. Rename AgendaConversationMention -> ConversationMention and generalize
it to take an onSelect callback so the agenda keeps its task-promotion
dispatch while regular docs insert a plain conversationNode chip.
Backend: rename services/document-store/ -> services/documents/ and absorb
services/sse/doc-event-bus.ts + services/sse/doc-events-delta.ts alongside
their tests.
New: {{ event mention in documents. Custom Tiptap suggestion matcher requires
the literal {{ prefix; picker shows a type-icon, title, conversation context,
and relative time; selecting inserts an eventNode chip. New tRPC route
crm.searchEventsForMention runs a global search across the user's crm_events
(emails, slack, meetings, calls, notes, custom) joined to company info.
crm_conversation_updates lives in its own table and stays excluded by design.
Co-Authored-By: Claude Opus 4.7 (1M context) <<email>>May 26, 2026, 9:30 AMuseDocumentHistory.tsrefactor: consolidate document code into documents/ + add {{ event mention
Frontend: move the editor primitive, file-link/, mention/, yjs/, and history/
under apps/mail/modules/documents/ so every doc-editor concern lives in one
place. Rename AgendaConversationMention -> ConversationMention and generalize
it to take an onSelect callback so the agenda keeps its task-promotion
dispatch while regular docs insert a plain conversationNode chip.
Backend: rename services/document-store/ -> services/documents/ and absorb
services/sse/doc-event-bus.ts + services/sse/doc-events-delta.ts alongside
their tests.
New: {{ event mention in documents. Custom Tiptap suggestion matcher requires
the literal {{ prefix; picker shows a type-icon, title, conversation context,
and relative time; selecting inserts an eventNode chip. New tRPC route
crm.searchEventsForMention runs a global search across the user's crm_events
(emails, slack, meetings, calls, notes, custom) joined to company info.
crm_conversation_updates lives in its own table and stays excluded by design.
Co-Authored-By: Claude Opus 4.7 (1M context) <<email>>May 26, 2026, 9:30 AMuseVersionDiff.tsrefactor: consolidate document code into documents/ + add {{ event mention
Frontend: move the editor primitive, file-link/, mention/, yjs/, and history/
under apps/mail/modules/documents/ so every doc-editor concern lives in one
place. Rename AgendaConversationMention -> ConversationMention and generalize
it to take an onSelect callback so the agenda keeps its task-promotion
dispatch while regular docs insert a plain conversationNode chip.
Backend: rename services/document-store/ -> services/documents/ and absorb
services/sse/doc-event-bus.ts + services/sse/doc-events-delta.ts alongside
their tests.
New: {{ event mention in documents. Custom Tiptap suggestion matcher requires
the literal {{ prefix; picker shows a type-icon, title, conversation context,
and relative time; selecting inserts an eventNode chip. New tRPC route
crm.searchEventsForMention runs a global search across the user's crm_events
(emails, slack, meetings, calls, notes, custom) joined to company info.
crm_conversation_updates lives in its own table and stays excluded by design.
Co-Authored-By: Claude Opus 4.7 (1M context) <<email>>May 26, 2026, 9:30 AM