Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/platform/benchimport/resume_source.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/platform/benchimport/resume_source.go |
| Original SHA-256 | e2d28c9f074f0c5dc5c1c631842027cab84819dac02d8621ae4204073b542eb9 |
| Git blob SHA | d6232b76caa08bdc7584a8a60e9b89f9b1255140 |
| Reading-copy SHA-256 | e2d28c9f074f0c5dc5c1c631842027cab84819dac02d8621ae4204073b542eb9 |
Every recorded occurrence
These 13 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/platform/benchimport/resume_source.go | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | collision-deconfliction | 4ee5a09972608ed89f8377c6665542d5f450f0a6 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | m5-price-to-win | 41000ad30fff4129fdaf5ec84e15ba14c27d4890 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | master | 1e9249840a4302ec82e123b9c9cb6f75badea3e4 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | mag-substrate | b82c7100a492dec67dfd1eda6b3f53def859be35 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | time-to-fill-survival | b66e1e505863d4f17741a4b9ede73509e45bd6c6 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | graphrag-foundation | b0ddeb9f633fd138d09309d1a17b7d13bc3a67f7 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | ws9-bench-ingestion | f585a9ef32fa554663ce1fba9a414a54b6e49cf0 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | presentation-readiness | eb574acaa29d71ce4d0f852572e87c275c79fdb7 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | vendor-intelligence | fe9796a19c261951d3f2565206c0c1b5ac294465 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | phase2-connectors | e038d4c687aec16f8bd9bc4d907eea14d91f8704 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
| Janady13/missionmatch / internal/platform/benchimport/resume_source.go | capture-readiness | bae6af7cb2997e819174a9e9cfff5e16067a1975 | Open original |
Recovered source transcript
Download complete source text ↓192 lines · 7.8 KB
package benchimport
import (
"context"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"github.com/missionworkforce/missionmatch/internal/platform/docextract"
"github.com/missionworkforce/missionmatch/internal/platform/extraction"
)
// resumeSource is the FileSource backed by the pure Go docextract reader and the deterministic
// extraction.Extractor. It walks a directory of resume files, converts each to plain text, runs the
// offline extractor, and maps the structured RawExtraction onto a BenchRecord. No provider key, no
// network, no browser.
type resumeSource struct {
ext extraction.Extractor
}
// NewResumeSource builds a resume FileSource over the given extractor. Pass extraction.NewDeterministic()
// for the offline default.
func NewResumeSource(ext extraction.Extractor) FileSource {
return resumeSource{ext: ext}
}
// resumeExtensions are the file types the docextract reader handles. Other files in the directory are
// skipped rather than mined, so a stray archive or image never produces a garbage record.
var resumeExtensions = map[string]bool{
".pdf": true, ".docx": true, ".htm": true, ".html": true, ".txt": true,
}
// Resumes walks dir (non recursively, then one level of subdirectories so a per person folder works),
// reads each resume file, extracts its text, runs the extractor, and yields one BenchRecord per readable
// file. A file that fails to read, fails to extract, or yields no scoring signal is skipped and counted,
// never aborts the batch. Profiles is the structured path; this is the unstructured resume path.
func (s resumeSource) Resumes(ctx context.Context, dir string, yield func(rec BenchRecord, file string) error) (BatchResult, error) {
var res BatchResult
walkErr := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
ext := strings.ToLower(filepath.Ext(path))
if !resumeExtensions[ext] {
return nil
}
res.Read++
data, err := os.ReadFile(path)
if err != nil {
res.Skipped++
return nil
}
text, err := docextract.ExtractText(ctx, path, data)
if err != nil || strings.TrimSpace(text) == "" {
res.Skipped++
return nil
}
rec, ok := s.mapResume(ctx, text)
if !ok {
res.Skipped++
return nil
}
// Count a record as mapped only after yield accepts it, so a batch cap does not inflate the count.
if err := yield(rec, path); err != nil {
return err
}
res.Mapped++
return nil
})
if walkErr != nil {
return res, walkErr
}
return res, nil
}
// Profiles is the structured roster path and is not the resume reader's job. A resume source delegates
// the CSV and JSONL decode to the structured source.
func (s resumeSource) Profiles(ctx context.Context, path string, yield func(rec BenchRecord, batch string) error) (BatchResult, error) {
return structuredSource{}.Profiles(ctx, path, yield)
}
// mapResume turns extracted resume text into a BenchRecord, honoring invariant 5. The extractor yields a
// RawExtraction whose FullName is a best effort person name and whose Skills, Certifications, Agencies,
// ClearanceLevel, YearsExperience, and Location are structured tokens. The mapping places FullName ONLY on
// BenchRecord.FullName (which lands on candidates.full_name and is never embedded), derives JobTitle ONLY
// from a sanitized title gazetteer over the text (never a raw span, never a name), pulls the email ONLY
// into the dedup contact field, and carries the clearance code for triage only. A record with no scoring
// signal is rejected (ok is false) so an empty or garbage upload is not written.
func (s resumeSource) mapResume(ctx context.Context, text string) (BenchRecord, bool) {
rx, err := s.ext.ExtractResume(ctx, text)
if err != nil {
return BenchRecord{}, false
}
if !rx.HasSignal() {
return BenchRecord{}, false
}
rec := BenchRecord{
FullName: sanitizeName(rx.FullName),
Location: rx.Location,
JobTitle: detectTitle(text),
Skills: append([]string(nil), rx.Skills...),
Certs: append([]string(nil), rx.Certifications...),
Agencies: append([]string(nil), rx.Agencies...),
Years: rx.YearsExperience,
ClearanceCode: rx.ClearanceLevel,
Email: detectEmail(text),
Phone: detectPhone(text),
}
return rec, true
}
// sanitizeName trims a detected name. It is the ONLY field that may carry a person name; it lands on
// candidates.full_name and is never embedded or scored.
func sanitizeName(name string) string { return strings.TrimSpace(name) }
// reEmail and rePhone find a contact email and phone for dedup ONLY. Neither value ever reaches a job
// title, a role, a headline, or any field the embed profile composer reads (invariant 5).
var (
reEmail = regexp.MustCompile(`[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}`)
rePhone = regexp.MustCompile(`\b(?:\+?1[\s.\-]?)?\(?\d{3}\)?[\s.\-]?\d{3}[\s.\-]?\d{4}\b`)
)
func detectEmail(text string) string {
if m := reEmail.FindString(text); m != "" {
return strings.ToLower(m)
}
return ""
}
func detectPhone(text string) string { return rePhone.FindString(text) }
// titleGazetteer maps a sanitized canonical job title to the lowercased mentions that resolve to it. A
// JobTitle on a BenchRecord can ONLY be one of these canonical labels, so it is a closed sanitized
// vocabulary: a raw resume span, a name, or an email can never become a title (invariant 5). The labels
// are chosen to be useful headline anchors for the name free embed profile.
var titleGazetteer = []struct {
canonical string
mentions []string
}{
{"Intelligence Analyst", []string{"intelligence analyst", "intel analyst", "all source analyst", "sigint analyst", "geoint analyst"}},
{"Cyber Security Engineer", []string{"cyber security engineer", "cybersecurity engineer", "security engineer", "cyber engineer"}},
{"Information System Security Officer", []string{"information system security officer", "isso", "information systems security officer"}},
{"Information System Security Manager", []string{"information system security manager", "issm"}},
{"Systems Engineer", []string{"systems engineer", "system engineer"}},
{"Software Engineer", []string{"software engineer", "software developer"}},
{"Network Engineer", []string{"network engineer"}},
{"Cloud Architect", []string{"cloud architect", "solutions architect"}},
{"Data Scientist", []string{"data scientist"}},
{"Data Engineer", []string{"data engineer"}},
{"Penetration Tester", []string{"penetration tester", "pen tester"}},
{"Incident Responder", []string{"incident responder", "incident response analyst"}},
{"Program Manager", []string{"program manager"}},
{"Project Manager", []string{"project manager"}},
{"DevSecOps Engineer", []string{"devsecops engineer", "devops engineer"}},
{"COMSEC Custodian", []string{"comsec custodian"}},
}
// detectTitle returns the first canonical title whose mention appears in the lowercased text, sanitized to
// the closed vocabulary above, empty when none matches. A word boundary check keeps a short mention from
// matching inside a larger word. Because the output is always a canonical label, the title is sanitized by
// construction: a name, an email, or a raw span can never become a title.
func detectTitle(text string) string {
lower := strings.ToLower(text)
var hits []string
for _, g := range titleGazetteer {
for _, m := range g.mentions {
if wordBoundaryContains(lower, m) {
hits = append(hits, g.canonical)
break
}
}
}
if len(hits) == 0 {
return ""
}
// Sort so the chosen title is deterministic regardless of order of appearance.
sort.Strings(hits)
return hits[0]
}
// wordBoundaryContains reports whether mention appears in lower on a word boundary, so "isso" matches
// "ISSO" but not the inside of a longer token. mention is a lowercased gazetteer phrase.
func wordBoundaryContains(lower, mention string) bool {
re := regexp.MustCompile(`\b` + regexp.QuoteMeta(mention) + `\b`)
return re.MatchString(lower)
}