job-forge 2.0.0 → 2.0.1

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/README.md CHANGED
@@ -19,17 +19,17 @@
19
19
  ## Quick Start
20
20
 
21
21
  ```bash
22
- npx github:razroo/JobForge create-job-forge my-job-search
22
+ npx --package=job-forge create-job-forge my-job-search
23
23
  cd my-job-search
24
24
  npm install
25
25
  opencode
26
26
  ```
27
27
 
28
- The scaffolded `opencode.json` already has the Geometra MCP (browser automation + PDF) and Gmail MCP (reading replies) wired up — they launch automatically the first time opencode starts.
28
+ The scaffolded `opencode.json` already has the Geometra MCP (browser automation + PDF) and Gmail MCP (reading replies) wired up — they launch automatically the first time opencode starts. `npm install` also materializes symlinks for every supported agent harness — OpenCode, Cursor, Claude Code, and Codex — so you can run `opencode`, `cursor`, `claude`, or `codex` in the same project and each picks up the shared MCP config and instructions.
29
29
 
30
30
  Then fill in `cv.md`, `config/profile.yml`, and `portals.yml` with your personal data, paste a job URL into opencode, and JobForge evaluates + tracks it.
31
31
 
32
- **Upgrade later:** `npm run update-harness` (pulls latest harness + fallback plugin, re-syncs symlinks, prints the resolved commit)
32
+ **Upgrade later:** `npm run update-harness` (pulls latest `job-forge` from npm, re-syncs symlinks, prints the resolved version)
33
33
 
34
34
  Full setup guide and alternative install paths (including contributing to the harness itself): **[docs/SETUP.md](docs/SETUP.md)**.
35
35
 
@@ -125,61 +125,74 @@ You paste a job URL or description
125
125
 
126
126
  ## Project Structure
127
127
 
128
- **Your personal project** (after `npx create-job-forge my-search`):
128
+ **Your personal project** (after `npx --package=job-forge create-job-forge my-search`):
129
129
 
130
130
  ```
131
131
  my-search/
132
- ├── package.json # depends on "job-forge" (github:razroo/JobForge)
133
- ├── opencode.json # thin config — enables MCPs + states.yml
134
- ├── cv.md # your CV (personal)
135
- ├── article-digest.md # your proof points (optional, personal)
136
- ├── portals.yml # companies you want to scan (personal)
137
- ├── config/profile.yml # your identity, target roles (personal)
138
- ├── data/ # applications, pipeline, scan history (personal, gitignored)
139
- ├── reports/ # generated evaluation reports (personal, gitignored)
140
- ├── batch/
141
- ├── batch-input.tsv # URLs to batch-evaluate (personal)
142
- ├── batch-state.tsv # resumable batch state (personal)
143
- ├── tracker-additions/ # TSVs waiting to merge (personal)
144
- ├── logs/ # per-worker logs (personal, gitignored)
145
- ├── batch-prompt.md # → symlink to node_modules/job-forge/
146
- │ └── batch-runner.sh # → symlink to node_modules/job-forge/
147
- ├── modes/ # → symlink to node_modules/job-forge/modes/
148
- ├── templates/ # → symlink to node_modules/job-forge/templates/
149
- ├── .opencode/skills/job-forge.md # → symlink to node_modules/job-forge/
150
- └── node_modules/job-forge/ # the harness (fetched from github:razroo/JobForge)
132
+ ├── package.json # depends on "job-forge": "^2.0.0" (npm registry)
133
+ ├── opencode.json # thin config — enables MCPs + states.yml
134
+ ├── cv.md # your CV (personal)
135
+ ├── article-digest.md # your proof points (optional, personal)
136
+ ├── portals.yml # companies to scan (personal)
137
+ ├── config/profile.yml # your identity, target roles (personal)
138
+ ├── data/ # applications, pipeline, scan history (personal, gitignored)
139
+ ├── reports/ # generated evaluation reports (personal, gitignored)
140
+ ├── batch/{batch-input,batch-state}.tsv, tracker-additions/, logs/ # personal
141
+ ├── AGENTS.md # personal overrides (opencode + codex)
142
+ ├── CLAUDE.md # personal overrides (Claude Code), @-imports CLAUDE.harness.md
143
+
144
+ │ # ↓ symlinks into node_modules/job-forge/, regenerated by postinstall sync.mjs
145
+ ├── AGENTS.harness.md # → harness instructions (loaded via opencode.json)
146
+ ├── CLAUDE.harness.md # → harness instructions (imported from personal CLAUDE.md)
147
+ ├── .mcp.json # → Claude Code MCP config
148
+ ├── .codex/config.toml # → Codex MCP config
149
+ ├── .cursor/mcp.json # → Cursor MCP config
150
+ ├── .cursor/rules/main.mdc # Cursor always-apply rule
151
+ ├── .opencode/skills/job-forge.md # → skill router
152
+ ├── .opencode/agents/ # → @general-free, @general-paid, @glm-minimal
153
+ ├── modes/ # → _shared.md + skill modes
154
+ ├── templates/ # → states.yml, portals.example.yml, cv-template.html
155
+ ├── batch/batch-prompt.md # → batch worker prompt
156
+ ├── batch/batch-runner.sh # → parallel orchestrator
157
+
158
+ └── node_modules/job-forge/ # the harness (from npm: `job-forge@2.x`)
151
159
  ```
