job-forge 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codex/config.toml +8 -0
- package/.cursor/mcp.json +21 -0
- package/.cursor/rules/main.mdc +519 -0
- package/.mcp.json +21 -0
- package/.opencode/agents/general-free.md +85 -0
- package/.opencode/agents/general-paid.md +39 -0
- package/.opencode/agents/glm-minimal.md +50 -0
- package/.opencode/skills/job-forge.md +185 -0
- package/AGENTS.md +514 -0
- package/CLAUDE.md +514 -0
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/batch/README.md +60 -0
- package/batch/batch-prompt.md +399 -0
- package/batch/batch-runner.sh +673 -0
- package/bin/create-job-forge.mjs +375 -0
- package/bin/job-forge.mjs +120 -0
- package/bin/sync.mjs +141 -0
- package/config/profile.example.yml +67 -0
- package/cv-sync-check.mjs +128 -0
- package/dedup-tracker.mjs +201 -0
- package/docs/ARCHITECTURE.md +220 -0
- package/docs/CUSTOMIZATION.md +101 -0
- package/docs/MODEL-ROUTING.md +195 -0
- package/docs/README.md +54 -0
- package/docs/SETUP.md +186 -0
- package/docs/demo.gif +0 -0
- package/fonts/dm-sans-latin-ext.woff2 +0 -0
- package/fonts/dm-sans-latin.woff2 +0 -0
- package/fonts/space-grotesk-latin-ext.woff2 +0 -0
- package/fonts/space-grotesk-latin.woff2 +0 -0
- package/generate-pdf.mjs +168 -0
- package/iso/agents/general-free.md +90 -0
- package/iso/agents/general-paid.md +44 -0
- package/iso/agents/glm-minimal.md +55 -0
- package/iso/commands/job-forge.md +188 -0
- package/iso/config.json +7 -0
- package/iso/instructions.md +514 -0
- package/iso/mcp.json +15 -0
- package/merge-tracker.mjs +377 -0
- package/modes/README.md +30 -0
- package/modes/_shared-calibration.md +26 -0
- package/modes/_shared.md +272 -0
- package/modes/apply.md +257 -0
- package/modes/auto-pipeline.md +70 -0
- package/modes/batch.md +110 -0
- package/modes/compare.md +23 -0
- package/modes/contact.md +82 -0
- package/modes/deep.md +99 -0
- package/modes/followup.md +68 -0
- package/modes/negotiation.md +146 -0
- package/modes/offer.md +199 -0
- package/modes/pdf.md +121 -0
- package/modes/pipeline.md +83 -0
- package/modes/project.md +30 -0
- package/modes/rejection.md +92 -0
- package/modes/scan.md +185 -0
- package/modes/tracker.md +31 -0
- package/modes/training.md +27 -0
- package/normalize-statuses.mjs +152 -0
- package/opencode.json +28 -0
- package/package.json +78 -0
- package/scripts/add-tags.mjs +894 -0
- package/scripts/cursor-agent-loop.sh +211 -0
- package/scripts/cursor-agent-stream-format.py +134 -0
- package/scripts/next-num.mjs +33 -0
- package/scripts/release/check-source.mjs +37 -0
- package/scripts/render-report-header.mjs +78 -0
- package/scripts/session-report.mjs +129 -0
- package/scripts/slugify.mjs +27 -0
- package/scripts/today.mjs +20 -0
- package/scripts/token-usage-report.mjs +315 -0
- package/scripts/tracker-line.mjs +67 -0
- package/scripts/verify-greenhouse-urls.mjs +195 -0
- package/templates/cv-template.html +395 -0
- package/templates/portals.example.yml +3140 -0
- package/templates/states.yml +62 -0
- package/tracker-lib.mjs +257 -0
- package/verify-pipeline.mjs +267 -0
package/modes/offer.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Mode: offer — Full Evaluation A-F
|
|
2
|
+
|
|
3
|
+
When the candidate pastes an offer (text or URL), ALWAYS deliver all 6 blocks:
|
|
4
|
+
|
|
5
|
+
## Emit-once rule — REQUIRED
|
|
6
|
+
|
|
7
|
+
Before writing any of the blocks below, **emit the Score JSON block first** (per `_shared.md` → "Score Emission — EMIT-ONCE JSON"). The blocks that follow reference the JSON's score keys and rationales; they do NOT re-enumerate the 10 dimensions.
|
|
8
|
+
|
|
9
|
+
Workflow:
|
|
10
|
+
|
|
11
|
+
1. Detect archetype (Step 0 below).
|
|
12
|
+
2. `cv.md` is already in your context via `opencode.json:instructions` — **do NOT Read it again**. If you need detailed proof points beyond cv.md, Read `article-digest.md` (if it exists) — once, not per block.
|
|
13
|
+
3. Decide the 10 scores. **Do not narrate this process in thinking.** Write the scores straight into the JSON block.
|
|
14
|
+
4. Emit the JSON block exactly once.
|
|
15
|
+
5. Then write Blocks A-F referencing the JSON — not parallel to it.
|
|
16
|
+
|
|
17
|
+
Re-scoring mid-report is banned. If you change your mind on a dimension, update the JSON and regenerate the prose from it — don't keep two copies in sync.
|
|
18
|
+
|
|
19
|
+
## Step 0 — Archetype Detection
|
|
20
|
+
|
|
21
|
+
Classify the offer into one of the 6 archetypes (see `_shared.md`). If it's a hybrid, indicate the 2 closest ones. This determines:
|
|
22
|
+
- Which proof points to prioritize in block B
|
|
23
|
+
- How to rewrite the summary in block E
|
|
24
|
+
- Which STAR stories to prepare in block F
|
|
25
|
+
|
|
26
|
+
## Block A — Role Summary
|
|
27
|
+
|
|
28
|
+
Build a table with these rows.
|
|
29
|
+
|
|
30
|
+
- Detected archetype.
|
|
31
|
+
- Domain (platform/agentic/LLMOps/ML/enterprise).
|
|
32
|
+
- Function (build/consult/manage/deploy).
|
|
33
|
+
- Seniority.
|
|
34
|
+
- Remote (full/hybrid/onsite).
|
|
35
|
+
- Team size (if mentioned).
|
|
36
|
+
- TL;DR in 1 sentence.
|
|
37
|
+
|
|
38
|
+
## Match the CV (Block B)
|
|
39
|
+
|
|
40
|
+
**cv.md is already in your context** (via opencode.json:instructions) — use it directly, don't Read it again. Build a table mapping each JD requirement to exact lines from the CV.
|
|
41
|
+
|
|
42
|
+
**Adapt the proof points to the archetype.**
|
|
43
|
+
|
|
44
|
+
- For FDE: prioritize proof points about fast delivery and client-facing work.
|
|
45
|
+
- For SA: prioritize system design and integrations.
|
|
46
|
+
- For PM: prioritize product discovery and metrics.
|
|
47
|
+
- For LLMOps: prioritize evals, observability, pipelines.
|
|
48
|
+
- For Agentic: prioritize multi-agent, HITL, orchestration.
|
|
49
|
+
- For Transformation: prioritize change management, adoption, scaling.
|
|
50
|
+
|
|
51
|
+
**Gaps** section with a mitigation strategy for each one. For each gap, answer in order.
|
|
52
|
+
|
|
53
|
+
1. Classify it as a hard blocker or an optional requirement.
|
|
54
|
+
2. Identify any adjacent experience the candidate can demonstrate.
|
|
55
|
+
3. Identify any portfolio project that covers the gap.
|
|
56
|
+
4. Write a concrete mitigation plan (a cover-letter phrase or a quick project).
|
|
57
|
+
|
|
58
|
+
## Compute level and strategy (Block C)
|
|
59
|
+
|
|
60
|
+
1. **Compare detected level** in the JD against the candidate's calibrated level for that archetype.
|
|
61
|
+
2. **"Sell senior without lying" plan**: specific phrases adapted to the archetype, concrete achievements to highlight, how to position founder experience as an advantage.
|
|
62
|
+
3. **"If I get downleveled" plan**: accept if comp is fair, negotiate 6-month review, clear promotion criteria.
|
|
63
|
+
|
|
64
|
+
## Compute comp and demand (Block D)
|
|
65
|
+
|
|
66
|
+
**Check first:** If `reports/deep-{company-slug}-*.md` exists, read it — deep research may already have comp data, funding info, and hiring signals. Use it as a starting point instead of duplicating WebSearch effort.
|
|
67
|
+
|
|
68
|
+
Use WebSearch for:
|
|
69
|
+
- Current salaries for the role (Glassdoor, Levels.fyi, Blind)
|
|
70
|
+
- Company compensation reputation
|
|
71
|
+
- Role demand trend
|
|
72
|
+
|
|
73
|
+
Table with data and cited sources. If no data is available, say so instead of making things up.
|
|
74
|
+
|
|
75
|
+
## List the customization plan (Block E)
|
|
76
|
+
|
|
77
|
+
Build a table with these columns: # | Section | Current State | Proposed Change | Why.
|
|
78
|
+
|
|
79
|
+
| # | Section | Current State | Proposed Change | Why |
|
|
80
|
+
|---|---------|---------------|-----------------|-----|
|
|
81
|
+
| 1 | Summary | ... | ... | ... |
|
|
82
|
+
| ... | ... | ... | ... | ... |
|
|
83
|
+
|
|
84
|
+
Top 5 changes to the CV + Top 5 changes to LinkedIn to maximize match.
|
|
85
|
+
|
|
86
|
+
## List interview-prep stories (Block F)
|
|
87
|
+
|
|
88
|
+
Map 6-10 STAR+R stories to JD requirements (STAR + **Reflection**).
|
|
89
|
+
|
|
90
|
+
| # | JD Requirement | STAR+R Story | S | T | A | R | Reflection |
|
|
91
|
+
|---|----------------|--------------|---|---|---|---|------------|
|
|
92
|
+
|
|
93
|
+
The **Reflection** column captures what was learned or what would be done differently. This signals seniority — junior candidates describe what happened, senior candidates extract lessons.
|
|
94
|
+
|
|
95
|
+
**Story Bank:** If `interview-prep/story-bank.md` exists, manage it actively — not just append:
|
|
96
|
+
|
|
97
|
+
1. **Check for existing stories** that cover the same theme (e.g., "technical leadership", "delivery under pressure"). Use the `**Best for questions about:**` tags to match.
|
|
98
|
+
2. **If a new story covers the same theme as an existing one**, compare them. Keep the one with stronger quantified results and broader applicability. Update the match count on the keeper. Remove the weaker one.
|
|
99
|
+
3. **If a new story covers a NEW theme**, append it.
|
|
100
|
+
4. **Update match counts**: Each story MUST have a `**Matched N evaluations:**` line listing which reports used it (e.g., `Matched 5 evaluations: #012, #045, #078, #102, #115`). Stories with 5+ matches are the most versatile — practice them first.
|
|
101
|
+
5. **Cap at 10-12 stories max.** If adding a new story would exceed 12, retire the story with the fewest matches and narrowest applicability. Move retired stories to a `## Retired` section at the bottom (don't delete — keep them for niche roles).
|
|
102
|
+
6. **Tag archetypes**: Each story MUST have `**Archetypes:**` listing which role archetypes it's strongest for (e.g., `LLMOps, Platform`).
|
|
103
|
+
|
|
104
|
+
The goal is a curated bank of 10 versatile stories, not an ever-growing log.
|
|
105
|
+
|
|
106
|
+
**Frame story selection by archetype.**
|
|
107
|
+
|
|
108
|
+
- FDE: emphasize delivery speed and client-facing work.
|
|
109
|
+
- SA: emphasize architecture decisions.
|
|
110
|
+
- PM: emphasize discovery and trade-offs.
|
|
111
|
+
- LLMOps: emphasize metrics, evals, production hardening.
|
|
112
|
+
- Agentic: emphasize orchestration, error handling, HITL.
|
|
113
|
+
- Transformation: emphasize adoption, organizational change.
|
|
114
|
+
|
|
115
|
+
Also include:
|
|
116
|
+
- 1 recommended case study (which of their projects to present and how)
|
|
117
|
+
- Red-flag questions and how to answer them (e.g., "Why did you sell your company?", "Do you have direct reports?")
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Run post-evaluation steps
|
|
122
|
+
|
|
123
|
+
**ALWAYS** after generating blocks A-F:
|
|
124
|
+
|
|
125
|
+
### Save the report .md (step 1)
|
|
126
|
+
|
|
127
|
+
Save the full evaluation to `reports/{###}-{company-slug}-{YYYY-MM-DD}.md`.
|
|
128
|
+
|
|
129
|
+
- `{###}` = next sequential number (3 digits, zero-padded)
|
|
130
|
+
- `{company-slug}` = company name in lowercase, no spaces (use hyphens)
|
|
131
|
+
- `{YYYY-MM-DD}` = current date
|
|
132
|
+
|
|
133
|
+
**Report format:**
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
# Evaluation: {Company} — {Role}
|
|
137
|
+
|
|
138
|
+
**Date:** {YYYY-MM-DD}
|
|
139
|
+
**Archetype:** {detected}
|
|
140
|
+
**Score:** {X.X/5}
|
|
141
|
+
**URL:** {original offer URL}
|
|
142
|
+
**PDF:** {path or pending}
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Score
|
|
147
|
+
|
|
148
|
+
{the JSON block emitted per _shared.md, verbatim, inside a fenced ```json block}
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## A) Role Summary
|
|
153
|
+
(full content of block A — reference scores by key, do not re-enumerate dimensions)
|
|
154
|
+
|
|
155
|
+
## B) CV Match
|
|
156
|
+
(full content of block B)
|
|
157
|
+
|
|
158
|
+
## C) Level and Strategy
|
|
159
|
+
(full content of block C)
|
|
160
|
+
|
|
161
|
+
## D) Comp and Demand
|
|
162
|
+
(full content of block D)
|
|
163
|
+
|
|
164
|
+
## E) Customization Plan
|
|
165
|
+
(full content of block E)
|
|
166
|
+
|
|
167
|
+
## F) Interview Prep Plan
|
|
168
|
+
(full content of block F)
|
|
169
|
+
|
|
170
|
+
## G) Draft Application Answers
|
|
171
|
+
(only if `draft_answers_threshold_met` in the JSON — draft answers for the application form)
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Extracted Keywords
|
|
176
|
+
(list of 15-20 keywords from the JD for ATS optimization)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Global Score
|
|
180
|
+
|
|
181
|
+
**Use the Canonical Scoring Model from `modes/_shared.md`.** The per-dimension breakdown lives in the JSON block (`## Score` section of the report). Don't repeat it as a prose table — that's the duplication we're eliminating. If you need to reference a specific dimension in the narrative, quote its score and rationale from the JSON inline: *"Seniority fit (3/5 — Senior IC, no formal mgmt) is the main gap."*
|
|
182
|
+
|
|
183
|
+
### Append to the tracker (step 2)
|
|
184
|
+
|
|
185
|
+
**ALWAYS** register in `data/applications/` (the day file for the current date, e.g., `data/applications/2026-04-13.md`):
|
|
186
|
+
- Next sequential number
|
|
187
|
+
- Current date
|
|
188
|
+
- Company
|
|
189
|
+
- Role
|
|
190
|
+
- Score: weighted total from the Canonical Scoring Model (1-5)
|
|
191
|
+
- Status: `Evaluated`
|
|
192
|
+
- PDF: ❌ (or ✅ if auto-pipeline generated PDF)
|
|
193
|
+
- Report: relative link to the report .md (e.g., `[001](reports/001-company-2026-01-01.md)`)
|
|
194
|
+
|
|
195
|
+
**Tracker format:**
|
|
196
|
+
|
|
197
|
+
```markdown
|
|
198
|
+
| # | Date | Company | Role | Score | Status | PDF | Report |
|
|
199
|
+
```
|
package/modes/pdf.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Mode: pdf — ATS-Optimized PDF Generation
|
|
2
|
+
|
|
3
|
+
## Full Pipeline
|
|
4
|
+
|
|
5
|
+
1. `cv.md` is already in your context via `opencode.json:instructions` — use it as the source of truth, do NOT Read it again
|
|
6
|
+
2. Ask the user for the JD if not already in context (text or URL)
|
|
7
|
+
3. Extract 15-20 keywords from the JD
|
|
8
|
+
4. Detect JD language → CV language (EN default)
|
|
9
|
+
5. Detect company location → paper format:
|
|
10
|
+
- US/Canada → `letter`
|
|
11
|
+
- Rest of the world → `a4`
|
|
12
|
+
6. Detect role archetype → adapt framing
|
|
13
|
+
7. Rewrite Professional Summary injecting JD keywords + exit narrative bridge ("Built and sold a business. Now applying systems thinking to [JD domain].")
|
|
14
|
+
8. Select the top 3-4 most relevant projects for the offer
|
|
15
|
+
9. Reorder experience bullets by relevance to the JD
|
|
16
|
+
10. Build competency grid from JD requirements (6-8 keyword phrases)
|
|
17
|
+
11. Inject keywords naturally into existing achievements (NEVER fabricate)
|
|
18
|
+
12. Generate complete HTML from template + personalized content
|
|
19
|
+
13. Write HTML to `/tmp/cv-candidate-{company}.html`
|
|
20
|
+
14. Run: `node generate-pdf.mjs /tmp/cv-candidate-{company}.html output/cv-candidate-{company}-{YYYY-MM-DD}.pdf --format={letter|a4}`
|
|
21
|
+
15. Report: PDF path, page count, keyword coverage %
|
|
22
|
+
|
|
23
|
+
## Apply these ATS rules for clean parsing
|
|
24
|
+
|
|
25
|
+
- Single-column layout (no sidebars, no parallel columns)
|
|
26
|
+
- Standard headers: "Professional Summary", "Work Experience", "Education", "Skills", "Certifications", "Projects"
|
|
27
|
+
- No text in images/SVGs
|
|
28
|
+
- No critical info in PDF headers/footers (ATS ignores them)
|
|
29
|
+
- UTF-8, selectable text (not rasterized)
|
|
30
|
+
- No nested tables
|
|
31
|
+
- JD keywords distributed across: Summary (top 5), first bullet of each role, Skills section
|
|
32
|
+
|
|
33
|
+
## Apply this PDF design
|
|
34
|
+
|
|
35
|
+
- **Fonts**: Space Grotesk (headings, 600-700) + DM Sans (body, 400-500)
|
|
36
|
+
- **Fonts self-hosted**: `fonts/`
|
|
37
|
+
- **Header**: name in Space Grotesk 24px bold + gradient line `linear-gradient(to right, hsl(187,74%,32%), hsl(270,70%,45%))` 2px + contact row
|
|
38
|
+
- **Section headers**: Space Grotesk 13px, uppercase, letter-spacing 0.05em, cyan primary color
|
|
39
|
+
- **Body**: DM Sans 11px, line-height 1.5
|
|
40
|
+
- **Company names**: accent purple color `hsl(270,70%,45%)`
|
|
41
|
+
- **Margins**: 0.6in
|
|
42
|
+
- **Background**: pure white
|
|
43
|
+
|
|
44
|
+
## Sort sections for the "6-second recruiter scan"
|
|
45
|
+
|
|
46
|
+
1. Header (large name, gradient, contact, portfolio link)
|
|
47
|
+
2. Professional Summary (3-4 lines, keyword-dense)
|
|
48
|
+
3. Core Competencies (6-8 keyword phrases in flex-grid)
|
|
49
|
+
4. Work Experience (reverse chronological)
|
|
50
|
+
5. Projects (top 3-4 most relevant)
|
|
51
|
+
6. Education & Certifications
|
|
52
|
+
7. Skills (languages + technical)
|
|
53
|
+
|
|
54
|
+
## Apply ethical keyword injection (truth-based)
|
|
55
|
+
|
|
56
|
+
Examples of legitimate reformulation:
|
|
57
|
+
- JD says "RAG pipelines" and CV says "LLM workflows with retrieval" → change to "RAG pipeline design and LLM orchestration workflows"
|
|
58
|
+
- JD says "MLOps" and CV says "observability, evals, error handling" → change to "MLOps and observability: evals, error handling, cost monitoring"
|
|
59
|
+
- JD says "stakeholder management" and CV says "collaborated with team" → change to "stakeholder management across engineering, operations, and business"
|
|
60
|
+
|
|
61
|
+
**NEVER add skills the candidate does not have. Only reformulate real experience using the exact vocabulary of the JD.**
|
|
62
|
+
|
|
63
|
+
## Write in a style that defeats AI-detection (CRITICAL)
|
|
64
|
+
|
|
65
|
+
ATS platforms (Indeed, LinkedIn, Workday) increasingly flag AI-generated CVs. The PDF generation MUST produce text that reads as human-written. This is not about deception — it's about ensuring the candidate's real experience isn't filtered out by an automated detector before a human ever sees it.
|
|
66
|
+
|
|
67
|
+
### Apply sentence-structure variations
|
|
68
|
+
- **Vary sentence length deliberately.** Mix short punchy fragments ("Shipped in 3 weeks.") with longer compound sentences. AI text tends toward uniform medium-length sentences.
|
|
69
|
+
- **Start bullets differently.** Don't begin every bullet with a past-tense action verb. Mix structures: "Led...", "The team needed X, so I...", "After discovering Y, rebuilt Z to..."
|
|
70
|
+
- **Use the candidate's actual phrasing from cv.md when possible.** The candidate's own words have idiosyncratic phrasing that AI-generated text lacks. Preserve their voice — reformulate for keywords, but don't rewrite the whole sentence.
|
|
71
|
+
|
|
72
|
+
### Select words carefully
|
|
73
|
+
- **Avoid AI-hallmark phrases.** Never use: "leveraged", "utilized", "spearheaded", "orchestrated" (as a metaphor for "managed"), "cutting-edge", "passionate about", "drive innovation", "synergy", "holistic approach", "navigate complex", "foster collaboration". These are the first things detectors look for.
|
|
74
|
+
- **Use plain, specific verbs.** "Built" not "architected". "Ran" not "orchestrated". "Fixed" not "remediated". "Cut costs by" not "optimized cost efficiency". The more specific and concrete, the more human it reads.
|
|
75
|
+
- **Preserve technical jargon as-is.** Real engineers say "k8s" not "Kubernetes orchestration platform". Keep the candidate's working shorthand.
|
|
76
|
+
|
|
77
|
+
### Apply structural variations
|
|
78
|
+
- **Don't over-polish.** A real CV has minor asymmetries — one job has 4 bullets, another has 3. One bullet is 2 lines, the next is 1. Don't normalize everything to uniform length.
|
|
79
|
+
- **Keep the Professional Summary under 4 sentences.** AI-generated summaries tend to be dense paragraphs that try to cover everything. A human writes a tighter summary and lets the experience section do the work.
|
|
80
|
+
- **Don't repeat the same metric in both the summary and a bullet.** Humans don't do this. Pick the best place for each number.
|
|
81
|
+
|
|
82
|
+
### Check the draft before generating HTML
|
|
83
|
+
After drafting all CV content, review it once against these checks.
|
|
84
|
+
1. Do 3+ bullets start with the same word? → Rewrite the openings.
|
|
85
|
+
2. Are all bullets the same length (± 25 chars)? → Vary them.
|
|
86
|
+
3. Does any sentence contain 2+ words from the AI-hallmark list in "Choose words carefully"? → Rewrite.
|
|
87
|
+
4. Does the summary read like a paragraph from a cover letter? → Make it more telegraphic.
|
|
88
|
+
|
|
89
|
+
## Use this HTML template
|
|
90
|
+
|
|
91
|
+
Use the template in `cv-template.html`. Replace the `{{...}}` placeholders with personalized content:
|
|
92
|
+
|
|
93
|
+
| Placeholder | Content |
|
|
94
|
+
|-------------|---------|
|
|
95
|
+
| `{{LANG}}` | `en` or `es` |
|
|
96
|
+
| `{{PAGE_WIDTH}}` | `8.5in` (letter) or `210mm` (A4) |
|
|
97
|
+
| `{{NAME}}` | (from profile.yml) |
|
|
98
|
+
| `{{EMAIL}}` | (from profile.yml) |
|
|
99
|
+
| `{{LINKEDIN_URL}}` | (from profile.yml) |
|
|
100
|
+
| `{{LINKEDIN_DISPLAY}}` | (from profile.yml) |
|
|
101
|
+
| `{{PORTFOLIO_URL}}` | (from profile.yml) (or /es depending on language) |
|
|
102
|
+
| `{{PORTFOLIO_DISPLAY}}` | (from profile.yml) (or /es depending on language) |
|
|
103
|
+
| `{{LOCATION}}` | (from profile.yml) |
|
|
104
|
+
| `{{SECTION_SUMMARY}}` | Professional Summary / Resumen Profesional |
|
|
105
|
+
| `{{SUMMARY_TEXT}}` | Personalized summary with keywords |
|
|
106
|
+
| `{{SECTION_COMPETENCIES}}` | Core Competencies / Competencias Core |
|
|
107
|
+
| `{{COMPETENCIES}}` | `<span class="competency-tag">keyword</span>` × 6-8 |
|
|
108
|
+
| `{{SECTION_EXPERIENCE}}` | Work Experience / Experiencia Laboral |
|
|
109
|
+
| `{{EXPERIENCE}}` | HTML for each job with reordered bullets |
|
|
110
|
+
| `{{SECTION_PROJECTS}}` | Projects / Proyectos |
|
|
111
|
+
| `{{PROJECTS}}` | HTML for top 3-4 projects |
|
|
112
|
+
| `{{SECTION_EDUCATION}}` | Education / Formación |
|
|
113
|
+
| `{{EDUCATION}}` | HTML for education |
|
|
114
|
+
| `{{SECTION_CERTIFICATIONS}}` | Certifications / Certificaciones |
|
|
115
|
+
| `{{CERTIFICATIONS}}` | HTML for certifications |
|
|
116
|
+
| `{{SECTION_SKILLS}}` | Skills / Competencias |
|
|
117
|
+
| `{{SKILLS}}` | HTML for skills |
|
|
118
|
+
|
|
119
|
+
## Update the tracker post-generation
|
|
120
|
+
|
|
121
|
+
Update the tracker when the offer is already registered: change PDF from ❌ to ✅.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Mode: pipeline — URL Inbox (Second Brain)
|
|
2
|
+
|
|
3
|
+
Processes accumulated job offer URLs from `data/pipeline.md`. The user adds URLs at any time and then runs `/job-forge pipeline` to process them all.
|
|
4
|
+
|
|
5
|
+
## Run This Workflow
|
|
6
|
+
|
|
7
|
+
1. **Read** `data/pipeline.md` → find `- [ ]` items in the "Pending" section
|
|
8
|
+
2. **For each pending URL**:
|
|
9
|
+
a. Calculate the next sequential `REPORT_NUM` (read `reports/`, take the highest number + 1)
|
|
10
|
+
b. **Extract JD** using Geometra MCP (geometra_connect + geometra_page_model) → WebFetch → WebSearch
|
|
11
|
+
c. If the URL is not accessible → mark as `- [!]` with a note and continue
|
|
12
|
+
d. **Run full auto-pipeline**: A-F Evaluation → Report .md → PDF (if score >= 3.0, per `_shared.md` thresholds) → Draft answers (if score >= 3.5) → Tracker
|
|
13
|
+
e. **Move from "Pending" to "Processed"**: `- [x] #NNN | URL | Company | Role | Score/5 | PDF ✅/❌`
|
|
14
|
+
3. **Parallel dispatch — max 2 at a time** (Hard Limit #1 in `AGENTS.md`). For N pending URLs, run `ceil(N/2)` rounds of 2 `task` dispatches. Never 3+ in one message.
|
|
15
|
+
4. **When finished**, display a summary table:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
| # | Company | Role | Score | PDF | Recommended action |
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Apply pipeline.md Format
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
## Pending
|
|
25
|
+
- [ ] https://jobs.example.com/posting/123
|
|
26
|
+
- [ ] https://boards.greenhouse.io/company/jobs/456 | Company Inc | Senior PM
|
|
27
|
+
- [!] https://private.url/job — Error: login required
|
|
28
|
+
|
|
29
|
+
## Processed
|
|
30
|
+
- [x] #143 | https://jobs.example.com/posting/789 | Acme Corp | AI PM | 4.2/5 | PDF ✅
|
|
31
|
+
- [x] #144 | https://boards.greenhouse.io/xyz/jobs/012 | BigCo | SA | 2.1/5 | PDF ❌
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Detect JD From URL
|
|
35
|
+
|
|
36
|
+
1. **Geometra MCP (preferred):** `geometra_connect` + `geometra_page_model`. Works with all SPAs, uses fewer tokens than raw DOM snapshots.
|
|
37
|
+
2. **WebFetch (fallback):** For static pages or when Geometra is not available.
|
|
38
|
+
3. **WebSearch (last resort):** Search on secondary portals that index the JD.
|
|
39
|
+
|
|
40
|
+
**Special cases:**
|
|
41
|
+
- **LinkedIn**: May require login → mark `[!]` and ask the user to paste the text
|
|
42
|
+
- **PDF**: If the URL points to a PDF, read it directly with the Read tool
|
|
43
|
+
- **`local:` prefix**: Read the local file. Example: `local:jds/linkedin-pm-ai.md` → read `jds/linkedin-pm-ai.md`
|
|
44
|
+
|
|
45
|
+
## Automatic Numbering
|
|
46
|
+
|
|
47
|
+
1. List all files in `reports/`
|
|
48
|
+
2. Extract the number from the prefix (e.g., `142-medispend...` → 142)
|
|
49
|
+
3. New number = highest found + 1
|
|
50
|
+
|
|
51
|
+
## Source Synchronization
|
|
52
|
+
|
|
53
|
+
Before processing any URL, verify sync:
|
|
54
|
+
```bash
|
|
55
|
+
node cv-sync-check.mjs
|
|
56
|
+
```
|
|
57
|
+
If there is a desynchronization, warn the user before continuing.
|
|
58
|
+
|
|
59
|
+
## Run This Pipeline Runbook When N >= 2
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Step 1 — Read data/pipeline.md; collect "- [ ]" URLs into `pending = [url_1, ..., url_N]`
|
|
63
|
+
Step 2 — Pre-flight cleanup (once, before loop):
|
|
64
|
+
geometra_list_sessions()
|
|
65
|
+
geometra_disconnect({ closeBrowser: true })
|
|
66
|
+
Step 3 — For round in ceil(N/2):
|
|
67
|
+
pair = pending[round*2 : round*2 + 2]
|
|
68
|
+
# ONE message, 1 or 2 task() calls. Never 3.
|
|
69
|
+
task(process url pair[0])
|
|
70
|
+
task(process url pair[1]) # only if pair has 2
|
|
71
|
+
# WAIT for both returns before the next round.
|
|
72
|
+
Step 4 — Between rounds: geometra_list_sessions() + geometra_disconnect({closeBrowser: true})
|
|
73
|
+
Step 5 — Reconcile outcomes (Hard Limit #6):
|
|
74
|
+
bash: node merge-tracker.mjs # TSVs → correct day file
|
|
75
|
+
bash: node verify-pipeline.mjs # validate URL/status consistency
|
|
76
|
+
Step 6 — Display summary table; flag any verify-pipeline errors.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Hard rules:**
|
|
80
|
+
- Max 2 `task` dispatches per message (Hard Limit #1).
|
|
81
|
+
- Never re-dispatch a URL whose previous subagent is still in-flight (Hard Limit #5).
|
|
82
|
+
- Orchestrator does not call `geometra_fill_form` / `geometra_page_model` in multi-URL runs (Hard Limit #4) — delegate.
|
|
83
|
+
- **The only edits allowed to `data/pipeline.md` are flipping `[ ]` → `[x]`** (inbox state) (Hard Limit #6). APPLIED / FAILED / SKIP outcomes go via `batch/tracker-additions/*.tsv` into the day file. Do NOT write application status to pipeline.md.
|
package/modes/project.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Mode: project — Portfolio Project Evaluation
|
|
2
|
+
|
|
3
|
+
Scoring across 6 dimensions (1-5):
|
|
4
|
+
|
|
5
|
+
| Dimension | Weight | 5 = ... | 1 = ... |
|
|
6
|
+
|-----------|--------|---------|---------|
|
|
7
|
+
| Signal for target roles | 25% | Directly demonstrates JD skill | Unrelated |
|
|
8
|
+
| Uniqueness | 20% | Nobody has done this | Everyone has it |
|
|
9
|
+
| Demo-ability | 20% | Live demo in 2 min | Code only, not visual |
|
|
10
|
+
| Metrics potential | 15% | Clear metrics (latency, cost, accuracy) | No possible metrics |
|
|
11
|
+
| Time to MVP | 10% | 1 week | 3+ months |
|
|
12
|
+
| STAR story potential | 10% | Rich story with trade-offs | Just implementation |
|
|
13
|
+
|
|
14
|
+
## "Interview Pack" Requirements
|
|
15
|
+
|
|
16
|
+
For each approved project:
|
|
17
|
+
1. **One-pager**: product + architecture + metrics + evaluation plan
|
|
18
|
+
2. **Demo**: live URL or 2-min recorded walkthrough
|
|
19
|
+
3. **Postmortem**: what worked, what didn't, mitigations
|
|
20
|
+
|
|
21
|
+
## Apply The 80/20 Plan
|
|
22
|
+
|
|
23
|
+
- Week 1 → MVP with core metric
|
|
24
|
+
- Week 2 → polish + interview pack
|
|
25
|
+
|
|
26
|
+
## Return One Of These Verdicts
|
|
27
|
+
|
|
28
|
+
- **BUILD** → plan with weekly milestones
|
|
29
|
+
- **SKIP** → why and what to do instead
|
|
30
|
+
- **PIVOT TO [alternative]** → more impactful variant
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Mode: rejection — Rejection Analysis & Learning Loop
|
|
2
|
+
|
|
3
|
+
When the user reports a rejection, capture structured data and surface patterns over time.
|
|
4
|
+
|
|
5
|
+
**This mode is additive.** It uses the existing notes column in tracker files (no new columns) and appends a section to existing reports (no changes to report format).
|
|
6
|
+
|
|
7
|
+
## Use These Trigger Conditions
|
|
8
|
+
|
|
9
|
+
- User says "I got rejected from [company]".
|
|
10
|
+
- User updates a tracker entry to Rejected.
|
|
11
|
+
- User runs `/job-forge rejection` to review patterns.
|
|
12
|
+
|
|
13
|
+
## Step 1 — Record The Rejection
|
|
14
|
+
|
|
15
|
+
Update the entry in `data/applications/` (the day file where the entry exists):
|
|
16
|
+
- Status → `Rejected`
|
|
17
|
+
- Notes → append rejection info in compact format: `REJ@{stage}:{reason}`
|
|
18
|
+
|
|
19
|
+
**Stages** (ask the user which applies):
|
|
20
|
+
| Stage | Code | Meaning |
|
|
21
|
+
|-------|------|---------|
|
|
22
|
+
| Resume screen | `resume` | Rejected before any human contact |
|
|
23
|
+
| Phone screen | `phone` | Rejected after initial call |
|
|
24
|
+
| Technical interview | `tech` | Rejected after technical assessment |
|
|
25
|
+
| Hiring manager | `hm` | Rejected after HM interview |
|
|
26
|
+
| Final round | `final` | Rejected at final stage |
|
|
27
|
+
| Offer pulled | `offer` | Offer was extended then retracted |
|
|
28
|
+
| Unknown | `unk` | User doesn't know |
|
|
29
|
+
|
|
30
|
+
**Reasons** (ask the user if they have signal, otherwise `unk`):
|
|
31
|
+
- `exp` — not enough experience / seniority
|
|
32
|
+
- `skill` — missing specific technical skill
|
|
33
|
+
- `culture` — culture/team fit
|
|
34
|
+
- `comp` — comp expectations too high
|
|
35
|
+
- `geo` — location/timezone mismatch
|
|
36
|
+
- `internal` — went with internal candidate
|
|
37
|
+
- `closed` — role was closed/frozen
|
|
38
|
+
- `unk` — no feedback given
|
|
39
|
+
|
|
40
|
+
Example notes: `REJ@tech:skill — failed system design round`
|
|
41
|
+
|
|
42
|
+
## Step 2 — Append To Report
|
|
43
|
+
|
|
44
|
+
Append a `## Rejection` section to the report in `reports/` when one exists:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
## Rejection
|
|
48
|
+
**Date:** YYYY-MM-DD
|
|
49
|
+
**Stage:** Technical interview
|
|
50
|
+
**Reason:** Missing specific skill (system design at scale)
|
|
51
|
+
**Signal:** What this tells us about future applications for this archetype
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Step 3 — Run Pattern Analysis
|
|
55
|
+
|
|
56
|
+
Run pattern analysis when the user runs `/job-forge rejection` without a specific company. Analyze ALL rejected entries:
|
|
57
|
+
|
|
58
|
+
1. **Read** all day files in `data/applications/` — filter to Rejected entries
|
|
59
|
+
2. **Parse** `REJ@{stage}:{reason}` from notes column
|
|
60
|
+
3. **Aggregate** patterns:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
## Rejection Patterns — {date}
|
|
64
|
+
|
|
65
|
+
### By Stage
|
|
66
|
+
- Resume screen: N rejections (N% of all rejections)
|
|
67
|
+
- Technical: N rejections
|
|
68
|
+
- ...
|
|
69
|
+
|
|
70
|
+
### By Archetype
|
|
71
|
+
- LLMOps roles: N/M rejected (N% rejection rate)
|
|
72
|
+
- Platform roles: N/M rejected
|
|
73
|
+
- ...
|
|
74
|
+
|
|
75
|
+
### By Score Range
|
|
76
|
+
- Score 4.0+: N/M rejected (should be low — if high, scoring model needs recalibration)
|
|
77
|
+
- Score 3.0-3.9: N/M rejected
|
|
78
|
+
- Score <3.0: N/M rejected (expected to be high)
|
|
79
|
+
|
|
80
|
+
### Signals
|
|
81
|
+
- [If 3+ resume-screen rejections for same archetype]: "Consider stronger keyword injection for {archetype} roles — see pdf.md anti-AI-detection rules"
|
|
82
|
+
- [If high-score offers getting rejected]: "Scoring model may be inflated — review calibration anchors in _shared.md"
|
|
83
|
+
- [If rejections cluster at tech stage]: "Story bank may need stronger technical stories for {archetype} — review interview-prep/story-bank.md"
|
|
84
|
+
- [If comp rejections]: "Consider adjusting target range in config/profile.yml"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Skip These Actions (Out Of Scope)
|
|
88
|
+
|
|
89
|
+
- Does NOT change the scoring model or thresholds automatically
|
|
90
|
+
- Does NOT modify reports retroactively (only appends Rejection section)
|
|
91
|
+
- Does NOT add new columns to tracker files (uses notes column)
|
|
92
|
+
- Does NOT require any changes to merge-tracker, dedup, or verify scripts
|