Skip to content

feat(sessions): FTS session search across transcripts + member scope; session links resolve (v0.461.0) - #869

Merged
vikasprogrammer merged 1 commit into
mainfrom
feat/session-search
Oct 13, 2026
Merged

vikasprogrammer merged 1 commit into
mainfrom
feat/session-search

Conversation

@vikasprogrammer

Copy link
Copy Markdown
Owner

Why

On expresstech a human asked an agent to find "the session where we fixed the PayPal webhook". The work was buried late in a long run titled after its first job. session_history only did LIKE over title and seed task for the agent's own runs, so it couldn't see that work. The agent then read the tenant DB with node:sqlite from Bash and grepped other agents' transcripts. It handed the human #/sessions/ses_…, a link it built itself. The console didn't route it, because the detail segment is the tmux name aos-<id>.

What

  • term_sessions_fts: an external-content FTS5 (porter) index over title, task and report summary. Its UPDATE trigger fires only when one of those columns actually changes, so activity and cost writes never re-tokenize.
  • session_text_fts: a per-conversation digest of prompts, replies and action hints (paths, URLs). It is filled off the scheduler tick in 150ms slices (indexSessionText). Each conversation is capped at 32KB and sampled evenly, so the last topic of a long run survives.
  • Ranking: all-words matches come before any-word matches, the resumed runs of one conversation collapse to a single hit, and each hit has a match snippet.
  • scope:'member' searches and opens what the run-as human can see in the console (canReadRow). It is audited as session.searched / session.opened. A run acting for nobody stays own-agent only.
  • Links: results carry the console url. session_open accepts an id, aos-<id> or a URL, and the console rewrites #/sessions/ses_… to the routed form.

Measured (scratch copy of the instapods DB, 1,913 sessions)

  • Migration plus boot: 150ms.
  • Transcript backfill: 1,641 conversations in 5.2s of 150ms slices (about 16 minutes of wall time at the tick rate). Largest slice 161ms; an idle sweep takes 3ms.
  • Index size: 3.4MB. Queries: 3–11ms.

Tests

  • New scripts/session-search-test.cjs (43 checks), added to test:governance.
  • Full npm run test:governance passes; typecheck and web build are clean.

Not in this PR (separate finding)

The protected-path read guard covers only Read, Glob and Grep, not Bash. Any agent can open agent-os.db from the shell, and auth_sessions.sid holds raw login cookies.

🤖 Generated with Claude Code

… session links resolve (v0.461.0)

session_history's query was a LIKE over title + seed task, own agent only. Asked to find "the session
where we fixed the PayPal webhook" (work buried late in a run titled after its first job), an expresstech
agent read the tenant DB with node:sqlite from Bash, grepped other agents' transcripts, then handed the
human #/sessions/ses_..., a link it built itself that the console didn't route (the detail is the tmux
name, aos-<id>).

- term_sessions_fts: external-content FTS5 (porter) over title/task/report_summary; UPDATE trigger
  scoped to those columns AND a real change, so activity/cost writes never re-tokenize.
- session_text_fts: per-conversation digest of prompts, replies and action hints, filled off the
  scheduler tick in 150ms slices (indexSessionText), 32KB cap sampled evenly so a long run's last topic
  survives. Instapods copy: 1,641 convos in 5.2s of slices, 3.4MB, queries 3-11ms.
- searchSessions: all-words matches before any-word, one hit per conversation, match snippet.
- scope:'member' searches/opens what the run-as human can see in the console (canReadRow), audited
  session.searched / session.opened. A run acting for nobody stays own-agent only.
- Results carry the console url; session_open accepts id, aos-<id>, or a URL; the console rewrites
  #/sessions/ses_... to the routed form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vikasprogrammer
vikasprogrammer merged commit 706bad2 into main Oct 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant