Files
audita/docs/policy/architecture.md

144 lines
7.4 KiB
Markdown

# Architecture Policy
**Base Policy Version:** 1.3
**Last Updated**: 2026-09-28
**Upstream Source:** [Standard Repository Policies architecture](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/architecture.md)
## Purpose And Ownership
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.
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.
## Architectural Approach
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.
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.
## Application-Specific Topics
Audita is a single-process Go CLI for transcript polishing. Its architecture
separates deterministic transcript processing from external LLM effects through
narrow contracts and adapters. Correction modules and validators remain explicit,
composable components in an ordered processing pipeline.
This policy owns architectural requirements. The [internal overview](../internal/overview.md)
owns the implemented component inventory and links to runtime mechanics.
[CLI](../cli.md), [configuration](../config.md), [operations](../operations.md),
and [integration documentation](../integrations/subprocess.md) own external contracts.
## Ownership and Dependency Direction
- **Core:** owns domain data handling and reusable configuration, schema,
normalization, chunking, output, diagnostics, and reporting contracts. Domain
behavior must not require CLI or provider-transport knowledge.
- **Framework:** owns orchestration contracts and shared runtime mechanics for
modules, validators, proposals, LLM adapters, and report assembly.
It composes domain operations through explicit inputs and outputs.
- **Modules:** own narrowly scoped correction behavior and module-specific prompt
choices. Keep module packages separate rather than collapsing their distinct
responsibilities into a broad generic stage abstraction.
- **Validators:** own validation behavior and composition. Deterministic and
LLM-backed validators remain explicit, independently composable elements.
- **Prompts:** own embedded prompt assets and metadata used by the runtime.
- **CLI and adapters:** own command parsing, streams, filesystem wiring, and
transport. Keep these concerns outside module, validator, and schema logic.
LLM transport belongs behind `StructuredLLMClient` and framework adapter
boundaries. Prefer small shared helpers over broad rewrites. Keep module and
validator inputs, outputs, and configuration dependencies explicit, without
hidden global state.
## Correction and Concurrency Invariants
- Treat LLM responses as nondeterministic inputs. Preserve deterministic proposal
indexing, validator ordering, transcript mutation, reports, and serialization.
- Validate corrections before final mutation, including local proposal checks,
decision cardinality, and apply-time safety. Provider-side schema enforcement
does not replace these checks.
- Keep LLM concurrency bounded and context-aware through PromptKit's engine-local
per-backend admission. Proposal and validation calls selecting the same backend
share that capacity, including retries and repairs. Preserve deterministic
collection order. Recoverable model-operation failures stay local to their
proposal response or validation batch; fatal invariant/application failure
and parent cancellation stop peers and join them.
- Keep module and validator identities, reason codes, and execution-class
distinctions stable where exposed as contracts.
The [pipeline](../internal/pipeline.md), [modules](../internal/modules.md),
[validators](../internal/validators.md), and [LLM runtime](../internal/llm-runtime.md)
describe how these requirements are implemented.
## State and Compatibility
Keep transcript mutation and output handling deterministic around external
calls. Reports and correction ledgers are derived from processing results.
Preserve the separation between transient processing state and filesystem
adapters; physical report placement and optional debug retention belong to
[operations](../operations.md).
Public CLI, configuration, output-schema, diagnostics, report, prompt, module,
and validator contracts should remain stable unless a change is deliberate and
tested. The resilience work intentionally replaced the earlier JSON process
report with versioned errors/recoveries YAML and a fixed Markdown overview;
future changes should treat those current contracts deliberately. Current implementation
limits are documented in the [internal overview](../internal/overview.md#current-scope);
they are not additional prohibitions on future development.
## Trust Boundaries And Threat Scope
Errors should identify the failed processing phase sufficiently for users and
subprocess callers. Preserve the stream and exit behavior defined by the
[CLI contract](../cli.md) and the artifact handling defined by
[operations](../operations.md).
Diagnostics, reports, and surfaced errors must not leak configured LLM secrets.
Configuration redaction and LLM payload/error redaction have separate
responsibilities and should remain separate. Implementation details belong in
[diagnostics and reporting](../internal/diagnostics-reporting.md).
## Dependencies
Keep Audita dependency-light and prefer the Go standard library for CLI parsing,
filesystems, synchronization, and tests. ConfigKit owns configuration loading,
presence, provenance, and secret resolution; PromptKit owns prompt/profile
loading, OpenAI-compatible transport, retries, repairs, and backend admission.
Audita owns domain meaning, role selection, and deterministic processing.
Do not introduce broad CLI, dependency-injection, workflow, logging, or plugin
frameworks without a concrete implemented need and focused tests.
## Testing and Documentation
Follow the [testing policy](testing.md) for risk-based sufficiency and stable test
boundaries. Keep tests close to the behavior they protect; shared helpers should
remove duplication without obscuring component-specific behavior. Relevant
internal docs identify component tests and change recipes; the
[contributor guide](../development.md) provides baseline validation commands.
Follow the [documentation policy](documentation.md) for ownership, current versus
future behavior, and the ADR lifecycle. Keep architecture concise and normative;
use the roadmap for implementation plans rather than maintaining a changelog or
future-feature specification here.