222 lines
6.3 KiB
Markdown
222 lines
6.3 KiB
Markdown
# Candidate Profile Ingestion Design
|
|
|
|
This spec covers the simplified first executable slice of the job discovery system: take a PDF CV and a light-template markdown profile, then produce one usable `candidate-profile.yaml` that the user can inspect and edit directly. It stops before scraping, ranking, separate `Search Preferences`, or OpenCode-driven session overrides.
|
|
|
|
## Scope
|
|
|
|
This slice must let the user:
|
|
|
|
- provide a PDF CV,
|
|
- provide a light structured markdown profile,
|
|
- run one main CLI command,
|
|
- produce one canonical normalized YAML profile,
|
|
- see warnings when CV facts and markdown intent disagree or when extraction is uncertain,
|
|
- edit the resulting YAML directly if they want to refine or correct it.
|
|
|
|
Out of scope:
|
|
|
|
- job scraping,
|
|
- ranking,
|
|
- separate saved `Search Preferences`,
|
|
- multi-step override workflows,
|
|
- hard-stop review gates,
|
|
- browser or web UI flows.
|
|
|
|
## Architecture
|
|
|
|
The design is a single-step profile normalizer.
|
|
|
|
Inputs:
|
|
|
|
- PDF CV for raw career history,
|
|
- light-template markdown profile for curated interpretation, job intent, and constraints.
|
|
|
|
Output:
|
|
|
|
- one canonical `candidate-profile.yaml`.
|
|
|
|
The trust rule is simpler than the earlier layered design: the system always writes the output file, but it never hides uncertainty. When the CV and markdown profile disagree on facts, or when extraction confidence is weak, the output YAML includes explicit warnings. The user can then edit the canonical YAML directly.
|
|
|
|
## Components
|
|
|
|
### CV Extractor
|
|
|
|
Responsibility:
|
|
|
|
- read the PDF CV,
|
|
- extract text deterministically,
|
|
- derive structured career-history candidates.
|
|
|
|
Expected fields include:
|
|
|
|
- identity basics,
|
|
- experience entries,
|
|
- education entries,
|
|
- skill mentions,
|
|
- language mentions.
|
|
|
|
Behavior:
|
|
|
|
- prefer explicit extraction over inference,
|
|
- leave uncertainty visible instead of guessing,
|
|
- use LLM assistance only when deterministic extraction is too weak to structure useful output.
|
|
|
|
### Markdown Profile Parser
|
|
|
|
Responsibility:
|
|
|
|
- read a light required markdown template,
|
|
- parse known sections into structured authored intent.
|
|
|
|
Required sections:
|
|
|
|
- `Summary`
|
|
- `Target Roles`
|
|
- `Strengths`
|
|
- `Skills To Emphasize`
|
|
- `Constraints`
|
|
- `Notes`
|
|
|
|
This file carries both durable interpretation and current job intent for the first slice.
|
|
|
|
### Profile Merger
|
|
|
|
Responsibility:
|
|
|
|
- combine CV-derived facts and markdown-derived intent,
|
|
- normalize them into one canonical profile document,
|
|
- record warnings for factual conflicts or ambiguity.
|
|
|
|
Authority rules:
|
|
|
|
- CV is the default source for raw career history,
|
|
- markdown profile is the source for interpretation, emphasis, and job intent,
|
|
- factual disagreement becomes a warning, not a blocked workflow,
|
|
- the final YAML is user-editable and becomes the local source of truth after generation.
|
|
|
|
## Data Flow
|
|
|
|
1. The user provides a PDF CV.
|
|
2. The user provides a light-template markdown profile.
|
|
3. The system extracts CV-derived structured candidates.
|
|
4. The system parses markdown-derived authored intent.
|
|
5. The system merges both into one normalized profile document.
|
|
6. The system writes `candidate-profile.yaml`.
|
|
7. The system includes warnings inside the YAML when facts conflict or extraction is uncertain.
|
|
8. The user edits `candidate-profile.yaml` directly if they want to refine the final result.
|
|
|
|
## File Layout
|
|
|
|
```text
|
|
data/
|
|
candidate-profile.yaml
|
|
```
|
|
|
|
Optional debug artifacts may be added later, but the first slice should optimize for a single obvious output file.
|
|
|
|
## Output Shape
|
|
|
|
The canonical YAML should include:
|
|
|
|
- identity and summary,
|
|
- target roles and job intent,
|
|
- skills and technologies,
|
|
- experience entries,
|
|
- education entries,
|
|
- constraints,
|
|
- notes,
|
|
- warnings.
|
|
|
|
The warnings section should be human-readable and should point out:
|
|
|
|
- factual conflicts,
|
|
- missing important fields,
|
|
- low-confidence extraction areas.
|
|
|
|
## Validation and Error Handling
|
|
|
|
### Hard Failures
|
|
|
|
These should fail immediately and avoid producing misleading output:
|
|
|
|
- unreadable or missing PDF input,
|
|
- malformed markdown template missing required headings,
|
|
- invalid command arguments.
|
|
|
|
### Non-Blocking Warnings
|
|
|
|
These should still produce `candidate-profile.yaml`:
|
|
|
|
- factual conflicts between CV and markdown profile,
|
|
- incomplete optional fields,
|
|
- low-confidence extraction,
|
|
- unclear dates or inferred experience totals.
|
|
|
|
The system must prefer explicit warnings over silent incorrect certainty.
|
|
|
|
## Command Surface
|
|
|
|
The first slice should expose one main command:
|
|
|
|
- `build-profile --cv <cv.pdf> --profile <profile.md> --out data/candidate-profile.yaml`
|
|
|
|
Optional helper commands may be added later, but they are not required for this slice.
|
|
|
|
Expected behavior:
|
|
|
|
- read both inputs,
|
|
- produce one canonical YAML file,
|
|
- print a success message,
|
|
- print whether warnings were included.
|
|
|
|
## LLM Usage Boundaries
|
|
|
|
This slice is deterministic-first.
|
|
|
|
Allowed LLM use:
|
|
|
|
- fallback structuring help when deterministic extraction alone cannot produce a usable normalized profile.
|
|
|
|
Disallowed LLM use:
|
|
|
|
- replacing deterministic extraction as the default path,
|
|
- silently deciding factual conflicts,
|
|
- acting as the only source of truth for the final persisted profile.
|
|
|
|
## Testing Strategy
|
|
|
|
The first slice should be tested around usefulness and transparency.
|
|
|
|
Core test cases:
|
|
|
|
- valid CV plus valid markdown produces `candidate-profile.yaml`,
|
|
- missing required markdown sections fails clearly,
|
|
- factual conflict still writes output and records warnings,
|
|
- final YAML contains both extracted facts and markdown intent,
|
|
- output serialization is stable and readable,
|
|
- command-line usage is repeatable.
|
|
|
|
## Acceptance Criteria
|
|
|
|
This slice is done when:
|
|
|
|
- a real PDF CV and light-template markdown profile can produce one local `candidate-profile.yaml`,
|
|
- the YAML is readable and useful enough for the user to trust and edit directly,
|
|
- factual conflicts and uncertainty appear as warnings rather than hidden behavior,
|
|
- the workflow is one obvious command rather than a multi-step state machine,
|
|
- the result is good enough to become the input to later scraping and ranking work.
|
|
|
|
## Non-Goals for This Slice
|
|
|
|
This design intentionally does not solve:
|
|
|
|
- job board integration,
|
|
- listing normalization,
|
|
- score computation,
|
|
- `Stretch Opportunity` classification,
|
|
- dismissed listing behavior,
|
|
- separate persisted `Search Preferences`,
|
|
- session-level conversational overrides.
|
|
|
|
Those belong to later slices after the system can reliably understand the candidate.
|