import type { BrainstormQuestion, MissionType } from "./state.js"; /** Marker written at the top of mission-brief.md while a brief is still * being shaped — the /senai-brainstorm-approve command removes it. The * marker is a single line so it is robust to editors. */ export declare const BRIEF_DRAFT_MARKER = "\n"; /** Top-level sections every mission-brief.md must contain, in order. Doctor * uses this list to validate both brainstorm-scoped and run-scoped briefs. */ export declare const REQUIRED_BRIEF_SECTIONS: readonly string[]; /** Required sections for a mission type: the base 6 plus the pack's extra * sections (bugfix adds 4; all other types currently add none). */ export declare function requiredBriefSectionsFor(type: MissionType | undefined): readonly string[]; /** Parse the brief's own "## Mission type" section. Returns undefined when * the section is missing or holds no known type — callers then fall back * to base-6 / untyped behavior. Substring match with MISSION_TYPES order, * so "test" never shadows a more specific type name in the body. */ export declare function parseBriefMissionType(brief: string): MissionType | undefined; /** ISO-ish timestamp safe for filenames: 2026-09-01-1244. */ export declare function slugifyStamp(d?: Date): string; /** Slugify a short free-form label. Falls back to "discussion" when the * input collapses to an empty string after normalization. */ export declare function slugifyLabel(input: string): string; export interface DiscussionLocation { transcriptPath: string; briefPath: string; /** Monotonic sequence number within the run (or brainstorm), 2-digit padded. */ sequence: string; /** Brainstorm run id when the brief lives under .IDE_Plans/pi-senai/Brainstorm/. */ brainstormRunId?: string; } export interface RecordDiscussionInput { cwd: string; /** Brainstorm run id — preferred path. Lives under * .IDE_Plans/pi-senai/Brainstorm//. When present, takes * precedence over legacy `runId`. */ brainstormRunId?: string; /** Pass a runId to record under that active run; omit to record under the * legacy pre-run folder (backward compat only). */ runId?: string; label: string; /** Body of the transcript (the parent's Q&A log + free-form notes). */ transcript: string; /** Mission type picked in UNDERSTAND. Bugfix briefs get the pack's extra * sections seeded into the skeleton (with `_TBD_`) so the approve gates * have headings to check. */ missionType?: MissionType; /** A "## Discussion — " section appended to the brief, with * inline amendments (cross-outs + new bullets) per the approved design. */ discussionSection: string; } /** Append a discussion transcript + a "## Discussion — " section to * the brief, then return the absolute paths the caller records into * state.discussionEvents. The brief is created on first call; the draft * marker stays at the top until /senai-brainstorm-approve clears it. */ export declare function recordDiscussion(input: RecordDiscussionInput): DiscussionLocation; /** * Clear the draft marker (first line) of mission-brief.md, leaving the * rest intact. Called by /senai-brainstorm-approve. * * Idempotent: if the marker is already gone (the brief was finalized on a * previous call), this is a no-op. Before rewriting, the function copies * the unfinalized brief to `.bak` so a corrupted finalization * (or an interrupted write) can be recovered by hand. Writes go through * the atomic helper. */ export declare function finalizeMissionBrief(briefPath: string): void; /** Cross-out old bullet text and append a replacement, preserving the * superseded text in place. Pure helper used by the parent LLM via the * skill — exposed for unit testing. */ export declare function amendBullet(brief: string, oldLine: string, replacement: string): string; /** Validate a brief has all required top-level sections, in order. * Returns the list of missing sections; empty list = ok. The section list * defaults to the base 6; callers that know the mission type pass * requiredBriefSectionsFor(type) so pack sections are validated too. */ export declare function validateBriefSections(brief: string, sections?: readonly string[]): string[]; /** Placeholder marker for unfilled brief sections. Recognized by * validateBriefContent below. */ export declare const BRIEF_CONTENT_PLACEHOLDER = "_TBD_"; /** Validate that every required section has REAL content — not `_TBD_` and * not empty. Returns the list of unfilled section names; empty list = ok. * This is stricter than validateBriefSections, which only checks that the * section heading exists. The brainstorm guard layer (Phase 2) wraps this * to hard-reject finalize when the brief is still skeletal. */ export declare function validateBriefContent(brief: string): string[]; /** validateBriefContent against the section list of a specific mission * type. Bugfix briefs must fill the base 6 plus the 4 pack sections; a * hard reject names every missing or placeholder section so the parent * can fix them in one pass. */ export declare function validateBriefContentForType(raw: string, type: MissionType | undefined): { ok: boolean; reason?: string; }; /** ────────────────────────────────────────────────────────────────────── * Decision ledger (Agreed / Not wanted / Open) * ────────────────────────────────────────────────────────────────────── */ /** Markers wrapping the machine-managed decisions block inside a discussion * document. The block is REGENERATED from state.brainstormQuestions on * every change, so it is always consistent — no incremental edits. */ export declare const DECISIONS_BLOCK_START = ""; export declare const DECISIONS_BLOCK_END = ""; /** Render the three decision lists from the question ledger. * - agreed → "## Agreed" * - not-wanted / replaced → "## Not wanted" (with reason; replaced keeps * the strikethrough so the superseded text survives) * - draft / discussing → "## Open" (with the current state labeled) */ export declare function renderDecisionsBlock(questions: BrainstormQuestion[]): string; /** Write (or refresh) the decisions block in the current discussion * document. Returns the document path so callers can surface it. */ export declare function syncDecisionsToDiscussionDoc(cwd: string, brainstormRunId: string, questions: BrainstormQuestion[]): string; /** Append a rejected question to the brief's "## Out-of-scope" section with * its reason ("deferred, not forgotten"). Idempotent per question id. * Returns true when a bullet was added. */ export declare function appendOutOfScopeDecision(briefPath: string, question: BrainstormQuestion): boolean;