# Migration Step 7: Slim Scriptorium And Adopt Promptkit ## Status Proposed. ## Purpose Complete Scriptorium's application-side cutover to the independently published Promptkit library. After this work, Scriptorium is a runnable CLI and HTTP application built on Promptkit's supported public API rather than a second owner of the prompt-execution framework. This roadmap defines the required end state for Step 7. The [main migration roadmap](migration.md) owns the overall migration sequence, while [ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md) owns the durable project, package, configuration, compatibility, and documentation boundaries. ## Starting Point Promptkit is independently published as module `gitea.maximumdirect.net/eric/promptkit` at annotated tag `v0.1.0`. That release contains the characterized framework, root public facade, built-in profile registry, maintained framework tests, and consumer documentation extracted in Step 6. Scriptorium intentionally still contains the pre-cutover copy of that framework. Its executable adapters already consume framework behavior through the local root facade, which provides a narrow migration seam. Step 7 replaces that local facade with Promptkit and removes the duplicated implementation; it does not redesign the framework or the executable interfaces. ## Desired End State Scriptorium is an application-only Go module with this dependency direction: ```text scriptorium command | v CLI and HTTP adapters, application config, and output formatting | v gitea.maximumdirect.net/eric/promptkit public package | v Promptkit-owned framework implementation ``` The Scriptorium module root no longer provides an importable Go package. Scriptorium has no compatibility facade, type aliases, forwarding functions, or deprecated wrappers for the former `scriptorium` public API. Go consumers must import Promptkit; consumers that have not migrated may remain pinned to a previous framework-bearing Scriptorium version as established by ADR 0002. ## Promptkit Dependency Scriptorium must declare `gitea.maximumdirect.net/eric/promptkit v0.1.0` as a direct module dependency. Production code, tests, examples, builds, and release configuration must resolve that published tag without a committed workspace, local filesystem replacement, vendored Promptkit copy, or unpublished revision. The cutover must use only Promptkit's supported root package. Scriptorium must not import, copy, or depend conceptually on Promptkit implementation packages. No Promptkit API expansion is expected for this step: Step 4 established the required application seam, and Step 6 published it. If implementation discovers a genuine missing Promptkit capability, that is a cross-repository blocker: the capability must be accepted, implemented, validated, and tagged in Promptkit before Scriptorium can depend on it. Dependencies used only by the removed framework must leave Scriptorium's `go.mod` and `go.sum`. Scriptorium retains only dependencies required by its application-owned code. The module's Go version remains compatible with the selected Promptkit release. ## Application Assembly And Adapter Boundary The CLI must construct `promptkit.Engine` values from Scriptorium's resolved application settings. It must translate Scriptorium CLI inputs and execution overrides into `promptkit.RunRequest`, `promptkit.ArtifactRef`, and `promptkit.ExecutionTargetOverride` values without introducing a parallel application model. The `run` command must invoke `promptkit.Engine.Run`; the `render` command must invoke `promptkit.Engine.Prepare`. The `serve` command must inject Scriptorium's restricted artifact reader through `promptkit.WithArtifactReader` and pass the engine to the HTTP adapter through the adapter-owned consumer interface. The HTTP adapter's `Runner` interface remains owned by Scriptorium because it is a consumer-side test and substitution boundary. Its method uses Promptkit request and result types. Request DTOs, response DTOs, strict JSON decoding, HTTP limits, error-to-status mapping, response encoding, and route behavior remain Scriptorium concerns and must not move into Promptkit. Prepared-run formatting remains in Scriptorium because text and JSON output selection is an executable presentation concern. The formatter operates directly on Promptkit public prepared-run values; it must not introduce copied framework types. ## Artifact And Security Boundary Scriptorium retains its HTTP-specific restricted artifact reader. The reader must implement `promptkit.ArtifactReader` and consume and return Promptkit artifact values directly. The cutover must preserve the current HTTP artifact policy: - an empty artifact root permits inline artifacts and denies file references; - configured byte limits apply to file artifacts, with zero meaning unlimited; - file paths are checked using the documented lexical root-containment rule; - symlinks retain their currently documented behavior; - content type, size, hash, name, URI, and cancellation behavior remain observable through the same HTTP contract; and - Scriptorium reader errors remain identifiable so the HTTP adapter can preserve its existing status and error-code mappings. Ordinary in-process and CLI file reading belongs to Promptkit. Scriptorium must not retain its former general-purpose artifact reader or framework artifact package after the cutover. ## Configuration And Defaults Scriptorium continues to own: - configuration discovery and strict YAML decoding; - configuration-file and CLI precedence; - `prompt_dir`, `profile_dir`, and `schema_dir` as application source locations; - `server.*` settings and transport byte limits; - the default prepared-run output format; and - CLI, HTTP server, and process defaults. These settings are translated into Promptkit construction options and request values at the application boundary. When omission means “use Promptkit's framework default,” Scriptorium must leave the value unset rather than redeclare a Promptkit constant. Promptkit owns prompt, profile, and output-contract file semantics; built-in profiles; execution-setting resolution; validation behavior; output-artifact and framework content-type defaults; OpenAI-compatible request behavior; and generation and transport timeout semantics. Scriptorium's defaults package must be reduced to application and transport defaults still used by the CLI, HTTP server, configuration loader, or output formatter. The cutover must not change documented configuration discovery, CLI precedence, source-path interpretation, server limits, or render-format behavior. ## Package And Asset Disposition The following Scriptorium components remain: | Component | Retained responsibility | | --- | --- | | `cmd/scriptorium` | Runnable process entrypoint. | | `internal/adapter/cli` | CLI parsing, application assembly, streams, files, summaries, and exit codes. | | `internal/adapter/http` | Routes, DTOs, strict decoding, HTTP limits and mappings, and restricted artifact reading. | | `internal/config` | Application configuration discovery, decoding, validation, defaults, and CLI precedence. | | `internal/format` | Prepared-run text and JSON presentation using Promptkit public values. | | `internal/defaults` | Scriptorium-only CLI, HTTP, server, and application defaults. | | `.woodpecker`, release metadata, and executable packaging | Scriptorium build and binary-release behavior. | The following duplicated framework components must be removed from Scriptorium: - all root-package facade source and tests; - `internal/artifact`, `internal/domain`, `internal/filecatalog`, `internal/llm`, `internal/profile`, `internal/prompt`, `internal/promptdef`, `internal/usecase`, and `internal/validate`; - embedded built-in profile assets and framework-package test fixtures; - the root framework contract tests and `testdata/framework`; and - `examples/go-library`, which is owned and maintained by Promptkit. Tests remain with the behavior they protect. Scriptorium retains and adapts application configuration, adapter, formatting, HTTP containment, command, and representative executable-workflow coverage. It must not retain duplicate Promptkit unit or contract tests merely to exercise dependency internals. The executable examples under `examples/` remain when they support Scriptorium's CLI or HTTP workflows. This includes application configuration, render scripts, HTTP requests, prompt/profile/schema inputs, and synthetic fixtures needed by those workflows. Their format semantics are owned by Promptkit documentation even though the files remain runnable Scriptorium assets. ## Observable Behavior To Preserve Step 7 is an ownership and dependency cutover, not an intentional CLI or HTTP contract change. Subject to the deliberate removal of the public Scriptorium Go package, preserve: - the `run`, `render`, and `serve` command names, flags, precedence, output destinations, summaries, exit classifications, and process behavior; - application configuration schema, discovery, validation, and defaults; - HTTP route, method, request and response shapes, strict decoding, media types, size enforcement, status codes, and stable error codes; - prompt, profile, execution-setting, request-override, and validation behavior as supplied by Promptkit `v0.1.0`; - built-in profile availability and custom-profile overlay behavior; - presence-aware zero-valued execution overrides; - the rule that explicit timeout zero disables only the generation deadline, while caller cancellation and the transport cap remain active; - public error identity as consumed by Scriptorium's CLI and HTTP mappings; - structured-output requests, output validation, and validation-failure classification; - strict external YAML and JSON decoding; - secret resolution and redaction; and - deterministic prepared-run formatting and output metadata. Any observable application change discovered during implementation must be treated as a regression unless this roadmap, an accepted ADR, or a separately approved feature decision authorizes it. ## Architecture Enforcement Repository checks must make the new dependency direction durable. They must detect production imports of: - the removed Scriptorium root facade; - former Scriptorium framework package families; and - Promptkit `internal` packages. The checks must cover the command, adapters, configuration, formatting, and other remaining production packages recursively without treating test-only fixtures as the application architecture. Go's own `internal` enforcement is useful but does not replace a repository-level check that explains the intended boundary. The final tree must contain no duplicate framework directories, embedded built-in registry, copied Promptkit source, or dormant compatibility package. ## Documentation End State Permanent Scriptorium documentation must describe the implemented slim application only: - `README.md` presents the runnable CLI and HTTP application and contains no in-process Go-library positioning; - `docs/policy/architecture.md` defines Scriptorium as a Promptkit consumer and removes the single-repository framework architecture; - `docs/development.md` routes contributors through the retained application packages and the Promptkit contracts relevant to cross-project work; - `docs/internal/overview.md` inventories only the remaining Scriptorium packages; - CLI, HTTP, configuration, operations, adapter, source, and subprocess documents retain their application-owned contracts and mechanics; - the former Scriptorium Go-package consumer guide is retired, and incoming navigation directs Go framework consumers to Promptkit; - framework format and OpenAI-compatible behavior are linked to their canonical Promptkit owners rather than redefined in Scriptorium; - former runner, model-client, source, and other internal framework documentation is removed or reduced to the application-owned boundary where such a boundary still exists; - maintained examples and all documentation links refer only to files and commands that remain; and - future release and downstream-consumer work remains in the migration roadmap until Steps 8 and 9 are completed. Promptkit's existing references to Scriptorium as a downstream application become accurate when this cutover lands. Step 7 does not otherwise change Promptkit's public API, implementation, version, or release documentation. ## Validation Expectations Validation must demonstrate the resulting boundary and behavior, not the deleted implementation structure. Scriptorium must pass: - all ordinary and race-enabled Go tests; - `go vet` for all remaining packages; - an executable build to a temporary output path; - formatting, module-tidiness, whitespace, documentation-link, and repository hygiene checks; - maintained executable examples other than the retired Go-library example; - both maintained application configuration examples; - representative HTTP handler and restricted-artifact workflows; and - architecture checks proving the absence of the former framework dependency direction. Validation must run with no active Go workspace and no module replacement. Module inspection must show the tagged Promptkit dependency selected directly. Promptkit must continue to pass its own documented validation independently; Scriptorium validation must not rely on the sibling Promptkit checkout. Scriptorium's hosted validation and executable release workflow must remain capable of resolving the public Promptkit tag and building the command without cross-repository filesystem state. ## Non-Goals Step 7 does not: - redesign or broaden Promptkit's public API; - preserve source compatibility for the former Scriptorium Go package; - migrate downstream repositories other than Scriptorium; - publish the breaking Scriptorium release or general downstream migration guide assigned to Steps 8 and 9; - change CLI, HTTP, configuration, prompt, profile, schema, validation, model, or timeout contracts; - move Scriptorium transport, deployment, or presentation policy into Promptkit; - add hosted CI or binary releases to Promptkit; or - retain duplicated code or documentation as a fallback. ## Completion Criteria Step 7 is complete only when all of the following are true: - Scriptorium declares and resolves `gitea.maximumdirect.net/eric/promptkit v0.1.0` as a direct dependency with no workspace, replacement, vendored copy, or unpublished revision. - The command, CLI adapter, HTTP adapter, restricted artifact reader, and prepared-run formatter use Promptkit public values and interfaces. - The Scriptorium module root exposes no Go package or compatibility facade. - Every Promptkit-owned framework package, built-in asset copy, framework test, fixture corpus, and Go-library example has been removed from Scriptorium. - Only application-owned configuration, adapter, formatting, transport, process, packaging, and executable-example responsibilities remain. - CLI, HTTP, configuration, containment, formatting, error-mapping, security, and representative end-to-end behavior remain protected by passing Scriptorium-owned tests. - Architecture checks prevent imports of the former local framework and Promptkit internals. - Scriptorium's current documentation describes the slim application and links to Promptkit for framework contracts without duplicating them. - Both repositories validate independently, and Scriptorium's full test, race, vet, build, example, link, module, and hygiene checks pass against the published Promptkit tag. - The working tree contains no generated binaries, temporary workspaces, replacement directives, credentials, or migration residue. **Gate:** Scriptorium is a clean, independently buildable CLI and HTTP consumer of the published Promptkit module, contains no reusable framework implementation or public Go facade, preserves its application contracts, and is ready for the out-of-band downstream-consumer migrations in Step 8.