# Internal: Adapters ## Purpose Explain the adapter interfaces and production composition used by application and stage orchestration. Externally observable protocols and formats belong in the [integration contracts](../integrations/). ## Adapter Boundaries Narratio stage logic depends on adapter interfaces, not transport-specific details. Primary adapters: - `whisperx.Client` - `seriatim.Runner` - `audita.Runner` - `scriptorium.Runner` - `notarius.Runner` - `storage.ObjectStore` - `notify.Sender` ## Ownership Adapters own: - HTTP/subprocess/SDK argument and transport details. - Backend-specific request/response mapping. Adapters do not own: - stage ordering/skip/force logic; - manifest transitions; - canonical path policy. ## Default Wiring The application composes default adapters per invocation when they were not injected through the stage environment, and only when the selected execution plan needs them: - WhisperX HTTP client for `transcribe`. - Seriatim subprocess runner for `merge`, `normalize`, `trim`, or `render`. - Audita subprocess runner for `polish`. - Scriptorium subprocess runner for `trim` or `analyze`. - Notarius subprocess runner for `extract` when extraction is enabled. - Noop notifier (`notify.NoopSender`) for `notify`. - Object store only when required by selected stages/config. Remote publish locks are loaded only for a selected, enabled publish that uploads a run. Shared session lifecycle setup still applies to every selected range, but an unselected integration is neither initialized nor validated by application-owned composition. Constructor, clock, randomness, remote-lock, and post-publish deletion boundaries are scoped to the invocation; stages still receive their collaborators through the stage environment. Each selected stage retains its own fail-fast configuration and input validation. `session plan` is outside production adapter composition. It performs resume validation and models selected transitions against cloned manifest state without constructing or invoking stage-execution adapters. The shared command configuration loader may still use object storage to retrieve a missing remote session file before planning begins. Notarius is composed only when extraction is enabled; the extract stage owns prepared reference resolution, receipt, bundle, and configured-lane policy. The adapter validates the ordered selector/absolute-path pairs and is the sole owner of serializing them as repeated `--reference` arguments before `--json`. Its request may also carry one already-resolved opaque ConfigKit secret reference. Only the Notarius adapter reads that value, rejects an unresolved or empty programmatic reference, and maps the exact configured name/value into the shared subprocess override and sensitive-name fields. It never rereads the parent environment. A nil reference preserves the previous invocation. Application-owned object-store construction loads configured filesystem secrets before invoking the invocation's storage factory. Production commands use the concrete storage adapter constructor; focused tests can supply an in-memory backend without changing package state. ## Failure Semantics - Constructor errors fail stage execution setup early. - Runtime adapter errors propagate to stage code and then manifest failure handling. - Subprocess adapters persist stage logs/generated configs through stage-managed paths. - Shared subprocess execution keeps private lifecycle mechanics separate from Narratio's environment, diagnostics, redaction, and error policy. It starts an owned process group on Linux and macOS. Every terminal path disposes of that owned tree before returning. After a natural leader exit, the runner checks for remaining group members and uses bounded graceful then forceful termination. Cancellation, deadlines, and diagnostic limits use the same terminal disposal path without losing their original result classification. Child environments contain only the execution baseline and adapter-specified values; configured credentials are resolved once by ConfigKit and passed explicitly as sensitive values. Adapters do not re-read their named environment references. Stdout and stderr are redacted while streaming into separate 8 MiB diagnostic captures; a bounded wait closes a stream retained by a departed leader's descendant. Unsupported platforms reject owned command execution. ## Implementation And Tests - Composition: `internal/app/runner_composition.go`, `internal/app/runner_dependencies.go`, `internal/app/object_store.go` - Shared subprocess mechanics: `internal/adapters/subprocess` - Focused adapters: `internal/adapters/{whisperx,seriatim,audita,scriptorium,notarius,storage,notify}` - `internal/adapters/whisperx/http_test.go` - `internal/adapters/seriatim/subprocess_test.go` - `internal/adapters/audita/subprocess_test.go` - `internal/adapters/scriptorium/subprocess_test.go` - `internal/adapters/notarius/subprocess_test.go` - `internal/adapters/storage/*_test.go` - `internal/app/runner_test.go` See the [WhisperX](../integrations/whisperx.md), [Seriatim](../integrations/seriatim.md), [Audita](../integrations/audita.md), [Scriptorium](../integrations/scriptorium.md), and [Notarius](../integrations/notarius.md) contracts before changing an externally visible boundary. Operator-selected values belong in [Configuration](../config.md).