Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit bf4e4c2c0f011b7fee2f08e3917770ad2137b3be
parent 7cb1d765993386693547b561922cb8c63b614a66
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Sat, 12 Sep 2026 02:07:59 -0400

common: the five lib/search/ modules S3 fills, claimed as stubs

S2a, S2b, S2c, S3 and S0-pause all branch off this slice's merged tip and run in
parallel. Two of them creating `lib/search/policy.ts` independently is a merge
conflict in a file neither wrote, so S1 claims all five now: `export {}` plus the
intended signatures in a comment block, taken from
`plans/one-core-phase-2.md` §S3 with the line anchors in `mcp/src/search.ts`
they come from.

Each comment carries the thing that must survive the move rather than just the
shape: the three caps are PASSED, not re-derived, so the bench's structural
counts cannot drift; `passesFilters` stays singular because a second "cheap"
predicate for planning is how a pruner starts disagreeing with the scanner; and
collapse never maps a timestamp between mirrors — that needs the per-pair
`aligned` gate this code does not have.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Acommon/lib/search/collapse.ts | 29+++++++++++++++++++++++++++++
Acommon/lib/search/evalTree.ts | 31+++++++++++++++++++++++++++++++
Acommon/lib/search/policy.ts | 30++++++++++++++++++++++++++++++
Acommon/lib/search/rank.ts | 16++++++++++++++++
Acommon/lib/search/window.ts | 18++++++++++++++++++
5 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/common/lib/search/collapse.ts b/common/lib/search/collapse.ts @@ -0,0 +1,29 @@ +// ONE SEARCH PIPELINE — placeholder. Filled by one-core phase 2 slice S3 +// (`plans/one-core-phase-2.md` §S3); created here by S1 so no two parallel +// slices race to create the same file. +// +// Intended contents: cross-platform mirror collapsing, from +// `mcp/src/search.ts` (collapseDuplicates) and `components/SearchResults.tsx`. +// +// The two rules that make it safe on by default, and that must survive the +// move verbatim: +// +// 1. The kept row is the cluster's canonical member WHEN that member is +// itself among the matches — otherwise simply the first match. A mirror is +// frequently the only surviving copy of a deleted upload, and preferring +// an absent canonical would delete exactly the evidence a "what did the +// removed videos say" question is asking for. +// 2. The collapsed copies are NAMED on the row they folded into. Nothing +// vanishes; the count stops double-counting. +// +// And the one it must never break: timestamps are NEVER mapped between copies +// here. That requires the per-pair `aligned` gate, and this function does not +// move a single second of anything. +// +// export function collapseDuplicates<T extends CollapsibleHit>( +// hits: T[], +// dupes: DuplicateIndex, +// enabled: boolean, +// ): { collapsed: number; kept: T[] }; + +export {}; diff --git a/common/lib/search/evalTree.ts b/common/lib/search/evalTree.ts @@ -0,0 +1,31 @@ +// ONE SEARCH PIPELINE — placeholder. Filled by one-core phase 2 slice S3 +// (`plans/one-core-phase-2.md` §S3); created here by S1 so no two parallel +// slices race to create the same file. +// +// Intended contents: the query-tree evaluator that exists twice today — +// `mcp/src/search.ts:1189-1338` (evalLeaf / evalNode / passesFilters) and +// `common/lib/searchEval.ts`'s copy — as one implementation over one record +// shape. `passesFilters` stays SINGULAR: a second "cheap" predicate for +// planning is exactly how a pruner starts silently disagreeing with the scanner +// about what matches. +// +// export type LeafMatcher = { scope: LayerScope; test: (text: string) => boolean }; +// export type RecordCtx = { +// cues: Cue[]; +// title: string; +// description?: string; +// tags?: string[]; +// includeSnippets: boolean; +// snippetsPerVideo: number; +// }; +// export type LeafOutcome = { matched: boolean; count: number; hits: ScopedSnippet[] }; +// +// export function evalLeaf(leaf: QueryNode, m: LeafMatcher, ctx: RecordCtx): LeafOutcome; +// export function evalNode(node: QueryNode, ms: LeafMatcher[], ctx: RecordCtx): LeafOutcome; +// export function passesFilters( +// rec: { isLivestream?: boolean; ageRestricted?: boolean; uploadDate: string }, +// f: SearchFilters, +// avail: VideoAvailability | undefined, +// ): boolean; + +export {}; diff --git a/common/lib/search/policy.ts b/common/lib/search/policy.ts @@ -0,0 +1,30 @@ +// ONE SEARCH PIPELINE — placeholder. Filled by one-core phase 2 slice S3 +// (`plans/one-core-phase-2.md` §S3); created here by S1 so no two parallel +// slices race to create the same file. +// +// Intended contents: the caps that are today private constants of +// `mcp/src/search.ts`, named and passed rather than re-derived, so the bench's +// structural counts are unchanged by construction. +// +// export type SearchPolicy = { +// // A hard ceiling on shard pages fetched per query, so a rare term over a +// // large (or hub-wide) corpus cannot run away. Reaching it sets +// // `truncated`. search.ts:259 MAX_PAGES 400 +// maxPages: number; +// // A ceiling on matched videos collected before counting stops, so +// // `total` stays bounded for a very common term. Reaching it also sets +// // `truncated`. search.ts:263 HARD_VIDEO_CAP 2000 +// hardVideoCap: number; +// // Cap on windowed excerpt lines per video, so a video with hundreds of +// // matches cannot blow a batch's token budget. +// // search.ts:268 WINDOW_LINE_CAP 200 +// windowLineCap: number; +// // Snippet truncation width. search.ts:456 truncate(…, 240) +// snippetChars: number; +// }; +// +// // What the MCP server passes. The viewer passes its own, UNCAPPED: a human +// // scrolling a page is not spending an agent's token budget. +// export const MCP_POLICY: SearchPolicy; + +export {}; diff --git a/common/lib/search/rank.ts b/common/lib/search/rank.ts @@ -0,0 +1,16 @@ +// ONE SEARCH PIPELINE — placeholder. Filled by one-core phase 2 slice S3 +// (`plans/one-core-phase-2.md` §S3); created here by S1 so no two parallel +// slices race to create the same file. +// +// Intended contents: result ordering, once. `mcp/src/search.ts:477` and the +// viewer's ordering in `components/SearchResults.tsx` are the same intent +// written twice. +// +// export type RankMode = "relevance" | "date" | "duration" | …; +// export function rankHits<T extends RankableHit>(hits: T[], mode: RankMode): T[]; +// +// Fetchers are INJECTED into this module's callers ({ reader, policy, +// onProgress }) so react-query stays in `components/`; reuse +// `lib/concurrency.ts`'s `mapConcurrent` rather than a second limiter. + +export {}; diff --git a/common/lib/search/window.ts b/common/lib/search/window.ts @@ -0,0 +1,18 @@ +// ONE SEARCH PIPELINE — placeholder. Filled by one-core phase 2 slice S3 +// (`plans/one-core-phase-2.md` §S3); created here by S1 so no two parallel +// slices race to create the same file. +// +// Intended contents: the windowing + snippet layer, over the existing +// `lib/transcriptWindow.ts` primitives (`windowCues`, `cuesToSnippets`, +// `mergeSnippets`), so the viewer's excerpt and the MCP's excerpt are the same +// excerpt. +// +// export function windowedTranscript( +// cues: Cue[], +// match: Matcher, +// opts: { before: number; after: number; lineCap: number }, +// ): WindowSnippet[]; +// +// export function truncate(text: string, max: number): string; + +export {};