Add an implementation plan and roadmap for Step 6 of the migration plan
This commit is contained in:
987
docs/roadmap/implementation.md
Normal file
987
docs/roadmap/implementation.md
Normal file
@@ -0,0 +1,987 @@
|
||||
# Step 6 Implementation Plan
|
||||
|
||||
## Status
|
||||
|
||||
Proposed.
|
||||
|
||||
This plan implements
|
||||
[Migration Step 6: Extract And Stabilize Promptkit](step6.md). The feature
|
||||
roadmap is the canonical source for the target state and migration policy; this
|
||||
document owns implementation order, exact work boundaries, validation gates,
|
||||
and release coordination.
|
||||
|
||||
## Repository Roles
|
||||
|
||||
Step 6 changes two sibling repositories:
|
||||
|
||||
- **Scriptorium** is the source of the characterized framework and the
|
||||
controlling repository for ADRs and migration status.
|
||||
- **Promptkit** receives the reusable framework, tests, assets, public
|
||||
contracts, examples, and first release tag.
|
||||
|
||||
Paths in this plan are relative to the named repository. Run commands from the
|
||||
repository root named by each stage.
|
||||
|
||||
Stages 1 through 7 change Promptkit only. They do not delete or refactor
|
||||
Scriptorium framework code. Stage 8 publishes Promptkit and then updates only
|
||||
Scriptorium's roadmap documents to record completion. Scriptorium does not
|
||||
import Promptkit until Step 7.
|
||||
|
||||
## Preconditions And Execution Rules
|
||||
|
||||
Before Stage 1:
|
||||
|
||||
1. Read `docs/development.md` and all files under `docs/policy/` in both
|
||||
repositories.
|
||||
2. Confirm the Scriptorium Step 6 feature roadmap and this plan are the only
|
||||
intended planning changes.
|
||||
3. Confirm Promptkit starts clean on its intended default branch.
|
||||
4. Confirm there is no active Go workspace affecting either repository:
|
||||
|
||||
```sh
|
||||
gowork=$(go env GOWORK)
|
||||
test -z "$gowork" || test "$gowork" = off
|
||||
```
|
||||
|
||||
5. Record the starting Scriptorium and Promptkit commit IDs in implementation
|
||||
notes. The Scriptorium commit is the extraction source snapshot and must be
|
||||
included in the eventual Step 6 completion record.
|
||||
6. Run the current baselines before copying code.
|
||||
|
||||
From Scriptorium:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./cmd/scriptorium
|
||||
```
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
```
|
||||
|
||||
Stop and correct or explicitly disposition any baseline failure before
|
||||
extraction. Do not interpret a pre-existing failure as an extraction defect.
|
||||
|
||||
Apply these rules throughout:
|
||||
|
||||
- Copy the characterized framework into Promptkit; do not remove its
|
||||
Scriptorium source during Step 6.
|
||||
- Rewrite imports to `gitea.maximumdirect.net/eric/promptkit`; Promptkit code
|
||||
and tests must never import Scriptorium.
|
||||
- Preserve observable behavior unless the package/module rename requires a
|
||||
Promptkit identity change or the feature roadmap explicitly requires a
|
||||
boundary correction.
|
||||
- Do not combine extraction with dependency upgrades, public API redesign,
|
||||
renaming for taste, or unrelated cleanup.
|
||||
- Move tests and repository-local fixtures with the behavior they protect.
|
||||
- Keep each stage independently buildable and testable.
|
||||
- Update Promptkit's README, architecture policy, and internal overview in the
|
||||
same stage whenever their current-state statements become inaccurate.
|
||||
- Keep exact public API contracts in Go declarations and GoDoc. Consumer and
|
||||
internal documents summarize tasks and link to canonical owners rather than
|
||||
duplicating declarations.
|
||||
- Do not create a Promptkit command, inbound HTTP adapter, application
|
||||
configuration package, compatibility facade, hosted CI configuration,
|
||||
`go.work`, `go.work.sum`, or committed local `replace`.
|
||||
- Do not create, move, or publish a version tag before Stage 8.
|
||||
- Do not push either repository until the publication stage unless the user
|
||||
separately directs otherwise.
|
||||
- Review Promptkit and Scriptorium diffs independently. Never create a
|
||||
cross-repository commit.
|
||||
|
||||
If Scriptorium framework code changes after the recorded source snapshot and
|
||||
before publication, inspect the intervening diff. Port any relevant correctness
|
||||
or security change to Promptkit and rerun all affected stage gates. Do not
|
||||
silently extract from two different source states.
|
||||
|
||||
## Stage 1: Extract Domain Types, Framework Defaults, And File Catalog
|
||||
|
||||
### Objective
|
||||
|
||||
Create the internal foundation on which the remaining Promptkit framework
|
||||
packages depend without introducing a public API prematurely.
|
||||
|
||||
### Promptkit Implementation
|
||||
|
||||
Create these package groups from the recorded Scriptorium source snapshot:
|
||||
|
||||
- `internal/domain`
|
||||
- `internal/defaults`
|
||||
- `internal/filecatalog`
|
||||
|
||||
Copy `internal/domain/domain.go` and
|
||||
`internal/domain/prepared_run_test.go`, changing only module imports or
|
||||
Promptkit-specific package references required for compilation.
|
||||
|
||||
Copy the file catalog implementation and tests:
|
||||
|
||||
- `internal/filecatalog/catalog.go`
|
||||
- `internal/filecatalog/catalog_test.go`
|
||||
|
||||
Create Promptkit's `internal/defaults/defaults.go` as a responsibility split,
|
||||
not a blind copy. It contains only:
|
||||
|
||||
- `SchemaDirDefault`;
|
||||
- `OutputArtifactName`;
|
||||
- `ContentTypeTextPlain`;
|
||||
- `ContentTypeTextMarkdown`;
|
||||
- `ContentTypeApplicationJSON`;
|
||||
- `OpenAIChatCompletionsPath`;
|
||||
- the four execution defaults;
|
||||
- `LLMRequestTimeoutDefault`; and
|
||||
- `ExecutionTargetDefault`.
|
||||
|
||||
Do not copy:
|
||||
|
||||
- `HTTPAddrDefault`;
|
||||
- `HTTPReadHeaderTimeoutDefault`;
|
||||
- `HTTPMaxRequestBytesDefault`;
|
||||
- `HTTPMaxArtifactBytesDefault`; or
|
||||
- `HTTPMaxResponseBytesDefault`.
|
||||
|
||||
Those values remain Scriptorium application or transport concerns.
|
||||
|
||||
Retain existing literal values and behavior. Do not add exported public facade
|
||||
symbols for internal defaults.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Update Promptkit in the same stage:
|
||||
|
||||
- `README.md` states that extraction is in progress, identifies the internal
|
||||
foundation now present, and still states that no usable public framework API
|
||||
exists.
|
||||
- `docs/policy/architecture.md` no longer claims that the root package is the
|
||||
only implemented package. It identifies the implemented foundation and keeps
|
||||
downstream-to-facade dependency direction as the target for later stages.
|
||||
- `docs/internal/overview.md` lists the root package, `internal/domain`,
|
||||
`internal/defaults`, and `internal/filecatalog` with only their implemented
|
||||
responsibilities.
|
||||
|
||||
Do not document later packages as implemented.
|
||||
|
||||
### Stage 1 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./internal/domain ./internal/filecatalog
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
The formatting command must produce no paths. Also confirm:
|
||||
|
||||
- no external dependency was added;
|
||||
- `internal/defaults` contains no CLI, server, or HTTP-limit constant;
|
||||
- no file imports Scriptorium;
|
||||
- all changed Markdown links resolve; and
|
||||
- the README, architecture policy, and internal overview describe the same
|
||||
implemented package set.
|
||||
|
||||
### Stage 1 Completion Gate
|
||||
|
||||
Proceed only when the foundational packages pass independently in Promptkit and
|
||||
the Promptkit repository makes no claim that later sources, orchestration, or
|
||||
public APIs already exist.
|
||||
|
||||
## Stage 2: Extract Prompt Definitions, Profiles, Built-Ins, And Rendering
|
||||
|
||||
### Objective
|
||||
|
||||
Move the YAML-backed prompt and profile source stack, embedded default registry,
|
||||
and prompt renderer onto the Promptkit foundation.
|
||||
|
||||
### Promptkit Implementation
|
||||
|
||||
Extract these package trees with their tests and test data:
|
||||
|
||||
- `internal/promptdef`
|
||||
- `internal/profile`
|
||||
- `internal/profile/builtin`
|
||||
- `internal/prompt`
|
||||
|
||||
The extraction includes:
|
||||
|
||||
- filesystem and `fs.FS` prompt-definition repositories;
|
||||
- strict prompt YAML decoding and validation;
|
||||
- prompt selection by ID and optional version;
|
||||
- contained `content_file` resolution;
|
||||
- filesystem and `fs.FS` profile repositories;
|
||||
- profile validation and raw-key rejection;
|
||||
- overlay behavior and error-preserving fallback;
|
||||
- the embedded built-in repository;
|
||||
- all 24 current built-in YAML assets from the recorded source snapshot; and
|
||||
- Go-template rendering, session IDs, and cache-control behavior.
|
||||
|
||||
Rewrite all internal imports to the Promptkit module path. Preserve package
|
||||
boundaries; do not export repository or renderer implementations.
|
||||
|
||||
Add `gopkg.in/yaml.v3` at the currently validated version used by Scriptorium.
|
||||
Run `go mod tidy`; allow Go to generate the corresponding `go.sum` entries.
|
||||
Do not copy Scriptorium's complete `go.sum` or introduce unused dependencies.
|
||||
|
||||
The built-in asset tree must be byte-for-byte equivalent to the recorded source
|
||||
snapshot at extraction. Asset additions, removals, model renames, or semantic
|
||||
profile changes are separate work.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Update Promptkit's architecture policy and internal overview to include the
|
||||
implemented source and rendering packages. Keep the README accurate that the
|
||||
repository now contains internal framework behavior but still has no usable
|
||||
exported engine.
|
||||
|
||||
Do not create the public format contract yet. These loaders are internal until
|
||||
the root facade exposes supported source construction in Stage 6.
|
||||
|
||||
### Stage 2 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./internal/filecatalog ./internal/promptdef ./internal/profile/... ./internal/prompt
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
go mod tidy
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Also:
|
||||
|
||||
1. Compare the Promptkit built-in asset tree with the recorded Scriptorium
|
||||
source tree and require no content difference.
|
||||
2. Confirm there are exactly 24 embedded YAML assets.
|
||||
3. Confirm the registry test loads every asset, detects duplicate IDs, and
|
||||
verifies the expected catalog.
|
||||
4. Confirm prompt and profile tests use only Promptkit-local test data.
|
||||
5. Confirm strict unknown-field, invalid YAML, duplicate, containment, raw-key,
|
||||
and overlay-failure cases remain covered.
|
||||
6. Confirm no package imports Scriptorium.
|
||||
7. Check every changed Markdown link and run `git diff --check` after module
|
||||
tidying.
|
||||
|
||||
### Stage 2 Completion Gate
|
||||
|
||||
Proceed only when Promptkit independently owns and tests prompt loading, profile
|
||||
loading, the unchanged built-in registry, and rendering without exposing
|
||||
internal implementations as public packages.
|
||||
|
||||
## Stage 3: Extract Artifact Reading And Output Validation
|
||||
|
||||
### Objective
|
||||
|
||||
Move Promptkit's ordinary artifact boundary and validation implementation while
|
||||
leaving Scriptorium's restricted HTTP policy behind.
|
||||
|
||||
### Promptkit Implementation
|
||||
|
||||
Extract:
|
||||
|
||||
- `internal/artifact/reader.go`
|
||||
- `internal/artifact/reader_test.go`
|
||||
- the complete `internal/validate` package and tests
|
||||
|
||||
Promptkit's artifact package includes only the ordinary inline and unrestricted
|
||||
caller-selected file reader. Preserve artifact copying, metadata, hashing,
|
||||
content-type fallback, cancellation, and error behavior.
|
||||
|
||||
Do not copy:
|
||||
|
||||
- `internal/adapter/http/artifact_reader.go`;
|
||||
- its rooted containment implementation;
|
||||
- HTTP byte limits;
|
||||
- HTTP denial policy; or
|
||||
- Scriptorium status/error mapping.
|
||||
|
||||
Extract the standard filesystem validator, `fs.FS` validator, validator
|
||||
interface, schema loading, JSON and JSON Schema behavior, and all associated
|
||||
tests.
|
||||
|
||||
Add `github.com/santhosh-tekuri/jsonschema/v6` at Scriptorium's currently
|
||||
validated version. Run `go mod tidy` and accept only required transitive module
|
||||
entries.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Create `docs/internal/sources.md` as the current internal source document. It
|
||||
describes implemented prompt, profile, built-in, schema, renderer, and ordinary
|
||||
artifact behavior. It must:
|
||||
|
||||
- link to the architecture policy;
|
||||
- distinguish ordinary file reading from Scriptorium's restricted HTTP
|
||||
reader;
|
||||
- identify the package-local test owners;
|
||||
- avoid presenting the future public facade as implemented; and
|
||||
- avoid linking to Scriptorium-local filesystem paths.
|
||||
|
||||
Update the internal overview and architecture policy with artifact and
|
||||
validation responsibilities.
|
||||
|
||||
### Stage 3 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./internal/artifact ./internal/validate
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
go mod tidy
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Confirm:
|
||||
|
||||
- artifact tests cover inline, file, missing-file, unsupported-reference,
|
||||
cancellation, metadata, and copying behavior retained from the source;
|
||||
- validator tests retain basic, JSON, schema success, content-failure, source,
|
||||
registration, compilation, and operational-error distinctions;
|
||||
- no rooted HTTP reader, request-size limit, response mapping, or inbound HTTP
|
||||
package exists;
|
||||
- the module graph contains only the YAML and JSON Schema dependency families
|
||||
needed by implemented code;
|
||||
- no source, test, or documentation path reaches into Scriptorium; and
|
||||
- all changed Markdown links resolve.
|
||||
|
||||
### Stage 3 Completion Gate
|
||||
|
||||
Proceed only when artifact and validation behavior is independently tested in
|
||||
Promptkit and the Scriptorium-specific HTTP security boundary remains entirely
|
||||
outside Promptkit.
|
||||
|
||||
## Stage 4: Extract The OpenAI-Compatible Model Client
|
||||
|
||||
### Objective
|
||||
|
||||
Move the provider-neutral internal client boundary and built-in
|
||||
OpenAI-compatible implementation with its complete wire, timeout, security, and
|
||||
failure contract.
|
||||
|
||||
### Promptkit Implementation
|
||||
|
||||
Extract:
|
||||
|
||||
- `internal/llm/client.go`
|
||||
- `internal/llm/openai_compatible_client.go`
|
||||
- `internal/llm/openai_compatible_client_test.go`
|
||||
|
||||
Rewrite module imports only. Preserve:
|
||||
|
||||
- endpoint selection and `/chat/completions` construction;
|
||||
- request mapping, reserved fields, extra parameters, cache control, session
|
||||
IDs, and structured output;
|
||||
- direct API-key precedence over environment lookup;
|
||||
- response and token-usage decoding;
|
||||
- non-success and malformed-response categories;
|
||||
- response-body suppression for non-success statuses;
|
||||
- supplied-client cloning and non-mutation; and
|
||||
- layered caller-context, transport-cap, and generation-deadline behavior.
|
||||
|
||||
Retain deterministic deadline-capturing transport tests. Do not replace them
|
||||
with short wall-clock sleeps. Keep live providers, real credentials, and paid
|
||||
requests out of the default suite.
|
||||
|
||||
Do not add retries, tool calls, provider catalogs, inbound HTTP behavior, or a
|
||||
stateful session store.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Create:
|
||||
|
||||
- `docs/internal/llm.md`
|
||||
- `docs/integrations/openai-compatible-chat.md`
|
||||
|
||||
The integration document owns the observable outbound wire and timeout
|
||||
contract. The internal document owns implementation flow, collaborators, error
|
||||
categories, and tests. At this stage both documents must accurately note that
|
||||
the client is implemented internally but is not yet assembled through a usable
|
||||
public engine.
|
||||
|
||||
Update the architecture policy and internal overview to include
|
||||
`internal/llm`.
|
||||
|
||||
### Stage 4 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./internal/llm
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Confirm the moved client tests still cover:
|
||||
|
||||
- configuration validation and endpoint behavior;
|
||||
- supplied-client cloning and timeout precedence;
|
||||
- caller deadlines and explicit generation timeout zero;
|
||||
- direct and environment-based authentication;
|
||||
- field inclusion, structured output, extra parameters, and collisions;
|
||||
- malformed payload and response cases;
|
||||
- non-success status handling without body disclosure; and
|
||||
- cancellation and public-facing internal error identity needed by the runner.
|
||||
|
||||
Check all new documentation links and verify that no document claims the root
|
||||
facade is usable before Stage 6.
|
||||
|
||||
### Stage 4 Completion Gate
|
||||
|
||||
Proceed only when the outbound client and its exact integration contract are
|
||||
independently implemented, deterministic, and free of Scriptorium transport or
|
||||
application policy.
|
||||
|
||||
## Stage 5: Extract Framework Orchestration
|
||||
|
||||
### Objective
|
||||
|
||||
Assemble the internal source, rendering, artifact, model, and validation
|
||||
components under Promptkit's use-case runner while keeping the runner internal.
|
||||
|
||||
### Promptkit Implementation
|
||||
|
||||
Extract:
|
||||
|
||||
- `internal/usecase/runner.go`
|
||||
- `internal/usecase/repairer.go`
|
||||
- `internal/usecase/runner_test.go`
|
||||
|
||||
Rewrite imports to Promptkit and make no unrelated algorithmic changes.
|
||||
Preserve:
|
||||
|
||||
- request validation and prompt/profile selection;
|
||||
- source loading and hashing;
|
||||
- execution-setting and presence resolution;
|
||||
- schema loading before generation when structured output is required;
|
||||
- `Run` reuse of `Prepare`;
|
||||
- one-call generation and result construction;
|
||||
- content-validation results versus operational validation errors;
|
||||
- internal optional repair behavior;
|
||||
- error wrapping and identity;
|
||||
- direct-key handling and redaction boundaries; and
|
||||
- per-request state with no durable run store.
|
||||
|
||||
The public engine still does not enable the optional repairer and this stage
|
||||
does not add a public repair option.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Create `docs/internal/runner.md` for implemented orchestration, dependencies,
|
||||
flows, failure categories, guarantees, tests, and change guidance. Link to the
|
||||
source and LLM internal documents rather than repeating their contracts.
|
||||
|
||||
Update the architecture policy and internal overview. The README continues to
|
||||
state that internal framework behavior exists but the public facade is not yet
|
||||
usable.
|
||||
|
||||
### Stage 5 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./internal/usecase
|
||||
go test ./...
|
||||
go test -race ./internal/usecase
|
||||
go vet ./...
|
||||
go build ./...
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Confirm runner coverage retains:
|
||||
|
||||
- preparation order and `Run`-through-`Prepare`;
|
||||
- default, profile, and explicit override precedence;
|
||||
- explicit zero and negative-value handling;
|
||||
- prompt/profile/source errors and credential validation;
|
||||
- input and rendered-prompt hashes;
|
||||
- structured schema loading before generation;
|
||||
- generation, validation, and repair outcomes;
|
||||
- cancellation and error categories; and
|
||||
- output artifact names, content types, usage, and timing.
|
||||
|
||||
Confirm all collaborators remain behind internal interfaces and no internal
|
||||
package has been exported merely for wiring.
|
||||
|
||||
### Stage 5 Completion Gate
|
||||
|
||||
Proceed only when the complete internal framework workflow passes in Promptkit
|
||||
and remains inaccessible except through the future root facade.
|
||||
|
||||
## Stage 6: Extract And Characterize The Root Public Facade
|
||||
|
||||
### Objective
|
||||
|
||||
Publish the implemented framework through Promptkit's supported root package
|
||||
with the characterized Scriptorium API shape and Promptkit identity.
|
||||
|
||||
### Promptkit Public Implementation
|
||||
|
||||
Extract and adapt these Scriptorium root files:
|
||||
|
||||
- `artifact_reader.go`
|
||||
- `convert.go`
|
||||
- `engine.go`
|
||||
- `errors.go`
|
||||
- `formatting.go`
|
||||
- `json_copy.go`
|
||||
- `llm_adapter.go`
|
||||
- `profiles.go`
|
||||
- `types.go`
|
||||
|
||||
Replace the foundation-only `doc.go` comment with accurate package-level GoDoc
|
||||
for the implemented Promptkit library.
|
||||
|
||||
Extract and adapt:
|
||||
|
||||
- `engine_test.go`
|
||||
- `artifact_reader_internal_test.go`
|
||||
- `testdata/framework/**`
|
||||
|
||||
Use package `promptkit` for implementation and `promptkit_test` where the source
|
||||
uses external-package contract tests. Change imports from the Scriptorium root
|
||||
to the Promptkit root.
|
||||
|
||||
Preserve the complete exported facade described by the feature roadmap:
|
||||
|
||||
- `Engine`, `Config`, `Option`, `NewEngine`, `Prepare`, and `Run`;
|
||||
- source and injection options;
|
||||
- request, result, artifact, execution, output, validation, rendering, cache,
|
||||
structured-output, usage, and profile values;
|
||||
- serialized constants and helper constructors;
|
||||
- `ArtifactReader` and `LLMClient`;
|
||||
- built-in OpenAI-compatible profile construction; and
|
||||
- all public sentinel errors and `errors.Is` relationships.
|
||||
|
||||
Do not export internal repositories, domain types, concrete validators,
|
||||
concrete internal clients, or public subpackages.
|
||||
|
||||
Make only these intentional identity changes:
|
||||
|
||||
- module imports use `gitea.maximumdirect.net/eric/promptkit`;
|
||||
- package names and GoDoc say Promptkit;
|
||||
- `String` and `GoString` outputs identify `promptkit.RunRequest` and
|
||||
`promptkit.GenerateRequest`; and
|
||||
- examples embedded in GoDoc use the Promptkit qualifier.
|
||||
|
||||
Do not retain the Scriptorium package name or provide an alias/forwarder.
|
||||
|
||||
Preserve:
|
||||
|
||||
- nil engine and option handling;
|
||||
- source replacement and overlay precedence;
|
||||
- empty schema-directory fallback;
|
||||
- client cloning and timeout behavior;
|
||||
- public value copying and mutation isolation;
|
||||
- JSON-compatible extra-parameter validation;
|
||||
- secret omission and redacted formatting;
|
||||
- artifact-reader nil-response handling;
|
||||
- public error mapping and wrapped collaborator identity; and
|
||||
- preparation and run results characterized in Scriptorium.
|
||||
|
||||
### Dependency Guard
|
||||
|
||||
Add a focused Promptkit architecture test that recursively walks repository Go
|
||||
source files, parses their imports, and fails when production or test code imports
|
||||
`gitea.maximumdirect.net/eric/scriptorium` or a subpackage. The test must:
|
||||
|
||||
- inspect nested packages, not only the root;
|
||||
- ignore `.git` and generated or vendor directories that are not maintained
|
||||
source;
|
||||
- report the offending file and import;
|
||||
- avoid encoding the full current package inventory; and
|
||||
- remain useful after legitimate internal reorganization.
|
||||
|
||||
Do not add a brittle test that rejects ordinary standard-library `net/http`
|
||||
use, because Promptkit's outbound client legitimately requires it.
|
||||
|
||||
### Current-State Documentation
|
||||
|
||||
Update immediately:
|
||||
|
||||
- `README.md` now states that Promptkit provides a usable public engine and
|
||||
links to the forthcoming/final consumer documentation only when that file
|
||||
exists in the same stage.
|
||||
- `docs/policy/architecture.md` describes the implemented root-facade-to-
|
||||
internal dependency direction as current state.
|
||||
- `docs/internal/overview.md` inventories the root facade and every implemented
|
||||
internal package.
|
||||
- `docs/integrations/openai-compatible-chat.md` and internal documents remove
|
||||
any temporary statement that the client or runner is not publicly assembled.
|
||||
|
||||
Create `docs/consumers/pkg-promptkit.md` in this stage so task-oriented
|
||||
consumers have a current owner when the public API lands. Derive it from the
|
||||
characterized Scriptorium consumer contract, but:
|
||||
|
||||
- use the Promptkit module and package names;
|
||||
- link exact exported declarations to GoDoc ownership rather than restating
|
||||
signatures unnecessarily;
|
||||
- retain construction, sources, preparation, execution, profiles, credentials,
|
||||
extensions, redaction, and error guidance;
|
||||
- do not mention the Scriptorium CLI or HTTP contract except as a downstream
|
||||
consumer boundary; and
|
||||
- link file-format and outbound integration details only after their canonical
|
||||
documents exist.
|
||||
|
||||
If `docs/formats.md` is deferred to Stage 7, do not add a broken link; add it
|
||||
when that document is created.
|
||||
|
||||
### Stage 6 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test .
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Also:
|
||||
|
||||
1. Run `go doc .` and compare the exported inventory with the characterized
|
||||
Scriptorium facade, allowing only the package/module identity change.
|
||||
2. Run focused public contract tests for construction, source options, profile
|
||||
precedence, preparation, execution, validation, timeout layering, custom
|
||||
clients, custom artifact readers, copying, redaction, and errors.
|
||||
3. Confirm `String` and `GoString` never expose raw API keys and contain no
|
||||
`scriptorium.` type prefix.
|
||||
4. Confirm the recursive dependency guard detects a temporary nested
|
||||
Scriptorium import when deliberately exercised, then remove the temporary
|
||||
violation.
|
||||
5. Search every tracked Go file for the Scriptorium module path and require no
|
||||
matches.
|
||||
6. Confirm no public subpackage, command, application config, inbound HTTP
|
||||
adapter, or compatibility shim exists.
|
||||
7. Check every changed Markdown link and every new GoDoc example.
|
||||
|
||||
### Stage 6 Completion Gate
|
||||
|
||||
Proceed only when an external Go consumer can construct and exercise the
|
||||
Promptkit engine through the module root and the complete public contract suite
|
||||
passes without Scriptorium or repository-local coupling.
|
||||
|
||||
## Stage 7: Complete Durable Documentation, Examples, And Release Readiness
|
||||
|
||||
### Objective
|
||||
|
||||
Finish Promptkit's current-state documentation and provide a maintained,
|
||||
offline consumer workflow before release validation.
|
||||
|
||||
### Framework Format Contract
|
||||
|
||||
Create `docs/formats.md` as the canonical owner for:
|
||||
|
||||
- prompt-definition YAML fields and strict decoding;
|
||||
- inputs, messages, inline content, `content_file`, cache control, session IDs,
|
||||
default profiles, and output contracts;
|
||||
- profile YAML fields, ranges, overlays, `api_key_env`, raw-key prohibition,
|
||||
and execution settings;
|
||||
- the current built-in profile catalog;
|
||||
- schema references and supported validation modes;
|
||||
- credential behavior that belongs to framework formats; and
|
||||
- relationships among file values, in-memory profiles, and request overrides.
|
||||
|
||||
Derive framework-format content from the implemented code and the framework
|
||||
sections of Scriptorium's `docs/config.md`. Do not copy:
|
||||
|
||||
- Scriptorium config discovery;
|
||||
- `prompt_dir`, `profile_dir`, or `schema_dir` application precedence;
|
||||
- server settings;
|
||||
- render-output settings;
|
||||
- CLI flags; or
|
||||
- Scriptorium operations behavior.
|
||||
|
||||
Update Promptkit's documentation policy to assign framework formats to
|
||||
`docs/formats.md`. Update all consumer, integration, and internal documents to
|
||||
link to that canonical owner rather than duplicate its field tables and
|
||||
defaults.
|
||||
|
||||
### Consumer Example
|
||||
|
||||
Create a self-contained offline example at:
|
||||
|
||||
- `examples/go-library/prepare/main.go`
|
||||
- `examples/go-library/prepare/prompt.yaml`
|
||||
|
||||
The example:
|
||||
|
||||
- imports `gitea.maximumdirect.net/eric/promptkit`;
|
||||
- uses `WithPromptFile` for its repository-local prompt;
|
||||
- supplies a valid in-memory `Profile` with `WithProfiles`;
|
||||
- uses an inline synthetic input;
|
||||
- calls `Prepare`, not a live provider;
|
||||
- prints deterministic JSON containing only stable summary fields;
|
||||
- requires no credential or environment variable;
|
||||
- reads no Scriptorium path; and
|
||||
- runs from the Promptkit repository root with
|
||||
`go run ./examples/go-library/prepare`.
|
||||
|
||||
Keep the prompt asset minimal and copyable. Do not duplicate Scriptorium's full
|
||||
executable example tree.
|
||||
|
||||
### Documentation Reconciliation
|
||||
|
||||
Reconcile these Promptkit documents with the final implemented tree:
|
||||
|
||||
- `README.md`
|
||||
- `docs/development.md`
|
||||
- `docs/policy/architecture.md`
|
||||
- `docs/policy/documentation.md`
|
||||
- `docs/policy/testing.md`
|
||||
- `docs/release.md`
|
||||
- `docs/consumers/pkg-promptkit.md`
|
||||
- `docs/formats.md`
|
||||
- `docs/integrations/openai-compatible-chat.md`
|
||||
- `docs/internal/overview.md`
|
||||
- `docs/internal/runner.md`
|
||||
- `docs/internal/sources.md`
|
||||
- `docs/internal/llm.md`
|
||||
|
||||
Requirements:
|
||||
|
||||
- The README provides a minimal current quickstart and links to the maintained
|
||||
example and consumer guide.
|
||||
- The development guide routes public API, source, model-client, validation,
|
||||
test, example, documentation, and release work to current owners.
|
||||
- Architecture and the internal overview agree on every package and dependency
|
||||
boundary.
|
||||
- The testing policy describes the actual consumer-workflow and package test
|
||||
types without copying a test inventory.
|
||||
- The release procedure adds `go test -race ./...` to pre-tag validation while
|
||||
retaining ordinary test, vet, build, formatting, links, and hygiene checks.
|
||||
- The release procedure still requires a clean checkout, no workspace or
|
||||
replacement, an annotated semantic tag, and remote verification.
|
||||
- The first release remains `v0.1.0`; do not create it in this stage.
|
||||
- No permanent Promptkit document relies on the temporary Scriptorium roadmap
|
||||
as its current contract.
|
||||
- No document claims Promptkit provides a command, inbound HTTP service,
|
||||
application configuration, or binary release.
|
||||
- Exact Go declarations stay in GoDoc; exact format and wire definitions stay
|
||||
in their canonical documents.
|
||||
|
||||
### Stage 7 Validation
|
||||
|
||||
From Promptkit:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
go run ./examples/go-library/prepare
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Also:
|
||||
|
||||
1. Validate every maintained local Markdown link.
|
||||
2. Compile or run fenced Go snippets that are represented as runnable.
|
||||
3. Confirm the example output is deterministic and contains no secret,
|
||||
timestamp, absolute path, or machine-specific value.
|
||||
4. Search maintained files for:
|
||||
|
||||
- the Scriptorium module import;
|
||||
- `scriptorium.RunRequest` and `scriptorium.GenerateRequest`;
|
||||
- stale claims that framework APIs are unimplemented;
|
||||
- template residue;
|
||||
- absolute maintainer filesystem paths;
|
||||
- live credentials; and
|
||||
- claims of hosted CI or binary releases.
|
||||
|
||||
5. Confirm `docs/formats.md` owns framework field tables and that other
|
||||
documents summarize and link.
|
||||
6. Confirm the README, architecture policy, development guide, internal
|
||||
overview, consumer guide, and release procedure agree that Promptkit is a
|
||||
usable library validated by maintainers.
|
||||
|
||||
### Stage 7 Completion Gate
|
||||
|
||||
Proceed only when Promptkit can be understood, used, tested, and prepared for
|
||||
release solely from its own maintained documentation and example.
|
||||
|
||||
## Stage 8: Validate, Publish `v0.1.0`, And Close Step 6
|
||||
|
||||
### Objective
|
||||
|
||||
Validate the complete extraction from clean independent checkouts, publish the
|
||||
first immutable Promptkit module tag, verify remote consumption, and record the
|
||||
completed migration gate in Scriptorium.
|
||||
|
||||
### Prepare The Promptkit Release Candidate
|
||||
|
||||
Before release:
|
||||
|
||||
1. Review every Promptkit change against the recorded Scriptorium source
|
||||
commit.
|
||||
2. Confirm all Stages 1 through 7 are committed in Promptkit with a clean
|
||||
working tree.
|
||||
3. Use plain-English commit messages and keep Promptkit commits in the
|
||||
Promptkit repository only.
|
||||
4. Confirm no `go.work`, `go.work.sum`, local `replace`, generated output, or
|
||||
temporary extraction script is tracked.
|
||||
5. Confirm the release candidate commit is published through Promptkit's normal
|
||||
branch workflow before tagging, as required by `docs/release.md`.
|
||||
|
||||
Do not amend, force-push, or retag an already published version to correct a
|
||||
late failure. Correct the source and repeat validation before the first tag is
|
||||
published.
|
||||
|
||||
### Independent Promptkit Acceptance
|
||||
|
||||
Create a fresh temporary checkout of the exact Promptkit release candidate
|
||||
outside both repositories. Ensure `GOWORK` is empty or `off`. From that
|
||||
checkout run:
|
||||
|
||||
```sh
|
||||
go mod tidy
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
go run ./examples/go-library/prepare
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Require the checkout to remain clean after validation.
|
||||
|
||||
Verify module identity:
|
||||
|
||||
```sh
|
||||
go list -m -f '{{.Path}} {{.GoVersion}}'
|
||||
go list -f '{{.Name}} {{.ImportPath}}' .
|
||||
```
|
||||
|
||||
Verify dependency independence:
|
||||
|
||||
- `go list -m all` contains no Scriptorium module;
|
||||
- `go list -deps ./...` contains no Scriptorium package;
|
||||
- a recursive source search contains no Scriptorium module import;
|
||||
- `go.mod` has no `replace`;
|
||||
- no workspace file is tracked; and
|
||||
- no source, fixture, example, or documentation read depends on a sibling
|
||||
checkout.
|
||||
|
||||
Verify architecture and assets:
|
||||
|
||||
- the root is the only supported public Promptkit package;
|
||||
- all implementation packages are under `internal/`;
|
||||
- no `cmd`, inbound adapter, application config, restricted HTTP reader, or
|
||||
executable artifact exists;
|
||||
- the 24 built-in assets match the recorded extraction source and all load;
|
||||
- the architecture dependency test passes;
|
||||
- the public Go inventory and sentinel errors match the accepted initial
|
||||
facade;
|
||||
- all local Markdown links and runnable examples pass; and
|
||||
- GPLv3 and Promptkit-specific notices remain unchanged by extraction.
|
||||
|
||||
If any check fails, fix the owning stage, commit the correction, and repeat the
|
||||
entire fresh-checkout acceptance suite.
|
||||
|
||||
### Preserve The Pre-Cutover Scriptorium
|
||||
|
||||
Before tagging, validate Scriptorium from its own repository without a
|
||||
workspace or replacement:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./cmd/scriptorium
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Run maintained configuration and example checks required by Scriptorium's
|
||||
current documentation when affected by any intervening source correction.
|
||||
Confirm:
|
||||
|
||||
- `go.mod` has no Promptkit dependency or local replacement;
|
||||
- the CLI and HTTP adapters still use the current Scriptorium facade;
|
||||
- no framework implementation was deleted;
|
||||
- no current Scriptorium contract was redirected prematurely; and
|
||||
- only roadmap documentation is awaiting the Step 6 completion update.
|
||||
|
||||
### Publish And Verify `v0.1.0`
|
||||
|
||||
Follow Promptkit's `docs/release.md` exactly:
|
||||
|
||||
1. create annotated tag `v0.1.0` on the accepted Promptkit commit;
|
||||
2. record in the annotation that documented validation passed for that commit;
|
||||
3. inspect the tag and its resolved commit;
|
||||
4. push the tag to the configured Promptkit origin; and
|
||||
5. verify the remote annotated tag object and resolved commit.
|
||||
|
||||
Do not publish a binary or hosting-provider-specific release artifact.
|
||||
|
||||
After the remote tag is available, create a temporary Go consumer module
|
||||
outside both repositories with `GOWORK=off`. Require
|
||||
`gitea.maximumdirect.net/eric/promptkit@v0.1.0` from the configured remote,
|
||||
compile a minimal program that imports the root package and uses an exported
|
||||
value such as `promptkit.Inline`, and confirm:
|
||||
|
||||
- the module resolves without a local replacement;
|
||||
- the selected version is exactly `v0.1.0`; and
|
||||
- the program builds against the published tag.
|
||||
|
||||
This temporary smoke module is validation only. Do not commit it or use it to
|
||||
begin Scriptorium adoption.
|
||||
|
||||
### Scriptorium Completion Records
|
||||
|
||||
Only after the tag and remote-consumption check succeed, update Scriptorium:
|
||||
|
||||
- change `docs/roadmap/step6.md` to Complete and replace active planning prose
|
||||
with a concise completion record that includes the source Scriptorium commit,
|
||||
accepted Promptkit commit, published tag, validation outcome, retained
|
||||
application boundary, and Step 7 gate;
|
||||
- update `docs/roadmap/migration.md` to mark Steps 1 through 6 complete and
|
||||
identify tagged Promptkit adoption and Scriptorium framework removal in Step
|
||||
7 as next;
|
||||
- revise this file into a concise `Completed Work` record rather than leaving
|
||||
an active stage checklist; and
|
||||
- remove stale “next step” language from older completed gate summaries if any
|
||||
has reappeared.
|
||||
|
||||
Do not update Scriptorium production code, imports, `go.mod`, consumer
|
||||
documentation, or executable examples in this stage.
|
||||
|
||||
Validate all changed Scriptorium links and run `git diff --check`. Keep the
|
||||
completion-record commit in Scriptorium's history and separate from all
|
||||
Promptkit commits.
|
||||
|
||||
### Stage 8 Completion Gate
|
||||
|
||||
Step 6 is complete only when:
|
||||
|
||||
- all feature-roadmap completion criteria are satisfied;
|
||||
- Promptkit passes the full suite from a clean independent checkout;
|
||||
- Scriptorium remains valid in its pre-cutover state;
|
||||
- remote tag `v0.1.0` resolves to the accepted Promptkit commit;
|
||||
- a clean temporary consumer resolves and builds against that tag without a
|
||||
replacement;
|
||||
- both repositories have clean, independent histories; and
|
||||
- Scriptorium's migration roadmap authorizes Step 7 and no earlier adoption.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The accepted ADRs, Step 6 feature roadmap, characterized facade, and
|
||||
current repository policies resolve the extraction, public boundary,
|
||||
validation, documentation, and release decisions required for implementation.
|
||||
536
docs/roadmap/step6.md
Normal file
536
docs/roadmap/step6.md
Normal file
@@ -0,0 +1,536 @@
|
||||
# Migration Step 6: Extract And Stabilize Promptkit
|
||||
|
||||
## Status
|
||||
|
||||
Proposed scope. Migration Step 5 is complete, the Promptkit repository
|
||||
foundation is available, and framework extraction has not yet begun.
|
||||
|
||||
## Purpose
|
||||
|
||||
Establish Promptkit as the independent owner of Scriptorium's reusable
|
||||
prompt-execution framework, public Go facade, built-in profile registry,
|
||||
framework tests, consumer example, and framework documentation.
|
||||
|
||||
This step delivers and publishes the first usable Promptkit library without
|
||||
changing Scriptorium to consume it. The
|
||||
[main migration roadmap](migration.md) owns the overall sequence.
|
||||
[Step 6 implementation plan](implementation.md) owns execution staging and
|
||||
validation gates; this document owns the desired end state and completion
|
||||
policy.
|
||||
[ADR 0002](../adr/0002-split-promptkit-from-scriptorium.md) owns the project
|
||||
boundary, breaking-change policy, module path, versioning direction, and
|
||||
cross-repository release order.
|
||||
[ADR 0003](../adr/0003-use-maintainer-run-validation-and-tag-only-releases-for-promptkit.md)
|
||||
owns Promptkit's maintainer-run validation and tag-only release model.
|
||||
|
||||
## Confirmed Migration Policy
|
||||
|
||||
- Promptkit's module and public import path remain
|
||||
`gitea.maximumdirect.net/eric/promptkit`.
|
||||
- The public package is `promptkit` at the module root.
|
||||
- This migration is intentionally breaking. Promptkit does not provide aliases,
|
||||
forwarding packages, or another compatibility layer for the former
|
||||
Scriptorium import path.
|
||||
- The initial Promptkit facade preserves the useful exported shape and
|
||||
observable behavior of the characterized Scriptorium facade, except for
|
||||
project and package identity changes required by the new module.
|
||||
- Extraction must not become an unrelated public API redesign. Broader changes
|
||||
follow the split unless correctness or the accepted ownership boundary
|
||||
requires them.
|
||||
- Promptkit owns application-neutral framework behavior. Scriptorium continues
|
||||
to own executable, CLI, HTTP-server, application-configuration, deployment,
|
||||
and process concerns.
|
||||
- Promptkit must remain independently buildable and testable without a
|
||||
Scriptorium checkout, Go workspace, local replacement, or unpublished
|
||||
dependency.
|
||||
- Promptkit's first release is `v0.1.0`. The tag must be published before
|
||||
Scriptorium or another consumer adopts Promptkit.
|
||||
- Scriptorium adoption and removal of its former framework implementation
|
||||
belong to Step 7, not this step.
|
||||
|
||||
## Extraction Model And Transitional Ownership
|
||||
|
||||
Step 6 establishes the framework in Promptkit while leaving the current
|
||||
Scriptorium module operational until Step 7. Because the repositories cannot
|
||||
land one atomic cross-repository change, the Scriptorium framework code and
|
||||
current Go-consumer documentation remain temporarily in place during this
|
||||
step.
|
||||
|
||||
At Step 6 completion:
|
||||
|
||||
- Promptkit is the canonical project for new framework development and the
|
||||
tagged library contract.
|
||||
- Scriptorium still contains its pre-cutover framework copy solely so the
|
||||
executable and existing module remain buildable before Step 7.
|
||||
- New framework features and unrelated framework refactors do not land in the
|
||||
Scriptorium copy during this transition.
|
||||
- A necessary defect or security correction discovered before Step 7 is
|
||||
applied consistently to Promptkit and to any still-executed Scriptorium copy,
|
||||
with contract tests protecting the shared observable behavior.
|
||||
- No source file, test, asset, or documentation in either repository reads from
|
||||
the other repository's working tree.
|
||||
|
||||
This temporary duplication is a migration state, not the target architecture.
|
||||
Step 7 removes the Scriptorium framework copy after adopting the tagged
|
||||
Promptkit module.
|
||||
|
||||
## Target Promptkit Repository State
|
||||
|
||||
Promptkit becomes a complete reusable Go library with:
|
||||
|
||||
- a supported root public facade;
|
||||
- internal framework implementation packages;
|
||||
- embedded built-in execution profiles;
|
||||
- strict prompt, profile, and schema loading;
|
||||
- ordinary inline and caller-selected file artifact reading;
|
||||
- prompt rendering, preparation, generation, validation, and error
|
||||
classification;
|
||||
- a provider-neutral model-client boundary and built-in OpenAI-compatible
|
||||
client;
|
||||
- contract-focused, deterministic, offline tests;
|
||||
- current consumer, format, integration, and internal documentation;
|
||||
- a maintained, offline Go consumer example; and
|
||||
- a published `v0.1.0` Go module tag.
|
||||
|
||||
Promptkit has no runnable command, HTTP service, binary release, hosted CI
|
||||
configuration, application-config discovery, deployment policy, or
|
||||
Scriptorium dependency.
|
||||
|
||||
## Public Go Facade
|
||||
|
||||
### Package Identity
|
||||
|
||||
The existing Scriptorium root facade is extracted to package `promptkit`.
|
||||
Exported GoDoc, package comments, examples, formatted request summaries, and
|
||||
other project-identifying text use Promptkit terminology. In particular,
|
||||
`String` and `GoString` representations identify `promptkit.RunRequest` and
|
||||
`promptkit.GenerateRequest`, not the former package.
|
||||
|
||||
No import-path compatibility package is created in either repository.
|
||||
|
||||
### Engine Construction And Sources
|
||||
|
||||
Promptkit provides:
|
||||
|
||||
- `NewEngine(Config, ...Option)`;
|
||||
- `Engine.Prepare`;
|
||||
- `Engine.Run`;
|
||||
- directory-backed prompt, profile, and schema sources through `Config`;
|
||||
- `WithPromptFS` and `WithPromptFile`;
|
||||
- `WithProfileFS`, `WithProfileFile`, and `WithProfiles`;
|
||||
- `WithSchemaFS` and `WithSchemaFile`;
|
||||
- `WithArtifactReader`; and
|
||||
- `WithLLMClient`.
|
||||
|
||||
Nil options retain the characterized behavior. Invalid construction and invalid
|
||||
extension values preserve the public `ErrInvalidConfig` category.
|
||||
|
||||
Prompt definitions, profiles, schemas, source selection, overlay precedence,
|
||||
and strict-decoding behavior remain application-neutral Promptkit concerns.
|
||||
Scriptorium configuration-file discovery and CLI precedence do not move with
|
||||
them.
|
||||
|
||||
### Public Values And Extension Points
|
||||
|
||||
The initial root facade includes the currently characterized:
|
||||
|
||||
- request, prepared-run, result, artifact, execution-target, output-contract,
|
||||
validation, usage, rendered-prompt, cache-control, and structured-output
|
||||
values;
|
||||
- serialized enum values for artifact types, output formats, validation modes,
|
||||
validation statuses, cache control, and structured output;
|
||||
- presence-aware numeric request overrides;
|
||||
- `ArtifactReader` extension point and `File`, `Inline`, and `InlineWithURI`
|
||||
helpers;
|
||||
- `LLMClient`, `GenerateRequest`, and `GenerateResponse` extension boundary;
|
||||
- in-memory `Profile`, `OpenAICompatibleProfileConfig`, and
|
||||
`OpenAICompatibleProfile`; and
|
||||
- public sentinel errors used by Go consumers to classify failures through
|
||||
`errors.Is`.
|
||||
|
||||
Exported names, signatures, serialized values, copying and mutation isolation,
|
||||
nil handling, and error relationships match the characterized Scriptorium
|
||||
facade unless the module/package rename necessarily changes the observable
|
||||
text. `ErrProfileRequired` and `ErrAPIKeyEnvMissing` continue also to match
|
||||
`ErrInvalidRequest`.
|
||||
|
||||
The root facade does not expose internal domain types, repositories, renderers,
|
||||
validators, concrete model clients, adapter DTOs, or assembly constructors.
|
||||
No speculative extension point or public subpackage is introduced.
|
||||
|
||||
### Preparation And Execution Contract
|
||||
|
||||
Promptkit preserves the characterized engine workflow:
|
||||
|
||||
- `Prepare` validates and loads the prompt and profile, resolves execution
|
||||
settings and credentials, loads any structured-output schema, reads input
|
||||
artifacts, renders messages, computes hashes, and returns prepared state
|
||||
without calling a model.
|
||||
- `Run` reuses the same preparation flow, makes one generation call, creates
|
||||
the output artifact, validates generated content, and returns result,
|
||||
validation, usage, hash, and timing metadata.
|
||||
- Generated-content validation failures remain successful calls with a failed
|
||||
validation result. Schema access, compilation, and validator runtime failures
|
||||
remain errors.
|
||||
- Optional internal repair behavior and its tests remain framework-owned, but
|
||||
extraction does not add a new public repair API.
|
||||
- The framework creates no durable run store, checkpoint, archive, or resume
|
||||
workflow.
|
||||
|
||||
## Framework Package Ownership
|
||||
|
||||
The implementation may reorganize files when needed for clean Promptkit
|
||||
boundaries, but the completed library owns these current Scriptorium
|
||||
responsibilities:
|
||||
|
||||
| Current Scriptorium package or file group | Promptkit responsibility |
|
||||
| --- | --- |
|
||||
| Root facade Go files and facade tests | Root `promptkit` package, public construction, values, options, conversions, error mapping, redaction, and facade contracts. |
|
||||
| `internal/domain` | Framework request, preparation, execution, result, validation, artifact, profile, and model-client domain values. |
|
||||
| `internal/usecase` | Preparation and execution orchestration, setting resolution, validation coordination, and internal repair boundary. |
|
||||
| `internal/filecatalog` | Deterministic YAML discovery and source-root helpers. |
|
||||
| `internal/promptdef` | Strict prompt-definition loading from filesystem and `fs.FS` sources. |
|
||||
| `internal/profile` | Strict execution-profile loading, validation, filesystem and `fs.FS` sources, and overlay behavior. |
|
||||
| `internal/profile/builtin` | Embedded built-in profile registry and assets. |
|
||||
| `internal/prompt` | Go-template prompt rendering and cache-control handling. |
|
||||
| `internal/artifact` | Ordinary inline and unrestricted caller-selected file artifact reading. |
|
||||
| `internal/validate` | Basic, JSON, and JSON Schema validation plus filesystem and `fs.FS` schema access. |
|
||||
| `internal/llm` | Provider-neutral internal client boundary and OpenAI-compatible implementation. |
|
||||
| Framework-owned members of `internal/defaults` | Schema fallback, execution defaults, output artifact and content types, OpenAI request path, and built-in client transport cap. |
|
||||
| Framework contract and package test data | Repository-local Promptkit fixtures that support the moved public and internal test suites. |
|
||||
|
||||
Internal packages use the Promptkit module path and may import other Promptkit
|
||||
internal packages only in the dependency direction defined by its architecture
|
||||
policy. They do not import Scriptorium.
|
||||
|
||||
## Defaults And Settings
|
||||
|
||||
Promptkit owns the behavior and defaults used by its engine:
|
||||
|
||||
- empty `SchemaDir` uses the framework's current `.` fallback;
|
||||
- execution temperature, token, top-p, and generation-timeout defaults;
|
||||
- output artifact name and content types;
|
||||
- the OpenAI-compatible chat-completions path;
|
||||
- the built-in client's ten-minute transport-cap fallback; and
|
||||
- source and validation defaults that do not depend on an application
|
||||
transport.
|
||||
|
||||
The execution-setting hierarchy remains request override, then non-zero profile
|
||||
value, then framework default. Numeric request fields remain presence-aware so
|
||||
explicit zero is distinct from omission.
|
||||
|
||||
Scriptorium retains ownership of its server address, request and response byte
|
||||
limits, HTTP read-header timeout, CLI defaults, render-format defaults, and
|
||||
application configuration precedence. Those values do not enter Promptkit.
|
||||
|
||||
## Source, Profile, And Built-In Registry Behavior
|
||||
|
||||
Promptkit preserves:
|
||||
|
||||
- strict YAML decoding and rejection of unknown fields;
|
||||
- prompt selection by ID and optional version rather than filename;
|
||||
- prompt `content_file` resolution relative to its owning source and
|
||||
containment within `fs.FS` roots;
|
||||
- profile selection by ID, validation ranges, raw-key rejection, and
|
||||
`api_key_env` behavior;
|
||||
- in-memory profile precedence over an explicit file or filesystem source,
|
||||
followed by built-ins;
|
||||
- fallback to built-ins only for a genuine profile-not-found result, without
|
||||
hiding primary-source decoding or validation failures;
|
||||
- schema path resolution and the distinction between validation mismatch and
|
||||
operational failure; and
|
||||
- ordinary inline/file artifact hashing, content-type handling, copying, and
|
||||
failure behavior.
|
||||
|
||||
The complete current embedded built-in profile registry moves into Promptkit.
|
||||
All assets remain embedded, strict-loader-valid, uniquely identifiable, and
|
||||
covered by registry tests. No built-in asset is silently added, removed, or
|
||||
semantically changed merely as part of extraction.
|
||||
|
||||
Promptkit's ordinary file reader is intentionally not a deployment sandbox. It
|
||||
may read a path deliberately selected by an in-process consumer. Rooted
|
||||
containment, byte limits, denial policy, and symlink/deployment policy for the
|
||||
Scriptorium HTTP interface remain in Scriptorium.
|
||||
|
||||
## OpenAI-Compatible Client
|
||||
|
||||
Promptkit owns the characterized outbound client contract:
|
||||
|
||||
- endpoint construction and `POST /chat/completions`;
|
||||
- rendered messages, session IDs, cache-control blocks, structured-output
|
||||
payloads, and flattened provider-specific parameters;
|
||||
- reserved-field protection and JSON-compatible extra-parameter validation;
|
||||
- direct request API-key precedence over environment lookup;
|
||||
- model and execution-setting mapping, including explicit numeric zero values;
|
||||
- response decoding and token-usage mapping;
|
||||
- non-success and malformed-response classification without exposing provider
|
||||
response bodies; and
|
||||
- no implicit retry, tool-call, or durable-session behavior.
|
||||
|
||||
Timeout enforcement remains layered:
|
||||
|
||||
- a positive supplied `HTTPClient.Timeout` is the transport cap;
|
||||
- otherwise a positive `Config.Timeout` supplies the transport cap;
|
||||
- otherwise the internal ten-minute cap applies;
|
||||
- a positive effective `timeout_seconds` creates a per-generation context
|
||||
deadline;
|
||||
- an explicit request value of zero disables only the generation deadline; and
|
||||
- the earliest caller-context deadline, transport cap, or positive generation
|
||||
deadline terminates the call.
|
||||
|
||||
Supplied HTTP clients are cloned and not mutated. Cancellation and transport
|
||||
failures retain the public generation-error category.
|
||||
|
||||
## Application Concerns That Do Not Move
|
||||
|
||||
Step 6 does not copy or recreate these Scriptorium-owned components in
|
||||
Promptkit:
|
||||
|
||||
- `cmd/scriptorium`;
|
||||
- `internal/adapter/cli`;
|
||||
- `internal/adapter/http`, including the restricted HTTP artifact reader;
|
||||
- `internal/config`;
|
||||
- `internal/format`;
|
||||
- CLI and HTTP DTOs, parsing, output, status mapping, and transport limits;
|
||||
- configuration-file discovery and CLI-over-configuration precedence;
|
||||
- process cancellation, logging, server construction, or operations behavior;
|
||||
- executable packaging, subprocess integration, or deployment guidance; or
|
||||
- Scriptorium-specific executable examples and configuration files.
|
||||
|
||||
Use of `net/http` for Promptkit's outbound model client and the public
|
||||
`*http.Client` construction option remains valid framework behavior. It does
|
||||
not authorize an inbound HTTP service or transport adapter in Promptkit.
|
||||
|
||||
## Dependencies And Repository Independence
|
||||
|
||||
Promptkit adds only dependencies required by the extracted implementation. The
|
||||
initial extraction retains the currently validated YAML and JSON Schema library
|
||||
versions unless a correctness issue requires an explicit change. Module
|
||||
metadata is tidied and includes only direct and transitive dependencies used by
|
||||
Promptkit.
|
||||
|
||||
The completed Promptkit module:
|
||||
|
||||
- has no dependency on `gitea.maximumdirect.net/eric/scriptorium`;
|
||||
- contains no import of a Scriptorium package;
|
||||
- contains no committed `go.work`, `go.work.sum`, or local filesystem
|
||||
`replace`;
|
||||
- does not read Scriptorium-relative paths from code, tests, examples, or
|
||||
documentation;
|
||||
- does not require Scriptorium environment variables, commands, or build
|
||||
artifacts; and
|
||||
- builds and tests successfully from an independent clean checkout.
|
||||
|
||||
Temporary local workspace or replacement configuration may be used while
|
||||
developing the cross-repository extraction, subject to Promptkit's development
|
||||
guide. It is removed before acceptance and does not appear in a commit or tag.
|
||||
|
||||
## Test And Fixture Ownership
|
||||
|
||||
Tests move with the framework behavior they protect. Promptkit owns:
|
||||
|
||||
- public facade construction, source, profile, execution, validation,
|
||||
extension, timeout, copying, redaction, and error-classification tests;
|
||||
- runner and domain contract tests;
|
||||
- prompt, profile, built-in registry, schema, artifact, renderer, file-catalog,
|
||||
and OpenAI-compatible client tests;
|
||||
- deterministic test doubles for model and external boundaries;
|
||||
- package-local prompt, profile, schema, and artifact test data; and
|
||||
- representative end-to-end library preparation and execution coverage.
|
||||
|
||||
Tests are rewritten only for Promptkit identity, repository-local paths, clean
|
||||
package boundaries, or an explicitly documented correction. They do not lose
|
||||
meaningful behavioral coverage merely because internal files move.
|
||||
|
||||
Promptkit tests remain deterministic, offline, parallel-safe, and independent
|
||||
of credentials, paid APIs, live providers, mutable services, Scriptorium, and
|
||||
test execution order. HTTP client tests use controlled local transports or
|
||||
test servers as appropriate.
|
||||
|
||||
Scriptorium's CLI, HTTP, restricted-reader, application-config, prepared-output
|
||||
formatting, executable dependency-guard, and process tests remain in
|
||||
Scriptorium. Step 6 does not move those transport tests into Promptkit.
|
||||
|
||||
## Documentation And Examples
|
||||
|
||||
Promptkit's durable documentation describes the implemented library at Step 6
|
||||
completion and owns the framework contracts. At minimum:
|
||||
|
||||
- `README.md` presents Promptkit as usable, includes a minimal current
|
||||
orientation or quickstart, and no longer says framework behavior is
|
||||
unimplemented.
|
||||
- Go declarations and GoDoc own exact exported names, signatures, fields,
|
||||
values, and error contracts.
|
||||
- `docs/consumers/pkg-promptkit.md` provides task-oriented construction,
|
||||
preparation, execution, source, profile, credential, extension, and error
|
||||
guidance without duplicating exact Go declarations.
|
||||
- `docs/formats.md` owns prompt-definition, profile, schema-reference,
|
||||
validation, execution-setting, built-in-profile, and credential file-format
|
||||
contracts.
|
||||
- `docs/integrations/openai-compatible-chat.md` owns the outbound HTTP wire and
|
||||
timeout contract.
|
||||
- `docs/internal/runner.md`, `docs/internal/sources.md`, and
|
||||
`docs/internal/llm.md` describe the implemented internal behavior and tests.
|
||||
- `docs/internal/overview.md` inventories every implemented package and links
|
||||
to its canonical contract or focused internal document.
|
||||
- `docs/development.md`, the architecture, documentation, and testing policies,
|
||||
and `docs/release.md` are reconciled with the implemented package tree and
|
||||
validation workflow.
|
||||
|
||||
Promptkit's documentation policy is updated to assign one canonical owner to
|
||||
framework formats. Documentation uses Promptkit package names and import paths,
|
||||
does not claim CLI or inbound HTTP ownership, and does not rely on temporary
|
||||
Scriptorium roadmap files for its current public contract.
|
||||
|
||||
Promptkit contains a maintained Go consumer example under
|
||||
`examples/go-library/prepare`. The example:
|
||||
|
||||
- imports Promptkit at its canonical module path;
|
||||
- is self-contained within the Promptkit repository;
|
||||
- uses only implemented public APIs;
|
||||
- performs an offline representative preparation flow without credentials or
|
||||
a live model call;
|
||||
- does not read Scriptorium's examples or working tree; and
|
||||
- is executed as part of acceptance validation.
|
||||
|
||||
Any example-specific prompt, profile, schema, or fixture asset belongs to
|
||||
Promptkit and is minimal, synthetic, secret-free, and maintained with the
|
||||
example. Scriptorium's executable examples remain in Scriptorium until their
|
||||
Step 7 documentation cutover.
|
||||
|
||||
Because Scriptorium still implements and exposes its old facade during this
|
||||
transition, its current Go and framework documentation remains in place through
|
||||
Step 6. Step 7 replaces that material with Scriptorium application guidance and
|
||||
links Go consumers to Promptkit.
|
||||
|
||||
## Release Outcome
|
||||
|
||||
After the extracted library and documentation satisfy every acceptance check,
|
||||
Promptkit publishes annotated semantic Go module tag `v0.1.0` using its
|
||||
documented release procedure.
|
||||
|
||||
The tag:
|
||||
|
||||
- identifies the validated Promptkit commit;
|
||||
- contains no workspace, replacement, generated binary, or release artifact;
|
||||
- is available from the configured Promptkit origin;
|
||||
- resolves to the independently validated source commit; and
|
||||
- is the version that Step 7 will use when Scriptorium adopts Promptkit.
|
||||
|
||||
No Scriptorium dependency update, consumer release, Promptkit binary, or
|
||||
hosting-provider-specific release artifact is part of this release.
|
||||
|
||||
## Required Validation Outcome
|
||||
|
||||
From an independent clean Promptkit checkout with no active workspace or local
|
||||
replacement, maintainers must successfully run:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go test -race ./...
|
||||
go vet ./...
|
||||
go build ./...
|
||||
gofmt -l $(git ls-files '*.go')
|
||||
git diff --check
|
||||
```
|
||||
|
||||
The formatting command produces no paths. Acceptance also requires:
|
||||
|
||||
- `go list -m` reports module
|
||||
`gitea.maximumdirect.net/eric/promptkit` and the intended Go version;
|
||||
- the root package reports name `promptkit` and the canonical import path;
|
||||
- `go mod tidy` leaves module metadata clean;
|
||||
- the module graph and all source imports contain no Scriptorium dependency;
|
||||
- every package test and representative library workflow is offline and
|
||||
deterministic;
|
||||
- the maintained Go consumer example runs successfully and produces its
|
||||
documented output shape;
|
||||
- all embedded built-in profiles load and the registry tests pass;
|
||||
- all maintained Markdown links, Go snippets, import paths, commands, and
|
||||
repository-relative paths are valid;
|
||||
- current Promptkit documents agree on package ownership, behavior, validation,
|
||||
and release state;
|
||||
- no template residue, stale Scriptorium package identity, real credential,
|
||||
private fixture, or unsupported future claim remains;
|
||||
- no command package, inbound HTTP adapter, application config, workspace,
|
||||
replacement, hosted CI configuration, generated binary, or unrelated
|
||||
artifact is present;
|
||||
- Git status is clean before tagging; and
|
||||
- the published `v0.1.0` tag passes the verification required by
|
||||
`docs/release.md`.
|
||||
|
||||
The current Scriptorium repository must continue to pass:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build ./cmd/scriptorium
|
||||
```
|
||||
|
||||
Scriptorium documentation links and maintained examples also remain valid.
|
||||
These checks confirm that Step 6 did not break the pre-cutover executable while
|
||||
Promptkit was established independently.
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
Step 6 does not:
|
||||
|
||||
- update Scriptorium imports or `go.mod` to consume Promptkit;
|
||||
- delete the Scriptorium root facade or framework packages;
|
||||
- remove or redirect Scriptorium's current Go-consumer documentation;
|
||||
- migrate CLI, HTTP, application configuration, prepared-output formatting, or
|
||||
restricted HTTP artifact behavior;
|
||||
- migrate downstream consumers;
|
||||
- provide a Scriptorium compatibility facade;
|
||||
- redesign the public engine around a new workflow;
|
||||
- add retries, tool calls, durable sessions, checkpoints, or multi-step
|
||||
orchestration;
|
||||
- add a public repair API without a separately accepted need;
|
||||
- add hosted Promptkit CI, binary packaging, or executable releases;
|
||||
- introduce placeholder public packages or speculative extension points;
|
||||
- upgrade unrelated dependencies; or
|
||||
- begin the Step 7 Scriptorium cutover before `v0.1.0` is published and
|
||||
verified.
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
Step 6 is complete when:
|
||||
|
||||
- Promptkit independently implements the application-neutral framework
|
||||
contract owned by ADR 0002;
|
||||
- the root `promptkit` facade exposes the characterized engine, values,
|
||||
sources, profiles, extension points, and public error identities without
|
||||
compatibility shims or speculative exports;
|
||||
- preparation, execution, profile/default precedence, presence-aware
|
||||
overrides, artifact loading, rendering, structured output, validation,
|
||||
timeout layering, redaction, and error classification retain their
|
||||
characterized behavior;
|
||||
- all framework packages, tests, fixtures, and the complete built-in profile
|
||||
registry are owned and maintained within Promptkit;
|
||||
- Scriptorium-only executable, adapter, application-config, restricted-reader,
|
||||
formatting, deployment, and process concerns are absent from Promptkit;
|
||||
- Promptkit's module dependencies are minimal, tidy, and independent of
|
||||
Scriptorium;
|
||||
- current consumer, format, integration, internal, contributor, architecture,
|
||||
testing, and release documentation has one coherent Promptkit-specific
|
||||
ownership model;
|
||||
- the maintained Promptkit Go example is self-contained, offline, and passing;
|
||||
- the complete Promptkit validation suite, race suite, documentation checks,
|
||||
repository-hygiene checks, and release checks pass from a clean independent
|
||||
checkout;
|
||||
- Scriptorium remains independently buildable, tested, and documented in its
|
||||
pre-cutover state;
|
||||
- Promptkit `v0.1.0` is published and verified against the validated commit;
|
||||
- no Scriptorium or downstream consumer has adopted an unpublished Promptkit
|
||||
revision or a local replacement; and
|
||||
- `migration.md` records Step 6 as complete and identifies the tagged
|
||||
Scriptorium adoption and framework-removal work in Step 7 as the next gate.
|
||||
|
||||
Migration Step 7 must not begin until these criteria are satisfied.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
This feature roadmap is a temporary cross-repository migration artifact. It
|
||||
remains in Scriptorium while Step 6 is active and may be reduced to a completion
|
||||
record or removed after the migration status and durable contracts have moved
|
||||
to their canonical owners.
|
||||
Reference in New Issue
Block a user