active project
GhostSSH
GhostSSH ingests candidate evidence from GitHub, LinkedIn, and portfolio data, normalizes it into a structured candidate profile, then ranks roles through an evidence-first matching workflow. The agent loop reasons in steps, cites the evidence behind each match, and surfaces missing-evidence gaps recruiters care about.
Problem
What it solves.
Candidate evidence is scattered across GitHub, LinkedIn, and personal sites. Job-matching tools rank on keywords, not evidence. GhostSSH closes the gap by extracting structured evidence, normalizing it, and matching roles with explicit reasoning and missing-evidence callouts.
What I built
The specific parts I implemented.
What I owned
My responsibility surface.
Product direction
Frontend UI
Backend architecture
Data model
AI workflow design
Verification strategy
Architecture
How data moves through the system.
Screenshots
What the system looks like.
Agent workflow
How it reasons, chooses, and verifies.
- 01Plan: read role spec, list required evidence types (skills, projects, ownership signals).
- 02Retrieve: pull candidate evidence from normalized Postgres profile.
- 03Score: rate each requirement against evidence, with citations.
- 04Verify: cross-check claims against raw source records (commit history, README, role bullets).
- 05Decide: produce a ranked match with confidence, reasoning, and missing-evidence list.
Data model
What entities the system tracks.
- id - source - skills - projects - experience - evidence_items
- id - role_title - company - match_score - reasoning - missing_evidence - status
- id - role_match_id - event_type - timestamp - notes
Failure handling
What happens when something breaks.
Extraction fails on a profile source
Skip source, mark partial coverage, persist error in event log, continue with remaining sources.
LLM returns malformed JSON
Validate against schema; on fail, retry once with stricter prompt; if still bad, fall back to rule-based scoring.
Role spec is ambiguous
Agent emits clarification request; UI prompts the user instead of hallucinating requirements.
No evidence matches a requirement
Mark requirement as missing-evidence with severity, do not fabricate matches.
Verification
How I tested or evaluated it.
- ✓Snapshot tests on extractor output for fixture profiles.
- ✓Eval harness with hand-labeled (role, candidate) → expected match cases.
- ✓Schema validation on every LLM response with retry budget.
- ✓Per-match evidence log retained for audit.
Eval harness
Cases, expected, actual.
Strong match — full-stack AI role
pass- Input
- Candidate has React, Next.js, Python, Postgres, RAG project experience.
- Expected
- High match with reasoning tied to project evidence.
- Actual
- High match. Cited GhostSSH, ICT Knowledge Engine, Aqentix as evidence.
Partial match — Kubernetes ownership required
partial- Input
- Same candidate vs role requiring Kubernetes production ownership.
- Expected
- Partial match with explicit missing-evidence on Kubernetes.
- Actual
- Partial match. Listed Kubernetes ownership as missing-evidence with severity=high.
Hallucination guard — fabricated framework
pass- Input
- Role mentions a framework the candidate has never used.
- Expected
- Mark missing, do not invent a match.
- Actual
- Marked missing-evidence; reasoning string contained no false claim.
Next improvements
Known gaps & next moves.
- →Persistent eval dashboard with regression tracking.
- →Auth and team workspace model for shared candidate libraries.
- →Background job queue for extraction (Inngest or BullMQ).
- →Observability and per-step trace logging (OpenTelemetry).
- →Production deployment notes and runbook.