refactor(ai-vault-search): drop the file count nothing reads, and say what memory is left

`store.indexedFileCount` has no caller: the status reports the state counts and
PR 4 reads sessions.

The class doc claimed two things outlive a pass. Six do, and each is now named
with the reason it cannot be a row: the grace bit, the two timer fields, the
three the last pass observed for `status()` to answer between passes, and one
cached query result read only after a close. A slogan that undercounts is worse
than a list, because the next round has to rediscover what it left out.
This commit is contained in:
Jinwoo-H
2026-09-10 23:29:16 -04:00
parent 57baf70590
commit ba94d7372c
2 changed files with 13 additions and 13 deletions
@@ -55,10 +55,19 @@ export type SessionSearchIndexStatus = {
* what is owed a read, what has failed and how often, what the index holds and
* therefore what may have been deleted, what to report — is answered by a row
* in the `files` table. There is no queue, no watch set, no hold-out map and no
* counter with a reset rule. Two things outlive a pass and are not rows: the
* timer, and one bit per root recording whether the previous pass listed
* transcripts under it, which is the grace the retirement walk needs and cannot
* get from the index. That is the whole of it.
* counter with a reset rule.
*
* What is left here, and why none of it can be a row:
* - `previousRootsWithFiles`, the one bit per root the retirement walk's grace
* needs. Deliberately not durable: see the mountpoint trade in
* `session-search-deleted-sources.ts`.
* - `cyclesSinceSweep` and `sweepNext`, which are about the timer rather than
* about any file, and mean nothing to a second process.
* - `degradedRoots`, `lastReconcileAt` and `lastSweepCompletedAt`: what the last
* pass observed, held so `status()` can answer between passes.
* - `lastCounts`, the one cached query result, read only after `close()` so that
* describing what happened does not reopen a handle the owner has finished
* with. While the indexer is open every call re-queries.
*
* **Immutable after construction.** There is no `pause`, `resume`, `clear` or
* `setHistoryDays`. A configuration change is `close()` and a new instance;
@@ -188,15 +188,6 @@ export class SessionSearchStore {
this.onError(error)
}
/**
* Files the index currently holds, for a status that reports what is there.
* Throws on a handle that cannot answer; zero is a number a caller would
* render, and "the index is empty" is not what a broken handle means.
*/
get indexedFileCount(): number {
return Number((this.db.prepare('SELECT count(*) AS n FROM files').get() as { n: number }).n)
}
/**
* Every row this index holds. The candidate list for retirement and the whole
* of the status, read in one query so that no pass has to carry either.