diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 428dd65..a99776e 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,85 +1,637 @@ -# Step 6 Implementation Completion Record +# Step 7 Implementation Plan ## Status -Completed on 2026-07-28. +Accepted for implementation. -This record closes -[Migration Step 6: Extract And Stabilize Promptkit](step6.md). It replaces the -temporary implementation checklist now that every extraction, documentation, -validation, and publication gate has passed. +Implement each stage in order. Do not begin a later stage until the current +stage's exit criteria pass. The +[Step 7 feature roadmap](step7.md) is the north star for scope, policy, desired +behavior, and completion. [ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md) +controls the durable project boundary. -## Recorded Commits And Release +This plan changes Scriptorium only. Promptkit `v0.1.0` is a published, +read-only input to the cutover. Do not edit Promptkit, create a new Promptkit +tag, or use the sibling Promptkit checkout to make an intermediate +Scriptorium state pass. -- Scriptorium extraction source: - `c7263ab2a8e58f7fb97280082d327a820c7cece7` -- Accepted Promptkit release commit: - `9e68a2bbf779545995270c47842048a3bc6c85dc` -- Published annotated Promptkit tag: `v0.1.0` -- Verified remote tag object: - `b4495c2b294967049bb363f20d5607b1f2a36f49` +## Implementation Rules -All Promptkit extraction commits use plain-English messages and remain in the -Promptkit repository. Scriptorium received no framework implementation or -dependency change during this work. +Apply these rules throughout every stage: -## Completed Work +- Read both repositories' development, architecture, documentation, and + testing policies before implementation. +- Preserve unrelated working-tree changes. The removals of completed roadmap + files that predate this plan are user-owned changes and must not be restored. +- Run Scriptorium commands outside a Go workspace. Do not commit `go.work`, + `go.work.sum`, a local `replace`, vendored Promptkit source, or generated + dependency output. +- Depend only on + `gitea.maximumdirect.net/eric/promptkit v0.1.0` and its root `promptkit` + package. Do not import `promptkit/internal/...`. +- Treat the former Scriptorium Go package as intentionally removed. Do not add + aliases, forwarding wrappers, deprecated shims, or an application-local copy + of Promptkit values. +- Preserve CLI, HTTP, configuration, formatting, artifact-containment, + security, error-mapping, and process behavior unless the feature roadmap + explicitly says otherwise. +- Prefer adapting existing application tests to Promptkit values over adding + parallel test suites. Delete tests whose only owner is the removed framework. +- Keep permanent documentation aligned with implemented state. Do not describe + a later stage as complete before its code has landed. +- Use `gofmt` for Go formatting and `go mod tidy` for module metadata. Do not + hand-edit `go.sum`. -Promptkit received and characterized: +If a required capability is absent from Promptkit `v0.1.0`, stop the Step 7 +implementation and report the exact public-boundary gap. Do not work around it +with a Scriptorium framework copy or an unpublished Promptkit revision. -- the application-neutral domain, defaults, and file-catalog foundation; -- prompt and profile sources, the embedded built-in catalog, and rendering; -- ordinary artifact reading and output validation; -- the provider-neutral model-client boundary and OpenAI-compatible client; -- preparation and execution orchestration; -- the supported root facade, values, extension points, error mapping, copying, - and redacted formatting; -- recursive dependency-boundary protection; -- framework contract fixtures and deterministic offline tests; -- canonical consumer, format, integration, internal, development, testing, - architecture, and release documentation; and -- a maintained offline `Prepare` example. +## Stage 1: Cut The Application Seam Over To Promptkit -Application configuration, CLI and HTTP adapters, transport policy, restricted -artifact access, deployment behavior, and executable concerns remained in -Scriptorium. +### Objective -## Validation Evidence +Make all retained Scriptorium application code and tests consume the published +Promptkit facade while the old local framework remains temporarily available +for comparison. This stage proves that `v0.1.0` is sufficient before deleting +the old implementation. -The exact Promptkit release commit passed from a fresh detached checkout with -`GOWORK=off`: +### Module Dependency -- module tidiness, ordinary tests, race-enabled tests, vet, and build; -- the maintained offline example; -- Go formatting, whitespace, and clean-tree checks; -- module and package identity checks; -- absence of Scriptorium module and package dependencies; -- absence of workspaces and replacements; -- the recursive architecture guard; -- public Go inventory and sentinel-error comparison; -- all maintained local links; -- exact comparison of all 24 built-in assets with the source snapshot; and -- preservation of GPLv3 and Promptkit-specific project notices. +Add an exact direct requirement: -Before publication, unchanged Scriptorium independently passed all tests, vet, -the `cmd/scriptorium` build, and whitespace checks with no Promptkit dependency -or replacement. +```text +gitea.maximumdirect.net/eric/promptkit v0.1.0 +``` -Promptkit's `main` branch was published before tagging. The annotated -`v0.1.0` tag was inspected, pushed, and remotely verified to resolve to the -accepted commit. A clean temporary consumer module then downloaded exactly -`v0.1.0`, built and ran a minimal root-package program, and verified its module -graph without a local replacement. +Resolve it from the configured module source with `GOWORK=off`. Do not add a +replacement. Do not prune the old framework-only dependencies yet; the local +framework still compiles during this stage. -No binary or hosting-provider-specific release artifact was created. +Confirm before changing imports that the selected module resolves to +`v0.1.0` and that its origin hash is the accepted Promptkit release commit +`9e68a2bbf779545995270c47842048a3bc6c85dc`. -## Migration Handoff +### Production Import And Type Migration -Scriptorium remains deliberately unchanged at its pre-cutover application -boundary. [Migration Step 7](migration.md#step-7-slim-scriptorium-and-adopt-promptkit) -is the next authorized work: adopt the tagged Promptkit module and remove the -duplicated framework while retaining Scriptorium-owned executable and transport -behavior. +Replace the former root-package import with +`gitea.maximumdirect.net/eric/promptkit` in every retained application package. +Use the package name `promptkit` in code rather than aliasing it back to +`scriptorium`. -The [Step 6 completion record](step6.md) owns the completed result and retained -boundary. The [main migration roadmap](migration.md) owns all later work. +Update `internal/adapter/cli/run.go` so: + +- engine construction calls `promptkit.NewEngine` with `promptkit.Config`; +- `run` and `render` requests use `promptkit.RunRequest`; +- input mappings use `promptkit.File` and Promptkit artifact references; +- execution overrides use `promptkit.ExecutionTargetOverride`; +- the `serve` path injects the HTTP reader with + `promptkit.WithArtifactReader`; +- result summaries, validation classification, and exit-code selection use + Promptkit result and status values; and +- no CLI flag, precedence, output, or error wording changes solely because of + the import migration. + +Update `internal/adapter/http` so: + +- the adapter-owned `Runner` interface accepts `promptkit.RunRequest` and + returns `*promptkit.RunResult`; +- DTO mapping constructs Promptkit artifact references and execution + overrides; +- response mapping reads Promptkit artifact, validation, model, usage, and + metadata values directly; +- HTTP error mapping uses Promptkit's public sentinel errors with `errors.Is`; + and +- the restricted reader implements `promptkit.ArtifactReader` and uses + Promptkit artifact reference, artifact, and reference-type values. + +Keep `ErrFileNotAllowed`, `ErrFileOutsideRoot`, and `ErrFileTooLarge` in +Scriptorium. Confirm that Promptkit's artifact-load wrapping preserves those +underlying identities so the existing HTTP mappings continue to work. + +Update `internal/format` so every formatter interface, entry point, message +collection, and test fixture uses Promptkit prepared-run and message values +directly. + +### Test Migration + +Update retained CLI, HTTP, restricted-reader, and formatter tests to import and +construct Promptkit public values. In particular: + +- fake runners must use the Promptkit request/result signature; +- handler integration helpers must construct a real `promptkit.Engine`; +- test LLM clients must implement `promptkit.LLMClient`; +- engine options must use Promptkit options; +- error-mapping tables must use Promptkit sentinels; and +- formatting fixtures must use Promptkit public prepared-run types. + +Do not change expected CLI output, HTTP payloads, status codes, error codes, +artifact policy, or formatted render output merely to accommodate the new +package name. + +### Validation + +Run: + +```sh +go mod download gitea.maximumdirect.net/eric/promptkit@v0.1.0 +go list -m -f '{{.Path}} {{.Version}}' gitea.maximumdirect.net/eric/promptkit +go test ./internal/adapter/... ./internal/format/... +go test ./... +go vet ./... +go build ./cmd/scriptorium +``` + +Also run the maintained render script and the existing CLI command tests that +exercise built-in profiles, custom profiles, explicit zero-valued overrides, +restricted HTTP artifacts, public error mapping, and prepared-run formatting. + +### Exit Criteria + +- All retained application production code uses Promptkit public types. +- Application tests use Promptkit at the same boundaries as production. +- The exact direct `v0.1.0` dependency is selected without a replacement. +- The full repository still builds and tests while the local framework copy is + present but unused by retained application code. +- No Promptkit API gap has been discovered. + +## Stage 2: Remove The Duplicated Framework + +### Objective + +Delete every Promptkit-owned implementation, facade, test, fixture, and example +from Scriptorium, then reduce application defaults and module dependencies to +the slim repository boundary. + +### Remove The Former Root Package + +Delete the complete former root facade: + +- `artifact_reader.go` +- `artifact_reader_internal_test.go` +- `convert.go` +- `engine.go` +- `engine_test.go` +- `errors.go` +- `formatting.go` +- `json_copy.go` +- `llm_adapter.go` +- `profiles.go` +- `types.go` + +After deletion, the Scriptorium module root must contain no `.go` files and +must not be importable as package `gitea.maximumdirect.net/eric/scriptorium`. +Do not replace these files with a stub package or migration shim. + +### Remove Promptkit-Owned Internal Packages + +Delete these directories in full, including their package tests, testdata, and +embedded assets: + +- `internal/artifact` +- `internal/domain` +- `internal/filecatalog` +- `internal/llm` +- `internal/profile` +- `internal/prompt` +- `internal/promptdef` +- `internal/usecase` +- `internal/validate` + +Delete `testdata/framework`. Promptkit owns the framework contract corpus and +already contains its maintained copy. + +Delete `examples/go-library`. The Scriptorium Go-library example is obsolete; +Promptkit owns the maintained in-process preparation example. + +Do not delete the executable assets under `examples/config*.yml`, +`examples/prompts`, `examples/profiles`, `examples/schemas`, +`examples/fixtures`, `examples/http-run.json`, or +`examples/render-markdown-summary.sh`. Those remain Scriptorium application +examples even though Promptkit owns their file-format semantics. + +### Split Defaults By Ownership + +Reduce `internal/defaults/defaults.go` to values still owned and used by +Scriptorium: + +- `HTTPAddrDefault` +- `SchemaDirDefault`, which remains the application configuration default for + Scriptorium's schema source location; +- `HTTPMaxRequestBytesDefault` +- `HTTPMaxArtifactBytesDefault` +- `HTTPMaxResponseBytesDefault`; and +- `HTTPReadHeaderTimeoutDefault`. + +Remove framework-owned output-artifact names, content types, +OpenAI-compatible paths, execution defaults, model-client timeouts, domain +imports, and `ExecutionTargetDefault`. + +Do not copy constants from Promptkit merely to make tests convenient. When the +CLI does not supply a framework setting, continue passing the zero value so +Promptkit applies its own default. + +### Prune Module Metadata + +Run `go mod tidy` only after all Promptkit-owned source and tests are gone. +Keep `gopkg.in/yaml.v3` as a direct dependency because Scriptorium still +decodes application configuration. Allow `go mod tidy` to remove or reclassify +JSON Schema and other modules according to the actual remaining import graph. + +The final `go.mod` must have: + +- Promptkit `v0.1.0` as a direct dependency; +- no `replace` directive; +- no dependency retained solely for deleted framework code; and +- the existing compatible Go language version. + +### Validation + +Run: + +```sh +go mod tidy +go list ./... +go test ./... +go vet ./... +go build ./cmd/scriptorium +``` + +Inspect `go list ./...` and the filesystem. The package inventory must consist +only of the command and retained application packages: adapters, +configuration, defaults, and formatting. The module root and removed framework +package families must be absent. + +### Exit Criteria + +- Scriptorium exposes no root Go package. +- No duplicated framework package, built-in registry, framework testdata, or + Go-library example remains. +- Application defaults contain no Promptkit-owned behavior. +- Module metadata reflects the actual slim application graph. +- All remaining packages test, vet, and build against Promptkit `v0.1.0`. + +## Stage 3: Harden The Boundary And Rationalize Tests + +### Objective + +Make the slim dependency direction durable and leave Scriptorium with a lean +test suite that protects application behavior rather than retesting Promptkit. + +### Architecture Guard + +Rewrite `internal/adapter/dependency_test.go` as a repository-level +application-boundary guard. It may remain in the `internal/adapter` test +package, but it must locate the module root reliably and recursively inspect +all non-test production `.go` files under the repository. + +The scanner must: + +- skip `.git`, `vendor`, and other non-source output directories; +- parse imports with the Go parser instead of searching raw source text; +- reject the exact former root import + `gitea.maximumdirect.net/eric/scriptorium`; +- reject the former Scriptorium framework package families removed in Stage 2; +- reject `gitea.maximumdirect.net/eric/promptkit/internal` and every path below + it; and +- continue allowing retained Scriptorium application-internal imports such as + `internal/config`, `internal/defaults`, `internal/format`, and adapter + packages. + +Add focused scanner tests using temporary nested source trees to prove exact +root-package detection, nested former-family detection, Promptkit-internal +detection, and allowance of retained application packages. + +Add an architecture assertion that: + +- the module root has no production `.go` file; and +- each removed framework directory is absent. + +This is an intentional architecture invariant, not a generic assertion that +the whole repository tree can never change. + +### Test Ownership Audit + +Review every remaining test after the mechanical import migration: + +- `internal/adapter/cli` owns CLI parsing, configuration/flag mapping, command + output, summaries, exit codes, and representative real-engine command + workflows; +- `internal/adapter/http` owns DTO mapping, strict JSON, status/error mapping, + limits, restricted artifact policy, cancellation, and representative + real-engine handler workflows; +- `internal/config` owns strict application YAML, discovery, precedence, + validation, and application defaults; +- `internal/format` owns deterministic text/JSON presentation; and +- the architecture guard owns dependency direction and removal invariants. + +Retain the existing real Promptkit-engine adapter tests because they protect +the consumer integration seam. Keep their prompt and profile fixtures +package-local or generated with `t.TempDir`; do not recreate +`testdata/framework`. + +Delete or simplify any assertion that only duplicates Promptkit parser, +orchestration, profile, validation, model-client, or public-contract tests. +Do not add a Scriptorium table for every Promptkit sentinel or field. Preserve +only mappings Scriptorium exposes through CLI or HTTP behavior. + +Add a new test only when the cutover exposes an application-owned risk that is +not already covered. Prefer updating an existing adapter integration test over +creating a new end-to-end harness. + +### Release Workflow Check + +Inspect `.woodpecker/release.yml` and any packaging metadata for assumptions +about the removed root package or framework directories. Keep the release +target at `./cmd/scriptorium` (or its canonical module package path) and ensure +the workflow obtains Promptkit through ordinary module resolution. + +Do not add a Promptkit checkout, workspace, replacement, vendor step, or +cross-repository artifact to Scriptorium CI or release packaging. + +### Validation + +Run: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./cmd/scriptorium +``` + +Run the architecture guard directly by name as a focused diagnostic. Confirm +that its negative fixtures fail the scanner for the intended import and that +the real repository produces no violation. + +Exercise the release workflow's Go build commands locally with temporary +outputs for its supported target platforms. Do not create `dist/` or another +tracked output directory during validation. + +### Exit Criteria + +- The repository guard protects the complete new dependency direction. +- Remaining tests have an explicit application-owned purpose. +- No deleted Promptkit behavior is redundantly reimplemented in tests or + fixtures. +- Race-enabled tests, vet, application builds, and release-equivalent builds + pass. + +## Stage 4: Reconcile Permanent Documentation And Examples + +### Objective + +Make all permanent Scriptorium documentation describe the implemented slim +application and route framework readers to the version of Promptkit the +application actually consumes. + +### Version-Appropriate Promptkit Links + +Use the tagged Promptkit `v0.1.0` documents as the canonical framework +references during this step. Link to the corresponding files under: + +```text +https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/ +``` + +Use these owners where applicable: + +- `docs/consumers/pkg-promptkit.md` for Go-library consumer guidance; +- `docs/formats.md` for prompt, profile, schema, execution-setting, built-in + profile, and framework credential contracts; and +- `docs/integrations/openai-compatible-chat.md` for outbound provider wire and + timeout behavior. + +Do not copy their field tables, defaults, error inventories, or timeout rules +into Scriptorium. Scriptorium documents only its own mapping or invocation +surface and links to the Promptkit owner for the framework definition. + +### Orientation And Policy + +Update: + +- `README.md` to present only the runnable CLI and HTTP application, remove the + Scriptorium Go-package link and Go-library example, and identify Promptkit as + the imported framework; +- `docs/policy/architecture.md` to define the current application-only shape, + retained package boundaries, Promptkit dependency direction, HTTP artifact + security boundary, application invariants, and non-goals; +- `docs/development.md` to route contributors to the remaining adapter, + configuration, formatting, packaging, and Promptkit-consumer boundaries; +- `docs/policy/documentation.md` where its ownership table or boundary rules + still imply that Scriptorium owns a public Go package or framework + integration; and +- `docs/policy/testing.md` where framework-domain, validator, model-client, or + orchestration examples imply those are still Scriptorium test owners. + +Do not rewrite accepted ADR decision content. ADR 0002 remains the permanent +decision record even where its context describes the pre-split state. + +### External And User Contracts + +Audit and update: + +- `docs/cli.md` +- `docs/api.md` +- `docs/config.md` +- `docs/operations.md` +- `docs/consumers/api.md` +- `docs/integrations/subprocess.md` + +Preserve Scriptorium-owned command syntax, configuration discovery and server +fields, HTTP schemas and mappings, operations, and subprocess behavior. Remove +claims that Scriptorium provides an in-process Go API. Where these documents +name prompt/profile fields, model semantics, built-in profiles, framework +credentials, or timeout behavior, keep only the Scriptorium mapping context +and link to the tagged Promptkit owner. + +Delete `docs/consumers/pkg-scriptorium.md`. Update every incoming link so Go +framework consumers are directed to Promptkit rather than to a compatibility +document. + +Delete `docs/integrations/openai-compatible-chat.md` after replacing all +incoming Scriptorium links with the tagged Promptkit integration contract. +Scriptorium no longer owns the outbound provider protocol. + +### Internal Documentation + +Update `docs/internal/overview.md` to inventory exactly: + +- `cmd/scriptorium`; +- `internal/adapter/cli`; +- `internal/adapter/http`; +- `internal/config`; +- `internal/defaults`; and +- `internal/format`. + +Update `docs/internal/adapters.md` for Promptkit request/result mapping, engine +construction, consumer-owned interfaces, error mapping, output behavior, and +restricted-reader injection. + +Rewrite `docs/internal/sources.md` around Scriptorium-owned application source +locations and the restricted HTTP artifact reader. Link Promptkit for ordinary +artifact loading and framework source semantics. + +Delete: + +- `docs/internal/runner.md` +- `docs/internal/llm.md` + +Promptkit owns those subsystem documents. Remove all incoming links rather than +leaving placeholder internal documents. + +### Examples And Navigation + +Keep the executable configuration, prompt, profile, schema, fixture, HTTP, and +render-script examples. Confirm they still run against the tagged dependency +and that prose describes them as Scriptorium application examples. + +Remove every link to `examples/go-library`, root Go declarations, removed +framework directories, deleted Scriptorium consumer documentation, and deleted +internal or integration documents. + +Search all permanent Markdown outside `docs/roadmap/` for: + +- the former root import path used as a Go package; +- claims that Scriptorium owns or implements the framework; +- references to removed packages, tests, fixtures, or examples; and +- duplicate Promptkit framework contracts. + +The migration roadmap and accepted ADRs may retain historical and future +language appropriate to their lifecycle. + +### Validation + +Validate every local Markdown link and follow every new external Promptkit +link. Run: + +```sh +git diff --check +go test ./... +go vet ./... +go build ./cmd/scriptorium +``` + +Run the maintained render script and both `examples/config.yml` and +`examples/config.full.yml` through a credential-free `render` workflow. No +documentation validation may invoke a paid or live model endpoint. + +### Exit Criteria + +- Permanent docs describe only the implemented application boundary. +- Framework contracts have one Promptkit owner and version-appropriate links. +- Removed code and examples have no live incoming links. +- All retained examples are valid, secret-free, and runnable offline where + intended. +- Documentation links, whitespace, tests, vet, and the executable build pass. + +## Stage 5: Perform Independent Acceptance And Record Completion + +### Objective + +Validate the exact final state without sibling-repository coupling, then record +the Step 7 gate only after every feature-roadmap completion criterion is +satisfied. + +### Scriptorium Acceptance + +From the Scriptorium repository root, confirm no Go workspace is active and no +replacement or vendored dependency exists. Validate module identity and +selection: + +```sh +go list -m -f '{{.Path}} {{.GoVersion}}' +go list -m -f '{{.Path}} {{.Version}}' gitea.maximumdirect.net/eric/promptkit +go mod graph +go mod tidy -diff +``` + +Require the Scriptorium module path and existing Go version, and require +Promptkit to resolve exactly to `v0.1.0`. Inspect the graph for a normal tagged +module edge rather than a local path. + +Run: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./cmd/scriptorium +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +The formatting command must produce no paths. Build the executable to a +temporary directory rather than the repository. Reproduce the release +workflow's supported cross-compilation targets and linker flags with temporary +outputs. + +Run the maintained render script and credential-free render commands using +both configuration examples. Verify representative HTTP behavior through the +retained handler tests, including strict decoding, request/response size +limits, restricted file access, public error mapping, and optional raw output. + +Validate all maintained Markdown links, including the tagged Promptkit links. +Search the final tracked tree for former root-facade imports, removed framework +packages, built-in asset copies, framework fixtures, Go-library examples, +workspaces, replacements, generated binaries, credentials, and stale +documentation references. + +### Clean Remote-Dependency Verification + +Use a fresh temporary module cache with `GOWORK=off` and ordinary remote module +resolution to download dependencies and run at least the Scriptorium build and +test suite. The verification must not read the sibling Promptkit working tree. +Confirm the downloaded Promptkit module reports version `v0.1.0` and origin +commit `9e68a2bbf779545995270c47842048a3bc6c85dc`. + +Do not clear or destructively rewrite the maintainer's normal module cache. +Use a temporary directory and remove it after validation. + +### Independent Promptkit Reconfirmation + +Without changing Promptkit, validate the exact `v0.1.0` source from a temporary +detached worktree or the downloaded module directory. If the clean Promptkit +checkout still has `HEAD` exactly at the peeled `v0.1.0` commit, it may be used +directly. Run Promptkit's documented sequence from that exact source: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./... +go run ./examples/go-library/prepare +``` + +Also check Promptkit formatting, links, whitespace, module tidiness, absence of +a workspace/replacement, clean status, and the local and remote `v0.1.0` tag +target. Remove any temporary detached worktree after validation. This proves +that Scriptorium's adoption did not introduce cross-repository state or require +an unpublished Promptkit change. + +### Completion Records + +Only after all acceptance checks pass: + +- update `docs/roadmap/step7.md` status from Proposed to Complete and replace + future-oriented starting-state material as needed with a concise result, + retained application boundary, validation evidence, and Step 8 handoff; +- update `docs/roadmap/migration.md` so its status says Steps 1 through 7 are + complete and its Step 7 gate records the tagged dependency, removal of the + framework copy and public facade, independent validation, and readiness for + downstream migration; and +- replace this staged checklist with a concise Step 7 implementation + completion record containing the dependency version, resulting package + boundary, removed ownership, validation evidence, and next gate. + +Do not mark Step 8 or Step 9 complete. Do not publish a Scriptorium release or +claim that external consumers have migrated. + +### Exit Criteria + +- Every completion criterion in `docs/roadmap/step7.md` is demonstrably true. +- Scriptorium passes release-grade validation against remotely resolved + Promptkit `v0.1.0`. +- Promptkit remains independently clean and valid at its published tag. +- Permanent documentation, examples, module metadata, and architecture checks + match the final slim application. +- Completion records accurately authorize Step 8 without claiming later work. diff --git a/docs/roadmap/step6.md b/docs/roadmap/step6.md deleted file mode 100644 index 411652d..0000000 --- a/docs/roadmap/step6.md +++ /dev/null @@ -1,68 +0,0 @@ -# Migration Step 6: Extract And Stabilize Promptkit - -## Status - -Complete as of 2026-07-28. - -## Result - -Promptkit is now the independently published owner of Scriptorium's reusable -prompt-execution framework. The extraction used Scriptorium commit -`c7263ab2a8e58f7fb97280082d327a820c7cece7` as its source snapshot and was -accepted at Promptkit commit -`9e68a2bbf779545995270c47842048a3bc6c85dc`. - -The accepted commit is published as the annotated Go module tag `v0.1.0`. -Promptkit now provides: - -- the supported root Go facade and public error contract; -- internal prompt, profile, artifact, rendering, validation, model-client, and - orchestration packages; -- the 24 characterized built-in execution profiles; -- deterministic offline contract and package tests; -- current consumer, framework-format, integration, internal, development, - testing, and release documentation; and -- a maintained offline Go preparation example. - -Promptkit remains an importable library. It does not provide a command, inbound -HTTP service, application configuration, deployment policy, hosted CI, or -binary release. - -## Acceptance And Publication - -The exact Promptkit release commit passed ordinary and race-enabled tests, vet, -build, formatting, repository hygiene, link validation, architecture checks, -public-inventory comparison, asset comparison, and its maintained example from -a fresh checkout with `GOWORK=off`. - -The remote annotated tag object resolves to the accepted commit. A separate -temporary Go module then resolved -`gitea.maximumdirect.net/eric/promptkit@v0.1.0` from the configured remote, -selected exactly `v0.1.0`, and built and ran a root-package consumer without a -workspace or replacement. - -Scriptorium also passed its complete pre-cutover test, vet, and executable -build checks before publication. - -## Retained Application Boundary - -Scriptorium intentionally remains at the pre-cutover boundary after this -step. Its CLI, HTTP adapters, application configuration, transport policy, -restricted HTTP artifact reader, current public facade, and framework copy -remain unchanged so the application is independently buildable. - -No Scriptorium production import, dependency, consumer document, or executable -example adopts Promptkit in this completion record. - -## Next Gate - -[Migration Step 7](migration.md#step-7-slim-scriptorium-and-adopt-promptkit) -is authorized to adopt the published `v0.1.0` module, wire Scriptorium through -Promptkit's supported root API, and remove the duplicated Scriptorium framework. -That work must retain the application-owned CLI, HTTP, configuration, and -deployment boundaries and pass the Step 7 gate before any later consumer -migration begins. - -The [implementation completion record](implementation.md) records the executed -validation and release evidence. The [main migration roadmap](migration.md) -owns the remaining sequence. diff --git a/docs/roadmap/step7.md b/docs/roadmap/step7.md new file mode 100644 index 0000000..7d20ca4 --- /dev/null +++ b/docs/roadmap/step7.md @@ -0,0 +1,339 @@ +# 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.