job-forge 2.14.33 → 2.14.35
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/.cursor/rules/main.mdc +11 -49
- package/AGENTS.md +11 -49
- package/CLAUDE.md +11 -49
- package/README.md +8 -4
- package/bin/create-job-forge.mjs +42 -0
- package/bin/job-forge.mjs +69 -0
- package/docs/ARCHITECTURE.md +18 -3
- package/docs/CUSTOMIZATION.md +8 -0
- package/docs/README.md +2 -2
- package/docs/SETUP.md +4 -0
- package/iso/instructions.md +11 -49
- package/lib/jobforge-lineage.mjs +122 -0
- package/lib/jobforge-prioritize.mjs +294 -0
- package/modes/README.md +2 -0
- package/modes/reference-local-helpers.md +55 -0
- package/package.json +19 -2
- package/scripts/check-helper-integration.mjs +143 -0
- package/scripts/check-iso-smoke.mjs +4 -2
- package/scripts/lineage.mjs +247 -0
- package/scripts/prioritize.mjs +323 -0
- package/templates/migrations.json +17 -0
- package/templates/prioritize.json +125 -0
- package/verify-pipeline.mjs +48 -0
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -18,6 +18,8 @@ my-search/
|
|
|
18
18
|
├── portals.yml # personal
|
|
19
19
|
├── data/ # personal (gitignored)
|
|
20
20
|
├── .jobforge-ledger/ # local workflow events (personal, gitignored)
|
|
21
|
+
├── .jobforge-prioritize.json # next-action ranking (generated, gitignored)
|
|
22
|
+
├── .jobforge-lineage.json # report/PDF lineage checks (generated, gitignored)
|
|
21
23
|
├── reports/ # personal (gitignored)
|
|
22
24
|
├── AGENTS.md # personal overrides (opencode + codex)
|
|
23
25
|
├── CLAUDE.md # personal overrides (Claude Code); @-imports CLAUDE.harness.md
|
|
@@ -32,7 +34,7 @@ my-search/
|
|
|
32
34
|
├── .opencode/skills/job-forge.md # → skill router
|
|
33
35
|
├── .opencode/agents/ # → @general-free, @general-paid, @glm-minimal
|
|
34
36
|
├── modes/ # → mode files
|
|
35
|
-
├── templates/ # → states.yml, portals.example.yml, cv-template.html, score.json, timeline.json, preflight.json, postflight.json
|
|
37
|
+
├── templates/ # → states.yml, portals.example.yml, cv-template.html, score.json, timeline.json, prioritize.json, preflight.json, postflight.json
|
|
36
38
|
├── batch/batch-prompt.md # → batch worker prompt
|
|
37
39
|
├── batch/batch-runner.sh # → parallel orchestrator
|
|
38
40
|
└── node_modules/job-forge/ # harness, installed from npm
|
|
@@ -164,6 +166,8 @@ data/pipeline.md → Pending URLs and `local:jds/...` inbox (see modes/p
|
|
|
164
166
|
.jobforge-index.json → Deterministic artifact lookup index built from templates/index.json
|
|
165
167
|
.jobforge-facts.json → Deterministic fact set built from templates/facts.json
|
|
166
168
|
.jobforge-timeline.json → Deterministic follow-up action plan built from templates/timeline.json
|
|
169
|
+
.jobforge-prioritize.json → Deterministic next-action priority queue built from templates/prioritize.json
|
|
170
|
+
.jobforge-lineage.json → Artifact lineage graph for stale report/PDF checks
|
|
167
171
|
jds/*.md → Saved job descriptions referenced from the pipeline (`local:jds/{file}`)
|
|
168
172
|
templates/states.yml → Canonical status values
|
|
169
173
|
templates/canon.json → Canonical URL/company/role identity keys
|
|
@@ -171,6 +175,7 @@ templates/score.json → Canonical weighted scoring rubric and gates
|
|
|
171
175
|
templates/context.json → Deterministic mode/reference context bundle policy
|
|
172
176
|
templates/facts.json → Source-backed fact extraction policy
|
|
173
177
|
templates/timeline.json → Follow-up and next-action timing policy
|
|
178
|
+
templates/prioritize.json → Next-action ranking policy
|
|
174
179
|
templates/preflight.json → Safe apply dispatch rounds/gates policy
|
|
175
180
|
templates/postflight.json → Safe apply dispatch settlement policy
|
|
176
181
|
templates/migrations.json → Safe consumer-project upgrade policy
|
|
@@ -189,9 +194,12 @@ Create `data/pipeline.md` when you start using the URL inbox (`/job-forge pipeli
|
|
|
189
194
|
- Index: `.jobforge-index.json` (created on demand by `job-forge index:*`; gitignored local lookup state)
|
|
190
195
|
- Facts: `.jobforge-facts.json` (created on demand by `job-forge facts:*`; gitignored local fact state)
|
|
191
196
|
- Timeline: `.jobforge-timeline.json` (created on demand by `job-forge timeline:*`; gitignored local next-action state)
|
|
197
|
+
- Prioritize: `.jobforge-prioritize.json` and `.jobforge-prioritize-items.json` (created on demand by `job-forge prioritize:*`; gitignored local ranking state)
|
|
198
|
+
- Lineage: `.jobforge-lineage.json` (created by `job-forge lineage:record`; gitignored local stale-output state)
|
|
192
199
|
- Canon: `templates/canon.json` (identity rules inspected with `job-forge canon:*`)
|
|
193
200
|
- Score: `templates/score.json` (weighted rubric and gates inspected with `job-forge score:*`)
|
|
194
201
|
- Timeline policy: `templates/timeline.json` (follow-up windows inspected with `job-forge timeline:*`)
|
|
202
|
+
- Prioritize policy: `templates/prioritize.json` (next-action ranking inspected with `job-forge prioritize:*`)
|
|
195
203
|
- Preflight: `templates/preflight.json` (dispatch rounds/gates inspected with `job-forge preflight:*`)
|
|
196
204
|
- Postflight: `templates/postflight.json` (dispatch outcomes/artifacts/post-steps inspected with `job-forge postflight:*`)
|
|
197
205
|
- Migrations: `templates/migrations.json` (applied by `job-forge sync` and inspectable with `job-forge migrate:*`)
|
|
@@ -200,7 +208,7 @@ Create `data/pipeline.md` when you start using the URL inbox (`/job-forge pipeli
|
|
|
200
208
|
|
|
201
209
|
## Pipeline Integrity
|
|
202
210
|
|
|
203
|
-
From the project root, `npx job-forge verify` (or `npm run verify`) runs `verify-pipeline.mjs`. When a tracker file exists, it validates canonical statuses (using `templates/states.yml` when that file is present and parseable), validates every tracker row against `templates/contracts.json`, warns on probable duplicate company/role rows, checks that report column markdown links resolve to files in the repo, validates score column format (`X.X/5`, `N/A`, or `DUP`), rejects table rows with too few columns, flags markdown bold inside the score column, and warns if any `batch/tracker-additions/*.tsv` files are still waiting to be merged. If `.jobforge-ledger/events.jsonl` exists, verify also validates the append-only ledger. If `.jobforge-index.json` exists, verify validates the artifact index. If `.jobforge-facts.json` exists, verify validates the materialized fact set. If `.jobforge-timeline.json` exists, verify validates the follow-up timeline. It also compares state ids from `templates/states.yml` to an internal fallback list and warns when the two sets drift. **Fresh clone:** the command exits successfully when neither `data/applications.md` nor root `applications.md` exists yet; pending-TSV and states-drift checks still run so contributors see unmerged batch output early. Optional setup validation after you add `cv.md` and `config/profile.yml`: `npm run sync-check` (`cv-sync-check.mjs`).
|
|
211
|
+
From the project root, `npx job-forge verify` (or `npm run verify`) runs `verify-pipeline.mjs`. When a tracker file exists, it validates canonical statuses (using `templates/states.yml` when that file is present and parseable), validates every tracker row against `templates/contracts.json`, warns on probable duplicate company/role rows, checks that report column markdown links resolve to files in the repo, validates score column format (`X.X/5`, `N/A`, or `DUP`), rejects table rows with too few columns, flags markdown bold inside the score column, and warns if any `batch/tracker-additions/*.tsv` files are still waiting to be merged. If `.jobforge-ledger/events.jsonl` exists, verify also validates the append-only ledger. If `.jobforge-index.json` exists, verify validates the artifact index. If `.jobforge-facts.json` exists, verify validates the materialized fact set. If `.jobforge-timeline.json` exists, verify validates the follow-up timeline. If `.jobforge-prioritize.json` exists, verify validates the priority queue. If `.jobforge-lineage.json` exists, verify validates the graph and checks recorded artifacts for stale/missing inputs. It also compares state ids from `templates/states.yml` to an internal fallback list and warns when the two sets drift. **Fresh clone:** the command exits successfully when neither `data/applications.md` nor root `applications.md` exists yet; pending-TSV and states-drift checks still run so contributors see unmerged batch output early. Optional setup validation after you add `cv.md` and `config/profile.yml`: `npm run sync-check` (`cv-sync-check.mjs`).
|
|
204
212
|
|
|
205
213
|
**`verify-pipeline.mjs` checks (same order as the script header):**
|
|
206
214
|
|
|
@@ -217,6 +225,8 @@ From the project root, `npx job-forge verify` (or `npm run verify`) runs `verify
|
|
|
217
225
|
11. Validate `.jobforge-index.json` when present.
|
|
218
226
|
12. Validate `.jobforge-facts.json` when present.
|
|
219
227
|
13. Validate `.jobforge-timeline.json` when present.
|
|
228
|
+
14. Validate `.jobforge-prioritize.json` when present.
|
|
229
|
+
15. Validate/check `.jobforge-lineage.json` when present.
|
|
220
230
|
|
|
221
231
|
When the tracker file is missing, checks 1-6 and 8 are skipped; checks 7, 9, 10, 11, 12, and 13 still run when applicable.
|
|
222
232
|
|
|
@@ -224,7 +234,7 @@ When the tracker file is missing, checks 1-6 and 8 are skipped; checks 7, 9, 10,
|
|
|
224
234
|
|
|
225
235
|
Prefer one focused change per pull request: a single mode under `modes/`, one repository-root `.mjs` utility, documentation under `docs/`, fictional samples under [`examples/`](../examples/README.md), templates such as [`templates/portals.example.yml`](../templates/portals.example.yml), the batch flow described in [`batch/README.md`](../batch/README.md), or the Go TUI under `dashboard/` — not a repo-wide refactor across 3+ of those at once. Branch workflow, the verify + dashboard build gate, and starter ideas are in [CONTRIBUTING.md](../CONTRIBUTING.md) (**What to Contribute** and **Development**). To look for in-repo `TODO`, `FIXME`, or `HACK` markers before choosing a task, use the `rg` one-liner in [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations). Upstream PRs MUST stay generic: do not commit real candidate data (`cv.md`, `config/profile.yml`, personalized `portals.yml`, `data/applications.md`, `reports/`, or similar paths called out in CONTRIBUTING and `.gitignore`).
|
|
226
236
|
|
|
227
|
-
**PR / maintainer gate:** Before opening a pull request against `razroo/JobForge`, run `npm run verify` and `npm run build:dashboard` (or `(cd dashboard && go build .)`) from the harness repo root (same as [CONTRIBUTING.md](../CONTRIBUTING.md#development)). For optional scripted iterations that repeat that gate and commit one small change per pass, see [`scripts/cursor-agent-loop.sh`](../scripts/cursor-agent-loop.sh) (environment variables and usage in the script header; overview in [CONTRIBUTING.md](../CONTRIBUTING.md#optional-scripted-agent-iterations)).
|
|
237
|
+
**PR / maintainer gate:** Before opening a pull request against `razroo/JobForge`, run `npm run verify`, `npm run smoke:iso`, and `npm run build:dashboard` (or `(cd dashboard && go build .)`) from the harness repo root (same as [CONTRIBUTING.md](../CONTRIBUTING.md#development)). `smoke:iso` includes `npm run lint:helpers`, which prevents local helper dependencies, CLI aliases, scaffolder scripts, migrations, generated ignores, templates, docs, and helper reference from drifting. For optional scripted iterations that repeat that gate and commit one small change per pass, see [`scripts/cursor-agent-loop.sh`](../scripts/cursor-agent-loop.sh) (environment variables and usage in the script header; overview in [CONTRIBUTING.md](../CONTRIBUTING.md#optional-scripted-agent-iterations)).
|
|
228
238
|
|
|
229
239
|
Scripts maintain data consistency. In a consumer project they're invoked via the `job-forge` CLI (`npx job-forge <cmd>`); in the harness repo they're also directly runnable as `node <script>.mjs`.
|
|
230
240
|
|
|
@@ -241,9 +251,13 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
|
|
|
241
251
|
| `scripts/telemetry.mjs` | `npx job-forge telemetry:status` / `telemetry:show` | JobForge operational telemetry derived from OpenCode traces plus tracker TSV state |
|
|
242
252
|
| `scripts/guard.mjs` | `npx job-forge guard:audit` / `guard:explain` | Deterministic `@razroo/iso-guard` policy audits over local OpenCode traces |
|
|
243
253
|
| `scripts/ledger.mjs` | `npx job-forge ledger:status` / `ledger:has` / `ledger:rebuild` | Deterministic `@razroo/iso-ledger` state over tracker, TSV, and pipeline files |
|
|
254
|
+
| `scripts/capabilities.mjs` | `npx job-forge capabilities:check` / `capabilities:explain` | Deterministic `@razroo/iso-capabilities` role boundary checks for tools, MCPs, commands, filesystem, and network access |
|
|
255
|
+
| `scripts/cache.mjs` | `npx job-forge cache:has` / `cache:get` / `cache:put` | Deterministic `@razroo/iso-cache` JD and artifact reuse keyed by stable job/url inputs |
|
|
244
256
|
| `scripts/index.mjs` | `npx job-forge index:status` / `index:has` / `index:query` | Deterministic `@razroo/iso-index` lookup over reports, tracker rows, TSVs, pipeline, scan history, and ledger events |
|
|
245
257
|
| `scripts/facts.mjs` | `npx job-forge facts:status` / `facts:has` / `facts:query` | Deterministic `@razroo/iso-facts` materialization over job URLs, scores, application statuses, preflight candidates, scan history, and ledger events |
|
|
246
258
|
| `scripts/timeline.mjs` | `npx job-forge timeline:due` / `timeline:check` / `timeline:build` | Deterministic `@razroo/iso-timeline` follow-up and next-action planning over tracker rows and dated pipeline items |
|
|
259
|
+
| `scripts/prioritize.mjs` | `npx job-forge prioritize:build` / `prioritize:select` / `prioritize:check` | Deterministic `@razroo/iso-prioritize` next-action ranking over materialized facts and due timeline items |
|
|
260
|
+
| `scripts/lineage.mjs` | `npx job-forge lineage:record` / `lineage:check` / `lineage:explain` | Deterministic `@razroo/iso-lineage` stale-output checks for generated reports, PDFs, and their source inputs |
|
|
247
261
|
| `scripts/score.mjs` | `npx job-forge score:check` / `score:gate` / `score:explain` | Deterministic `@razroo/iso-score` checks for weighted offer scores, threshold booleans, recommendations, and score gates |
|
|
248
262
|
| `scripts/canon.mjs` | `npx job-forge canon:normalize` / `canon:key` / `canon:compare` | Deterministic `@razroo/iso-canon` identity normalization for URLs, companies, roles, and company+role pairs |
|
|
249
263
|
| `scripts/context.mjs` | `npx job-forge context:list` / `context:plan` / `context:check` / `context:render` | Deterministic `@razroo/iso-context` mode/reference context bundle planning and rendering |
|
|
@@ -251,6 +265,7 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
|
|
|
251
265
|
| `scripts/postflight.mjs` | `npx job-forge postflight:status` / `postflight:check` / `postflight:explain` | Deterministic `@razroo/iso-postflight` settlement for dispatch outcomes, required tracker TSV artifacts, and merge/verify post-steps |
|
|
252
266
|
| `scripts/redact.mjs` | `npx job-forge redact:scan` / `redact:apply` / `redact:verify` | Deterministic `@razroo/iso-redact` safe-export scanning and sanitization for traces, prompts, reports, and fixtures |
|
|
253
267
|
| `scripts/migrate.mjs` | `npx job-forge migrate:plan` / `migrate:apply` / `migrate:check` | Deterministic `@razroo/iso-migrate` consumer-project upgrades for scripts and generated-artifact ignores |
|
|
268
|
+
| `scripts/check-helper-integration.mjs` | `npm run lint:helpers` | Integration lint that keeps helper packages, scripts, scaffolder defaults, migrations, generated ignores, docs, and `modes/reference-local-helpers.md` aligned |
|
|
254
269
|
| `tracker-lib.mjs` | _(library)_ | Shared helpers for reading/writing day-based tracker files — imported by merge/dedup/verify/normalize |
|
|
255
270
|
| `bin/sync.mjs` | `npx job-forge sync` | Creates the harness symlinks in a consumer project and applies safe migrations (also runs as `postinstall`) |
|
|
256
271
|
| `bin/create-job-forge.mjs` | `npx create-job-forge <dir>` | Scaffolds a new personal project |
|
package/docs/CUSTOMIZATION.md
CHANGED
|
@@ -162,6 +162,14 @@ Fact extraction policy lives in `templates/facts.json` and is built locally by `
|
|
|
162
162
|
|
|
163
163
|
Follow-up and next-action policy lives in `templates/timeline.json` and is planned locally by `@razroo/iso-timeline`. Use `job-forge timeline:due` to list due/overdue nudges, `job-forge timeline:check --fail-on overdue` to fail only when action is stale, and `job-forge timeline:build` to materialize `.jobforge-timeline-events.jsonl` plus `.jobforge-timeline.json` for inspection. It reads tracker rows and dated pipeline items from local files, so scaffolded projects need no setup. This is not an MCP and does not add prompt or tool-schema tokens.
|
|
164
164
|
|
|
165
|
+
## JobForge priority queue
|
|
166
|
+
|
|
167
|
+
Next-action ranking policy lives in `templates/prioritize.json` and is planned locally by `@razroo/iso-prioritize`. Use `job-forge prioritize:build` to materialize `.jobforge-prioritize-items.json` plus `.jobforge-prioritize.json`, `job-forge prioritize:select --limit 3` to inspect the selected queue, and `job-forge prioritize:check` when a workflow must fail if no actionable candidate is selected. It reads source-backed facts and due timeline items, so scaffolded projects need no setup. This is not an MCP and does not add prompt or tool-schema tokens.
|
|
168
|
+
|
|
169
|
+
## JobForge artifact lineage
|
|
170
|
+
|
|
171
|
+
Artifact lineage lives in `.jobforge-lineage.json` and is checked locally by `@razroo/iso-lineage`. Use `job-forge lineage:record --artifact <report-or-pdf> --input cv.md --input config/profile.yml` after generating an artifact, then `job-forge lineage:check` or `job-forge lineage:check --artifact <file>` to detect stale outputs after source inputs change. This is not an MCP and does not add prompt or tool-schema tokens.
|
|
172
|
+
|
|
165
173
|
## JobForge scoring policy
|
|
166
174
|
|
|
167
175
|
Weighted scoring policy lives in `templates/score.json` and is enforced locally by `@razroo/iso-score`. Use `job-forge score:check --input <score.json>` to validate emitted report score JSON, `job-forge score:gate --input <score.json> --gate apply` to check an application threshold, and `job-forge score:explain` to inspect the active dimensions, weights, bands, and gates. Custom forks can change weights or thresholds in `templates/score.json`, but keep the dimension ids aligned with `modes/_shared.md` and report rendering.
|
package/docs/README.md
CHANGED
|
@@ -31,10 +31,10 @@ The harness exposes a single CLI (`job-forge`) installed as a `bin` entry. In a
|
|
|
31
31
|
|
|
32
32
|
| What you need | Where to read |
|
|
33
33
|
|---------------|---------------|
|
|
34
|
-
| Full command list (`verify`, `merge`, `dedup`, `normalize`, `pdf`, `sync-check`, `tokens`, `trace`, `telemetry`, `guard`, `ledger`, `
|
|
34
|
+
| Full command list (`verify`, `merge`, `dedup`, `normalize`, `pdf`, `sync-check`, `tokens`, `trace`, `telemetry`, `guard`, `ledger`, `capabilities`, `context`, `cache`, `index`, `facts`, `score`, `canon`, `timeline`, `prioritize`, `lineage`, `preflight`, `postflight`, `redact`, `migrate`, `sync`). | [SETUP.md — Tracker and scripts (terminal)](SETUP.md#tracker-and-scripts-terminal). |
|
|
35
35
|
| What each harness `.mjs` script does. | [ARCHITECTURE.md — Pipeline integrity](ARCHITECTURE.md#pipeline-integrity) and the scripts table underneath. |
|
|
36
36
|
| Batch runner, TSV layout, and `batch/tracker-additions/` merge flow. | [batch/README.md](../batch/README.md). |
|
|
37
|
-
| PR gate for harness contributions (`npm run verify` + `npm run build:dashboard`). | [CONTRIBUTING.md — Development](../CONTRIBUTING.md#development). |
|
|
37
|
+
| PR gate for harness contributions (`npm run verify` + `npm run smoke:iso` + `npm run build:dashboard`). | [CONTRIBUTING.md — Development](../CONTRIBUTING.md#development). |
|
|
38
38
|
| Optional scripted iterations (harness repo only). | [scripts/cursor-agent-loop.sh](../scripts/cursor-agent-loop.sh). Usage and env vars live in the script header and in [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations). Verbose JSON output is formatted by [cursor-agent-stream-format.py](../scripts/cursor-agent-stream-format.py). |
|
|
39
39
|
| Work-marker search (`T`ODO, `F`IXME, `H`ACK strings in the source) before picking work. | [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations) — `rg` one-liner from the harness repo root. |
|
|
40
40
|
|
package/docs/SETUP.md
CHANGED
|
@@ -137,6 +137,8 @@ From your project root, these commands maintain the tracker and pipeline checks.
|
|
|
137
137
|
| Inspect local materialized facts | `npx job-forge facts:status` | `npm run facts:status` |
|
|
138
138
|
| Show due follow-up actions | `npx job-forge timeline:due` | `npm run timeline:due` |
|
|
139
139
|
| Fail on stale follow-up actions | `npx job-forge timeline:check --fail-on overdue` | `npm run timeline:check -- --fail-on overdue` |
|
|
140
|
+
| Rank next actions from facts and timeline | `npx job-forge prioritize:build` / `npx job-forge prioritize:select --limit 3` | `npm run prioritize:build` |
|
|
141
|
+
| Check report/PDF lineage for stale inputs | `npx job-forge lineage:check` | `npm run lineage:check` |
|
|
140
142
|
| Plan safe application dispatch rounds | `npx job-forge preflight:plan --candidates batch/preflight-candidates.json` | `npm run preflight:plan -- --candidates ...` |
|
|
141
143
|
| Fail on blocked preflight candidates | `npx job-forge preflight:check --candidates batch/preflight-candidates.json` | `npm run preflight:check -- --candidates ...` |
|
|
142
144
|
| Settle dispatch outcomes after a round | `npx job-forge postflight:status --plan batch/preflight-plan.json --outcomes batch/postflight-outcomes.json` | `npm run postflight:status -- --plan ... --outcomes ...` |
|
|
@@ -164,6 +166,8 @@ From your project root, these commands maintain the tracker and pipeline checks.
|
|
|
164
166
|
| Query local artifact pointers | `npx job-forge index:query "Acme"` / `npx job-forge index:has --key company-role:acme:staff-engineer` | `npm run index:query -- Acme` |
|
|
165
167
|
| Query local source-backed facts | `npx job-forge facts:query --fact job.url` / `npx job-forge facts:has --fact application.status --key company-role:acme:staff-engineer` | `npm run facts:query -- --fact job.url` |
|
|
166
168
|
| Materialize follow-up timeline | `npx job-forge timeline:build` | `npm run timeline:build` |
|
|
169
|
+
| Materialize next-action priority queue | `npx job-forge prioritize:build` | `npm run prioritize:build` |
|
|
170
|
+
| Record artifact lineage | `npx job-forge lineage:record --artifact reports/123-acme.md --input cv.md --input config/profile.yml` | `npm run lineage:record -- --artifact ...` |
|
|
167
171
|
| Apply safe consumer migrations | `npx job-forge migrate:apply` | `npm run migrate:apply` |
|
|
168
172
|
| Re-create harness symlinks | `npx job-forge sync` | `npm run sync` |
|
|
169
173
|
| Build optional dashboard TUI (Go on `PATH`) | `(cd node_modules/job-forge/dashboard && go build .)` | `npm run build:dashboard` (harness repo only) |
|
package/iso/instructions.md
CHANGED
|
@@ -19,13 +19,13 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
19
19
|
- [H5] Re-dispatch the same company only AFTER the previous subagent returns. Never fire the same `task` twice while the first is still in flight.
|
|
20
20
|
why: two in-flight subagents for the same URL race on Geometra sessions and on tracker TSV writes, corrupting state and sometimes double-submitting
|
|
21
21
|
|
|
22
|
-
- [H5b] Do not use `task` to poll task status. If OpenCode returns a task/session id without a final result, record the id, stop dispatching new rounds, and tell the user the round is still in flight. When the user asks to check later, inspect authoritative files (`batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`, day files, `.jobforge-ledger/events.jsonl`, `.jobforge-index.json`, `.jobforge-facts.json`, `.jobforge-timeline.json`, or `iso-trace`) rather than spawning a "check task status" subagent.
|
|
22
|
+
- [H5b] Do not use `task` to poll task status. If OpenCode returns a task/session id without a final result, record the id, stop dispatching new rounds, and tell the user the round is still in flight. When the user asks to check later, inspect authoritative files (`batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`, day files, `.jobforge-ledger/events.jsonl`, `.jobforge-index.json`, `.jobforge-facts.json`, `.jobforge-timeline.json`, `.jobforge-prioritize.json`, `.jobforge-lineage.json`, or `iso-trace`) rather than spawning a "check task status" subagent.
|
|
23
23
|
why: OpenCode status prompts can be delivered into the target subagent as a new user message; a 2026-04-25 trace caused a subagent to call `task` recursively instead of finishing the application
|
|
24
24
|
|
|
25
25
|
- [H6] Application outcomes flow through `batch/tracker-additions/*.tsv`, not `data/pipeline.md`. After any multi-apply run, the orchestrator MUST run `npx job-forge merge` then `npx job-forge verify` before ending the session.
|
|
26
26
|
why: `pipeline.md` is the URL inbox (`[ ]` pending → `[x]` processed); `data/applications/YYYY-MM-DD.md` is the outcome log; the TSV pathway is the only safe bridge because `merge` handles column order and duplicate detection
|
|
27
27
|
|
|
28
|
-
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, emitted score JSON validated by `npx job-forge score:check --input ...`, `batch/tracker-additions/*.tsv`, cached JD content returned by `npx job-forge cache:get --url ...`, source path/line pointers returned by `npx job-forge index:query ...`,
|
|
28
|
+
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, emitted score JSON validated by `npx job-forge score:check --input ...`, `batch/tracker-additions/*.tsv`, cached JD content returned by `npx job-forge cache:get --url ...`, source path/line pointers returned by `npx job-forge index:query ...`, materialized fact records returned by `npx job-forge facts:query ...`, selected next actions returned by `npx job-forge prioritize:select ...`, and lineage records returned by `npx job-forge lineage:explain ...`.
|
|
29
29
|
why: 2026-04-18 scan subagent returned 30 fabricated Greenhouse IDs in prose (plausible-looking, non-existent); orchestrator dispatched 30 downstream subagents that all 404'd. Subagents can hallucinate IDs, scores, and confirmation text — round-trip through a file or don't trust the value
|
|
30
30
|
|
|
31
31
|
- [H8] Never paste proxy values from `config/profile.yml` into `task` prompts, status text, or summaries. If a proxy is configured, tell the subagent exactly: "Proxy is configured; read `config/profile.yml` and pass its top-level `proxy:` object to every `geometra_connect` call." Do not transcribe `server`, `username`, `password`, or `bypass`, even if you just read them from disk.
|
|
@@ -54,60 +54,21 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
54
54
|
- [D7] For standalone `batch` runs, prefer `batch/batch-runner.sh` instead of hand-rolling the loop. It delegates to `@razroo/iso-orchestrator`, persists workflow records in `.jobforge-runs/`, caps bundle fan-out, and mutexes state/report-number writes. Use `JOBFORGE_LEGACY_BATCH_RUNNER=1` only as a fallback.
|
|
55
55
|
why: the old Bash loop encoded resumability and parallelism manually; the iso-orchestrator path makes the durable control state inspectable and prevents report-number collisions under parallel bundles
|
|
56
56
|
|
|
57
|
-
- [D8] Use
|
|
58
|
-
why:
|
|
59
|
-
|
|
60
|
-
- [D9] Treat `templates/contracts.json` as the source of truth for machine-readable artifacts. Prefer `npx job-forge tracker-line ... --write` for tracker additions; if emitting TSV manually, inspect `npx iso-contract explain jobforge.tracker-row --contracts templates/contracts.json` first. `merge` and `verify` enforce the tracker-row contract locally.
|
|
61
|
-
why: deterministic code owns the exact tracker TSV/table shape; repeated prose gets re-tokenized and agents occasionally misremember it
|
|
62
|
-
|
|
63
|
-
- [D10] Treat `templates/capabilities.json` as the source of truth for role capability boundaries. Use `npx job-forge capabilities:explain <role>` or `npx job-forge capabilities:check <role> ...` when changing or validating subagent tool/MCP/filesystem/command permissions; do not paste the full capability matrix into task prompts.
|
|
64
|
-
why: executable local policy prevents role-permission drift without adding MCP/tool-schema tokens or loading a capability matrix into the shared prefix
|
|
65
|
-
|
|
66
|
-
- [D11] Treat `templates/context.json` as the source of truth for mode/reference context bundles. Use `npx job-forge context:plan <mode>` or `npx job-forge context:check <mode>` when changing or validating what a mode loads; do not paste the full context matrix into prompts.
|
|
67
|
-
why: deterministic context bundles prevent reference-file drift and accidental token bloat without adding MCP/tool-schema tokens
|
|
68
|
-
|
|
69
|
-
- [D12] Use `job-forge cache:*` for deterministic local artifact reuse when available. For URL inputs, check `npx job-forge cache:has --url "..."` / `cache:get` before browser or network JD fetches; after a successful fetch, store the exact JD text with `npx job-forge cache:put --url "..." --ttl 14d --input @file` when it is already on disk.
|
|
70
|
-
why: `iso-cache` is not an MCP and adds no prompt/tool-schema tokens; it avoids repeated JD fetch/render passes and lets future sessions reuse stable content from `.jobforge-cache/`
|
|
71
|
-
|
|
72
|
-
- [D13] Use `job-forge index:*` for deterministic artifact lookup when available. `index:has` and `index:query` rebuild `.jobforge-index.json` from `templates/index.json` on demand, covering reports, tracker day files, tracker TSVs, pipeline URLs, scan history, and ledger events without loading those growing files into prompt context.
|
|
73
|
-
why: `iso-index` is not an MCP and adds no prompt/tool-schema tokens; it gives agents compact file/line pointers and duplicate prefilters before expensive reads or browser dispatches
|
|
74
|
-
|
|
75
|
-
- [D13b] Use `job-forge facts:*` for deterministic source-backed fact materialization when available. `facts:has` and `facts:query` rebuild `.jobforge-facts.json` from `templates/facts.json` on demand, covering job URLs, scores, application statuses, tracker TSVs, preflight candidates, scan history, and ledger events with path/line provenance.
|
|
76
|
-
why: `iso-facts` is not an MCP and adds no prompt/tool-schema tokens; it turns authoritative files into compact queryable fact records so agents do not repeatedly reread broad artifact trees
|
|
77
|
-
|
|
78
|
-
- [D14] Treat `templates/migrations.json` as the source of truth for consumer-project upgrades. Use `npx job-forge migrate:plan` or `npx job-forge migrate:check` when diagnosing harness drift; `job-forge sync` applies safe migrations automatically unless `JOB_FORGE_SKIP_MIGRATIONS=1` is set.
|
|
79
|
-
why: `iso-migrate` is not an MCP and adds no prompt/tool-schema tokens; it prevents stale consumer scripts and generated-artifact ignores without asking agents to hand-edit package.json
|
|
80
|
-
|
|
81
|
-
- [D15] Treat `templates/canon.json` as the source of truth for URL/company/role identity keys. Use `npx job-forge canon:key ...` or `npx job-forge canon:compare ...` before broad duplicate checks when a stable key or same/possible/different decision is useful.
|
|
82
|
-
why: `iso-canon` is not an MCP and adds no prompt/tool-schema tokens; it centralizes duplicate-key rules so agents do not repeatedly derive inconsistent slugs for aliases, suffixes, remote/location noise, or tracking URLs
|
|
83
|
-
|
|
84
|
-
- [D16] Treat `templates/preflight.json` as the source of truth for multi-apply dispatch safety. After candidate facts and gates are materialized from authoritative files, run `npx job-forge preflight:plan --candidates <file>` or `npx job-forge preflight:check --candidates <file>` before task dispatch; follow the emitted rounds and pre/post steps. This does not replace H2 four-source grep until those facts are materialized into the candidate JSON.
|
|
85
|
-
why: `iso-preflight` is not an MCP and adds no prompt/tool-schema tokens; it turns file-backed facts, duplicate/location gates, max-two rounds, and cleanup/merge/verify steps into an executable local plan instead of repeated prose
|
|
86
|
-
|
|
87
|
-
- [D17] Treat `templates/postflight.json` as the source of truth for multi-apply dispatch settlement. Save the JSON preflight plan and per-round observed dispatch/outcome/artifact records, then run `npx job-forge postflight:status --plan <plan.json> --outcomes <outcomes.json>` after each round and `npx job-forge postflight:check ...` after merge/verify. Follow its next action instead of inferring completion from subagent prose.
|
|
88
|
-
why: `iso-postflight` is not an MCP and adds no prompt/tool-schema tokens; it makes "round complete", missing TSVs, failed candidates, replacements, merge, and verify an executable local gate instead of repeated orchestration prose
|
|
89
|
-
|
|
90
|
-
- [D18] Treat `templates/redact.json` as the source of truth before exporting local traces, prompts, reports, or fixtures outside the project. Use `npx job-forge redact:scan --input <file>`, `redact:apply --input <file> --output .jobforge-redacted/<file>`, or `redact:verify --input <file>` instead of hand-redacting with prose. This complements H8; it does not make it acceptable to paste secrets into prompts.
|
|
91
|
-
why: `iso-redact` is not an MCP and adds no prompt/tool-schema tokens; it gives deterministic safe-export checks whose findings do not print matched secret values
|
|
92
|
-
|
|
93
|
-
- [D19] Treat `templates/score.json` as the source of truth for offer scoring weights, bands, and gates. After emitting a report score JSON that will drive PDF/application/batch decisions, run `npx job-forge score:check --input <file>`; for apply decisions run `npx job-forge score:gate --input <file> --gate apply`. Do not recalculate weighted totals or thresholds manually when the local helper can check them.
|
|
94
|
-
why: `iso-score` is not an MCP and adds no prompt/tool-schema tokens; it makes scoring math, recommendation bands, and threshold booleans executable local policy instead of repeated model prose
|
|
95
|
-
|
|
96
|
-
- [D20] Treat `templates/timeline.json` as the source of truth for follow-up and next-action timing. For follow-up triage, run `npx job-forge timeline:due` before reading tracker files; use `npx job-forge timeline:check --fail-on overdue` when a workflow must fail only on stale actions. Use `timeline:build` when a durable `.jobforge-timeline.json` artifact is useful.
|
|
97
|
-
why: `iso-timeline` is not an MCP and adds no prompt/tool-schema tokens; it turns timing windows over tracker/pipeline sources into executable local policy instead of repeated date math in model context
|
|
57
|
+
- [D8] Use deterministic local helpers instead of prose when they can answer or validate state, identity, policy, scoring, timing, dispatch, priority, lineage, migration, or safe-export questions. Read `modes/reference-local-helpers.md` when choosing a helper or changing helper wiring.
|
|
58
|
+
why: the helper ecosystem is now broad enough that repeating every command in the shared prefix wastes cache budget; the reference keeps operational details on demand while `npm run lint:helpers` enforces integration drift in code
|
|
98
59
|
|
|
99
60
|
## Procedure
|
|
100
61
|
|
|
101
62
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
102
63
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
103
|
-
3. Read the active mode file [D3]. Use
|
|
104
|
-
4. Prepare Geometra dispatches: cleanup [H3],
|
|
105
|
-
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b], then settle the round with postflight status [
|
|
64
|
+
3. Read the active mode file [D3]. Use local helpers when they can replace broad file reads, prose math, manual policy checks, or artifact reuse decisions [D8]. Decide inline vs delegated work [D1].
|
|
65
|
+
4. Prepare Geometra dispatches: cleanup [H3], local-helper prefilters when useful [D8], dedupe [H2], location filter [D5], file-backed preflight plan/check [D8], routing [D2], proxy prompt hygiene [H8].
|
|
66
|
+
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b], then settle the round with postflight status [D8].
|
|
106
67
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
107
68
|
7. Cross-check subagent facts against authoritative files [H7].
|
|
108
|
-
8. Apply score gate [D4,
|
|
109
|
-
9. Merge contract-validated TSV outcomes [H6,
|
|
110
|
-
10. Verify tracker and run postflight check before ending [H6,
|
|
69
|
+
8. Apply score gate [D4, D8].
|
|
70
|
+
9. Merge contract-validated TSV outcomes [H6, D8].
|
|
71
|
+
10. Verify tracker and run postflight check before ending [H6, D8].
|
|
111
72
|
|
|
112
73
|
## Routing
|
|
113
74
|
|
|
@@ -142,6 +103,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
|
|
|
142
103
|
The sections above are the shared contract. Load detailed context on demand:
|
|
143
104
|
|
|
144
105
|
- `modes/{mode}.md` for the active mode procedure, output shape, and mode-specific routing.
|
|
106
|
+
- `modes/reference-local-helpers.md` for deterministic local helper selection, mandatory uses, and enforcement.
|
|
145
107
|
- `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
|
|
146
108
|
- `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
|
|
147
109
|
- `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'path';
|
|
3
|
+
import {
|
|
4
|
+
checkLineage,
|
|
5
|
+
emptyLineageGraph,
|
|
6
|
+
loadLineageGraph,
|
|
7
|
+
parseJson,
|
|
8
|
+
recordLineage,
|
|
9
|
+
verifyLineageGraph,
|
|
10
|
+
} from '@razroo/iso-lineage';
|
|
11
|
+
|
|
12
|
+
export const LINEAGE_FILE = '.jobforge-lineage.json';
|
|
13
|
+
|
|
14
|
+
export function resolveProjectDir(projectDir = process.env.JOB_FORGE_PROJECT || process.cwd()) {
|
|
15
|
+
return projectDir;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function jobForgeLineagePath(projectDir = resolveProjectDir()) {
|
|
19
|
+
return process.env.JOB_FORGE_LINEAGE || join(projectDir, LINEAGE_FILE);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function lineageExists(projectDir = resolveProjectDir()) {
|
|
23
|
+
return existsSync(jobForgeLineagePath(projectDir));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function readJobForgeLineage(projectDir = resolveProjectDir()) {
|
|
27
|
+
const path = jobForgeLineagePath(projectDir);
|
|
28
|
+
return loadLineageGraph(parseJson(readFileSync(path, 'utf8'), path));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function readJobForgeLineageOrEmpty(projectDir = resolveProjectDir()) {
|
|
32
|
+
return lineageExists(projectDir) ? readJobForgeLineage(projectDir) : emptyLineageGraph();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function writeJobForgeLineage(graph, options = {}, projectDir = resolveProjectDir()) {
|
|
36
|
+
const out = options.out || jobForgeLineagePath(projectDir);
|
|
37
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
38
|
+
writeFileSync(out, `${JSON.stringify(graph, null, 2)}\n`, 'utf8');
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function recordJobForgeLineage(options = {}, projectDir = resolveProjectDir()) {
|
|
43
|
+
const graph = options.graph || readJobForgeLineageOrEmpty(projectDir);
|
|
44
|
+
const updated = recordLineage(graph, {
|
|
45
|
+
root: projectDir,
|
|
46
|
+
artifact: required(options.artifact, '--artifact'),
|
|
47
|
+
inputs: options.inputs || [],
|
|
48
|
+
optionalInputs: options.optionalInputs || [],
|
|
49
|
+
...(options.kind ? { kind: options.kind } : {}),
|
|
50
|
+
...(options.command ? { command: options.command } : {}),
|
|
51
|
+
...(options.now ? { now: options.now } : {}),
|
|
52
|
+
...(options.metadata ? { metadata: options.metadata } : {}),
|
|
53
|
+
});
|
|
54
|
+
const out = writeJobForgeLineage(updated, { out: options.out }, projectDir);
|
|
55
|
+
const artifact = storedPath(projectDir, options.artifact);
|
|
56
|
+
const record = updated.records.find((item) => item.artifact.path === artifact);
|
|
57
|
+
if (!record) throw new Error(`${artifact} was not recorded`);
|
|
58
|
+
return { graph: updated, record, out };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function checkJobForgeLineage(options = {}, projectDir = resolveProjectDir()) {
|
|
62
|
+
const graph = options.graph || readJobForgeLineage(projectDir);
|
|
63
|
+
return checkLineage(graph, {
|
|
64
|
+
root: projectDir,
|
|
65
|
+
...(options.artifact ? { artifact: options.artifact } : {}),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function staleJobForgeLineage(options = {}, projectDir = resolveProjectDir()) {
|
|
70
|
+
return checkJobForgeLineage(options, projectDir);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function verifyJobForgeLineage(options = {}, projectDir = resolveProjectDir()) {
|
|
74
|
+
const graph = options.graph || readJobForgeLineage(projectDir);
|
|
75
|
+
return verifyLineageGraph(graph);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function jobForgeLineageSummary(projectDir = resolveProjectDir()) {
|
|
79
|
+
if (!lineageExists(projectDir)) {
|
|
80
|
+
return {
|
|
81
|
+
path: jobForgeLineagePath(projectDir),
|
|
82
|
+
exists: false,
|
|
83
|
+
records: 0,
|
|
84
|
+
current: 0,
|
|
85
|
+
stale: 0,
|
|
86
|
+
missing: 0,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const graph = readJobForgeLineage(projectDir);
|
|
90
|
+
const result = checkJobForgeLineage({ graph }, projectDir);
|
|
91
|
+
return {
|
|
92
|
+
path: jobForgeLineagePath(projectDir),
|
|
93
|
+
exists: true,
|
|
94
|
+
id: graph.id,
|
|
95
|
+
records: graph.records.length,
|
|
96
|
+
current: result.current,
|
|
97
|
+
stale: result.stale,
|
|
98
|
+
missing: result.missing,
|
|
99
|
+
ok: result.ok,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function normalizeJobForgeLineageArtifact(projectDir = resolveProjectDir(), artifact = '') {
|
|
104
|
+
return storedPath(projectDir, artifact);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function required(value, flag) {
|
|
108
|
+
if (!value) throw new Error(`lineage:record requires ${flag}`);
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function storedPath(root, path) {
|
|
113
|
+
const absRoot = resolve(root);
|
|
114
|
+
const abs = resolve(absRoot, path);
|
|
115
|
+
const rel = relative(absRoot, abs);
|
|
116
|
+
if (rel && !rel.startsWith('..') && !isAbsolute(rel)) return normalizePath(rel);
|
|
117
|
+
return normalizePath(abs);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizePath(path) {
|
|
121
|
+
return path.split(sep).join('/');
|
|
122
|
+
}
|