# Runner Internals ## Purpose `internal/usecase.Runner` is the prompt-execution orchestrator. It prepares domain requests, invokes an injected LLM client, validates output, and returns domain results. Transport parsing, response mapping, and public type conversion remain outside this package. The [configuration reference](../config.md) owns prompt, profile, schema, and runtime-setting definitions. Public error behavior is defined by the [HTTP API](../api.md) and [Go package](../consumers/pkg-scriptorium.md) contracts. ## Dependencies And Construction `Runner` receives these collaborators: - `promptdef.Repository`; - `profile.Repository`; - `artifact.Reader`; - `prompt.Renderer`; - `llm.Client`; - `validate.Validator`; and - an optional `OutputRepairer`. `NewRunner` constructs a runner without a repairer. `NewRunnerWithRepairer` accepts one explicitly. Adapters and the public engine choose concrete repositories and readers; the runner does not load application configuration. ## Prepare Flow `Prepare` performs one deterministic preparation pass for a request: 1. validate the prompt ID and load the prompt definition; 2. hash the definition and select the explicit or default profile; 3. load the profile and resolve effective execution settings; 4. validate endpoint, model, and credential availability; 5. resolve the output contract and, for JSON Schema output, load a structured schema document before model execution; 6. read and hash input artifacts; 7. render messages and the session ID; and 8. return a `PreparedRun` containing the effective state and rendered-prompt hash. Execution settings merge defaults, profile values, and a request override. Numeric override presence is retained so explicit zero values are not confused with omissions. ## Run And Validation Flow `Run` creates a run ID and timestamps, then calls `Prepare` rather than duplicating preparation. It sends the prepared prompt, effective target, target-presence state, and optional structured-output specification to the LLM client. It converts the returned content to an output artifact, validates it, and returns the artifact, validation, hashes, usage, and timing metadata. A validator can return a content result or an operational error. Content failures stay in the result; schema loading, compilation, and validator operational failures are returned as `ErrValidation`. The canonical distinction for callers is documented by the public contracts. ## Repair Boundary Repair is an internal optional loop. It starts only when a repairer is present, the output contract permits one or more attempts, validation failed, and the validation mode is JSON or JSON Schema. Each repair receives the previous output, validation errors, effective target, structured-output specification, and attempt metadata; every repaired result is validated again. `NewDefaultOutputRepairer` delegates to the injected LLM client. CLI, HTTP, and the public engine use `NewRunner` and therefore do not inject this repairer. ## Error Translation Runner sentinels identify failure categories for adapters: - `ErrInvalidRequest` - `ErrProfileRequired` - `ErrAPIKeyEnvMissing` and `ErrAPIKeyRequired` - `ErrPromptLoad`, `ErrProfileLoad`, and `ErrArtifactLoad` - `ErrPromptRender` - `ErrLLMGenerate` - `ErrValidation` Wrap errors with those sentinels and preserve their identities through `errors.Is`; adapters must not classify errors by message text. The runner passes direct keys only to the LLM boundary and never includes resolved key values in prepared or run results. ## Package-Local Guarantees - `Run` always reuses `Prepare`. - Schema documents are loaded before the initial LLM call when structured output is required. - Output validation records attempts used, including repair attempts. - Runner state is per request; the package does not create a durable run store or manifest. - Source, renderer, validator, and LLM implementations remain injected boundaries. ## Verification And Change Recipe Inspect: - `internal/usecase/runner_test.go` - `internal/usecase/integration_test.go` - `engine_test.go` When changing orchestration: 1. identify the collaborator boundary and the affected `Prepare` or `Run` state; 2. preserve the `Run`-through-`Prepare` path and error identity; 3. add focused runner or integration tests for changed state transitions, validation, or repair behavior; and 4. update the owning external contract and any affected source or LLM internal document. The [testing policy](../policy/testing.md) owns global test sufficiency.