// Search results — flat turn-level results with FTS marks const SearchScreen = () => { const { query, go } = useRouter(); const q = (query || '').trim(); // Fake search corpus — turns with snippets that match the query const corpus = [ { ts: '04-23 10:54', cwd: '~/work/scarlet-svc', n: 18, tool: 'claude-code', sid: 'a3', text: "use jittered exp backoff with 30s cap, but always read Retry-After from server", hits: ['backoff', 'Retry-After', 'retry'] }, { ts: '04-23 10:52', cwd: '~/work/scarlet-svc', n: 14, tool: 'claude-code', sid: 'a3', text: "tolerate 429s without sleep — retry should respect Retry-After", hits: ['429', 'retry', 'Retry-After'] }, { ts: '04-19 16:30', cwd: '~/code/tt-bundle', n: 8, tool: 'claude-code', sid: 'a1', text: "rate limited; we retry once at the call site, anything beyond is real 429", hits: ['retry', '429'] }, { ts: '04-15 09:11', cwd: '~/work/atelier', n: 3, tool: 'opencode', sid: 'a2', text: "queue worker hits 429 bursts when upstream cache misses", hits: ['429'] }, { ts: '04-12 14:02', cwd: '~/work/scarlet-svc', n: 22, tool: 'claude-code', sid: 'a3', text: "the backoff library you're using has Decorrelated Jitter built in", hits: ['backoff'] }, { ts: '04-09 11:45', cwd: '~/code/tt-bundle', n: 12, tool: 'claude-code', sid: 'a1', text: "for the retry loop in the resolver, bump to 4 attempts but cap at 30s", hits: ['retry'] }, { ts: '04-04 17:20', cwd: '~/code/tt-bundle', n: 5, tool: 'claude-code', sid: 'a6', text: "bumping a transitive dep should not invalidate every output", hits: ['transitive'] }, { ts: '04-02 10:08', cwd: '~/code/tt-bundle', n: 19, tool: 'claude-code', sid: 'a1', text: "lockfile entries store the resolved transitive tree, not declared", hits: ['lockfile', 'transitive'] }, ]; const lc = q.toLowerCase(); const results = !q ? [] : corpus.filter(r => r.text.toLowerCase().includes(lc) || r.hits.some(h => h.toLowerCase().includes(lc))); const renderSnippet = (text, hits) => { if (!q) return text; // Build a regex from query + hit list const terms = [q, ...hits].filter(Boolean).map(t => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')); const re = new RegExp(`(${terms.join('|')})`, 'gi'); const parts = text.split(re); return parts.map((p, i) => re.test(p) ? {p} : {p} ); }; const cols = '110px 110px 200px 50px 1fr'; const sids = new Set(results.map(r => r.sid)); return ( <>
"{q || '(empty)'}" → {results.length} turns / {sids.size} sessions / 0.012s {}} onRemove={() => {}} /> {}} onRemove={() => {}} /> {}} onRemove={() => {}} /> ★ save
tstoolcwd#snippet
{!q && ( )} {q && results.length === 0 && ( )} {results.map((r, i) => (
go({ name: 'session', id: r.sid })}> {r.ts} { e.stopPropagation(); go({ name: 'project', cwd: r.cwd }); }}>{r.cwd} #{r.n} {renderSnippet(r.text, r.hits)}
))}
); }; Object.assign(window, { SearchScreen });