Record the completed Promptkit application cutover

This commit is contained in:
2026-07-28 14:28:26 +00:00
parent 7bb4cf35b9
commit 6f64947e42
3 changed files with 99 additions and 939 deletions

View File

@@ -1,460 +1,19 @@
# Step 7 Implementation Plan
# Step 7 Implementation Completion
## Status
Accepted for implementation.
Complete as of 2026-07-28.
Implement each stage in order. Do not begin a later stage until the current
stage's exit criteria pass. The
[Step 7 feature roadmap](step7.md) is the north star for scope, policy, desired
behavior, and completion. [ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md)
controls the durable project boundary.
## Result
This plan changes Scriptorium only. Promptkit `v0.1.0` is a published,
read-only input to the cutover. Do not edit Promptkit, create a new Promptkit
tag, or use the sibling Promptkit checkout to make an intermediate
Scriptorium state pass.
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.
## Implementation Rules
Apply these rules throughout every stage:
- Read both repositories' development, architecture, documentation, and
testing policies before implementation.
- Preserve unrelated working-tree changes. The removals of completed roadmap
files that predate this plan are user-owned changes and must not be restored.
- Run Scriptorium commands outside a Go workspace. Do not commit `go.work`,
`go.work.sum`, a local `replace`, vendored Promptkit source, or generated
dependency output.
- Depend only on
`gitea.maximumdirect.net/eric/promptkit v0.1.0` and its root `promptkit`
package. Do not import `promptkit/internal/...`.
- Treat the former Scriptorium Go package as intentionally removed. Do not add
aliases, forwarding wrappers, deprecated shims, or an application-local copy
of Promptkit values.
- Preserve CLI, HTTP, configuration, formatting, artifact-containment,
security, error-mapping, and process behavior unless the feature roadmap
explicitly says otherwise.
- Prefer adapting existing application tests to Promptkit values over adding
parallel test suites. Delete tests whose only owner is the removed framework.
- Keep permanent documentation aligned with implemented state. Do not describe
a later stage as complete before its code has landed.
- Use `gofmt` for Go formatting and `go mod tidy` for module metadata. Do not
hand-edit `go.sum`.
If a required capability is absent from Promptkit `v0.1.0`, stop the Step 7
implementation and report the exact public-boundary gap. Do not work around it
with a Scriptorium framework copy or an unpublished Promptkit revision.
## Stage 1: Cut The Application Seam Over To Promptkit
### Objective
Make all retained Scriptorium application code and tests consume the published
Promptkit facade while the old local framework remains temporarily available
for comparison. This stage proves that `v0.1.0` is sufficient before deleting
the old implementation.
### Module Dependency
Add an exact direct requirement:
```text
gitea.maximumdirect.net/eric/promptkit v0.1.0
```
Resolve it from the configured module source with `GOWORK=off`. Do not add a
replacement. Do not prune the old framework-only dependencies yet; the local
framework still compiles during this stage.
Confirm before changing imports that the selected module resolves to
`v0.1.0` and that its origin hash is the accepted Promptkit release commit
`9e68a2bbf779545995270c47842048a3bc6c85dc`.
### Production Import And Type Migration
Replace the former root-package import with
`gitea.maximumdirect.net/eric/promptkit` in every retained application package.
Use the package name `promptkit` in code rather than aliasing it back to
`scriptorium`.
Update `internal/adapter/cli/run.go` so:
- engine construction calls `promptkit.NewEngine` with `promptkit.Config`;
- `run` and `render` requests use `promptkit.RunRequest`;
- input mappings use `promptkit.File` and Promptkit artifact references;
- execution overrides use `promptkit.ExecutionTargetOverride`;
- the `serve` path injects the HTTP reader with
`promptkit.WithArtifactReader`;
- result summaries, validation classification, and exit-code selection use
Promptkit result and status values; and
- no CLI flag, precedence, output, or error wording changes solely because of
the import migration.
Update `internal/adapter/http` so:
- the adapter-owned `Runner` interface accepts `promptkit.RunRequest` and
returns `*promptkit.RunResult`;
- DTO mapping constructs Promptkit artifact references and execution
overrides;
- response mapping reads Promptkit artifact, validation, model, usage, and
metadata values directly;
- HTTP error mapping uses Promptkit's public sentinel errors with `errors.Is`;
and
- the restricted reader implements `promptkit.ArtifactReader` and uses
Promptkit artifact reference, artifact, and reference-type values.
Keep `ErrFileNotAllowed`, `ErrFileOutsideRoot`, and `ErrFileTooLarge` in
Scriptorium. Confirm that Promptkit's artifact-load wrapping preserves those
underlying identities so the existing HTTP mappings continue to work.
Update `internal/format` so every formatter interface, entry point, message
collection, and test fixture uses Promptkit prepared-run and message values
directly.
### Test Migration
Update retained CLI, HTTP, restricted-reader, and formatter tests to import and
construct Promptkit public values. In particular:
- fake runners must use the Promptkit request/result signature;
- handler integration helpers must construct a real `promptkit.Engine`;
- test LLM clients must implement `promptkit.LLMClient`;
- engine options must use Promptkit options;
- error-mapping tables must use Promptkit sentinels; and
- formatting fixtures must use Promptkit public prepared-run types.
Do not change expected CLI output, HTTP payloads, status codes, error codes,
artifact policy, or formatted render output merely to accommodate the new
package name.
### Validation
Run:
```sh
go mod download gitea.maximumdirect.net/eric/promptkit@v0.1.0
go list -m -f '{{.Path}} {{.Version}}' gitea.maximumdirect.net/eric/promptkit
go test ./internal/adapter/... ./internal/format/...
go test ./...
go vet ./...
go build ./cmd/scriptorium
```
Also run the maintained render script and the existing CLI command tests that
exercise built-in profiles, custom profiles, explicit zero-valued overrides,
restricted HTTP artifacts, public error mapping, and prepared-run formatting.
### Exit Criteria
- All retained application production code uses Promptkit public types.
- Application tests use Promptkit at the same boundaries as production.
- The exact direct `v0.1.0` dependency is selected without a replacement.
- The full repository still builds and tests while the local framework copy is
present but unused by retained application code.
- No Promptkit API gap has been discovered.
## Stage 2: Remove The Duplicated Framework
### Objective
Delete every Promptkit-owned implementation, facade, test, fixture, and example
from Scriptorium, then reduce application defaults and module dependencies to
the slim repository boundary.
### Remove The Former Root Package
Delete the complete former root facade:
- `artifact_reader.go`
- `artifact_reader_internal_test.go`
- `convert.go`
- `engine.go`
- `engine_test.go`
- `errors.go`
- `formatting.go`
- `json_copy.go`
- `llm_adapter.go`
- `profiles.go`
- `types.go`
After deletion, the Scriptorium module root must contain no `.go` files and
must not be importable as package `gitea.maximumdirect.net/eric/scriptorium`.
Do not replace these files with a stub package or migration shim.
### Remove Promptkit-Owned Internal Packages
Delete these directories in full, including their package tests, testdata, and
embedded assets:
- `internal/artifact`
- `internal/domain`
- `internal/filecatalog`
- `internal/llm`
- `internal/profile`
- `internal/prompt`
- `internal/promptdef`
- `internal/usecase`
- `internal/validate`
Delete `testdata/framework`. Promptkit owns the framework contract corpus and
already contains its maintained copy.
Delete `examples/go-library`. The Scriptorium Go-library example is obsolete;
Promptkit owns the maintained in-process preparation example.
Do not delete the executable assets under `examples/config*.yml`,
`examples/prompts`, `examples/profiles`, `examples/schemas`,
`examples/fixtures`, `examples/http-run.json`, or
`examples/render-markdown-summary.sh`. Those remain Scriptorium application
examples even though Promptkit owns their file-format semantics.
### Split Defaults By Ownership
Reduce `internal/defaults/defaults.go` to values still owned and used by
Scriptorium:
- `HTTPAddrDefault`
- `SchemaDirDefault`, which remains the application configuration default for
Scriptorium's schema source location;
- `HTTPMaxRequestBytesDefault`
- `HTTPMaxArtifactBytesDefault`
- `HTTPMaxResponseBytesDefault`; and
- `HTTPReadHeaderTimeoutDefault`.
Remove framework-owned output-artifact names, content types,
OpenAI-compatible paths, execution defaults, model-client timeouts, domain
imports, and `ExecutionTargetDefault`.
Do not copy constants from Promptkit merely to make tests convenient. When the
CLI does not supply a framework setting, continue passing the zero value so
Promptkit applies its own default.
### Prune Module Metadata
Run `go mod tidy` only after all Promptkit-owned source and tests are gone.
Keep `gopkg.in/yaml.v3` as a direct dependency because Scriptorium still
decodes application configuration. Allow `go mod tidy` to remove or reclassify
JSON Schema and other modules according to the actual remaining import graph.
The final `go.mod` must have:
- Promptkit `v0.1.0` as a direct dependency;
- no `replace` directive;
- no dependency retained solely for deleted framework code; and
- the existing compatible Go language version.
### Validation
Run:
```sh
go mod tidy
go list ./...
go test ./...
go vet ./...
go build ./cmd/scriptorium
```
Inspect `go list ./...` and the filesystem. The package inventory must consist
only of the command and retained application packages: adapters,
configuration, defaults, and formatting. The module root and removed framework
package families must be absent.
### Exit Criteria
- Scriptorium exposes no root Go package.
- No duplicated framework package, built-in registry, framework testdata, or
Go-library example remains.
- Application defaults contain no Promptkit-owned behavior.
- Module metadata reflects the actual slim application graph.
- All remaining packages test, vet, and build against Promptkit `v0.1.0`.
## Stage 3: Harden The Boundary And Rationalize Tests
### Objective
Make the slim dependency direction durable and leave Scriptorium with a lean
test suite that protects application behavior rather than retesting Promptkit.
### Architecture Guard
Rewrite `internal/adapter/dependency_test.go` as a repository-level
application-boundary guard. It may remain in the `internal/adapter` test
package, but it must locate the module root reliably and recursively inspect
all non-test production `.go` files under the repository.
The scanner must:
- skip `.git`, `vendor`, and other non-source output directories;
- parse imports with the Go parser instead of searching raw source text;
- reject the exact former root import
`gitea.maximumdirect.net/eric/scriptorium`;
- reject the former Scriptorium framework package families removed in Stage 2;
- reject `gitea.maximumdirect.net/eric/promptkit/internal` and every path below
it; and
- continue allowing retained Scriptorium application-internal imports such as
`internal/config`, `internal/defaults`, `internal/format`, and adapter
packages.
Add focused scanner tests using temporary nested source trees to prove exact
root-package detection, nested former-family detection, Promptkit-internal
detection, and allowance of retained application packages.
Add an architecture assertion that:
- the module root has no production `.go` file; and
- each removed framework directory is absent.
This is an intentional architecture invariant, not a generic assertion that
the whole repository tree can never change.
### Test Ownership Audit
Review every remaining test after the mechanical import migration:
- `internal/adapter/cli` owns CLI parsing, configuration/flag mapping, command
output, summaries, exit codes, and representative real-engine command
workflows;
- `internal/adapter/http` owns DTO mapping, strict JSON, status/error mapping,
limits, restricted artifact policy, cancellation, and representative
real-engine handler workflows;
- `internal/config` owns strict application YAML, discovery, precedence,
validation, and application defaults;
- `internal/format` owns deterministic text/JSON presentation; and
- the architecture guard owns dependency direction and removal invariants.
Retain the existing real Promptkit-engine adapter tests because they protect
the consumer integration seam. Keep their prompt and profile fixtures
package-local or generated with `t.TempDir`; do not recreate
`testdata/framework`.
Delete or simplify any assertion that only duplicates Promptkit parser,
orchestration, profile, validation, model-client, or public-contract tests.
Do not add a Scriptorium table for every Promptkit sentinel or field. Preserve
only mappings Scriptorium exposes through CLI or HTTP behavior.
Add a new test only when the cutover exposes an application-owned risk that is
not already covered. Prefer updating an existing adapter integration test over
creating a new end-to-end harness.
### Release Workflow Check
Inspect `.woodpecker/release.yml` and any packaging metadata for assumptions
about the removed root package or framework directories. Keep the release
target at `./cmd/scriptorium` (or its canonical module package path) and ensure
the workflow obtains Promptkit through ordinary module resolution.
Do not add a Promptkit checkout, workspace, replacement, vendor step, or
cross-repository artifact to Scriptorium CI or release packaging.
### Validation
Run:
```sh
go test ./...
go test -race ./...
go vet ./...
go build ./cmd/scriptorium
```
Run the architecture guard directly by name as a focused diagnostic. Confirm
that its negative fixtures fail the scanner for the intended import and that
the real repository produces no violation.
Exercise the release workflow's Go build commands locally with temporary
outputs for its supported target platforms. Do not create `dist/` or another
tracked output directory during validation.
### Exit Criteria
- The repository guard protects the complete new dependency direction.
- Remaining tests have an explicit application-owned purpose.
- No deleted Promptkit behavior is redundantly reimplemented in tests or
fixtures.
- Race-enabled tests, vet, application builds, and release-equivalent builds
pass.
## Stage 4: Reconcile Permanent Documentation And Examples
### Objective
Make all permanent Scriptorium documentation describe the implemented slim
application and route framework readers to the version of Promptkit the
application actually consumes.
### Version-Appropriate Promptkit Links
Use the tagged Promptkit `v0.1.0` documents as the canonical framework
references during this step. Link to the corresponding files under:
```text
https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.1.0/
```
Use these owners where applicable:
- `docs/consumers/pkg-promptkit.md` for Go-library consumer guidance;
- `docs/formats.md` for prompt, profile, schema, execution-setting, built-in
profile, and framework credential contracts; and
- `docs/integrations/openai-compatible-chat.md` for outbound provider wire and
timeout behavior.
Do not copy their field tables, defaults, error inventories, or timeout rules
into Scriptorium. Scriptorium documents only its own mapping or invocation
surface and links to the Promptkit owner for the framework definition.
### Orientation And Policy
Update:
- `README.md` to present only the runnable CLI and HTTP application, remove the
Scriptorium Go-package link and Go-library example, and identify Promptkit as
the imported framework;
- `docs/policy/architecture.md` to define the current application-only shape,
retained package boundaries, Promptkit dependency direction, HTTP artifact
security boundary, application invariants, and non-goals;
- `docs/development.md` to route contributors to the remaining adapter,
configuration, formatting, packaging, and Promptkit-consumer boundaries;
- `docs/policy/documentation.md` where its ownership table or boundary rules
still imply that Scriptorium owns a public Go package or framework
integration; and
- `docs/policy/testing.md` where framework-domain, validator, model-client, or
orchestration examples imply those are still Scriptorium test owners.
Do not rewrite accepted ADR decision content. ADR 0002 remains the permanent
decision record even where its context describes the pre-split state.
### External And User Contracts
Audit and update:
- `docs/cli.md`
- `docs/api.md`
- `docs/config.md`
- `docs/operations.md`
- `docs/consumers/api.md`
- `docs/integrations/subprocess.md`
Preserve Scriptorium-owned command syntax, configuration discovery and server
fields, HTTP schemas and mappings, operations, and subprocess behavior. Remove
claims that Scriptorium provides an in-process Go API. Where these documents
name prompt/profile fields, model semantics, built-in profiles, framework
credentials, or timeout behavior, keep only the Scriptorium mapping context
and link to the tagged Promptkit owner.
Delete `docs/consumers/pkg-scriptorium.md`. Update every incoming link so Go
framework consumers are directed to Promptkit rather than to a compatibility
document.
Delete `docs/integrations/openai-compatible-chat.md` after replacing all
incoming Scriptorium links with the tagged Promptkit integration contract.
Scriptorium no longer owns the outbound provider protocol.
### Internal Documentation
Update `docs/internal/overview.md` to inventory exactly:
The Scriptorium module root no longer exposes a Go package. The remaining
production boundary consists of:
- `cmd/scriptorium`;
- `internal/adapter/cli`;
@@ -463,175 +22,43 @@ Update `docs/internal/overview.md` to inventory exactly:
- `internal/defaults`; and
- `internal/format`.
Update `docs/internal/adapters.md` for Promptkit request/result mapping, engine
construction, consumer-owned interfaces, error mapping, output behavior, and
restricted-reader injection.
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.
Rewrite `docs/internal/sources.md` around Scriptorium-owned application source
locations and the restricted HTTP artifact reader. Link Promptkit for ordinary
artifact loading and framework source semantics.
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.
Delete:
## Validation Evidence
- `docs/internal/runner.md`
- `docs/internal/llm.md`
Scriptorium passed, outside a Go workspace and without a replacement:
Promptkit owns those subsystem documents. Remove all incoming links rather than
leaving placeholder internal documents.
- 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.
### Examples And Navigation
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.
Keep the executable configuration, prompt, profile, schema, fixture, HTTP, and
render-script examples. Confirm they still run against the tagged dependency
and that prose describes them as Scriptorium application examples.
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.
Remove every link to `examples/go-library`, root Go declarations, removed
framework directories, deleted Scriptorium consumer documentation, and deleted
internal or integration documents.
## Next Gate
Search all permanent Markdown outside `docs/roadmap/` for:
- the former root import path used as a Go package;
- claims that Scriptorium owns or implements the framework;
- references to removed packages, tests, fixtures, or examples; and
- duplicate Promptkit framework contracts.
The migration roadmap and accepted ADRs may retain historical and future
language appropriate to their lifecycle.
### Validation
Validate every local Markdown link and follow every new external Promptkit
link. Run:
```sh
git diff --check
go test ./...
go vet ./...
go build ./cmd/scriptorium
```
Run the maintained render script and both `examples/config.yml` and
`examples/config.full.yml` through a credential-free `render` workflow. No
documentation validation may invoke a paid or live model endpoint.
### Exit Criteria
- Permanent docs describe only the implemented application boundary.
- Framework contracts have one Promptkit owner and version-appropriate links.
- Removed code and examples have no live incoming links.
- All retained examples are valid, secret-free, and runnable offline where
intended.
- Documentation links, whitespace, tests, vet, and the executable build pass.
## Stage 5: Perform Independent Acceptance And Record Completion
### Objective
Validate the exact final state without sibling-repository coupling, then record
the Step 7 gate only after every feature-roadmap completion criterion is
satisfied.
### Scriptorium Acceptance
From the Scriptorium repository root, confirm no Go workspace is active and no
replacement or vendored dependency exists. Validate module identity and
selection:
```sh
go list -m -f '{{.Path}} {{.GoVersion}}'
go list -m -f '{{.Path}} {{.Version}}' gitea.maximumdirect.net/eric/promptkit
go mod graph
go mod tidy -diff
```
Require the Scriptorium module path and existing Go version, and require
Promptkit to resolve exactly to `v0.1.0`. Inspect the graph for a normal tagged
module edge rather than a local path.
Run:
```sh
go test ./...
go test -race ./...
go vet ./...
go build ./cmd/scriptorium
gofmt -l $(git ls-files '*.go')
git diff --check
```
The formatting command must produce no paths. Build the executable to a
temporary directory rather than the repository. Reproduce the release
workflow's supported cross-compilation targets and linker flags with temporary
outputs.
Run the maintained render script and credential-free render commands using
both configuration examples. Verify representative HTTP behavior through the
retained handler tests, including strict decoding, request/response size
limits, restricted file access, public error mapping, and optional raw output.
Validate all maintained Markdown links, including the tagged Promptkit links.
Search the final tracked tree for former root-facade imports, removed framework
packages, built-in asset copies, framework fixtures, Go-library examples,
workspaces, replacements, generated binaries, credentials, and stale
documentation references.
### Clean Remote-Dependency Verification
Use a fresh temporary module cache with `GOWORK=off` and ordinary remote module
resolution to download dependencies and run at least the Scriptorium build and
test suite. The verification must not read the sibling Promptkit working tree.
Confirm the downloaded Promptkit module reports version `v0.1.0` and origin
commit `9e68a2bbf779545995270c47842048a3bc6c85dc`.
Do not clear or destructively rewrite the maintainer's normal module cache.
Use a temporary directory and remove it after validation.
### Independent Promptkit Reconfirmation
Without changing Promptkit, validate the exact `v0.1.0` source from a temporary
detached worktree or the downloaded module directory. If the clean Promptkit
checkout still has `HEAD` exactly at the peeled `v0.1.0` commit, it may be used
directly. Run Promptkit's documented sequence from that exact source:
```sh
go test ./...
go test -race ./...
go vet ./...
go build ./...
go run ./examples/go-library/prepare
```
Also check Promptkit formatting, links, whitespace, module tidiness, absence of
a workspace/replacement, clean status, and the local and remote `v0.1.0` tag
target. Remove any temporary detached worktree after validation. This proves
that Scriptorium's adoption did not introduce cross-repository state or require
an unpublished Promptkit change.
### Completion Records
Only after all acceptance checks pass:
- update `docs/roadmap/step7.md` status from Proposed to Complete and replace
future-oriented starting-state material as needed with a concise result,
retained application boundary, validation evidence, and Step 8 handoff;
- update `docs/roadmap/migration.md` so its status says Steps 1 through 7 are
complete and its Step 7 gate records the tagged dependency, removal of the
framework copy and public facade, independent validation, and readiness for
downstream migration; and
- replace this staged checklist with a concise Step 7 implementation
completion record containing the dependency version, resulting package
boundary, removed ownership, validation evidence, and next gate.
Do not mark Step 8 or Step 9 complete. Do not publish a Scriptorium release or
claim that external consumers have migrated.
### Exit Criteria
- Every completion criterion in `docs/roadmap/step7.md` is demonstrably true.
- Scriptorium passes release-grade validation against remotely resolved
Promptkit `v0.1.0`.
- Promptkit remains independently clean and valid at its published tag.
- Permanent documentation, examples, module metadata, and architecture checks
match the final slim application.
- Completion records accurately authorize Step 8 without claiming later work.
[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.

View File

@@ -2,8 +2,8 @@
## Status
Accepted plan. Steps 1 through 6 are complete. Steps 7 through 9 remain
proposed and are not yet implemented.
Accepted plan. Steps 1 through 7 are complete. Steps 8 and 9 remain proposed
and are not yet implemented.
## Objective
@@ -259,6 +259,14 @@ Retain only Scriptorium-owned executable and transport behavior. In particular:
dependency, contains no duplicate framework implementation, and its current
documentation describes only the slimmed application.
**Gate status:** Complete as of 2026-07-28. Scriptorium directly resolves
Promptkit `v0.1.0`, no longer contains the framework copy or public Go facade,
and retains only its application, adapter, configuration, presentation,
transport, packaging, and executable-example responsibilities. Release-grade
Scriptorium validation passed with a fresh remote dependency cache, and the
published Promptkit tag passed its documented validation independently. The
application is ready for the downstream-consumer migrations in Step 8.
### Step 8: Migrate Downstream Consumers To Promptkit
Inventory downstream Go consumers and migrate each from the Scriptorium package

View File

@@ -2,338 +2,63 @@
## Status
Proposed.
Complete as of 2026-07-28.
## Purpose
## Result
Complete Scriptorium's application-side cutover to the independently published
Promptkit library. After this work, Scriptorium is a runnable CLI and HTTP
application built on Promptkit's supported public API rather than a second
owner of the prompt-execution framework.
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.
This roadmap defines the required end state for Step 7. The
[main migration roadmap](migration.md) owns the overall migration sequence,
while
[ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md) owns the durable
project, package, configuration, compatibility, and documentation boundaries.
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.
## Starting Point
## Retained Application Boundary
Promptkit is independently published as module
`gitea.maximumdirect.net/eric/promptkit` at annotated tag `v0.1.0`. That release
contains the characterized framework, root public facade, built-in profile
registry, maintained framework tests, and consumer documentation extracted in
Step 6.
Scriptorium owns only its runnable process and application concerns:
Scriptorium intentionally still contains the pre-cutover copy of that
framework. Its executable adapters already consume framework behavior through
the local root facade, which provides a narrow migration seam. Step 7 replaces
that local facade with Promptkit and removes the duplicated implementation; it
does not redesign the framework or the executable interfaces.
- 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.
## Desired End State
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.
Scriptorium is an application-only Go module with this dependency direction:
## Acceptance
```text
scriptorium command
|
v
CLI and HTTP adapters, application config, and output formatting
|
v
gitea.maximumdirect.net/eric/promptkit public package
|
v
Promptkit-owned framework implementation
```
The completed cutover passed:
The Scriptorium module root no longer provides an importable Go package.
Scriptorium has no compatibility facade, type aliases, forwarding functions,
or deprecated wrappers for the former `scriptorium` public API. Go consumers
must import Promptkit; consumers that have not migrated may remain pinned to a
previous framework-bearing Scriptorium version as established by ADR 0002.
- 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.
## Promptkit Dependency
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.
Scriptorium must declare
`gitea.maximumdirect.net/eric/promptkit v0.1.0` as a direct module dependency.
Production code, tests, examples, builds, and release configuration must
resolve that published tag without a committed workspace, local filesystem
replacement, vendored Promptkit copy, or unpublished revision.
## Handoff
The cutover must use only Promptkit's supported root package. Scriptorium must
not import, copy, or depend conceptually on Promptkit implementation packages.
No Promptkit API expansion is expected for this step: Step 4 established the
required application seam, and Step 6 published it. If implementation discovers
a genuine missing Promptkit capability, that is a cross-repository blocker:
the capability must be accepted, implemented, validated, and tagged in
Promptkit before Scriptorium can depend on it.
Dependencies used only by the removed framework must leave Scriptorium's
`go.mod` and `go.sum`. Scriptorium retains only dependencies required by its
application-owned code. The module's Go version remains compatible with the
selected Promptkit release.
## Application Assembly And Adapter Boundary
The CLI must construct `promptkit.Engine` values from Scriptorium's resolved
application settings. It must translate Scriptorium CLI inputs and execution
overrides into `promptkit.RunRequest`, `promptkit.ArtifactRef`, and
`promptkit.ExecutionTargetOverride` values without introducing a parallel
application model.
The `run` command must invoke `promptkit.Engine.Run`; the `render` command must
invoke `promptkit.Engine.Prepare`. The `serve` command must inject
Scriptorium's restricted artifact reader through
`promptkit.WithArtifactReader` and pass the engine to the HTTP adapter through
the adapter-owned consumer interface.
The HTTP adapter's `Runner` interface remains owned by Scriptorium because it
is a consumer-side test and substitution boundary. Its method uses Promptkit
request and result types. Request DTOs, response DTOs, strict JSON decoding,
HTTP limits, error-to-status mapping, response encoding, and route behavior
remain Scriptorium concerns and must not move into Promptkit.
Prepared-run formatting remains in Scriptorium because text and JSON output
selection is an executable presentation concern. The formatter operates
directly on Promptkit public prepared-run values; it must not introduce copied
framework types.
## Artifact And Security Boundary
Scriptorium retains its HTTP-specific restricted artifact reader. The reader
must implement `promptkit.ArtifactReader` and consume and return Promptkit
artifact values directly.
The cutover must preserve the current HTTP artifact policy:
- an empty artifact root permits inline artifacts and denies file references;
- configured byte limits apply to file artifacts, with zero meaning unlimited;
- file paths are checked using the documented lexical root-containment rule;
- symlinks retain their currently documented behavior;
- content type, size, hash, name, URI, and cancellation behavior remain
observable through the same HTTP contract; and
- Scriptorium reader errors remain identifiable so the HTTP adapter can
preserve its existing status and error-code mappings.
Ordinary in-process and CLI file reading belongs to Promptkit. Scriptorium must
not retain its former general-purpose artifact reader or framework artifact
package after the cutover.
## Configuration And Defaults
Scriptorium continues to own:
- configuration discovery and strict YAML decoding;
- configuration-file and CLI precedence;
- `prompt_dir`, `profile_dir`, and `schema_dir` as application source
locations;
- `server.*` settings and transport byte limits;
- the default prepared-run output format; and
- CLI, HTTP server, and process defaults.
These settings are translated into Promptkit construction options and request
values at the application boundary. When omission means “use Promptkit's
framework default,” Scriptorium must leave the value unset rather than
redeclare a Promptkit constant.
Promptkit owns prompt, profile, and output-contract file semantics; built-in
profiles; execution-setting resolution; validation behavior; output-artifact
and framework content-type defaults; OpenAI-compatible request behavior; and
generation and transport timeout semantics. Scriptorium's defaults package
must be reduced to application and transport defaults still used by the CLI,
HTTP server, configuration loader, or output formatter.
The cutover must not change documented configuration discovery, CLI
precedence, source-path interpretation, server limits, or render-format
behavior.
## Package And Asset Disposition
The following Scriptorium components remain:
| Component | Retained responsibility |
| --- | --- |
| `cmd/scriptorium` | Runnable process entrypoint. |
| `internal/adapter/cli` | CLI parsing, application assembly, streams, files, summaries, and exit codes. |
| `internal/adapter/http` | Routes, DTOs, strict decoding, HTTP limits and mappings, and restricted artifact reading. |
| `internal/config` | Application configuration discovery, decoding, validation, defaults, and CLI precedence. |
| `internal/format` | Prepared-run text and JSON presentation using Promptkit public values. |
| `internal/defaults` | Scriptorium-only CLI, HTTP, server, and application defaults. |
| `.woodpecker`, release metadata, and executable packaging | Scriptorium build and binary-release behavior. |
The following duplicated framework components must be removed from
Scriptorium:
- all root-package facade source and tests;
- `internal/artifact`, `internal/domain`, `internal/filecatalog`,
`internal/llm`, `internal/profile`, `internal/prompt`,
`internal/promptdef`, `internal/usecase`, and `internal/validate`;
- embedded built-in profile assets and framework-package test fixtures;
- the root framework contract tests and `testdata/framework`; and
- `examples/go-library`, which is owned and maintained by Promptkit.
Tests remain with the behavior they protect. Scriptorium retains and adapts
application configuration, adapter, formatting, HTTP containment, command, and
representative executable-workflow coverage. It must not retain duplicate
Promptkit unit or contract tests merely to exercise dependency internals.
The executable examples under `examples/` remain when they support
Scriptorium's CLI or HTTP workflows. This includes application configuration,
render scripts, HTTP requests, prompt/profile/schema inputs, and synthetic
fixtures needed by those workflows. Their format semantics are owned by
Promptkit documentation even though the files remain runnable Scriptorium
assets.
## Observable Behavior To Preserve
Step 7 is an ownership and dependency cutover, not an intentional CLI or HTTP
contract change. Subject to the deliberate removal of the public Scriptorium
Go package, preserve:
- the `run`, `render`, and `serve` command names, flags, precedence, output
destinations, summaries, exit classifications, and process behavior;
- application configuration schema, discovery, validation, and defaults;
- HTTP route, method, request and response shapes, strict decoding, media
types, size enforcement, status codes, and stable error codes;
- prompt, profile, execution-setting, request-override, and validation
behavior as supplied by Promptkit `v0.1.0`;
- built-in profile availability and custom-profile overlay behavior;
- presence-aware zero-valued execution overrides;
- the rule that explicit timeout zero disables only the generation deadline,
while caller cancellation and the transport cap remain active;
- public error identity as consumed by Scriptorium's CLI and HTTP mappings;
- structured-output requests, output validation, and validation-failure
classification;
- strict external YAML and JSON decoding;
- secret resolution and redaction; and
- deterministic prepared-run formatting and output metadata.
Any observable application change discovered during implementation must be
treated as a regression unless this roadmap, an accepted ADR, or a separately
approved feature decision authorizes it.
## Architecture Enforcement
Repository checks must make the new dependency direction durable. They must
detect production imports of:
- the removed Scriptorium root facade;
- former Scriptorium framework package families; and
- Promptkit `internal` packages.
The checks must cover the command, adapters, configuration, formatting, and
other remaining production packages recursively without treating test-only
fixtures as the application architecture. Go's own `internal` enforcement is
useful but does not replace a repository-level check that explains the intended
boundary.
The final tree must contain no duplicate framework directories, embedded
built-in registry, copied Promptkit source, or dormant compatibility package.
## Documentation End State
Permanent Scriptorium documentation must describe the implemented slim
application only:
- `README.md` presents the runnable CLI and HTTP application and contains no
in-process Go-library positioning;
- `docs/policy/architecture.md` defines Scriptorium as a Promptkit consumer and
removes the single-repository framework architecture;
- `docs/development.md` routes contributors through the retained application
packages and the Promptkit contracts relevant to cross-project work;
- `docs/internal/overview.md` inventories only the remaining Scriptorium
packages;
- CLI, HTTP, configuration, operations, adapter, source, and subprocess
documents retain their application-owned contracts and mechanics;
- the former Scriptorium Go-package consumer guide is retired, and incoming
navigation directs Go framework consumers to Promptkit;
- framework format and OpenAI-compatible behavior are linked to their
canonical Promptkit owners rather than redefined in Scriptorium;
- former runner, model-client, source, and other internal framework
documentation is removed or reduced to the application-owned boundary where
such a boundary still exists;
- maintained examples and all documentation links refer only to files and
commands that remain; and
- future release and downstream-consumer work remains in the migration roadmap
until Steps 8 and 9 are completed.
Promptkit's existing references to Scriptorium as a downstream application
become accurate when this cutover lands. Step 7 does not otherwise change
Promptkit's public API, implementation, version, or release documentation.
## Validation Expectations
Validation must demonstrate the resulting boundary and behavior, not the
deleted implementation structure.
Scriptorium must pass:
- all ordinary and race-enabled Go tests;
- `go vet` for all remaining packages;
- an executable build to a temporary output path;
- formatting, module-tidiness, whitespace, documentation-link, and repository
hygiene checks;
- maintained executable examples other than the retired Go-library example;
- both maintained application configuration examples;
- representative HTTP handler and restricted-artifact workflows; and
- architecture checks proving the absence of the former framework dependency
direction.
Validation must run with no active Go workspace and no module replacement.
Module inspection must show the tagged Promptkit dependency selected directly.
Promptkit must continue to pass its own documented validation independently;
Scriptorium validation must not rely on the sibling Promptkit checkout.
Scriptorium's hosted validation and executable release workflow must remain
capable of resolving the public Promptkit tag and building the command without
cross-repository filesystem state.
## Non-Goals
Step 7 does not:
- redesign or broaden Promptkit's public API;
- preserve source compatibility for the former Scriptorium Go package;
- migrate downstream repositories other than Scriptorium;
- publish the breaking Scriptorium release or general downstream migration
guide assigned to Steps 8 and 9;
- change CLI, HTTP, configuration, prompt, profile, schema, validation, model,
or timeout contracts;
- move Scriptorium transport, deployment, or presentation policy into
Promptkit;
- add hosted CI or binary releases to Promptkit; or
- retain duplicated code or documentation as a fallback.
## Completion Criteria
Step 7 is complete only when all of the following are true:
- Scriptorium declares and resolves
`gitea.maximumdirect.net/eric/promptkit v0.1.0` as a direct dependency with no
workspace, replacement, vendored copy, or unpublished revision.
- The command, CLI adapter, HTTP adapter, restricted artifact reader, and
prepared-run formatter use Promptkit public values and interfaces.
- The Scriptorium module root exposes no Go package or compatibility facade.
- Every Promptkit-owned framework package, built-in asset copy, framework test,
fixture corpus, and Go-library example has been removed from Scriptorium.
- Only application-owned configuration, adapter, formatting, transport,
process, packaging, and executable-example responsibilities remain.
- CLI, HTTP, configuration, containment, formatting, error-mapping, security,
and representative end-to-end behavior remain protected by passing
Scriptorium-owned tests.
- Architecture checks prevent imports of the former local framework and
Promptkit internals.
- Scriptorium's current documentation describes the slim application and links
to Promptkit for framework contracts without duplicating them.
- Both repositories validate independently, and Scriptorium's full test, race,
vet, build, example, link, module, and hygiene checks pass against the
published Promptkit tag.
- The working tree contains no generated binaries, temporary workspaces,
replacement directives, credentials, or migration residue.
**Gate:** Scriptorium is a clean, independently buildable CLI and HTTP consumer
of the published Promptkit module, contains no reusable framework
implementation or public Go facade, preserves its application contracts, and
is ready for the out-of-band downstream-consumer migrations in Step 8.
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.