152
160
 
153
161
  Symlinks are regenerated on every `npm install` via the package's `postinstall` hook. You never have to know about harness internals — just edit `cv.md`, `portals.yml`, and `config/profile.yml`.
154
162
 
155
- **The harness itself** (this repo, what gets installed into `node_modules/job-forge/`):
163
+ **The harness itself** (this repo, what gets published as `job-forge` on npm):
156
164
 
157
165
  ```
158
166
  JobForge/
159
- ├── package.json # bin: job-forge, create-job-forge
167
+ ├── iso/ # SOURCE OF TRUTH for harness configuration
168
+ │ ├── instructions.md # → AGENTS.md + CLAUDE.md (Claude Code / Codex / Cursor)
169
+ │ ├── mcp.json # → .mcp.json + .cursor/mcp.json + .codex/config.toml + opencode.json
170
+ │ ├── agents/*.md # → .opencode/agents/*.md (general-free, general-paid, glm-minimal)
171
+ │ ├── commands/job-forge.md # → .opencode/skills/job-forge.md
172
+ │ └── config.json # per-harness top-level extras (e.g. opencode `instructions` array)
173
+
174
+ ├── package.json # bin: job-forge, create-job-forge; prepack runs iso-harness
160
175
  ├── bin/
161
- │ ├── job-forge.mjs # CLI dispatcher (merge/verify/pdf/tokens/sync/...)
162
- │ ├── sync.mjs # postinstall: creates symlinks in consumer project
163
- │ └── create-job-forge.mjs # npx create-job-forge scaffolder
164
- ├── .opencode/skills/job-forge.md # the skill router
165
- ├── modes/ # _shared.md + 16 skill modes
166
- ├── templates/ # cv-template.html, portals.example.yml, states.yml
167
- ├── config/profile.example.yml # template for consumer's profile.yml
168
- ├── batch/batch-prompt.md # batch worker prompt template
169
- ├── batch/batch-runner.sh # parallel orchestrator
170
- ├── scripts/token-usage-report.mjs # opencode cost analyzer
171
- ├── tracker-lib.mjs # shared tracker read/write helper
172
- ├── merge-tracker.mjs # merge batch TSVs → tracker
173
- ├── dedup-tracker.mjs # remove dupes
174
- ├── verify-pipeline.mjs # pipeline integrity checks
175
- ├── normalize-statuses.mjs # canonicalize status values
176
- ├── generate-pdf.mjs # CV PDF generator
177
- ├── cv-sync-check.mjs # setup lint
178
- ├── dashboard/ # optional Go TUI
179
- ├── fonts/ # Space Grotesk + DM Sans (for PDF)
180
- └── docs/ # architecture, setup, customization
176
+ │ ├── job-forge.mjs # CLI dispatcher (merge/verify/pdf/tokens/sync/...)
177
+ │ ├── sync.mjs # postinstall: creates symlinks in consumer project
178
+ │ └── create-job-forge.mjs # scaffolder
179
+ ├── modes/ # _shared.md + 16 skill modes
180
+ ├── templates/ # cv-template.html, portals.example.yml, states.yml
181
+ ├── config/profile.example.yml # template for consumer's profile.yml
182
+ ├── batch/{batch-prompt.md,batch-runner.sh} # batch orchestrator
183
+ ├── scripts/
184
+ ├── token-usage-report.mjs # opencode cost analyzer
185
+ │ └── release/check-source.mjs # version gate for npm publish
186
+ ├── tracker-lib.mjs / merge-tracker.mjs / dedup-tracker.mjs / verify-pipeline.mjs
187
+ ├── normalize-statuses.mjs / generate-pdf.mjs / cv-sync-check.mjs
188
+ ├── dashboard/ # optional Go TUI
189
+ ├── fonts/ # Space Grotesk + DM Sans (for PDF)
190
+ ├── docs/ # architecture, setup, customization
191
+ └── .github/workflows/ # quality.yml + release.yml (CI publish to npm)
181
192
  ```
