From c7263ab2a8e58f7fb97280082d327a820c7cece7 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 27 Jul 2026 23:06:23 -0500 Subject: [PATCH] Add an implementation plan and roadmap for Step 6 of the migration plan --- docs/roadmap/implementation.md | 987 +++++++++++++++++++++++++++++++++ docs/roadmap/step6.md | 536 ++++++++++++++++++ 2 files changed, 1523 insertions(+) create mode 100644 docs/roadmap/implementation.md create mode 100644 docs/roadmap/step6.md diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md new file mode 100644 index 0000000..1000612 --- /dev/null +++ b/docs/roadmap/implementation.md @@ -0,0 +1,987 @@ +# Step 6 Implementation Plan + +## Status + +Proposed. + +This plan implements +[Migration Step 6: Extract And Stabilize Promptkit](step6.md). The feature +roadmap is the canonical source for the target state and migration policy; this +document owns implementation order, exact work boundaries, validation gates, +and release coordination. + +## Repository Roles + +Step 6 changes two sibling repositories: + +- **Scriptorium** is the source of the characterized framework and the + controlling repository for ADRs and migration status. +- **Promptkit** receives the reusable framework, tests, assets, public + contracts, examples, and first release tag. + +Paths in this plan are relative to the named repository. Run commands from the +repository root named by each stage. + +Stages 1 through 7 change Promptkit only. They do not delete or refactor +Scriptorium framework code. Stage 8 publishes Promptkit and then updates only +Scriptorium's roadmap documents to record completion. Scriptorium does not +import Promptkit until Step 7. + +## Preconditions And Execution Rules + +Before Stage 1: + +1. Read `docs/development.md` and all files under `docs/policy/` in both + repositories. +2. Confirm the Scriptorium Step 6 feature roadmap and this plan are the only + intended planning changes. +3. Confirm Promptkit starts clean on its intended default branch. +4. Confirm there is no active Go workspace affecting either repository: + + ```sh + gowork=$(go env GOWORK) + test -z "$gowork" || test "$gowork" = off + ``` + +5. Record the starting Scriptorium and Promptkit commit IDs in implementation + notes. The Scriptorium commit is the extraction source snapshot and must be + included in the eventual Step 6 completion record. +6. Run the current baselines before copying code. + + From Scriptorium: + + ```sh + go test ./... + go vet ./... + go build ./cmd/scriptorium + ``` + + From Promptkit: + + ```sh + go test ./... + go vet ./... + go build ./... + ``` + +Stop and correct or explicitly disposition any baseline failure before +extraction. Do not interpret a pre-existing failure as an extraction defect. + +Apply these rules throughout: + +- Copy the characterized framework into Promptkit; do not remove its + Scriptorium source during Step 6. +- Rewrite imports to `gitea.maximumdirect.net/eric/promptkit`; Promptkit code + and tests must never import Scriptorium. +- Preserve observable behavior unless the package/module rename requires a + Promptkit identity change or the feature roadmap explicitly requires a + boundary correction. +- Do not combine extraction with dependency upgrades, public API redesign, + renaming for taste, or unrelated cleanup. +- Move tests and repository-local fixtures with the behavior they protect. +- Keep each stage independently buildable and testable. +- Update Promptkit's README, architecture policy, and internal overview in the + same stage whenever their current-state statements become inaccurate. +- Keep exact public API contracts in Go declarations and GoDoc. Consumer and + internal documents summarize tasks and link to canonical owners rather than + duplicating declarations. +- Do not create a Promptkit command, inbound HTTP adapter, application + configuration package, compatibility facade, hosted CI configuration, + `go.work`, `go.work.sum`, or committed local `replace`. +- Do not create, move, or publish a version tag before Stage 8. +- Do not push either repository until the publication stage unless the user + separately directs otherwise. +- Review Promptkit and Scriptorium diffs independently. Never create a + cross-repository commit. + +If Scriptorium framework code changes after the recorded source snapshot and +before publication, inspect the intervening diff. Port any relevant correctness +or security change to Promptkit and rerun all affected stage gates. Do not +silently extract from two different source states. + +## Stage 1: Extract Domain Types, Framework Defaults, And File Catalog + +### Objective + +Create the internal foundation on which the remaining Promptkit framework +packages depend without introducing a public API prematurely. + +### Promptkit Implementation + +Create these package groups from the recorded Scriptorium source snapshot: + +- `internal/domain` +- `internal/defaults` +- `internal/filecatalog` + +Copy `internal/domain/domain.go` and +`internal/domain/prepared_run_test.go`, changing only module imports or +Promptkit-specific package references required for compilation. + +Copy the file catalog implementation and tests: + +- `internal/filecatalog/catalog.go` +- `internal/filecatalog/catalog_test.go` + +Create Promptkit's `internal/defaults/defaults.go` as a responsibility split, +not a blind copy. It contains only: + +- `SchemaDirDefault`; +- `OutputArtifactName`; +- `ContentTypeTextPlain`; +- `ContentTypeTextMarkdown`; +- `ContentTypeApplicationJSON`; +- `OpenAIChatCompletionsPath`; +- the four execution defaults; +- `LLMRequestTimeoutDefault`; and +- `ExecutionTargetDefault`. + +Do not copy: + +- `HTTPAddrDefault`; +- `HTTPReadHeaderTimeoutDefault`; +- `HTTPMaxRequestBytesDefault`; +- `HTTPMaxArtifactBytesDefault`; or +- `HTTPMaxResponseBytesDefault`. + +Those values remain Scriptorium application or transport concerns. + +Retain existing literal values and behavior. Do not add exported public facade +symbols for internal defaults. + +### Current-State Documentation + +Update Promptkit in the same stage: + +- `README.md` states that extraction is in progress, identifies the internal + foundation now present, and still states that no usable public framework API + exists. +- `docs/policy/architecture.md` no longer claims that the root package is the + only implemented package. It identifies the implemented foundation and keeps + downstream-to-facade dependency direction as the target for later stages. +- `docs/internal/overview.md` lists the root package, `internal/domain`, + `internal/defaults`, and `internal/filecatalog` with only their implemented + responsibilities. + +Do not document later packages as implemented. + +### Stage 1 Validation + +From Promptkit: + +```sh +go test ./internal/domain ./internal/filecatalog +go test ./... +go vet ./... +go build ./... +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +The formatting command must produce no paths. Also confirm: + +- no external dependency was added; +- `internal/defaults` contains no CLI, server, or HTTP-limit constant; +- no file imports Scriptorium; +- all changed Markdown links resolve; and +- the README, architecture policy, and internal overview describe the same + implemented package set. + +### Stage 1 Completion Gate + +Proceed only when the foundational packages pass independently in Promptkit and +the Promptkit repository makes no claim that later sources, orchestration, or +public APIs already exist. + +## Stage 2: Extract Prompt Definitions, Profiles, Built-Ins, And Rendering + +### Objective + +Move the YAML-backed prompt and profile source stack, embedded default registry, +and prompt renderer onto the Promptkit foundation. + +### Promptkit Implementation + +Extract these package trees with their tests and test data: + +- `internal/promptdef` +- `internal/profile` +- `internal/profile/builtin` +- `internal/prompt` + +The extraction includes: + +- filesystem and `fs.FS` prompt-definition repositories; +- strict prompt YAML decoding and validation; +- prompt selection by ID and optional version; +- contained `content_file` resolution; +- filesystem and `fs.FS` profile repositories; +- profile validation and raw-key rejection; +- overlay behavior and error-preserving fallback; +- the embedded built-in repository; +- all 24 current built-in YAML assets from the recorded source snapshot; and +- Go-template rendering, session IDs, and cache-control behavior. + +Rewrite all internal imports to the Promptkit module path. Preserve package +boundaries; do not export repository or renderer implementations. + +Add `gopkg.in/yaml.v3` at the currently validated version used by Scriptorium. +Run `go mod tidy`; allow Go to generate the corresponding `go.sum` entries. +Do not copy Scriptorium's complete `go.sum` or introduce unused dependencies. + +The built-in asset tree must be byte-for-byte equivalent to the recorded source +snapshot at extraction. Asset additions, removals, model renames, or semantic +profile changes are separate work. + +### Current-State Documentation + +Update Promptkit's architecture policy and internal overview to include the +implemented source and rendering packages. Keep the README accurate that the +repository now contains internal framework behavior but still has no usable +exported engine. + +Do not create the public format contract yet. These loaders are internal until +the root facade exposes supported source construction in Stage 6. + +### Stage 2 Validation + +From Promptkit: + +```sh +go test ./internal/filecatalog ./internal/promptdef ./internal/profile/... ./internal/prompt +go test ./... +go vet ./... +go build ./... +go mod tidy +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Also: + +1. Compare the Promptkit built-in asset tree with the recorded Scriptorium + source tree and require no content difference. +2. Confirm there are exactly 24 embedded YAML assets. +3. Confirm the registry test loads every asset, detects duplicate IDs, and + verifies the expected catalog. +4. Confirm prompt and profile tests use only Promptkit-local test data. +5. Confirm strict unknown-field, invalid YAML, duplicate, containment, raw-key, + and overlay-failure cases remain covered. +6. Confirm no package imports Scriptorium. +7. Check every changed Markdown link and run `git diff --check` after module + tidying. + +### Stage 2 Completion Gate + +Proceed only when Promptkit independently owns and tests prompt loading, profile +loading, the unchanged built-in registry, and rendering without exposing +internal implementations as public packages. + +## Stage 3: Extract Artifact Reading And Output Validation + +### Objective + +Move Promptkit's ordinary artifact boundary and validation implementation while +leaving Scriptorium's restricted HTTP policy behind. + +### Promptkit Implementation + +Extract: + +- `internal/artifact/reader.go` +- `internal/artifact/reader_test.go` +- the complete `internal/validate` package and tests + +Promptkit's artifact package includes only the ordinary inline and unrestricted +caller-selected file reader. Preserve artifact copying, metadata, hashing, +content-type fallback, cancellation, and error behavior. + +Do not copy: + +- `internal/adapter/http/artifact_reader.go`; +- its rooted containment implementation; +- HTTP byte limits; +- HTTP denial policy; or +- Scriptorium status/error mapping. + +Extract the standard filesystem validator, `fs.FS` validator, validator +interface, schema loading, JSON and JSON Schema behavior, and all associated +tests. + +Add `github.com/santhosh-tekuri/jsonschema/v6` at Scriptorium's currently +validated version. Run `go mod tidy` and accept only required transitive module +entries. + +### Current-State Documentation + +Create `docs/internal/sources.md` as the current internal source document. It +describes implemented prompt, profile, built-in, schema, renderer, and ordinary +artifact behavior. It must: + +- link to the architecture policy; +- distinguish ordinary file reading from Scriptorium's restricted HTTP + reader; +- identify the package-local test owners; +- avoid presenting the future public facade as implemented; and +- avoid linking to Scriptorium-local filesystem paths. + +Update the internal overview and architecture policy with artifact and +validation responsibilities. + +### Stage 3 Validation + +From Promptkit: + +```sh +go test ./internal/artifact ./internal/validate +go test ./... +go vet ./... +go build ./... +go mod tidy +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Confirm: + +- artifact tests cover inline, file, missing-file, unsupported-reference, + cancellation, metadata, and copying behavior retained from the source; +- validator tests retain basic, JSON, schema success, content-failure, source, + registration, compilation, and operational-error distinctions; +- no rooted HTTP reader, request-size limit, response mapping, or inbound HTTP + package exists; +- the module graph contains only the YAML and JSON Schema dependency families + needed by implemented code; +- no source, test, or documentation path reaches into Scriptorium; and +- all changed Markdown links resolve. + +### Stage 3 Completion Gate + +Proceed only when artifact and validation behavior is independently tested in +Promptkit and the Scriptorium-specific HTTP security boundary remains entirely +outside Promptkit. + +## Stage 4: Extract The OpenAI-Compatible Model Client + +### Objective + +Move the provider-neutral internal client boundary and built-in +OpenAI-compatible implementation with its complete wire, timeout, security, and +failure contract. + +### Promptkit Implementation + +Extract: + +- `internal/llm/client.go` +- `internal/llm/openai_compatible_client.go` +- `internal/llm/openai_compatible_client_test.go` + +Rewrite module imports only. Preserve: + +- endpoint selection and `/chat/completions` construction; +- request mapping, reserved fields, extra parameters, cache control, session + IDs, and structured output; +- direct API-key precedence over environment lookup; +- response and token-usage decoding; +- non-success and malformed-response categories; +- response-body suppression for non-success statuses; +- supplied-client cloning and non-mutation; and +- layered caller-context, transport-cap, and generation-deadline behavior. + +Retain deterministic deadline-capturing transport tests. Do not replace them +with short wall-clock sleeps. Keep live providers, real credentials, and paid +requests out of the default suite. + +Do not add retries, tool calls, provider catalogs, inbound HTTP behavior, or a +stateful session store. + +### Current-State Documentation + +Create: + +- `docs/internal/llm.md` +- `docs/integrations/openai-compatible-chat.md` + +The integration document owns the observable outbound wire and timeout +contract. The internal document owns implementation flow, collaborators, error +categories, and tests. At this stage both documents must accurately note that +the client is implemented internally but is not yet assembled through a usable +public engine. + +Update the architecture policy and internal overview to include +`internal/llm`. + +### Stage 4 Validation + +From Promptkit: + +```sh +go test ./internal/llm +go test ./... +go vet ./... +go build ./... +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Confirm the moved client tests still cover: + +- configuration validation and endpoint behavior; +- supplied-client cloning and timeout precedence; +- caller deadlines and explicit generation timeout zero; +- direct and environment-based authentication; +- field inclusion, structured output, extra parameters, and collisions; +- malformed payload and response cases; +- non-success status handling without body disclosure; and +- cancellation and public-facing internal error identity needed by the runner. + +Check all new documentation links and verify that no document claims the root +facade is usable before Stage 6. + +### Stage 4 Completion Gate + +Proceed only when the outbound client and its exact integration contract are +independently implemented, deterministic, and free of Scriptorium transport or +application policy. + +## Stage 5: Extract Framework Orchestration + +### Objective + +Assemble the internal source, rendering, artifact, model, and validation +components under Promptkit's use-case runner while keeping the runner internal. + +### Promptkit Implementation + +Extract: + +- `internal/usecase/runner.go` +- `internal/usecase/repairer.go` +- `internal/usecase/runner_test.go` + +Rewrite imports to Promptkit and make no unrelated algorithmic changes. +Preserve: + +- request validation and prompt/profile selection; +- source loading and hashing; +- execution-setting and presence resolution; +- schema loading before generation when structured output is required; +- `Run` reuse of `Prepare`; +- one-call generation and result construction; +- content-validation results versus operational validation errors; +- internal optional repair behavior; +- error wrapping and identity; +- direct-key handling and redaction boundaries; and +- per-request state with no durable run store. + +The public engine still does not enable the optional repairer and this stage +does not add a public repair option. + +### Current-State Documentation + +Create `docs/internal/runner.md` for implemented orchestration, dependencies, +flows, failure categories, guarantees, tests, and change guidance. Link to the +source and LLM internal documents rather than repeating their contracts. + +Update the architecture policy and internal overview. The README continues to +state that internal framework behavior exists but the public facade is not yet +usable. + +### Stage 5 Validation + +From Promptkit: + +```sh +go test ./internal/usecase +go test ./... +go test -race ./internal/usecase +go vet ./... +go build ./... +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Confirm runner coverage retains: + +- preparation order and `Run`-through-`Prepare`; +- default, profile, and explicit override precedence; +- explicit zero and negative-value handling; +- prompt/profile/source errors and credential validation; +- input and rendered-prompt hashes; +- structured schema loading before generation; +- generation, validation, and repair outcomes; +- cancellation and error categories; and +- output artifact names, content types, usage, and timing. + +Confirm all collaborators remain behind internal interfaces and no internal +package has been exported merely for wiring. + +### Stage 5 Completion Gate + +Proceed only when the complete internal framework workflow passes in Promptkit +and remains inaccessible except through the future root facade. + +## Stage 6: Extract And Characterize The Root Public Facade + +### Objective + +Publish the implemented framework through Promptkit's supported root package +with the characterized Scriptorium API shape and Promptkit identity. + +### Promptkit Public Implementation + +Extract and adapt these Scriptorium root files: + +- `artifact_reader.go` +- `convert.go` +- `engine.go` +- `errors.go` +- `formatting.go` +- `json_copy.go` +- `llm_adapter.go` +- `profiles.go` +- `types.go` + +Replace the foundation-only `doc.go` comment with accurate package-level GoDoc +for the implemented Promptkit library. + +Extract and adapt: + +- `engine_test.go` +- `artifact_reader_internal_test.go` +- `testdata/framework/**` + +Use package `promptkit` for implementation and `promptkit_test` where the source +uses external-package contract tests. Change imports from the Scriptorium root +to the Promptkit root. + +Preserve the complete exported facade described by the feature roadmap: + +- `Engine`, `Config`, `Option`, `NewEngine`, `Prepare`, and `Run`; +- source and injection options; +- request, result, artifact, execution, output, validation, rendering, cache, + structured-output, usage, and profile values; +- serialized constants and helper constructors; +- `ArtifactReader` and `LLMClient`; +- built-in OpenAI-compatible profile construction; and +- all public sentinel errors and `errors.Is` relationships. + +Do not export internal repositories, domain types, concrete validators, +concrete internal clients, or public subpackages. + +Make only these intentional identity changes: + +- module imports use `gitea.maximumdirect.net/eric/promptkit`; +- package names and GoDoc say Promptkit; +- `String` and `GoString` outputs identify `promptkit.RunRequest` and + `promptkit.GenerateRequest`; and +- examples embedded in GoDoc use the Promptkit qualifier. + +Do not retain the Scriptorium package name or provide an alias/forwarder. + +Preserve: + +- nil engine and option handling; +- source replacement and overlay precedence; +- empty schema-directory fallback; +- client cloning and timeout behavior; +- public value copying and mutation isolation; +- JSON-compatible extra-parameter validation; +- secret omission and redacted formatting; +- artifact-reader nil-response handling; +- public error mapping and wrapped collaborator identity; and +- preparation and run results characterized in Scriptorium. + +### Dependency Guard + +Add a focused Promptkit architecture test that recursively walks repository Go +source files, parses their imports, and fails when production or test code imports +`gitea.maximumdirect.net/eric/scriptorium` or a subpackage. The test must: + +- inspect nested packages, not only the root; +- ignore `.git` and generated or vendor directories that are not maintained + source; +- report the offending file and import; +- avoid encoding the full current package inventory; and +- remain useful after legitimate internal reorganization. + +Do not add a brittle test that rejects ordinary standard-library `net/http` +use, because Promptkit's outbound client legitimately requires it. + +### Current-State Documentation + +Update immediately: + +- `README.md` now states that Promptkit provides a usable public engine and + links to the forthcoming/final consumer documentation only when that file + exists in the same stage. +- `docs/policy/architecture.md` describes the implemented root-facade-to- + internal dependency direction as current state. +- `docs/internal/overview.md` inventories the root facade and every implemented + internal package. +- `docs/integrations/openai-compatible-chat.md` and internal documents remove + any temporary statement that the client or runner is not publicly assembled. + +Create `docs/consumers/pkg-promptkit.md` in this stage so task-oriented +consumers have a current owner when the public API lands. Derive it from the +characterized Scriptorium consumer contract, but: + +- use the Promptkit module and package names; +- link exact exported declarations to GoDoc ownership rather than restating + signatures unnecessarily; +- retain construction, sources, preparation, execution, profiles, credentials, + extensions, redaction, and error guidance; +- do not mention the Scriptorium CLI or HTTP contract except as a downstream + consumer boundary; and +- link file-format and outbound integration details only after their canonical + documents exist. + +If `docs/formats.md` is deferred to Stage 7, do not add a broken link; add it +when that document is created. + +### Stage 6 Validation + +From Promptkit: + +```sh +go test . +go test ./... +go test -race ./... +go vet ./... +go build ./... +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Also: + +1. Run `go doc .` and compare the exported inventory with the characterized + Scriptorium facade, allowing only the package/module identity change. +2. Run focused public contract tests for construction, source options, profile + precedence, preparation, execution, validation, timeout layering, custom + clients, custom artifact readers, copying, redaction, and errors. +3. Confirm `String` and `GoString` never expose raw API keys and contain no + `scriptorium.` type prefix. +4. Confirm the recursive dependency guard detects a temporary nested + Scriptorium import when deliberately exercised, then remove the temporary + violation. +5. Search every tracked Go file for the Scriptorium module path and require no + matches. +6. Confirm no public subpackage, command, application config, inbound HTTP + adapter, or compatibility shim exists. +7. Check every changed Markdown link and every new GoDoc example. + +### Stage 6 Completion Gate + +Proceed only when an external Go consumer can construct and exercise the +Promptkit engine through the module root and the complete public contract suite +passes without Scriptorium or repository-local coupling. + +## Stage 7: Complete Durable Documentation, Examples, And Release Readiness + +### Objective + +Finish Promptkit's current-state documentation and provide a maintained, +offline consumer workflow before release validation. + +### Framework Format Contract + +Create `docs/formats.md` as the canonical owner for: + +- prompt-definition YAML fields and strict decoding; +- inputs, messages, inline content, `content_file`, cache control, session IDs, + default profiles, and output contracts; +- profile YAML fields, ranges, overlays, `api_key_env`, raw-key prohibition, + and execution settings; +- the current built-in profile catalog; +- schema references and supported validation modes; +- credential behavior that belongs to framework formats; and +- relationships among file values, in-memory profiles, and request overrides. + +Derive framework-format content from the implemented code and the framework +sections of Scriptorium's `docs/config.md`. Do not copy: + +- Scriptorium config discovery; +- `prompt_dir`, `profile_dir`, or `schema_dir` application precedence; +- server settings; +- render-output settings; +- CLI flags; or +- Scriptorium operations behavior. + +Update Promptkit's documentation policy to assign framework formats to +`docs/formats.md`. Update all consumer, integration, and internal documents to +link to that canonical owner rather than duplicate its field tables and +defaults. + +### Consumer Example + +Create a self-contained offline example at: + +- `examples/go-library/prepare/main.go` +- `examples/go-library/prepare/prompt.yaml` + +The example: + +- imports `gitea.maximumdirect.net/eric/promptkit`; +- uses `WithPromptFile` for its repository-local prompt; +- supplies a valid in-memory `Profile` with `WithProfiles`; +- uses an inline synthetic input; +- calls `Prepare`, not a live provider; +- prints deterministic JSON containing only stable summary fields; +- requires no credential or environment variable; +- reads no Scriptorium path; and +- runs from the Promptkit repository root with + `go run ./examples/go-library/prepare`. + +Keep the prompt asset minimal and copyable. Do not duplicate Scriptorium's full +executable example tree. + +### Documentation Reconciliation + +Reconcile these Promptkit documents with the final implemented tree: + +- `README.md` +- `docs/development.md` +- `docs/policy/architecture.md` +- `docs/policy/documentation.md` +- `docs/policy/testing.md` +- `docs/release.md` +- `docs/consumers/pkg-promptkit.md` +- `docs/formats.md` +- `docs/integrations/openai-compatible-chat.md` +- `docs/internal/overview.md` +- `docs/internal/runner.md` +- `docs/internal/sources.md` +- `docs/internal/llm.md` + +Requirements: + +- The README provides a minimal current quickstart and links to the maintained + example and consumer guide. +- The development guide routes public API, source, model-client, validation, + test, example, documentation, and release work to current owners. +- Architecture and the internal overview agree on every package and dependency + boundary. +- The testing policy describes the actual consumer-workflow and package test + types without copying a test inventory. +- The release procedure adds `go test -race ./...` to pre-tag validation while + retaining ordinary test, vet, build, formatting, links, and hygiene checks. +- The release procedure still requires a clean checkout, no workspace or + replacement, an annotated semantic tag, and remote verification. +- The first release remains `v0.1.0`; do not create it in this stage. +- No permanent Promptkit document relies on the temporary Scriptorium roadmap + as its current contract. +- No document claims Promptkit provides a command, inbound HTTP service, + application configuration, or binary release. +- Exact Go declarations stay in GoDoc; exact format and wire definitions stay + in their canonical documents. + +### Stage 7 Validation + +From Promptkit: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./... +go run ./examples/go-library/prepare +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Also: + +1. Validate every maintained local Markdown link. +2. Compile or run fenced Go snippets that are represented as runnable. +3. Confirm the example output is deterministic and contains no secret, + timestamp, absolute path, or machine-specific value. +4. Search maintained files for: + + - the Scriptorium module import; + - `scriptorium.RunRequest` and `scriptorium.GenerateRequest`; + - stale claims that framework APIs are unimplemented; + - template residue; + - absolute maintainer filesystem paths; + - live credentials; and + - claims of hosted CI or binary releases. + +5. Confirm `docs/formats.md` owns framework field tables and that other + documents summarize and link. +6. Confirm the README, architecture policy, development guide, internal + overview, consumer guide, and release procedure agree that Promptkit is a + usable library validated by maintainers. + +### Stage 7 Completion Gate + +Proceed only when Promptkit can be understood, used, tested, and prepared for +release solely from its own maintained documentation and example. + +## Stage 8: Validate, Publish `v0.1.0`, And Close Step 6 + +### Objective + +Validate the complete extraction from clean independent checkouts, publish the +first immutable Promptkit module tag, verify remote consumption, and record the +completed migration gate in Scriptorium. + +### Prepare The Promptkit Release Candidate + +Before release: + +1. Review every Promptkit change against the recorded Scriptorium source + commit. +2. Confirm all Stages 1 through 7 are committed in Promptkit with a clean + working tree. +3. Use plain-English commit messages and keep Promptkit commits in the + Promptkit repository only. +4. Confirm no `go.work`, `go.work.sum`, local `replace`, generated output, or + temporary extraction script is tracked. +5. Confirm the release candidate commit is published through Promptkit's normal + branch workflow before tagging, as required by `docs/release.md`. + +Do not amend, force-push, or retag an already published version to correct a +late failure. Correct the source and repeat validation before the first tag is +published. + +### Independent Promptkit Acceptance + +Create a fresh temporary checkout of the exact Promptkit release candidate +outside both repositories. Ensure `GOWORK` is empty or `off`. From that +checkout run: + +```sh +go mod tidy +go test ./... +go test -race ./... +go vet ./... +go build ./... +go run ./examples/go-library/prepare +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +Require the checkout to remain clean after validation. + +Verify module identity: + +```sh +go list -m -f '{{.Path}} {{.GoVersion}}' +go list -f '{{.Name}} {{.ImportPath}}' . +``` + +Verify dependency independence: + +- `go list -m all` contains no Scriptorium module; +- `go list -deps ./...` contains no Scriptorium package; +- a recursive source search contains no Scriptorium module import; +- `go.mod` has no `replace`; +- no workspace file is tracked; and +- no source, fixture, example, or documentation read depends on a sibling + checkout. + +Verify architecture and assets: + +- the root is the only supported public Promptkit package; +- all implementation packages are under `internal/`; +- no `cmd`, inbound adapter, application config, restricted HTTP reader, or + executable artifact exists; +- the 24 built-in assets match the recorded extraction source and all load; +- the architecture dependency test passes; +- the public Go inventory and sentinel errors match the accepted initial + facade; +- all local Markdown links and runnable examples pass; and +- GPLv3 and Promptkit-specific notices remain unchanged by extraction. + +If any check fails, fix the owning stage, commit the correction, and repeat the +entire fresh-checkout acceptance suite. + +### Preserve The Pre-Cutover Scriptorium + +Before tagging, validate Scriptorium from its own repository without a +workspace or replacement: + +```sh +go test ./... +go vet ./... +go build ./cmd/scriptorium +git diff --check +``` + +Run maintained configuration and example checks required by Scriptorium's +current documentation when affected by any intervening source correction. +Confirm: + +- `go.mod` has no Promptkit dependency or local replacement; +- the CLI and HTTP adapters still use the current Scriptorium facade; +- no framework implementation was deleted; +- no current Scriptorium contract was redirected prematurely; and +- only roadmap documentation is awaiting the Step 6 completion update. + +### Publish And Verify `v0.1.0` + +Follow Promptkit's `docs/release.md` exactly: + +1. create annotated tag `v0.1.0` on the accepted Promptkit commit; +2. record in the annotation that documented validation passed for that commit; +3. inspect the tag and its resolved commit; +4. push the tag to the configured Promptkit origin; and +5. verify the remote annotated tag object and resolved commit. + +Do not publish a binary or hosting-provider-specific release artifact. + +After the remote tag is available, create a temporary Go consumer module +outside both repositories with `GOWORK=off`. Require +`gitea.maximumdirect.net/eric/promptkit@v0.1.0` from the configured remote, +compile a minimal program that imports the root package and uses an exported +value such as `promptkit.Inline`, and confirm: + +- the module resolves without a local replacement; +- the selected version is exactly `v0.1.0`; and +- the program builds against the published tag. + +This temporary smoke module is validation only. Do not commit it or use it to +begin Scriptorium adoption. + +### Scriptorium Completion Records + +Only after the tag and remote-consumption check succeed, update Scriptorium: + +- change `docs/roadmap/step6.md` to Complete and replace active planning prose + with a concise completion record that includes the source Scriptorium commit, + accepted Promptkit commit, published tag, validation outcome, retained + application boundary, and Step 7 gate; +- update `docs/roadmap/migration.md` to mark Steps 1 through 6 complete and + identify tagged Promptkit adoption and Scriptorium framework removal in Step + 7 as next; +- revise this file into a concise `Completed Work` record rather than leaving + an active stage checklist; and +- remove stale “next step” language from older completed gate summaries if any + has reappeared. + +Do not update Scriptorium production code, imports, `go.mod`, consumer +documentation, or executable examples in this stage. + +Validate all changed Scriptorium links and run `git diff --check`. Keep the +completion-record commit in Scriptorium's history and separate from all +Promptkit commits. + +### Stage 8 Completion Gate + +Step 6 is complete only when: + +- all feature-roadmap completion criteria are satisfied; +- Promptkit passes the full suite from a clean independent checkout; +- Scriptorium remains valid in its pre-cutover state; +- remote tag `v0.1.0` resolves to the accepted Promptkit commit; +- a clean temporary consumer resolves and builds against that tag without a + replacement; +- both repositories have clean, independent histories; and +- Scriptorium's migration roadmap authorizes Step 7 and no earlier adoption. + +## Open Questions + +None. The accepted ADRs, Step 6 feature roadmap, characterized facade, and +current repository policies resolve the extraction, public boundary, +validation, documentation, and release decisions required for implementation. diff --git a/docs/roadmap/step6.md b/docs/roadmap/step6.md new file mode 100644 index 0000000..33586a6 --- /dev/null +++ b/docs/roadmap/step6.md @@ -0,0 +1,536 @@ +# Migration Step 6: Extract And Stabilize Promptkit + +## Status + +Proposed scope. Migration Step 5 is complete, the Promptkit repository +foundation is available, and framework extraction has not yet begun. + +## Purpose + +Establish Promptkit as the independent owner of Scriptorium's reusable +prompt-execution framework, public Go facade, built-in profile registry, +framework tests, consumer example, and framework documentation. + +This step delivers and publishes the first usable Promptkit library without +changing Scriptorium to consume it. The +[main migration roadmap](migration.md) owns the overall sequence. +[Step 6 implementation plan](implementation.md) owns execution staging and +validation gates; this document owns the desired end state and completion +policy. +[ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md) owns the project +boundary, breaking-change policy, module path, versioning direction, and +cross-repository release order. +[ADR 0003](../adr/0003-use-maintainer-run-validation-and-tag-only-releases-for-promptkit.md) +owns Promptkit's maintainer-run validation and tag-only release model. + +## Confirmed Migration Policy + +- Promptkit's module and public import path remain + `gitea.maximumdirect.net/eric/promptkit`. +- The public package is `promptkit` at the module root. +- This migration is intentionally breaking. Promptkit does not provide aliases, + forwarding packages, or another compatibility layer for the former + Scriptorium import path. +- The initial Promptkit facade preserves the useful exported shape and + observable behavior of the characterized Scriptorium facade, except for + project and package identity changes required by the new module. +- Extraction must not become an unrelated public API redesign. Broader changes + follow the split unless correctness or the accepted ownership boundary + requires them. +- Promptkit owns application-neutral framework behavior. Scriptorium continues + to own executable, CLI, HTTP-server, application-configuration, deployment, + and process concerns. +- Promptkit must remain independently buildable and testable without a + Scriptorium checkout, Go workspace, local replacement, or unpublished + dependency. +- Promptkit's first release is `v0.1.0`. The tag must be published before + Scriptorium or another consumer adopts Promptkit. +- Scriptorium adoption and removal of its former framework implementation + belong to Step 7, not this step. + +## Extraction Model And Transitional Ownership + +Step 6 establishes the framework in Promptkit while leaving the current +Scriptorium module operational until Step 7. Because the repositories cannot +land one atomic cross-repository change, the Scriptorium framework code and +current Go-consumer documentation remain temporarily in place during this +step. + +At Step 6 completion: + +- Promptkit is the canonical project for new framework development and the + tagged library contract. +- Scriptorium still contains its pre-cutover framework copy solely so the + executable and existing module remain buildable before Step 7. +- New framework features and unrelated framework refactors do not land in the + Scriptorium copy during this transition. +- A necessary defect or security correction discovered before Step 7 is + applied consistently to Promptkit and to any still-executed Scriptorium copy, + with contract tests protecting the shared observable behavior. +- No source file, test, asset, or documentation in either repository reads from + the other repository's working tree. + +This temporary duplication is a migration state, not the target architecture. +Step 7 removes the Scriptorium framework copy after adopting the tagged +Promptkit module. + +## Target Promptkit Repository State + +Promptkit becomes a complete reusable Go library with: + +- a supported root public facade; +- internal framework implementation packages; +- embedded built-in execution profiles; +- strict prompt, profile, and schema loading; +- ordinary inline and caller-selected file artifact reading; +- prompt rendering, preparation, generation, validation, and error + classification; +- a provider-neutral model-client boundary and built-in OpenAI-compatible + client; +- contract-focused, deterministic, offline tests; +- current consumer, format, integration, and internal documentation; +- a maintained, offline Go consumer example; and +- a published `v0.1.0` Go module tag. + +Promptkit has no runnable command, HTTP service, binary release, hosted CI +configuration, application-config discovery, deployment policy, or +Scriptorium dependency. + +## Public Go Facade + +### Package Identity + +The existing Scriptorium root facade is extracted to package `promptkit`. +Exported GoDoc, package comments, examples, formatted request summaries, and +other project-identifying text use Promptkit terminology. In particular, +`String` and `GoString` representations identify `promptkit.RunRequest` and +`promptkit.GenerateRequest`, not the former package. + +No import-path compatibility package is created in either repository. + +### Engine Construction And Sources + +Promptkit provides: + +- `NewEngine(Config, ...Option)`; +- `Engine.Prepare`; +- `Engine.Run`; +- directory-backed prompt, profile, and schema sources through `Config`; +- `WithPromptFS` and `WithPromptFile`; +- `WithProfileFS`, `WithProfileFile`, and `WithProfiles`; +- `WithSchemaFS` and `WithSchemaFile`; +- `WithArtifactReader`; and +- `WithLLMClient`. + +Nil options retain the characterized behavior. Invalid construction and invalid +extension values preserve the public `ErrInvalidConfig` category. + +Prompt definitions, profiles, schemas, source selection, overlay precedence, +and strict-decoding behavior remain application-neutral Promptkit concerns. +Scriptorium configuration-file discovery and CLI precedence do not move with +them. + +### Public Values And Extension Points + +The initial root facade includes the currently characterized: + +- request, prepared-run, result, artifact, execution-target, output-contract, + validation, usage, rendered-prompt, cache-control, and structured-output + values; +- serialized enum values for artifact types, output formats, validation modes, + validation statuses, cache control, and structured output; +- presence-aware numeric request overrides; +- `ArtifactReader` extension point and `File`, `Inline`, and `InlineWithURI` + helpers; +- `LLMClient`, `GenerateRequest`, and `GenerateResponse` extension boundary; +- in-memory `Profile`, `OpenAICompatibleProfileConfig`, and + `OpenAICompatibleProfile`; and +- public sentinel errors used by Go consumers to classify failures through + `errors.Is`. + +Exported names, signatures, serialized values, copying and mutation isolation, +nil handling, and error relationships match the characterized Scriptorium +facade unless the module/package rename necessarily changes the observable +text. `ErrProfileRequired` and `ErrAPIKeyEnvMissing` continue also to match +`ErrInvalidRequest`. + +The root facade does not expose internal domain types, repositories, renderers, +validators, concrete model clients, adapter DTOs, or assembly constructors. +No speculative extension point or public subpackage is introduced. + +### Preparation And Execution Contract + +Promptkit preserves the characterized engine workflow: + +- `Prepare` validates and loads the prompt and profile, resolves execution + settings and credentials, loads any structured-output schema, reads input + artifacts, renders messages, computes hashes, and returns prepared state + without calling a model. +- `Run` reuses the same preparation flow, makes one generation call, creates + the output artifact, validates generated content, and returns result, + validation, usage, hash, and timing metadata. +- Generated-content validation failures remain successful calls with a failed + validation result. Schema access, compilation, and validator runtime failures + remain errors. +- Optional internal repair behavior and its tests remain framework-owned, but + extraction does not add a new public repair API. +- The framework creates no durable run store, checkpoint, archive, or resume + workflow. + +## Framework Package Ownership + +The implementation may reorganize files when needed for clean Promptkit +boundaries, but the completed library owns these current Scriptorium +responsibilities: + +| Current Scriptorium package or file group | Promptkit responsibility | +| --- | --- | +| Root facade Go files and facade tests | Root `promptkit` package, public construction, values, options, conversions, error mapping, redaction, and facade contracts. | +| `internal/domain` | Framework request, preparation, execution, result, validation, artifact, profile, and model-client domain values. | +| `internal/usecase` | Preparation and execution orchestration, setting resolution, validation coordination, and internal repair boundary. | +| `internal/filecatalog` | Deterministic YAML discovery and source-root helpers. | +| `internal/promptdef` | Strict prompt-definition loading from filesystem and `fs.FS` sources. | +| `internal/profile` | Strict execution-profile loading, validation, filesystem and `fs.FS` sources, and overlay behavior. | +| `internal/profile/builtin` | Embedded built-in profile registry and assets. | +| `internal/prompt` | Go-template prompt rendering and cache-control handling. | +| `internal/artifact` | Ordinary inline and unrestricted caller-selected file artifact reading. | +| `internal/validate` | Basic, JSON, and JSON Schema validation plus filesystem and `fs.FS` schema access. | +| `internal/llm` | Provider-neutral internal client boundary and OpenAI-compatible implementation. | +| Framework-owned members of `internal/defaults` | Schema fallback, execution defaults, output artifact and content types, OpenAI request path, and built-in client transport cap. | +| Framework contract and package test data | Repository-local Promptkit fixtures that support the moved public and internal test suites. | + +Internal packages use the Promptkit module path and may import other Promptkit +internal packages only in the dependency direction defined by its architecture +policy. They do not import Scriptorium. + +## Defaults And Settings + +Promptkit owns the behavior and defaults used by its engine: + +- empty `SchemaDir` uses the framework's current `.` fallback; +- execution temperature, token, top-p, and generation-timeout defaults; +- output artifact name and content types; +- the OpenAI-compatible chat-completions path; +- the built-in client's ten-minute transport-cap fallback; and +- source and validation defaults that do not depend on an application + transport. + +The execution-setting hierarchy remains request override, then non-zero profile +value, then framework default. Numeric request fields remain presence-aware so +explicit zero is distinct from omission. + +Scriptorium retains ownership of its server address, request and response byte +limits, HTTP read-header timeout, CLI defaults, render-format defaults, and +application configuration precedence. Those values do not enter Promptkit. + +## Source, Profile, And Built-In Registry Behavior + +Promptkit preserves: + +- strict YAML decoding and rejection of unknown fields; +- prompt selection by ID and optional version rather than filename; +- prompt `content_file` resolution relative to its owning source and + containment within `fs.FS` roots; +- profile selection by ID, validation ranges, raw-key rejection, and + `api_key_env` behavior; +- in-memory profile precedence over an explicit file or filesystem source, + followed by built-ins; +- fallback to built-ins only for a genuine profile-not-found result, without + hiding primary-source decoding or validation failures; +- schema path resolution and the distinction between validation mismatch and + operational failure; and +- ordinary inline/file artifact hashing, content-type handling, copying, and + failure behavior. + +The complete current embedded built-in profile registry moves into Promptkit. +All assets remain embedded, strict-loader-valid, uniquely identifiable, and +covered by registry tests. No built-in asset is silently added, removed, or +semantically changed merely as part of extraction. + +Promptkit's ordinary file reader is intentionally not a deployment sandbox. It +may read a path deliberately selected by an in-process consumer. Rooted +containment, byte limits, denial policy, and symlink/deployment policy for the +Scriptorium HTTP interface remain in Scriptorium. + +## OpenAI-Compatible Client + +Promptkit owns the characterized outbound client contract: + +- endpoint construction and `POST /chat/completions`; +- rendered messages, session IDs, cache-control blocks, structured-output + payloads, and flattened provider-specific parameters; +- reserved-field protection and JSON-compatible extra-parameter validation; +- direct request API-key precedence over environment lookup; +- model and execution-setting mapping, including explicit numeric zero values; +- response decoding and token-usage mapping; +- non-success and malformed-response classification without exposing provider + response bodies; and +- no implicit retry, tool-call, or durable-session behavior. + +Timeout enforcement remains layered: + +- a positive supplied `HTTPClient.Timeout` is the transport cap; +- otherwise a positive `Config.Timeout` supplies the transport cap; +- otherwise the internal ten-minute cap applies; +- a positive effective `timeout_seconds` creates a per-generation context + deadline; +- an explicit request value of zero disables only the generation deadline; and +- the earliest caller-context deadline, transport cap, or positive generation + deadline terminates the call. + +Supplied HTTP clients are cloned and not mutated. Cancellation and transport +failures retain the public generation-error category. + +## Application Concerns That Do Not Move + +Step 6 does not copy or recreate these Scriptorium-owned components in +Promptkit: + +- `cmd/scriptorium`; +- `internal/adapter/cli`; +- `internal/adapter/http`, including the restricted HTTP artifact reader; +- `internal/config`; +- `internal/format`; +- CLI and HTTP DTOs, parsing, output, status mapping, and transport limits; +- configuration-file discovery and CLI-over-configuration precedence; +- process cancellation, logging, server construction, or operations behavior; +- executable packaging, subprocess integration, or deployment guidance; or +- Scriptorium-specific executable examples and configuration files. + +Use of `net/http` for Promptkit's outbound model client and the public +`*http.Client` construction option remains valid framework behavior. It does +not authorize an inbound HTTP service or transport adapter in Promptkit. + +## Dependencies And Repository Independence + +Promptkit adds only dependencies required by the extracted implementation. The +initial extraction retains the currently validated YAML and JSON Schema library +versions unless a correctness issue requires an explicit change. Module +metadata is tidied and includes only direct and transitive dependencies used by +Promptkit. + +The completed Promptkit module: + +- has no dependency on `gitea.maximumdirect.net/eric/scriptorium`; +- contains no import of a Scriptorium package; +- contains no committed `go.work`, `go.work.sum`, or local filesystem + `replace`; +- does not read Scriptorium-relative paths from code, tests, examples, or + documentation; +- does not require Scriptorium environment variables, commands, or build + artifacts; and +- builds and tests successfully from an independent clean checkout. + +Temporary local workspace or replacement configuration may be used while +developing the cross-repository extraction, subject to Promptkit's development +guide. It is removed before acceptance and does not appear in a commit or tag. + +## Test And Fixture Ownership + +Tests move with the framework behavior they protect. Promptkit owns: + +- public facade construction, source, profile, execution, validation, + extension, timeout, copying, redaction, and error-classification tests; +- runner and domain contract tests; +- prompt, profile, built-in registry, schema, artifact, renderer, file-catalog, + and OpenAI-compatible client tests; +- deterministic test doubles for model and external boundaries; +- package-local prompt, profile, schema, and artifact test data; and +- representative end-to-end library preparation and execution coverage. + +Tests are rewritten only for Promptkit identity, repository-local paths, clean +package boundaries, or an explicitly documented correction. They do not lose +meaningful behavioral coverage merely because internal files move. + +Promptkit tests remain deterministic, offline, parallel-safe, and independent +of credentials, paid APIs, live providers, mutable services, Scriptorium, and +test execution order. HTTP client tests use controlled local transports or +test servers as appropriate. + +Scriptorium's CLI, HTTP, restricted-reader, application-config, prepared-output +formatting, executable dependency-guard, and process tests remain in +Scriptorium. Step 6 does not move those transport tests into Promptkit. + +## Documentation And Examples + +Promptkit's durable documentation describes the implemented library at Step 6 +completion and owns the framework contracts. At minimum: + +- `README.md` presents Promptkit as usable, includes a minimal current + orientation or quickstart, and no longer says framework behavior is + unimplemented. +- Go declarations and GoDoc own exact exported names, signatures, fields, + values, and error contracts. +- `docs/consumers/pkg-promptkit.md` provides task-oriented construction, + preparation, execution, source, profile, credential, extension, and error + guidance without duplicating exact Go declarations. +- `docs/formats.md` owns prompt-definition, profile, schema-reference, + validation, execution-setting, built-in-profile, and credential file-format + contracts. +- `docs/integrations/openai-compatible-chat.md` owns the outbound HTTP wire and + timeout contract. +- `docs/internal/runner.md`, `docs/internal/sources.md`, and + `docs/internal/llm.md` describe the implemented internal behavior and tests. +- `docs/internal/overview.md` inventories every implemented package and links + to its canonical contract or focused internal document. +- `docs/development.md`, the architecture, documentation, and testing policies, + and `docs/release.md` are reconciled with the implemented package tree and + validation workflow. + +Promptkit's documentation policy is updated to assign one canonical owner to +framework formats. Documentation uses Promptkit package names and import paths, +does not claim CLI or inbound HTTP ownership, and does not rely on temporary +Scriptorium roadmap files for its current public contract. + +Promptkit contains a maintained Go consumer example under +`examples/go-library/prepare`. The example: + +- imports Promptkit at its canonical module path; +- is self-contained within the Promptkit repository; +- uses only implemented public APIs; +- performs an offline representative preparation flow without credentials or + a live model call; +- does not read Scriptorium's examples or working tree; and +- is executed as part of acceptance validation. + +Any example-specific prompt, profile, schema, or fixture asset belongs to +Promptkit and is minimal, synthetic, secret-free, and maintained with the +example. Scriptorium's executable examples remain in Scriptorium until their +Step 7 documentation cutover. + +Because Scriptorium still implements and exposes its old facade during this +transition, its current Go and framework documentation remains in place through +Step 6. Step 7 replaces that material with Scriptorium application guidance and +links Go consumers to Promptkit. + +## Release Outcome + +After the extracted library and documentation satisfy every acceptance check, +Promptkit publishes annotated semantic Go module tag `v0.1.0` using its +documented release procedure. + +The tag: + +- identifies the validated Promptkit commit; +- contains no workspace, replacement, generated binary, or release artifact; +- is available from the configured Promptkit origin; +- resolves to the independently validated source commit; and +- is the version that Step 7 will use when Scriptorium adopts Promptkit. + +No Scriptorium dependency update, consumer release, Promptkit binary, or +hosting-provider-specific release artifact is part of this release. + +## Required Validation Outcome + +From an independent clean Promptkit checkout with no active workspace or local +replacement, maintainers must successfully run: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./... +gofmt -l $(git ls-files '*.go') +git diff --check +``` + +The formatting command produces no paths. Acceptance also requires: + +- `go list -m` reports module + `gitea.maximumdirect.net/eric/promptkit` and the intended Go version; +- the root package reports name `promptkit` and the canonical import path; +- `go mod tidy` leaves module metadata clean; +- the module graph and all source imports contain no Scriptorium dependency; +- every package test and representative library workflow is offline and + deterministic; +- the maintained Go consumer example runs successfully and produces its + documented output shape; +- all embedded built-in profiles load and the registry tests pass; +- all maintained Markdown links, Go snippets, import paths, commands, and + repository-relative paths are valid; +- current Promptkit documents agree on package ownership, behavior, validation, + and release state; +- no template residue, stale Scriptorium package identity, real credential, + private fixture, or unsupported future claim remains; +- no command package, inbound HTTP adapter, application config, workspace, + replacement, hosted CI configuration, generated binary, or unrelated + artifact is present; +- Git status is clean before tagging; and +- the published `v0.1.0` tag passes the verification required by + `docs/release.md`. + +The current Scriptorium repository must continue to pass: + +```sh +go test ./... +go vet ./... +go build ./cmd/scriptorium +``` + +Scriptorium documentation links and maintained examples also remain valid. +These checks confirm that Step 6 did not break the pre-cutover executable while +Promptkit was established independently. + +## Out Of Scope + +Step 6 does not: + +- update Scriptorium imports or `go.mod` to consume Promptkit; +- delete the Scriptorium root facade or framework packages; +- remove or redirect Scriptorium's current Go-consumer documentation; +- migrate CLI, HTTP, application configuration, prepared-output formatting, or + restricted HTTP artifact behavior; +- migrate downstream consumers; +- provide a Scriptorium compatibility facade; +- redesign the public engine around a new workflow; +- add retries, tool calls, durable sessions, checkpoints, or multi-step + orchestration; +- add a public repair API without a separately accepted need; +- add hosted Promptkit CI, binary packaging, or executable releases; +- introduce placeholder public packages or speculative extension points; +- upgrade unrelated dependencies; or +- begin the Step 7 Scriptorium cutover before `v0.1.0` is published and + verified. + +## Completion Criteria + +Step 6 is complete when: + +- Promptkit independently implements the application-neutral framework + contract owned by ADR 0002; +- the root `promptkit` facade exposes the characterized engine, values, + sources, profiles, extension points, and public error identities without + compatibility shims or speculative exports; +- preparation, execution, profile/default precedence, presence-aware + overrides, artifact loading, rendering, structured output, validation, + timeout layering, redaction, and error classification retain their + characterized behavior; +- all framework packages, tests, fixtures, and the complete built-in profile + registry are owned and maintained within Promptkit; +- Scriptorium-only executable, adapter, application-config, restricted-reader, + formatting, deployment, and process concerns are absent from Promptkit; +- Promptkit's module dependencies are minimal, tidy, and independent of + Scriptorium; +- current consumer, format, integration, internal, contributor, architecture, + testing, and release documentation has one coherent Promptkit-specific + ownership model; +- the maintained Promptkit Go example is self-contained, offline, and passing; +- the complete Promptkit validation suite, race suite, documentation checks, + repository-hygiene checks, and release checks pass from a clean independent + checkout; +- Scriptorium remains independently buildable, tested, and documented in its + pre-cutover state; +- Promptkit `v0.1.0` is published and verified against the validated commit; +- no Scriptorium or downstream consumer has adopted an unpublished Promptkit + revision or a local replacement; and +- `migration.md` records Step 6 as complete and identifies the tagged + Scriptorium adoption and framework-removal work in Step 7 as the next gate. + +Migration Step 7 must not begin until these criteria are satisfied. + +## Lifecycle + +This feature roadmap is a temporary cross-repository migration artifact. It +remains in Scriptorium while Step 6 is active and may be reduced to a completion +record or removed after the migration status and durable contracts have moved +to their canonical owners.