| File | Path | Loaded where? |
|---|---|---|
| cv.md | cv.md (project root) |
Already in context via opencode.json:instructions — do NOT Read again |
| _shared.md | modes/_shared.md (this file) |
Already in context via instructions |
| AGENTS.harness.md | symlink to node_modules/job-forge/AGENTS.md |
Already in context via instructions |
| article-digest.md | article-digest.md (if exists) |
Read on demand — optional detailed proof points, only when evaluating |
| profile.yml | config/profile.yml |
Read on demand — for name, contact, targets |
| templates/states.yml | canonical application states | Already in context via instructions |
RULE: Do NOT Read cv.md or modes/_shared.md from within a mode — they're already in your context. Re-Reading them pulls the same tokens into conversation history at full input cost; opencode's instructions array caches them for you.
RULE: NEVER hardcode metrics from proof points. Reference them from the already-loaded cv.md, or Read article-digest.md if you need the richer proof points.
RULE: For article/project metrics, article-digest.md takes precedence over cv.md (cv.md may have older numbers).
The skill applies with EQUAL rigor to ALL target roles. None is primary or secondary -- any is a success if comp and growth are right:
| Archetype | Thematic axes | What they buy |
|---|---|---|
| AI Platform / LLMOps Engineer | Evaluation, observability, reliability, pipelines | Someone who puts AI in production with metrics |
| Agentic Workflows / Automation | HITL, tooling, orchestration, multi-agent | Someone who builds reliable agent systems |
| Technical AI Product Manager | GenAI/Agents, PRDs, discovery, delivery | Someone who translates business to AI product |
| AI Solutions Architect | Hyperautomation, enterprise, integrations | Someone who designs end-to-end AI architectures |
| AI Forward Deployed Engineer | Client-facing, fast delivery, prototyping | Someone who delivers AI solutions to clients fast |
| AI Transformation Lead | Change management, adoption, org enablement | Someone who leads AI transformation in an org |
Concrete metrics: read from
cv.md+article-digest.mdat evaluation time. NEVER hardcode numbers here.
| If the role is... | Emphasize about the candidate... | Proof point sources |
|---|---|---|
| Platform / LLMOps | Production systems builder, observability, evals, closed-loop | article-digest.md + cv.md |
| Agentic / Automation | Multi-agent orchestration, HITL, reliability, cost | article-digest.md + cv.md |
| Technical AI PM | Product discovery, PRDs, metrics, stakeholder mgmt | cv.md + article-digest.md |
| Solutions Architect | System design, integrations, enterprise-ready | article-digest.md + cv.md |
| Forward Deployed Engineer | Fast delivery, client-facing, prototype to prod | cv.md + article-digest.md |
| AI Transformation Lead | Change management, team enablement, adoption | cv.md + article-digest.md |
Use the candidate's exit story from config/profile.yml to frame ALL content:
- In PDF Summaries: Bridge from past to future -- "Now applying the same [skill] to [JD domain]."
- In STAR stories: Reference proof points from article-digest.md
- In Draft Answers (Section G): Place the transition narrative in the first response.
- When the JD asks for "entrepreneurial", "ownership", "builder", "end-to-end": This is the #1 differentiator. Increase match weight.
Frame the candidate as a "Technical builder with real-world proof". Adapt the phrasing per archetype.
- For PM: "builder who reduces uncertainty with prototypes then productionizes with discipline."
- For FDE: "builder who delivers fast with observability and metrics from day 1."
- For SA: "builder who designs end-to-end systems with real integration experience."
- For LLMOps: "builder who puts AI in production with closed-loop quality systems."
Convert "builder" into a professional signal, not a "hobby maker". Real proof points make this credible.
If the candidate has a live demo/dashboard (check profile.yml), offer access in applications for relevant roles.
Follow this general guidance.
- Use WebSearch for current market data (Glassdoor, Levels.fyi, Blind).
- Frame by role title, not by skills — titles determine comp bands.
- Contractor rates are typically 30-50% higher than employee base to account for benefits.
- Geographic arbitrage works for remote roles: lower CoL = better net.
Salary expectations (general framework):
"Based on market data for this role, I'm targeting [RANGE from profile.yml]. I'm flexible on structure -- what matters is the total package and the opportunity."
Geographic discount pushback:
"The roles I'm competitive for are output-based, not location-based. My track record doesn't change based on postal code."
When offered below target:
"I'm comparing with opportunities in the [higher range]. I'm drawn to [company] because of [reason]. Can we explore [target]?"
In forms:
- Binary "can you be on-site?" questions: follow your actual availability from profile.yml
- In free-text fields: specify your timezone overlap and availability
In evaluations (scoring):
- Remote dimension for hybrid outside your country: score 3.0 (not 1.0)
- Only score 1.0 if JD explicitly says "must be on-site 4-5 days/week, no exceptions"
- Working demo + metrics > perfection
- Apply sooner > learn more
- 80/20 approach, timebox everything
ALL evaluation modes MUST use this exact model. Whether the offer is evaluated via offer, auto-pipeline, batch, or compared via compare, the score is computed the same way. The executable source of truth is templates/score.json; use npx job-forge score:check --input <score.json> and score:gate --gate apply when validating emitted score JSON instead of recalculating gates in prose. This ensures scores are comparable across the entire pipeline.
| # | Dimension | Weight | 1 | 3 | 5 |
|---|---|---|---|---|---|
| 1 | North Star alignment | 25% | Unrelated to any target archetype | Adjacent — transferable skills apply | Exact target archetype match |
| 2 | CV match | 15% | <40% requirements covered | 60-75% covered, gaps are soft | 90%+ covered with proof points |
| 3 | Seniority fit | 15% | Junior / 2+ levels below | Mid-senior, manageable positioning | Staff+ or exact level match |
| 4 | Comp estimate | 10% | Well below market / no data | Median for role+location | Top quartile or above target |
| 5 | Growth trajectory | 10% | Dead end, no progression path | 1-2 yr path forward, timeline unclear | Clear path to next level |
| 6 | Remote quality | 5% | On-site only, no flexibility | Hybrid 2-3 days in office | Full remote, async-friendly |
| 7 | Company reputation | 5% | Red flags, poor reviews | Average employer, neutral signals | Top employer, strong brand |
| 8 | Tech stack modernity | 5% | Legacy, no AI/ML relevance | Mix of modern and legacy tooling | Frontier AI/ML stack (LLMs, agents, evals) |
| 9 | Speed to offer | 5% | 6+ month process, bureaucratic | Standard 4-6 week process | Fast-track, <4 weeks typical |
| 10 | Cultural signals | 5% | Bureaucratic, risk-averse | Mixed signals | Builder culture, high ownership |
Final score = weighted sum, rounded to 1 decimal (e.g., 4.2/5).
Before writing any report prose, emit the score as a single JSON block. Then derive the narrative from the JSON — do NOT re-enumerate the 10 dimensions in thinking or prose. This rule exists because repeated scoring monologues are a major token-burn source: a typical eval session otherwise spends ~1,500 tokens narrating the same 10 scores two or three times.
Shape (emit exactly one block, nothing else in the block):
{
"report_num": "520",
"company": "Anthropic",
"role": "Manager, Forward Deployed Engineering",
"archetype": "AI Forward Deployed Engineer",
"url": "https://job-boards.greenhouse.io/anthropic/jobs/5099753008",
"date": "2026-04-15",
"scores": {
"north_star": { "score": 5, "rationale": "Exact FDE archetype match" },
"cv_match": { "score": 3, "rationale": "60% coverage; mgmt gap" },
"seniority_fit": { "score": 3, "rationale": "Senior IC, no formal mgmt" },
"comp": { "score": 5, "rationale": "$320-400K vs target $135-200K" },
"growth": { "score": 5, "rationale": "Founding team" },
"remote": { "score": 3, "rationale": "Hybrid, 25% in-office" },
"company": { "score": 5, "rationale": "Top AI brand" },
"stack": { "score": 5, "rationale": "Cutting-edge AI" },
"speed": { "score": 3, "rationale": "Standard process" },
"culture": { "score": 5, "rationale": "Builder culture" }
},
"weighted_total": 4.2,
"recommendation": "apply",
"pdf_threshold_met": true,
"draft_answers_threshold_met": true
}Rules:
scoreper dimension is 1-5 (integer or 0.5 step).rationaleis ≤ 80 characters, no markdown.weighted_total= round(Σ weight × score, 1). The 10 weights sum to 100% exactly.recommendation∈ {"apply"(≥3.5),"apply_with_caveats"(3.0-3.4),"skip"(<3.0)}.pdf_threshold_met⇔weighted_total ≥ 3.0.draft_answers_threshold_met⇔weighted_total ≥ 3.5.
After emitting the JSON:
- Embed the same JSON block verbatim in the report
.mdunder a## Scoresection (fenced as```json). - Save/check the emitted block when it will drive a PDF, application gate, comparison, or batch dispatch:
npx job-forge score:check --input <score.json>and, for apply decisions,npx job-forge score:gate --input <score.json> --gate apply. - Write Blocks A-F referencing the scores by key (e.g., "Seniority fit: 3/5 — Senior IC, no formal management"). Do NOT re-list all 10 dimensions in prose. Do NOT repeat the rationales verbatim.
- Do NOT narrate the scoring process in thinking before emitting the JSON. Decide, emit, move on.
Score interpretation (use consistently everywhere):
- 4.5-5.0 — Strong match. Generate PDF + draft answers. Apply promptly.
- 3.5-4.4 — Apply with tailored CV. Generate PDF + draft answers.
- 3.0-3.4 — Moderate match. Generate PDF. Flag gaps to candidate before applying.
- < 3.0 — Weak match. Report only. Explicitly discourage applying unless candidate has a specific reason.
PDF generation threshold: >= 3.0 (consistent across all modes). Draft answer threshold: >= 3.5 (consistent across all modes).
Moved: the score anchors table now lives in modes/_shared-calibration.md — Read on-demand during evaluation, NOT loaded into the global instructions prefix. This split matters because the anchors churn as you accumulate reports; keeping them out of the cached prefix means each update doesn't bust cache for every unrelated session.
Rule: right before assigning a final score, Read modes/_shared-calibration.md once (per evaluation, not per dimension) and sanity-check your score against the anchors. Do not Read it more than once per evaluation.
- Invent experience or metrics
- Modify cv.md or portfolio files
- Submit applications on behalf of the candidate
- Share phone number in generated messages
- Recommend comp below market rate
- Generate a PDF without reading the JD first
- Use corporate-speak
- Ignore the tracker (every evaluated offer gets registered)
- Use AI-hallmark words: "leveraged", "utilized", "spearheaded", "orchestrated" (as metaphor), "cutting-edge", "passionate about", "drive innovation", "synergy", "holistic approach", "navigate complex", "foster collaboration". ATS platforms flag these. Use plain, specific verbs instead.
- Cover letter: If the form has an option to attach or write a cover letter, ALWAYS include one. Generate PDF with the same visual design as the CV. Content: JD quotes mapped to proof points, links to relevant case studies. 1 page max.
- Read cv.md and article-digest.md (if exists) before evaluating any offer
1b. First evaluation of each session: Run
npx job-forge sync-checkwith Bash. If it reports warnings, notify the candidate before continuing - Detect the role archetype and adapt framing
- Cite exact lines from CV when matching
- Use WebSearch for comp and company data
- Register in tracker after evaluating
- Generate content in the language of the JD (EN default)
- Be direct and actionable -- no fluff
- When generating English text (PDF summaries, bullets, LinkedIn messages, STAR stories): native tech English, not translated. Short sentences, action verbs, no unnecessary passive voice.
8b. Case study URLs in PDF Professional Summary: If the PDF mentions case studies or demos, URLs MUST appear in the first paragraph (Professional Summary). The recruiter may only read the summary. All URLs with
white-space: nowrapin HTML. - Tracker additions as TSV -- NEVER add new entries directly to day files in
data/applications/. Write TSV inbatch/tracker-additions/andmerge-tracker.mjshandles the merge. - Include
**URL:**in every report header -- between Score and PDF.
| Tool | Use |
|---|---|
| WebSearch | Comp research, trends, company culture, LinkedIn contacts, fallback for JDs |
| WebFetch | Fallback for extracting JDs from static pages |
| Geometra MCP | Verify offers (geometra_page_model), extract JDs (geometra_connect + geometra_snapshot), fill forms (geometra_fill_form), generate PDFs (geometra_generate_pdf). The MCP server accepts up to 5 concurrent sessions, but orchestrator subagent parallelism is capped at 2 (Hard Limit #1 in AGENTS.md) — do not interpret the 5-session ceiling as permission to dispatch 5 subagents. Each geometra_connect returns a sessionId — pass it to all subsequent tool calls to target the right session. Omitting sessionId targets the most recently connected session. Use geometra_list_sessions to inspect active sessions. |
| Read | cv.md, article-digest.md, cv-template.html |
| Write | Temporary HTML for PDF, day files in data/applications/YYYY-MM-DD.md, reports .md |
| Edit | Update tracker |
| Bash | npx job-forge pdf |