Skip to content

osrforge.convert

The end-to-end conversion and its resume: preprocess → survey → content → monsters → mapread → assemble.

Each stage writes its own run.json status; a stage failure propagates after its failed status is written, keeping everything upstream. rerun resumes: it re-runs the named stage and everything downstream through assemble — the one reading that leaves a workdir artifact-consistent, since every stage already clears or supersedes its downstream caches. on_progress receives the stage-transitions-and-usage stream promised to hosts, covering exactly the stages the chain runs.

KNOB_STAGES module-attribute

KNOB_STAGES: Mapping[str, Stage] = {
    "render_dpi": Stage.PREPROCESS,
    "max_pages": Stage.PREPROCESS,
    "max_source_bytes": Stage.PREPROCESS,
    "blank_page_renders": Stage.PREPROCESS,
    "survey_max_pages": Stage.SURVEY,
    "content_batch_pages": Stage.CONTENT,
    "monster_fuzzy_threshold": Stage.MONSTERS,
    "monster_llm_top_k": Stage.MONSTERS,
    "custom_monsters": Stage.MONSTERS,
    "map_reading": Stage.MAPREAD,
    "unresolved_fallback": Stage.ASSEMBLE,
}

Each settings knob's owning stage — the drift guard's table.

Updating a knob whose owning stage is upstream of the rerun stage is rejected: the drifted run.json echo would otherwise claim, say, pages were rendered at a DPI they weren't.

RUNNABLE_STAGES module-attribute

The six chain steps, in order — geometry has no independent run (it lives inside assembly).

OnProgress module-attribute

OnProgress = Callable[[StageEvent], None]

The progress callback: called synchronously with each stage transition.

ConversionResult dataclass

ConversionResult(run: RunMeta, adventure: Adventure, report: ExtractionReport)

convert's and rerun's return: the final run metadata, the draft, and its report.

run instance-attribute

run: RunMeta

adventure instance-attribute

adventure: Adventure

report instance-attribute

StageEvent dataclass

StageEvent(stage: Stage, status: StageState, usage: TokenUsage | None = None)

One progress event: a stage transition, with usage on completion.

Events cover the chain steps the run drives; the geometry stage tracked inside assemble() gets no separate event — from a host's perspective it is an implementation detail of assembly, and its status is still readable in run.json.

stage instance-attribute

stage: Stage

status instance-attribute

status: StageState

usage class-attribute instance-attribute

usage: TokenUsage | None = None

convert

convert(
    pdf_path: Path,
    workdir: Path,
    provider: ModelProvider,
    settings: ConversionSettings | None = None,
    on_progress: OnProgress | None = None,
) -> ConversionResult

Convert a module PDF into a draft adventure, end to end.

Parameters:

Name Type Description Default
pdf_path Path

The source module PDF.

required
workdir Path

The workdir root to create or rebuild.

required
provider ModelProvider

The model provider for the extraction stages.

required
settings ConversionSettings | None

Pipeline settings; defaults to ConversionSettings().

None
on_progress OnProgress | None

Optional callback receiving a running event before each stage and a completed event (with that stage's usage from run.json) after it; a failing stage emits failed before the error propagates.

None

Returns:

Type Description
ConversionResult

The conversion result.

Raises:

Type Description
PdfError

If preprocessing rejects the source.

ExtractionError

If the survey finds nothing.

ProviderError

On provider transport, auth, or rate-limit exhaustion.

SchemaValidationError

If the provider exhausts its schema budget.

OverrideError

If an existing overrides.yaml entry cannot take effect.

Examples:

from pathlib import Path

from osrforge import ConversionSettings, convert
from osrforge.providers.foundry import FoundryProvider, FoundrySettings

provider = FoundryProvider(FoundrySettings.from_env())
result = convert(Path("module.pdf"), Path("module.forge"), provider, ConversionSettings())
print(result.report.validation.passed)

rerun

rerun(
    workdir: Path,
    stage: Stage,
    provider: ModelProvider | None = None,
    settings_updates: Mapping[str, object] | None = None,
    on_progress: OnProgress | None = None,
) -> ConversionResult

Re-run one stage — and everything downstream of it — from cached upstream outputs.

The stage argument is the skip: the user names what to redo and everything upstream is kept verbatim (no automatic staleness detection). rerun(…, Stage.ASSEMBLE) needs no provider and is the documented correction-loop assemble; rerun preprocess reads the workdir's own source.pdf.

Parameters:

Name Type Description Default
workdir Path

An existing workdir (its run.json must be present).

required
stage Stage

The stage to resume from — one of RUNNABLE_STAGES (geometry has no independent run; it lives inside assembly).

required
provider ModelProvider | None

The model provider; required exactly when the resumed chain contains a model stage.

None
settings_updates Mapping[str, object] | None

Settings knobs to update in the run.json echo before the chain runs — the echo stays the single source of truth stages read. A knob owned by a stage upstream of stage is rejected: the drifted echo would lie about how upstream artifacts were produced.

None
on_progress OnProgress | None

The same stage-event stream convert emits, covering exactly the stages the resumed chain runs.

None

Returns:

Type Description
ConversionResult

The conversion result.

Raises:

Type Description
ValueError

If stage is not runnable, the resumed chain needs a provider none was given for, a settings update targets an upstream stage, or a stage precondition fails (incomplete upstream).

ValidationError

If a settings update names an unknown knob or an invalid value.

Examples:

from pathlib import Path

from osrforge.contracts.run import Stage
from osrforge.convert import rerun

# The correction loop's re-assembly: no provider, no model call.
result = rerun(Path("module.forge"), Stage.ASSEMBLE)

# Re-resolve monsters with the stat-block pass off, then re-assemble.
result = rerun(
    Path("module.forge"),
    Stage.MONSTERS,
    provider=provider,
    settings_updates={"custom_monsters": "off"},
)