import { Outcome } from './types.ts'; import type { Abandoned, Ask, CommandContext, CommandRule, Decision, Deny, Pending, SessionDecisionsQuery } from './types.ts'; import { Scope } from './types.ts'; /** * A host that answers an Ask inside the line. * * `signal` is the run's, so a host that puts a question to a person can * take its prompt down when the run it belongs to is killed. Ignoring it * is safe: the ledger stops waiting on the handler either way. */ export type AskHandler = (record: Decision, signal?: AbortSignal) => Promise; /** * The id a record is named by: a digest of what was asked, so a retry * of the same line quotes the same id and a host answers it once. * * The id names the record; it does not decide what a retry matches. * That comparison is made against the recorded fields themselves * (`covers`), so a line the digest cannot tell apart from another still * cannot borrow its answer. */ export declare function decisionId(sessionId: string, cwd: string, argv: readonly string[]): Promise; /** * The rule an Ask is keyed on: the document's, or for a coded Ask one * synthesized over the program that asked, so a session answer reads * "stop asking me about this program". */ export declare function askRule(ctx: CommandContext, ask: Ask): CommandRule; /** * Whether an answered record answers this rule of this line. * * A ONCE answer covers the exact line it was given for, compared field * by field. A SESSION answer covers every line the same rule asks * about. Both are keyed on the rule as well as the words: an answer * that outlives a rule change (a persisted store reopened under an * edited profile) must not answer the new rule's ask, and a stale * refusal must not speak in its voice. */ export declare function covers(record: Decision, rule: CommandRule, argv: readonly string[], cwd: string): boolean; /** * The workspace's decision ledger: turns an Ask into run, refuse or * pending, and is the host's handle on every question raised and every * answer given. * * One record type, one store. A `Decision` with no outcome is a * question waiting; one with an outcome is a question settled, and how * far the answer reaches is its `scope`. Keeping both in one place is * the point: they used to be two stores, a pending map that vanished on * restart and a per-session answer list that did not, so a host could * see a question that no longer existed or miss one that did. * * Mirrors the Python Decisions. */ export declare class Decisions { private readonly sessions; private readonly onAsk; private readonly memory; constructor(sessions?: SessionDecisionsQuery | null, onAsk?: AskHandler | null); /** Every record, oldest first: questions waiting and questions settled. */ list(sessionId?: string): Decision[]; /** The records nobody has answered, oldest first. */ pending(sessionId?: string): Decision[]; /** * Answer a waiting record, yes or no. * * ALLOW at ONCE passes the retry of the exact line and is consumed by * it; at SESSION it passes every line the rule covers for the rest of * the session. DENY refuses the retry in the deny voice, once, and * asking again raises a new record. */ answer(decisionId: string, outcome: Outcome, scope?: Scope, note?: string): Promise; /** * The executor's branch for an Ask: settled records answer it, else * the question is raised now. * * Every rule the ask names has to be answered, because each won a * subject of its own and a nod covers the subject it was given for. * They are asked one at a time, the retry of the line raising the * next, and a ONCE answer is only spent once the whole line is * answered: spending one while another is still waiting would make * the first question come back on every retry. * * @param ctx the classified command being admitted. * @param ask the chain's Ask. * @param signal the run's abort signal, so a question outlives * neither its run's deadline nor a caller's kill. * @returns the refusal, the question left waiting, an Abandoned for a * run killed mid-question, or null to run. */ resolve(ctx: CommandContext, ask: Ask, signal?: AbortSignal): Promise; /** * What the settled records alone say about an asked line. * * The read-only half of `resolve`, and the only half a dry run may * take: it consults what the session already holds and stops there, * spending nothing, recording no question and never reaching the * host. So `explain` can report that a line would be refused, or * would still be waiting, without a question arriving for a line * nobody typed. */ held(ctx: CommandContext, ask: Ask): Promise; /** * Record one rule of a line as a question and put it to the host, * null when the host said yes. * * A question already waiting is reused rather than duplicated, so a * retry keeps quoting one id. * * The host is given the run's signal and the wait is bounded by it, * because a host that asks a person can take an unbounded amount of * time and the executor's own cooperative abort checks cannot reach * inside that wait: without this a killed or timed-out run would sit * here until somebody answered. * * A run killed mid-question is reported as Abandoned and its record is * left waiting, with whatever the host eventually says dropped rather * than recorded: an ALLOW banked against a run that is already dead * would leave a spent-once grant in the ledger for the next identical * line to take, with nobody asked. * * @param ctx the classified command being admitted. * @param rule the one rule of the line being asked about. * @param argv the line, command name first. * @param signal the run's abort signal. * @returns the refusal, the question left waiting, an Abandoned for a * run killed mid-question, or null to run. */ private raise; /** The question already recorded for this rule of this line. */ private waiting; /** * The answered record standing behind one rule of a line, null when * nobody has answered it. */ private static settled; /** Drop the ONCE answers this line just used up. */ private spend; private keys; private records; private set; private add; private flush; } //# sourceMappingURL=decisions.d.ts.map