UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

125 lines (124 loc) • 6.45 kB
/** * coverage/inProgress — "this has not finished; its outcome is not known yet". * * Pattern: one rule set, two doors (the `period.ts` law): `coverage()`'s mint * REFUSES a malformed `inProgress` at the line the author wrote; the * dispatch door READS a foreign `in_progress` (a sidecar in another * language mints `af_coverage` too) and drops a malformed one from the * record, dev-warned, never repaired. Both ask {@link readInProgressList}. * Role: core/ layer, pure. * Emits: N/A (the caller emits `agentfootprint.tools.coverage_declared`). * * ## Why a third outcome needs its own words * * A vendor state machine has at least three outcomes: settled-ok, in * progress, failed. A tool that tests "equals the success value" counts the * middle one as a failure — a backup two hours into its run read beside a VM * with no backup at all; an array with zero unhealthy replication sessions * read as "97 non-OK" because 96 were still synchronizing. Both were measured * in the field, and both would have been escalated. * * The fix belongs in the TOOL: only the tool knows which of its vendor's states * are in flight, and when the vendor gives its own verdict field that verdict * wins over a state name. So this library never reads a state string. What it * adds is a place to SAY the third outcome — `coverage(value, { checked, * inProgress })` — so the model reads it as data, the record keeps it, and a * person reading the answer sees it beside the other limits. * * ## What it deliberately does not do * * It does not change the answer's standing. "Not sure" would be right only * when the answer STATES a settled outcome for an item in flight, and the * record holds the answer as prose: telling "vm-42's backup is still running" * from "vm-42 has no backup" is a reading of words — a phrase parser or a * model judge, both refused here. Firing on every answer from such a tool would * mark the honest answers too. So the declaration is a LABEL: served, recorded, * printed with the limits (docs/design/honesty/results.md § 11). */ import type { InProgressItem } from './types.js'; /** * The wire spelling as DATA — the key an in-progress list sits under inside * `af_coverage`, and its one item key that is not the coverage items' own. * `canonical-notes.json` publishes it (`scripts/gen-canonical-notes.mjs`), so a * tool written in another language mints it byte for byte. */ export declare const IN_PROGRESS_WIRE: Readonly<{ /** The key the list sits under inside `af_coverage`. */ readonly key: "in_progress"; /** How many things one entry stands for — a positive whole number. */ readonly count: "count"; }>; /** * The one clause the dispatch door appends to the note of a ledger that * declares a well-formed, non-empty `in_progress` — the model is SERVED it; the * tool's own output keeps `COVERAGE_NOTE`. Static, never interpolated; anchored * to "the call this result answers" (the container deictic's own anchor), so a * later call re-reading it cannot take it for its own. Added at the door, not * at the mint, so an envelope a sidecar minted gets it too. */ export declare const IN_PROGRESS_CLAUSE: string; /** What one list reads as: its items, or the first problem. */ export type InProgressReading = { readonly items: readonly InProgressItem[]; readonly problem?: undefined; } | { readonly items?: undefined; readonly problem: string; }; /** * THE rule set for one list. `at` is the list's name as the reader spells it * (`inProgress` at the mint, `in_progress` on the wire). `strictKeys` refuses * an item key the shape does not have (the mint: a misspelt `why` must not * vanish); the wire reader copies the known keys and lets the rest ride, as * every recognized envelope does. Everything else is one rule. */ export declare function readInProgressList(raw: unknown, at: string, strictKeys: boolean): InProgressReading; /** * The mint's reading: the normalized items, `[]` when omitted (`undefined` or * `null`) — and a refusal, thrown where `coverage()` is called, for anything * the rule set refuses. */ export declare function mintInProgress(raw: unknown): readonly InProgressItem[]; /** * A ledger marker's `in_progress`, read for the RECORD: the items when the list * is well-formed and non-empty, else `undefined` — a malformed one dropped from * the record and named once per tool in dev mode (the model still reads what * the tool wrote, without the clause). */ export declare function inProgressOf(marker: { readonly in_progress?: unknown; }, toolName: string | undefined): readonly InProgressItem[] | undefined; /** * Forget every dropped-list warning issued so far. * @internal test seam — the ledger is process-wide and warn-once. */ export declare function _resetInProgressWarnings(): void; /** * One ledger marker as SERVED: {@link IN_PROGRESS_CLAUSE} after its note when * it declares a well-formed, non-empty `in_progress`. The same reference back * otherwise — an undeclared ledger is served byte for byte — and when the note * already ends with the clause (served once is served). */ export declare function withInProgressServed<T extends object>(marker: T): T; /** * The inverse, for a reader of what the model was served (the evidence * projection): the marker with the clause removed from the END of its note — * words the library derived never ground an answer. The same reference back * when the note does not end with it. */ export declare function withoutInProgressServed<T extends object>(marker: T): T; /** The section heading the limits block prints in-progress items under. Stable — readers match on it. */ export declare const IN_PROGRESS_SECTION_LABEL = "In progress (outcome not known yet)"; /** * One line of that section: the tool, then the item as it declared it — its * count in brackets, its `why` after a dash. Static words around the tool's own. * * @example * ```ts * inProgressLine('replication_sessions', { what: 'sessions still synchronizing', count: 96 }); * // 'replication_sessions: sessions still synchronizing (96)' * ``` */ export declare function inProgressLine(toolName: string, item: InProgressItem): string; /** One item as detached plain data — the declared fields, nothing else. */ export declare function copyInProgressItem(item: InProgressItem): InProgressItem;