import { ChapterTraceSchema, RuleStackSchema, } from "../models/input-governance.js";
const MAX_OVERRIDE_REASON_CHARS = 80;
function truncateForOverrideReason(value) {
    const collapsed = value.replace(/\s+/g, " ").trim();
    return collapsed.length > MAX_OVERRIDE_REASON_CHARS
        ? `${collapsed.slice(0, MAX_OVERRIDE_REASON_CHARS - 1)}…`
        : collapsed;
}
/**
 * Compose the per-chapter rule stack used by writer / continuity / reviser
 * prompts. Source names follow the Phase 5 layout (story_frame, volume_map,
 * roles/) and activeOverrides are derived from the planner's intent so the
 * "Governed Control Stack" block surfaces the actual gating in effect for
 * the current chapter — it used to be a static stub that ignored both
 * `plan` and `chapterNumber`.
 *
 * Phase hotfix 6 (Option A): make this honestly dynamic instead of deleting
 * it, because writer.ts (~L820/L900), continuity.ts (~L590), and
 * reviser.ts (~L600) all render ruleStack.sections / activeOverrides into
 * the model prompt. Removing the function would require a much larger
 * prompt refactor; making it real fixes the lie at the source.
 */
export function buildGovernedRuleStack(plan, chapterNumber) {
    const activeOverrides = [];
    // L4 → L3: per-chapter prohibitions narrow the planning layer for this
    // chapter only. mustAvoid items come from rules-reader prohibitions +
    // current_focus avoid section (planner.collectMustAvoid).
    for (const item of plan.intent.mustAvoid) {
        activeOverrides.push({
            from: "L4",
            to: "L3",
            target: `chapter:${chapterNumber}/mustAvoid`,
            reason: truncateForOverrideReason(item),
        });
    }
    // L4 → L3: planner-issued style emphasis is also a per-chapter override
    // on the planning layer. Style emphasis surfaces things like POV tightness
    // or character-conflict focus that the writer must honor this chapter.
    for (const item of plan.intent.styleEmphasis) {
        activeOverrides.push({
            from: "L4",
            to: "L3",
            target: `chapter:${chapterNumber}/styleEmphasis`,
            reason: truncateForOverrideReason(item),
        });
    }
    return RuleStackSchema.parse({
        layers: [
            { id: "L1", name: "hard_facts", precedence: 100, scope: "global" },
            { id: "L2", name: "author_intent", precedence: 80, scope: "book" },
            { id: "L3", name: "planning", precedence: 60, scope: "arc" },
            { id: "L4", name: "current_task", precedence: 70, scope: "local" },
        ],
        sections: {
            // Phase 5 authoritative source names (was: story_bible, volume_outline).
            hard: ["story_frame", "current_state", "book_rules", "roles"],
            soft: ["author_intent", "current_focus", "volume_map"],
            diagnostic: ["anti_ai_checks", "continuity_audit", "style_regression_checks"],
        },
        overrideEdges: [
            { from: "L4", to: "L3", allowed: true, scope: "current_chapter" },
            { from: "L4", to: "L2", allowed: false, scope: "current_chapter" },
            { from: "L4", to: "L1", allowed: false, scope: "current_chapter" },
        ],
        activeOverrides,
    });
}
export function buildGovernedTrace(params) {
    return ChapterTraceSchema.parse({
        chapter: params.chapterNumber,
        plannerInputs: params.plan.plannerInputs,
        composerInputs: params.composerInputs,
        selectedSources: params.contextPackage.selectedContext.map((entry) => entry.source),
        notes: [],
    });
}
//# sourceMappingURL=context-assembly.js.map