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.