feat(session-query): ship full-text session search opt-in via openAt never
The shipped bundles keep ctx.sessionQuery mounted but set the new session-query-sqlite `openAt: never` phase: searchSessions/searchEvents fail with the typed SESSION_QUERY_SEARCH_DISABLED code before any request normalization, node:sqlite is never imported or opened, and no source observation or reconciliation runs. Every inherited exact read, filter, and trace — session export descendants, subagent-fork Workspace inheritance, title reads — keeps working, and the Web sidebar search degrades to its designed local title/workspace matching. Enabling content search is a one-line openAt override in a later patch layer; the web e2e scaffold keeps it enabled as the assembled opt-in coverage.
This commit is contained in:
@@ -231,6 +231,36 @@ describe('SQLite session search', () => {
|
||||
await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
})
|
||||
|
||||
it('refuses search in never mode while inherited reads and traces keep working', async () => {
|
||||
const path = await temporaryPath('never-mode.db')
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
const search = await ctx.plugin(SqliteSessionQueryEngine, { path, openAt: 'never' })
|
||||
const service = ctx.sessionQuery as SqliteSessionQueryEngine
|
||||
expect(service.config.openAt).toBe('never')
|
||||
|
||||
const parent = SessionId('never-parent')
|
||||
const child = SessionId('never-child')
|
||||
ctx.sessions.create(parent, { seed: messageEvents('never opened needle'), meta: { createdAt: 10 } })
|
||||
ctx.sessions.create(child, { meta: { parentSession: parent, createdAt: 20 } })
|
||||
|
||||
await expect(service.searchSessions({ query: 'needle' }))
|
||||
.rejects.toThrow(expectCode('SESSION_QUERY_SEARCH_DISABLED'))
|
||||
await expect(service.searchEvents({ sessionId: parent, query: 'needle' }))
|
||||
.rejects.toThrow(expectCode('SESSION_QUERY_SEARCH_DISABLED'))
|
||||
|
||||
expect((await service.listSessions()).map(record => record.header.id).sort())
|
||||
.toEqual([child, parent])
|
||||
const lineage = await service.traceSession(parent)
|
||||
expect(lineage.complete).toBe(true)
|
||||
expect(lineage.descendants.map(node => node.session.header.id)).toEqual([child])
|
||||
|
||||
// The disabled index never touches the filesystem, in mount, use, or disposal.
|
||||
await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
await search.dispose()
|
||||
await expect(stat(path)).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
})
|
||||
|
||||
it('opens once on the first search and reuses readiness for later searches', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
|
||||
Reference in New Issue
Block a user