job-forge 2.14.33 → 2.14.34
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 +9 -3
- package/AGENTS.md +9 -3
- package/CLAUDE.md +9 -3
- package/README.md +8 -4
- package/bin/create-job-forge.mjs +21 -0
- package/bin/job-forge.mjs +69 -0
- package/docs/ARCHITECTURE.md +12 -2
- package/docs/CUSTOMIZATION.md +8 -0
- package/docs/SETUP.md +4 -0
- package/iso/instructions.md +9 -3
- package/lib/jobforge-lineage.mjs +122 -0
- package/lib/jobforge-prioritize.mjs +294 -0
- package/package.json +17 -1
- package/scripts/check-iso-smoke.mjs +2 -0
- 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.
|
|
@@ -101,11 +101,17 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
101
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
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
|
|
103
103
|
|
|
104
|
+
- [D21] Treat `templates/prioritize.json` as the source of truth for choosing between evaluated applications, candidate facts, and due follow-ups. When the user asks what to do next or when a batch needs replacement candidates, run `npx job-forge prioritize:build` or `npx job-forge prioritize:select --limit N` instead of ranking items in prose.
|
|
105
|
+
why: `iso-prioritize` is not an MCP and adds no prompt/tool-schema tokens; it converts facts and timeline records into a deterministic ranked queue so agents do not reread broad tracker/report trees or invent priorities
|
|
106
|
+
|
|
107
|
+
- [D22] Treat `.jobforge-lineage.json` as the source of truth for whether generated reports/PDFs are current. After creating or refreshing a derived report/PDF, record its inputs with `npx job-forge lineage:record --artifact <file> --input <source>...`; before reusing an old artifact after source changes, run `npx job-forge lineage:check --artifact <file>` or `npx job-forge lineage:check`.
|
|
108
|
+
why: `iso-lineage` is not an MCP and adds no prompt/tool-schema tokens; it detects stale outputs by hashing local files instead of asking agents to remember which CV/profile/report version produced an artifact
|
|
109
|
+
|
|
104
110
|
## Procedure
|
|
105
111
|
|
|
106
112
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
107
113
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
108
|
-
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
114
|
+
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use priority queues when choosing next actions or replacements [D21]. Use lineage checks before reusing generated artifacts [D22]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
109
115
|
4. Prepare Geometra dispatches: cleanup [H3], canon/index/facts/ledger prefilter when useful [D8, D13, D13b, D15], dedupe [H2], location filter [D5], materialize candidate facts/gates and run preflight plan/check [D16], routing [D2, D10], proxy prompt hygiene [H8].
|
|
110
116
|
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 [D17].
|
|
111
117
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
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.
|
|
@@ -96,11 +96,17 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
96
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
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
|
|
98
98
|
|
|
99
|
+
- [D21] Treat `templates/prioritize.json` as the source of truth for choosing between evaluated applications, candidate facts, and due follow-ups. When the user asks what to do next or when a batch needs replacement candidates, run `npx job-forge prioritize:build` or `npx job-forge prioritize:select --limit N` instead of ranking items in prose.
|
|
100
|
+
why: `iso-prioritize` is not an MCP and adds no prompt/tool-schema tokens; it converts facts and timeline records into a deterministic ranked queue so agents do not reread broad tracker/report trees or invent priorities
|
|
101
|
+
|
|
102
|
+
- [D22] Treat `.jobforge-lineage.json` as the source of truth for whether generated reports/PDFs are current. After creating or refreshing a derived report/PDF, record its inputs with `npx job-forge lineage:record --artifact <file> --input <source>...`; before reusing an old artifact after source changes, run `npx job-forge lineage:check --artifact <file>` or `npx job-forge lineage:check`.
|
|
103
|
+
why: `iso-lineage` is not an MCP and adds no prompt/tool-schema tokens; it detects stale outputs by hashing local files instead of asking agents to remember which CV/profile/report version produced an artifact
|
|
104
|
+
|
|
99
105
|
## Procedure
|
|
100
106
|
|
|
101
107
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
102
108
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
103
|
-
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
109
|
+
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use priority queues when choosing next actions or replacements [D21]. Use lineage checks before reusing generated artifacts [D22]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
104
110
|
4. Prepare Geometra dispatches: cleanup [H3], canon/index/facts/ledger prefilter when useful [D8, D13, D13b, D15], dedupe [H2], location filter [D5], materialize candidate facts/gates and run preflight plan/check [D16], routing [D2, D10], proxy prompt hygiene [H8].
|
|
105
111
|
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 [D17].
|
|
106
112
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
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.
|
|
@@ -96,11 +96,17 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
96
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
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
|
|
98
98
|
|
|
99
|
+
- [D21] Treat `templates/prioritize.json` as the source of truth for choosing between evaluated applications, candidate facts, and due follow-ups. When the user asks what to do next or when a batch needs replacement candidates, run `npx job-forge prioritize:build` or `npx job-forge prioritize:select --limit N` instead of ranking items in prose.
|
|
100
|
+
why: `iso-prioritize` is not an MCP and adds no prompt/tool-schema tokens; it converts facts and timeline records into a deterministic ranked queue so agents do not reread broad tracker/report trees or invent priorities
|
|
101
|
+
|
|
102
|
+
- [D22] Treat `.jobforge-lineage.json` as the source of truth for whether generated reports/PDFs are current. After creating or refreshing a derived report/PDF, record its inputs with `npx job-forge lineage:record --artifact <file> --input <source>...`; before reusing an old artifact after source changes, run `npx job-forge lineage:check --artifact <file>` or `npx job-forge lineage:check`.
|
|
103
|
+
why: `iso-lineage` is not an MCP and adds no prompt/tool-schema tokens; it detects stale outputs by hashing local files instead of asking agents to remember which CV/profile/report version produced an artifact
|
|
104
|
+
|
|
99
105
|
## Procedure
|
|
100
106
|
|
|
101
107
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
102
108
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
103
|
-
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
109
|
+
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use priority queues when choosing next actions or replacements [D21]. Use lineage checks before reusing generated artifacts [D22]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
104
110
|
4. Prepare Geometra dispatches: cleanup [H3], canon/index/facts/ledger prefilter when useful [D8, D13, D13b, D15], dedupe [H2], location filter [D5], materialize candidate facts/gates and run preflight plan/check [D16], routing [D2, D10], proxy prompt hygiene [H8].
|
|
105
111
|
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 [D17].
|
|
106
112
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
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
|
@@ -164,6 +164,20 @@ const consumerPkg = {
|
|
|
164
164
|
'postflight:status': 'job-forge postflight:status',
|
|
165
165
|
'postflight:check': 'job-forge postflight:check',
|
|
166
166
|
'postflight:explain': 'job-forge postflight:explain',
|
|
167
|
+
'prioritize:status': 'job-forge prioritize:status',
|
|
168
|
+
'prioritize:items': 'job-forge prioritize:items',
|
|
169
|
+
'prioritize:build': 'job-forge prioritize:build',
|
|
170
|
+
'prioritize:rank': 'job-forge prioritize:rank',
|
|
171
|
+
'prioritize:select': 'job-forge prioritize:select',
|
|
172
|
+
'prioritize:check': 'job-forge prioritize:check',
|
|
173
|
+
'prioritize:verify': 'job-forge prioritize:verify',
|
|
174
|
+
'prioritize:explain': 'job-forge prioritize:explain',
|
|
175
|
+
'lineage:status': 'job-forge lineage:status',
|
|
176
|
+
'lineage:record': 'job-forge lineage:record',
|
|
177
|
+
'lineage:check': 'job-forge lineage:check',
|
|
178
|
+
'lineage:stale': 'job-forge lineage:stale',
|
|
179
|
+
'lineage:verify': 'job-forge lineage:verify',
|
|
180
|
+
'lineage:explain': 'job-forge lineage:explain',
|
|
167
181
|
'migrate:plan': 'job-forge migrate:plan',
|
|
168
182
|
'migrate:apply': 'job-forge migrate:apply',
|
|
169
183
|
'migrate:check': 'job-forge migrate:check',
|
|
@@ -270,6 +284,8 @@ Before doing any work, remember where things live in *this* project:
|
|
|
270
284
|
| Local workflow ledger | \`.jobforge-ledger/events.jsonl\` | Deterministic append-only state; use \`job-forge ledger:*\` |
|
|
271
285
|
| Local artifact index | \`.jobforge-index.json\` | Deterministic file/line lookup; use \`job-forge index:*\` |
|
|
272
286
|
| Local fact set | \`.jobforge-facts.json\` | Deterministic source-backed facts; use \`job-forge facts:*\` |
|
|
287
|
+
| Local priority queue | \`.jobforge-prioritize.json\` | Deterministic next-action ranking; use \`job-forge prioritize:*\` |
|
|
288
|
+
| Artifact lineage | \`.jobforge-lineage.json\` | Stale report/PDF detection; use \`job-forge lineage:*\` |
|
|
273
289
|
| Identity canonicalization | \`templates/canon.json\` | Stable URL/company/role keys; use \`job-forge canon:*\` |
|
|
274
290
|
| Dispatch preflight policy | \`templates/preflight.json\` | Safe apply rounds/gates; use \`job-forge preflight:*\` |
|
|
275
291
|
| Dispatch postflight policy | \`templates/postflight.json\` | Safe apply settlement; use \`job-forge postflight:*\` |
|
|
@@ -365,6 +381,9 @@ data/token-usage.tsv
|
|
|
365
381
|
.jobforge-cache/
|
|
366
382
|
.jobforge-index.json
|
|
367
383
|
.jobforge-facts.json
|
|
384
|
+
.jobforge-prioritize.json
|
|
385
|
+
.jobforge-prioritize-items.json
|
|
386
|
+
.jobforge-lineage.json
|
|
368
387
|
.jobforge-runs/
|
|
369
388
|
reports/
|
|
370
389
|
!reports/.gitkeep
|
|
@@ -428,6 +447,8 @@ job-forge verify # verify pipeline integrity
|
|
|
428
447
|
job-forge ledger:status # local deterministic workflow ledger status
|
|
429
448
|
job-forge index:status # local artifact index status
|
|
430
449
|
job-forge facts:status # local source-backed fact status
|
|
450
|
+
job-forge prioritize:status # local next-action priority queue status
|
|
451
|
+
job-forge lineage:status # local artifact lineage status
|
|
431
452
|
job-forge canon:key company-role --company "Acme, Inc." --role "Senior SWE"
|
|
432
453
|
job-forge preflight:plan --candidates batch/preflight-candidates.json
|
|
433
454
|
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)
|
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
|
|
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/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.
|
|
@@ -96,11 +96,17 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
96
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
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
|
|
98
98
|
|
|
99
|
+
- [D21] Treat `templates/prioritize.json` as the source of truth for choosing between evaluated applications, candidate facts, and due follow-ups. When the user asks what to do next or when a batch needs replacement candidates, run `npx job-forge prioritize:build` or `npx job-forge prioritize:select --limit N` instead of ranking items in prose.
|
|
100
|
+
why: `iso-prioritize` is not an MCP and adds no prompt/tool-schema tokens; it converts facts and timeline records into a deterministic ranked queue so agents do not reread broad tracker/report trees or invent priorities
|
|
101
|
+
|
|
102
|
+
- [D22] Treat `.jobforge-lineage.json` as the source of truth for whether generated reports/PDFs are current. After creating or refreshing a derived report/PDF, record its inputs with `npx job-forge lineage:record --artifact <file> --input <source>...`; before reusing an old artifact after source changes, run `npx job-forge lineage:check --artifact <file>` or `npx job-forge lineage:check`.
|
|
103
|
+
why: `iso-lineage` is not an MCP and adds no prompt/tool-schema tokens; it detects stale outputs by hashing local files instead of asking agents to remember which CV/profile/report version produced an artifact
|
|
104
|
+
|
|
99
105
|
## Procedure
|
|
100
106
|
|
|
101
107
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
102
108
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
103
|
-
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
109
|
+
3. Read the active mode file [D3]. Use context bundle checks when changing context loads [D11]. Check cached artifacts before URL/JD refetches [D12]. Use artifact index lookups before broad file reads when they can answer the question [D13]. Use materialized facts when a fact query can answer the question [D13b]. Use canonical identity keys for duplicate checks [D15]. Use score checks/gates for scoring decisions [D19]. Use timeline due/check commands for follow-up timing [D20]. Use priority queues when choosing next actions or replacements [D21]. Use lineage checks before reusing generated artifacts [D22]. Use migration checks for harness drift [D14]. Use redaction checks before exporting local artifacts [D18]. Decide inline vs delegated work [D1].
|
|
104
110
|
4. Prepare Geometra dispatches: cleanup [H3], canon/index/facts/ledger prefilter when useful [D8, D13, D13b, D15], dedupe [H2], location filter [D5], materialize candidate facts/gates and run preflight plan/check [D16], routing [D2, D10], proxy prompt hygiene [H8].
|
|
105
111
|
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 [D17].
|
|
106
112
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|