2026-05-05 08:25:32 -05:00
# Scriptorium Architecture
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 1. Purpose and Non-Goals
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Scriptorium is a prompt-profile execution engine.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
It takes named input artifacts, renders prompt templates, calls an LLM, validates output, optionally performs bounded structured-output repair, and returns an artifact with metadata.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Scriptorium is not an orchestrator. It should not own transcription, transcript merging, transcript polishing, notification, or cross-step workflow control.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
For the motivating D&D workflow:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Narratio orchestrates.
- WhisperX transcribes.
- Seriatim merges transcripts.
- Audita polishes transcripts.
- Scriptorium generates output artifacts from prepared inputs.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Core Go code must remain domain-generic.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 2. Current Architecture
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Current high-level structure:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `cmd/scriptorium` : binary entrypoint.
- `internal/domain` : core domain types.
- `internal/usecase` : `Runner` use case and repair loop orchestration.
- `internal/profile` : filesystem prompt profile repository and profile validation.
- `internal/artifact` : artifact reference readers (`inline` , `file` ) and routing.
- `internal/prompt` : Go template-based prompt renderer.
- `internal/llm` : LLM client interface + OpenAI-compatible HTTP adapter.
- `internal/validate` : output validator implementation (`none/basic/json/json_schema` ).
- `internal/adapter/cli` : CLI adapter.
- `internal/adapter/http` : HTTP adapter (`POST /v1/runs` ).
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
This is a practical ports-and-adapters implementation.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 3. Run Data Flow
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
`Runner.Run(ctx, RunRequest)` currently executes:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
1. Validate minimum request requirements (`profile_id` ).
2. Load prompt profile by ID/version.
3. Merge effective model target (profile defaults + request override).
4. Resolve effective output contract (profile + optional request override).
5. Resolve named artifact refs to loaded artifacts.
6. Render prompt messages from templates.
7. Hash rendered prompt for auditability.
8. Call LLM client with provider-neutral `GenerateRequest` .
9. Build output artifact from model content.
10. Validate output.
11. If structured validation failed and repair is enabled/bounded, run repair attempts and re-validate.
12. Return `RunResult` with artifact, validation, raw output, and metadata.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Validation content failure remains a successful run result with `validation.status=failed` .
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 4. Package Responsibilities
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `domain`
- Owns core nouns and contracts.
- Must not import adapters/provider SDK types.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `usecase`
- Owns execution sequence and cross-port orchestration for a single run.
- May coordinate validation and bounded repair.
- Must not contain HTTP/CLI/wire concerns.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `profile`
- Owns prompt profile loading/parsing/validation.
- Handles YAML strict decoding and profile-level constraints.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `artifact`
- Owns artifact ref resolution and content loading.
- Produces normalized `Artifact` values with size/hash/content type.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `prompt`
- Owns template rendering and required-input enforcement.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `llm`
- Owns generation port and provider adapters.
- Current adapter: OpenAI-compatible chat completions over `net/http` .
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `validate`
- Owns output validation semantics and JSON Schema integration.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `adapter/http` , `adapter/cli`
- Owns transport/wire/flag concerns only.
- Should stay thin and delegate business flow to `usecase.Runner` .
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 5. Domain Model (Current)
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Key types in `internal/domain` :
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `RunRequest` : profile selector, named input refs, vars, optional model override, optional validation override.
- `RunResult` : output artifact, validation result, raw output, profile/model metadata, hashes, usage, timestamps, duration.
- `ArtifactRef` : `{type, uri, body}` reference contract.
- `Artifact` : loaded payload (`name` , `content_type` , `body` , `uri` , `size` , `hash` ).
- `PromptProfile` : YAML-backed profile definition.
- `RenderedPrompt` / `RenderedMessage` : provider-neutral prompt structure.
- `GenerateRequest` / `GenerateResponse` : provider-neutral model I/O.
- `ValidationResult` : passed/failed/skipped + mode/errors/schema/repair attempts.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 6. Interfaces and Adapters
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Primary ports:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `profile.Repository`
- `artifact.Reader`
- `prompt.Renderer`
- `llm.Client`
- `validate.Validator`
- `usecase.OutputRepairer` (usecase-local abstraction)
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Current adapters:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Profile repository: filesystem YAML loader.
- Artifact reader: composite reader for `inline` and `file` .
- Prompt renderer: Go templates with input helper + vars.
- LLM adapter: OpenAI-compatible `/chat/completions` .
- Validator: standard validator with `none/basic/json/json_schema` .
- CLI/HTTP adapters: thin request mapping and response mapping.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 7. Validation and Repair Model
2026-05-04 20:14:31 -05:00
Validation modes:
2026-05-05 08:45:10 -05:00
- `none`
- `basic`
- `json`
- `json_schema`
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Repair behavior:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Only applies to structured modes (`json` , `json_schema` ).
- Attempted only when validation fails, repairer exists, and `repair_attempts > 0` .
- Bounded strictly by `repair_attempts` .
- Uses a narrow JSON-repair prompt and re-validates each attempt.
- If still invalid, run succeeds with failed validation and preserved final raw output.
- Validator runtime/config errors are run errors.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 8. Public Contracts
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
### CLI
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Commands:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `scriptorium run`
- `scriptorium serve`
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
`run` :
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Required: `--profile-dir` , `--profile-id` , `--input` .
- Optional: model/endpoint overrides (`--model` , `--llm-base-url` ), vars, output path, schema dir, timeout.
- Artifact bytes go to stdout (or `--out` file); summaries/errors go to stderr.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
`serve` :
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Required: `--profile-dir` , `--llm-base-url` .
- Exposes HTTP run endpoint.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
### HTTP
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Endpoint: `POST /v1/runs` .
- Request maps to `RunRequest` (`profile_id` , `inputs` , `vars` , optional `model` override).
- Response includes `artifact` , `validation` , `metadata` , `raw_model_output` .
- Validation content failures are represented as `200` with `validation.status=failed` .
- Error responses are `{error:{code,message}}` with stable code mapping.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
### Prompt Profile YAML
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `id` , `version` , `expected_inputs` , `templates` , `model_defaults` , `output_format` , `validation` .
- Strict YAML decoding (`KnownFields` ) rejects unknown fields.
- `validation.schema_path` required when `validation_mode=json_schema` .
- `validation.repair_attempts` must be non-negative.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
### Metadata
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Current run metadata includes:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- `run_id` (UUID v4)
- `profile_id` , `profile_version` , `profile_hash`
- `model_name` , `endpoint` , effective `model_params`
- `input_hashes` , `prompt_hash`
- token usage
- start/end timestamps
- duration
- validation mode/status
- repair attempts used
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 9. Extension Points (Future Work)
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Future features should plug into existing boundaries, not bypass them.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Candidate extensions:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- S3 artifact refs via `artifact.Reader` extension.
- Token budgeting in usecase/model-target policy layer.
- Streaming LLM output via additional `llm.Client` methods/adapters.
- Batch execution as a separate use case (not hidden in single-run path).
- Additional LLM providers implementing `llm.Client` .
- Additional validators/modes in `validate` .
- Additional profile repositories (embedded, remote, object storage).
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
These are future work, not part of current default behavior.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 10. Architectural Guardrails
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Contributors should preserve these constraints:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- No D&D-specific behavior in core Go packages.
- No orchestration creep into Scriptorium.
- No unbounded repair loops.
- No silent truncation/omission of rendered inputs or outputs.
- Do not log full artifacts/prompts by default.
- Keep provider-specific wire/SDK details out of domain types.
- Keep adapter boundaries explicit and thin.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
## 11. Testing Strategy
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Protect behavior at boundaries and in usecase flow:
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
- Profile loading/parsing/validation errors.
- Artifact reading for inline/file + hash/content type behavior.
- Prompt rendering required inputs/template error behavior.
- LLM adapter request/response/error/timeout behavior.
- Runner success path and metadata population.
- Validation failure raw-output preservation.
- Successful/failed/bounded repair flows.
- HTTP request mapping, response shape, and error mapping.
- CLI parsing helpers, required flags, and output stream separation.
2026-05-04 20:14:31 -05:00
2026-05-05 08:45:10 -05:00
Prefer focused unit tests and small integration-style tests with fake LLMs.