Updated transcript artifact names and canonical paths to use a consistent, role-based nomenclature

This commit is contained in:
2026-05-22 19:05:23 -05:00
parent e920f3a8d5
commit cee52aa092
56 changed files with 991 additions and 463 deletions

View File

@@ -186,11 +186,11 @@ func TestSpoolAndArchiveDefaults(t *testing.T) {
if item.Required == nil || !*item.Required {
t.Fatalf("archive.promote_artifacts[0].required = %#v, want true", item.Required)
}
if item.Source != "narratio.transcript.trimmed" {
t.Fatalf("archive.promote_artifacts[0].source = %q, want narratio.transcript.trimmed", item.Source)
if item.Source != "narratio.transcript.final_trimmed" {
t.Fatalf("archive.promote_artifacts[0].source = %q, want narratio.transcript.final_trimmed", item.Source)
}
if item.Dest != "transcripts/trimmed.json" {
t.Fatalf("archive.promote_artifacts[0].dest = %q, want transcripts/trimmed.json", item.Dest)
if item.Dest != "transcripts/final.trimmed.json" {
t.Fatalf("archive.promote_artifacts[0].dest = %q, want transcripts/final.trimmed.json", item.Dest)
}
}
@@ -204,8 +204,8 @@ func TestArchivePromotionValidation(t *testing.T) {
name: "absolute dest path rejected",
ruleYML: `archive:
promote_artifacts:
- source: "narratio.transcript.trimmed"
dest: "/transcripts/trimmed.json"
- source: "narratio.transcript.final_trimmed"
dest: "/transcripts/final.trimmed.json"
`,
wantErr: "must be a relative path",
},
@@ -213,7 +213,7 @@ func TestArchivePromotionValidation(t *testing.T) {
name: "traversal dest path rejected",
ruleYML: `archive:
promote_artifacts:
- source: "narratio.transcript.trimmed"
- source: "narratio.transcript.final_trimmed"
dest: "../trimmed.json"
`,
wantErr: "must not contain path traversal",
@@ -223,7 +223,7 @@ func TestArchivePromotionValidation(t *testing.T) {
ruleYML: `archive:
promote_artifacts:
- source: "narratio.unknown"
dest: "transcripts/trimmed.json"
dest: "transcripts/final.trimmed.json"
`,
wantErr: "source \"narratio.unknown\" is unsupported",
},
@@ -231,9 +231,9 @@ func TestArchivePromotionValidation(t *testing.T) {
name: "duplicate destination rejected",
ruleYML: `archive:
promote_artifacts:
- source: "narratio.transcript.trimmed"
- source: "narratio.transcript.final_trimmed"
dest: "artifacts/shared.md"
- source: "narratio.transcript.full"
- source: "narratio.transcript.final"
dest: "artifacts/shared.md"
`,
wantErr: "duplicates another archive promotion destination",
@@ -278,6 +278,35 @@ archive:
}
}
func TestArchivePromotionLegacyTranscriptSourcesRejected(t *testing.T) {
legacyTranscriptSources := []string{
"narratio.transcript." + "merged",
"narratio.transcript." + "full",
"narratio.transcript." + "trimmed",
}
for _, source := range legacyTranscriptSources {
t.Run(source, func(t *testing.T) {
pipelineYAML := testPipelineBaseYAML + `
archive:
promote_artifacts:
- source: ` + source + `
dest: transcripts/final.trimmed.json
`
pipelinePath, sessionPath := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
cfg, err := Load(pipelinePath, sessionPath)
if err != nil {
t.Fatalf("Load() error = %v", err)
}
err = Validate(cfg)
wantErr := `source "` + source + `" is unsupported`
if err == nil || !strings.Contains(err.Error(), wantErr) {
t.Fatalf("Validate() error = %v, want to contain %q", err, wantErr)
}
})
}
}
func TestArchivePromotionDerivesDestinationWhenOmitted(t *testing.T) {
tests := []struct {
name string
@@ -289,9 +318,9 @@ func TestArchivePromotionDerivesDestinationWhenOmitted(t *testing.T) {
pipelineYML: testPipelineBaseYAML + `
archive:
promote_artifacts:
- source: narratio.transcript.full
- source: narratio.transcript.final
`,
wantDest: "transcripts/normalized.json",
wantDest: "transcripts/final.json",
},
{
name: "configured source derives configured output path",
@@ -341,7 +370,7 @@ func TestArchiveLockValidation(t *testing.T) {
pipelineYML: testPipelineBaseYAML + `
archive:
locks:
- source: narratio.transcript.trimmed
- source: narratio.transcript.final_trimmed
reason: reviewed transcript
`,
},
@@ -382,8 +411,8 @@ archive:
pipelineYML: testPipelineBaseYAML + `
archive:
locks:
- source: narratio.transcript.trimmed
- source: " narratio.transcript.trimmed "
- source: narratio.transcript.final_trimmed
- source: " narratio.transcript.final_trimmed "
`,
wantErr: "duplicates another archive lock source",
},
@@ -410,12 +439,40 @@ archive:
}
}
func TestArchiveLockLegacyTranscriptSourcesRejected(t *testing.T) {
legacyTranscriptSources := []string{
"narratio.transcript." + "merged",
"narratio.transcript." + "full",
"narratio.transcript." + "trimmed",
}
for _, source := range legacyTranscriptSources {
t.Run(source, func(t *testing.T) {
pipelineYAML := testPipelineBaseYAML + `
archive:
locks:
- source: ` + source + `
`
pipelinePath, sessionPath := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
cfg, err := Load(pipelinePath, sessionPath)
if err != nil {
t.Fatalf("Load() error = %v", err)
}
err = Validate(cfg)
wantErr := `source "` + source + `" is unsupported`
if err == nil || !strings.Contains(err.Error(), wantErr) {
t.Fatalf("Validate() error = %v, want to contain %q", err, wantErr)
}
})
}
}
func TestArchiveLockUnknownFieldFailsStrictDecode(t *testing.T) {
pipelineYAML := testPipelineBaseYAML + `
archive:
locks:
- source: narratio.transcript.trimmed
dest: transcripts/trimmed.json
- source: narratio.transcript.final_trimmed
dest: transcripts/final.trimmed.json
`
pipelinePath, sessionPath := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
_, err := Load(pipelinePath, sessionPath)
@@ -428,8 +485,8 @@ func TestArchiveLegacyFromToFailsStrictDecode(t *testing.T) {
pipelineYAML := testPipelineBaseYAML + `
archive:
promote_artifacts:
- from: transcripts/trimmed.json
to: transcripts/trimmed.json
- from: transcripts/final.trimmed.json
to: transcripts/final.trimmed.json
`
pipelinePath, sessionPath := writeConfigFiles(t, pipelineYAML, testSessionBaseYAML)
_, err := Load(pipelinePath, sessionPath)
@@ -440,27 +497,27 @@ archive:
func TestArchiveLockStoreBytesStrictDecodeAndValidation(t *testing.T) {
store, err := LoadArchiveLockStoreBytes("locks.yml", []byte(`locks:
- source: narratio.transcript.trimmed
- source: narratio.transcript.final_trimmed
reason: reviewed
`), nil)
if err != nil {
t.Fatalf("LoadArchiveLockStoreBytes() error = %v", err)
}
if len(store.Locks) != 1 || store.Locks[0].Source != "narratio.transcript.trimmed" || store.Locks[0].Reason != "reviewed" {
if len(store.Locks) != 1 || store.Locks[0].Source != "narratio.transcript.final_trimmed" || store.Locks[0].Reason != "reviewed" {
t.Fatalf("locks = %#v", store.Locks)
}
_, err = LoadArchiveLockStoreBytes("locks.yml", []byte(`locks:
- source: narratio.transcript.trimmed
dest: transcripts/trimmed.json
- source: narratio.transcript.final_trimmed
dest: transcripts/final.trimmed.json
`), nil)
if err == nil || !strings.Contains(err.Error(), "strict decode failed") {
t.Fatalf("unknown field error = %v, want strict decode failed", err)
}
_, err = LoadArchiveLockStoreBytes("locks.yml", []byte(`locks:
- source: narratio.transcript.trimmed
- source: narratio.transcript.trimmed
- source: narratio.transcript.final_trimmed
- source: narratio.transcript.final_trimmed
`), nil)
if err == nil || !strings.Contains(err.Error(), "duplicates another archive lock source") {
t.Fatalf("duplicate error = %v", err)
@@ -469,19 +526,19 @@ func TestArchiveLockStoreBytesStrictDecodeAndValidation(t *testing.T) {
func TestMergeArchiveLockRulesStaticWins(t *testing.T) {
merged := MergeArchiveLockRules(
[]ArchiveLockRule{{Source: "narratio.transcript.trimmed", Reason: "static"}},
[]ArchiveLockRule{{Source: "narratio.transcript.final_trimmed", Reason: "static"}},
[]ArchiveLockRule{
{Source: "narratio.transcript.trimmed", Reason: "remote"},
{Source: "narratio.transcript.full", Reason: "remote full"},
{Source: "narratio.transcript.final_trimmed", Reason: "remote"},
{Source: "narratio.transcript.final", Reason: "remote full"},
},
)
if len(merged) != 2 {
t.Fatalf("merged len = %d, want 2: %#v", len(merged), merged)
}
if merged[0].Source != "narratio.transcript.trimmed" || merged[0].Reason != "static" {
if merged[0].Source != "narratio.transcript.final_trimmed" || merged[0].Reason != "static" {
t.Fatalf("merged[0] = %#v, want static lock", merged[0])
}
if merged[1].Source != "narratio.transcript.full" {
if merged[1].Source != "narratio.transcript.final" {
t.Fatalf("merged[1] = %#v, want remote full lock", merged[1])
}
}