package matching import ( "github.com/missionworkforce/missionmatch/internal/modules/governance" "github.com/missionworkforce/missionmatch/internal/modules/matching/engine" ) // Recommendation is the derived Mission Check advisory: SUBMIT, REVIEW, or DO NOT SUBMIT. It is a PURE // derivation of the engine Band, adds no scoring, and is always advisory. A human makes the final call, // so the recommendation never auto rejects anyone, it only summarizes the band in proposal language. type Recommendation struct { Value string `json:"value"` Reason string `json:"reason"` } // The three advisory values. DO NOT SUBMIT is a derived label on top of the Red band, not a fourth // band, so the displayed Mission Readiness band stays identical to every other surface. const ( RecSubmit = "SUBMIT" RecReview = "REVIEW" RecDoNotSubmit = "DO NOT SUBMIT" ) // RecommendFromBand maps the engine band to the advisory: Green to SUBMIT, Yellow to REVIEW, Red to // DO NOT SUBMIT. It is the single place the mapping lives so it stays consistent across both modes. func RecommendFromBand(b engine.Band) Recommendation { switch b { case engine.BandGreen: return Recommendation{Value: RecSubmit, Reason: "Green band, proposal ready"} case engine.BandYellow: return Recommendation{Value: RecReview, Reason: "Yellow band, review gaps before submission"} default: return Recommendation{Value: RecDoNotSubmit, Reason: "Red band, recruiting required"} } } // recommendFromBandCode derives the advisory from a persisted band code (green, yellow, red), defaulting // to the Red advisory on an unrecognized code so an unknown band never reads as a recommendation to bid. func recommendFromBandCode(code string) Recommendation { b, err := engine.ParseBand(code) if err != nil { b = engine.BandRed } return RecommendFromBand(b) } // MissionCheckFitRow is one ranked Mode A opportunity (the shared OpportunityFitView) plus the derived // advisory recommendation for that opportunity. type MissionCheckFitRow struct { OpportunityFitView Recommendation string `json:"recommendation"` RecommendationReason string `json:"recommendation_reason"` } // ParsedCandidate is the structured field set the extractor proposed from the resume. It is surfaced in // the result so the user can SEE what was parsed and Save it as a candidate. Clearance fields are DB // codes; every value is a self reported parse the user reviews, never a verified fact. type ParsedCandidate struct { FullName string `json:"full_name"` ClearanceLevel string `json:"clearance_level"` ClearancePoly string `json:"clearance_poly"` ClearanceStatus string `json:"clearance_status"` YearsExperience int `json:"years_experience"` Location string `json:"location"` Skills []string `json:"skills"` Certifications []string `json:"certifications"` CustomerExperience []string `json:"customer_experience"` } // MissionCheckModeAResult is the Mode A response: an in memory resume scored against every open // opportunity, ranked, with the parsed candidate, the surfaced assumptions, and the AEDT disclosure. type MissionCheckModeAResult struct { Rows []MissionCheckFitRow `json:"rows"` Candidate ParsedCandidate `json:"candidate"` Assumptions []string `json:"assumptions"` DataCategories []string `json:"data_categories"` } // ParsedRequirement is the requirement the JD parsed to, surfaced so the Mode B result panel reflects // the job description that was actually scored rather than a placeholder. Required level is a DB code. type ParsedRequirement struct { Title string `json:"title"` RequiredLevel string `json:"required_level"` CustomerAgency string `json:"customer_agency"` KeyPersonnel bool `json:"key_personnel"` } // MissionCheckModeBResult is the Mode B response: an in memory resume scored against one pasted job // description. View is the EXACT ScreenView shape POST /screen returns, so the result renders // identically and the Mission Readiness value ties out to every other surface. type MissionCheckModeBResult struct { View ScreenView `json:"view"` Recommendation string `json:"recommendation"` RecommendationReason string `json:"recommendation_reason"` Candidate ParsedCandidate `json:"candidate"` Requirement ParsedRequirement `json:"requirement"` Assumptions []string `json:"assumptions"` DataCategories []string `json:"data_categories"` } // missionCheckAssumptions are the explicit assumptions behind a Mission Check score, surfaced in the // result so the advisory output is honest about what it inferred and never verified. var missionCheckAssumptions = []string{ "assumed available for evaluation", "clearance is a self reported indicator, not verified", } // missionCheckDataCategories is the AEDT disclosure list, the single governance source of truth, so the // in modal notice names exactly the data the tool assesses. None of these is a demographic attribute. var missionCheckDataCategories = governance.DefaultDataCategories