فهرست منبع

fix(writer): pass moodDirective and titleDirective through to governed prompt

The planner's cadence analysis produces moodDirective and titleDirective
in ChapterIntent, but after v11 switched the writer to brief-only mode,
these signals were lost — the governed prompt only read ChapterBrief.

Now runner.prepareWriteInput passes plan.intent.moodDirective and
plan.intent.titleDirective through WriteChapterInput, and the governed
user prompt renders them as a "## Cadence Directives" section alongside
the brief block.

This is a stop-gap: the moodDirective's "force cooldown after N chapters
of high pressure" logic doesn't align with new.txt's rhythm model
(objective-cycle based, not mood-toggle based), but restoring the signal
is better than losing it entirely. v12 should redesign the rhythm
control around objective cycles.
Ma 7 ماه پیش
والد
کامیت
5a93378fef
2فایلهای تغییر یافته به همراه30 افزوده شده و 1 حذف شده
  1. 27 0
      packages/core/src/agents/writer.ts
  2. 3 1
      packages/core/src/pipeline/runner.ts

+ 27 - 0
packages/core/src/agents/writer.ts

@@ -50,6 +50,8 @@ export interface WriteChapterInput {
   readonly externalContext?: string;
   readonly chapterIntent?: string;
   readonly chapterBrief?: ChapterBrief;
+  readonly moodDirective?: string;
+  readonly titleDirective?: string;
   readonly contextPackage?: ContextPackage;
   readonly ruleStack?: RuleStack;
   readonly trace?: ChapterTrace;
@@ -196,6 +198,8 @@ export class WriterAgent extends BaseAgent {
       ? this.buildGovernedUserPrompt({
           chapterNumber,
           chapterBrief: input.chapterBrief,
+          moodDirective: input.moodDirective,
+          titleDirective: input.titleDirective,
           contextPackage: input.contextPackage,
           ruleStack: input.ruleStack,
           trace: input.trace,
@@ -813,6 +817,8 @@ ${lengthRequirementBlock}
   private buildGovernedUserPrompt(params: {
     readonly chapterNumber: number;
     readonly chapterBrief: ChapterBrief;
+    readonly moodDirective?: string;
+    readonly titleDirective?: string;
     readonly contextPackage: ContextPackage;
     readonly ruleStack: RuleStack;
     readonly trace?: ChapterTrace;
@@ -848,11 +854,13 @@ ${lengthRequirementBlock}
       ? `\n${sanitizeNarrativeEvidenceBlock(params.selectedEvidenceBlock, language)}\n`
       : "";
     const briefNarrative = renderBriefAsNarrativeBlock(params.chapterBrief, language);
+    const cadenceBlock = this.buildCadenceDirectiveBlock(params.moodDirective, params.titleDirective, language);
 
     if (params.language === "en") {
       return `Write chapter ${params.chapterNumber}.
 
 ${briefNarrative}
+${cadenceBlock}
 
 ## Selected Context
 ${contextSections || "(none)"}
@@ -878,6 +886,7 @@ ${lengthRequirementBlock}
     return `请续写第${params.chapterNumber}章。
 
 ${briefNarrative}
+${cadenceBlock}
 
 ## 已选上下文
 ${contextSections || "(无)"}
@@ -920,6 +929,24 @@ ${lengthRequirementBlock}
     return joined || undefined;
   }
 
+  private buildCadenceDirectiveBlock(
+    moodDirective: string | undefined,
+    titleDirective: string | undefined,
+    language: "zh" | "en",
+  ): string {
+    if (!moodDirective && !titleDirective) return "";
+    const isEn = language === "en";
+    const lines: string[] = [];
+    if (moodDirective) {
+      lines.push(`- ${isEn ? "mood" : "情绪节奏"}: ${moodDirective}`);
+    }
+    if (titleDirective) {
+      lines.push(`- ${isEn ? "title" : "标题提示"}: ${titleDirective}`);
+    }
+    const heading = isEn ? "## Cadence Directives" : "## 节奏指令";
+    return `\n${heading}\n${lines.join("\n")}`;
+  }
+
   private buildSettlerGovernedControlBlock(
     chapterIntent: string,
     contextPackage: ContextPackage,

+ 3 - 1
packages/core/src/pipeline/runner.ts

@@ -2068,7 +2068,7 @@ ${matrix}`,
     bookDir: string,
     chapterNumber: number,
     externalContext?: string,
-  ): Promise<Pick<WriteChapterInput, "externalContext" | "chapterIntent" | "chapterBrief" | "contextPackage" | "ruleStack" | "trace">> {
+  ): Promise<Pick<WriteChapterInput, "externalContext" | "chapterIntent" | "chapterBrief" | "moodDirective" | "titleDirective" | "contextPackage" | "ruleStack" | "trace">> {
     if ((this.config.inputGovernanceMode ?? "v2") === "legacy") {
       return { externalContext };
     }
@@ -2084,6 +2084,8 @@ ${matrix}`,
     return {
       chapterIntent: plan.intentMarkdown,
       chapterBrief: plan.brief,
+      moodDirective: plan.intent.moodDirective,
+      titleDirective: plan.intent.titleDirective,
       contextPackage: composed.contextPackage,
       ruleStack: composed.ruleStack,
       trace: composed.trace,