agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
82 lines (81 loc) • 4.93 kB
TypeScript
/**
* readings — what makes two calls the SAME search, what makes one WIDER than another, and how
* the reads of one search merge (design § 5.3).
*
* Pattern: every answer is read off the COMPOSED executed scope of each call (#199's
* `ComposedCoverage` items) — the tool, every filter in effect (a `whenOmitted` default
* composed as if sent), the `fixed` qualifiers, a host-filled identity filter by its
* reference, a period by its span resolved at dispatch, and the page asked for.
* Equivalent spellings of one executed span share a key; the same relative spelling
* at two dispatch instants does not. Never the tool name or
* the model-visible arguments alone. An inert argument is not in the scope, so it never
* splits a key; nor does a cap.
* Role: integrity/ layer (L3), read by `citation.ts`, `containment.ts` and `statement.ts`.
* Values compare by the library's one name rule (`lib/normalize.ts` · `sameName`);
* spans by the time layer's half-open ranges (`time/range.ts`).
*
* The merge: within one key a later read replaces only an UNREAD outcome; two reads that both
* read and disagree — one empty, one with rows — are a disagreement, never settled by order.
*/
import type { ComposedItem, ComposedSpan } from '../../semantics/coverage/composedCoverage.js';
import type { DeclaredPeriod } from '../../semantics/coverage/period.js';
import { type TimeRange } from '../../time/range.js';
import type { SearchTool, TurnCall } from './types.js';
type SearchCheckedItem = ComposedItem;
type DeclaredTool = SearchTool;
/** The value rule: strings by the one name rule (`sameName`); anything else by stable JSON. */
export declare function sameValue(a: unknown, b: unknown): boolean;
/**
* A value as a key spells it — one spelling for every value `sameValue` calls the same: a
* string's text (`textOf`), with a foldable word lower-cased unless the text has a digit.
*/
export declare function spellValue(value: unknown): string;
/** Whether `outer` holds all of `inner` (half-open). A malformed range holds nothing. */
export declare function holdsRange(outer: TimeRange, inner: TimeRange): boolean;
/** Whether two ranges share an instant. A malformed range is treated as overlapping. */
export declare function meets(a: TimeRange, b: TimeRange): boolean;
/**
* The parts of a read's `queried` time the store did not hold, half-open: all of it when `held`
* is unknown, the parts outside `held` otherwise (#199's `span.ts` · `resultSpan` makes the
* queried span half-open; the held one is made so the same way).
*/
export declare function unheldRanges(period: DeclaredPeriod): TimeRange[];
/** A read's window: the span its period item ran with (dispatch time), else the result's. */
export declare function searchWindow(call: TurnCall): ComposedSpan | undefined;
/** A call is a READ only when the caller says so; undeclared = `not-read` (§ 5.1). */
export declare const isRead: (call: TurnCall) => boolean;
/** The call's row is an `among` miss: it counts the names its source holds. */
export declare const isAmongRow: (call: TurnCall) => boolean;
/** It ran and returned something the record can read as empty or not. */
export declare const returnedReading: (call: TurnCall) => boolean;
/** The composed executed scope: the row's, or the scope composed for a call with no row. */
export declare const scopeOf: (call: TurnCall) => readonly SearchCheckedItem[] | undefined;
/**
* The reading key — or undefined when the call has no composed scope. `clock` is accepted for
* the callers' symmetry and never read: the executed period was resolved at dispatch.
*/
export declare function readingKey(call: TurnCall, tool: DeclaredTool | undefined, _clock?: string): string | undefined;
/** A filter (or the population) the narrower search applied: its argument and value(s). */
export interface Narrowed {
readonly argument: string;
readonly values: readonly unknown[];
}
export interface ScopeRelation {
/** `a` relative to `b`: `wider` = `a`'s scope holds all of `b`'s and more. */
readonly relation: 'same' | 'wider' | 'narrower' | 'other';
/** For `wider`: what `b` narrowed that `a` did not. */
readonly narrowed: readonly Narrowed[];
/** For `wider`: `b`'s window is strictly inside `a`'s. */
readonly windowNarrowed: boolean;
}
/**
* How `a`'s composed scope relates to `b`'s. Different tools are always `other`. A period
* compares the spans the calls ran with before any unresolved spelling — no clock is needed.
*/
export declare function scopeRelation(a: TurnCall, b: TurnCall, tool: DeclaredTool | undefined, _clock?: string): ScopeRelation;
/** The reads of one key, in order, merged. */
export declare function mergeKeyReadings(calls: readonly TurnCall[]): {
readonly reading?: TurnCall;
readonly disagree: boolean;
};
export {};