job-forge 2.14.39 → 2.14.40
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 +2 -1
- package/.cursor/mcp.json +8 -3
- package/.mcp.json +8 -3
- package/README.md +143 -191
- package/bin/create-job-forge.mjs +5 -1
- package/bin/geometra-mcp-launcher.mjs +86 -0
- package/bin/job-forge.mjs +3 -0
- package/docs/SETUP.md +1 -1
- package/iso/mcp.json +5 -1
- package/modes/reference-portals.md +3 -1
- package/opencode.json +7 -3
- package/package.json +1 -1
package/.codex/config.toml
CHANGED
|
@@ -17,7 +17,8 @@ model_provider = "openai"
|
|
|
17
17
|
|
|
18
18
|
[mcp_servers.geometra]
|
|
19
19
|
command = "npx"
|
|
20
|
-
args = ["-
|
|
20
|
+
args = ["--no-install", "job-forge", "mcp:geometra"]
|
|
21
|
+
env = { GEOMETRA_STEALTH = "1", GEOMETRA_BROWSER = "stealth" }
|
|
21
22
|
|
|
22
23
|
[mcp_servers.gmail]
|
|
23
24
|
command = "npx"
|
package/.cursor/mcp.json
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
"geometra": {
|
|
4
4
|
"command": "npx",
|
|
5
5
|
"args": [
|
|
6
|
-
"-
|
|
7
|
-
"
|
|
8
|
-
|
|
6
|
+
"--no-install",
|
|
7
|
+
"job-forge",
|
|
8
|
+
"mcp:geometra"
|
|
9
|
+
],
|
|
10
|
+
"env": {
|
|
11
|
+
"GEOMETRA_STEALTH": "1",
|
|
12
|
+
"GEOMETRA_BROWSER": "stealth"
|
|
13
|
+
}
|
|
9
14
|
},
|
|
10
15
|
"gmail": {
|
|
11
16
|
"command": "npx",
|
package/.mcp.json
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
"geometra": {
|
|
4
4
|
"command": "npx",
|
|
5
5
|
"args": [
|
|
6
|
-
"-
|
|
7
|
-
"
|
|
8
|
-
|
|
6
|
+
"--no-install",
|
|
7
|
+
"job-forge",
|
|
8
|
+
"mcp:geometra"
|
|
9
|
+
],
|
|
10
|
+
"env": {
|
|
11
|
+
"GEOMETRA_STEALTH": "1",
|
|
12
|
+
"GEOMETRA_BROWSER": "stealth"
|
|
13
|
+
}
|
|
9
14
|
},
|
|
10
15
|
"gmail": {
|
|
11
16
|
"command": "npx",
|
package/README.md
CHANGED
|
@@ -1,242 +1,194 @@
|
|
|
1
1
|
# JobForge
|
|
2
2
|
|
|
3
|
-
> AI-powered job search pipeline
|
|
3
|
+
> AI-powered job search pipeline for opencode: evaluate roles, generate tailored CV PDFs, scan portals, apply to good-fit jobs, and track the whole search locally.
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
9
|
-

|
|
10
9
|
|
|
11
10
|
<p align="center">
|
|
12
|
-
<img src="demo/demo.gif" alt="JobForge
|
|
11
|
+
<img src="demo/demo.gif" alt="JobForge demo" width="800">
|
|
13
12
|
</p>
|
|
14
13
|
|
|
15
|
-
<p align="center"><em>Paste a job URL. Get a scored evaluation, tailored CV, and
|
|
14
|
+
<p align="center"><em>Paste a job URL. Get a scored evaluation, tailored CV, and tracker entry.</em></p>
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
## Start Here
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
Most users should scaffold a personal job-search project instead of cloning this harness repo directly.
|
|
19
|
+
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
- [opencode](https://opencode.ai) installed and configured
|
|
23
|
+
- Node.js 20.6 or newer
|
|
24
|
+
- Optional: Go, only if you want to build the dashboard TUI
|
|
25
|
+
|
|
26
|
+
### Create Your Project
|
|
20
27
|
|
|
21
28
|
```bash
|
|
22
29
|
npx --package=job-forge create-job-forge my-job-search
|
|
23
30
|
cd my-job-search
|
|
24
31
|
npm install
|
|
25
|
-
opencode
|
|
26
32
|
```
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
Then edit the three personal files the scaffolder creates:
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
| File | What to put there |
|
|
37
|
+
|------|-------------------|
|
|
38
|
+
| `cv.md` | Your CV in markdown. This is the source for matching and PDF generation. |
|
|
39
|
+
| `config/profile.yml` | Your identity, target roles, location constraints, compensation, and proof points. |
|
|
40
|
+
| `portals.yml` | Companies, search queries, and title filters for portal scanning. |
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
Optional: add `article-digest.md` with portfolio links, case studies, or extra proof points.
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
### First Run
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Full setup guide and alternative install paths (including contributing to the harness itself): **[docs/SETUP.md](docs/SETUP.md)**.
|
|
46
|
+
```bash
|
|
47
|
+
npx job-forge sync-check
|
|
48
|
+
opencode
|
|
49
|
+
```
|
|
43
50
|
|
|
44
|
-
|
|
51
|
+
Inside opencode, paste a job URL or job description. JobForge routes it through the auto-pipeline: evaluation, score, tailored report, PDF, and tracker update.
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
To see the command menu:
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
```text
|
|
56
|
+
/job-forge
|
|
57
|
+
```
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
59
|
+
## What It Does
|
|
60
|
+
|
|
61
|
+
JobForge is built for selective, high-fit applications. It is not intended for spray-and-pray submission.
|
|
62
|
+
|
|
63
|
+
- Scores opportunities with a consistent weighted rubric.
|
|
64
|
+
- Generates tailored ATS-friendly CV PDFs.
|
|
65
|
+
- Scans configured company portals and job boards.
|
|
66
|
+
- Tracks applications, follow-ups, rejections, offers, reports, and PDFs.
|
|
67
|
+
- Supports batch evaluation and application work through bounded subagents.
|
|
68
|
+
- Uses local helper CLIs for dedupe, scoring, lineage, preflight, postflight, and tracker integrity.
|
|
69
|
+
|
|
70
|
+
## Common Commands
|
|
71
|
+
|
|
72
|
+
Run these from your personal project root after `npm install`.
|
|
73
|
+
|
|
74
|
+
| Need | Command |
|
|
75
|
+
|------|---------|
|
|
76
|
+
| Verify setup after editing profile and CV | `npx job-forge sync-check` |
|
|
77
|
+
| Check tracker and pipeline health | `npx job-forge verify` |
|
|
78
|
+
| Merge batch tracker additions | `npx job-forge merge` |
|
|
79
|
+
| Generate a CV PDF from the current project | `npx job-forge pdf` |
|
|
80
|
+
| Show token usage | `npx job-forge tokens --days 1` |
|
|
81
|
+
| Rebuild harness symlinks | `npx job-forge sync` |
|
|
82
|
+
| Upgrade the harness | `npm run update-harness` |
|
|
83
|
+
|
|
84
|
+
Useful opencode commands:
|
|
85
|
+
|
|
86
|
+
| Need | Command |
|
|
87
|
+
|------|---------|
|
|
88
|
+
| Evaluate a pasted URL or JD | Paste it directly, or use `/job-forge` |
|
|
89
|
+
| Scan configured portals | `/job-forge scan` |
|
|
90
|
+
| Process queued URLs | `/job-forge pipeline` |
|
|
91
|
+
| Batch evaluate roles | `/job-forge batch` |
|
|
92
|
+
| Fill an application form | `/job-forge apply` |
|
|
93
|
+
| Check application status | `/job-forge tracker` |
|
|
94
|
+
| Check due follow-ups | `/job-forge followup` |
|
|
95
|
+
| Draft LinkedIn outreach | `/job-forge contact` |
|
|
96
|
+
| Research a company | `/job-forge deep` |
|
|
97
|
+
| Handle rejection or offer workflows | `/job-forge rejection` or `/job-forge negotiation` |
|
|
98
|
+
|
|
99
|
+
## How The Flow Works
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
Paste a job URL or JD
|
|
103
|
+
|
|
|
104
|
+
v
|
|
105
|
+
Extract role details and classify fit
|
|
106
|
+
|
|
|
107
|
+
v
|
|
108
|
+
Score against profile, CV, location, comp, and role goals
|
|
109
|
+
|
|
|
110
|
+
v
|
|
111
|
+
Create report + tailored PDF + tracker entry
|
|
112
|
+
|
|
|
113
|
+
v
|
|
114
|
+
Apply, follow up, research, or negotiate from the tracked state
|
|
115
|
+
```
|
|
58
116
|
|
|
59
|
-
|
|
117
|
+
## Project Layout
|
|
118
|
+
|
|
119
|
+
A scaffolded personal project looks like this:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
my-job-search/
|
|
123
|
+
├── package.json # depends on job-forge from npm
|
|
124
|
+
├── opencode.json # MCP and opencode configuration
|
|
125
|
+
├── cv.md # personal, gitignored
|
|
126
|
+
├── article-digest.md # optional personal proof points, gitignored
|
|
127
|
+
├── config/profile.yml # personal, gitignored
|
|
128
|
+
├── portals.yml # personal scanner config, gitignored
|
|
129
|
+
├── data/ # pipeline, applications, scan history
|
|
130
|
+
├── reports/ # generated evaluations
|
|
131
|
+
├── output/ # generated PDFs
|
|
132
|
+
├── batch/tracker-additions/ # batch apply/eval results before merge
|
|
133
|
+
├── AGENTS.md # personal overrides
|
|
134
|
+
├── AGENTS.harness.md # symlink into node_modules/job-forge
|
|
135
|
+
├── modes/ # symlinked JobForge modes
|
|
136
|
+
├── templates/ # symlinked policies and templates
|
|
137
|
+
└── node_modules/job-forge/ # the harness package
|
|
138
|
+
```
|
|
60
139
|
|
|
61
|
-
|
|
140
|
+
Your personal files and generated job-search state are gitignored by the scaffolded project.
|
|
62
141
|
|
|
63
|
-
|
|
64
|
-
|---------|-------------|
|
|
65
|
-
| **Auto-Pipeline** | Paste a URL, get a full evaluation + PDF + tracker entry |
|
|
66
|
-
| **Unified Scoring** | 10 weighted dimensions, consistent across all modes, with calibration anchors and deterministic `job-forge score:*` checks |
|
|
67
|
-
| **Anti-AI-Detection CVs** | Writing rules that avoid ATS filters on Indeed, LinkedIn, Workday |
|
|
68
|
-
| **6-Block Evaluation** | Role summary, CV match, level strategy, comp research, personalization, interview prep (STAR+R) |
|
|
69
|
-
| **Interview Story Bank** | Curated bank of 10-12 stories with match counts, archetype tags, and automatic pruning |
|
|
70
|
-
| **Follow-Up System** | `job-forge timeline:*` computes timing-based nudges from local tracker/pipeline sources: Applied 7+ days ago, Contacted 5+ days ago, Interview 1-day thank-you, and 7-day interview nudge. |
|
|
71
|
-
| **Gmail Integration** | MCP server configured to retrieve emails for interview callbacks, offer responses, and application status updates |
|
|
72
|
-
| **Rejection Analysis** | Captures stage + reason, surfaces patterns (archetype gaps, scoring miscalibration) |
|
|
73
|
-
| **Offer Negotiation** | Total comp breakdown, equity valuation, leverage from pipeline, counter-offer scripts |
|
|
74
|
-
| **Deep Research** | Company research that feeds back into scores and interview prep |
|
|
75
|
-
| **Smart LinkedIn Outreach** | Reads evaluation reports to craft targeted messages using top proof points |
|
|
76
|
-
| **Portal Scanner** | 45+ companies pre-configured with fuzzy dedup for reposts |
|
|
77
|
-
| **Batch Processing** | Parallel evaluation with headless AI CLI workers (`opencode run` or `codex exec`), with honest verification flagging |
|
|
78
|
-
| **Durable Batch Orchestration** | `batch-runner.sh` uses `@agent-pattern-labs/iso-orchestrator` for resumable bundle execution, bounded fan-out, mutexed state writes, and workflow records in `.jobforge-runs/`. |
|
|
79
|
-
| **Pipeline Integrity** | Automated merge, dedup, status normalization, health checks |
|
|
80
|
-
| **Cost-Aware Agent Routing** | Three subagents (`@general-free`, `@general-paid`, `@glm-minimal`) with per-task tool surfaces. On OpenCode, JobForge pins all tiers to `opencode-go/deepseek-v4-flash` so application runs avoid overloaded free-model pools. See [Subagent Routing in AGENTS.md](AGENTS.md) for the task-to-agent mapping. |
|
|
81
|
-
| **Trace + Telemetry + Guard + Contract + Score + Canon + Ledger + Capabilities + Context + Cache + Index + Facts + Timeline + Prioritize + Lineage + Preflight + Postflight + Redact + Migrate** | `job-forge trace:*` exposes local harness transcripts, `job-forge telemetry:*` summarizes runs, `job-forge guard:*` audits deterministic policy rules, `templates/contracts.json` enforces artifact shape with `iso-contract`, `job-forge score:*` computes/checks weighted offer scores, `job-forge canon:*` derives stable URL/company/role identity keys, `job-forge ledger:*` queries append-only workflow state, `job-forge capabilities:*` checks role boundaries, `job-forge context:*` plans mode/reference context bundles, `job-forge cache:*` reuses fetched JD/artifact content, `job-forge index:*` queries compact source pointers, `job-forge facts:*` materializes source-backed job/application/candidate facts, `job-forge timeline:*` computes due/overdue follow-up actions, `job-forge prioritize:*` ranks local apply/follow-up candidates, `job-forge lineage:*` detects stale reports/PDFs after source changes, `job-forge preflight:*` plans bounded apply dispatch rounds from file-backed candidate facts, `job-forge postflight:*` settles dispatch outcomes/artifacts/post-steps, `job-forge redact:*` sanitizes local exports, and `job-forge migrate:*` applies safe consumer-project upgrades without MCP/tool-schema overhead. |
|
|
82
|
-
| **Token Cost Visibility** | `job-forge tokens --days 1` for per-session breakdown; `job-forge session-report --since-minutes 60 --log` to flag sessions over budget and append history to `data/token-usage.tsv`. Auto-logged after every batch run. |
|
|
142
|
+
## MCPs And Automation
|
|
83
143
|
|
|
84
|
-
|
|
144
|
+
The scaffolded opencode project wires up the browser and mail automation JobForge needs:
|
|
85
145
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
/job-forge {paste a JD} → Full auto-pipeline (evaluate + PDF + tracker)
|
|
89
|
-
/job-forge scan → Scan portals for new offers
|
|
90
|
-
/job-forge pdf → Generate ATS-optimized CV
|
|
91
|
-
/job-forge batch → Batch evaluate multiple offers
|
|
92
|
-
/job-forge tracker → View application status
|
|
93
|
-
/job-forge apply → Fill application forms with AI
|
|
94
|
-
/job-forge pipeline → Process pending URLs
|
|
95
|
-
/job-forge contact → LinkedIn outreach (uses evaluation report)
|
|
96
|
-
/job-forge deep → Deep company research (feeds back into scores)
|
|
97
|
-
/job-forge followup → Check what needs follow-up action
|
|
98
|
-
/job-forge rejection → Record/analyze rejection patterns
|
|
99
|
-
/job-forge negotiation → Structured offer negotiation
|
|
100
|
-
/job-forge training → Evaluate a course/cert
|
|
101
|
-
/job-forge project → Evaluate a portfolio project
|
|
102
|
-
```
|
|
146
|
+
- Geometra MCP for browser automation and PDF generation.
|
|
147
|
+
- Gmail MCP for recruiter replies, interview callbacks, offer responses, and status emails.
|
|
103
148
|
|
|
104
|
-
|
|
149
|
+
The harness also ships config for Cursor, Claude Code, and Codex through generated symlinks. `npm install` and `npx job-forge sync` refresh those links.
|
|
105
150
|
|
|
106
|
-
|
|
151
|
+
## Contributor Setup
|
|
107
152
|
|
|
108
|
-
|
|
153
|
+
Clone this repo directly only when you want to work on the harness itself: modes, scripts, templates, generated agent configs, or release packaging.
|
|
109
154
|
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
│ Detection │
|
|
117
|
-
└────────┬─────────┘
|
|
118
|
-
│
|
|
119
|
-
┌────────▼─────────┐
|
|
120
|
-
│ A-F Evaluation │ Match, gaps, comp research, STAR stories
|
|
121
|
-
│ (reads cv.md) │ Unified 10-dimension scoring model + iso-score checks
|
|
122
|
-
└────────┬─────────┘
|
|
123
|
-
│
|
|
124
|
-
┌────┼────┐
|
|
125
|
-
▼ ▼ ▼
|
|
126
|
-
Report PDF Tracker
|
|
127
|
-
.md .pdf .tsv
|
|
128
|
-
│
|
|
129
|
-
┌────┼────┐
|
|
130
|
-
▼ ▼ ▼
|
|
131
|
-
Apply Follow Negotiate
|
|
132
|
-
up (if offer)
|
|
155
|
+
```bash
|
|
156
|
+
git clone https://github.com/Agent-Pattern-Labs/JobForge.git
|
|
157
|
+
cd JobForge
|
|
158
|
+
npm install
|
|
159
|
+
npm run build:config
|
|
160
|
+
npm run verify
|
|
133
161
|
```
|
|
134
162
|
|
|
135
|
-
|
|
163
|
+
The source of truth for generated harness configuration is under `iso/`. Run `npm run build:config` after changing `iso/` files.
|
|
136
164
|
|
|
137
|
-
|
|
165
|
+
## Documentation
|
|
138
166
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
├── config/profile.yml # your identity, target roles (personal)
|
|
147
|
-
├── data/ # applications, pipeline, scan history (personal, gitignored)
|
|
148
|
-
├── .jobforge-ledger/ # append-only local workflow events (personal, gitignored)
|
|
149
|
-
├── .jobforge-cache/ # content-addressed local JD/artifact cache (personal, gitignored)
|
|
150
|
-
├── .jobforge-index.json # deterministic artifact lookup index (generated, gitignored)
|
|
151
|
-
├── .jobforge-facts.json # deterministic fact set with provenance (generated, gitignored)
|
|
152
|
-
├── .jobforge-timeline.json # deterministic follow-up action plan (generated, gitignored)
|
|
153
|
-
├── .jobforge-prioritize.json # deterministic next-action ranking (generated, gitignored)
|
|
154
|
-
├── .jobforge-lineage.json # report/PDF lineage and stale-output checks (generated, gitignored)
|
|
155
|
-
├── .jobforge-redacted/ # sanitized local exports (generated, gitignored)
|
|
156
|
-
├── reports/ # generated evaluation reports (personal, gitignored)
|
|
157
|
-
├── batch/{batch-input,batch-state}.tsv, tracker-additions/, logs/ # personal
|
|
158
|
-
├── .jobforge-runs/ # durable batch workflow records (generated)
|
|
159
|
-
├── AGENTS.md # personal overrides (opencode + codex)
|
|
160
|
-
├── CLAUDE.md # personal overrides (Claude Code), @-imports CLAUDE.harness.md
|
|
161
|
-
│
|
|
162
|
-
│ # ↓ symlinks into node_modules/job-forge/, regenerated by postinstall sync.mjs
|
|
163
|
-
├── AGENTS.harness.md # → harness instructions (loaded via opencode.json)
|
|
164
|
-
├── CLAUDE.harness.md # → harness instructions (imported from personal CLAUDE.md)
|
|
165
|
-
├── .mcp.json # → Claude Code MCP config
|
|
166
|
-
├── .codex/config.toml # → Codex MCP config
|
|
167
|
-
├── .cursor/mcp.json # → Cursor MCP config
|
|
168
|
-
├── .cursor/rules/main.mdc # → Cursor always-apply rule
|
|
169
|
-
├── .opencode/skills/job-forge.md # → skill router
|
|
170
|
-
├── .opencode/agents/ # → @general-free, @general-paid, @glm-minimal
|
|
171
|
-
├── modes/ # → _shared.md + skill modes
|
|
172
|
-
├── templates/ # → states.yml, portals.example.yml, cv-template.html, canon.json, score.json, timeline.json, prioritize.json, capabilities.json, context.json, index.json, facts.json, preflight.json, postflight.json, redact.json, migrations.json
|
|
173
|
-
├── batch/batch-prompt.md # → batch worker prompt
|
|
174
|
-
├── batch/batch-runner.sh # → parallel orchestrator
|
|
175
|
-
│
|
|
176
|
-
└── node_modules/job-forge/ # the harness (from npm: `job-forge@2.x`)
|
|
177
|
-
```
|
|
167
|
+
- [Setup](docs/SETUP.md) - full install paths, personalization, tracker setup, token tracking, troubleshooting.
|
|
168
|
+
- [Architecture](docs/ARCHITECTURE.md) - consumer vs harness split, modes, scripts, batch flow, generated config.
|
|
169
|
+
- [Customization](docs/CUSTOMIZATION.md) - profile, archetypes, scanner keywords, states, templates, local overrides.
|
|
170
|
+
- [Model Routing](docs/MODEL-ROUTING.md) - subagent tiers and how to change model routing.
|
|
171
|
+
- [Examples](examples/README.md) - fictional CVs, sample JD, and sample report.
|
|
172
|
+
- [Batch Runner](batch/README.md) - TSV format, durable batch runner, merge flow.
|
|
173
|
+
- [Contributing](CONTRIBUTING.md) - branch workflow and quality checks.
|
|
178
174
|
|
|
179
|
-
|
|
175
|
+
## Troubleshooting
|
|
180
176
|
|
|
181
|
-
|
|
177
|
+
`sync-check` fails before your CV/profile are complete. That is expected until `cv.md` and `config/profile.yml` are filled in.
|
|
182
178
|
|
|
183
|
-
|
|
184
|
-
JobForge/
|
|
185
|
-
├── iso/ # ← SOURCE OF TRUTH for harness configuration
|
|
186
|
-
│ ├── instructions.md # → AGENTS.md + CLAUDE.md (Claude Code / Codex / Cursor)
|
|
187
|
-
│ ├── mcp.json # → .mcp.json + .cursor/mcp.json + .codex/config.toml + opencode.json
|
|
188
|
-
│ ├── agents/*.md # → .opencode/agents/*.md (general-free, general-paid, glm-minimal)
|
|
189
|
-
│ ├── commands/job-forge.md # → .opencode/skills/job-forge.md
|
|
190
|
-
│ └── config.json # per-harness top-level extras (e.g. opencode `instructions` array)
|
|
191
|
-
│
|
|
192
|
-
├── package.json # bin: job-forge, create-job-forge; prepack runs iso-harness
|
|
193
|
-
├── bin/
|
|
194
|
-
│ ├── job-forge.mjs # CLI dispatcher (merge/verify/pdf/tokens/sync/...)
|
|
195
|
-
│ ├── sync.mjs # postinstall: creates symlinks in consumer project
|
|
196
|
-
│ └── create-job-forge.mjs # scaffolder
|
|
197
|
-
├── modes/ # _shared.md + 16 skill modes
|
|
198
|
-
├── templates/ # cv-template.html, portals.example.yml, states.yml, canon.json, score.json, timeline.json, prioritize.json, capabilities.json, context.json, facts.json, preflight.json, postflight.json, redact.json, migrations.json
|
|
199
|
-
├── config/profile.example.yml # template for consumer's profile.yml
|
|
200
|
-
├── batch/{batch-prompt.md,batch-runner.sh} # batch orchestrator
|
|
201
|
-
├── scripts/
|
|
202
|
-
│ ├── batch-orchestrator.mjs # iso-orchestrator-backed batch control loop
|
|
203
|
-
│ ├── tracker-line.mjs # iso-contract-backed tracker TSV renderer
|
|
204
|
-
│ ├── ledger.mjs # iso-ledger-backed workflow-state CLI
|
|
205
|
-
│ ├── capabilities.mjs # iso-capabilities-backed role policy CLI
|
|
206
|
-
│ ├── context.mjs # iso-context-backed context bundle CLI
|
|
207
|
-
│ ├── cache.mjs # iso-cache-backed local artifact cache CLI
|
|
208
|
-
│ ├── index.mjs # iso-index-backed artifact lookup CLI
|
|
209
|
-
│ ├── facts.mjs # iso-facts-backed local fact materialization
|
|
210
|
-
│ ├── timeline.mjs # iso-timeline-backed follow-up planning CLI
|
|
211
|
-
│ ├── prioritize.mjs # iso-prioritize-backed next-action ranking
|
|
212
|
-
│ ├── lineage.mjs # iso-lineage-backed stale artifact checks
|
|
213
|
-
│ ├── score.mjs # iso-score-backed offer scoring CLI
|
|
214
|
-
│ ├── canon.mjs # iso-canon-backed identity normalization CLI
|
|
215
|
-
│ ├── preflight.mjs # iso-preflight-backed dispatch planning CLI
|
|
216
|
-
│ ├── postflight.mjs # iso-postflight-backed dispatch settlement CLI
|
|
217
|
-
│ ├── redact.mjs # iso-redact-backed safe-export redaction CLI
|
|
218
|
-
│ ├── migrate.mjs # iso-migrate-backed consumer-project migrations
|
|
219
|
-
│ ├── token-usage-report.mjs # opencode cost analyzer
|
|
220
|
-
│ └── release/check-source.mjs # version gate for npm publish
|
|
221
|
-
├── tracker-lib.mjs / merge-tracker.mjs / dedup-tracker.mjs / verify-pipeline.mjs
|
|
222
|
-
├── normalize-statuses.mjs / generate-pdf.mjs / cv-sync-check.mjs
|
|
223
|
-
├── dashboard/ # optional Go TUI
|
|
224
|
-
├── fonts/ # Space Grotesk + DM Sans (for PDF)
|
|
225
|
-
├── docs/ # architecture, setup, customization
|
|
226
|
-
└── .github/workflows/ # quality.yml + release.yml (CI publish to npm)
|
|
227
|
-
```
|
|
179
|
+
If symlinks look stale after moving a project, run:
|
|
228
180
|
|
|
229
|
-
|
|
181
|
+
```bash
|
|
182
|
+
npx job-forge sync
|
|
183
|
+
```
|
|
230
184
|
|
|
231
|
-
|
|
185
|
+
If PDF or browser automation fails, start with:
|
|
232
186
|
|
|
233
|
-
|
|
187
|
+
```bash
|
|
188
|
+
opencode mcp list
|
|
189
|
+
```
|
|
234
190
|
|
|
235
|
-
|
|
236
|
-
- [Architecture](docs/ARCHITECTURE.md) — package architecture, modes, evaluation flow, batch runner, pipeline scripts
|
|
237
|
-
- [Customization](docs/CUSTOMIZATION.md) — archetypes, scanner keywords, CV template, states, customizing symlinked modes
|
|
238
|
-
- [Model Routing](docs/MODEL-ROUTING.md) — the three cost-tiered subagents, why the architecture exists, and how to swap models or add your own
|
|
239
|
-
- [Contributing](CONTRIBUTING.md) — branch workflow, quality gate, and ideas for PRs
|
|
191
|
+
Then see [docs/SETUP.md](docs/SETUP.md#troubleshooting) for Geometra, Gmail, dashboard, tracker, and merge troubleshooting.
|
|
240
192
|
|
|
241
193
|
## License
|
|
242
194
|
|
package/bin/create-job-forge.mjs
CHANGED
|
@@ -240,7 +240,11 @@ const opencodeCfg = {
|
|
|
240
240
|
mcp: {
|
|
241
241
|
geometra: {
|
|
242
242
|
type: 'local',
|
|
243
|
-
command: ['npx', '-
|
|
243
|
+
command: ['npx', '--no-install', 'job-forge', 'mcp:geometra'],
|
|
244
|
+
environment: {
|
|
245
|
+
GEOMETRA_STEALTH: '1',
|
|
246
|
+
GEOMETRA_BROWSER: 'stealth',
|
|
247
|
+
},
|
|
244
248
|
enabled: true,
|
|
245
249
|
},
|
|
246
250
|
gmail: {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { dirname, resolve } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_FALLBACK_PACKAGE = '@geometra/mcp@1.61.3';
|
|
9
|
+
const RESOLVE_ONLY_FLAG = '--job-forge-resolve-target';
|
|
10
|
+
|
|
11
|
+
function normalizeEnv(value) {
|
|
12
|
+
if (typeof value !== 'string') return null;
|
|
13
|
+
const trimmed = value.trim();
|
|
14
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveExplicitPath(rawPath) {
|
|
18
|
+
const resolvedPath = resolve(rawPath);
|
|
19
|
+
if (!existsSync(resolvedPath)) {
|
|
20
|
+
throw new Error(`JOB_FORGE_GEOMETRA_MCP_PATH points to a missing file: ${resolvedPath}`);
|
|
21
|
+
}
|
|
22
|
+
return resolvedPath;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function resolveGeometraMcpLaunchTarget() {
|
|
26
|
+
const explicitPath = normalizeEnv(process.env.JOB_FORGE_GEOMETRA_MCP_PATH);
|
|
27
|
+
if (explicitPath) {
|
|
28
|
+
const resolvedPath = resolveExplicitPath(explicitPath);
|
|
29
|
+
return {
|
|
30
|
+
source: 'env-path',
|
|
31
|
+
command: process.execPath,
|
|
32
|
+
args: [resolvedPath],
|
|
33
|
+
resolvedPath,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
38
|
+
const siblingRepoPath = resolve(scriptDir, '../../geometra/mcp/dist/index.js');
|
|
39
|
+
if (existsSync(siblingRepoPath)) {
|
|
40
|
+
return {
|
|
41
|
+
source: 'sibling-repo',
|
|
42
|
+
command: process.execPath,
|
|
43
|
+
args: [siblingRepoPath],
|
|
44
|
+
resolvedPath: siblingRepoPath,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const packageSpec = normalizeEnv(process.env.JOB_FORGE_GEOMETRA_MCP_PACKAGE) ?? DEFAULT_FALLBACK_PACKAGE;
|
|
49
|
+
return {
|
|
50
|
+
source: 'npm-package',
|
|
51
|
+
command: 'npx',
|
|
52
|
+
args: ['-y', packageSpec],
|
|
53
|
+
packageSpec,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
58
|
+
const target = resolveGeometraMcpLaunchTarget();
|
|
59
|
+
|
|
60
|
+
if (argv.length === 1 && argv[0] === RESOLVE_ONLY_FLAG) {
|
|
61
|
+
process.stdout.write(`${JSON.stringify(target, null, 2)}\n`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const child = spawn(target.command, [...target.args, ...argv], {
|
|
66
|
+
stdio: 'inherit',
|
|
67
|
+
env: process.env,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
child.on('error', (error) => {
|
|
71
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
child.on('exit', (code, signal) => {
|
|
76
|
+
if (signal) {
|
|
77
|
+
process.kill(process.pid, signal);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
process.exit(code ?? 0);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
85
|
+
void main();
|
|
86
|
+
}
|
package/bin/job-forge.mjs
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* normalize Run normalize-statuses.mjs
|
|
17
17
|
* pdf Run generate-pdf.mjs
|
|
18
18
|
* sync-check Run cv-sync-check.mjs
|
|
19
|
+
* mcp:geometra Launch Geometra MCP via JobForge's local/npm resolver
|
|
19
20
|
* tokens Run scripts/token-usage-report.mjs
|
|
20
21
|
* trace:* Inspect local agent transcripts via iso-trace
|
|
21
22
|
* telemetry:* Summarize JobForge pipeline status from traces + tracker files
|
|
@@ -55,6 +56,7 @@ const commands = {
|
|
|
55
56
|
normalize: 'normalize-statuses.mjs',
|
|
56
57
|
pdf: 'generate-pdf.mjs',
|
|
57
58
|
'sync-check': 'cv-sync-check.mjs',
|
|
59
|
+
'mcp:geometra': 'bin/geometra-mcp-launcher.mjs',
|
|
58
60
|
tokens: 'scripts/token-usage-report.mjs',
|
|
59
61
|
sync: 'bin/sync.mjs',
|
|
60
62
|
// Deterministic helpers — agents call these instead of deriving values
|
|
@@ -244,6 +246,7 @@ Commands:
|
|
|
244
246
|
normalize Normalize status values across the tracker
|
|
245
247
|
pdf Generate ATS-optimized CV PDF from cv.md
|
|
246
248
|
sync-check Lint: verify cv.md and profile.yml are filled in
|
|
249
|
+
mcp:geometra Launch Geometra MCP, preferring local JobForge/Geometra dev wiring
|
|
247
250
|
tokens Show opencode token usage and cost by session/day
|
|
248
251
|
trace Pass through to iso-trace (e.g. job-forge trace sources)
|
|
249
252
|
trace:list List recent local agent sessions (defaults: --since 7d --cwd project)
|
package/docs/SETUP.md
CHANGED
|
@@ -214,7 +214,7 @@ Use it to identify which sessions or models are consuming the most tokens. The `
|
|
|
214
214
|
`sync-check` requires `cv.md` and `config/profile.yml` with the fields checked in `cv-sync-check.mjs`. Until you finish the profile and CV steps, that is normal.
|
|
215
215
|
|
|
216
216
|
**PDF generation fails**
|
|
217
|
-
The scaffolded `opencode.json` already registers Geometra MCP; if it's not running, check `opencode mcp list` and verify the scaffolded config under the `mcp.geometra` key — its `command` MUST be `["npx", "-
|
|
217
|
+
The scaffolded `opencode.json` already registers Geometra MCP; if it's not running, check `opencode mcp list` and verify the scaffolded config under the `mcp.geometra` key — its `command` MUST be `["npx", "--no-install", "job-forge", "mcp:geometra"]`, `enabled: true`, and its `environment` should include `GEOMETRA_STEALTH=1` (or equivalently `GEOMETRA_BROWSER=stealth`) so proxy-backed portal sessions default to CloakBrowser's patched Chromium. `job-forge mcp:geometra` prefers `JOB_FORGE_GEOMETRA_MCP_PATH` when set, otherwise a sibling `../geometra/mcp/dist/index.js` checkout for local JobForge development, and otherwise falls back to the pinned npm package. Geometra manages Chromium via its built-in proxy. JobForge still passes `stealth: true` for portal sessions explicitly; the env block keeps the default aligned for auto-spawned sessions and local debugging. For standalone CLI usage (outside opencode), `generate-pdf.mjs` also works with standalone Playwright/Chromium — install with `npx playwright install chromium`.
|
|
218
218
|
|
|
219
219
|
**Symlinks are missing or pointing to a stale path**
|
|
220
220
|
Run `npx job-forge sync` (or `npm run sync`) to recreate them. This happens if you move the project directory after installing, or if `postinstall` didn't run (rare — check `npm install` output for errors).
|
package/iso/mcp.json
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
"servers": {
|
|
3
3
|
"geometra": {
|
|
4
4
|
"command": "npx",
|
|
5
|
-
"args": ["-
|
|
5
|
+
"args": ["--no-install", "job-forge", "mcp:geometra"],
|
|
6
|
+
"env": {
|
|
7
|
+
"GEOMETRA_STEALTH": "1",
|
|
8
|
+
"GEOMETRA_BROWSER": "stealth"
|
|
9
|
+
}
|
|
6
10
|
},
|
|
7
11
|
"gmail": {
|
|
8
12
|
"command": "npx",
|
|
@@ -128,7 +128,7 @@ The Geometra MCP partitions its reusable-proxy pool by proxy identity and browse
|
|
|
128
128
|
"geometra": {
|
|
129
129
|
"type": "stdio",
|
|
130
130
|
"command": "npx",
|
|
131
|
-
"args": ["-
|
|
131
|
+
"args": ["--no-install", "job-forge", "mcp:geometra"]
|
|
132
132
|
},
|
|
133
133
|
"gmail": {
|
|
134
134
|
"type": "stdio",
|
|
@@ -139,4 +139,6 @@ The Geometra MCP partitions its reusable-proxy pool by proxy identity and browse
|
|
|
139
139
|
}
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
`job-forge mcp:geometra` resolves Geometra in this order: `JOB_FORGE_GEOMETRA_MCP_PATH` if set, then a sibling local `../geometra/mcp/dist/index.js` checkout for maintainers working across both repos, then the pinned npm fallback.
|
|
143
|
+
|
|
142
144
|
To check or modify MCP settings, edit `opencode.json` in the project root.
|
package/opencode.json
CHANGED
|
@@ -17,10 +17,14 @@
|
|
|
17
17
|
"type": "local",
|
|
18
18
|
"command": [
|
|
19
19
|
"npx",
|
|
20
|
-
"-
|
|
21
|
-
"
|
|
20
|
+
"--no-install",
|
|
21
|
+
"job-forge",
|
|
22
|
+
"mcp:geometra"
|
|
22
23
|
],
|
|
23
|
-
"environment": {
|
|
24
|
+
"environment": {
|
|
25
|
+
"GEOMETRA_STEALTH": "1",
|
|
26
|
+
"GEOMETRA_BROWSER": "stealth"
|
|
27
|
+
}
|
|
24
28
|
},
|
|
25
29
|
"gmail": {
|
|
26
30
|
"type": "local",
|