import { type LedgerClass } from "./ledger.js"; import { type InterviewCheckpoint } from "./interview-checkpoint.js"; /** * The Interviewer: asks the next right question about a job, turns what a person says into cards * (tasks, tools, waits, decisions, ways out, cases, checks, the account), and proposes the ops. * Two engines behind one interface: a rule engine that follows the open protocol and runs anywhere, * and a model engine (Anthropic Messages API) used when a key is present. Same cards, same ops. */ import type { Board, Job } from "./model.js"; import type { Op } from "./ops.js"; export { byKey, DEFAULT_MODELS, normalizeModelConfig, testModelConnection, ModelConnectionError } from "./providers.js"; export type { ModelConfig, ModelProvider } from "./providers.js"; export interface Line { who: "person" | "interviewer"; text: string; } export interface Card { type: "vocabulary" | "settle" | "update" | "remove" | "replace" | "task" | "job" | "tool" | "wait" | "gate" | "exit" | "case" | "check" | "outcome" | "beneficiary" | "doneWhen" | "context" | "who" | "connect" | "disconnect" | "role" | "mergeRoles"; name: string; detail?: string; quote: string; kind?: string; warning?: string; auto?: boolean; /** said: their words directly · implied: an inference · asked: a gap about to be asked */ confidence?: "said" | "implied" | "asked"; ops: Op[]; } export interface Turn { checkpoint?: InterviewCheckpoint; reply: string; cards: Card[]; done?: boolean; engine: "rules" | "model"; /** the ledger classes this turn was about. One answer often feeds several, and the strip says so. */ topics?: LedgerClass[]; } /** Turn one thing a person said into cards. Heuristic, conservative: a card is only made when the words carry it. */ export declare function extract(text: string, j: Job, b: Board): Card[]; /** The rule engine: what to ask next, given the job and what has been said. */ export declare function nextQuestion(b: Board, j: Job, lines: Line[]): { text: string; done: boolean; }; /** Board-level: start from the goal, outside-in, and sketch jobs as the person talks. */ export declare function extractFlow(text: string, b: Board): Card[]; /** Coverage objectives, deliberately not a bank or sequence of questions. */ export declare const INTERVIEW_COVERAGE: readonly [readonly ["Human purpose", "Beneficiary, desired change, success evidence, whose interests conflict, and what should remain under human control."], readonly ["Work in context", "Triggers, actual versus intended practice, roles and handoffs, informal workarounds, tacit coordination, and differences between typical and exceptional cases."], readonly ["Time and scale", "Active effort separately from elapsed time and waiting; frequency with an explicit unit and period; batches, peaks, variability, rework, and rough ranges rather than forced precision."], readonly ["Difficulty and expertise", "What makes the work hard; domain knowledge, experience, tacit cues, interpretation, negotiation, relationships, and judgment. Distinguish tedious effort from consequential judgment."], readonly ["Inputs and access", "Information needed, where it comes from, quality and completeness, examples, tool access and permissions, and what an agent could actually read or change. Reported access is not verified access."], readonly ["Decision structure", "Explicit rules versus ambiguity, changing criteria, novelty, disagreements, dependencies, and when someone must decide rather than infer."], readonly ["Verification and failure", "Observable acceptance criteria, who checks the result, checking effort, error detectability, consequences, reversibility, exceptions, recovery and escalation."], readonly ["Delegation boundaries", "Authority to propose versus act, approval and spending limits, sensitive information, consent, who is accountable, and actions that require a person."], readonly ["Value and feasibility", "Desired benefit such as less waiting, effort, errors or exclusion; data and tool readiness; setup, maintenance, supervision and review costs. Do not fabricate savings or an automation score."], readonly ["Adoption and learning", "Trust, worker and beneficiary preferences, an observable small trial, feedback from real runs, and evidence that would change the design."]]; /** The interviewer's craft, in one place: both engines read it, the model as its system prompt. */ export declare const CRAFT: string; export declare const INTERVIEW_MODES: readonly ["understand", "check", "friction", "opportunities"]; export type InterviewMode = typeof INTERVIEW_MODES[number]; /** Unknown client input must never become a model instruction. */ export declare function normalizeInterviewMode(value: unknown): InterviewMode; /** * Who writes the first draft. * * "ask" records what the person says and nothing else. "draft" lets staves put up a provisional map * from familiar work for them to correct, because people correct far more readily than they generate — * a wrong first draft is often faster than forty questions. * * It is only safe because of what sits under it: a card cannot claim the person said something unless * they did, a class staves drafted cannot be closed by staves, and an inferred card never applies * itself. Turn those off and this becomes a machine for inventing workflows nobody has. */ export type DraftStance = "ask" | "draft"; export declare const DRAFT_STANCES: DraftStance[]; export declare const normalizeDraftStance: (value: unknown) => DraftStance; export interface Session { mode?: InterviewMode; /** whether staves may put up a provisional map, or only record what it is told */ draft?: DraftStance; onReply?: (text: string) => void; mute?: string[]; suggestions?: { type: string; name: string; quote?: string; state: "pending" | "accepted" | "dismissed"; about?: string; }[]; } /** What the person has asked staves to do about blanks. The scaffold paragraph in the craft is * permission, not instruction; this is the instruction, and it is theirs to give. */ export declare const DRAFT_PROTOCOL: Record; export declare function interviewFlow(b: Board, lines: Line[], said: string | null, key?: string | Complete, session?: Session): Promise; /** A completion function: system + user → text. Anthropic API by key, or an MCP client's model via sampling. */ export type Complete = (system: string, user: string, onText?: (text: string) => void) => Promise; /** Decode only a JSON reply string, including incomplete escapes, from actual model output. */ export declare function partialReply(text: string): string; export declare function interviewTurn(b: Board, j: Job, lines: Line[], said: string | null, key?: string | Complete, session?: Session): Promise; /** The browser already appends the latest utterance; API clients may pass it separately. */ export declare function discussionTranscript(lines: Line[], said: string | null): string; /** Board-level model turn: the whole conversation, from the goal. */ export declare function modelFlow(b: Board, lines: Line[], said: string | null, complete: Complete, session?: Session): Promise; export declare function findingsLine(b: Board, findings: { about: string; message: string; }[]): string; export declare function cardsFromModel(raw: any[], b: Board, said?: string | null, priorEvidence?: string[]): Card[]; /** Existing work may evolve, but model prose never becomes an arbitrary operation. */ /** A question or a hedge is not testimony. "maybe the profile feeds the menu?" contains the words but * asserts nothing, and recording it as something they said puts a guess in their mouth wearing their * own sentence. It is still worth drawing — as staves' reading of what they were circling. */ export declare const hedged: (quote: string | undefined) => boolean; /** Their own words, in their latest message, carrying an instruction rather than a musing. */ export declare function instructed(quote: string | undefined, said: string | null | undefined): boolean; export declare function editCardFromModel(raw: unknown, b: Board, said: string | null, scope?: Job): Card | null;