forge: high effort for prose-craft passes, max only for audit

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.
This commit is contained in:
Sulkta 2026-05-14 22:32:52 -07:00
parent b5576f4ec5
commit c863543580

View file

@ -7,7 +7,7 @@
//! //!
//! 1. **gen** — produces a new chapter draft from an assembled //! 1. **gen** — produces a new chapter draft from an assembled
//! context blob (parent prose + bible + characters + similarity- //! 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 //! 2. **cleanup** — polishes the draft for prose quality, voice
//! consistency, dialogue rhythm, pacing dead spots. Same Opus, //! consistency, dialogue rhythm, pacing dead spots. Same Opus,
@ -43,8 +43,11 @@ use crate::config::ForgeConfig;
pub struct Forge { pub struct Forge {
client: Client, client: Client,
/// The model alias we pass to clawdforge. Skald is opinionated: /// The model alias we pass to clawdforge. Skald is opinionated:
/// always opus max effort. (See `project_story_writer_container.md`.) /// always opus. Story-writing passes (gen/cleanup/narrate_prep/
/// `clawdforge` resolves the alias to the actual claude CLI flag. /// 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, model: String,
} }
@ -136,7 +139,7 @@ impl Forge {
model: Some(self.model.clone()), model: Some(self.model.clone()),
system: Some(system), system: Some(system),
system_mode: Some(mode), system_mode: Some(mode),
effort: Some(Effort::Max), effort: Some(Effort::High),
timeout_secs: Some(1800), timeout_secs: Some(1800),
..Default::default() ..Default::default()
}; };
@ -161,7 +164,7 @@ impl Forge {
model: Some(self.model.clone()), model: Some(self.model.clone()),
system: Some(system), system: Some(system),
system_mode: Some(mode), system_mode: Some(mode),
effort: Some(Effort::Max), effort: Some(Effort::High),
timeout_secs: Some(1800), timeout_secs: Some(1800),
..Default::default() ..Default::default()
}; };
@ -231,9 +234,9 @@ impl Forge {
model: Some(self.model.clone()), model: Some(self.model.clone()),
system: Some(system), system: Some(system),
system_mode: Some(mode), system_mode: Some(mode),
// Tag placement IS a craft choice; max effort buys // Tag placement IS a craft choice; high effort is
// better beat sense. Same posture as gen/cleanup. // plenty for beat sense. Same posture as gen/cleanup.
effort: Some(Effort::Max), effort: Some(Effort::High),
timeout_secs: Some(1800), timeout_secs: Some(1800),
..Default::default() ..Default::default()
}; };
@ -251,7 +254,8 @@ impl Forge {
/// ///
/// Author REQUIRED — a rewrite without an author has no target /// Author REQUIRED — a rewrite without an author has no target
/// voice. SystemMode::Replace; the model BECOMES the author. /// 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( pub async fn rewrite(
&self, &self,
prose: &str, prose: &str,
@ -272,7 +276,7 @@ impl Forge {
model: Some(self.model.clone()), model: Some(self.model.clone()),
system: Some(system), system: Some(system),
system_mode: Some(SystemMode::Replace), system_mode: Some(SystemMode::Replace),
effort: Some(Effort::Max), effort: Some(Effort::High),
timeout_secs: Some(1800), timeout_secs: Some(1800),
..Default::default() ..Default::default()
}; };
@ -516,6 +520,10 @@ fn build_audit_request(model: &str, parent: &str, sequel: &str, bible: &str) ->
prompt, prompt,
model: Some(model.to_string()), model: Some(model.to_string()),
system: Some(SYSTEM_AUDIT.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), timeout_secs: Some(600),
..Default::default() ..Default::default()
} }