Snapshot: full project state

This commit is contained in:
2026-10-06 23:43:21 -07:00
commit 1551408fc5
37 changed files with 2827 additions and 0 deletions

442
tailor.py Normal file
View File

@@ -0,0 +1,442 @@
# Procyon — resume tailoring + fit scoring + cover email drafting.
# LLM-first, deterministic keyword fallback. Honest-only: never fabricates.
# Holds a resume LIBRARY (tech / hydro / driving) and combines the right
# resumes per job ("the grower who also builds" differentiator).
import os
import db
import llm
RESUME_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'resumes')
# library: track -> ordered list of resume files (first = primary)
TRACKS = {
'tech': ['tech-costco.txt', 'tech-polished.txt'],
'hydro': ['hydro-clean.txt'],
'driving': ['driving.txt'],
}
HYDRO_KW = ['hydroponic', 'horticulture', 'grower', 'cultivat', 'greenhouse', 'agricultur',
'nursery', 'botan', 'plant', 'ipm', 'irrigation', 'nutrient', 'cannabis', 'crop']
DRIVE_KW = ['delivery', 'driver', 'logistics', 'warehouse', 'forklift', 'route', 'fleet',
'dispatch', 'courier', 'cdl', 'field operations', 'shipping', 'transport']
TECH_KW = ['software', 'engineer', 'developer', 'devops', 'sysadmin', 'system admin',
'infrastructure', 'cloud', 'python', 'linux', 'it ', 'network', 'ai',
'automation', 'full-stack', 'full stack', 'backend', 'frontend', 'sre',
'platform', 'data ', 'security', 'mcp', 'llm']
def _load(name):
p = os.path.join(RESUME_DIR, name)
if os.path.exists(p):
with open(p, 'r', encoding='utf-8', errors='replace') as f:
return f.read()
return ''
def list_library():
out = []
for track, files in TRACKS.items():
for fn in files:
p = os.path.join(RESUME_DIR, fn)
out.append({'track': track, 'file': fn, 'exists': os.path.exists(p),
'chars': os.path.getsize(p) if os.path.exists(p) else 0})
return out
def classify_track(job):
"""Return the primary track for a job based on keyword density."""
text = ((job.get('title') or '') + ' ' + (job.get('description') or '')).lower()
hydro = sum(1 for k in HYDRO_KW if k in text)
drive = sum(1 for k in DRIVE_KW if k in text)
tech = sum(1 for k in TECH_KW if k in text)
# default tech when ambiguous (his primary target)
if hydro > drive and hydro >= tech and hydro > 0:
return 'hydro'
if drive > hydro and drive >= tech and drive > 0:
return 'driving'
return 'tech'
def _tech_differentiator():
"""Compact 'also a builder' block extracted from the tech resume."""
tech = _load('tech-costco.txt')
profile = ''
if '## Technical Profile' in tech:
profile = tech.split('## Technical Profile', 1)[1].split('## Core Engineering', 1)[0]
return ('\n\n## Technical Differentiator\n\n'
f"Beyond cultivation, I'm a self-taught full-stack developer and infrastructure "
f"engineer who builds the software and sensor hardware that modern growing "
f"operations run on (see hydro.thetempleofdoom.com).\n{profile.strip()}")
def build_master(job):
"""Select + combine the right resumes. Returns (tracks_used, combined_text)."""
track = classify_track(job)
tracks = [track]
if track == 'hydro':
text = _load('hydro-clean.txt') + _tech_differentiator()
tracks.append('tech')
elif track == 'driving':
text = _load('driving.txt')
# if the role has a meaningful tech/ops slant, fold in the tech profile
jt = ((job.get('title') or '') + ' ' + (job.get('description') or '')).lower()
if sum(1 for k in TECH_KW if k in jt) >= 2:
text += _tech_differentiator()
tracks.append('tech')
else:
text = _load('tech-costco.txt')
if not text.strip():
text = _load('tech-polished.txt')
# single-resume override (Settings) takes precedence
override = db.get_setting('master_resume', '')
if override and os.path.exists(override):
with open(override, 'r', encoding='utf-8', errors='replace') as f:
return ['custom'], f.read()
# always append the canonical work history so tailoring has the full verified record
wh = _load('work-history.txt')
if wh:
text += '\n\n## WORK HISTORY (verified facts)\n' + wh
return tracks, text
def score_job(job):
"""Return (score 0..1, opinion string)."""
desc = job.get('description') or ''
title = job.get('title') or ''
company = job.get('company') or ''
track = classify_track(job)
prompt = (
f"Score how well this job fits a self-taught full-stack developer and self-hosted "
f"infrastructure engineer (Python, Flask, Linux, Proxmox, Docker, networking, "
f"automation, LLM/agent tooling). Candidate track: {track}. Return JSON: "
f"{{\"score\": <0.0 to 1.0>, \"opinion\": \"<one sentence why>\", "
f"\"top_skills\": [\"..\"]}}\n\n"
f"Job title: {title}\nCompany: {company}\n\n{desc[:3000]}"
)
data = llm.llm_json(prompt)
if data and isinstance(data, dict) and 'score' in data:
try:
score = float(data['score'])
except (TypeError, ValueError):
score = 0.5
return round(max(0.0, min(1.0, score)), 3), str(data.get('opinion', ''))
score, opinion = llm.keyword_score(desc)
return score, opinion
def tailor_resume(job):
"""Tailor the combined master resume for a specific job. Returns tailored text."""
tracks, master = build_master(job)
title = job.get('title') or ''
company = job.get('company') or ''
desc = (job.get('description') or '')[:3000]
prompt = (
f"Rewrite this resume to target the role '{title}' at {company}. "
"Keep every fact identical — same employers, titles, dates, skills, credentials. "
"Only reorder sections to surface the most relevant experience first and rephrase bullet "
"points to echo the job description's own terminology WITHOUT inventing anything. "
"Do not add skills the candidate doesn't have. Do NOT add a 'Targeting' header or any "
"meta-commentary — it should read like a normal resume.\n\n"
f"JOB DESCRIPTION:\n{desc}\n\nMASTER RESUME (combined tracks: {', '.join(tracks)}):\n{master}"
)
tailored = llm.llm_chat(prompt)
if tailored:
return tailored
# keyword fallback: keep master intact (no fabricated targeting header)
return master
def draft_email(job, tailored_resume, research=''):
"""Draft a tailored outreach email. No fabrication; human, specific, natural voice."""
title = job.get('title') or 'the role'
company = job.get('company') or 'your team'
from_name = db.get_setting('from_name', 'Indiana Holmes')
phone = db.get_setting('resume_phone', '')
email = db.get_setting('resume_email', '')
website = db.get_setting('website', 'https://thetempleofdoom.com').strip()
research_hint = ''
if research:
research_hint = (
f"\n\nCOMPANY CONTEXT (weave ONE natural, specific reference into the body — show "
f"you actually looked at what they do; do NOT lead with it or recite it like a "
f"fact sheet):\n{research[:1200]}\n"
)
prompt = (
f"You are {from_name}, a self-taught full-stack developer and infrastructure engineer "
f"based in Seattle, WA. You are applying to {company} for the '{title}' role as an "
f"EXTERNAL candidate — you have NEVER worked at {company}, and you do NOT currently "
f"hold this role or any role there. Your only real experience is what is in the "
f"TAILORED RESUME below.\n\n"
f"Write a short, warm, plain-spoken cold-application email for that role. It should read "
f"like a real person wrote it quickly and confidently — not a template and not "
f"AI-sounding. Rules:\n"
"- 2-3 short paragraphs, varied sentence length, concrete and specific.\n"
"- NO buzzwords and NO cliche phrases: 'I am writing to', 'I hope this email finds you "
"well', 'I would welcome', 'I am excited to', 'passionate about', 'I believe', "
"'leverage', 'delve', 'synergy'. Avoid em-dashes and semicolons.\n"
"- Open naturally with a specific reason this role caught your eye, then name the TWO "
"strongest RELEVANT qualifications from the resume in plain concrete terms, then a "
"short direct close.\n"
"- If a COMPANY CONTEXT block is present, reference ONE specific fact about the company "
"as something you've noticed about THEM (e.g. 'I've been following FreedomPay's work in "
"payments'), NOT as your own employment. NEVER claim or imply you currently work at "
f"{company}, have ever worked at {company}, or currently hold the '{title}' role.\n"
"- Do NOT invent any employer, job title, date, skill, or metric that is not in the "
"resume. If the resume does not support a claim, do not make it.\n"
"- End with a short direct closing line. Do NOT include your name, phone number, email, "
"or website — the signature is appended automatically.\n"
"- Return ONLY the email body text (no subject line, no preamble).\n\n"
f"TAILORED RESUME:\n{tailored_resume[:4000]}"
f"{research_hint}"
)
body = llm.llm_chat(prompt)
body = _clean(body)
if body and not _looks_fabricated(body, company, title):
return _append_signature(body, from_name, phone, email, website)
return (
f"Hello,\n\n"
f"I came across the {title} opening at {company} and it lines up well with what I do. "
f"I'm a self-taught full-stack developer and infrastructure engineer — I build and run "
f"Python/Flask services, Linux servers, Proxmox virtualization, Docker, and agent/LLM "
f"tooling on hardware I operate myself.\n\n"
f"If you're open to it, I'd like to talk about how that hands-on background fits the "
f"team.\n\n"
f"Thanks,\n{from_name}\n{phone}\n{email}\n{website}"
)
def _append_signature(body, from_name, phone, email, website):
"""Deterministically append the signature block. The model reliably drops it, so
never trust it to sign its own output. Skips if a signature is already present."""
if (website and website in body) or (email and email in body):
return body
sig = f"{from_name}\n{phone}\n{email}\n{website}"
return (body.rstrip() + f"\n\n{sig}").strip()
def _clean(body):
"""Strip broken-tokenizer artifacts and a leading 'Subject:' line from LLM output.
The local models intermittently leak `<unusedNN>` / `????` tokens; if nothing
usable remains, return '' so the caller falls back to the safe template."""
import re
if not body:
return ''
body = re.sub(r'<unused\d+>', '', body)
body = re.sub(r'^[\s?]+', '', body)
lines = body.splitlines()
while lines and lines[0].strip().lower().startswith('subject:'):
lines = lines[1:]
cleaned = '\n'.join(lines).strip()
# if after cleanup it's essentially empty or pure punctuation, treat as garbage
if not cleaned or not any(ch.isalnum() for ch in cleaned):
return ''
return cleaned
def _looks_fabricated(body, company, title):
"""Deterministic guard: reject LLM output that claims the candidate currently
works at the target company or already holds the applied-for role (weak-model
hallucination). Returns True if the body looks fabricated."""
if not body:
return True
low = body.lower()
c = (company or '').lower().strip()
t = (title or '').lower().strip()
markers = ['right now i ', 'i currently ', 'currently work', "i'm currently",
'i am currently', 'i joined ', 'my role at', 'i work at', 'i own the ',
"i've been at ", 'i lead the ', 'i manage the ']
hits = [m for m in markers if m in low]
# present-tense claim tying the candidate to the company/title
if c and c in low:
for phrase in (f'at {c} where i', f'at {c}, where i', f'working at {c}',
f'i am a {t} at {c}', f"i'm a {t} at {c}"):
if phrase in low:
hits.append(phrase)
return bool(hits)
def make_subject(job):
title = job.get('title') or 'Open Role'
company = job.get('company') or ''
return f"Application: {title}" + (f" — {company}" if company else "")
# ===================== structured one-page resume =====================
# Verified facts only (from work-history.txt). Renders to a one-page PDF.
EXPERIENCE = [
{'title': 'Water System Technician', 'company': 'Northwest Water Systems Inc',
'dates': '2025', 'tracks': ['tech', 'driving'],
'bullets': [
'Maintained 45 pump houses across WA — install, repair, and troubleshoot water treatment & distribution infrastructure.',
'Field inspections, EPA-standard water sampling, emergency response, and compliance documentation.',
'Operated pumps, filtration, and chemical-dosing equipment.']},
{'title': 'Lead Field Operations Specialist', 'company': 'Lime',
'dates': '2023 – 2025', 'tracks': ['tech', 'driving'],
'bullets': [
'Led daily field operations to keep the scooter/bike fleet available; supervised 5 field agents.',
'Coordinated dispatch logistics, GPS-based asset recovery, and route optimization.',
'Repaired and replaced vehicle parts; directed drivers via two-way radio.']},
{'title': 'Master Grower / Cultivation Manager', 'company': 'Los Angeles, CA (controlled-environment agriculture)',
'dates': '2014 – 2023', 'tracks': ['hydro'],
'bullets': [
'Managed full cultivation cycles (propagation → harvest) and designed custom hydroponic systems.',
'Developed nutrient programs; maintained lighting, humidity, airflow, and temperature control.',
'Implemented integrated pest management; trained and supervised growers.']},
{'title': 'Lead Service Representative', 'company': 'LabCorp',
'dates': '2022 – 2023', 'tracks': ['driving', 'tech'],
'bullets': [
'Ran daily medical specimen pickup routes across hospitals and clinics with strict regulatory compliance.',
'Coordinated emergency pickups and route adjustments with dispatch.']},
{'title': 'Field Operations / Warehouse Specialist', 'company': 'Aboda',
'dates': '2019 – 2022', 'tracks': ['driving', 'tech'],
'bullets': [
'Managed logistics and setup for corporate housing units across Seattle and Bellevue.',
'Operated forklifts; maintained warehouse inventory and move-in-ready quality inspections.']},
{'title': 'Sales Manager', 'company': 'Mission Motors',
'dates': '2017 – 2019', 'tracks': ['driving'],
'bullets': ['Managed vehicle inventory and sales; guided customers through the full purchase process.']},
{'title': 'Logistics Coordinator', 'company': 'Salt Works',
'dates': '2012', 'tracks': ['driving'],
'bullets': ['Loaded pallets into shipping containers and box trucks; operated forklift and cherry picker.']},
]
PROJECTS = [
{'title': 'Self-Hosted Infrastructure (Proxmox homelab)',
'bullets': [
'Operate a multi-node Proxmox cluster running AI services, databases, websites, and automation.',
'Built a self-hosted SaaS ecosystem (Git, automation, cloud storage) with secure remote access.']},
{'title': 'AI Automation & Local LLM Pipelines',
'bullets': [
'Built local-LLM agent workflows and MCP integrations for research, monitoring, and data processing.']},
{'title': 'Embedded & RF Systems (ESP32, LoRa / Meshtastic)',
'bullets': [
'Engineered ESP32 telemetry and sensor devices with custom firmware; built LoRa/Meshtastic mesh networks.']},
]
SUMMARIES = {
'tech': 'Self-taught full-stack and embedded systems engineer who builds across the entire stack — '
'Python/Flask backends, Linux/Docker/Proxmox infrastructure, ESP32 firmware for embedded devices, '
'LoRa/Meshtastic mesh networks, and local AI/LLM agent tooling — on hardware I design and operate myself.',
'hydro': 'Self-taught horticulture specialist with 14+ years in hydroponics and controlled-environment '
'agriculture — custom grow systems, plant nutrition, environmental control, and high-yield production.',
'driving': 'Reliable logistics and field-operations professional with extensive route-driving, fleet, and '
'warehouse experience — safety-focused with strong dispatch coordination and problem-solving.',
}
SKILLS = {
'tech': ['Embedded firmware (ESP32)', 'LoRa / Meshtastic mesh networks', 'Embedded systems design',
'Python', 'Bash', 'Proxmox / virtualization', 'Linux administration', 'Docker',
'Networking / SSH / VPN', 'REST APIs', 'Git', 'AI / LLM infrastructure',
'Agent & MCP development', 'Monitoring / Grafana', 'Automation pipelines'],
'hydro': ['Hydroponic system design', 'Plant propagation', 'Nutrient programs', 'IPM',
'Environmental control', 'Grow-facility design', 'Grower training',
'Plant-health troubleshooting'],
'driving': ['Route driving & delivery', 'Forklift (certified)', 'Fleet tracking & recovery',
'Warehouse inventory', 'Field operations', 'GPS route optimization',
'Dispatch coordination', 'Customer service'],
}
EDUCATION = 'Lake Stevens High School — Diploma (Computer Applications & Technology)'
TRACK_HEADLINES = {
'tech': 'Full-Stack & Embedded Systems Engineer',
'hydro': 'Hydroponics & Controlled-Environment Agriculture Specialist',
'driving': 'Logistics & Field Operations Professional',
}
def _deterministic_structured(track, job):
"""Deterministic one-page structured resume from verified facts (no LLM)."""
headline = TRACK_HEADLINES.get(track, TRACK_HEADLINES['tech'])
exp = [e for e in EXPERIENCE if track in e['tracks']]
resume = {
'contact': 'Seattle, WA | 425-280-0023 | indianaholmes1@icloud.com',
'headline': headline,
'summary': SUMMARIES.get(track, SUMMARIES['tech']),
'skills': SKILLS.get(track, SKILLS['tech']),
'experience': exp,
'education': EDUCATION,
}
if track == 'tech':
resume['projects'] = PROJECTS
return resume
def structured_resume(job):
"""Deterministic one-page resume from verified facts. (Was LLM-first, but the JSON
generation call was slow under MacBook memory pressure and its failure tripped the
circuit breaker — blocking the email draft, which is the call that actually matters.
The deterministic path is honest and clean, so use it exclusively.)"""
track = classify_track(job)
return _deterministic_structured(track, job)
def structured_to_text(resume):
"""Render a structured resume dict to readable plain text (for display + audit)."""
lines = []
if resume.get('headline'):
lines.append(resume['headline'])
if resume.get('summary'):
lines.append(resume['summary'])
if resume.get('skills'):
lines.append('\nSKILLS: ' + ' • '.join(resume['skills']))
if resume.get('experience'):
lines.append('\nEXPERIENCE:')
for e in resume['experience']:
lines.append(f" {e.get('title')} — {e.get('company')} ({e.get('dates')})")
for b in e.get('bullets', []):
lines.append(f" - {b}")
if resume.get('projects'):
lines.append('\nPROJECTS:')
for p in resume['projects']:
lines.append(f" {p.get('title')}")
for b in p.get('bullets', []):
lines.append(f" - {b}")
if resume.get('education'):
lines.append('\nEDUCATION: ' + resume['education'])
return '\n'.join(lines)
# ---- ATS optimization & gap analysis (quality steps) ----
def extract_job_keywords(description, top_n=15):
"""Extract the most signal-bearing keywords from a job description."""
import re as _re
if not description:
return []
d = description.lower()
freq = {}
for kw in llm._skill_keywords():
if kw in d:
freq[kw] = d.count(kw)
# capitalized technical terms (e.g. "Kubernetes", "AWS", "Terraform")
for m in _re.findall(r'\b[A-Z][A-Za-z0-9+#./]{2,}\b', description):
k = m.lower()
if k not in freq and len(k) >= 3:
freq[k] = description.lower().count(k)
ranked = sorted(freq.items(), key=lambda x: -x[1])
return [k for k, _ in ranked[:top_n]]
def ats_coverage(text, keywords):
"""Return (coverage 0..1, keywords, missing_keywords) for ATS matching."""
if not keywords:
return 1.0, [], []
t = (text or '').lower()
missing = [k for k in keywords if k.lower() not in t]
hit = len(keywords) - len(missing)
return round(hit / len(keywords), 3), keywords, missing
def candidate_gaps(job):
"""Job keywords absent from the candidate's skill surface -> honest fit gaps."""
desc = (job.get('description') or '') + ' ' + (job.get('title') or '')
kws = extract_job_keywords(desc, top_n=12)
_tracks, master = build_master(job)
cov, _kws, missing = ats_coverage(master, kws)
return {'keywords': kws, 'missing': missing, 'coverage': cov}