Add an implementation plan and roadmap for Step 6 of the migration plan

This commit is contained in:
2026-07-27 23:06:23 -05:00
parent 532c31c09a
commit c7263ab2a8
2 changed files with 1523 additions and 0 deletions

View File

@@ -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.

536
docs/roadmap/step6.md Normal file
View File

@@ -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.