3 Commits

Author SHA1 Message Date
2f42bdde39 Publish Promptkit migration guidance and release notes
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
2026-07-28 19:43:57 +00:00
9a00f30c7b Establish the Scriptorium release procedure 2026-07-28 19:38:11 +00:00
f71d2bbb73 Add an implementation plan and roadmap for Step 9 of the migration plan 2026-07-28 14:25:56 -05:00
13 changed files with 1302 additions and 117 deletions

3
.gitignore vendored
View File

@@ -56,6 +56,8 @@ mono_crash.*
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
!docs/releases/
!docs/releases/*.md
x64/
x86/
[Ww][Ii][Nn]32/
@@ -433,4 +435,3 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml

View File

@@ -11,9 +11,16 @@ steps:
version="$CI_COMMIT_TAG"
dist="dist"
pkg="gitea.maximumdirect.net/eric/scriptorium/cmd/scriptorium"
notes="docs/releases/$version.md"
if [ ! -f "$notes" ]; then
printf 'release notes not found: %s\n' "$notes" >&2
exit 1
fi
rm -rf "$dist"
mkdir -p "$dist"
cp "$notes" "$dist/RELEASE_NOTES.md"
build_binary() {
goos="$1"
@@ -22,7 +29,7 @@ steps:
output="$dist/scriptorium-$version-$goos-$goarch$suffix"
CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" \
go build -trimpath -ldflags "-s -w -X gitea.maximumdirect.net/eric/scriptorium/internal/buildinfo.Version=$version" \
go build -trimpath -ldflags "-s -w" \
-o "$output" "$pkg"
}
@@ -38,6 +45,7 @@ steps:
from_secret: GITEA_RELEASE_TOKEN
files:
- dist/scriptorium-*
note: dist/RELEASE_NOTES.md
checksum: sha256
checksum-file: SHA256SUMS
checksum-flatten: true

View File

@@ -35,6 +35,7 @@ a model. For complete invocation and output behavior, see the
- [HTTP API reference](docs/api.md)
- [Operations guide](docs/operations.md)
- [Consumer integration overview](docs/consumers/api.md)
- [Migration from the former Go package](docs/consumers/migrating-to-promptkit.md)
- [Subprocess integration](docs/integrations/subprocess.md)
- [Architecture policy](docs/policy/architecture.md)
- [Promptkit framework formats](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md)

View File

@@ -16,6 +16,8 @@ Go applications that need an in-process prompt framework should import
Promptkit directly. The tagged
[Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md)
owns that interface; Scriptorium does not provide a Go library package.
Consumers arriving from the former Scriptorium Go API should follow the
[migration guide](migrating-to-promptkit.md).
## Consumer Responsibilities

View File

@@ -0,0 +1,109 @@
# Migrate From Scriptorium To Promptkit
## Supported Migration Boundary
Scriptorium `v0.11.1` at
`gitea.maximumdirect.net/eric/scriptorium` is the final release that provides
the former in-process Go framework. Promptkit `v0.1.0` at
`gitea.maximumdirect.net/eric/promptkit` is the destination for that framework
API. Scriptorium `v0.12.0` and later provide the CLI and HTTP application only.
There is no Scriptorium compatibility facade, alias package, forwarding
package, or deprecated wrapper. A consumer that cannot migrate may remain
pinned to Scriptorium `v0.11.1`, but that framework-bearing line does not
provide the slim application release.
## Update A Go Consumer
Start from a clean consumer checkout and review the pending diff before
committing it. Add the published Promptkit module:
```sh
go get gitea.maximumdirect.net/eric/promptkit@v0.1.0
```
For an ordinary consumer that imports the former root package under its
default name, replace the exact import and package qualifier, then format the
changed Go files:
```sh
git grep -l \
'"gitea.maximumdirect.net/eric/scriptorium"' \
-- '*.go' |
while IFS= read -r go_file
do
perl -pi -e \
's{"gitea.maximumdirect.net/eric/scriptorium"}{"gitea.maximumdirect.net/eric/promptkit"}g; s{\bscriptorium\.}{promptkit.}g' \
"$go_file"
gofmt -w "$go_file"
done
```
Inspect the resulting diff. Consumers that used an import alias should retain
or deliberately rename that alias instead of applying the qualifier
replacement mechanically.
Remove the now-unused Scriptorium requirement through module tidiness and run
the consumer's complete tests:
```sh
go mod tidy
go test ./...
```
Confirm that `go.mod` selects Promptkit `v0.1.0` and that no Go file imports
the former Scriptorium package:
```sh
test "$(
go list -m -f '{{.Path}}@{{.Version}}' \
gitea.maximumdirect.net/eric/promptkit
)" = 'gitea.maximumdirect.net/eric/promptkit@v0.1.0'
if git grep -n \
'gitea.maximumdirect.net/eric/scriptorium' \
-- '*.go'
then
printf '%s\n' 'a former Scriptorium Go import remains' >&2
exit 1
fi
```
## Compatibility And Additions
Promptkit preserves the established engine, request, result, profile,
source-option, model-client, artifact, validation-value, and public-error
shapes where practical. Exact declarations and current behavior belong to the
tagged [Promptkit consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md)
and Go source.
Promptkit also includes migration-relevant public contracts that were not in
Scriptorium `v0.11.1`:
- [`WithArtifactReader`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/engine.go#L96-L105)
and the
[`ArtifactReader` declaration](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/types.go#L129-L135)
provide the artifact-reading extension described by the tagged
[extension-interface guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md#extension-interfaces).
- [`ErrProfileRequired` and `ErrAPIKeyEnvMissing`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/engine.go#L28-L40)
provide the specific identities described by the tagged
[error guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md#errors).
Use those tagged owners for exact signatures, wrapping guarantees, and
extension behavior.
## Verify Consumer Behavior
Source compatibility is only the first check. Exercise the behavior the
consumer actually relies upon, especially:
- prompt, profile, and schema source selection;
- direct and environment-based credentials;
- caller, generation, and transport timeout layering;
- output validation and validation-failure handling;
- injected model-client and artifact-reader extensions; and
- every `errors.Is` branch used for recovery or classification.
Also verify any serialized values, redaction expectations, filesystem policy,
and provider integration behavior that crosses the consumer's own boundary.
Promptkit owns the in-process framework contract; Scriptorium owns only its
executable CLI and HTTP application interfaces.

View File

@@ -31,7 +31,7 @@ tests.
| OpenAI-compatible outbound behavior or timeout layering | [Promptkit integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/integrations/openai-compatible-chat.md) |
| Subprocess behavior | [Subprocess integration](integrations/subprocess.md) and [CLI contract](cli.md) |
| Runtime operation or recovery | [Operations](operations.md) |
| Release packaging | `.woodpecker/release.yml`, [operations](operations.md), and the architecture policy |
| Release packaging or publication | The [release procedure](release.md), [hosted release workflow](../.woodpecker/release.yml), and [architecture policy](policy/architecture.md) |
| Examples or copyable assets | The owning Scriptorium contract, the relevant [Promptkit format contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/formats.md), and the related files under `examples/` |
| Architecture decisions or future work | The [documentation policy](policy/documentation.md), relevant accepted ADRs, and relevant roadmap documents |

View File

@@ -71,6 +71,8 @@ secret values.
| CLI contract | `docs/cli.md` | Commands, arguments, flags, invocation semantics, and exit codes. | End-to-end operating procedures, configuration field definitions, runtime filesystem layout, module implementation details. |
| Configuration contract | `docs/config.md` | Application discovery and precedence, source locations, server fields, render default, HTTP limits, and credential mapping. | Promptkit framework formats and defaults, complete example files, CLI syntax, runtime lifecycle, and implementation detail. |
| Operations | `docs/operations.md` | Runtime workflows, physical filesystem and state layout, output, cache, and debug handling, resume, cleanup, permissions, recovery, and operational limits. | CLI flag syntax, configuration field definitions, logical output schemas, implementation mechanics. |
| Release procedure | `docs/release.md` | Candidate validation, version and tag operations, hosted-workflow observation, and published-artifact verification. | Runtime operations, version-specific announcements, and complete application-interface contracts. |
| Version-specific release notes | `docs/releases/` | Immutable release summaries, compatibility notices, and migration announcements for one published version. | Complete CLI, HTTP, configuration, operations, or dependency contracts. |
| Public HTTP contract | `docs/api.md` | Routes, authentication, media types, request and response schemas, status codes, pagination, caching, idempotency, rate limits, and HTTP retry semantics. | Client walkthroughs, upstream or downstream integration internals, implementation detail. |
| Consumer guidance | `docs/consumers/` | Choosing between Scriptorium's executable interfaces and understanding consumer responsibilities. | HTTP wire semantics, CLI syntax, Promptkit's Go package, and internal implementation detail. |
| External and durable integration contracts | `docs/integrations/` | Scriptorium-owned process and executable integration contracts. | Promptkit framework formats and outbound provider protocols, physical runtime placement, internal transformations, CLI syntax, and configuration defaults. |

373
docs/release.md Normal file
View File

@@ -0,0 +1,373 @@
# Release Procedure
## Release Model And Status
Scriptorium publishes annotated semantic tags and tag-triggered Linux binary
releases. The hosted
[release workflow](../.woodpecker/release.yml) builds `amd64` and `arm64`
executables, publishes their SHA-256 checksums, and uses the matching file
under `docs/releases/` as the hosted release body.
`v0.12.0` is the selected version for the pending first application-only
release. It remains an unreleased candidate until its annotated tag is
published, the hosted workflow succeeds, and every published artifact is
verified. Later releases select a new `vMAJOR.MINOR.PATCH` version according to
the intended compatibility change.
Run this procedure from the Scriptorium repository root. A release must not
depend on a Go workspace, module replacement, vendor tree, sibling checkout,
unpublished dependency, or unpushed source commit.
## Establish The Candidate
For the pending application-only release, start a POSIX shell and select:
```sh
export RELEASE_VERSION=v0.12.0
```
For a later release, export its not-yet-published semantic version instead.
Then run the following guard in that same shell:
```sh
set -eu
: "${RELEASE_VERSION:?export an unpublished vMAJOR.MINOR.PATCH version}"
if ! printf '%s\n' "$RELEASE_VERSION" |
grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$'
then
printf '%s\n' "invalid release version: $RELEASE_VERSION" >&2
exit 1
fi
RELEASE_COMMIT=$(git rev-parse --verify 'HEAD^{commit}')
export RELEASE_COMMIT
check_release_candidate() {
test "$(git branch --show-current)" = main
test -z "$(git status --porcelain)"
gowork_value=$(go env GOWORK)
case "$gowork_value" in
''|off) ;;
*)
printf '%s\n' "active Go workspace: $gowork_value" >&2
return 1
;;
esac
test -z "$(git ls-files go.work go.work.sum)"
test ! -e vendor
if grep -Eq '^[[:space:]]*replace([[:space:]]|\()' go.mod
then
printf '%s\n' 'go.mod contains a replacement' >&2
return 1
fi
git fetch origin main --tags
test "$RELEASE_COMMIT" = \
"$(git rev-parse --verify 'refs/remotes/origin/main^{commit}')"
if git show-ref --verify --quiet "refs/tags/$RELEASE_VERSION"
then
printf '%s\n' "local tag already exists: $RELEASE_VERSION" >&2
return 1
fi
if test -n "$(
git ls-remote --tags origin \
"refs/tags/$RELEASE_VERSION" \
"refs/tags/$RELEASE_VERSION^{}"
)"
then
printf '%s\n' "remote tag already exists: $RELEASE_VERSION" >&2
return 1
fi
}
check_release_candidate
```
Do not continue unless this guard succeeds. It deliberately requires the
candidate to be the exact clean commit already published at `origin/main`.
## Verify Modules And Repository Boundaries
Confirm the module path and declared Go version:
```sh
test "$(
GOWORK=off go list -m -f '{{.Path}} {{.GoVersion}}'
)" = 'gitea.maximumdirect.net/eric/scriptorium 1.25.5'
```
Require Promptkit `v0.1.0` as both the direct module-graph edge and the selected
module version:
```sh
direct_promptkit=$(
GOWORK=off go mod graph |
awk '
$1 == "gitea.maximumdirect.net/eric/scriptorium" &&
$2 ~ /^gitea\.maximumdirect\.net\/eric\/promptkit@/ {
print $2
}
'
)
test "$direct_promptkit" = \
'gitea.maximumdirect.net/eric/promptkit@v0.1.0'
test "$(
GOWORK=off go list -m -f '{{.Path}}@{{.Version}}' \
gitea.maximumdirect.net/eric/promptkit
)" = 'gitea.maximumdirect.net/eric/promptkit@v0.1.0'
GOWORK=off go list -m all
```
Require tidy module metadata and recheck the repository exclusions:
```sh
GOWORK=off go mod tidy -diff
test -z "$(git ls-files go.work go.work.sum)"
test ! -e vendor
if grep -Eq '^[[:space:]]*replace([[:space:]]|\()' go.mod
then
printf '%s\n' 'go.mod contains a replacement' >&2
exit 1
fi
test -z "$(git status --porcelain)"
```
## Validate The Application
Run the complete application validation:
```sh
GOWORK=off go test ./...
GOWORK=off go test -race ./...
GOWORK=off go vet ./...
validation_build_dir=$(mktemp -d)
GOWORK=off go build \
-o "$validation_build_dir/scriptorium" \
./cmd/scriptorium
```
The ordinary test run includes the architecture guard that rejects a root Go
package, former framework package families, and imports of Promptkit internal
packages. Inspect the repository for generated binaries, credentials,
temporary output, sibling paths, and other files that do not belong in the
tracked release source.
Check every tracked Go file. This command must produce no output:
```sh
unformatted=$(
git ls-files '*.go' |
while IFS= read -r go_file
do
gofmt -l "$go_file"
done
)
test -z "$unformatted"
```
Run the maintained render script and smoke-test both maintained configuration
examples without a model call:
```sh
GOWORK=off ./examples/render-markdown-summary.sh
for config_file in examples/config.yml examples/config.full.yml
do
GOWORK=off go run ./cmd/scriptorium render \
--config "$config_file" \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md \
--input glossary=./examples/fixtures/glossary.yml \
--format json >/dev/null
done
```
Exercise usage output and offline rendering with the temporary native
executable:
```sh
usage_output="$validation_build_dir/usage.txt"
if "$validation_build_dir/scriptorium" >"$usage_output" 2>&1
then
printf '%s\n' 'expected an invocation without a command to fail' >&2
exit 1
fi
grep -F 'usage: scriptorium' "$usage_output"
"$validation_build_dir/scriptorium" render \
--config ./examples/config.yml \
--prompt generic.markdown_summary \
--input transcript=./examples/fixtures/transcript.md \
--input glossary=./examples/fixtures/glossary.yml \
--format text >/dev/null
```
Follow every maintained local, Promptkit-tagged, and other external Markdown
link. Confirm that all repository-relative link targets exist. Finish the
application checks with:
```sh
git diff --check
test -z "$(git status --porcelain)"
```
## Require Release Notes And Reproduce Packaging
The immutable release note must exist before tagging:
```sh
release_notes="docs/releases/$RELEASE_VERSION.md"
test -f "$release_notes"
test -s "$release_notes"
```
Validate every local and currently published link in the note. For links
pinned to the candidate Scriptorium tag, confirm that the corresponding
repository-relative path exists even though its tag URL is not live yet.
Reproduce the hosted build flags, targets, and filenames in a temporary
directory:
```sh
release_dist=$(mktemp -d)
release_package='gitea.maximumdirect.net/eric/scriptorium/cmd/scriptorium'
build_release_binary() {
target_os="$1"
target_arch="$2"
output="$release_dist/scriptorium-$RELEASE_VERSION-$target_os-$target_arch"
CGO_ENABLED=0 GOOS="$target_os" GOARCH="$target_arch" GOWORK=off \
go build -trimpath -ldflags '-s -w' \
-o "$output" "$release_package"
}
build_release_binary linux amd64
build_release_binary linux arm64
test -s "$release_dist/scriptorium-$RELEASE_VERSION-linux-amd64"
test -s "$release_dist/scriptorium-$RELEASE_VERSION-linux-arm64"
file "$release_dist/scriptorium-$RELEASE_VERSION-linux-amd64"
file "$release_dist/scriptorium-$RELEASE_VERSION-linux-arm64"
```
Require `file` to identify Linux executables for `x86-64` and `ARM aarch64`,
respectively. Inspect the
[hosted workflow](../.woodpecker/release.yml) and confirm that it uses the
same build flags and names, copies the selected release note to
`dist/RELEASE_NOTES.md`, publishes only `dist/scriptorium-*`, and keeps
checksum generation enabled.
## Create And Publish The Tag
Run the candidate guard again immediately before creating the tag:
```sh
check_release_candidate
test -f "$release_notes"
test -s "$release_notes"
```
Create an annotated tag explicitly bound to the validated commit, using the
version-specific release note as its message:
```sh
git tag --annotate "$RELEASE_VERSION" \
--file "$release_notes" \
"$RELEASE_COMMIT"
```
Inspect the tag and require it to resolve to the validated source:
```sh
test "$(git cat-file -t "refs/tags/$RELEASE_VERSION")" = tag
git show --no-patch --decorate "refs/tags/$RELEASE_VERSION"
test "$(
git rev-parse --verify "refs/tags/$RELEASE_VERSION^{commit}"
)" = "$RELEASE_COMMIT"
```
If inspection finds an error, delete only the unpublished local tag, correct
the candidate, and repeat the complete validation. Never move or recreate a
published tag.
Push only the selected tag ref:
```sh
git push origin \
"refs/tags/$RELEASE_VERSION:refs/tags/$RELEASE_VERSION"
```
## Observe And Verify Publication
Open the hosted workflow run for the selected tag. Require
`build-release-assets` to succeed before `publish-release`, then require the
publication step and hosted release to succeed. A queued, running, failed, or
partially published workflow is not a verified release.
Compare the local and remote annotated-tag objects and their source commits:
```sh
remote_tag=$(
git ls-remote --tags origin "refs/tags/$RELEASE_VERSION" |
awk 'NR == 1 { print $1 }'
)
remote_commit=$(
git ls-remote --tags origin "refs/tags/$RELEASE_VERSION^{}" |
awk 'NR == 1 { print $1 }'
)
test -n "$remote_tag"
test "$remote_tag" = \
"$(git rev-parse --verify "refs/tags/$RELEASE_VERSION")"
test "$remote_commit" = "$RELEASE_COMMIT"
```
Download the hosted binaries and checksum file into a temporary directory:
```sh
release_base="https://gitea.maximumdirect.net/eric/scriptorium/releases/download/$RELEASE_VERSION"
download_dir=$(mktemp -d)
(
cd "$download_dir"
for asset in \
"scriptorium-$RELEASE_VERSION-linux-amd64" \
"scriptorium-$RELEASE_VERSION-linux-arm64" \
SHA256SUMS
do
curl --fail --location --remote-name "$release_base/$asset"
done
test -s "scriptorium-$RELEASE_VERSION-linux-amd64"
test -s "scriptorium-$RELEASE_VERSION-linux-arm64"
test -s SHA256SUMS
sha256sum --check SHA256SUMS
test "$(wc -l < SHA256SUMS | tr -d ' ')" = 2
file "scriptorium-$RELEASE_VERSION-linux-amd64"
file "scriptorium-$RELEASE_VERSION-linux-arm64"
)
```
Require the same Linux architectures observed in the local packaging check and
confirm that the hosted release contains no unexpected asset. On a compatible
Linux host, make the matching downloaded binary executable and repeat the
usage-output and offline-render smoke checks against it.
Only after the tag, workflow, release body, binaries, architectures, and
checksums all pass verification is the candidate a verified published release.
## Handle Failures
Before tag publication, correct the release commit or note and restart the
complete procedure. After tag publication, never delete, move, overwrite, or
recreate the tag. A transient hosted failure may be retried only against the
same immutable tag and commit and only when doing so cannot overwrite or
silently retain partial assets. A source, packaging, note, or artifact defect
requires a new corrective semantic version from a new validated commit.
Record the selected version, validated commit, tag object, workflow result,
artifact names, checksum result, and smoke-check outcome in the release
checkpoint. Keep temporary builds and downloaded assets outside the repository,
and require a clean `main` synchronized with `origin/main` when verification
is complete.

36
docs/releases/v0.12.0.md Normal file
View File

@@ -0,0 +1,36 @@
# Scriptorium v0.12.0
## Breaking Project Boundary
Scriptorium is now an executable-only CLI and HTTP application. This is a
breaking change for Go consumers: the former root Go package is not included,
and no compatibility facade is provided.
Scriptorium `v0.11.1` was the final framework-bearing release. Former Go
consumers should follow the
[migration guide](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.12.0/docs/consumers/migrating-to-promptkit.md)
and adopt
[Promptkit `v0.1.0`](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md)
for in-process prompt preparation and execution.
## Application Interfaces
The Scriptorium command-line and HTTP application interfaces remain. Their
canonical documentation defines the supported commands, configuration,
requests, responses, operational behavior, and deployment responsibilities:
- [CLI reference](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.12.0/docs/cli.md)
- [HTTP API reference](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.12.0/docs/api.md)
- [Configuration reference](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.12.0/docs/config.md)
- [Operations guide](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.12.0/docs/operations.md)
## Framework Dependency And Consumers
The released Scriptorium binaries use Promptkit `v0.1.0` as their framework
dependency. Promptkit owns the reusable engine, source formats, profiles,
generation boundary, and validation contracts. See the
[Promptkit Go consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/docs/consumers/pkg-promptkit.md)
for that supported API.
All known downstream Go consumers were migrated to Promptkit before this
release.

View File

@@ -1,64 +1,493 @@
# Step 7 Implementation Completion
# Step 9 Implementation Plan
## Status
Complete as of 2026-07-28.
Ready for implementation.
## Result
This plan implements the target state and policy decisions in
[Step 9](step9.md). Execute the stages in order. A later stage may begin only
after the preceding stage's completion checks pass and any required
cross-repository commit is published.
Scriptorium now consumes
`gitea.maximumdirect.net/eric/promptkit v0.1.0` as an ordinary direct module
dependency. The published tag resolves to Promptkit commit
`9e68a2bbf779545995270c47842048a3bc6c85dc`; no workspace, replacement,
vendored dependency, or sibling-repository state is required.
## Fixed Decisions And Baseline
The Scriptorium module root no longer exposes a Go package. The remaining
production boundary consists of:
- Promptkit `v0.1.0` at commit
`9e68a2bbf779545995270c47842048a3bc6c85dc` is the published framework
baseline. Do not create a new Promptkit tag for documentation-only work.
- Scriptorium `v0.11.1` is the final framework-bearing release.
- Scriptorium `v0.12.0` is the intended first application-only release.
- Scriptorium will not restore a Go facade, compatibility package, alias, or
forwarding API.
- Promptkit retains maintainer-run validation and tag-only source releases. Do
not add hosted Promptkit CI or binary packaging.
- Scriptorium retains hosted, tag-triggered Linux `amd64` and `arm64` binary
releases with SHA-256 checksums.
- Versioned Scriptorium release notes live at
`docs/releases/<tag>.md`. The release workflow copies the file matching
`CI_COMMIT_TAG` into its build workspace and supplies that copy to the
Woodpecker release plugin's documented
[`note` setting](https://woodpecker-ci.org/plugins/release).
- The obsolete linker assignment to the removed
`internal/buildinfo.Version` symbol is deleted. Do not introduce a version
command or replacement build-information package.
- Temporary roadmaps remain present through tag and hosted-release
verification. They are removed only after completion is recorded in Git
history.
- `cmd/scriptorium`;
- `internal/adapter/cli`;
- `internal/adapter/http`;
- `internal/config`;
- `internal/defaults`; and
- `internal/format`.
Repository paths for this work are:
The CLI constructs and invokes Promptkit engines, the HTTP adapter maps its
transport contract to Promptkit public values, and the HTTP-specific restricted
artifact reader is injected through Promptkit's public extension point.
Scriptorium retains application configuration, presentation, transport,
containment, process, packaging, and executable-example responsibilities.
- Scriptorium: `/Users/eric/Code/scriptorium/scriptorium`
- Promptkit: `/Users/eric/Code/scriptorium/promptkit`
- Notarius verification checkout: `/Users/eric/Code/notarius`
The former root facade, duplicated framework packages, built-in profile copy,
framework tests and fixtures, Go-library example, and framework-owned
documentation were removed. Permanent Scriptorium documentation now describes
the CLI and HTTP application and links to the tagged Promptkit documentation
for framework contracts.
Do not commit `go.work`, `go.work.sum`, a `replace` directive, vendored
Promptkit source, generated binaries, downloaded release assets, credentials,
or temporary validation output. Use directories created with `mktemp -d` for
clones, caches, builds, and downloads, and remove or leave those directories
outside the repositories.
## Validation Evidence
## Stage 1: Correct Promptkit Release And Project Documentation
Scriptorium passed, outside a Go workspace and without a replacement:
Work only in the Promptkit repository during this stage.
- module identity, graph, tagged dependency, and `go mod tidy -diff` checks;
- ordinary and race-enabled tests, including retained HTTP decoding, limit,
restricted-file, error-mapping, and raw-output coverage;
- vet, formatting, whitespace, architecture, and tracked-tree hygiene checks;
- temporary native and release-equivalent Linux `amd64` and `arm64` builds;
- the maintained render script and both configuration examples without model
credentials; and
- all maintained local and tagged Promptkit documentation links.
### Changes
A fresh temporary module and build cache resolved Promptkit remotely, reported
the expected `v0.1.0` origin commit, and passed the Scriptorium test suite and
build without reading the sibling Promptkit checkout.
1. Rewrite `docs/release.md` as a current, reusable procedure:
- state that `v0.1.0` is the initial published release rather than a planned
tag;
- retain semantic `vMAJOR.MINOR.PATCH` tags, pre-`v1` compatibility notes,
maintainer-run validation, and source-only publication;
- require the maintainer to provide a not-yet-published
`RELEASE_VERSION`, validate it as a semantic version, and derive the
release commit from `HEAD`;
- retain clean-checkout, no-workspace, no-replacement, module identity,
tests, race tests, vet, build, maintained example, formatting, link,
whitespace, and repository-hygiene checks;
- use the annotated tag message as Promptkit's source-only release notes,
recording the version, validated commit, compatibility summary, public
API changes, and any required consumer action;
- retain annotated-tag creation, exact-ref publication, remote tag-object
comparison, source-commit verification, and ordinary Go module
resolution checks; and
- state the Promptkit-before-consumer release ordering without restating
Scriptorium's release procedure.
2. Use guarded shell examples. A missing or already-existing release version,
a dirty checkout, an active workspace, a replacement, an unpushed release
commit, or an existing local or remote tag must stop the procedure before
tag creation. Publish only the selected tag ref, never all local tags.
3. Add a short “Related project” entry to Promptkit's `README.md` linking to
the Scriptorium repository as the CLI and HTTP application built on
Promptkit. Do not copy Scriptorium invocation or transport contracts into
Promptkit.
4. Audit Promptkit README, consumer, architecture, development, and internal
documents for stale extraction or pre-release language. Change only claims
that are no longer true; exact public API and format contracts remain with
their existing canonical owners.
Promptkit was reconfirmed independently at the exact published tag. Its local
and remote tag targets agree, its working tree remains clean, and its
documented test, race, vet, build, example, formatting, module, link,
whitespace, and repository-hygiene checks pass.
### Validation
## Next Gate
- Follow every changed local and cross-project Markdown link.
- Check all changed shell fragments for valid POSIX shell syntax without
executing tag or push commands.
- Run `git diff --check`.
- Confirm no code, module, example, architecture boundary, or public contract
changed.
[Step 8](migration.md#step-8-migrate-downstream-consumers-to-promptkit) may
now inventory and migrate downstream Go consumers. Step 7 did not migrate
external consumers, publish a breaking Scriptorium release, or complete the
release and documentation cutover assigned to Step 9.
### Completion State
Commit the Promptkit documentation changes with a plain-English message and
push the commit to `origin/main`. Require a clean Promptkit working tree with
`main` synchronized to `origin/main` before Stage 2. Do not create a Promptkit
tag.
## Stage 2: Establish Scriptorium Release Ownership And Mechanics
Work only in the Scriptorium repository during this stage.
### Documentation Ownership
1. Add two canonical-owner rows to `docs/policy/documentation.md`:
- `docs/release.md` owns the Scriptorium release procedure, including
candidate validation, version and tag operations, hosted-workflow
observation, and artifact verification;
- `docs/releases/` owns immutable version-specific release notes and
migration announcements, not complete interface contracts.
2. Update the release-packaging row in `docs/development.md` to route
contributors to `docs/release.md`, `.woodpecker/release.yml`, and the
architecture policy.
3. Create `docs/release.md` with an end-to-end procedure for:
- selecting `v0.12.0` for this release and a semantic version for later
releases;
- requiring a clean, pushed release commit on `main`, outside a Go
workspace and without a module replacement or vendor tree;
- confirming module identity, Go version, direct Promptkit version, module
graph, module tidiness, and tag availability;
- running the complete application and release-equivalent validation
defined in Stage 4;
- requiring `docs/releases/<tag>.md`;
- creating and inspecting an annotated tag bound to the validated commit;
- pushing only that exact tag ref;
- monitoring the hosted workflow;
- comparing local and remote tag objects and commits;
- downloading and verifying release assets and checksums; and
- handling failures without moving or recreating a published tag.
The procedure must distinguish an unreleased candidate from a verified
published release and must not claim that `v0.12.0` exists before its tag
and hosted artifacts are confirmed.
4. Keep operator workflows in `docs/operations.md`; add a release-procedure
link there only if a concrete operator task needs it.
### Release Workflow
Update `.woodpecker/release.yml` as follows:
1. Keep tag-only execution, Go `1.25`, `CGO_ENABLED=0`, `-trimpath`, `-s -w`,
the existing Linux architectures, filenames, release plugin, and checksum
policy.
2. Remove only the stale
`-X gitea.maximumdirect.net/eric/scriptorium/internal/buildinfo.Version=...`
linker assignment.
3. Before building, require a release-notes source at
`docs/releases/$CI_COMMIT_TAG.md`. Fail with a clear diagnostic when it is
absent.
4. Copy that source to a stable path under the workflow's `dist` directory,
such as `dist/RELEASE_NOTES.md`.
5. Set the release plugin's `note` value to the copied file. Keep release-note
content out of the binary asset glob so only the two binaries are
checksummed and uploaded alongside `SHA256SUMS`.
6. Preserve `overwrite: false` and non-prerelease publication. Do not add
automatic tag generation or release mutation.
Do not add a Go test that parses or snapshots the workflow. The material risks
are protected by release-equivalent builds, missing-note failure behavior,
hosted execution, and artifact inspection.
### Validation
- Inspect the YAML and embedded shell for the exact intended paths and
dependency between build and publish steps.
- In a temporary directory, reproduce the build step with
`CI_COMMIT_TAG=v0.12.0` and a temporary output directory. Confirm both
release-equivalent binaries build and the release-note selection fails for
a nonexistent tag.
- Use `file` or an equivalent binary inspector to confirm Linux `amd64` and
Linux `arm64` targets.
- Run `git diff --check` and validate all new local documentation links.
### Completion State
The release contract and workflow are internally consistent, reusable after
`v0.12.0`, and contain no reference to a removed package. Do not tag or publish
Scriptorium in this stage.
## Stage 3: Publish Migration Guidance And Release Notes
Work only in the Scriptorium repository during this stage.
### Go Consumer Migration Guide
Create `docs/consumers/migrating-to-promptkit.md` as the canonical guide for
leaving the former Scriptorium Go package. It must:
1. Identify Scriptorium `v0.11.1` and
`gitea.maximumdirect.net/eric/scriptorium` as the source, Promptkit `v0.1.0`
and `gitea.maximumdirect.net/eric/promptkit` as the destination, and
Scriptorium `v0.12.0` as executable-only.
2. Give copyable commands that:
- add Promptkit `v0.1.0`;
- replace Go imports and package qualifiers;
- remove the old Scriptorium dependency through `go mod tidy`; and
- run the consumer's tests.
3. Explain at a high level that the established engine, requests, results,
profiles, source options, model-client boundary, artifacts, validation
values, and error identities were preserved where practical.
4. Identify the Promptkit additions relevant to migration:
`WithArtifactReader`, `ArtifactReader`, `ErrProfileRequired`, and
`ErrAPIKeyEnvMissing`. Link exact declarations and behavior to Promptkit's
tagged consumer guide and Go source rather than reproducing them.
5. Tell consumers to verify the behavior they actually rely upon, including
configuration sources, credentials, timeout layering, validation,
injected extensions, and `errors.Is` handling.
6. State that no compatibility facade exists. Consumers unable to migrate may
remain pinned to Scriptorium `v0.11.1`, but that line does not provide the
slim application release.
### Scriptorium Navigation
1. Add the migration guide to the documentation list in `README.md`.
2. Add a concise link from `docs/consumers/api.md` for readers arriving from
the former Go API.
3. Audit all Scriptorium Markdown and Go package comments:
- current product statements must describe a CLI and HTTP application;
- framework contracts must link to tagged Promptkit `v0.1.0` owners;
- no permanent document may imply that Scriptorium still exports a Go
package;
- no document may copy Promptkit's exact fields, defaults, or API
declarations merely to explain the split.
4. Keep general cross-project navigation pointed at project entry pages and
contract links pinned to the consumed Promptkit tag.
### Versioned Release Notes
Create `docs/releases/v0.12.0.md`. Write it so the same Markdown works both as
a checked-in document and as the hosted release body. It must:
- identify the executable-only boundary as a breaking change;
- direct former Go consumers to the migration guide and Promptkit `v0.1.0`;
- identify `v0.11.1` as the last framework-bearing Scriptorium release;
- summarize the retained CLI and HTTP application interfaces without
duplicating their contracts;
- state that all known downstream Go consumers were migrated;
- name Promptkit `v0.1.0` as the released binary's framework dependency; and
- link to canonical CLI, HTTP, configuration, operations, migration, and
Promptkit consumer documents.
Use absolute tag URLs for links that must work from the hosted release page.
Scriptorium `v0.12.0` tag URLs will not exist before publication; validate
their corresponding repository-relative targets locally before tagging and
the actual URLs in Stage 5. Promptkit `v0.1.0` links must already resolve.
### Validation
- Run every copyable non-destructive migration command against a temporary Go
module or a temporary copy of the maintained historical consumer shape.
Confirm it selects Promptkit `v0.1.0`, contains no Scriptorium import, and
compiles.
- Validate every local and currently published cross-project link.
- Confirm every prospective Scriptorium `v0.12.0` URL maps to an existing path
in the candidate tree.
- Run `git diff --check`.
- Re-audit for stale project identity, framework ownership, pre-cutover, and
planned-release claims.
### Completion State
Commit the combined Scriptorium release-workflow, release-procedure, migration,
release-note, policy, and navigation changes with one or more plain-English
messages. Push them to `origin/main`. Require a clean Scriptorium working tree
with `main` synchronized to `origin/main` before Stage 4. Do not tag the release
yet.
## Stage 4: Perform The Independent Pre-Release Acceptance Run
This is a validation and release-readiness stage. Do not modify product code,
move tags, or publish a release while running it.
### Promptkit Main And Published Tag
1. Confirm Promptkit's local `main`, `origin/main`, local annotated `v0.1.0`
tag, remote tag object, and resolved tag commit.
2. On Promptkit `main`, run:
- `go test ./...`;
- `go test -race ./...`;
- `go vet ./...`;
- `go build ./...`;
- `go run ./examples/go-library/prepare`;
- `gofmt -l` over tracked Go files;
- local and cross-project Markdown-link checks;
- `git diff --check`;
- module identity, no-workspace, no-replacement, no-vendor, and tracked-tree
hygiene checks.
3. Clone the remote Promptkit `v0.1.0` tag into a temporary directory with
fresh task-specific `GOMODCACHE` and `GOCACHE` directories and `GOWORK=off`.
Run the complete documented Promptkit validation there.
4. From a separate temporary consumer module, resolve
`gitea.maximumdirect.net/eric/promptkit@v0.1.0` through the ordinary remote
module path and confirm its origin metadata and expected source commit
without reading the sibling Promptkit checkout.
### Scriptorium Release Candidate
Clone the pushed Scriptorium release commit from `origin/main` into a temporary
directory. Use fresh task-specific module and build caches and `GOWORK=off`.
Perform all checks from that clone:
1. Confirm:
- module path and Go version;
- direct Promptkit requirement exactly `v0.1.0`;
- module graph selection of Promptkit `v0.1.0`;
- no `replace`, `go.work`, `go.work.sum`, vendor tree, root Go package,
former framework packages, Promptkit internal import, or sibling path;
- `go mod tidy -diff` produces no changes; and
- local and remote `v0.12.0` tags do not exist.
2. Run:
- `go test ./...`;
- `go test -race ./...`;
- `go vet ./...`;
- `gofmt -l` over tracked Go files;
- `git diff --check`;
- architecture and tracked-tree hygiene checks;
- the maintained render script;
- render smoke checks with both configuration examples; and
- every maintained local, Promptkit-tagged, and other existing external
documentation link.
3. Build a temporary native executable and exercise basic help and offline
render behavior.
4. Reproduce the release workflow with `CI_COMMIT_TAG=v0.12.0` into temporary
output:
- select and copy `docs/releases/v0.12.0.md`;
- build stripped, trimmed Linux `amd64` and `arm64` binaries;
- verify exact filenames, nonempty files, target operating systems and
architectures, and absence of the obsolete linker assignment;
- compute SHA-256 checksums in the same basename-only form expected from the
plugin; and
- confirm no extra file matches the upload glob.
5. Confirm repository-relative targets for the not-yet-live Scriptorium
`v0.12.0` release-note links.
### Downstream Confirmation
In the Notarius checkout:
- require a clean `main` synchronized with `origin/main`;
- confirm `go.mod` directly requires Promptkit and no tracked file imports the
former Scriptorium Go package; and
- run `go test ./...`.
If another downstream consumer is discovered, stop and disposition it under
the Step 8 gate before publication.
### Release Checkpoint
Record the exact Scriptorium release commit, Promptkit tag object and commit,
validation commands, and results. Confirm both source repositories remain
clean after validation.
Any failure returns work to the owning earlier stage. Repeat the complete
Stage 4 acceptance run after the fix is committed and pushed. Proceed only
when the validated Scriptorium commit is the exact clean `origin/main` commit
intended for `v0.12.0`.
## Stage 5: Publish And Verify Scriptorium `v0.12.0`
This stage performs external, tag-triggered publication. Do not start it
without confirmed repository access, the hosted release secret and workflow,
and the complete Stage 4 evidence.
### Tag Publication
1. Fetch `origin/main` and all tags without changing files.
2. Reconfirm that `v0.12.0` is absent locally and remotely and that the working
tree is clean at the validated release commit.
3. Create an annotated `v0.12.0` tag. Its message must identify Scriptorium
`v0.12.0`, the exact release commit, and that the documented release
validation passed.
4. Inspect the tag object and resolved commit.
5. Push only `refs/tags/v0.12.0`.
6. Compare the local and remote annotated tag object IDs and resolved commit
IDs.
Never move, delete, or recreate a published release tag. A transient hosted
workflow failure may be retried against the same tag. A source or workflow
defect discovered after tag publication requires a fix on `main` and an
explicit roadmap/version decision before a later patch release; do not silently
retag `v0.12.0` or mark Step 9 complete.
### Hosted Release Verification
1. Monitor the Woodpecker tag pipeline until it reaches a terminal state.
2. Require both the build and publish steps to succeed.
3. Inspect the Gitea release and require:
- a non-prerelease `v0.12.0` release;
- release body content sourced from `docs/releases/v0.12.0.md`;
- exactly the intended Linux `amd64` binary, Linux `arm64` binary, and
`SHA256SUMS` release assets; and
- no source-copy, Promptkit binary, release-note file, or stale artifact
uploaded by the workflow.
4. Download all three assets into a temporary directory.
5. Verify `SHA256SUMS` against both binaries, confirm file types and target
architectures, and inspect that neither file is empty or malformed.
6. Run basic `--help` and offline render smoke behavior on a downloaded binary
when the host or an available isolated Linux runtime supports its
architecture. When execution is unavailable, record that limitation and
rely on the matching pre-release binary smoke plus downloaded-artifact
format and checksum verification.
7. Verify every Scriptorium `v0.12.0` and Promptkit `v0.1.0` URL in the hosted
release notes.
8. Resolve Scriptorium `v0.12.0` and Promptkit `v0.1.0` through fresh remote Go
module queries and confirm their expected tag commits and dependency edge.
### Completion State
Retain the publication evidence needed for the final completion record. Remove
temporary downloads and confirm no release outputs entered either repository.
Do not retire the roadmaps until every hosted verification passes.
## Stage 6: Record Completion And Retire Migration Roadmaps
Work in Scriptorium only after Stage 5 is fully complete.
### Completion Record
1. Update `docs/roadmap/migration.md` to mark Step 9 and the overall Promptkit
migration complete.
2. Update `docs/roadmap/step9.md` and this implementation plan with a concise
completion summary containing:
- Promptkit tag and commit;
- Scriptorium tag and commit;
- hosted release and asset results;
- downstream status;
- independent validation results; and
- any explicitly accepted platform limitation in downloaded-binary
execution.
3. Commit and push that completion record with a plain-English message. This
commit provides the historical completion snapshot before temporary files
are removed.
### Roadmap Retirement
In a subsequent commit:
1. Move any still-useful current contract or procedure into its already
designated permanent owner.
2. Remove all completed Promptkit-migration roadmaps:
- `docs/roadmap/migration.md`;
- `docs/roadmap/step7.md`;
- `docs/roadmap/step9.md`; and
- `docs/roadmap/implementation.md`.
3. Remove the empty `docs/roadmap/` directory if no unrelated active roadmap
remains.
4. Search the full repository for incoming links or prose references to the
removed files and repair them by linking to ADRs, the release procedure,
versioned release notes, migration guide, or another canonical owner.
5. Do not change accepted ADR decision content. Git history, tags, hosted
release notes, permanent migration guidance, and the completion-record
commit retain the durable history.
### Final Validation
Run:
- all local Markdown-link checks;
- all maintained cross-project links;
- `git diff --check`;
- a stale-reference search for removed roadmap paths and pre-cutover claims;
- tracked-tree hygiene checks in both repositories; and
- `git status --short --branch` in Scriptorium, Promptkit, and Notarius.
The cleanup is documentation-only and does not require repeating unrelated Go
tests unless the cleanup changes a command, example, or behavior-bearing file.
Commit and push the retirement with a plain-English message.
## Final Completion State
The implementation is complete when:
- Promptkit main contains accurate reusable release guidance and still
publishes `v0.1.0` as an independently validated source-only Go module;
- Scriptorium main contains a canonical release procedure, permanent migration
guide, versioned `v0.12.0` release notes, and a release workflow matching the
current application;
- Scriptorium `v0.12.0` is published from the independently validated commit
with verified Linux `amd64` and `arm64` binaries and SHA-256 checksums;
- the hosted release body matches the checked-in versioned notes;
- Notarius remains migrated and no other downstream Go consumer remains;
- neither repository or release depends on local multi-repository state;
- both repositories are clean and synchronized with their remotes; and
- the completed temporary migration roadmaps have been removed after their
completion record was committed.
## Open Questions
None. The Step 9 feature roadmap, accepted ADRs, current release topology, and
repository policies determine the required implementation and release choices.

View File

@@ -2,8 +2,8 @@
## Status
Accepted plan. Steps 1 through 7 are complete. Steps 8 and 9 remain proposed
and are not yet implemented.
Accepted plan. Steps 1 through 8 are complete. Step 9 remains proposed and is
not yet implemented.
## Objective
@@ -290,6 +290,12 @@ explicitly recorded as remaining on the previous Scriptorium version with an
owner and follow-up plan. Do not declare the ecosystem migration complete until
the required out-of-band consumer changes are confirmed.
**Gate status:** Complete as of 2026-07-28. The maintainer confirmed that
Notarius was the only downstream consumer of Scriptorium's former Go package.
Its clean, synchronized main branch now directly requires Promptkit `v0.1.0`,
all relevant Go imports use Promptkit rather than Scriptorium, and its full Go
test suite passes. No downstream consumer remains to migrate or disposition.
### Step 9: Complete Release And Documentation Cutover
Complete the coordinated project transition:

View File

@@ -1,64 +0,0 @@
# Migration Step 7: Slim Scriptorium And Adopt Promptkit
## Status
Complete as of 2026-07-28.
## Result
Scriptorium is now an application-only consumer of the published
`gitea.maximumdirect.net/eric/promptkit v0.1.0` module. The command, CLI and
HTTP adapters, restricted artifact reader, and prepared-run formatter use
Promptkit's supported public API. The dependency resolves normally to
Promptkit commit `9e68a2bbf779545995270c47842048a3bc6c85dc` without a workspace,
replacement, vendored copy, or unpublished revision.
The Scriptorium module root no longer provides an importable Go package or
compatibility facade. The reusable framework packages, embedded built-in
profiles, framework contract tests and fixtures, and Go-library example were
removed. Architecture tests prevent production imports of the former root
facade, removed framework package families, and Promptkit internals.
## Retained Application Boundary
Scriptorium owns only its runnable process and application concerns:
- command and CLI parsing, assembly, streams, summaries, and exit behavior;
- HTTP routes, DTOs, strict decoding, limits, public error mapping, and
restricted artifact access;
- application configuration discovery, validation, precedence, and transport
defaults;
- prepared-run text and JSON presentation;
- executable examples, operations guidance, and binary packaging.
Promptkit owns prompt execution, framework sources and formats, validation,
model integration, built-in profiles, and ordinary artifact loading.
Scriptorium's permanent documentation reflects that boundary and links to the
tagged Promptkit contracts rather than duplicating them.
## Acceptance
The completed cutover passed:
- module graph and tidiness checks selecting exactly Promptkit `v0.1.0`;
- ordinary and race-enabled Scriptorium tests, vet, formatting, whitespace,
architecture, and repository-hygiene checks;
- temporary native and release-equivalent cross-builds;
- maintained offline render workflows with both application configurations;
- maintained local and tagged-documentation link checks;
- fresh-cache remote dependency resolution, tests, and build with the expected
Promptkit origin commit; and
- Promptkit's complete documented validation independently at its clean local
and remote `v0.1.0` tag.
These checks cover the retained CLI, HTTP, configuration, containment,
formatting, error-mapping, security, and representative executable behavior.
The working trees contain no generated binaries, temporary workspaces,
replacement directives, credentials, or migration residue.
## Handoff
The Step 7 gate is satisfied. [Step 8](migration.md#step-8-migrate-downstream-consumers-to-promptkit)
owns downstream consumer inventory and migration. Step 9 remains responsible
for the breaking Scriptorium release and final documentation cutover; neither
later gate is complete.

282
docs/roadmap/step9.md Normal file
View File

@@ -0,0 +1,282 @@
# Migration Step 9: Complete Release And Documentation Cutover
## Status
Proposed. Steps 1 through 8 of the
[migration roadmap](migration.md) are complete. This is the final migration
gate.
## Purpose
Finish the Promptkit split as a released, documented, and independently
maintainable project boundary. Step 9 turns the already-implemented repository
state into the supported public release state, gives former Scriptorium Go
consumers a durable migration path, reconciles release guidance in both
repositories, and retires the temporary migration records once their work is
complete.
This roadmap defines the intended end state.
## Release Baseline And Version Decisions
The coordinated release boundary is:
- Promptkit `v0.1.0`, already published from commit
`9e68a2bbf779545995270c47842048a3bc6c85dc`, is the framework version consumed
by Scriptorium;
- Scriptorium `v0.11.1` is the final published framework-bearing Scriptorium
release; and
- Scriptorium `v0.12.0` is the first slim application-only release.
The `v0.12.0` version satisfies
[ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md), which requires
the first slim pre-`v1` Scriptorium release to advance the minor version beyond
the final framework-bearing release.
Promptkit does not need another tag merely to complete this migration.
Promptkit documentation corrections that do not change the library contract
may land on its main branch without changing Scriptorium's dependency. If Step
9 discovers that a Promptkit code or consumer-visible contract change is
required, Promptkit must instead publish an appropriate later semantic version
first, and Scriptorium must adopt and validate that tag before `v0.12.0` is
published.
No release may depend on a Go workspace, local module replacement, vendored
sibling source, unpublished commit, or an unpushed tag.
## Scriptorium Release Readiness
Scriptorium must have a durable, canonical release procedure appropriate to
its hosted tag-triggered binary workflow. The procedure and contributor
reading guide must collectively define:
- semantic-version selection and the clean-checkout preconditions;
- validation outside a Go workspace and without a module replacement;
- module identity, dependency resolution, module tidiness, tests, race tests,
vet, formatting, link, example, and repository-hygiene checks;
- release-equivalent Linux `amd64` and `arm64` builds;
- annotated tag creation and publication;
- observation of the hosted release workflow;
- verification of published binaries and checksums; and
- post-publication smoke checks using downloaded release artifacts where the
execution platform permits.
The documentation policy must assign the release procedure one canonical
owner, and `docs/development.md` must route release work to it. Operations
documentation should link to release material only when an operator task
requires it; it must not become a second release procedure.
The tag workflow must accurately describe the current application. In
particular, remove the obsolete linker assignment to the deleted
`internal/buildinfo.Version` symbol. The release continues to use stripped,
trimmed binaries unless a separate supported application-version interface is
introduced. Adding a new `--version` command or other product behavior is not
part of this migration.
Release validation must exercise the same build commands and artifact names as
the hosted workflow. The resulting `v0.12.0` release must contain the supported
Linux `amd64` and `arm64` Scriptorium binaries and published SHA-256 checksums,
with no framework source or Promptkit binary artifact.
## Promptkit Release Readiness
Promptkit remains governed by
[ADR 0003](../adr/0003-use-maintainer-run-validation-and-tag-only-releases-for-promptkit.md):
maintainer-run validation, semantic Go module tags, and no hosted CI or binary
release artifacts.
Its release procedure must be corrected from pre-release language to current,
reusable guidance. It must no longer describe `v0.1.0` as an uncreated planned
release or instruct a maintainer to create an existing tag. It should:
- acknowledge `v0.1.0` as the initial published release;
- use version-agnostic instructions for later releases;
- retain the clean-checkout, full-validation, tag-ordering, and remote-tag
verification requirements; and
- require pre-`v1` release notes to identify public API changes and consumer
migration requirements.
Before Scriptorium `v0.12.0` is tagged, independently reconfirm that the local
and remote Promptkit `v0.1.0` tags resolve to the expected source commit, that
the tagged module is available through ordinary Go module resolution, and that
Promptkit passes its documented release validation without Scriptorium or
sibling-repository state.
## Go Consumer Migration Guidance
Scriptorium must publish a permanent migration guide under `docs/consumers/`
for consumers of the former Go package. Scriptorium owns this guide because it
describes departure from Scriptorium's removed API; Promptkit's declarations,
GoDoc, format reference, and consumer guide remain canonical for the
destination contract.
The guide must identify the supported migration baseline:
- source: Scriptorium `v0.11.1` and import path
`gitea.maximumdirect.net/eric/scriptorium`;
- destination: Promptkit `v0.1.0` and import path
`gitea.maximumdirect.net/eric/promptkit`; and
- Scriptorium `v0.12.0` and later: executable application only, with no root Go
package or compatibility facade.
It must provide a minimal, copyable migration workflow:
1. replace the Scriptorium module requirement and Go imports with Promptkit
`v0.1.0`;
2. update package qualifiers from `scriptorium` to `promptkit`;
3. run `go mod tidy`;
4. compile and test the consuming project; and
5. verify prompt, profile, schema, credential, timeout, validation, injected
client, and error-handling behavior relevant to that consumer.
The guide should explain that the established engine, request, result, profile,
source-option, model-client, artifact, validation, and error shapes were
intentionally preserved where practical, while Promptkit also owns the
post-extraction public error identities and artifact-reader extension point.
It must direct exact API questions to Promptkit's tagged GoDoc and consumer
guide rather than duplicating the declaration reference.
The guide must also state the deliberate compatibility policy: there are no
Scriptorium aliases, forwarding packages, or deprecated wrappers. A consumer
that cannot migrate may remain pinned to `v0.11.1`, but it will not receive the
application-only Scriptorium line through that package API.
## Documentation And Project Identity Cutover
Review both repositories as separate products and reconcile every maintained
link, example, package comment, and current-state statement with the released
boundary.
Scriptorium documentation must:
- present Scriptorium as a CLI and HTTP application, not a Go framework;
- link in-process Go consumers and framework contract questions to tagged
Promptkit `v0.1.0` documentation;
- link former Scriptorium Go consumers to the migration guide;
- keep CLI, HTTP, application configuration, operations, subprocess, and
executable examples under Scriptorium ownership; and
- avoid reproducing Promptkit fields, defaults, public declarations, or
integration contracts.
Promptkit documentation must:
- present Promptkit as the reusable Go framework and owner of its root API,
file formats, built-in profiles, validation, and outbound integration;
- retain Scriptorium only as a downstream application example or related
project, not as a framework owner or dependency;
- link to Scriptorium only for executable CLI and HTTP workflows when that
navigation is useful; and
- contain no stale extraction, planned-first-release, or pre-cutover claims.
Cross-project links must point to the canonical owner. Scriptorium links that
define the framework version it consumes remain pinned to Promptkit `v0.1.0`;
general project-navigation links may point to the other repository's current
project entry point. Maintained examples must stay repository-local and must
not require a sibling checkout.
## Release Notes And Public Communication
The Scriptorium `v0.12.0` release notes must clearly identify the release as a
breaking project-boundary change. They must:
- state that Scriptorium is now an executable-only CLI and HTTP application;
- state that the former Go framework moved to Promptkit;
- link the Scriptorium migration guide and Promptkit `v0.1.0` consumer
documentation;
- identify `v0.11.1` as the final framework-bearing Scriptorium release;
- summarize the retained Scriptorium interfaces and the removed root package;
- record that all known downstream Go consumers were migrated before release;
and
- identify the Promptkit version used by the released binary.
Release notes must not serve as a duplicate CLI, HTTP, configuration, or
Promptkit API reference. They should route readers to the corresponding
canonical documents.
## Independent Release And Artifact Verification
The final acceptance run must treat the repositories as independent remote
projects:
- validate Promptkit from its exact published tag without Scriptorium;
- validate Scriptorium from its intended release commit outside any workspace
and with a fresh module and build cache that cannot read the sibling
Promptkit checkout;
- confirm the Scriptorium module graph selects the intended published Promptkit
tag;
- verify both working trees contain no tracked workspace, replacement, vendored
cross-project source, generated binary, credential, or temporary release
residue;
- publish and verify the annotated Scriptorium `v0.12.0` tag;
- verify the hosted release completes and publishes the expected binaries and
checksums;
- download the published artifacts into a temporary location, verify their
checksums, file types, target architectures, and basic executable behavior;
and
- recheck maintained local and cross-project documentation links after
publication.
Ordinary ignored developer files, including an ignored local Scriptorium
binary, do not fail repository hygiene. Acceptance concerns tracked content,
release inputs, generated files introduced by the release work, and published
artifacts.
## Roadmap Retirement
Roadmaps are temporary coordination documents. After every Step 9 completion
criterion is satisfied and durable release and migration records exist:
- mark Step 9 and the overall migration complete before cleanup;
- preserve any still-useful current contract in its canonical permanent owner;
- rely on ADRs, Git history, tags, release notes, and the migration guide for
durable decision and release history;
- remove completed migration, step, and implementation roadmaps rather than
retaining them as a second current-state reference; and
- repair every incoming link affected by that removal.
The roadmap files must remain until the out-of-band tag and hosted release have
been verified. Creating a release candidate or merging documentation is not
enough to declare the migration complete.
## Non-Goals
Step 9 does not:
- redesign Promptkit's public API or Scriptorium's CLI or HTTP contracts;
- restore a Scriptorium Go facade or add compatibility shims;
- add hosted CI or binary artifacts to Promptkit;
- add new Scriptorium target platforms beyond the existing Linux `amd64` and
`arm64` release policy;
- introduce an application version command solely to preserve a stale linker
flag;
- redo the completed downstream migration inventory; or
- require a new Promptkit release when no Promptkit contract change is needed.
## Completion Criteria
Step 9 is complete only when all of the following are true:
- Promptkit `v0.1.0` remains independently available, validated, and correctly
documented as the published framework dependency;
- Scriptorium has an accurate, canonical, and tested release procedure;
- the Scriptorium release workflow contains no reference to removed framework
or build-information packages and produces only the intended application
artifacts;
- the permanent Go-consumer migration guide is complete, copyable, and linked
from appropriate Scriptorium entry points;
- both repositories' permanent documentation, examples, package comments, and
cross-project links reflect distinct and canonical ownership;
- Scriptorium `v0.12.0` is published from a clean, independently validated
commit that directly requires a published Promptkit tag;
- the hosted Scriptorium release publishes verified Linux `amd64` and `arm64`
binaries and SHA-256 checksums;
- the `v0.12.0` release notes communicate the breaking package move and link to
the migration path;
- all known downstream Go consumers remain migrated or explicitly
dispositioned;
- neither release depends on local multi-repository state; and
- completed migration roadmaps are removed after their useful content and
completion evidence have durable owners.
When these criteria are satisfied, the Promptkit split is complete and both
projects can evolve, validate, version, document, and release independently.