Imported from Allmight97/audiobook-boss (
src/app/outputPlan/AGENTS.md). Install upstream withnpx skills add Allmight97/audiobook-boss --skill outputPlan. Copyright stays with the author.
Output Plan
Scope
- Owns output directory, naming, path preview, export-size estimate, and
collision review under
src/app/outputPlan/. - Solid views live in
src/ui/outputPanelandsrc/ui/collisionDialog. They render this owner; they do not keep a second plan store.
Public API Strip
- Import Output Plan runtime symbols from
src/app/outputPlan.createOutputOwneris the Solid plan factory. - Workbench callers that only need the composed UI strip import
src/ui/outputPanelinstead. index.tsis the export surface. Do not importowner.ts,workflow.ts,collision.ts,estimate.ts, orpreviewDraft.tsfrom outside this owner.
Hard Invariants
- Per-title explicit encoding estimates use that title's total source duration
and Encoding's
estimateTitleKbps. Quality VBR displays a labeled rough reference estimate when Encoding supplies one, otherwise “Size varies with audio”. Auto has no estimate until a backend title preview resolves its copy/encode choice. Explicit Preserve estimates sum source sizes; they do not use encoder targets. The file-list row rendersestimateTitleSizeTextbeside that title's audio summary.estimate.tsowns the byte formula; bitrate is total across channels. - Path preview passes the selected title format to Rust. Audio owns its extension; changing quality or encoder availability alone does not re-run naming preview.
- Path preview is a Solid async memo on public Input, Metadata, output
directory, naming preset, year, and the committed template. Live template
typing updates the input immediately and commits after 150 ms. Do not preview
on every keystroke. Preview retriggers when Metadata series or subseries part
changes, not only title, album, or artist. Native path authority,
metadata-intent validation, and request-id stale suppression stay in the
preview workflow. Preview validation forwards
MetadataDraftValidationthrough the injectedonMetadataValidationdep. Do not add a Metadata setter here. - Collision review is a separate preflight/review workflow
(
runOutputPlanReviewWorkflow) whose view and pending choice live on the Output owner. Views useuseAppRuntime().output. Do not fold review into path-preview freshness. - App Settings hydration passes resolved
outputDefaultsto the runtime's Output owner without persisting. User changes hand accepted defaults to the injected SettingsrememberOutputDefaultsintent. - Processing submit and collision review use the injected Output owner
(
readRequestConfig,openCollisionReview).readRequestConfig()uses the live naming box (namingTemplate), not the 150 ms committedpreviewTemplate. Preview stays on the committed copy. Do not restoreupdateOutputPathorupdateEstimatedSize, or a last-writer owner lookup.
Testing
estimate.test.tspins the byte formula;outputPlan.test.tscovers title estimates and missing source facts. Resolved preview settings own Default encoding estimates; saved preferences must not substitute for the accepted plan.outputPlan.test.tspins hydration, per-title estimate (including FDK VBR uncertainty vs target-based estimates), live submit naming vs 150 ms preview debounce, series-part preview retrigger, preview draft/source-path projection, and collision resolve/cancel. Duration comes fromruntime.input.replaceSession.workflow.test.tspins stale preview suppression and review approve / cancel / hard-block.runtime-api-contract.test.tspins this owner's public export strip.- Two-runtime request and collision isolation lives in
src/app/runtime/runtime.test.ts.
Boundary Changes
- Adding, removing, or renaming a public export.
- Reading private Input, Metadata, file-list, or encoder state to build preview, estimate, or submit config.
- Moving the estimate formula or its title-row presentation.
