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:
Kayos 2026-05-14 22:32:52 -07:00
parent d2442f0a87
commit 98233182fd

View file

@ -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()
}