import { Vec } from "../vec.js"; import type { AncestorReach, MindContext } from "./types.js"; import { type WindowIndex } from "./evidence.js"; /** The reach memo this ask should use — see the note above. * * A TRACED response always gets a fresh, empty one. `AncestorReach`'s * `visited`/`maxDepth`/`saturation` fields are populated only when a trace is * attached, so an entry deposited by an untraced earlier turn would silently * black out the reach detail of a later traced one; and the trace's reach * payload is serialised by ITERATING this map, which must therefore hold what * THIS climb consulted, not the whole conversation's history. Consistent with * memoization.md: a traced response is a different machine — never benchmark * with a trace attached. */ export declare function sharedReachMemo(ctx: MindContext): Map; /** Invalidate every session-lifetime structural read after a write. */ export declare function invalidateStructuralCaches(ctx: MindContext): void; /** Climb the structural DAG from a node to its edge-bearing ancestor contexts. * Ascent stops at hub nodes (parents > √N) — their reach is non-discriminative. * When the start node has no structural parents, climbs from containment parents * (sub-span flat branches inheriting their chunks' context). * * `memo`, when given, caches whole climbs by start id for the duration of ONE * query (the store is read-only while a query is in flight, so a climb is a * pure function of the id). The consensus pipeline climbs the SAME anchors * repeatedly — regions sharing a chunk, and canonicalChunkId probing each * chunk's prefixes — so without the memo every repeat re-pays the full * fan-out reads. */ export declare function edgeAncestors(ctx: MindContext, id: number, contextCount: number, memo?: Map): AncestorReach; /** Convenience: forward edges of a node. */ export declare function nextOf(ctx: MindContext, id: number): number[]; /** Convenience: reverse edges of a node. */ export declare function prevOf(ctx: MindContext, id: number): number[]; /** The uniform-expectation floor on a byte atom's corpus commonality: N * learnt contexts, each at least one perception chunk of up to W of the 256 * possible byte values, contain a given atom in ≥ N·W/256 contexts on * average. An atom's TRUE containment is unmeasurable (atoms carry no * kid/contain links by construction), so this floor is the honest stand-in: * derived entirely from the corpus scale N, the perception window W, and * the alphabet size — never tuned. */ export declare function atomReach(ctx: MindContext, contextCount: number): number; /** Whether a byte atom is a hub at this corpus scale — its commonality floor * {@link atomReach} exceeds the hub bound √N. Below it (small stores) an * atom votes and is recognised exactly as any stored form; above it the * alphabet is scaffolding everywhere and abstains. */ export declare function atomIsHub(ctx: MindContext, contextCount: number): boolean; /** Cached "does this node bear a continuation edge?" — the CHEAP half of * {@link leadsSomewhere}, exported for hot paths that must PRE-FILTER a * candidate before paying for a fold and cannot afford the halo tier. * * `leadsSomewhere`'s second tier (`hasHalo`) is deliberately uncached — one * indexed point probe per candidate, which is right where candidates are * already few. On recognition's off-boundary chain pass they are not few: * using the full predicate there took haloProbes from 922 to 9,144 on a * nine-query battery over the trained store. The edge tier alone is memoised * for the response, so it is ~free, and a node bearing an edge is exactly the * "deposited whole, not an interned fragment" claim that pass needs. * * Strictly NARROWER than `leadsSomewhere` — a halo-only node reads false — so * it is sound as a pre-filter before a consumer that applies the full * predicate, and never as a replacement for it. */ export declare function bearsEdge(ctx: MindContext, id: number): boolean; /** Whether a node LEADS SOMEWHERE — the store's admission predicate * ({@link Store.leadsSomewhere}: edge or halo) with its edge tier memoised for * the response. Recognition filters sites with it (cover.md): a form that * leads nowhere contributes nothing to any derivation. Runs once per candidate * span on the recognition hot path — `hasNext` is cached per response (the same * flat-branch ids are probed across prefix variants by canonicalChunkId). * `hasHalo` is not cached: it's a single indexed point probe per candidate, and * the candidates that reach this check have already been filtered by hasNext * above in edgeAncestors. */ export declare function leadsSomewhere(ctx: MindContext, id: number): boolean; /** The structural IDF read of ONE node: how many distinct learnt contexts * its containment/edge climb reaches, or Infinity when it reaches none or * saturates (no usable identity evidence). The number every * discriminative-vs-scaffolding decision derives from — paired with the * half-dominance convention (geometry.dominates(reach, N)): content * reaching a corpus MINORITY of contexts discriminates (an entity, a * filler); content reaching a majority is frame scaffolding. */ export declare function reachOf(ctx: MindContext, id: number, contextCount: number, memo?: Map): number; /** The corpus scale N — the count of DISTINCT learnt contexts, floored at 2 * so its derived readings (ln N in the consensus floor, √N in the hub bound) * stay meaningful on a near-empty store. The one definition every consumer * of "how big is this corpus?" reads. */ export declare function corpusN(ctx: MindContext): number; /** The hub bound √N itself (≥ 2 always, since N is floored at 2) — for * consumers that pass it to the store's LIMITed reads instead of capping a * materialised list. {@link hubCap} is the list-side reading of the same * convention. */ export declare function hubBound(ctx: MindContext): number; /** Cap a candidate list at the hub bound √N (insertion order) — the ONE * fan-out convention every walk and disambiguation uses (see bounded-reads.md). * A node connected to more than √N others is a hub whose individual connections * carry ~no discriminative information; materialising or scoring them all would * make single decisions scale with the corpus. */ export declare function hubCap(ctx: MindContext, ids: readonly T[]): readonly T[]; /** Whether `descendant` lies within `ancestor`'s subtree — a structural DAG * relation read off the hash-consed `kids` lists, by a bounded explicit-stack * descent. Used by articulation to keep a voice from revoicing a fragment * OF that voice. * * A HOMONYM, NOT A RELATIVE: the law's `Continuation.contains` (derivation.ts) is * a producer's claim that its step IS a continuation, a boolean on one step. This * is a structural relation between two nodes in the DAG. The shared word is * deliberate vocabulary — "containment" is what both name — and the two must not be * read as one. */ export declare function contains(ctx: MindContext, ancestor: number, descendant: number): boolean; /** Whether a continuation edge joins the two forms, in either direction — * the EXACT half's veto on calling them synonyms. * * Halos measure company, and the strongest company any two forms can keep is * standing next to each other: a question and its answer co-occur in every * episode that taught the pair, so their halos SHOULD be similar, and on a * conversational store they are (measured on the CONV fixture: consecutive * turns at 0.809 against a 0.516 concept threshold). A gate reading halo cosine * alone therefore reads adjacency as synonymy and revoices an answer in the * words of the question it answers — "it hangs in madrid" spliced back into * "where is it kept now". The distributional layer cannot tell the two * relations apart, because to it they are the same observation; the exact half * can, for free, because it stored the edge. halo-sketch.md's division of * labour exactly: approximate proposes, exact decides. * * Read LIMITed in both directions at the hub bound — a common continuation's * fan-in is corpus-sized, and no single decision may scale with it. */ export declare function answers(ctx: MindContext, a: number, b: number): boolean; /** The best-scoring item by cosine against `query`, among items scoring at * or above `threshold` — the shared arg-max every Pattern-A "which of these * resonates best" decision reduces to. `strict` picks the tie-break a * caller needs: `true` keeps the first-seen leader on a tie (`>`), the * default lets a later equal score take it (`>=`). */ export declare function argmaxBy(items: Iterable, scoreOf: (item: T) => number, threshold: number, strict?: boolean): { item: T; score: number; } | null; export declare function argmaxCosine(query: Vec, items: Iterable, vecOf: (item: T) => Vec | null | undefined, threshold: number, strict?: boolean): { item: T; score: number; } | null; /** The guided-or-first continuation of a node, as answer-shaped bytes source: * chooseNext under the response guide, falling back to the FIRST-inserted * edge — the one no-guide convention chooseNext, project() and the search's * formRules all share. undefined when the node has no continuation. */ export declare function guidedFirst(ctx: MindContext, id: number): number | undefined; export declare function guidedNext(ctx: MindContext, node: number): number | undefined; /** Disambiguate among a node's learnt continuations: first by the question's * own witness of an establishing context (the exact tier, see * {@link askedContinuations}), then by distributional support. NOTE the * `guide` contract: its VALUE is deliberately unused — * only its PRESENCE gates disambiguation (a null guide means no query is in * flight, so structural walkers keep plain first-edge behaviour). The * gist-cosine of short answer candidates against a query guide is dominated * by accidental byte-pattern correlations, not semantic relatedness, so the * evidence consulted is structural: each candidate's reverse-edge support * count (see below). Contrast {@link chooseAmong}, the REVERSE-direction * disambiguator, whose candidates are whole learnt contexts — long enough * that their perceived gists ARE semantically meaningful — and which * therefore scores by guide cosine. The two directions consult different * halves of the evidence on purpose. */ export declare function chooseNext(ctx: MindContext, id: number, guide?: Vec | null): number | undefined; /** The response canonicalizer's reading of `bytes` when it keeps every offset * — so a window found in the canonical bytes sits at the same place in the * asker's — else the bytes themselves. Text canon is offset-preserving on * ASCII without interior whitespace runs; where it is not, the raw bytes are * read and a case-variant window simply does not match. */ export declare function offsetCanon(ctx: MindContext, bytes: Uint8Array): Uint8Array; /** A FRAGMENT ANSWERS OTHER QUESTIONS. A recognised form that sits inside * other forms (it has structural parents or containers) holds continuations * because the forms it is a piece of were asked — suffix inheritance gives * `f death` the answer of every `… place of death` question, and `director` * the answer of every `… director` one. Choosing one of several such * continuations by popularity voices some other question's answer. A * fragment with several continuations leads somewhere FOR THIS QUESTION only * when the question names one (the exact tier below). So does a fragment * with ONE continuation that was never learnt as a context — no company of * its own (halo): every continuation it holds is inherited, and which one * depends on deposit order (`ther` carried only the last `… mother` fact it * was found reused in). A form learnt as a context (`Tell me about X`'s `X`, * a defined term) keeps its one continuation. A form that is * (nearly) the whole question is not a piece of it: the question says * nothing beyond it, so its continuations answer THIS question. Read by * every mechanism that projects through a recognised site (cover's sites, * recall's argument binding). */ export declare function answersOtherQuestions(ctx: MindContext, id: number, queryLen: number, siteLen: number): boolean; /** The continuations of `id` that `asked` NAMES (see {@link * askedContinuations}) — for a caller holding material other than the whole * question: the multi-hop walk asks with what of the question no product has * restated yet. null when none is named. */ export declare function namedContinuations(ctx: MindContext, id: number, asked: { bytes: Uint8Array; index: WindowIndex; }): number[] | null; /** The question spans that NAMED `pick` among `id`'s continuations — the * evidence a projection through that pick stands on, so a mechanism can * account for what the question said about it (mechanism-market.md: * evidence travels). Empty when the question names no continuation of `id` * or names others. */ export declare function askedEvidence(ctx: MindContext, id: number, pick: number): Array<[number, number]>; /** The climb's points the question HOLDS under the response's equivalence — * stored forms whose canonical bytes occur in the question's, as sites. The * recognition walk matches bytes and the fold's own boundaries, so a stored * `Man at Bath` inside `… of film Man At Bath work at?` is no site; the * consensus climb reaches it through the windows the two spellings share, and * containment under the canon (offset-preserving, so the span is the * question's own) decides. Approximate proposes, exact decides. Read off * the `chainReach(W)` most corroborated points; empty before the climb. */ export declare function canonHeldPoints(ctx: MindContext, minLen: number): Array<{ start: number; end: number; payload: number; }>; /** A CO-INSTANCE of the question: a stored form that shares the question's * FRAME — the same opening and the same close, byte for byte under the * response's equivalence — around ONE different filler. `Where was Peter * Jackson born?` against `Where was the director of film Beat Girl born?` * shares `Where was ` and ` born?`, and leaves `Peter Jackson` against `the * director of film Beat Girl`: another instance of the same question, never * this one. It is the ordered limit of witnessing: a frame is not a bag of * windows (an order-free reading lets `Lyon is a city in France` pass for an * instance of `what if the capital of France were Lyon?`, which NAMES Lyon; * and a coincidental window inside a filler splits it). * * The frame must reach one window, every window inside it must be held by * the material (so on the walk, a frame a product already said cannot name a * second step), and the form's filler must be a thing the corpus knows * (below) — a record that differs from the question only inside the frame * by a description (`converts sunlight into chemical energy` against * `works`) is the same question about the frame's own subject. (Requiring * the two fillers to share no window as well was measured redundant with * this and cost two answers on the 2Wiki fixture.) Returns the form's filler span in `raw` and the * question spans of the frame, or null. One reading for every consumer: the * exact tier transfers the relation through it, and the readers that would * VOICE such a form's own continuation refuse it. */ export declare function coInstanceFiller(ctx: MindContext, raw: Uint8Array, indexes: ReadonlyArray, question: Uint8Array): { span: [number, number]; spans: Array<[number, number]>; filler: number; open: number; close: number; } | null; /** Whether `raw` is ANOTHER INSTANCE of the question — the reading the * refusals take: its frame around a filler of its own, unless the form * witnesses all the question's slot holds. Such a form says what the * question says, and more (`Hey, buddy. What's up? …` for `hey, what's * up? …`): no other filler stands where the question's does. */ export declare function otherInstance(ctx: MindContext, raw: Uint8Array): ReturnType; /** Whether other instances of the question carry a relation — a frame two * co-instances spell alike — once the consensus climb has shown its points. * It is the one piece of a question's evidence the climb adds: a reading made * before it is stale only where this holds (pipeline.ts, `runOf`). */ export declare function readsOffInstances(ctx: MindContext): boolean; /** One step of a derivation: a frame around the entity it stands on. A step * read off an instance's path also keeps the entity it REACHED there (`to`), * so what that entity is can be compared across instances. */ type Step = { prefix: Uint8Array; suffix: Uint8Array; to?: { id: number; bytes: Uint8Array; }; }; /** The first thing learnt WHOLE `bytes` hold, longest from where it opens — * the test {@link entitiesIn} applies to each span of a fact, asked only of * these bytes: ` is Thistlecombe.` holds `Thistlecombe`; `The date of birth * of ` holds nothing. */ export declare function thingIn(ctx: MindContext, bytes: Uint8Array): { id: number; bytes: Uint8Array; } | null; /** What an ANSWER FRAME says of a fact: it is spelled `head`, the entity the * derivation stood on, `mid`, the answer, `tail` (or the answer first, when * `answerFirst`). Read off the instances' last facts — the answer being * what the fact shares with the instance's continuation — and agreed on like * any frame, it says, exactly, which bytes of a new fact answer. */ interface AnswerFrame { head: Uint8Array; mid: Uint8Array; tail: Uint8Array; answerFirst: boolean; } /** One CONVERGENCE read off instances of a question about TWO things: the * derivation each thing takes, both ending at the entity the instance is * answered with (`Who is both the mother of A and the spouse of B?` → * `The answer is M.`: `· mother` from A, `· spouse` from B, both to M). */ export interface Convergence { by: number[]; steps: [Step[], Step[]]; answers: [AnswerFrame, AnswerFrame]; /** The question's bytes the convergence explains: what EVERY instance that * spells it shares with the question — the frame and the run that parts * the two things — and the question's two things. Nothing else. */ explains: Array<[number, number]>; /** Per instance, as read, before they are intersected. */ shared?: Uint8Array[]; /** Per instance, the answers its pairs of derivations met at. */ met?: Map; /** The facts EVERY instance's meeting entity holds (one of them, where an * instance met at several), spelled with the entity cut out. */ cond?: Map; } /** The two things a question names around its frame — and the convergences * two instances of that frame agree on — or null. */ export interface ConvergenceReading { x: [ { span: [number, number]; id: number; }, { span: [number, number]; id: number; } ]; frames: Convergence[]; } /** A question that names two things around one frame (`Who is both the * mother of · and the spouse of ·?`) is read the way a one-slot question is * read off its co-instances (`relationFrames`), with the slot parted where * the two forms share a run (` and the spouse of `): each side holds a thing * (`slotEntity`), and an instance whose continuation holds an entity both * its things reach — each by a derivation of its own (`pathTo`) — shows the * frame's CONVERGENCE. Two instances spelling the same pair of derivations * agree, the agreement every relation read off instances needs. The * proposals are the consensus climb's points, read once per question. */ export declare function convergenceOf(ctx: MindContext): ConvergenceReading | null; /** Where a question's two things meet by a convergence its instances agree * on: each derivation replayed from the question's own thing, the answer each * last fact spells in its side's answer frame (`answerIn`), and the two * compared byte for byte — the exact tier decides — and the entity met at * holding what every instance's did (`cond`). Each meet with the two facts, * its evidence. */ export declare function convergenceMeets(ctx: MindContext, reading: ConvergenceReading): Array<{ name: Uint8Array; facts: [number, number]; by: number; explains: Array<[number, number]>; }>; /** The question's own entity: the longest of the climb's points the question * holds whole, exactly or under the response's equivalence, that has * continuations of its own — `[start, end)` in the question, or null. * `learnt`: only a thing learnt WHOLE, with company of its own as well * (`entitiesIn`'s law), not a piece that inherits continuations. */ export declare function heldEntity(ctx: MindContext, question: Uint8Array, learnt?: boolean): [number, number] | null; /** The perceived gist of a candidate node, through the session gist cache. * Re-gisting a candidate is a full river fold of its bytes — the measured * recall bottleneck (a hub context offers up to √N continuations, EACH * re-perceived per pick). A node's bytes are immutable and perception is * pure, so the cached gist is valid for the store's lifetime. Exported for * every "score node ids against a guide" decision (chooseAmong here, the * bridge's junction pick) so they share ONE cache and one convention. */ export declare function candidateGist(ctx: MindContext, c: number): Vec | null; export declare function chooseAmong(ctx: MindContext, candidates: readonly number[], guide: Vec): { id: number; score: number; }; /** True when NO window of `query` discriminates anything — every stored * W-window it spells is contained by more places than the hub bound allows, * i.e. the whole query is corpus-global scaffolding. * * WHAT IT IS FOR. Several mechanisms ground a query through the literal spans * it * did NOT explain, and those spans are the whole of their evidence. When every * one of them is a hub, the query says nothing the corpus can be held to, and * grounding it means picking one of thousands of continuations it gives no * evidence for — a fabrication whatever the answer happens to be. Answering * with silence there is the honest degradation contract (INVARIANTS.md). * * MEASURED SEPARATION (trained store, hubBound 571) — this is categorical, * not marginal, and it is why the predicate lives here rather than being * spelled twice: * "What is the capital of" ALL saturated ("What":572) → fabricated * "What is the capital " ALL saturated ("What":572) → fabricated * "what is the capital of france" min "f fr":248 → correct * "What is the capitol of France?" min "f Fr":114 → correct * "WHAT IS THE CAPITAL OF FRANCE?" min "HE C":1 → correct * "What is the capital of France?" min "t i":4 → correct * "Who wrote Romeo and Juliet?" min "iet?":26 → correct * "What is the capital of Zamunda?" min "Zamu":3 → silent anyway * Note the last: the honest-silence probes are already refused on other * evidence and sit on the SAME side as the correct ones, so this predicate * is not what makes them silent and cannot be credited for them. * * NO NEW THRESHOLD (thresholds.md): `hubBound` is the √N reading of "hub" used * everywhere, and the containment read is clamped to it exactly as every other * fan-out read is (bounded-reads.md). A query with no stored window at all is * NOT scaffolding-only — it has no evidence either way, and its callers already * refuse it on their own terms. */ export declare function allWindowsAreScaffolding(ctx: MindContext, query: Uint8Array): boolean; /** Per offset of `bytes`: 1 when the W-window there is a stored form contained * in more than √N places (corpus-global scaffolding; see the floor below), * else 0. Memoised per * byte array for the life of the store's read-only response. */ export declare function hubWindows(ctx: MindContext, bytes: Uint8Array): Uint8Array; /** The query's SCAFFOLDING CORE, as spans: the bytes every W-window over which * is a hub (see {@link hubWindows}) — what is nothing but frame, where * {@link scaffoldExtents} is what a frame window reaches. */ export declare function scaffoldSpans(ctx: MindContext, query: Uint8Array): Array<[number, number]>; /** The EXTENTS of the query's SCAFFOLDING windows, merged: every byte some * W-window reaches that is a stored form contained in more than √N places — * corpus-global commonality (commonality.md), the same "hub" reading as * {@link allWindowsAreScaffolding} and the bridge's `explainedSpan`. A window * the store never saw is NOT scaffolding. The extent, not the core, is what * a coverage test needs: a span that still holds one hub window can be * "carried" by any fact that holds that window. */ export declare function scaffoldExtents(ctx: MindContext, query: Uint8Array): Array<[number, number]>; /** Trained forms the query may OPEN, proposed from the write side's own * leaf-id window index — the supply of last resort for prefix completion. * * WHY A SECOND SUPPLY EXISTS. The ranked list prefix completion normally reads * is a resonance list, and resonance cannot rank a proper prefix: measured on * the trained store, cos(prefix, form) falls from 0.9629 at a one-byte * truncation to 0.6206 at three bytes, against a reachThreshold of 0.8750. * Three bytes of truncation put the answer out of reach on GEOMETRY, not on a * bug, so no k and no re-ranking recovers it. * * WHY THIS ROUTE WORKS WHERE THE FOLD DOES NOT. A query's own fold is * useless here: content addressing is not phrase-position-invariant, so a * standalone prefix folds to a DIFFERENT node than the same bytes sitting * inside a longer deposit, and neither the prefix's own node nor its * ancestors lead to the deposit (measured: the 22-byte prefix of the * photosynthesis form resolves, is shared by 6 contexts, and does not have * the form among its ancestors). Leaf ids ARE position-invariant — they are * content-addressed on single bytes — and `indexSubSpans` already interns a * flat branch over every canonical WINDOW of a deposit's leaf-id stream, with * containment edges to the chunks that window spans. A query that is a * prefix therefore shares those window nodes exactly, and reaches the deposit * by climbing containment then parents. Nothing is added to the write side; * this reads an index training already built. * * BOUNDED (bounded-reads.md), AND WITH NO NEW THRESHOLD. The window whose * containment is SMALLEST carries the most evidence, and one saturated at * `hubBound` carries none — that is the same √N reading of "hub" the rest of * the mind uses, not a tuned knob. The upward walk spends a budget of * `hubBound` nodes and fans out by W, so a hub query enumerates nothing and the * caller stays silent rather than guessing (INVARIANTS.md). Measured on the * trained store: the photosynthesis form at a one-byte truncation picks a * window with 52 containers, visits 446 nodes, and yields exactly ONE candidate * that survives the caller's byte compare — the form itself. * * These are PROPOSALS only. Every candidate still faces the byte-exact prefix * compare and all three guards below, so a wrong proposal costs one bounded * read and can never be voiced (exact-vs-approximate.md). */ export declare function formsOpenedBy(ctx: MindContext, query: Uint8Array): number[]; export {};