Plan Notarius configuration profile support

This commit is contained in:
2026-09-21 14:54:47 +00:00
parent d3ecd907ee
commit 46096fc4ba
3 changed files with 501 additions and 0 deletions

View File

@@ -0,0 +1,248 @@
# Implementation Plan: Notarius Configuration Profile Selection
Status: Ready for implementation; all stages pending.
## Scope and Working Instructions
Implement the [feature roadmap](notarius-config-profile.md), whose authority is
the [consumer request](feature-request-notarius-config-profile.yml). Complete
the numbered stages in order. Each stage is a bounded task for a gpt-5.6-terra
coding agent. Do not treat completion of an intermediate stage as completion of
the feature. Record completed stages and actual verification results here.
Before each stage, read `docs/development.md`, all documents under
`docs/policy/`, the feature roadmap, and that stage's preparation list. Follow
AGENTS.md discovery guidance. Use existing collaborators and fixtures; do not
build a new configuration, cache, or profile-management subsystem. Tests must
remain offline and independent of installed Notarius binaries and credentials.
Do not change dependencies, implement Ansible changes, tag, or release as part
of this plan.
## Implementation Decisions
These choices resolve implementation details without adding restrictions to
the feature request:
- Represent the authored field as `ConfigProfile *string` with YAML/JSON name
`config_profile` and `omitempty`, in both typed configuration and its safe
YAML projection. Nil means omitted/null. A non-nil pointer preserves an
explicitly supplied empty string as well as `default` and named selections.
- Carry the same optional value in the Notarius adapter request. Nil emits no
flag; non-nil emits `--config-profile` followed by the exact supplied string
as a separate argument, including an empty string. Do not trim, lowercase,
substitute Narratio's profile, impose a name regex, or inspect profile files.
Notarius owns validation and selector interpretation.
- For reuse evidence only, use one small stage-local helper that maps nil,
`""`, and exact `"default"` to the empty identity; other values remain
unchanged. Both extraction fingerprints use it. This does not mutate the
authored field or change CLI forwarding. Do not attempt to recreate the
downstream parser's complete normalization rules.
- Add `ConfigProfile string` with `json:"config_profile,omitempty"` to both
existing fingerprint payloads, populated only where extraction is enabled.
Preserve existing field ordering and the current semantic fingerprint version
(1). With no non-base selector the serialized payload remains unchanged;
a named selection adds evidence that old records cannot already possess.
No dual-reader, manifest migration, new durable metadata field, or broad
fingerprint-version bump is needed. This is a minimal additive encoding,
not a permanent promise to freeze fingerprint bytes across future releases.
- Profile changes trigger the existing non-resumable/invalidation paths, not
force mode. Preserve configured resume/cache controls, force precedence,
credentials, output contracts, and stage-range behavior. Do not run extraction
outside the operator's selected range or add a separate testing workspace.
- Preserve the existing division of ownership: private downstream file changes
behind an unchanged selector require operator-directed force when needed.
No downstream configuration validation subprocess or runtime version gate
is added.
## Stage 1: Add Configuration and Adapter Support
Status: Pending.
Preparation:
- `docs/config.md` (composition, profiles, Notarius, credentials).
- `docs/integrations/notarius.md` (invocation and failure behavior).
- `internal/config/config.go`, `credential_projection.go`,
`pipeline_configkit.go`, `pipeline_normalize.go`, and `notarius_test.go`.
- `internal/adapters/notarius/runner.go`, `subprocess.go`, `fake.go`, and
`subprocess_test.go`.
Work:
1. Add the optional field to `NotariusConfig` and the `safeNotarius` projection,
including its returned value. Let existing ConfigKit composition handle
overrides and null; do not add a default or resolve this name as a path.
2. Add the optional field to `notarius.RunRequest` and append the argument pair
when non-nil in `SubprocessRunner.Run`, before `--json`. Leave subprocess
environment construction and error propagation unchanged.
3. Audit any explicit Notarius configuration/request copies for the new field.
Update actual omissions without introducing a generic cloning framework.
4. Extend real configuration-load tests to cover a base selection, an overlay
replacing it with a differently named downstream selection, and an overlay
clearing it with null. Cover omitted, empty, and `default` values compactly.
Verify the safe effective-YAML output retains a supplied value, including
explicit empty, and round-trips without leaking credential values. Reuse
existing credential tests rather than duplicating their full matrix.
5. Extend adapter invocation tests for omitted and supplied selections,
including empty and `default`. Assert the argument/value boundary rather
than imposing new ordering requirements on unrelated arguments. Reuse the
existing nonzero-exit test with a selected profile to prove there is no
fallback or successful receipt processing after failure.
Verification:
```sh
go test ./internal/config ./internal/adapters/notarius
```
Completion: Configuration composition and safe inspection preserve the field,
and the adapter forwards it correctly. The executing stage is connected in
Stage 2 together with reuse tracking, so it cannot start using untracked profile
selections as an intermediate implementation.
## Stage 2: Wire Extraction and Profile-Sensitive Reuse
Status: Pending.
Preparation:
- `docs/internal/stage-extract.md`.
- `internal/stage/extract.go`, `extract_resume.go`,
`semantic_contracts_delivery.go`, and their focused tests.
- In particular, `TestExtractStageResolvesManifestInputAndBuildsExactRequest`,
`TestExtractSemanticConfigSensitivityAndOperationalExclusions`, and
`TestExtractStageResumeValidationRequiresFreshEvidence`.
Work:
1. Pass `cfg.ConfigProfile` to the adapter request when extraction executes.
Keep the field independent of credential forwarding and force overrides.
2. Implement the reuse-identity helper and additive fingerprint fields described
above. Update both `extractSemanticConfig` and `fingerprintDocument`, using
the same identity in semantic comparison and `extractionFingerprint`.
Keep disabled extraction insensitive to unused downstream settings.
3. Extend the existing stage request test to prove the authored selection
reaches the adapter. Cover ordinary and forced execution sufficiently to
show that profile forwarding does not alter existing cache-control precedence.
4. Extend semantic-sensitivity coverage: base to named, named to different named,
and named to base change evidence; unchanged selection does not. Verify
nil/empty/`default` share base evidence and disabled settings remain inert.
5. Exercise the focused resume validator with an actual valid recorded bundle:
it remains reusable for the same selection and becomes non-resumable for a
changed selection. This guards the second fingerprint path independently
of the application's semantic comparison.
6. Check the additive encoding against the prior no-profile payload shape once
in focused coverage or a recorded development check. Avoid whole-manifest
snapshots and a permanent historical compatibility harness; retain existing
input/output/reference sorting and all unrelated fingerprint fields.
Verification:
```sh
go test ./internal/stage ./internal/adapters/notarius ./internal/config
```
Completion: Selected profiles reach actual extraction, and both existing reuse
checks account for the selection without forcing downstream cache refresh or
changing the manifest schema.
## Stage 3: Verify Application Lifecycle Behavior
Status: Pending.
Preparation:
- `internal/app/extract_lifecycle_test.go`, `runner_test.go`, and
`run_control_test.go`.
- Existing fixtures and tests for changed extraction outcomes, failure/retry,
and independent render/extract invalidation.
Work:
1. Extend the existing lifecycle fixtures rather than building another harness.
Run a successful extraction with a configured profile, then verify ordinary
reuse for that same profile. Change only the downstream selection and verify
that extraction executes again with the new value, upstream transcripts and
render remain current, and succeeded dependents are invalidated/rerun through
the existing runner policy. Include returning from a named selection to base.
2. Cover the changed-profile failure boundary with the existing fake runner:
return an ordinary downstream error and verify extraction is failed, the
previous result is not advertised as current success, and dependents are not
silently reused. Reuse existing retry coverage where it already proves the
recovery behavior. Do not assert Notarius-specific diagnostic wording.
3. Ensure one configuration-to-execution path proves explicit composition:
Narratio's testing overlay can select a differently named Notarius overlay;
without the field, selecting a Narratio profile does not populate the
downstream request. Use real configuration loading and the existing injected
runner, not a production provider or sibling repository dependency.
4. Review existing operational-exclusion and force tests for continued validity.
Do not broaden invalidation to the full effective configuration digest or
Narratio's profile label, and do not automatically change cache options.
Verification:
```sh
go test ./internal/app ./internal/stage
```
Completion: Tests demonstrate the requested workflow, including selection
changes and failure, across the real Narratio configuration/runner boundaries.
Notarius's own overlay loader and cache internals remain outside these tests.
## Stage 4: Document the Feature and Validate the Completed Change
Status: Pending.
Preparation: Canonical documentation owners listed in the feature roadmap,
`examples/README.md`, and the existing development-focused operations guidance.
Work:
1. Document the optional field in `docs/config.md`, including omitted/null,
explicit base selectors, and independence from Narratio's profile and
`notarius.llm_api_key`. Do not add profile-name restrictions.
2. Update the invocation in `docs/integrations/notarius.md` to include the
optional flag and identify Notarius v0.7.0 as a known supporting version,
not an unconditional version requirement. Preserve the distinction from
`--llm-profile` and ordinary downstream failure handling.
3. Update `docs/internal/stage-extract.md` to describe selection-sensitive reuse
and retain its distinction from private file content and operational settings.
Make clear this is an explicit downstream setting, not blanket invalidation
by Narratio's profile label or effective digest.
4. Add concise development workflow guidance in `docs/operations.md`: explicit
testing-overlay composition; different downstream names are allowed;
switching selection triggers extraction when that stage is in scope; edits
behind an unchanged selector may need force; testing is not a separate
workspace. Preserve the existing distinction between extract+analyze and
analyze-only regeneration.
5. Update the maintained annotated pipeline example to show the optional field
without requiring an externally installed testing overlay (use a commented
named-selection example). Do not make previously runnable examples depend
on new downstream files. Link to canonical owners instead of duplicating
full contracts or adding new top-level Narratio flags.
6. Review the final diff against every observable behavior and scope boundary
in the consumer request. Mark the implementation stages and roadmap status
accurately after verification; do not remove the original request or alter
historical release notes.
Run the repository checks with the maintained Go 1.26 toolchain:
```sh
go test ./...
go test -race ./...
go vet ./...
go build ./...
go test ./internal/doccheck
go test ./internal/config -run '^TestExamplesLoadAndValidate$'
git diff --check
```
Completion: The requested interface, failure and reuse behavior, examples, and
canonical documentation agree; all checks pass. No release is part of this
implementation sprint.
## Open Questions
None. The consumer request resolves the product behavior. The choices above
settle implementation details without adding new operator restrictions,
downstream configuration ownership, or cache guarantees.