Add generic semantic reconciliation prompt assets

This commit is contained in:
2026-08-09 16:08:53 +00:00
parent 297d58f090
commit b630384aa0
15 changed files with 441 additions and 23 deletions

View File

@@ -207,3 +207,106 @@ func TestSharedPromptDescriptorsReturnFreshCopies(t *testing.T) {
t.Fatalf("resolveSharedPromptFiles() reused descriptor state: first=%#v second=%#v", first, second)
}
}
func TestPromptAssetManifestMountsExternalSharedFiles(t *testing.T) {
external := fstest.MapFS{"core/protocol.md": {Data: []byte("integer protocol")}}
manifest := PromptAssetManifest{
ModuleDir: "dnd.test",
ModuleFiles: []promptfs.ModulePromptFile{
{Name: "prompt.yaml", Path: "prompts/prompt.yaml"},
},
ExternalSharedFiles: []promptfs.SharedPromptFile{
{Name: "protocol.md", FS: external, Path: "core/protocol.md"},
},
}
fys, err := manifest.PromptFS(fstest.MapFS{
"prompts/prompt.yaml": {Data: []byte("id: dnd.test")},
})
if err != nil {
t.Fatalf("PromptFS() error = %v, want nil", err)
}
content, err := fs.ReadFile(fys, "assets/prompts/dnd.test/sharedassets/protocol.md")
if err != nil || string(content) != "integer protocol" {
t.Fatalf("mounted external protocol = %q, %v", content, err)
}
}
func TestPromptAssetManifestHashIncludesExternalSharedFiles(t *testing.T) {
moduleFS := fstest.MapFS{"prompts/prompt.yaml": {Data: []byte("id: dnd.test")}}
external := fstest.MapFS{"core/protocol.md": {Data: []byte("integer protocol")}}
manifest := PromptAssetManifest{
ModuleDir: "dnd.test",
ModuleFiles: []promptfs.ModulePromptFile{
{Name: "prompt.yaml", Path: "prompts/prompt.yaml"},
},
ExternalSharedFiles: []promptfs.SharedPromptFile{
{Name: "protocol.md", FS: external, Path: "core/protocol.md"},
},
}
got, err := manifest.Hash(moduleFS)
if err != nil {
t.Fatalf("Hash() error = %v, want nil", err)
}
want, err := llm.HashAssets([]llm.AssetHashPart{
{FS: moduleFS, Path: "prompts/prompt.yaml"},
{FS: external, Path: "core/protocol.md"},
})
if err != nil {
t.Fatal(err)
}
if got != want {
t.Fatalf("Hash() = %q, want external-aware hash %q", got, want)
}
}
func TestPromptAssetManifestRejectsInvalidExternalSharedFiles(t *testing.T) {
moduleFS := fstest.MapFS{"prompts/prompt.yaml": {Data: []byte("id: dnd.test")}}
tests := []struct {
name string
external []promptfs.SharedPromptFile
shared []string
want string
}{
{
name: "missing",
external: []promptfs.SharedPromptFile{
{Name: "protocol.md", FS: fstest.MapFS{}, Path: "core/protocol.md"},
},
want: "read shared prompt asset core/protocol.md",
},
{
name: "duplicate external destinations",
external: []promptfs.SharedPromptFile{
{Name: "protocol.md", FS: fstest.MapFS{"a.md": {Data: []byte("a")}}, Path: "a.md"},
{Name: " protocol.md ", FS: fstest.MapFS{"b.md": {Data: []byte("b")}}, Path: "b.md"},
},
want: `duplicate sharedassets prompt destination "assets/prompts/dnd.test/sharedassets/protocol.md"`,
},
{
name: "duplicate named and external destinations",
shared: []string{"common-dnd-system.md"},
external: []promptfs.SharedPromptFile{
{Name: "common-dnd-system.md", FS: fstest.MapFS{"system.md": {Data: []byte("external")}}, Path: "system.md"},
},
want: `duplicate sharedassets prompt destination "assets/prompts/dnd.test/sharedassets/common-dnd-system.md"`,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
manifest := PromptAssetManifest{
ModuleDir: "dnd.test",
ModuleFiles: []promptfs.ModulePromptFile{
{Name: "prompt.yaml", Path: "prompts/prompt.yaml"},
},
SharedFiles: test.shared,
ExternalSharedFiles: test.external,
}
if _, err := manifest.PromptFS(moduleFS); err == nil || !strings.Contains(err.Error(), test.want) {
t.Fatalf("PromptFS() error = %v, want %q", err, test.want)
}
if _, err := manifest.Hash(moduleFS); err == nil || !strings.Contains(err.Error(), test.want) {
t.Fatalf("Hash() error = %v, want %q", err, test.want)
}
})
}
}