Files
scriptorium/docs/roadmap/implementation.md

515 lines
23 KiB
Markdown

# Step 9 Implementation Plan
## Status
Complete as of 2026-07-28.
## Completion Summary
Promptkit's annotated `v0.1.0` tag remains published at commit
`9e68a2bbf779545995270c47842048a3bc6c85dc`. Scriptorium's annotated
`v0.12.0` tag object `734632371773bb7620ce9f18e79ae179a2a2b44b`
resolves to independently validated commit
`2f42bdde3957563cb9b7a1e27fdd4ab2516f621a`. The
[hosted release](https://gitea.maximumdirect.net/eric/scriptorium/releases/tag/v0.12.0)
succeeded with release notes matching the checked-in source, exactly the Linux
`amd64` and `arm64` binaries, and verified SHA-256 checksums.
Fresh remote module resolution and independent repository validation passed
without sibling-repository state. The downloaded `amd64` binary completed an
offline render; its existing command interface treated `--help` as an unknown
command and printed usage. The `arm64` binary could not be executed on the
`amd64` host, so its checksum, format, and target architecture were verified.
Notarius at commit `de046a8f13e227676d79c3aa3b685b049902038d`
remains migrated and verified, and no other downstream Go consumer was
identified. All three repositories were clean and synchronized after
validation.
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.
## Fixed Decisions And Baseline
- 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.
Repository paths for this work are:
- Scriptorium: `/Users/eric/Code/scriptorium/scriptorium`
- Promptkit: `/Users/eric/Code/scriptorium/promptkit`
- Notarius verification checkout: `/Users/eric/Code/notarius`
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.
## Stage 1: Correct Promptkit Release And Project Documentation
Work only in the Promptkit repository during this stage.
### Changes
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.
### Validation
- 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.
### 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.