Remove legacy manifest provenance decoding
All checks were successful
ci/woodpecker/push/verify Pipeline was successful
All checks were successful
ci/woodpecker/push/verify Pipeline was successful
This commit is contained in:
@@ -23,11 +23,11 @@ portable opaque segments. Unsafe legacy identities are rejected with migration
|
|||||||
guidance rather than being normalized into a different workspace or remote
|
guidance rather than being normalized into a different workspace or remote
|
||||||
namespace.
|
namespace.
|
||||||
|
|
||||||
Decoding is strict at typed execution-state fields. Unknown informational fields
|
Decoding rejects unknown typed fields, including informational fields inside
|
||||||
inside `effective_config` are ignored so older selection labels can be read;
|
`effective_config` and its nested selection. The schema version remains
|
||||||
unknown fields elsewhere are rejected. The schema version remains
|
`narratio.session-manifest.v1`; there is no compatibility reader that silently
|
||||||
`narratio.session-manifest.v1` and there is no compatibility reader that
|
drops retired fields. See [overlay migration](../operations.md#migrating-manifest-overlay-provenance)
|
||||||
silently drops retired execution state. Cleanup progress uses
|
for deliberate migration of retired selection provenance. Cleanup progress uses
|
||||||
only the cleanup entry in `stages`.
|
only the cleanup entry in `stages`.
|
||||||
|
|
||||||
Every persisted session manifest has a non-nil `stages` map. Each entry is
|
Every persisted session manifest has a non-nil `stages` map. Each entry is
|
||||||
|
|||||||
@@ -410,6 +410,30 @@ execute. Deleting Narratio's local reference snapshots does not invalidate a
|
|||||||
complete durable extraction; missing snapshots are reconstructed only when a
|
complete durable extraction; missing snapshots are reconstructed only when a
|
||||||
later extraction actually runs.
|
later extraction actually runs.
|
||||||
|
|
||||||
|
## Migrating Manifest Overlay Provenance
|
||||||
|
|
||||||
|
The pipeline-selection rename is a clean cutover. Manifests containing
|
||||||
|
`effective_config.selected_profile` are rejected by strict decoding; Narratio
|
||||||
|
does not silently discard or translate that retired field.
|
||||||
|
|
||||||
|
Before using an affected local session with the new version:
|
||||||
|
|
||||||
|
1. Stop Narratio activity for the session and back up its manifest.
|
||||||
|
2. Rename only `effective_config.selected_profile` to `selected_overlay`, keeping
|
||||||
|
its `name` and `source`, or remove the retired informational member. If a
|
||||||
|
current `selected_overlay` member already exists, retain it and remove the
|
||||||
|
retired member rather than creating duplicate keys.
|
||||||
|
3. Preserve the schema version, digest, stage records, checkpoint evidence,
|
||||||
|
output references, and other session state. Retry the intended command.
|
||||||
|
|
||||||
|
This metadata is informational, not resume authority. Do not delete session
|
||||||
|
progress or force all stages merely to perform this migration. Other unknown
|
||||||
|
fields still require investigation rather than blanket removal.
|
||||||
|
|
||||||
|
Do not edit immutable remote committed snapshots. Restoring an older snapshot
|
||||||
|
with retired provenance requires a compatible previous Narratio version, followed
|
||||||
|
by migration of the restored local manifest before using the new version.
|
||||||
|
|
||||||
## Migrating Audita and Provider Credentials
|
## Migrating Audita and Provider Credentials
|
||||||
|
|
||||||
This is a breaking clean cutover to Audita v2. Narratio does not translate an
|
This is a breaking clean cutover to Audita v2. Narratio does not translate an
|
||||||
|
|||||||
@@ -93,8 +93,11 @@ newly written selection provenance use overlay terminology as well.
|
|||||||
|
|
||||||
Maintain existing value-based digest and stage-reuse semantics; renaming
|
Maintain existing value-based digest and stage-reuse semantics; renaming
|
||||||
informational selection provenance is not a reason to invalidate completed
|
informational selection provenance is not a reason to invalidate completed
|
||||||
work or rewrite historical manifests. Update maintained examples and operator
|
work or automatically rewrite historical manifests. Strict manifest decoding
|
||||||
migration guidance for the directory and flag changes.
|
rejects retired provenance fields; operators must deliberately migrate that
|
||||||
|
informational member on a backed-up manifest, preserving execution/checkpoint
|
||||||
|
state. Update maintained examples and operator migration guidance for the
|
||||||
|
directory, flag, and provenance changes.
|
||||||
|
|
||||||
This rename does not apply to downstream model profiles, Scriptorium
|
This rename does not apply to downstream model profiles, Scriptorium
|
||||||
`profile_id`, Audita's proposal/validation profiles, or Notarius's
|
`profile_id`, Audita's proposal/validation profiles, or Notarius's
|
||||||
|
|||||||
@@ -46,9 +46,11 @@ as base selection; do not add a persistent default selector or new precedence.
|
|||||||
|
|
||||||
Rename newly written informational provenance to overlay terminology, including
|
Rename newly written informational provenance to overlay terminology, including
|
||||||
`selected_overlay` in manifest configuration provenance. Do not add a dual-field
|
`selected_overlay` in manifest configuration provenance. Do not add a dual-field
|
||||||
reader, rewrite historical manifests, or introduce a manifest-version rejection
|
reader, automatically rewrite historical manifests, or introduce a manifest-version
|
||||||
solely for this informational rename. Existing generic decoding behavior applies
|
rejection solely for this informational rename. Existing strict typed decoding
|
||||||
to old optional provenance; it does not become resume authority. Preserve
|
rejects retired provenance fields. Document backed-up operator migration of
|
||||||
|
that informational member without changing execution/checkpoint state; it does
|
||||||
|
not become resume authority. Preserve
|
||||||
semantic fingerprints and effective-value digest rules when values are unchanged.
|
semantic fingerprints and effective-value digest rules when values are unchanged.
|
||||||
|
|
||||||
Only Narratio pipeline configuration selection is renamed. Keep model/profile
|
Only Narratio pipeline configuration selection is renamed. Keep model/profile
|
||||||
@@ -199,8 +201,9 @@ config commands in `internal/app/`; configuration provenance in
|
|||||||
directory is not a discovery fallback. Do not freeze incidental error wording.
|
directory is not a discovery fallback. Do not freeze incidental error wording.
|
||||||
5. Verify unchanged effective values retain digest and stage-reuse behavior;
|
5. Verify unchanged effective values retain digest and stage-reuse behavior;
|
||||||
only diagnostic source labels/paths and selected provenance terminology change.
|
only diagnostic source labels/paths and selected provenance terminology change.
|
||||||
Test loading representative existing manifests without inventing a new
|
Test current provenance round trips and strict rejection of unknown/retired
|
||||||
invalidation or rejection gate for old optional selection metadata.
|
provenance fields. Document deliberate operator migration; do not add a
|
||||||
|
compatibility decoder, semantic invalidation rule, or schema-version gate.
|
||||||
6. Run focused and full tests before proceeding so failures from the dependency
|
6. Run focused and full tests before proceeding so failures from the dependency
|
||||||
and terminology change are separated from adapter migrations. No Audita or
|
and terminology change are separated from adapter migrations. No Audita or
|
||||||
Notarius credential/CLI behavior changes in this stage.
|
Notarius credential/CLI behavior changes in this stage.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Audita v2 and ConfigKit Migration Review Remediation
|
# Audita v2 and ConfigKit Migration Review Remediation
|
||||||
|
|
||||||
Status: Pending.
|
Status: Complete.
|
||||||
|
|
||||||
Reviewed `83eaa96` through `fae18bf` against the approved clean-cutover decisions,
|
Reviewed `83eaa96` through `fae18bf` against the approved clean-cutover decisions,
|
||||||
[feature roadmap](audita.md), and [implementation plan](implementation.md).
|
[feature roadmap](audita.md), and [implementation plan](implementation.md).
|
||||||
@@ -46,7 +46,14 @@ Required remediation:
|
|||||||
|
|
||||||
## 2. Remove the unapproved manifest compatibility decoder
|
## 2. Remove the unapproved manifest compatibility decoder
|
||||||
|
|
||||||
Priority: P2. Status: Pending.
|
Priority: P2. Status: Complete.
|
||||||
|
|
||||||
|
Removed the permissive custom decoder; ordinary strict typed decoding now
|
||||||
|
applies to provenance as well. Replaced historical-acceptance coverage with
|
||||||
|
retired/unknown-field rejection tests, all of which failed before removal.
|
||||||
|
Current provenance round-trip coverage remains intact. Corrected the roadmap,
|
||||||
|
plan, internal contract, and operator guidance for narrow backed-up migration
|
||||||
|
without discarding execution/checkpoint state or changing resume authority.
|
||||||
|
|
||||||
Location: `internal/manifest/manifest.go:79-89`,
|
Location: `internal/manifest/manifest.go:79-89`,
|
||||||
`internal/manifest/store_test.go:78`, and `docs/internal/manifest.md`'s decoding
|
`internal/manifest/store_test.go:78`, and `docs/internal/manifest.md`'s decoding
|
||||||
@@ -92,6 +99,8 @@ reader. Do not treat that exception as already granted.
|
|||||||
|
|
||||||
## Review verification
|
## Review verification
|
||||||
|
|
||||||
|
The following records the original review, before remediation.
|
||||||
|
|
||||||
- Existing `go test ./...` passed.
|
- Existing `go test ./...` passed.
|
||||||
- Race tests passed for subprocess, Audita, Notarius, config, stage, app, and
|
- Race tests passed for subprocess, Audita, Notarius, config, stage, app, and
|
||||||
manifest packages after removing the temporary reproduction.
|
manifest packages after removing the temporary reproduction.
|
||||||
@@ -105,6 +114,13 @@ shared named credential forwarding/redaction, a v2-only Audita subprocess
|
|||||||
adapter, ordinary reports as diagnostics, and versioned ordered-module polish
|
adapter, ordinary reports as diagnostics, and versioned ordered-module polish
|
||||||
evidence. No live model/provider runs were performed during this review.
|
evidence. No live model/provider runs were performed during this review.
|
||||||
|
|
||||||
|
## Migration remediation verification
|
||||||
|
|
||||||
|
Completed on 2026-09-25. Both new regressions failed before their respective
|
||||||
|
fixes. After remediation, `go test ./...`, `go test -race ./...`,
|
||||||
|
`go vet ./...`, `go build ./...`, documentation checks, maintained configuration
|
||||||
|
example checks, and `git diff --check` passed. No live provider runs were needed.
|
||||||
|
|
||||||
## Historical completed transcription review
|
## Historical completed transcription review
|
||||||
|
|
||||||
Status: Complete.
|
Status: Complete.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package manifest
|
package manifest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -76,18 +75,6 @@ type EffectiveConfigProvenance struct {
|
|||||||
EffectiveConfigDigest string `json:"effective_config_digest,omitempty"`
|
EffectiveConfigDigest string `json:"effective_config_digest,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON accepts unknown informational provenance from older manifests.
|
|
||||||
// The enclosing manifest and its execution state remain strictly decoded.
|
|
||||||
func (p *EffectiveConfigProvenance) UnmarshalJSON(data []byte) error {
|
|
||||||
type provenance EffectiveConfigProvenance
|
|
||||||
var decoded provenance
|
|
||||||
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*p = EffectiveConfigProvenance(decoded)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectedOverlayProvenance identifies an explicitly or default-selected
|
// SelectedOverlayProvenance identifies an explicitly or default-selected
|
||||||
// pipeline overlay without recording overlay content.
|
// pipeline overlay without recording overlay content.
|
||||||
type SelectedOverlayProvenance struct {
|
type SelectedOverlayProvenance struct {
|
||||||
|
|||||||
@@ -75,18 +75,19 @@ func TestLocalStoreCreateSaveLoadRoundTrip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalStoreLoadsManifestWithHistoricalSelectionProvenance(t *testing.T) {
|
func TestLocalStoreRejectsUnknownProvenanceFields(t *testing.T) {
|
||||||
path := filepath.Join(t.TempDir(), "manifest.json")
|
for _, tc := range []struct{ name, provenance, field string }{
|
||||||
data := `{"schema_version":"narratio.session-manifest.v1","session_id":"2026-05-03","created_at":"2026-05-03T10:00:00Z","updated_at":"2026-05-03T10:00:00Z","effective_config":{"selected_profile":{"name":"testing","source":"explicit"},"effective_config_digest":"001122"},"stages":{}}`
|
{"retired selection", `{"selected_profile":{"name":"testing","source":"explicit"}}`, "selected_profile"},
|
||||||
if err := os.WriteFile(path, []byte(data), 0o600); err != nil {
|
{"unknown provenance", `{"unexpected":true}`, "unexpected"},
|
||||||
t.Fatal(err)
|
{"unknown selection field", `{"selected_overlay":{"name":"testing","source":"explicit","unexpected":true}}`, "unexpected"},
|
||||||
}
|
} {
|
||||||
loaded, err := (&LocalStore{}).Load(context.Background(), path)
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
if err != nil {
|
data := `{"schema_version":"narratio.session-manifest.v1","session_id":"2026-05-03","created_at":"2026-05-03T10:00:00Z","updated_at":"2026-05-03T10:00:00Z","effective_config":` + tc.provenance + `,"stages":{}}`
|
||||||
t.Fatal(err)
|
_, err := (&LocalStore{}).LoadReader(context.Background(), strings.NewReader(data))
|
||||||
}
|
if err == nil || !strings.Contains(err.Error(), tc.field) {
|
||||||
if loaded.EffectiveConfig == nil || loaded.EffectiveConfig.EffectiveConfigDigest != "001122" || loaded.EffectiveConfig.SelectedOverlay != nil {
|
t.Fatalf("expected rejection identifying %q, got %v", tc.field, err)
|
||||||
t.Fatalf("historical informational provenance = %#v", loaded.EffectiveConfig)
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user