// ingestion/internal/pipeline/prompt.go package pipeline import ( "fmt" "strings" "time" "github.com/mathiasbq/hyperguild/ingestion/internal/wiki" ) const systemPrompt = `You are a wiki agent. Read the source material and produce structured wiki pages following the schema provided. Output ONLY a valid JSON array — no markdown fences, no other text before or after. Each element must have exactly these fields: "title" — exact page title (e.g. "FinBERT", "Ryan Singer", "Shape Up") "type" — exactly one of: "source", "concept", "entity" "subtype" — for source: article|pdf|book|video|note|project; for entity: person|company|tool|model|framework|technology; omit for concept "domain" — one of the domains in the schema (omit if none fits) "content" — Markdown body only — NO frontmatter, NO path, NO slug Wikilinks in content: [[Display Name]] — just the display name, no slug, no pipe separator. Only link to pages listed in the inventory or pages you are creating in this response.` // BuildPrompt constructs the user prompt for a single chunk. func BuildPrompt(schema, source, content string, inventory map[wiki.PageType][]wiki.Entry) string { var sb strings.Builder fmt.Fprintf(&sb, "Today's date is %s.\n\n", time.Now().UTC().Format("2006-01-02")) sb.WriteString("## Schema\n\n") sb.WriteString(schema) sb.WriteString("\n\n") sb.WriteString("## Existing wiki pages\n\n") sb.WriteString("Reference these pages by display name only — [[Display Name]] — in your content.\n\n") for _, pt := range []wiki.PageType{wiki.PageTypeConcept, wiki.PageTypeEntity, wiki.PageTypeSource} { entries := inventory[pt] label := strings.ToUpper(string(pt)[:1]) + string(pt)[1:] if len(entries) == 0 { fmt.Fprintf(&sb, "%s — (none yet)\n\n", label) continue } fmt.Fprintf(&sb, "%s:\n", label) for _, e := range entries { fmt.Fprintf(&sb, " - %s\n", e.Title) } sb.WriteString("\n") } sb.WriteString("## Non-negotiable rules\n\n") sb.WriteString("1. Output ONLY a valid JSON array — no prose, no fences.\n") sb.WriteString("2. Fields: title, type, subtype (if applicable), domain (if applicable), content.\n") sb.WriteString("3. Wikilinks: [[Display Name]] — no slug, no pipe. The pipeline handles slugs.\n") sb.WriteString("4. Section links must match their section type (Related Concepts → concepts only, etc.).\n") sb.WriteString("5. One source page per book — if inventory shows it exists, return it as an UPDATE.\n\n") fmt.Fprintf(&sb, "## Source: %s\n\n", source) sb.WriteString(content) return sb.String() }