forge: always --effort max + multi-chapter batch (cap 20)

forge.rs threads Effort::Max on gen + cleanup. Audit + summarize stay
default — they're structured-output / tool-shaped tasks where extended
thinking doesn't help. Bumps subprocess timeout from 600s to 1800s so
max-effort prose-craft has the wall clock it needs.

continue_story::run takes a chapter_count param; loops gen+cleanup per
chapter with each iteration's just-written prose appended to context.
Audit fires once at end against the combined batch vs parent canon.
Cap is 20 (~5h wall clock, ~$600 at max effort — beyond that is
operationally absurd).

CLI: 'skald continue --chapters N'. Web: numeric field on both new-
story and continue forms, 1..=20, defaults to 1.

Vendored clawdforge SDK refreshed for the Effort enum.
This commit is contained in:
Kayos 2026-05-13 14:26:53 -07:00
parent 20e262c85d
commit 3a749b7643
6 changed files with 168 additions and 54 deletions

View file

@ -53,6 +53,6 @@ pub use client::{Client, ClientBuilder};
pub use error::Error;
pub use session::{Session, SessionList, SessionOptions, SessionState, TurnEvent, TurnResult};
pub use types::{
AppToken, AppTokenInfo, FileToken, Healthz, RunFailure, RunRequest, RunResult,
AppToken, AppTokenInfo, Effort, FileToken, Healthz, RunFailure, RunRequest, RunResult,
SystemMode, TokenCreateRequest, TokenList,
};

View file

@ -26,6 +26,30 @@ impl Default for SystemMode {
}
}
/// Maps to `claude -p --effort <level>`. Controls the extended-thinking
/// budget on the reasoning models. `None` on [`RunRequest::effort`] means
/// "let the CLI default decide" (today: medium).
///
/// Use [`Effort::Max`] for prose-craft tasks (fiction generation,
/// long-form rewrite) where the author persona benefits from extra
/// thinking. Leave default for tool-use / structured-JSON tasks.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Effort {
/// `--effort low` — minimum thinking budget.
Low,
/// `--effort medium` — claude's default if no flag is passed.
Medium,
/// `--effort high`.
High,
/// `--effort xhigh`.
Xhigh,
/// `--effort max` — maximum thinking budget. Right for long-form
/// prose generation where the author persona benefits from extra
/// thinking before each paragraph.
Max,
}
/// `GET /healthz` response body.
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Healthz {
@ -80,6 +104,11 @@ pub struct RunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub system_mode: Option<SystemMode>,
/// Maps to `claude -p --effort <level>`. `None` lets the CLI default
/// decide. Use [`Effort::Max`] on prose-craft / long-form generation.
#[serde(skip_serializing_if = "Option::is_none")]
pub effort: Option<Effort>,
/// File tokens previously returned from [`Client::upload_file`].
///
/// [`Client::upload_file`]: crate::Client::upload_file