Define Promptkit library policies and architecture

This commit is contained in:
2026-07-28 02:13:48 +00:00
parent 45653c3e53
commit 120c6db67a
4 changed files with 286 additions and 106 deletions

View File

@@ -14,7 +14,7 @@ A test must be:
- written and reviewed;
- understood by future maintainers and coding agents;
- executed in local and CI workflows;
- executed in maintainer-run validation;
- diagnosed when it fails;
- updated when legitimate behavior changes;
- maintained as fixtures, APIs, and dependencies evolve; and
@@ -49,9 +49,40 @@ Examples of appropriate seams include clocks, randomness, subprocesses, remote A
## Test execution requirements
Tests in the default suite must be deterministic, offline, and independent of real credentials. They must not invoke paid APIs or depend on mutable external services. Tests that require live infrastructure must be explicitly opt-in and clearly separated from the default suite.
Promptkit currently uses maintainer-run validation rather than hosted CI.
Maintainers run the repository-documented test, vet, build, formatting,
documentation-link, and repository-hygiene checks before accepting changes.
Introducing hosted CI later would supplement, not silently redefine, this
documented validation model.
Control clocks, randomness, environment variables, and other process-global or machine-specific state when they affect behavior. Tests should be safe to run repeatedly and alongside other tests without depending on execution order or state left by an earlier test.
Tests in the default suite must be deterministic, offline, and independent of
real credentials. They must not invoke paid APIs, use live network
dependencies, or depend on mutable external services. Tests that require live
infrastructure must be explicitly opt-in and clearly separated from the
default suite.
Control clocks, randomness, environment variables, and other process-global or
machine-specific state when they affect behavior. Tests must be parallel-safe:
they should run repeatedly and alongside other tests without depending on
execution order, shared mutable state, fixed ports, or state left by an earlier
test.
## Test types and assets
Use each test type where it protects a distinct risk:
- Unit and package tests protect focused behavior and invariants through the
narrowest stable boundary.
- Contract tests protect exported behavior, compatibility, and error identity
relied upon by consumers.
- Integration tests use real collaborators when correctness depends on their
interaction, while replacing live or nondeterministic external boundaries.
- Fixtures should be minimal, synthetic, versioned with the behavior they
exercise, and free of credentials or private data.
- Golden files are appropriate only when the complete output is intentionally
stable and semantic review of updates is practical.
- Failure-path tests should cover consequential malformed input, dependency
failure, cancellation, partial results, and recovery behavior.
## What deserves tests
@@ -63,7 +94,7 @@ Prioritize tests for:
4. Failure handling, cancellation, retries, recovery, and partial success.
5. Serialization, schemas, compatibility, and round trips.
6. Previously observed or plausible regressions.
7. Representative integration and end-to-end workflows.
7. Representative integration and consumer workflows.
A package-level contract is behavior relied upon by another package or major collaborator, not every observable detail of a package implementation.
@@ -81,7 +112,9 @@ This is often the package API, but it may instead be:
- a package-level operation when several internal collaborators jointly produce the behavior; or
- a larger integration boundary when correctness emerges from interaction with a real dependency.
Do not force all behavior through oversized end-to-end tests. Do not test every private helper merely because it exists. Choose the boundary that gives durable confidence with the least incidental coupling.
Do not force all behavior through oversized consumer-workflow tests. Do not
test every private helper merely because it exists. Choose the boundary that
gives durable confidence with the least incidental coupling.
## Test behavior, not implementation
@@ -165,10 +198,10 @@ Each behavior should have a clear test owner.
- Parser tests own parsing cases.
- Validator tests own validation rules.
- Domain tests own transformations and invariants.
- Adapter tests own external integration behavior.
- Boundary tests own external integration behavior.
- Orchestrator tests own coordination and failure propagation.
- CLI tests own argument and configuration mapping.
- End-to-end tests prove that representative assembled workflows work.
- Consumer-workflow tests prove that representative assembled library use
works.
Higher-level tests should not repeat every lower-level case. A single intentional policy change should not require unrelated edits across many test files.
@@ -205,13 +238,17 @@ Use:
- fuzz tests for parsers, normalization, path handling, and broad input spaces;
- golden files only when the complete output is intentionally stable;
- integration tests where correctness depends on component interaction; and
- a small number of representative end-to-end tests.
- a small number of representative consumer-workflow tests.
Avoid exact error-string assertions unless the wording is itself contractual. Prefer `errors.Is`, `errors.As`, typed errors, or structured error fields.
At CLI boundaries, prefer exit classifications, structured output, and the smallest stable semantic fragment needed to identify the error. Do not snapshot complete diagnostic wording unless it is contractual.
At public API boundaries, prefer stable error identity, structured values, and
the smallest semantic fragment needed to identify the failure. Do not snapshot
complete diagnostic wording unless it is contractual.
Golden-file updates must require an explicit local flag. CI must not update golden files automatically, and reviewers must inspect the semantic diff before accepting an update.
Golden-file updates must require an explicit local flag. Ordinary validation
runs must never update golden files automatically, and maintainers must inspect
the semantic diff before accepting an update.
Keep tests readable and direct. Test helpers and fixture frameworks must earn their own maintenance cost; do not build elaborate test infrastructure for small or isolated needs.
@@ -221,7 +258,8 @@ Coverage is a diagnostic, not a target.
Use it to find untested critical branches and unexpectedly weak packages. Do not write low-value tests solely to increase a percentage, and do not infer test quality from coverage alone.
Pure domain logic will often warrant higher coverage than CLI wiring or external adapters. Uneven coverage is acceptable when it reflects risk.
Pure domain logic will often warrant higher coverage than facade wiring or
external adapters. Uneven coverage is acceptable when it reflects risk.
Increasing coverage is valuable only when the newly covered behavior protects a meaningful risk at an acceptable cost.
@@ -289,7 +327,9 @@ A test suite is sufficient when:
- legitimate internal changes usually do not require test edits; and
- additional tests would mostly repeat existing protection or preserve inconsequential implementation details.
Sufficiency is a risk judgment, not a coverage percentage or test count. Reassess it as the application, its users, and the consequences of failure evolve.
Sufficiency is a risk judgment, not a coverage percentage or test count.
Reassess it as the library, its consumers, and the consequences of failure
evolve.
The governing rule is: