From 98233182fd4b54f19edcf211b4eddc1352dd5987 Mon Sep 17 00:00:00 2001 From: Kayos Date: Thu, 14 May 2026 22:32:52 -0700 Subject: [PATCH] forge: high effort for prose-craft passes, max only for audit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gen, cleanup, narrate_prep and rewrite drop from max to high effort. Audit keeps max — it is the one pass doing real reasoning (canon drift, timeline gaps, retcons) rather than prose-craft, so it is worth the frontier spend. Prose-craft is "good enough" at high. This also keeps the all-Opus skald pattern under the $200/month claude -p cap landing next month. --- skald-core/src/forge.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/skald-core/src/forge.rs b/skald-core/src/forge.rs index 75c22b1..9812459 100644 --- a/skald-core/src/forge.rs +++ b/skald-core/src/forge.rs @@ -7,7 +7,7 @@ //! //! 1. **gen** — produces a new chapter draft from an assembled //! context blob (parent prose + bible + characters + similarity- -//! matched passages, all from the database). Opus, max effort. +//! matched passages, all from the database). Opus, high effort. //! //! 2. **cleanup** — polishes the draft for prose quality, voice //! consistency, dialogue rhythm, pacing dead spots. Same Opus, @@ -43,8 +43,11 @@ use crate::config::ForgeConfig; pub struct Forge { client: Client, /// The model alias we pass to clawdforge. Skald is opinionated: - /// always opus max effort. (See `project_story_writer_container.md`.) - /// `clawdforge` resolves the alias to the actual claude CLI flag. + /// always opus. Story-writing passes (gen/cleanup/narrate_prep/ + /// rewrite) run at HIGH effort; only the audit pass runs at MAX — + /// audit genuinely needs the frontier reasoning, prose-craft does + /// not, and the $200/mo `claude -p` cap makes max-everywhere + /// unaffordable. `clawdforge` resolves the alias to the CLI flag. model: String, } @@ -136,7 +139,7 @@ impl Forge { model: Some(self.model.clone()), system: Some(system), system_mode: Some(mode), - effort: Some(Effort::Max), + effort: Some(Effort::High), timeout_secs: Some(1800), ..Default::default() }; @@ -161,7 +164,7 @@ impl Forge { model: Some(self.model.clone()), system: Some(system), system_mode: Some(mode), - effort: Some(Effort::Max), + effort: Some(Effort::High), timeout_secs: Some(1800), ..Default::default() }; @@ -231,9 +234,9 @@ impl Forge { model: Some(self.model.clone()), system: Some(system), system_mode: Some(mode), - // Tag placement IS a craft choice; max effort buys - // better beat sense. Same posture as gen/cleanup. - effort: Some(Effort::Max), + // Tag placement IS a craft choice; high effort is + // plenty for beat sense. Same posture as gen/cleanup. + effort: Some(Effort::High), timeout_secs: Some(1800), ..Default::default() }; @@ -251,7 +254,8 @@ impl Forge { /// /// Author REQUIRED — a rewrite without an author has no target /// voice. SystemMode::Replace; the model BECOMES the author. - /// Max effort: re-authoring is the heaviest prose-craft task. + /// High effort: re-authoring is heavy prose-craft, but it's + /// still craft, not reasoning — max is reserved for audit. pub async fn rewrite( &self, prose: &str, @@ -272,7 +276,7 @@ impl Forge { model: Some(self.model.clone()), system: Some(system), system_mode: Some(SystemMode::Replace), - effort: Some(Effort::Max), + effort: Some(Effort::High), timeout_secs: Some(1800), ..Default::default() }; @@ -516,6 +520,10 @@ fn build_audit_request(model: &str, parent: &str, sequel: &str, bible: &str) -> prompt, model: Some(model.to_string()), system: Some(SYSTEM_AUDIT.to_string()), + // Audit is the one pass that keeps MAX effort — catching + // canon drift, timeline gaps and retcons is reasoning work + // worth the frontier spend; prose-craft passes run at high. + effort: Some(Effort::Max), timeout_secs: Some(600), ..Default::default() }