package prompts import ( "embed" "fmt" "io/fs" "sort" "strings" ) //go:embed assets/** var embeddedAssets embed.FS const ( SourceBuiltin = "builtin" AssetRoot = "assets/prompts" PromptIDModuleGlossaryRepair = "audita/modules.glossary.repair" PromptIDModuleHomophonesRepair = "audita/modules.homophones.repair" PromptIDModuleSpokenWordRepair = "audita/modules.spoken_word.repair" PromptIDModuleGrammarRepair = "audita/modules.grammar.repair" PromptIDModuleGlossaryProposal = "audita/modules.glossary.proposal" PromptIDModuleHomophonesProposal = "audita/modules.homophones.proposal" PromptIDModuleSpokenWordProposal = "audita/modules.spoken_word.proposal" PromptIDModuleGrammarProposal = "audita/modules.grammar.proposal" PromptIDValidatorSpokenFormPlausibility = "audita/validators.spoken_form_plausibility" PromptIDValidatorMeaningReversalReview = "audita/validators.meaning_reversal_review" PromptIDValidatorEditorialReview = "audita/validators.editorial_review" ) var promptIDs = []string{ PromptIDModuleGlossaryRepair, PromptIDModuleHomophonesRepair, PromptIDModuleSpokenWordRepair, PromptIDModuleGrammarRepair, PromptIDModuleGlossaryProposal, PromptIDModuleHomophonesProposal, PromptIDModuleSpokenWordProposal, PromptIDModuleGrammarProposal, PromptIDValidatorSpokenFormPlausibility, PromptIDValidatorMeaningReversalReview, PromptIDValidatorEditorialReview, } type Metadata struct { PromptID string `json:"prompt_id"` PromptSource string `json:"prompt_source"` EmbeddedPath string `json:"embedded_path"` } func (m Metadata) DiagnosticsMap() map[string]any { return map[string]any{ "prompt_id": m.PromptID, "prompt_source": m.PromptSource, "embedded_path": m.EmbeddedPath, } } // Filesystem contains the PromptKit definitions and shared instruction fragments. func Filesystem() fs.FS { return embeddedAssets } func LookupMetadata(promptID string) (Metadata, bool) { id := strings.TrimSpace(promptID) for _, known := range promptIDs { if known == id { return Metadata{PromptID: id, PromptSource: SourceBuiltin, EmbeddedPath: AssetRoot + "/" + strings.TrimPrefix(id, "audita/") + ".yaml"}, true } } return Metadata{}, false } func MustLookupMetadata(promptID string) Metadata { m, ok := LookupMetadata(promptID) if !ok { panic(fmt.Sprintf("unknown prompt id %q", promptID)) } return m } func RegisteredMetadata() []Metadata { ids := append([]string(nil), promptIDs...) sort.Strings(ids) out := make([]Metadata, 0, len(ids)) for _, id := range ids { out = append(out, MustLookupMetadata(id)) } return out } // SharedVariables supplies embedded instructions through the normal PromptKit variables. func SharedVariables() map[string]string { return map[string]string{ "HardeningPolicy": HardeningText(), "ProposalContract": sharedText("proposal_contract.md"), "RepairContract": sharedText("repair_contract.md"), "ValidationContract": sharedText("validation_contract.md"), } } // WithSharedVariables fills missing Audita instruction variables without replacing caller values. func WithSharedVariables(values map[string]string) map[string]string { result := make(map[string]string, len(values)+3) for key, value := range values { result[key] = value } for key, value := range SharedVariables() { if _, exists := result[key]; !exists { result[key] = value } } if _, exists := result["ProtectedTermsJSON"]; !exists { result["ProtectedTermsJSON"] = "[]" } return result } func HardeningText() string { return sharedText("prompt_hardening.md") } func sharedText(name string) string { raw, err := embeddedAssets.ReadFile("assets/shared/" + name) if err != nil { panic(fmt.Sprintf("read embedded prompt fragment %s: %v", name, err)) } return string(raw) }