Align architecture and testing policies with upstream

This commit is contained in:
2026-09-28 01:43:29 +00:00
parent ba0d99f107
commit b3bb36fc86
4 changed files with 179 additions and 202 deletions

View File

@@ -1,147 +1,109 @@
# Architecture Policy
**Base Policy Version:** 1.1
**Base Policy Version:** 1.3
**Last Updated:** 2026-09-26
**Last Updated**: 2026-09-28
**Upstream Source:** https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/architecture.md
## Purpose And Ownership
This policy defines Scriptorium's purpose, responsibility and dependency
boundaries, established invariants, and non-goals. Concrete component inventory
and implementation mechanics belong in [internal documentation](../internal/overview.md);
public behavior belongs in its canonical contracts.
The adopted policy defines the application's purpose and the architectural
constraints contributors must follow. It owns system boundaries, responsibility
and dependency rules, established invariants, and explicit non-goals.
Adopted constraints govern future development without implying that every
capability they could govern exists or is planned. Keep proposed structure and
implementation status in roadmaps, and decision rationale in ADRs. Acceptance
of a decision is not proof of implementation. Do not turn incidental choices
into architectural invariants.
Describe the concrete package inventory and implementation mechanics in internal
documentation. Link to canonical public contracts for their exact behavior and
to ADRs for decision rationale.
## System Shape
## Architectural Approach
Scriptorium is an executable application with four command entry paths: CLI
`run`, CLI `render`, CLI `inspect`, and the HTTP service started by `serve`.
The `inspect` command has prompt and profile modes. Scriptorium does not expose
a reusable root Go package.
Hexagonal architecture is strongly recommended, including encapsulating external
integrations and APIs within internal adapters. Keep domain and application
logic independent of external integration details, and make dependency direction
clear in the adopted policy.
The application consumes
Implement that separation with proportionate, idiomatic code. Choose interfaces
and package layout to serve the application's actual boundaries. Use adapters
for collaborators with external integration responsibilities.
## Adopted Constraints And Implemented Structure
Architectural constraints govern current and future development. Record
implemented structure accurately, proposals and implementation status in the
roadmap, and significant decisions and rationale in ADRs. Describe a target
structure as implemented when its changes land.
Constraints must reflect deliberately selected requirements and decisions.
Do not promote incidental implementation choices into architectural invariants.
## Scriptorium's Purpose And System Shape
Scriptorium is an executable application with CLI `run`, `render`,
`inspect`, and `config` command families and an HTTP service started by
`serve`. It offers simple, request-independent execution of predefined
prompts, not a reusable Scriptorium root Go API or a workflow framework.
The [internal overview](../internal/overview.md) owns the concrete package
inventory; [adapter internals](../internal/adapters.md) and
[source internals](../internal/sources.md) own implementation mechanics.
## Framework And Application Boundaries
Scriptorium consumes
[Promptkit v0.11.1](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.1/docs/consumers/pkg-promptkit.md)
through its supported root package. Promptkit owns prompt execution,
preparation, source formats, built-in profiles, model-client behavior, and
validation. Scriptorium owns application configuration, executable adapters,
prepared-run and definition-inspection presentation, process behavior, and HTTP
deployment policy.
through its supported public root package. Promptkit owns prompt execution,
preparation, prompt and profile formats, built-in profiles, model-client
behavior, validation, and framework defaults. Scriptorium owns application
configuration, executable CLI and HTTP adapters, prepared-run and
definition-inspection presentation, process behavior, and HTTP deployment
policy. The [format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.1/docs/formats.md)
and [outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.1/docs/integrations/openai-compatible-chat.md)
remain Promptkit's contracts.
Scriptorium also consumes ConfigKit v0.4.1 for application configuration
decoding, resolution, and validation flow. Scriptorium owns its application
schema, defaults, normalization, validation rules, source selection, and CLI
flag mapping; ConfigKit does not own Promptkit framework sources or HTTP
artifact containment.
Scriptorium uses ConfigKit v0.4.1 for strict application YAML decoding,
resolution, and validation flow. Scriptorium retains its application schema,
defaults, normalization, validation rules, source selection, and CLI override
mapping. ConfigKit does not own Promptkit framework sources or HTTP artifact
containment. The [configuration contract](../config.md) owns externally
observable configuration behavior.
The concrete package inventory is maintained in the
[internal overview](../internal/overview.md).
Application code may import Promptkit's public root package, but not its
`internal` packages or catalog modules. It must not recreate the removed
Scriptorium framework facade or former framework package families. Use
consumer-owned interfaces only where substitution at an adapter boundary is
needed. Omitted framework settings pass as zero values so Promptkit applies
its own defaults. Cross-project changes land and release in Promptkit before
Scriptorium adopts its tagged dependency; do not commit Go workspaces, local
replacements, vendored Promptkit source, or unpublished dependency assumptions.
The repository's architecture guard protects these import and removal
boundaries. Adapter separation does not require an interface for every type,
extra wrappers, or a fixed directory tree.
As established by [ADR 0004](../adr/0004-definition-boundary.md), Scriptorium
aims to support the complete set of features in valid Promptkit prompt and
profile definitions for its selected upstream version. Promptkit remains the
canonical parser and validator. Library-only features are considered
individually against the simple predefined-prompt execution model.
## Definition Support And Request State
Maintain adapter boundaries with proportionate, idiomatic code. This approach
does not require an interface for every type, additional wrappers, or a fixed
directory tree for integrations that do not exist.
As decided in [ADR 0004](../adr/0004-definition-boundary.md), Scriptorium aims
to support the complete set of features in valid Promptkit prompt and profile
definitions for its selected upstream version. Promptkit remains the canonical
parser and validator. Library-only features are considered individually
against Scriptorium's simple predefined-prompt execution model.
## Dependency Direction
```text
cmd/scriptorium
|
v
CLI and HTTP adapters, configuration, defaults, and formatting
|
v
Promptkit (execution) and ConfigKit (application configuration)
```
- Retained application packages may import Promptkit's root package.
- They must not import Promptkit `internal` packages.
- They must not import Promptkit catalog modules directly.
- They must not import the removed Scriptorium root facade or recreate former
framework package families.
- Adapter-owned interfaces use Promptkit public values when a consumer-side
substitution boundary is needed.
- Scriptorium passes omitted framework settings as zero values so Promptkit
applies its own defaults.
The repository architecture guard enforces these import and removal
invariants.
Cross-project changes land and release in Promptkit before Scriptorium adopts
the tagged dependency. Do not commit Go workspaces, local replacements,
vendored Promptkit implementation, or unpublished dependency assumptions.
## Retained Boundaries
- `internal/adapter/cli` owns commands, flags, configuration precedence,
process streams, output files, summaries, and exit codes.
- `internal/adapter/http` owns routes, strict JSON DTOs, size limits, response
mapping, status mapping, and the restricted artifact reader.
- `internal/config` owns discovery and Scriptorium's application definition;
ConfigKit owns strict YAML decoding and the load/override pipeline.
- `internal/defaults` owns Scriptorium application and HTTP defaults only.
- `internal/format` owns deterministic prepared-run and definition-inspection
text and JSON presentation.
- Promptkit owns framework orchestration and contracts. Its
[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.1/docs/formats.md)
and
[outbound integration contract](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.11.1/docs/integrations/openai-compatible-chat.md)
are canonical.
## HTTP Artifact Security Boundary
Ordinary CLI file loading is provided by Promptkit. Scriptorium's HTTP adapter
injects a restricted `promptkit.ArtifactReader` for inbound HTTP requests.
That reader denies file references without an artifact root, enforces the
configured byte limit, and applies Scriptorium's lexical root-containment rule.
The operating system still follows symlinks after the lexical check.
This boundary handles untrusted request references under the documented
deployment model; it is not a filesystem sandbox. Defending against a
privileged actor concurrently modifying the host filesystem is outside the
adopted scope, not a claim that such activity cannot occur. Do not infer
additional defenses or guarantees from hypothetical threats; raise unsettled
scope decisions under the [agent policy](agents.md).
The [HTTP API](../api.md) owns observable request outcomes, and
[operations](../operations.md) owns deployment permissions and root selection.
## State, Errors, And Secrets
Scriptorium has no durable run-state store, checkpoint, cache, or resume
mechanism. Recovery is a new request after correcting inputs, configuration, or
environment.
Each request is self-contained from the caller's perspective, without
conversation or workflow state retained from completed requests. This does
not mean the process is internally stateless. Shared engines, backend capacity
and queue accounting, in-flight coordination, cancellation, and server
lifecycle resources are permitted and must be shared where necessary to
enforce configured backend limits across concurrent requests. Such state must
be concurrency-safe and does not create a durable user-workflow contract.
Adapters map Promptkit public error identities into CLI exits or HTTP statuses
without classifying by message text. Raw API keys are not accepted in
Scriptorium configuration, CLI arguments, or HTTP payloads, and resolved
External YAML and JSON decoding remains strict. Adapters map external values
through Promptkit public requests and results without taking over framework
orchestration. Explicit numeric request overrides preserve presence, including
zero. Adapters map Promptkit public error identities to CLI exits or HTTP
statuses without classifying by message text. Raw API keys are not accepted
in Scriptorium configuration, CLI arguments, or HTTP payloads, and resolved
secrets must not be emitted.
## Architectural Invariants
- External YAML and JSON decoding remains strict.
- CLI and HTTP behavior remains presentation and transport logic rather than
framework orchestration.
- Explicit numeric request overrides preserve presence, including zero.
- HTTP artifact containment and byte limits remain Scriptorium policy.
- No application package depends on Promptkit implementation packages.
Each execution request is self-contained from the caller's perspective; no
conversation or workflow state is retained from completed requests. This
does not preclude process-scoped operational state. A server shares its
Promptkit engine, backend registry, capacity admission and queue accounting
across relevant concurrent requests so configured backend limits cannot be
bypassed by per-request construction. In-flight coordination, cancellation,
and server lifecycle state must be concurrency-safe. None of this creates a
durable workflow, checkpoint, cache, or resume contract; recovery is a new
request after correcting inputs, configuration, or environment.
## Non-Goals
@@ -153,5 +115,19 @@ secrets must not be emitted.
- Do not add durable workflow, archive, or resume behavior.
- Do not add application-managed prompt modification, follow-up message flows,
conversation management, or multi-step workflow orchestration.
## Trust Boundaries And Threat Scope
Work that is not implemented belongs in `docs/roadmap/`.
Ordinary CLI file loading belongs to Promptkit. For untrusted inbound HTTP
artifact references, Scriptorium injects a restricted
`promptkit.ArtifactReader`. It denies file references without an artifact
root, applies the configured byte limit, and enforces lexical root containment.
The operating system follows symlinks after that lexical check. This is not a
filesystem sandbox or a defense against a privileged actor concurrently
modifying the host filesystem; that threat is outside the adopted scope.
Do not infer stronger defenses from hypothetical threats. Raise unsettled
scope decisions under the [agent policy](agents.md).
The [HTTP API](../api.md) owns observable request outcomes, the
[configuration contract](../config.md) owns credential supply, and
[operations](../operations.md) owns deployment permissions and root selection.
The [source internals](../internal/sources.md) describe reader mechanics.