import type { CortexStore } from '../db/store.js'; import { computeRootCensus } from '../capture/census.js'; import { type SearchQuery } from '../capture/search-query.js'; /** * The search ledger (FR-13, Story 4.3): has this exact search already been * proven to return nothing, and is that proof still current? * * **The census is the evidence; head is metadata.** `no-matches-at` is * asserted only when the search root's working tree re-fingerprints to the * recorded census (AD-6: evidence in hand, never a proxy — and never mtime). * The recorded `head_oid` renders in the verdict per the AC and is never * compared: a head that moved over a byte-identical root does not change what * the search would return, and comparing it could only manufacture false * misses. * * **Verdict ladder.** No record → `miss`. Root missing, census mismatch, or * the walk provably exceeding the recorded census (growth) → `miss` — AC #3's * "invalidated" is a verdict, never a row mutation: this query writes nothing * (the FR-21 read-only rule), and a `git stash pop` that restores the exact * bytes honestly re-validates the record. Anything unprovable in either * direction — an unreadable entry, an unresolvable scope root — → `unknown` * (AC #4). Scope isolation (AC #5) is the exact-key lookup's `scope_key` * equality; there is deliberately NO subsumption reasoning across roots. * * **The query walks with the RECORD's own census figures as its limits**, not * the environment ceilings. Exceeding the recorded file count or byte total * mid-walk proves growth (a change → miss) without hashing the rest, keeps * the work bounded by what was recorded (the "recorded size gates the work" * rule from FR-7/4.5), and makes the answer independent of any later change * to `CORTEX_NEGATIVE_MAX_*`. * * Query identity and the certifiability gates live in * `src/capture/search-query.ts` — the capture layer, because the flush shares * them and layer direction forbids `capture/` importing `query/`. Re-exported * here so consumers of the ledger see one module. */ export { CERTIFIABLE_GLOB, CERTIFIABLE_PATTERN, CERTIFIABLE_TYPES, canonicalSearchQuery, isCertifiableSearch, normalizeSearchRoot, searchQueryKey, } from '../capture/search-query.js'; export type { SearchQuery } from '../capture/search-query.js'; /** Mirrors READ_LEDGER_MAX_PATHS: a cap, not a budget — excess is refused. */ export declare const SEARCH_LEDGER_MAX_QUERIES = 16; /** AC #2: each rendered line fits 25 tokens, enforced as chars/4 like the read ledger. */ export declare const SEARCH_LEDGER_TOKENS_PER_QUERY = 25; export type SearchLedgerVerdict = 'no-matches-at' | 'miss' | 'unknown'; export interface SearchLedgerResult { /** The pattern exactly as asked, so a caller can correlate. */ pattern: string; queryKey: string; verdict: SearchLedgerVerdict; /** Present only on `no-matches-at`. */ headOid: string | null; recordedAt: string | null; } export interface SearchLedgerDeps { census: typeof computeRootCensus; } export declare function querySearchLedger(store: CortexStore, scopeKey: string, queries: SearchQuery[], deps?: SearchLedgerDeps): SearchLedgerResult[]; export declare function renderSearchLedgerLine(result: SearchLedgerResult): string; /** * `requested` names the drops. Silently returning 16 answers to a question * about 20 makes four searches indistinguishable from "not asked about" — the * wrong-answer direction AD-6 forbids, and the rule the read ledger already * follows on both of its surfaces. */ export declare function renderSearchLedger(results: SearchLedgerResult[], requested?: number): string; //# sourceMappingURL=search-ledger.d.ts.map