Accept the Promptkit split architecture
This commit is contained in:
@@ -44,6 +44,5 @@ reviewable alongside the implementation change that requires them.
|
||||
- Changes to behavior must update the canonical owner in the same change.
|
||||
- Cross-cutting documentation links to the owner instead of copying its
|
||||
details.
|
||||
- Documentation restructuring follows the implementation sequence in
|
||||
[`docs/roadmap/documentation.md`](../roadmap/documentation.md); the roadmap,
|
||||
not this ADR, records completion status.
|
||||
- Documentation restructuring followed a dedicated implementation roadmap;
|
||||
repository history, not this ADR, records its completion.
|
||||
|
||||
288
docs/adr/0002-split-promptkit-from-scriptorium.md
Normal file
288
docs/adr/0002-split-promptkit-from-scriptorium.md
Normal file
@@ -0,0 +1,288 @@
|
||||
# ADR 0002: Split Promptkit From Scriptorium
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Date
|
||||
|
||||
2026-07-26
|
||||
|
||||
## Context
|
||||
|
||||
Scriptorium currently combines two products in one Go module:
|
||||
|
||||
- a reusable prompt-execution framework with a public Go facade; and
|
||||
- a runnable application with CLI and HTTP interfaces.
|
||||
|
||||
Downstream Go projects increasingly import the framework directly and do not
|
||||
use the executable interfaces. Keeping both products in one module couples
|
||||
framework releases, dependencies, documentation, and public API evolution to
|
||||
application-specific transport concerns.
|
||||
|
||||
Promptkit will become the framework project, and Scriptorium will become a slim
|
||||
application that consumes it. This ADR records that end-state boundary. It does
|
||||
not assert that the split has been implemented; until then, the current
|
||||
repository structure and contracts remain authoritative.
|
||||
|
||||
## Decision
|
||||
|
||||
### Projects And Module Paths
|
||||
|
||||
Create a repository named `promptkit` alongside Scriptorium:
|
||||
|
||||
| Project | Repository and Go module path | Root Go package |
|
||||
| --- | --- | --- |
|
||||
| Promptkit | `gitea.maximumdirect.net/eric/promptkit` | `promptkit` |
|
||||
| Scriptorium | `gitea.maximumdirect.net/eric/scriptorium` | No reusable root facade after migration |
|
||||
|
||||
Promptkit will expose its supported public API from the module root. Its
|
||||
implementation packages will remain under `internal/` unless a real consumer
|
||||
extension point requires a public type or interface.
|
||||
|
||||
Scriptorium will import only Promptkit's supported public packages. It will not
|
||||
import Promptkit implementation packages or reproduce Promptkit orchestration.
|
||||
|
||||
### Product Responsibilities
|
||||
|
||||
Promptkit owns application-neutral framework behavior:
|
||||
|
||||
- the engine and its `Prepare` and `Run` workflow;
|
||||
- public request, result, profile, option, extension, and error APIs;
|
||||
- prompt-definition loading and rendering;
|
||||
- profile loading, overlays, and the embedded built-in profile registry;
|
||||
- schema loading and output validation;
|
||||
- provider-neutral model-client boundaries and the OpenAI-compatible client;
|
||||
- artifact types, artifact-reader injection, and general-purpose inline and
|
||||
caller-selected file readers;
|
||||
- execution-setting resolution and framework defaults; and
|
||||
- framework-level secret redaction and error classification.
|
||||
|
||||
Scriptorium owns executable and transport behavior:
|
||||
|
||||
- the `scriptorium` process and its `run`, `render`, and `serve` commands;
|
||||
- CLI parsing, streams, output files, formatting, exit codes, and process
|
||||
cancellation behavior;
|
||||
- application-configuration discovery and CLI-over-configuration precedence;
|
||||
- HTTP routing, strict request decoding, DTO mapping, response encoding,
|
||||
status codes, and transport limits;
|
||||
- HTTP artifact-root containment and deployment policy;
|
||||
- server construction, server defaults, and process logging; and
|
||||
- executable release artifacts.
|
||||
|
||||
The dependency direction is:
|
||||
|
||||
```text
|
||||
Scriptorium CLI and HTTP adapters
|
||||
|
|
||||
v
|
||||
Promptkit public API
|
||||
|
|
||||
v
|
||||
injected sources, readers, and model clients
|
||||
```
|
||||
|
||||
### Current Package Disposition
|
||||
|
||||
Implementation may reorganize files during extraction, but each current package
|
||||
has this target owner:
|
||||
|
||||
| Current package or file group | Target owner | Disposition |
|
||||
| --- | --- | --- |
|
||||
| Root `scriptorium` facade files and tests | Promptkit | Move and rename the public package to `promptkit`; Scriptorium retains no compatibility facade. |
|
||||
| `internal/domain`, `internal/usecase` | Promptkit | Move as internal engine implementation. |
|
||||
| `internal/promptdef`, `internal/prompt` | Promptkit | Move as internal prompt loading and rendering. |
|
||||
| `internal/profile`, `internal/profile/builtin` | Promptkit | Move with embedded built-in assets and registry tests. |
|
||||
| `internal/filecatalog` | Promptkit | Move as source-loading support. |
|
||||
| `internal/validate` | Promptkit | Move as schema and output-validation implementation. |
|
||||
| `internal/llm` | Promptkit | Move with the OpenAI-compatible integration. |
|
||||
| `internal/artifact` | Split | Move general inline/file reading to Promptkit; keep rooted, denied, and byte-limited HTTP file reading in Scriptorium behind a Promptkit reader interface. |
|
||||
| `internal/defaults` | Split | Move framework, execution, output-artifact, content-type, and model-client defaults to Promptkit; keep CLI, HTTP, and server defaults in Scriptorium. |
|
||||
| `internal/adapter/cli`, `internal/adapter/http` | Scriptorium | Keep and refactor to use Promptkit's public API. |
|
||||
| `internal/config` | Scriptorium | Keep application settings, discovery, validation, and CLI precedence. |
|
||||
| `internal/format` | Scriptorium | Keep prepared-run presentation, rewritten against Promptkit public values. |
|
||||
| `cmd/scriptorium` | Scriptorium | Keep as the process entrypoint. |
|
||||
|
||||
Tests move with the behavior they protect. Cross-boundary tests will live with
|
||||
the consuming side: Promptkit protects framework contracts, while Scriptorium
|
||||
protects adapter mapping, HTTP containment, and executable behavior.
|
||||
|
||||
### Public Boundary
|
||||
|
||||
Promptkit's initial facade will preserve the useful shape of the current
|
||||
Scriptorium Go API where that reduces extraction risk. It will expose only the
|
||||
capabilities required by Promptkit consumers and by Scriptorium:
|
||||
|
||||
- engine construction, preparation, and execution;
|
||||
- public request, result, profile, and error values;
|
||||
- prompt, profile, schema, artifact-reader, validator, and model-client source
|
||||
or injection options that have demonstrated consumers; and
|
||||
- enough stable error identity for Scriptorium to map CLI and HTTP outcomes.
|
||||
|
||||
Promptkit will not export its domain package, runner implementation,
|
||||
repositories, adapter DTOs, or general internal constructors merely to
|
||||
simplify the move.
|
||||
|
||||
Scriptorium's CLI and HTTP adapters will depend on a small consumer-facing
|
||||
`Prepare`/`Run` interface where test substitution is needed. That interface
|
||||
belongs at the consuming boundary rather than forcing adapter concepts into
|
||||
Promptkit.
|
||||
|
||||
### Artifact Reading And HTTP Containment
|
||||
|
||||
Promptkit will define the artifact-reader extension point used during
|
||||
preparation. Its ordinary file reader may read a path deliberately supplied by
|
||||
an in-process or CLI caller and does not claim to be a deployment sandbox.
|
||||
|
||||
Scriptorium will implement the HTTP-specific reader that:
|
||||
|
||||
- denies file references when no artifact root is configured;
|
||||
- applies the configured artifact byte limit;
|
||||
- enforces Scriptorium's documented lexical root-containment rule; and
|
||||
- maps reader failures to Scriptorium HTTP error responses.
|
||||
|
||||
Scriptorium will inject that reader through Promptkit's public construction
|
||||
boundary. Promptkit will not know about HTTP roots, status codes, request DTOs,
|
||||
or deployment policy.
|
||||
|
||||
### Configuration And Default Ownership
|
||||
|
||||
Configuration ownership follows the behavior configured, not the current file
|
||||
location:
|
||||
|
||||
| Configuration category | Owner |
|
||||
| --- | --- |
|
||||
| Application configuration discovery, configuration-file precedence, `prompt_dir`, `profile_dir`, and `schema_dir` | Scriptorium |
|
||||
| CLI flags and their mapping to application settings or request overrides | Scriptorium |
|
||||
| `server.*`, render-output settings, HTTP byte limits, and server defaults | Scriptorium |
|
||||
| Prompt-definition, profile, and output-contract file formats | Promptkit |
|
||||
| Prompt/profile source selection, overlays, schema behavior, and built-in profiles | Promptkit |
|
||||
| Execution settings, presence-aware request overrides, and execution defaults | Promptkit |
|
||||
| Built-in OpenAI-compatible client settings, timeout behavior, and provider wire mapping | Promptkit |
|
||||
| HTTP request and response fields, including their mapping to framework values | Scriptorium |
|
||||
|
||||
Scriptorium will translate its application settings and external request
|
||||
values into Promptkit construction options and requests. When an omitted
|
||||
Scriptorium setting means “use the framework default,” Scriptorium will omit
|
||||
the override rather than copy Promptkit's numeric default.
|
||||
|
||||
### Compatibility And Versioning
|
||||
|
||||
This migration is intentionally breaking:
|
||||
|
||||
- new Go consumers will import `gitea.maximumdirect.net/eric/promptkit`;
|
||||
- Scriptorium will not provide aliases, forwarding wrappers, or deprecated
|
||||
compatibility packages for its former Go facade;
|
||||
- existing consumers may remain pinned to the final framework-bearing
|
||||
Scriptorium tag until migrated; and
|
||||
- intermediate migration phases need not preserve source compatibility, but
|
||||
each merged phase must be internally buildable and tested.
|
||||
|
||||
Promptkit's first release will be `v0.1.0`. During the migration, incompatible
|
||||
Promptkit changes may advance its minor version until a stable `v1` contract is
|
||||
declared. The first slim Scriptorium release will advance the Scriptorium minor
|
||||
version beyond the final framework-bearing release. Normal semantic-versioning
|
||||
rules apply independently to both projects after the migration.
|
||||
|
||||
Promptkit must be tagged before Scriptorium or another consumer publishes a
|
||||
release that depends on it. Release branches must use tagged module
|
||||
dependencies, not local replacements or unpublished revisions.
|
||||
|
||||
### Local Development And Cross-Repository Coordination
|
||||
|
||||
For coordinated local work, place both repositories in a temporary Go
|
||||
workspace or use an uncommitted module replacement. `go.work`,
|
||||
`go.work.sum`, and local filesystem `replace` directives must not be committed
|
||||
to release branches.
|
||||
|
||||
Cross-repository changes follow this order:
|
||||
|
||||
1. land and tag the required Promptkit capability;
|
||||
2. update Scriptorium and other consumers to that tag;
|
||||
3. run each repository's own CI and smoke checks; and
|
||||
4. release consumers only after the Promptkit tag is available.
|
||||
|
||||
Migration coordination must confirm out-of-band repository creation, Promptkit
|
||||
tags, and downstream migrations before dependent work proceeds.
|
||||
Cross-repository changes are coordinated, not treated as atomic commits.
|
||||
|
||||
### Documentation And Maintained Assets
|
||||
|
||||
Each repository will maintain its own README, contributor guide, architecture,
|
||||
documentation, testing, release, and operations material appropriate to that
|
||||
project. Cross-project documents will link to the canonical owner rather than
|
||||
copy its contract.
|
||||
|
||||
Existing documentation and maintained assets have these target owners:
|
||||
|
||||
| Current material | Target owner |
|
||||
| --- | --- |
|
||||
| Current README and executable quickstart | Scriptorium; Promptkit creates its own framework orientation |
|
||||
| Public Go package and Go-consumer guidance | Promptkit |
|
||||
| Prompt, profile, schema, execution-setting, and framework credential reference | Promptkit |
|
||||
| OpenAI-compatible integration contract and framework internal documents | Promptkit |
|
||||
| CLI, HTTP API, subprocess, and Scriptorium operations contracts | Scriptorium |
|
||||
| Consumer interface overview | Scriptorium, revised to route Go consumers to Promptkit |
|
||||
| Application-configuration discovery, server settings, and adapter internals | Scriptorium |
|
||||
| Current internal overview and source documentation | Split into repository-local overviews; Promptkit owns framework sources and Scriptorium owns HTTP containment |
|
||||
| This ADR and cross-project migration records | Scriptorium |
|
||||
| `examples/go-library` | Promptkit |
|
||||
| `examples/config*.yml`, `examples/render-markdown-summary.sh`, and `examples/http-run.json` | Scriptorium |
|
||||
| Example prompts, profiles, schemas, and synthetic fixtures used by the executable examples | Scriptorium |
|
||||
| Embedded built-in profile assets | Promptkit |
|
||||
| Scriptorium release workflow and executable packaging | Scriptorium |
|
||||
| Repository-level license, ignore rules, agent guidance, and development policies | Each repository maintains its own applicable copy |
|
||||
|
||||
Promptkit will create or retain its own minimal framework examples and test
|
||||
fixtures rather than making either repository's tests depend on the other's
|
||||
working tree. Scriptorium's framework-format documentation will become a short
|
||||
version-appropriate link to Promptkit, while its maintained executable examples
|
||||
remain self-contained.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
- Keep the current combined repository and improve package naming. This avoids
|
||||
migration work but retains release and ownership coupling between the
|
||||
framework and executable.
|
||||
- Add Promptkit as a wrapper around the Scriptorium public package. This gives
|
||||
consumers a new import path but leaves framework ownership and dependency
|
||||
direction inverted.
|
||||
- Extract Promptkit while retaining a Scriptorium compatibility facade. This
|
||||
reduces immediate consumer changes but creates a second public API surface
|
||||
and prolongs duplicate maintenance.
|
||||
- Move all artifact reading into Promptkit. This would place HTTP containment,
|
||||
byte limits, and deployment policy in the application-neutral framework.
|
||||
- Keep Promptkit and Scriptorium as separate modules in one repository. This
|
||||
separates imports but not repository permissions, release workflows,
|
||||
issue ownership, or independent project evolution.
|
||||
|
||||
## Rationale
|
||||
|
||||
A separate Promptkit project makes the reusable framework the direct owner of
|
||||
the API that downstream Go projects already consume. Keeping Scriptorium as a
|
||||
public-API consumer exercises the same boundary as other consumers and prevents
|
||||
its adapters from relying on framework internals.
|
||||
|
||||
The selected split keeps transport and deployment policy close to the
|
||||
Scriptorium interfaces that expose it, while allowing Promptkit to remain
|
||||
useful to in-process consumers with different IO and security requirements.
|
||||
Explicit package, configuration, documentation, and asset ownership reduces
|
||||
ambiguity during extraction and after release.
|
||||
|
||||
## Consequences
|
||||
|
||||
- All Go consumers of the framework must change their import path.
|
||||
- Promptkit and Scriptorium gain independent issue, release, CI, policy, and
|
||||
documentation lifecycles.
|
||||
- Scriptorium becomes a real downstream integration test of Promptkit's public
|
||||
facade.
|
||||
- Framework changes that affect Scriptorium require tagged, ordered
|
||||
cross-repository coordination.
|
||||
- Some current packages, especially artifact reading and defaults, must be
|
||||
separated by responsibility rather than moved intact.
|
||||
- Scriptorium's current configuration and documentation references must be
|
||||
split between application and framework owners.
|
||||
- Maintainers must inventory and migrate downstream consumers explicitly; no
|
||||
compatibility facade will hide incomplete migration.
|
||||
- Until the split is implemented, the current repository structure and
|
||||
contracts remain authoritative.
|
||||
Reference in New Issue
Block a user