/** * interview.ts, a few questions that guide the owner to a good idea. * * *"if yes, ask me a few questions to guide me into a good gift idea. i feel * like a short interview section would be very useful here."* * * Three properties, each of which is a decision rather than a detail: * * 1. **It does not recommend.** The original framing was *"it doesn't need to * make a recommendation"*, and nothing here proposes a gift. It asks * questions. Judgement stays with the owner, which is also why the outcome * is recorded as what THEY landed on rather than what was suggested. * 2. **It opens from what the profile already knows.** People and Notes are * prose preserved verbatim; if the owner has mentioned she is into * something, the first question starts there. That is the difference * between useful and generic, and it is why {@link openInterview} takes * profile lines rather than a name. * 3. **It is genuinely short.** The question count is a setting with a default * of three. A long one is a form, and the owner will stop answering it. * * A thread the owner walks away from is a DROPPED thread, not a completion. The steps * and the answers so far persist, so resuming picks up at the next unanswered * question rather than starting again, that is what makes the open-item loop's * third case work. */ import type { ProfileLine } from '../owner-profile/types.js'; import type { IsoDate } from './dates.js'; import type { GiftRecord, Interview, InterviewStep, Occasion } from './types.js'; /** The profile line most likely to be about what she is interested in. */ export declare function interestLine(lines: readonly ProfileLine[]): string; export interface OpenInterviewInput { readonly occasion: Occasion; readonly occurrence: IsoDate; readonly now: number; /** Profile lines mentioning the person, from `profile.person`. */ readonly personLines: readonly ProfileLine[]; /** What the owner landed on in previous years, newest first. */ readonly history: readonly GiftRecord[]; /** How many questions to ask. Clamped to at least one. */ readonly maxQuestions: number; } /** * Build the questions. * * Order matters: the one grounded in something the owner already told the system comes * first, because it is the question that proves the thing was listening. A blank * opening question is what makes an interview feel like a form. */ export declare function interviewSteps(input: OpenInterviewInput): readonly InterviewStep[]; export declare function interviewIdFor(occasionId: string, occurrence: IsoDate): string; /** Start an interview. Nothing is asked until a surface renders the first step. */ export declare function openInterview(input: OpenInterviewInput): Interview; /** * The next unanswered question, or `undefined` when they are all answered. * * Resumption is exactly this call: an interview reloaded from disk after the * owner went quiet mid-thread returns the question they did not get to, not * the first one. Re-asking answered questions is how a resumed thread turns * into a restarted one. */ export declare function nextStep(interview: Interview): InterviewStep | undefined; /** Record one answer. Re-answering a step replaces the earlier answer. */ export declare function answerStep(interview: Interview, stepId: string, text: string, now: number): Interview; /** * Close the interview with what the owner landed on. * * Recording the OUTCOME rather than merely that the owner said yes is the * whole point of the history: year three should not steer where year one * did, and "the owner said yes in 2026" cannot tell it anything. */ export declare function completeInterview(interview: Interview, landedOn: string, now: number): Interview; /** True when the interview has an outcome. */ export declare function isComplete(interview: Interview): boolean; /** The gift record a completed interview produces. */ export declare function giftRecordFor(interview: Interview): GiftRecord | null; //# sourceMappingURL=interview.d.ts.map