182
193
 
194
+ All per-harness config trees (`.opencode/`, `.cursor/`, `.claude/`, `.codex/`, `CLAUDE.md`, `AGENTS.md`, `.mcp.json`, `opencode.json`) are **generated** from `iso/` by [`@razroo/iso-harness`](https://www.npmjs.com/package/@razroo/iso-harness) and gitignored in this repo. `npm run build:config` regenerates them locally; `prepack` regenerates them into the tarball at publish time so consumers get everything pre-baked.
195
+
183
196
  ## Documentation
184
197
 
185
198
  Index and cross-links: [docs/README.md](docs/README.md).
@@ -117,7 +117,7 @@ const consumerPkg = {
117
117
  'update-harness': 'npm update job-forge @razroo/opencode-model-fallback @razroo/gmail-mcp @geometra/mcp && job-forge sync && node -e "console.log(\'✅ harness at\', require(\'./package-lock.json\').packages[\'node_modules/job-forge\'].resolved)"',
118
118
  },
119
119
  dependencies: {
120
- 'job-forge': 'github:razroo/JobForge',
120
+ 'job-forge': '^2.0.0',
121
121
  // Model-fallback plugin: rotates agents through their fallback_models
122
122
  // chain on rate-limit / 5xx errors so a rate-limited free-tier model
123
123
  // doesn't wedge the whole flow. The chains live upstream in each
@@ -2,31 +2,42 @@
2
2
 
3
3
  ## Package architecture (v2.0.0+)
4
4
 
5
- JobForge ships as an npm package. There are two kinds of repo involved:
5
+ JobForge ships as an npm package at [`job-forge`](https://www.npmjs.com/package/job-forge). There are two kinds of repo involved:
6
6
 
7
- - **Harness** — this repo, `razroo/JobForge`. Installable via `github:razroo/JobForge` (no npm registry). Contains modes, scripts, skill router, templates, fonts, dashboard, and bin entries.
8
- - **Consumer project** — what users interact with day-to-day. Scaffolded via `npx create-job-forge <dir>`, or hand-authored with `job-forge` listed in `package.json` dependencies.
7
+ - **Harness** — this repo, `razroo/JobForge`. Published to npm. Contains `iso/` (single source of truth), modes, scripts, skill router, templates, fonts, dashboard, and bin entries. Per-harness config trees are **generated** from `iso/` by [`@razroo/iso-harness`](https://www.npmjs.com/package/@razroo/iso-harness) — gitignored here, baked into the tarball by `prepack` at publish time, and landed in consumer projects via symlinks.
8
+ - **Consumer project** — what users interact with day-to-day. Scaffolded via `npx --package=job-forge create-job-forge <dir>`, or hand-authored with `job-forge` listed in `package.json` dependencies.
9
9
 
10
- The consumer's project root contains only personal data:
10
+ The consumer's project root contains personal data plus symlinks into `node_modules/job-forge/`:
11
11
 
12
12
  ```
13
13
  my-search/
14
- ├── package.json # depends on "job-forge"
15
- ├── opencode.json # instructions: ["templates/states.yml"]
16
- ├── cv.md # personal
17
- ├── config/profile.yml # personal
18
- ├── portals.yml # personal
19
- ├── data/ # personal (gitignored)
20
- ├── reports/ # personal (gitignored)
21
- ├── modes/ # symlink to node_modules/job-forge/modes/
22
- ├── templates/ # symlink to node_modules/job-forge/templates/
23
- ├── .opencode/skills/job-forge.md # → symlink
24
- ├── batch/batch-prompt.md # symlink
25
- ├── batch/batch-runner.sh # → symlink
26
- └── node_modules/job-forge/ # harness, fetched from github
14
+ ├── package.json # depends on "job-forge": "^2.0.0"
15
+ ├── opencode.json # instructions: ["templates/states.yml"]
16
+ ├── cv.md # personal
17
+ ├── config/profile.yml # personal
18
+ ├── portals.yml # personal
19
+ ├── data/ # personal (gitignored)
20
+ ├── reports/ # personal (gitignored)
21
+ ├── AGENTS.md # personal overrides (opencode + codex)
22
+ ├── CLAUDE.md # personal overrides (Claude Code); @-imports CLAUDE.harness.md
23
+
24
+ # symlinks regenerated on every `npm install` by bin/sync.mjs
25
+ ├── AGENTS.harness.md # → node_modules/job-forge/AGENTS.md
26
+ ├── CLAUDE.harness.md # → node_modules/job-forge/CLAUDE.md
27
+ ├── .mcp.json # → Claude Code MCP config
28
+ ├── .codex/config.toml # → Codex MCP config
29
+ ├── .cursor/mcp.json # → Cursor MCP config
30
+ ├── .cursor/rules/main.mdc # → Cursor always-apply rule
31
+ ├── .opencode/skills/job-forge.md # → skill router
32
+ ├── .opencode/agents/ # → @general-free, @general-paid, @glm-minimal
33
+ ├── modes/ # → mode files
34
+ ├── templates/ # → states.yml, portals.example.yml, cv-template.html
35
+ ├── batch/batch-prompt.md # → batch worker prompt
36
+ ├── batch/batch-runner.sh # → parallel orchestrator
37
+ └── node_modules/job-forge/ # harness, installed from npm
27
38
  ```
28
39
 
29
- Symlinks are created by the harness's `postinstall` hook (`bin/sync.mjs`) on every `npm install`. They are gitignored in the scaffolder template. Real files at those paths are preserved — if a user locally customizes a mode file, the sync skips that symlink and warns.
40
+ Symlinks are created by the harness's `postinstall` hook (`bin/sync.mjs`) on every `npm install`. Real files at those paths are preserved — if a user locally customizes a mode file, the sync skips that symlink and warns.
30
41
 
31
42
  The consumer's `opencode.json` loads a small set of stable files as always-present instructions: `AGENTS.harness.md` (harness operational rules), `templates/states.yml` (canonical application states), `modes/_shared.md` (scoring model), and `cv.md` (the candidate's CV). Caching these in the prefix means agents never Read them as tool calls. Churning content (score calibration anchors, specific mode files) stays out of `instructions` and is Read on demand.
32
43
 
@@ -34,7 +45,9 @@ The skill router (`.opencode/skills/job-forge.md`) loads mode and data files on
34
45
 
35
46
  **Cost-tiered subagents** live in `.opencode/agents/` (`general-free`, `general-paid`, `glm-minimal`) — the orchestrator delegates procedural work to free-tier models and reserves paid models for quality-sensitive writing. See [MODEL-ROUTING.md](MODEL-ROUTING.md) for the routing architecture, why it exists, and how to customize.
36
47
 
37
- **Upgrading** the harness in a consumer project is `npm run update-harness` fetches the latest harness (`github:razroo/JobForge`) and `@razroo/opencode-model-fallback` plugin, re-runs symlink sync, and prints the resolved commit SHA.
48
+ **Multi-harness support.** Because `iso/` is the single source of truth, publishing ships config for OpenCode, Cursor, Claude Code, and Codex in one tarball. Consumers run any of `opencode`, `cursor`, `claude`, or `codex` in the project and each picks up the shared MCP config + instructions via the symlinks above.
49
+
50
+ **Upgrading** the harness in a consumer project is `npm run update-harness` — pulls the latest `job-forge` from npm, refreshes the fallback plugin + pinned MCPs, re-runs symlink sync, and prints the resolved version.
38
51
 
39
52
  ## System Overview
40
53
 
package/docs/README.md CHANGED
@@ -4,12 +4,12 @@ Guides for installing JobForge, understanding how pieces fit together, and tailo
4
4
 
5
5
  ## Install paths
6
6
 
7
- JobForge ships as an installable package (v2.0.0+). Pick the path that matches your goal:
7
+ JobForge ships on npm as [`job-forge`](https://www.npmjs.com/package/job-forge) (v2.0.0+). Pick the path that matches your goal:
8
8
 
9
9
  | Path | Who it's for | How |
10
10
  |------|--------------|-----|
11
- | **A — Scaffold a personal project** | Most users. You want a job search project with the harness in `node_modules`, updatable via `npm update job-forge`. | `npx github:razroo/JobForge create-job-forge my-search && cd my-search && npm install` |
12
- | **B — Clone the harness directly** | Contributors and hackers working on modes, scripts, or the scoring model. Personal files are gitignored. | `git clone https://github.com/razroo/JobForge.git && cd JobForge && npm install` |
11
+ | **A — Scaffold a personal project** | Most users. You want a job search project with the harness in `node_modules`, updatable via `npm update job-forge`. | `npx --package=job-forge create-job-forge my-search && cd my-search && npm install` |
12
+ | **B — Clone the harness directly** | Contributors and hackers working on `iso/`, modes, scripts, or the scoring model. Personal files are gitignored. | `git clone https://github.com/razroo/JobForge.git && cd JobForge && npm install && npm run build:config` |
13
13
 
14
14
  See [SETUP.md](SETUP.md) for both paths.
15
15
 
package/docs/SETUP.md CHANGED
@@ -10,16 +10,22 @@
10
10
 
11
11
  ### Path A — Scaffold a personal project (recommended)
12
12
 
13
- JobForge is distributed as an installable npm package. Use the scaffolder to create a new project that keeps only your personal data (CV, profile, portals, tracker) while the harness (modes, skills, scripts) lives in `node_modules/job-forge` and updates with one command.
13
+ JobForge is published on npm as [`job-forge`](https://www.npmjs.com/package/job-forge). Use the scaffolder to create a new project that keeps only your personal data (CV, profile, portals, tracker) while the harness (modes, skills, scripts, per-harness configs) lives in `node_modules/job-forge` and updates with one command.
14
14
 
15
15
  ```bash
16
16
  # 1. Scaffold
17
- npx github:razroo/JobForge create-job-forge my-job-search
17
+ npx --package=job-forge create-job-forge my-job-search
18
18
  cd my-job-search
19
19
 
20
- # 2. Install the harness (pulls razroo/JobForge from GitHub; postinstall
21
- # creates symlinks for modes/, templates/, .opencode/skills/job-forge.md,
22
- # and batch/{batch-prompt.md,batch-runner.sh,README.md})
20
+ # 2. Install the harness. `npm install` fetches job-forge@^2.0.0 from npm;
21
+ # its postinstall hook creates symlinks into your project root for:
22
+ # .opencode/{skills/job-forge.md, agents/}
23
+ # .cursor/mcp.json, .cursor/rules/main.mdc
24
+ # .mcp.json (Claude Code MCP config)
25
+ # .codex/config.toml (Codex MCP config)
26
+ # AGENTS.harness.md, CLAUDE.harness.md
27
+ # modes/, templates/
28
+ # batch/{batch-prompt.md, batch-runner.sh, README.md}
23
29
  npm install
24
30
 
25
31
  # 3. Fill in personal files
@@ -41,18 +47,25 @@ Paste a job URL or run `/job-forge` to see the command menu.
41
47
  To **upgrade the harness** later:
42
48
 
43
49
  ```bash
44
- npm update job-forge # pulls latest razroo/JobForge
50
+ npm update job-forge # pulls latest job-forge from the npm registry
45
51
  npx job-forge sync # refresh symlinks if anything drifted
46
52
  ```
47
53
 
54
+ Or simpler, via the scaffolded script: `npm run update-harness` (also refreshes the fallback plugin + pinned MCPs, reprints the resolved version).
55
+
48
56
  ### Path B — Clone the harness directly
49
57
 
50
- Use this if you want to hack on the harness itself (add modes, tune the scoring model, contribute back). Personal files are gitignored.
58
+ Use this if you want to hack on the harness itself (edit `iso/`, tune the scoring model, add modes, contribute back). Personal files are gitignored.
51
59
 
52
60
  ```bash
53
61
  git clone https://github.com/razroo/JobForge.git
54
62
  cd JobForge
55
63
  npm install
64
+ npm run build:config # regenerate per-harness trees from iso/ (CLAUDE.md,
65
+ # AGENTS.md, .mcp.json, .codex/, .cursor/, .opencode/,
66
+ # opencode.json) — these are gitignored but materialized
67
+ # locally so OpenCode/Cursor/Claude Code/Codex can read
68
+ # them while you develop
56
69
 
57
70
  # Add personal files the same way as Path A
58
71
  cp config/profile.example.yml config/profile.yml
@@ -60,7 +73,7 @@ cp templates/portals.example.yml portals.yml
60
73
  # Create cv.md in the project root
61
74
  ```
62
75
 
63
- When you're inside this repo, the `postinstall` symlink step is a no-op (detected and skipped). All npm scripts run the harness code directly. The repo's `opencode.json` at the project root registers the same Geometra + Gmail MCPs as the scaffolder ships to consumers.
76
+ When you're inside this repo, the `postinstall` symlink step is a no-op (detected and skipped). All npm scripts run the harness code directly. The repo's generated `opencode.json` at the project root registers the same Geometra + Gmail MCPs as the scaffolder ships to consumers. Re-run `npm run build:config` any time you edit something under `iso/`; `prepack` runs the same build automatically at publish time so tarballs always match `iso/`.
64
77
 
65
78
  ## Personalization
66
79
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job-forge",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "AI-powered job search pipeline built on opencode",
5
5
  "type": "module",
6
6
  "bin": {