// Package profile parses the user's ~/.apex/config/profile.yml and renders // it as a compact markdown summary for splicing into the eval prompt. package profile import ( "fmt" "os" "strings" "gopkg.in/yaml.v3" ) type Profile struct { // Candidate.Email is intentionally not parsed: email is PII we do not want // transmitted to the eval LLM API. Same reasoning applies to phone. Candidate struct { FullName string `yaml:"full_name"` Location string `yaml:"location"` Clearance string `yaml:"clearance"` } `yaml:"candidate"` TargetRoles struct { Primary []string `yaml:"primary"` Archetypes []struct { Name string `yaml:"name"` Level string `yaml:"level"` Fit string `yaml:"fit"` } `yaml:"archetypes"` } `yaml:"target_roles"` // ProofPoints.URL is parsed but never rendered into the LLM prompt — proof // point URLs can carry tokens or session IDs. Do NOT add URL rendering // without first sanitizing or whitelisting domains. Narrative struct { Headline string `yaml:"headline"` Superpowers []string `yaml:"superpowers"` ProofPoints []struct { Name string `yaml:"name"` URL string `yaml:"url"` HeroMetric string `yaml:"hero_metric"` } `yaml:"proof_points"` } `yaml:"narrative"` Compensation struct { TargetRange string `yaml:"target_range"` Currency string `yaml:"currency"` Minimum string `yaml:"minimum"` Note string `yaml:"note"` } `yaml:"compensation"` Location struct { Country string `yaml:"country"` State string `yaml:"state"` Timezone string `yaml:"timezone"` VisaStatus string `yaml:"visa_status"` Remote struct { Preference string `yaml:"preference"` Exceptions string `yaml:"exceptions"` NotAcceptable string `yaml:"not_acceptable_for"` } `yaml:"remote"` } `yaml:"location"` DealBreakers []string `yaml:"deal_breakers"` Priorities []string `yaml:"priorities"` DreamCompanies []string `yaml:"dream_companies"` } func Load(path string) (*Profile, error) { data, err := os.ReadFile(path) if err != nil { return nil, err } var p Profile if err := yaml.Unmarshal(data, &p); err != nil { return nil, fmt.Errorf("parse profile yaml: %w", err) } return &p, nil } func (p *Profile) Render() string { if p == nil { return "" } var b strings.Builder if p.Candidate.FullName != "" { fmt.Fprintf(&b, "- **Name:** %s\n", p.Candidate.FullName) } if p.Candidate.Location != "" { fmt.Fprintf(&b, "- **Location:** %s\n", p.Candidate.Location) } if p.Candidate.Clearance != "" { fmt.Fprintf(&b, "- **Clearance:** %s\n", p.Candidate.Clearance) } if p.Compensation.TargetRange != "" || p.Compensation.Minimum != "" { b.WriteString("\n**Compensation:**\n") if p.Compensation.TargetRange != "" { fmt.Fprintf(&b, "- Target range: %s\n", p.Compensation.TargetRange) } if p.Compensation.Minimum != "" { fmt.Fprintf(&b, "- **Hard floor:** %s (score < 2.0/5 if base falls below this)\n", p.Compensation.Minimum) } if p.Compensation.Note != "" { fmt.Fprintf(&b, "- Note: %s\n", p.Compensation.Note) } } if p.Location.Remote.Preference != "" || p.Location.VisaStatus != "" { b.WriteString("\n**Location & Work Style:**\n") if p.Location.Remote.Preference != "" { fmt.Fprintf(&b, "- Remote: %s\n", p.Location.Remote.Preference) } if p.Location.Remote.Exceptions != "" { fmt.Fprintf(&b, "- Remote exceptions: %s\n", p.Location.Remote.Exceptions) } if p.Location.VisaStatus != "" { fmt.Fprintf(&b, "- Visa: %s\n", p.Location.VisaStatus) } if p.Location.Timezone != "" { fmt.Fprintf(&b, "- Timezone: %s\n", p.Location.Timezone) } } if len(p.TargetRoles.Archetypes) > 0 { b.WriteString("\n**Target Archetypes** (must match one for score >= 4.0):\n") for _, a := range p.TargetRoles.Archetypes { if a.Name == "" { continue } lvl := a.Level if lvl == "" { lvl = "-" } fmt.Fprintf(&b, "- %s (%s)\n", a.Name, lvl) } } else if len(p.TargetRoles.Primary) > 0 { b.WriteString("\n**Target Roles:**\n") for _, r := range p.TargetRoles.Primary { if r != "" { fmt.Fprintf(&b, "- %s\n", r) } } } if len(p.DealBreakers) > 0 { b.WriteString("\n**Deal-Breakers** (any match -> score <= 2.0/5):\n") for _, d := range p.DealBreakers { if d != "" { fmt.Fprintf(&b, "- %s\n", d) } } } if len(p.DreamCompanies) > 0 { b.WriteString("\n**Dream Companies** (+0.5 score bonus if match):\n") for _, c := range p.DreamCompanies { if c != "" { fmt.Fprintf(&b, "- %s\n", c) } } } if len(p.Priorities) > 0 { b.WriteString("\n**Priorities (descending):**\n") for _, pr := range p.Priorities { if pr != "" { fmt.Fprintf(&b, "- %s\n", pr) } } } if p.Narrative.Headline != "" { b.WriteString("\n**Narrative:**\n") fmt.Fprintf(&b, "- Headline: %s\n", p.Narrative.Headline) } if len(p.Narrative.Superpowers) > 0 { b.WriteString("- Superpowers:\n") for _, s := range p.Narrative.Superpowers { if s != "" { fmt.Fprintf(&b, " - %s\n", s) } } } if len(p.Narrative.ProofPoints) > 0 { b.WriteString("- Proof points:\n") for _, pp := range p.Narrative.ProofPoints { if pp.Name == "" { continue } line := " - " + pp.Name if pp.HeroMetric != "" { line += " - " + pp.HeroMetric } b.WriteString(line + "\n") } } return b.String() }