diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 1000612..428dd65 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,987 +1,85 @@ -# Step 6 Implementation Plan +# Step 6 Implementation Completion Record ## 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. +Completed on 2026-07-28. + +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. + +## Recorded Commits And Release + +- Scriptorium extraction source: + `c7263ab2a8e58f7fb97280082d327a820c7cece7` +- Accepted Promptkit release commit: + `9e68a2bbf779545995270c47842048a3bc6c85dc` +- Published annotated Promptkit tag: `v0.1.0` +- Verified remote tag object: + `b4495c2b294967049bb363f20d5607b1f2a36f49` + +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. + +## Completed Work + +Promptkit received and characterized: + +- 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. + +Application configuration, CLI and HTTP adapters, transport policy, restricted +artifact access, deployment behavior, and executable concerns remained in +Scriptorium. + +## Validation Evidence + +The exact Promptkit release commit passed from a fresh detached checkout with +`GOWORK=off`: + +- 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. + +Before publication, unchanged Scriptorium independently passed all tests, vet, +the `cmd/scriptorium` build, and whitespace checks with no Promptkit dependency +or replacement. + +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. + +No binary or hosting-provider-specific release artifact was created. + +## Migration Handoff + +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. + +The [Step 6 completion record](step6.md) owns the completed result and retained +boundary. The [main migration roadmap](migration.md) owns all later work. diff --git a/docs/roadmap/migration.md b/docs/roadmap/migration.md index ed243aa..808b46e 100644 --- a/docs/roadmap/migration.md +++ b/docs/roadmap/migration.md @@ -2,7 +2,7 @@ ## Status -Accepted plan. Steps 1 through 5 are complete. Steps 6 through 9 remain +Accepted plan. Steps 1 through 6 are complete. Steps 7 through 9 remain proposed and are not yet implemented. ## Objective @@ -181,8 +181,8 @@ maintained examples, and configuration smoke checks. ### Step 5: Create The Promptkit Repository Promptkit was established as an independent repository and Go module through -the out-of-band workflow recorded in the -[Step 5 completion record](step5.md). Its foundation includes: +the completed out-of-band workflow recorded in repository history. Its +foundation includes: - confirmed repository access, governance, origin, and default-branch tracking; - module `gitea.maximumdirect.net/eric/promptkit` at Go `1.25.5`; @@ -203,8 +203,8 @@ records the controlling Promptkit validation and release decision. **Gate status:** Complete as of 2026-07-28. Promptkit passed its documented validation independently, all maintained links and repository-hygiene checks passed, and no workspace, replacement, CI configuration, binary, tag, command, -or placeholder package was added. Framework extraction and stabilization in -Step 6 is the next gate. +or placeholder package was added. The completed repository foundation +supported the Step 6 extraction. ### Step 6: Extract And Stabilize Promptkit @@ -231,6 +231,14 @@ passes its documented validation, and has published its first versioned tag before Scriptorium or another consumer adopts it, as required by [ADR 0003](../adr/0003-use-maintainer-run-validation-and-tag-only-releases-for-promptkit.md). +**Gate status:** Complete as of 2026-07-28. The +[Step 6 completion record](step6.md) records source Scriptorium commit +`c7263ab2a8e58f7fb97280082d327a820c7cece7`, accepted Promptkit commit +`9e68a2bbf779545995270c47842048a3bc6c85dc`, independently passing acceptance, +published annotated tag `v0.1.0`, and successful remote-consumer validation. +Scriptorium remains unchanged at its pre-cutover boundary. Step 7 adoption of +the tagged module and removal of the duplicated framework is the next gate. + ### Step 7: Slim Scriptorium And Adopt Promptkit Update Scriptorium to import the tagged Promptkit module and remove the diff --git a/docs/roadmap/step6.md b/docs/roadmap/step6.md index 33586a6..411652d 100644 --- a/docs/roadmap/step6.md +++ b/docs/roadmap/step6.md @@ -2,535 +2,67 @@ ## 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. +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.