7.1 KiB
Architecture Policy
Purpose
This document defines Promptkit's current high-level architecture and the durable boundaries that implementation changes must preserve. The internal component overview inventories concrete implemented packages without redefining these rules.
System Shape
Promptkit is an importable Go library. It does not ship a command, an HTTP service, or another application process. Repository examples demonstrate library use but are not Promptkit applications or release artifacts.
The module root contains package promptkit, which is the public facade. It
provides the supported engine, configuration and source options, requests,
results, public values, extension interfaces, profiles, and error sentinels.
The implemented internal components consist of:
internal/domain, which owns framework data values shared by later internal components;internal/backend, which owns validated immutable OpenAI-compatible backend definitions and the built-in OpenRouter definition;internal/defaults, which owns application-neutral framework defaults and constructs the default execution target;internal/filecatalog, which discovers YAML files and provides source-path helpers for filesystem andfs.FSconsumers;internal/promptdef, which loads and validates prompt definitions from filesystem andfs.FSsources;internal/profile, which loads, validates, and overlays execution profiles from filesystem andfs.FSsources;internal/profile/builtin, which embeds the built-in execution profile catalog;internal/prompt, which renders prompt messages from Go templates;internal/artifact, which resolves ordinary inline and unrestricted caller-selected file references;internal/validate, which validates basic, JSON, and JSON Schema output using filesystem andfs.FSschema sources;internal/llm, which defines the provider-neutral generation boundary and implements outbound OpenAI-compatible chat requests; andinternal/usecase, which coordinates preparation and execution across the internal framework components.
The examples/go-library/prepare and examples/go-library/run packages are
maintained downstream consumers of the root facade. They do not expose library
packages or participate in internal assembly.
The root facade assembles the internal repositories, renderer, validator,
outbound client, and use-case runner while translating public values and
errors at the library boundary. The defaults and renderer depend on the domain
model. Prompt-definition and profile repositories use the domain model, file
catalog, and YAML decoder. The built-in profile repository supplies an
embedded fs.FS to the profile package. Artifact reading uses the domain model
and application-neutral defaults. Validation uses the domain model, file
catalog, and JSON Schema implementation. The model client uses the domain
model, application-neutral defaults, and an injected or standard-library HTTP
client. The use-case runner depends on the narrow interfaces owned by each
internal component.
The current implementation follows this dependency direction:
downstream consumers, including Scriptorium
|
v
root promptkit public facade
|
v
internal framework components
|
v
narrow injected abstractions
The backend registry depends on the domain model, and the model client reuses its OpenAI-compatible reserved request-field rule. The facade coordinates internal components and adapts the supported public extension interfaces to narrow internal abstractions. Internal components must not depend on consumers or on Scriptorium.
Repository And Consumer Boundary
Scriptorium is a downstream application that consumes Promptkit through the supported public facade. It is not a Promptkit package and must not become an internal dependency.
Promptkit owns reusable, application-neutral library behavior. It does not own:
- binaries or executable packaging;
- CLI commands, parsing, streams, or exit codes;
- HTTP routes, servers, request DTOs, status mapping, or deployment policy;
- application configuration discovery or precedence;
- process lifecycle, operational state, or application logging; or
- consumer-specific filesystem or security policy.
Those concerns remain with Scriptorium or another consuming application.
Package Ownership
The module root is the supported public facade. Framework implementation
packages belong under Go's internal/ boundary unless a demonstrated, stable
consumer contract requires a public package.
Each package must have one cohesive responsibility and a clear dependency direction. Internal packages must not expose their types merely to simplify wiring, and the public facade must not leak internal representations through exported signatures. New public packages require a durable consumer need that cannot be served cleanly by the root facade.
The internal component overview must be updated as packages are implemented or their responsibilities change.
Exported API Discipline
Export the smallest contract required by real consumers. Exported declarations must have accurate GoDoc, stable semantics, and tests proportionate to their compatibility risk. Avoid speculative extension points, aliases for internal types, and public constructors that expose assembly details.
Once an exported API exists, its Go declaration and GoDoc own its exact public contract. Architecture documentation owns boundary rules, not a duplicate API reference.
Error Boundaries
Internal failures must cross the public facade as errors meaningful to a Go
consumer without exposing private package types or transport-specific policy.
Wrapping should add useful context while preserving any public error identity
needed with errors.Is or errors.As.
Promptkit must not assign CLI exit codes or HTTP status codes. Consumers map public library outcomes into their own transport behavior.
Dependency Injection
External effects and consumer-selected policy must enter through narrow interfaces or functions at the boundary that uses them. Dependencies should be explicitly supplied during construction or invocation rather than read from consumer configuration or hidden process-global state.
Interfaces should be owned by the code that consumes the behavior and should contain only the operations that code requires. Provide defaults only for application-neutral behavior; consumer-specific restrictions and adapters remain injected from the consuming project.
Repository Independence
Promptkit must build, test, and validate independently of Scriptorium. Do not
commit go.work, go.work.sum, or a local filesystem replace directive.
Temporary workspace or replacement configuration may support coordinated local
development, but it is not part of either repository's architecture or release
state.
Current-State Maintenance
Do not list planned packages as implemented components. When implementation introduces a package, update the internal inventory and the owning contract or subsystem document in the same change.