6.9 KiB
Bugfix Request: Preserve Publish Destination Derivation with Explicit Rules
Status: Implemented; release target v2.1.1
Summary
Narratio should successfully derive a publish destination when a valid
publish.outputs rule omits dest, regardless of whether that rule explicitly
sets required. Narratio v2.1.0 currently rejects this valid configuration in
some cases with a ConfigKit resolve.unrecorded_change diagnostic.
This is a configuration-resolution bookkeeping defect, not a YAML formatting
restriction. The fix should preserve the existing public configuration
contract: operators may omit a derivable destination and may independently set
required to either true or false.
Observed Behavior
A pipeline containing a rule equivalent to the following fails during native configuration loading:
publish:
outputs: [{"source": "narratio.transcript.final", "required": true}]
Narratio reports:
error [resolve.unrecorded_change] /publish/outputs: application resolution changed a value without a covering record
The same failure is possible with ordinary block-style YAML when required is
explicit and dest is omitted. Flow-style YAML is valid input and is not the
cause of the defect.
The existing destination-derivation tests do not expose this case because
their rules also omit required. Narratio then supplies the default value for
required and records a change covering the complete publish.outputs
sequence. That broader record happens to cover the destination mutation as
well, masking the missing resolution record that occurs when required is
already explicit.
Expected Contract
The current configuration contract remains unchanged:
publish.outputs[].sourceis required;publish.outputs[].destmay be omitted when Narratio can derive it from the selected built-in or configured artifact source;publish.outputs[].requireddefaults totrue, but an operator may set it explicitly to eithertrueorfalse; and- equivalent valid YAML representations have equivalent configuration semantics.
For example, both rules below should load and validate, retain their explicit requiredness, and receive the canonical derived destination:
publish:
outputs:
- source: narratio.transcript.final
required: true
- source: narratio.transcript.final_markdown
required: false
Root Cause
ConfigKit intentionally treats sequences as atomic when comparing values
before and after application resolution. Changing a field within one
publish.outputs entry is therefore observed as a change to the
/publish/outputs sequence.
Narratio currently derives each missing destination by recording a
normalization at the individual publish.outputs[index].dest path. That child
record does not cover the atomic parent-sequence change. A separate
container-level record is currently created only when Narratio also defaults
an omitted required value, so configurations with explicit required values
lose that incidental coverage.
Recommended Fix
Make Narratio's publish-output resolution bookkeeping conform to ConfigKit's
atomic-sequence contract. Whenever resolution derives one or more destinations
inside publish.outputs, the recorded resolution changes must cover the
/publish/outputs container. Destination derivation must not depend on an
unrelated required default being applied in the same list.
The implementation may retain more specific provenance where useful, but it must provide valid container-level coverage for the sequence mutation. Do not change ConfigKit's sequence comparison semantics merely to accommodate this call site.
Scope
- Correct destination derivation for publish rules that explicitly set
requiredand omit a derivabledest. - Preserve explicit
required: trueandrequired: falsevalues. - Preserve canonical destination derivation for built-in transcript sources and configured artifact sources.
- Add focused regression coverage through Narratio's real configuration load and validation boundary.
- Prepare a backward-compatible patch release after the fix passes the normal repository validation.
Non-goals
- Changing the
publish.outputsschema, defaults, source vocabulary, or destination derivation rules. - Requiring operators or configuration generators to supply
destwhen it is derivable. - Requiring operators to omit explicit
required: truevalues. - Treating flow-style YAML or JSON-compatible YAML values as unsupported.
- Changing ConfigKit's documented atomic treatment of sequences.
- Adding storage, publication, or network integration behavior.
Regression Coverage
Add one focused package-level behavioral test that loads and validates a
pipeline with omitted destinations and explicit requiredness. A representative
list should include both required: true and required: false, then assert
that:
- loading and validation succeed;
- each destination is derived from its source; and
- each explicit
requiredvalue is preserved.
Using the compact flow-style representation that exposed the integration
failure is reasonable, while the existing block-style cases continue to cover
omitted required. The test should exercise the public configuration behavior,
not ConfigKit call choreography or Narratio's private recording mechanism.
No network service, object store, credential, or test double is required.
Target End State
All valid publish rules with derivable sources behave consistently across these cases:
dest |
required |
Result |
|---|---|---|
| omitted | omitted | destination derived; required defaults to true |
| omitted | true |
destination derived; explicit true retained |
| omitted | false |
destination derived; explicit false retained |
| explicit | either value | explicit destination and requiredness retained |
narratio config validate, narratio config show, and ordinary pipeline
loading accept the corrected cases without an unrecorded-change diagnostic.
No operator configuration migration or workaround is required.
Release
This is a backward-compatible correction to documented configuration behavior
and should be released as Narratio v2.1.1. The release note should identify
the corrected explicit-required/derived-destination interaction and state that
no special upgrade action is required.
Acceptance Criteria
- The focused regression test fails against v2.1.0 behavior and passes after the fix.
- Publish rules with explicit
required: trueorrequired: falseand omitted derivable destinations load and validate successfully. - Derived destinations and explicit requiredness appear correctly in the safe effective configuration.
- Existing destination derivation, publish validation, imports, profiles, and configuration inspection tests remain green.
- The complete repository validation and release-candidate checks pass.
- The correction is published as the immutable
v2.1.1tag with the required release note.