Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/ai/mission.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/ai/mission.go |
| Original SHA-256 | 1617981eeabc906ddc5c7cbecc80a21bc783b76e30a0dabeb85a68e060082f15 |
| Git blob SHA | 93998f6463704015c7a67905708ad64f532033ba |
| Reading-copy SHA-256 | 1617981eeabc906ddc5c7cbecc80a21bc783b76e30a0dabeb85a68e060082f15 |
Every recorded occurrence
These 15 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / internal/modules/ai/mission.go | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | ws8-teaching-loop | c823f0fb6bb2aba0f39001eb6de96f4000d9321f | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | ws9-bench-ingestion | f585a9ef32fa554663ce1fba9a414a54b6e49cf0 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | vendor-intelligence | fe9796a19c261951d3f2565206c0c1b5ac294465 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | ws7-federal-signal | 6a9f6ce9cfb13345ffb47770d4960e7c2d9c17c2 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / internal/modules/ai/mission.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
Recovered source transcript
Download complete source text ↓102 lines · 5.4 KB
package ai
import (
"regexp"
"strings"
)
// Mission scoping (WS6 Option A). A RAG question can name a mission area (SIGINT, GEOINT, ...). When it
// does, the retrieval is constrained to candidates whose full_name, headline, or location text matches
// that mission keyword, using the existing full text index (search_tsv). This is the ONLY mission filter
// available without structured mission tags on candidates and requirements, which are WS7 work: it filters
// on that candidate TEXT, not on a semantic mission alignment, and not on the resume body. The limit is
// documented in docs/AI_RESEARCH.md.
//
// The vocabulary mirrors the curated mission_spine seed (migration 0021_ontology.sql), which is the
// source of truth. The ten terms change rarely and are controlled IC vocabulary, so mirroring them in
// code (rather than a database round trip on every question) keeps retrieval deterministic and avoids a
// dependency from the AI path onto a reference query. If mission_spine grows, extend this list to match.
// missionPattern pairs the canonical full text keyword fed to websearch_to_tsquery with the natural
// language forms a user might type. Acronyms and short tokens are matched on a word boundary so a bare
// acronym never matches inside another word.
type missionPattern struct {
canonical string // the keyword passed to the mission scoped query ($mission_query)
forms []*regexp.Regexp // question phrasings that select this mission
}
// wb compiles a case insensitive, word boundary anchored matcher for a mission form. Any single space in a
// multi word form becomes \s+, so a line break or a double space between phrase tokens still matches (for
// example "satellite command and control"). The forms contain no regex metacharacters, so the literal is
// safe to embed directly.
func wb(s string) *regexp.Regexp {
return regexp.MustCompile(`(?i)\b` + strings.ReplaceAll(s, " ", `\s+`) + `\b`)
}
// missionVocabulary is iterated in mission_spine order, so when a question names more than one mission the
// result is deterministic (the earliest spine term wins). Order MUST match migration 0021.
var missionVocabulary = []missionPattern{
{"SIGINT", []*regexp.Regexp{wb("sigint"), wb("signals intelligence")}},
{"GEOINT", []*regexp.Regexp{wb("geoint"), wb("geospatial intelligence")}},
{"HUMINT", []*regexp.Regexp{wb("humint"), wb("human intelligence")}},
{"MASINT", []*regexp.Regexp{wb("masint"), wb("measurement and signature intelligence")}},
{"OSINT", []*regexp.Regexp{wb("osint"), wb("open source intelligence")}},
{"Satellite C2", []*regexp.Regexp{wb("satellite c2"), wb("satellite command and control")}},
{"Cross Domain Solution", []*regexp.Regexp{wb("cross domain solution"), wb("cross domain solutions")}},
{"COMSEC", []*regexp.Regexp{wb("comsec"), wb("communications security")}},
{"TEMPEST", []*regexp.Regexp{wb("tempest")}},
{"Electronic Warfare", []*regexp.Regexp{wb("electronic warfare")}},
}
// MissionFromQuestion returns the canonical mission keyword named in the question, or "" if none is named.
// The returned value is drawn only from the fixed mission vocabulary above, never from free user text, so
// it can never carry a demographic reference into the retrieval path.
func MissionFromQuestion(question string) string {
if question == "" {
return ""
}
for _, m := range missionVocabulary {
for _, form := range m.forms {
if form.MatchString(question) {
return m.canonical
}
}
}
return ""
}
// missionTermToCode maps the canonical mission TERM that missionVocabulary uses (and that
// MissionFromQuestion returns) to the stable mission CODE that candidate_mission_tags.mission_code keys on.
// The codes mirror the mission_areas table (migration 0025) and missionclass.Codes; the multi word terms map
// to their short codes (Satellite C2 to SAT_C2, Cross Domain Solution to CDS, Electronic Warfare to EW). For
// the acronym missions the term already equals the code. The AI package keeps its own copy rather than
// importing missionclass so the retrieval path takes no dependency on the classifier package; a drift here is
// caught by the unit test below, which covers all ten terms.
var missionTermToCode = map[string]string{
"SIGINT": "SIGINT",
"GEOINT": "GEOINT",
"HUMINT": "HUMINT",
"MASINT": "MASINT",
"OSINT": "OSINT",
"Satellite C2": "SAT_C2",
"Cross Domain Solution": "CDS",
"COMSEC": "COMSEC",
"TEMPEST": "TEMPEST",
"Electronic Warfare": "EW",
}
// MissionCodeForTerm maps a canonical mission term (the value MissionFromQuestion returns) to its mission
// CODE, or "" when the term is not a known mission. It is the bridge from the WS6 keyword the retrieval leg
// already carries to the structured candidate_mission_tags.mission_code that the WS7 tagged query gates on.
func MissionCodeForTerm(term string) string {
return missionTermToCode[term]
}
// MissionCodeFromQuestion returns the structured mission CODE named in the question, or "" if none is named.
// It detects the mission exactly as MissionFromQuestion does (the same fixed vocabulary, the same word
// boundary forms, the same deterministic first match order) and maps the resulting term to its code. Like
// MissionFromQuestion, the result is drawn only from the fixed vocabulary, never from free user text.
func MissionCodeFromQuestion(question string) string {
return MissionCodeForTerm(MissionFromQuestion(question))
}