Fingerprint D&D extractor mapping policies
This commit is contained in:
@@ -263,12 +263,25 @@ func TestChangedSemanticSpellCatalogFingerprintCannotResumeRecordedCheckpoint(t
|
|||||||
if _, decision := changedLoader.Normalize("spells", spellnormalize.Key, normalizeDependencies); decision.Reused {
|
if _, decision := changedLoader.Normalize("spells", spellnormalize.Key, normalizeDependencies); decision.Reused {
|
||||||
t.Fatalf("changed normalize fingerprint decision = %#v, want normalize checkpoint cold miss", decision)
|
t.Fatalf("changed normalize fingerprint decision = %#v, want normalize checkpoint cold miss", decision)
|
||||||
}
|
}
|
||||||
|
changedMapping := replaceCheckpointFingerprintValue(t, fingerprints, extractSpellMappingFingerprintName(), "dnd.spells.extract_mapping.v2")
|
||||||
|
assertOnlyCheckpointFingerprintChanged(t, fingerprints, changedMapping, extractSpellMappingFingerprintName())
|
||||||
|
_, mappingLoader, err := checkpointHandlersForRun(settings, Options{}, materialized, changedMapping, []byte("same input"), nil, nil, "", "", true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, decision := mappingLoader.Source(materialized.Input.Module); decision.Reused {
|
||||||
|
t.Fatalf("changed mapping policy decision = %#v, want cold miss", decision)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeSpellCatalogFingerprintName() string {
|
func normalizeSpellCatalogFingerprintName() string {
|
||||||
return "normalize:spells:" + spellnormalize.Key + ":effective_catalog"
|
return "normalize:spells:" + spellnormalize.Key + ":effective_catalog"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractSpellMappingFingerprintName() string {
|
||||||
|
return "extract:spells:" + spells.Key + ":mapping_policy"
|
||||||
|
}
|
||||||
|
|
||||||
func replaceCheckpointFingerprintValue(t *testing.T, fingerprints []pipeline.CheckpointFingerprint, name, value string) []pipeline.CheckpointFingerprint {
|
func replaceCheckpointFingerprintValue(t *testing.T, fingerprints []pipeline.CheckpointFingerprint, name, value string) []pipeline.CheckpointFingerprint {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
changed := append([]pipeline.CheckpointFingerprint(nil), fingerprints...)
|
changed := append([]pipeline.CheckpointFingerprint(nil), fingerprints...)
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import (
|
|||||||
|
|
||||||
const Key = "dnd/npcs"
|
const Key = "dnd/npcs"
|
||||||
|
|
||||||
|
const mappingPolicy = "dnd.npcs.extract_mapping.v1"
|
||||||
|
|
||||||
var requiredCapabilities = []string{
|
var requiredCapabilities = []string{
|
||||||
"chunks",
|
"chunks",
|
||||||
"source.transcript",
|
"source.transcript",
|
||||||
@@ -85,6 +87,7 @@ func (e *Extractor) ManifestMetadata() map[string]any {
|
|||||||
"response_schema_version": SchemaVersion,
|
"response_schema_version": SchemaVersion,
|
||||||
"response_schema_sha256": e.responseSchemaSHA,
|
"response_schema_sha256": e.responseSchemaSHA,
|
||||||
"identity_policy": identity.Policy,
|
"identity_policy": identity.Policy,
|
||||||
|
"mapping_policy": mappingPolicy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +99,7 @@ func (e *Extractor) CheckpointFingerprints() []pipeline.CheckpointFingerprint {
|
|||||||
{Name: "prompt", Value: e.promptSHA},
|
{Name: "prompt", Value: e.promptSHA},
|
||||||
{Name: "response_schema", Value: e.responseSchemaSHA},
|
{Name: "response_schema", Value: e.responseSchemaSHA},
|
||||||
{Name: "identity_policy", Value: identity.Policy},
|
{Name: "identity_policy", Value: identity.Policy},
|
||||||
|
{Name: "mapping_policy", Value: mappingPolicy},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ func TestExtractorMetadataAndCheckpointIdentity(t *testing.T) {
|
|||||||
"response_schema_key": string(ResponseSchemaKey), "response_schema_id": ResponseSchemaID,
|
"response_schema_key": string(ResponseSchemaKey), "response_schema_id": ResponseSchemaID,
|
||||||
"response_schema_name": ResponseSchemaName, "response_schema_version": SchemaVersion,
|
"response_schema_name": ResponseSchemaName, "response_schema_version": SchemaVersion,
|
||||||
"identity_policy": "dnd.npcs.identity.v1",
|
"identity_policy": "dnd.npcs.identity.v1",
|
||||||
|
"mapping_policy": mappingPolicy,
|
||||||
} {
|
} {
|
||||||
if metadata[key] != want {
|
if metadata[key] != want {
|
||||||
t.Fatalf("metadata[%q] = %#v, want %q", key, metadata[key], want)
|
t.Fatalf("metadata[%q] = %#v, want %q", key, metadata[key], want)
|
||||||
@@ -88,7 +89,7 @@ func TestExtractorMetadataAndCheckpointIdentity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fingerprints := extractor.CheckpointFingerprints()
|
fingerprints := extractor.CheckpointFingerprints()
|
||||||
want := map[string]string{"prompt": metadata["prompt_sha256"].(string), "response_schema": metadata["response_schema_sha256"].(string), "identity_policy": "dnd.npcs.identity.v1"}
|
want := map[string]string{"prompt": metadata["prompt_sha256"].(string), "response_schema": metadata["response_schema_sha256"].(string), "identity_policy": "dnd.npcs.identity.v1", "mapping_policy": mappingPolicy}
|
||||||
if len(fingerprints) != len(want) {
|
if len(fingerprints) != len(want) {
|
||||||
t.Fatalf("CheckpointFingerprints() = %#v, want %d entries", fingerprints, len(want))
|
t.Fatalf("CheckpointFingerprints() = %#v, want %d entries", fingerprints, len(want))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ const Key = "dnd/spells"
|
|||||||
const ArtifactType = "dnd.spell_cast"
|
const ArtifactType = "dnd.spell_cast"
|
||||||
const SchemaVersion = "v1"
|
const SchemaVersion = "v1"
|
||||||
|
|
||||||
|
const mappingPolicy = "dnd.spells.extract_mapping.v1"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NPCRegistryReferenceSlot = npcregistry.ReferenceSlot
|
NPCRegistryReferenceSlot = npcregistry.ReferenceSlot
|
||||||
NPCRegistryMaxBytes = npcregistry.MaxBytes
|
NPCRegistryMaxBytes = npcregistry.MaxBytes
|
||||||
@@ -127,6 +129,7 @@ func (e *Extractor) ManifestMetadata() map[string]any {
|
|||||||
"catalog_base_id": e.effectiveCatalog.BaseID(),
|
"catalog_base_id": e.effectiveCatalog.BaseID(),
|
||||||
"catalog_digest": e.effectiveCatalog.Digest(),
|
"catalog_digest": e.effectiveCatalog.Digest(),
|
||||||
"catalog_overlay_ids": e.effectiveCatalog.OverlayIDs(),
|
"catalog_overlay_ids": e.effectiveCatalog.OverlayIDs(),
|
||||||
|
"mapping_policy": mappingPolicy,
|
||||||
"response_schema_key": string(ResponseSchemaKey),
|
"response_schema_key": string(ResponseSchemaKey),
|
||||||
"response_schema_id": ResponseSchemaID,
|
"response_schema_id": ResponseSchemaID,
|
||||||
"response_schema_name": ResponseSchemaName,
|
"response_schema_name": ResponseSchemaName,
|
||||||
@@ -147,6 +150,7 @@ func (e *Extractor) CheckpointFingerprints() []pipeline.CheckpointFingerprint {
|
|||||||
}
|
}
|
||||||
fingerprints := []pipeline.CheckpointFingerprint{
|
fingerprints := []pipeline.CheckpointFingerprint{
|
||||||
{Name: "effective_catalog", Value: e.effectiveCatalog.Digest()},
|
{Name: "effective_catalog", Value: e.effectiveCatalog.Digest()},
|
||||||
|
{Name: "mapping_policy", Value: mappingPolicy},
|
||||||
{Name: "prompt", Value: e.promptSHA},
|
{Name: "prompt", Value: e.promptSHA},
|
||||||
{Name: "response_schema", Value: e.responseSchemaSHA},
|
{Name: "response_schema", Value: e.responseSchemaSHA},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ func TestExtractPromptUsesCanonicalOverlayNamesWithoutAliasesOrMetadata(t *testi
|
|||||||
}
|
}
|
||||||
|
|
||||||
metadata := newExtractor(t, &fakeSpellsLLMClient{}, overlaySpellCatalogReference()).ManifestMetadata()
|
metadata := newExtractor(t, &fakeSpellsLLMClient{}, overlaySpellCatalogReference()).ManifestMetadata()
|
||||||
|
if metadata["mapping_policy"] != mappingPolicy {
|
||||||
|
t.Fatalf("mapping policy metadata = %#v, want %q", metadata["mapping_policy"], mappingPolicy)
|
||||||
|
}
|
||||||
if metadata["catalog_base_id"] != spellcatalog.SRD5E2014ID {
|
if metadata["catalog_base_id"] != spellcatalog.SRD5E2014ID {
|
||||||
t.Fatalf("catalog base metadata = %#v", metadata["catalog_base_id"])
|
t.Fatalf("catalog base metadata = %#v", metadata["catalog_base_id"])
|
||||||
}
|
}
|
||||||
@@ -116,6 +119,7 @@ func TestExtractPromptUsesCanonicalOverlayNamesWithoutAliasesOrMetadata(t *testi
|
|||||||
fingerprints := newExtractor(t, &fakeSpellsLLMClient{}, overlaySpellCatalogReference()).CheckpointFingerprints()
|
fingerprints := newExtractor(t, &fakeSpellsLLMClient{}, overlaySpellCatalogReference()).CheckpointFingerprints()
|
||||||
wantFingerprints := map[string]any{
|
wantFingerprints := map[string]any{
|
||||||
"effective_catalog": metadata["catalog_digest"],
|
"effective_catalog": metadata["catalog_digest"],
|
||||||
|
"mapping_policy": mappingPolicy,
|
||||||
"prompt": metadata["prompt_sha256"],
|
"prompt": metadata["prompt_sha256"],
|
||||||
"response_schema": metadata["response_schema_sha256"],
|
"response_schema": metadata["response_schema_sha256"],
|
||||||
"npc_registry": checkpointFingerprintMap(newExtractor(t, &fakeSpellsLLMClient{}).CheckpointFingerprints())["npc_registry"],
|
"npc_registry": checkpointFingerprintMap(newExtractor(t, &fakeSpellsLLMClient{}).CheckpointFingerprints())["npc_registry"],
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ func TestNPCOutputGroundsSpellAndCombatConsumersThroughOneOperation(t *testing.T
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Prepare() error = %v", err)
|
t.Fatalf("Prepare() error = %v", err)
|
||||||
}
|
}
|
||||||
|
for name, value := range map[string]string{
|
||||||
|
"extract:npcs:dnd/npcs:mapping_policy": "dnd.npcs.extract_mapping.v1",
|
||||||
|
"extract:spells:dnd/spells:mapping_policy": "dnd.spells.extract_mapping.v1",
|
||||||
|
} {
|
||||||
|
assertFingerprintValue(t, prepared.CheckpointFingerprints(), name, value)
|
||||||
|
}
|
||||||
for _, name := range []string{
|
for _, name := range []string{
|
||||||
"extract:npcs:dnd/npcs:prompt",
|
"extract:npcs:dnd/npcs:prompt",
|
||||||
"extract:npcs:dnd/npcs:response_schema",
|
"extract:npcs:dnd/npcs:response_schema",
|
||||||
@@ -173,6 +179,16 @@ func TestNPCOutputGroundsSpellAndCombatConsumersThroughOneOperation(t *testing.T
|
|||||||
assertCurrentEvidence(t, combatValue.CombatTurns[0].SourceRefs)
|
assertCurrentEvidence(t, combatValue.CombatTurns[0].SourceRefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertFingerprintValue(t *testing.T, fingerprints []pipeline.CheckpointFingerprint, name, want string) {
|
||||||
|
t.Helper()
|
||||||
|
for _, fingerprint := range fingerprints {
|
||||||
|
if fingerprint.Name == name && fingerprint.Value == want {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Fatalf("fingerprints = %#v, want %q = %q", fingerprints, name, want)
|
||||||
|
}
|
||||||
|
|
||||||
func assertCurrentEvidence(t *testing.T, references []source.SourceRef) {
|
func assertCurrentEvidence(t *testing.T, references []source.SourceRef) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
for _, reference := range references {
|
for _, reference := range references {
|
||||||
|
|||||||
Reference in New Issue
Block a user