/** * Phase 9-3: hard gate that a chapter draft actually acts on the hook ledger * the planner declared in the memo's "## 本章 hook 账" / "## Hook ledger for * this chapter" section. * * The planner commits, per chapter, to: * - advance: "name" → state-change * - resolve: "name" → action * * The validator parses those two lists and checks that every committed hook * has observable evidence in the draft. "Evidence" means the draft mentions * at least one keyword from the ledger line's descriptor (hook name, key * noun, etc.). We deliberately do NOT require the draft to repeat the raw * hook_id like "H007" — writers don't embed IDs in prose. */ export interface HookLedgerViolation { readonly severity: "critical"; readonly category: string; readonly description: string; readonly suggestion: string; } export interface HookLedgerEntry { readonly id: string; /** Raw text of the ledger line after the hook_id. */ readonly descriptor: string; /** 2+ char CJK sequences and 3+ letter ASCII words extracted from descriptor. */ readonly keywords: ReadonlyArray; } export interface HookLedger { readonly open: ReadonlyArray; readonly advance: ReadonlyArray; readonly resolve: ReadonlyArray; readonly defer: ReadonlyArray; /** * Count of `[new] ...` placeholder lines in the `open:` subsection. These * are brand-new hooks declared by the planner that have no pre-existing * hook_id (extractLedgerEntry rejects them because they carry no id to * match downstream), but they still count as "a new hook opened" for the * 揭 1 埋 1 floor check. */ readonly newOpenCount: number; } export declare function parseHookLedger(memoBody: string): HookLedger; /** * Enforce: every hook declared under advance / resolve must have observable * evidence in the draft text. We do NOT validate `open` (new hooks don't have * a pre-existing id/descriptor to echo) or `defer` (deferred = deliberately * not touched). * * Additionally enforces the "揭 1 埋 1" hard floor (Xu Er Jia De Mao, 番茄文章 * 10): whenever a chapter resolves one or more hooks, it must open at least * as many new hooks in the same memo. "Resolve without opening" leaves the * reader feeling "解完即索然无味" — the story loses forward pull. The softer * "揭 1 埋 2" rule is a planner-prompt recommendation, not a hard gate here, * because enforcing ×2 would conflict with the "≤ 2 new hooks per chapter" * cap on the planner side when resolve=2. */ export declare function validateHookLedger(memoBody: string, draftContent: string): ReadonlyArray; declare function extractLedgerSection(memoBody: string): string | undefined; declare function extractLedgerEntry(line: string): HookLedgerEntry | undefined; /** * Extract content-matching tokens from a ledger line's descriptor. * * Priority 1: quoted hook name — `H007 "胖虎借条" → ...` — this is the most * informative token the planner attached, and it's what the writer should * echo. We split compound CJK names into leading/trailing 2-grams so * partial echoes still count. * * Priority 2: if no quoted name, fall back to the descriptor text UP TO the * first state-transition arrow (→ or ->), same CJK/ASCII splitting. Anything * AFTER the arrow describes new state, not the hook itself, and risks * character-name false positives. */ declare function extractKeywords(descriptor: string): ReadonlyArray; export declare const INTERNAL: { SUBSECTION_KEYS: readonly (keyof HookLedger)[]; extractLedgerSection: typeof extractLedgerSection; extractLedgerEntry: typeof extractLedgerEntry; extractKeywords: typeof extractKeywords; }; export {}; //# sourceMappingURL=hook-ledger-validator.d.ts.map