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/.cursor/rules/main.mdc
CHANGED
|
@@ -24,13 +24,13 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
24
24
|
- [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.
|
|
25
25
|
why: two in-flight subagents for the same URL race on Geometra sessions and on tracker TSV writes, corrupting state and sometimes double-submitting
|
|
26
26
|
|
|
27
|
-
- [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.
|
|
27
|
+
- [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.
|
|
28
28
|
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
|
|
29
29
|
|
|
30
30
|
- [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.
|
|
31
31
|
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
|
|
32
32
|
|
|
33
|
-
- [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 ...`,
|
|
33
|
+
- [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 ...`.
|
|
34
34
|
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
|
|
35
35
|
|
|
36
36
|
- [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.
|
|
@@ -59,60 +59,21 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
59
59
|
- [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.
|
|
60
60
|
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
|
|
61
61
|
|
|
62
|
-
- [D8] Use
|
|
63
|
-
why:
|
|
64
|
-
|
|
65
|
-
- [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.
|
|
66
|
-
why: deterministic code owns the exact tracker TSV/table shape; repeated prose gets re-tokenized and agents occasionally misremember it
|
|
67
|
-
|
|
68
|
-
- [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.
|
|
69
|
-
why: executable local policy prevents role-permission drift without adding MCP/tool-schema tokens or loading a capability matrix into the shared prefix
|
|
70
|
-
|
|
71
|
-
- [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.
|
|
72
|
-
why: deterministic context bundles prevent reference-file drift and accidental token bloat without adding MCP/tool-schema tokens
|
|
73
|
-
|
|
74
|
-
- [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.
|
|
75
|
-
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/`
|
|
76
|
-
|
|
77
|
-
- [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.
|
|
78
|
-
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
|
|
79
|
-
|
|
80
|
-
- [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.
|
|
81
|
-
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
|
|
82
|
-
|
|
83
|
-
- [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.
|
|
84
|
-
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
|
|
85
|
-
|
|
86
|
-
- [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.
|
|
87
|
-
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
|
|
88
|
-
|
|
89
|
-
- [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.
|
|
90
|
-
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
|
|
91
|
-
|
|
92
|
-
- [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.
|
|
93
|
-
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
|
|
94
|
-
|
|
95
|
-
- [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.
|
|
96
|
-
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
|
|
97
|
-
|
|
98
|
-
- [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.
|
|
99
|
-
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
|
|
100
|
-
|
|
101
|
-
- [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.
|
|
102
|
-
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
|
|
62
|
+
- [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.
|
|
63
|
+
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
|
|
103
64
|
|
|
104
65
|
## Procedure
|
|
105
66
|
|
|
106
67
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
107
68
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
108
|
-
3. Read the active mode file [D3]. Use
|
|
109
|
-
4. Prepare Geometra dispatches: cleanup [H3],
|
|
110
|
-
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 [
|
|
69
|
+
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].
|
|
70
|
+
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].
|
|
71
|
+
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].
|
|
111
72
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
112
73
|
7. Cross-check subagent facts against authoritative files [H7].
|
|
113
|
-
8. Apply score gate [D4,
|
|
114
|
-
9. Merge contract-validated TSV outcomes [H6,
|
|
115
|
-
10. Verify tracker and run postflight check before ending [H6,
|
|
74
|
+
8. Apply score gate [D4, D8].
|
|
75
|
+
9. Merge contract-validated TSV outcomes [H6, D8].
|
|
76
|
+
10. Verify tracker and run postflight check before ending [H6, D8].
|
|
116
77
|
|
|
117
78
|
## Routing
|
|
118
79
|
|
|
@@ -147,6 +108,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
|
|
|
147
108
|
The sections above are the shared contract. Load detailed context on demand:
|
|
148
109
|
|
|
149
110
|
- `modes/{mode}.md` for the active mode procedure, output shape, and mode-specific routing.
|
|
111
|
+
- `modes/reference-local-helpers.md` for deterministic local helper selection, mandatory uses, and enforcement.
|
|
150
112
|
- `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
|
|
151
113
|
- `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
|
|
152
114
|
- `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
|
package/AGENTS.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.
|
package/CLAUDE.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.
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ The scaffolded `opencode.json` already has three MCPs wired up — they launch a
|
|
|
31
31
|
- **Gmail** — reads replies from recruiters
|
|
32
32
|
- **state-trace** — typed working memory for cross-session context (resumed batches, recent decisions, repeated portal quirks). Install once with `python3 -m pip install "state-trace[mcp]"`; the MCP command is `state-trace-mcp`.
|
|
33
33
|
|
|
34
|
-
JobForge also keeps MCP-free local workflow state and policy: `templates/canon.json` defines URL/company/role identity keys via `@razroo/iso-canon`, `templates/contracts.json` defines tracker/apply artifact shapes via `@razroo/iso-contract`, `templates/score.json` defines weighted scoring and gates via `@razroo/iso-score`, `templates/timeline.json` defines follow-up and next-action windows via `@razroo/iso-timeline`, `templates/capabilities.json` defines role capability boundaries via `@razroo/iso-capabilities`, `templates/context.json` defines deterministic mode/reference bundles via `@razroo/iso-context`, `templates/preflight.json` defines safe dispatch rounds/gates via `@razroo/iso-preflight`, `templates/postflight.json` defines safe dispatch settlement via `@razroo/iso-postflight`, `templates/redact.json` defines safe-export redaction rules via `@razroo/iso-redact`, `templates/migrations.json` defines safe consumer-project upgrades via `@razroo/iso-migrate`, `templates/facts.json` defines source-backed fact extraction via `@razroo/iso-facts`, `.jobforge-ledger/events.jsonl` records duplicate/status events via `@razroo/iso-ledger`, `.jobforge-cache/` stores reusable JD/artifact content via `@razroo/iso-cache`, `.jobforge-index.json` indexes artifact source pointers via `@razroo/iso-index`, `.jobforge-facts.json` materializes queryable facts with provenance,
|
|
34
|
+
JobForge also keeps MCP-free local workflow state and policy: `templates/canon.json` defines URL/company/role identity keys via `@razroo/iso-canon`, `templates/contracts.json` defines tracker/apply artifact shapes via `@razroo/iso-contract`, `templates/score.json` defines weighted scoring and gates via `@razroo/iso-score`, `templates/timeline.json` defines follow-up and next-action windows via `@razroo/iso-timeline`, `templates/prioritize.json` defines next-action ranking via `@razroo/iso-prioritize`, `templates/capabilities.json` defines role capability boundaries via `@razroo/iso-capabilities`, `templates/context.json` defines deterministic mode/reference bundles via `@razroo/iso-context`, `templates/preflight.json` defines safe dispatch rounds/gates via `@razroo/iso-preflight`, `templates/postflight.json` defines safe dispatch settlement via `@razroo/iso-postflight`, `templates/redact.json` defines safe-export redaction rules via `@razroo/iso-redact`, `templates/migrations.json` defines safe consumer-project upgrades via `@razroo/iso-migrate`, `templates/facts.json` defines source-backed fact extraction via `@razroo/iso-facts`, `.jobforge-ledger/events.jsonl` records duplicate/status events via `@razroo/iso-ledger`, `.jobforge-cache/` stores reusable JD/artifact content via `@razroo/iso-cache`, `.jobforge-index.json` indexes artifact source pointers via `@razroo/iso-index`, `.jobforge-facts.json` materializes queryable facts with provenance, `.jobforge-timeline.json` materializes due/overdue follow-up actions, `.jobforge-prioritize.json` materializes the ranked local priority queue, and `.jobforge-lineage.json` records stale-output checks for generated artifacts via `@razroo/iso-lineage`. None of these add always-on prompt or tool-schema tokens.
|
|
35
35
|
|
|
36
36
|
`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.
|
|
37
37
|
|
|
@@ -78,7 +78,7 @@ JobForge turns opencode into a full job search command center. Instead of manual
|
|
|
78
78
|
| **Durable Batch Orchestration** | `batch-runner.sh` uses `@razroo/iso-orchestrator` for resumable bundle execution, bounded fan-out, mutexed state writes, and workflow records in `.jobforge-runs/`. |
|
|
79
79
|
| **Pipeline Integrity** | Automated merge, dedup, status normalization, health checks |
|
|
80
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 + Preflight + Postflight + Redact + Migrate** | `job-forge trace:*` exposes local OpenCode 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 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. |
|
|
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 OpenCode 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
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. |
|
|
83
83
|
|
|
84
84
|
## Usage
|
|
@@ -150,6 +150,8 @@ my-search/
|
|
|
150
150
|
├── .jobforge-index.json # deterministic artifact lookup index (generated, gitignored)
|
|
151
151
|
├── .jobforge-facts.json # deterministic fact set with provenance (generated, gitignored)
|
|
152
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)
|
|
153
155
|
├── .jobforge-redacted/ # sanitized local exports (generated, gitignored)
|
|
154
156
|
├── reports/ # generated evaluation reports (personal, gitignored)
|
|
155
157
|
├── batch/{batch-input,batch-state}.tsv, tracker-additions/, logs/ # personal
|
|
@@ -167,7 +169,7 @@ my-search/
|
|
|
167
169
|
├── .opencode/skills/job-forge.md # → skill router
|
|
168
170
|
├── .opencode/agents/ # → @general-free, @general-paid, @glm-minimal
|
|
169
171
|
├── modes/ # → _shared.md + skill modes
|
|
170
|
-
├── templates/ # → states.yml, portals.example.yml, cv-template.html, canon.json, score.json, timeline.json, capabilities.json, context.json, index.json, facts.json, preflight.json, postflight.json, redact.json, migrations.json
|
|
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
|
|
171
173
|
├── batch/batch-prompt.md # → batch worker prompt
|
|
172
174
|
├── batch/batch-runner.sh # → parallel orchestrator
|
|
173
175
|
│
|
|
@@ -193,7 +195,7 @@ JobForge/
|
|
|
193
195
|
│ ├── sync.mjs # postinstall: creates symlinks in consumer project
|
|
194
196
|
│ └── create-job-forge.mjs # scaffolder
|
|
195
197
|
├── modes/ # _shared.md + 16 skill modes
|
|
196
|
-
├── templates/ # cv-template.html, portals.example.yml, states.yml, canon.json, score.json, timeline.json, capabilities.json, context.json, facts.json, preflight.json, postflight.json, redact.json, migrations.json
|
|
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
|
|
197
199
|
├── config/profile.example.yml # template for consumer's profile.yml
|
|
198
200
|
├── batch/{batch-prompt.md,batch-runner.sh} # batch orchestrator
|
|
199
201
|
├── scripts/
|
|
@@ -206,6 +208,8 @@ JobForge/
|
|
|
206
208
|
│ ├── index.mjs # iso-index-backed artifact lookup CLI
|
|
207
209
|
│ ├── facts.mjs # iso-facts-backed local fact materialization
|
|
208
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
|
|
209
213
|
│ ├── score.mjs # iso-score-backed offer scoring CLI
|
|
210
214
|
│ ├── canon.mjs # iso-canon-backed identity normalization CLI
|
|
211
215
|
│ ├── preflight.mjs # iso-preflight-backed dispatch planning CLI
|
package/bin/create-job-forge.mjs
CHANGED
|
@@ -154,6 +154,12 @@ const consumerPkg = {
|
|
|
154
154
|
'facts:has': 'job-forge facts:has',
|
|
155
155
|
'facts:query': 'job-forge facts:query',
|
|
156
156
|
'facts:explain': 'job-forge facts:explain',
|
|
157
|
+
'score:compute': 'job-forge score:compute',
|
|
158
|
+
'score:verify': 'job-forge score:verify',
|
|
159
|
+
'score:check': 'job-forge score:check',
|
|
160
|
+
'score:gate': 'job-forge score:gate',
|
|
161
|
+
'score:compare': 'job-forge score:compare',
|
|
162
|
+
'score:explain': 'job-forge score:explain',
|
|
157
163
|
'canon:normalize': 'job-forge canon:normalize',
|
|
158
164
|
'canon:key': 'job-forge canon:key',
|
|
159
165
|
'canon:compare': 'job-forge canon:compare',
|
|
@@ -164,6 +170,31 @@ const consumerPkg = {
|
|
|
164
170
|
'postflight:status': 'job-forge postflight:status',
|
|
165
171
|
'postflight:check': 'job-forge postflight:check',
|
|
166
172
|
'postflight:explain': 'job-forge postflight:explain',
|
|
173
|
+
'timeline:status': 'job-forge timeline:status',
|
|
174
|
+
'timeline:build': 'job-forge timeline:build',
|
|
175
|
+
'timeline:plan': 'job-forge timeline:plan',
|
|
176
|
+
'timeline:due': 'job-forge timeline:due',
|
|
177
|
+
'timeline:check': 'job-forge timeline:check',
|
|
178
|
+
'timeline:verify': 'job-forge timeline:verify',
|
|
179
|
+
'timeline:explain': 'job-forge timeline:explain',
|
|
180
|
+
'prioritize:status': 'job-forge prioritize:status',
|
|
181
|
+
'prioritize:items': 'job-forge prioritize:items',
|
|
182
|
+
'prioritize:build': 'job-forge prioritize:build',
|
|
183
|
+
'prioritize:rank': 'job-forge prioritize:rank',
|
|
184
|
+
'prioritize:select': 'job-forge prioritize:select',
|
|
185
|
+
'prioritize:check': 'job-forge prioritize:check',
|
|
186
|
+
'prioritize:verify': 'job-forge prioritize:verify',
|
|
187
|
+
'prioritize:explain': 'job-forge prioritize:explain',
|
|
188
|
+
'lineage:status': 'job-forge lineage:status',
|
|
189
|
+
'lineage:record': 'job-forge lineage:record',
|
|
190
|
+
'lineage:check': 'job-forge lineage:check',
|
|
191
|
+
'lineage:stale': 'job-forge lineage:stale',
|
|
192
|
+
'lineage:verify': 'job-forge lineage:verify',
|
|
193
|
+
'lineage:explain': 'job-forge lineage:explain',
|
|
194
|
+
'redact:scan': 'job-forge redact:scan',
|
|
195
|
+
'redact:verify': 'job-forge redact:verify',
|
|
196
|
+
'redact:apply': 'job-forge redact:apply',
|
|
197
|
+
'redact:explain': 'job-forge redact:explain',
|
|
167
198
|
'migrate:plan': 'job-forge migrate:plan',
|
|
168
199
|
'migrate:apply': 'job-forge migrate:apply',
|
|
169
200
|
'migrate:check': 'job-forge migrate:check',
|
|
@@ -270,6 +301,8 @@ Before doing any work, remember where things live in *this* project:
|
|
|
270
301
|
| Local workflow ledger | \`.jobforge-ledger/events.jsonl\` | Deterministic append-only state; use \`job-forge ledger:*\` |
|
|
271
302
|
| Local artifact index | \`.jobforge-index.json\` | Deterministic file/line lookup; use \`job-forge index:*\` |
|
|
272
303
|
| Local fact set | \`.jobforge-facts.json\` | Deterministic source-backed facts; use \`job-forge facts:*\` |
|
|
304
|
+
| Local priority queue | \`.jobforge-prioritize.json\` | Deterministic next-action ranking; use \`job-forge prioritize:*\` |
|
|
305
|
+
| Artifact lineage | \`.jobforge-lineage.json\` | Stale report/PDF detection; use \`job-forge lineage:*\` |
|
|
273
306
|
| Identity canonicalization | \`templates/canon.json\` | Stable URL/company/role keys; use \`job-forge canon:*\` |
|
|
274
307
|
| Dispatch preflight policy | \`templates/preflight.json\` | Safe apply rounds/gates; use \`job-forge preflight:*\` |
|
|
275
308
|
| Dispatch postflight policy | \`templates/postflight.json\` | Safe apply settlement; use \`job-forge postflight:*\` |
|
|
@@ -361,11 +394,18 @@ data/applications.md
|
|
|
361
394
|
data/pipeline.md
|
|
362
395
|
data/scan-history.tsv
|
|
363
396
|
data/token-usage.tsv
|
|
397
|
+
data/timeline-events.jsonl
|
|
364
398
|
.jobforge-ledger/
|
|
365
399
|
.jobforge-cache/
|
|
366
400
|
.jobforge-index.json
|
|
367
401
|
.jobforge-facts.json
|
|
402
|
+
.jobforge-timeline.json
|
|
403
|
+
.jobforge-timeline-events.jsonl
|
|
404
|
+
.jobforge-prioritize.json
|
|
405
|
+
.jobforge-prioritize-items.json
|
|
406
|
+
.jobforge-lineage.json
|
|
368
407
|
.jobforge-runs/
|
|
408
|
+
.jobforge-redacted/
|
|
369
409
|
reports/
|
|
370
410
|
!reports/.gitkeep
|
|
371
411
|
batch/batch-state.tsv
|
|
@@ -428,6 +468,8 @@ job-forge verify # verify pipeline integrity
|
|
|
428
468
|
job-forge ledger:status # local deterministic workflow ledger status
|
|
429
469
|
job-forge index:status # local artifact index status
|
|
430
470
|
job-forge facts:status # local source-backed fact status
|
|
471
|
+
job-forge prioritize:status # local next-action priority queue status
|
|
472
|
+
job-forge lineage:status # local artifact lineage status
|
|
431
473
|
job-forge canon:key company-role --company "Acme, Inc." --role "Senior SWE"
|
|
432
474
|
job-forge preflight:plan --candidates batch/preflight-candidates.json
|
|
433
475
|
job-forge postflight:status --plan batch/preflight-plan.json --outcomes batch/postflight-outcomes.json
|
package/bin/job-forge.mjs
CHANGED
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
* preflight:* Plan safe dispatch rounds via iso-preflight
|
|
32
32
|
* postflight:* Settle dispatch outcomes via iso-postflight
|
|
33
33
|
* timeline:* Plan follow-up/next-action windows via iso-timeline
|
|
34
|
+
* prioritize:* Rank local next-action queues via iso-prioritize
|
|
35
|
+
* lineage:* Record artifact lineage and stale outputs via iso-lineage
|
|
34
36
|
* redact:* Sanitize local exports via iso-redact
|
|
35
37
|
* migrate:* Apply deterministic consumer-project migrations via iso-migrate
|
|
36
38
|
* sync Re-run the harness symlink sync (bin/sync.mjs)
|
|
@@ -189,6 +191,28 @@ const timelineAliases = {
|
|
|
189
191
|
'timeline:path': 'path',
|
|
190
192
|
};
|
|
191
193
|
|
|
194
|
+
const prioritizeAliases = {
|
|
195
|
+
'prioritize:status': 'status',
|
|
196
|
+
'prioritize:items': 'items',
|
|
197
|
+
'prioritize:build': 'build',
|
|
198
|
+
'prioritize:rank': 'rank',
|
|
199
|
+
'prioritize:select': 'select',
|
|
200
|
+
'prioritize:check': 'check',
|
|
201
|
+
'prioritize:verify': 'verify',
|
|
202
|
+
'prioritize:explain': 'explain',
|
|
203
|
+
'prioritize:path': 'path',
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const lineageAliases = {
|
|
207
|
+
'lineage:status': 'status',
|
|
208
|
+
'lineage:record': 'record',
|
|
209
|
+
'lineage:check': 'check',
|
|
210
|
+
'lineage:stale': 'stale',
|
|
211
|
+
'lineage:verify': 'verify',
|
|
212
|
+
'lineage:explain': 'explain',
|
|
213
|
+
'lineage:path': 'path',
|
|
214
|
+
};
|
|
215
|
+
|
|
192
216
|
const redactAliases = {
|
|
193
217
|
'redact:scan': 'scan',
|
|
194
218
|
'redact:verify': 'verify',
|
|
@@ -280,6 +304,17 @@ Commands:
|
|
|
280
304
|
timeline:due Show currently due/overdue follow-up actions
|
|
281
305
|
timeline:check Fail on due/overdue timeline actions per policy
|
|
282
306
|
timeline:explain Show the active timeline policy
|
|
307
|
+
prioritize:status Show local next-action priority queue status
|
|
308
|
+
prioritize:build Build .jobforge-prioritize.json from facts/timeline sources
|
|
309
|
+
prioritize:rank Rank apply/follow-up candidates deterministically
|
|
310
|
+
prioritize:select Print selected next actions only
|
|
311
|
+
prioritize:check Fail when selected queue requirements are not met
|
|
312
|
+
prioritize:explain Show the active priority policy
|
|
313
|
+
lineage:status Show local artifact lineage status
|
|
314
|
+
lineage:record Record a report/PDF/derived artifact and its inputs
|
|
315
|
+
lineage:check Fail if recorded artifacts are stale or missing
|
|
316
|
+
lineage:stale List stale or missing recorded artifacts
|
|
317
|
+
lineage:explain Show recorded artifact inputs
|
|
283
318
|
redact:scan Scan local text for sensitive values before export
|
|
284
319
|
redact:verify Fail if local text still contains sensitive values
|
|
285
320
|
redact:apply Write a sanitized copy of local text
|
|
@@ -338,6 +373,10 @@ Pass --help after a command to see its own flags, e.g.:
|
|
|
338
373
|
job-forge postflight:check --plan batch/preflight-plan.json --outcomes batch/postflight-outcomes.json
|
|
339
374
|
job-forge timeline:due
|
|
340
375
|
job-forge timeline:check --fail-on overdue
|
|
376
|
+
job-forge prioritize:build
|
|
377
|
+
job-forge prioritize:select --limit 3
|
|
378
|
+
job-forge lineage:record --artifact reports/123-acme-2026-04-27.md --input cv.md --input config/profile.yml --kind report
|
|
379
|
+
job-forge lineage:check --artifact reports/123-acme-2026-04-27.md
|
|
341
380
|
job-forge redact:scan --input raw-session.jsonl
|
|
342
381
|
job-forge redact:apply --input raw-session.jsonl --output .jobforge-redacted/session.jsonl
|
|
343
382
|
job-forge migrate:check
|
|
@@ -561,6 +600,36 @@ if (cmd === 'timeline' || timelineAliases[cmd]) {
|
|
|
561
600
|
process.exit(result.status ?? 1);
|
|
562
601
|
}
|
|
563
602
|
|
|
603
|
+
if (cmd === 'prioritize' || prioritizeAliases[cmd]) {
|
|
604
|
+
const prioritizeArgs = cmd === 'prioritize'
|
|
605
|
+
? (rest.length === 0 ? ['help'] : rest)
|
|
606
|
+
: [prioritizeAliases[cmd], ...rest];
|
|
607
|
+
|
|
608
|
+
const scriptPath = join(PKG_ROOT, 'scripts/prioritize.mjs');
|
|
609
|
+
const result = spawnSync(process.execPath, [scriptPath, ...prioritizeArgs], {
|
|
610
|
+
stdio: 'inherit',
|
|
611
|
+
cwd: PROJECT_DIR,
|
|
612
|
+
env: process.env,
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
process.exit(result.status ?? 1);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (cmd === 'lineage' || lineageAliases[cmd]) {
|
|
619
|
+
const lineageArgs = cmd === 'lineage'
|
|
620
|
+
? (rest.length === 0 ? ['help'] : rest)
|
|
621
|
+
: [lineageAliases[cmd], ...rest];
|
|
622
|
+
|
|
623
|
+
const scriptPath = join(PKG_ROOT, 'scripts/lineage.mjs');
|
|
624
|
+
const result = spawnSync(process.execPath, [scriptPath, ...lineageArgs], {
|
|
625
|
+
stdio: 'inherit',
|
|
626
|
+
cwd: PROJECT_DIR,
|
|
627
|
+
env: process.env,
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
process.exit(result.status ?? 1);
|
|
631
|
+
}
|
|
632
|
+
|
|
564
633
|
if (cmd === 'redact' || redactAliases[cmd]) {
|
|
565
634
|
const redactArgs = cmd === 'redact'
|
|
566
635
|
? (rest.length === 0 ? ['help'] : rest)
|