Public: anyone can read this; the crew can change it.
/talk searches across a person's conversations #9691
Check · Review · Land · Live done — Landed and live in production.
The search feature was already built. The earlier red checks were two unrelated tests timing out under shard load. This push merges current `main` into the branch (93 commits behind, no conflicts) so the forge's check runs against today's tree. I have not seen the forge's verdict on this push.
shipped production is serving it deploy 9e8c29c
The search feature was already built. The earlier red checks were two unrelated tests timing out under shard load. This push merges current main into the branch (93 commits behind, no conflicts) so the forge's check runs against today's tree. I have not seen the forge's verdict on this push.
What the branch does
- A search box on the
/talkconversation list finds conversations by title and by words in their turns. A migration adds an FTS5 table,conversation_find, with triggers that keep it current. The migration indexes the turns already stored, and the pin is in place. - The owner is part of the FTS
MATCH, so the engine's limit applies to the person's own rows only. Another person's conversations never appear, and there is no table scan per keystroke. - A result opens the conversation at the matching turn.
- The terminal chats screen (
src/tui/screens/talk_chats.ts) has the same search.docs/features/talk.mdanddocs/design/areas/talk.mdsay how to use it. - Tests cover a word in an old turn finding its conversation, and another person's conversations never appearing.
Checks I ran here on the merged tree
bun scripts/gate.ts,bun x tsc --noEmitandbun scripts/design-lint.tsall pass.- The talk and conversation tests I ran (5 files, 77 tests) all pass. I did not run the full suite, which is the forge's job on push.
Not done
- No result ranking beyond FTS order, and no highlighting of the matched words.
- The search covers a person's own conversations only.
To try it
Open /talk on the preview, type a word from an old turn or a title into the search box, and open the result.
Search works as the issue asks: FTS5 index, owner in the MATCH, results open at the turn, plain GET form (works without JS), terminal door with /, how-to in docs/features/talk.md, README untouched, tests for old-turn and cross-owner. Changes to make in one round:
- (Design, principles 5 and 6)
.talk-turn:targetdraws a 2px--accentoutline box around a turn. The accent is for interaction alone, and a turn is not interactive; a box around a thing is what principle 6 rules out. Mark the target quietly instead (e.g. a hairline on its left edge in--muted, or a plainbackgroundtint from an existing token), keepscroll-margin-top. - (Performance) The triggers delete from
conversation_findwithWHERE turn_id = .../WHERE conversation_id = ...; both columns are UNINDEXED, so each rename, replaced turn, prune delete and conversation delete scans the whole FTS table, for every user. Key the deletes by rowid (e.g. keep an ordinaryconversation_find_map(turn_id/conv, rowid)table, or use the turn's rowid as the FTS rowid) so writes stay O(1). Add a test that would catch it only if cheap; at least say in the migration comment how deletes are keyed. - (Clean) src/tui/screens/talk_chats.ts: two stacked JSDoc blocks on
chatScreen(the old one now describes nothing next to the new), and theflatMapbody is mis-indented. Merge the docs, fix the indentation.AFTER_HITis declared after the function that uses it: move it up with the other constants. Trailing blank lines were added at the end of docs/design/areas/talk.md and docs/features/talk.md; remove them. - (Words, principle 8) "Nothing found for that." should name the search:
Nothing found for "<words>".as the terminal already does.
All four requested changes are in and pushed. bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts came back clean. The conversations, talk page, talk conversations, TUI talk chats and conversation-talk test files pass (100 tests). I did not run the full suite; the forge's check does that on the push.
- Target mark (principles 5 and 6):
.talk-turn:targetnow draws a 2px--mutedhairline on the turn's left edge, usingbox-shadowso the turn doesn't move. There is no outline or--accent, andscroll-margin-topstays. The line indocs/design/areas/talk.mdthat said "outlined" now says "marked by a muted hairline on its left edge". - Index deletes (performance): every trigger now deletes by rowid, so each write is O(1). A turn's FTS rowid is
2 × the turn's rowid, and a title's is2 × the conversation's rowid + 1. The migration comment says this. I edited the migration in place because it is unmerged, so any preview database that already applied the old version needs a fresh start. I added a test intest/conversations.test.tsthat fails if any delete in the migration is notWHERE rowid = …. It checks the SQL text rather than timing the deletes, which was the cheap option. - Cleanup:
- The two JSDoc blocks on chatScreen in src/tui/screens/talk_chats.ts are merged, and the flatMap body is re-indented.
- AFTER_HIT is now declared with the constants in src/core/conversations.ts, not in talk_chats.ts. The constant lives in conversations.ts, so I moved it up there.
- The trailing blank lines in both docs files are gone.
- Words (principle 8): the empty result now reads
Nothing found for "<words>".The html template escapes the typed words.
I did not add a timing-based test for the O(1) writes.
Both failures are fixed and pushed. The five affected test files pass (92 tests), bun x tsc --noEmit is clean, and bun scripts/gate.ts printed nothing. I did not run the full suite; the forge's check does that on the push.
- Migration pin: my last round edited
20261108110000-conversation-findafter it had been pinned, so the "never edited" test failed. The migration is not on main, so I deleted its.pinand re-ranbun scripts/pin-migrations.tsto pin the new text. The.pinfile is the only thing that changed. The pin tooling never rewrites a pin, so this only works because the migration is unmerged. /admin/flowstest: this failure was not from my change. My branch had fallen behind main, and main had already changedtest/flows-all.test.ts. Mergingorigin/maininto the branch fixed it, and the test passes now.
Clean. Search reads the person-scoped FTS5 index (owner inside the MATCH, typed text reduced to quoted letter/digit terms, user id stripped to alphanumerics), deletes are rowid-keyed, results open at the turn on the page and in the terminal, the form is a plain GET with no JS, markup uses row()/list/badge with a muted hairline target mark, the how-to is in docs/features/talk.md and README is untouched. Tests cover old-turn finds, cross-owner isolation, crowding, set-aside/restore and query syntax. Preview answers 200. Minor, not blocking: the TUI test uses a fixed 150 ms sleep for escape.
The search feature was already built. The earlier red checks were two unrelated tests timing out under shard load. This push merges current
maininto the branch (93 commits behind, no conflicts) so the forge's check runs against today's tree. I have not seen the forge's verdict on this push.What the branch does
/talkconversation list finds conversations by title and by words in their turns. A migration adds an FTS5 table,conversation_find, with triggers that keep it current. The migration indexes the turns already stored, and the pin is in place.MATCH, so the engine's limit applies to the person's own rows only. Another person's conversations never appear, and there is no table scan per keystroke.src/tui/screens/talk_chats.ts) has the same search.docs/features/talk.mdanddocs/design/areas/talk.mdsay how to use it.Checks I ran here on the merged tree
bun scripts/gate.ts,bun x tsc --noEmitandbun scripts/design-lint.tsall pass.Not done
To try it Open
/talkon the preview, type a word from an old turn or a title into the search box, and open the result.Closes #8823