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.
@@ -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 ...`, and materialized fact records returned by `npx job-forge facts: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 `job-forge ledger:*` for cheap local workflow-state checks when available. `iso-ledger` is not an MCP and adds no prompt/tool schema tokens; it records tracker TSV writes, merge outcomes, rebuilt tracker snapshots, and pipeline items in `.jobforge-ledger/events.jsonl`.
63
- why: state-trace remains working memory, while iso-ledger is deterministic append-only workflow truth that can answer duplicate/status questions without loading growing markdown/TSV files into the model context
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 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
- 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
- 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].
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, D19].
114
- 9. Merge contract-validated TSV outcomes [H6, D9].
115
- 10. Verify tracker and run postflight check before ending [H6, D17].
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 ...`, and materialized fact records returned by `npx job-forge facts: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 `job-forge ledger:*` for cheap local workflow-state checks when available. `iso-ledger` is not an MCP and adds no prompt/tool schema tokens; it records tracker TSV writes, merge outcomes, rebuilt tracker snapshots, and pipeline items in `.jobforge-ledger/events.jsonl`.
58
- why: state-trace remains working memory, while iso-ledger is deterministic append-only workflow truth that can answer duplicate/status questions without loading growing markdown/TSV files into the model context
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 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].
104
- 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
- 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].
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, D19].
109
- 9. Merge contract-validated TSV outcomes [H6, D9].
110
- 10. Verify tracker and run postflight check before ending [H6, D17].
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 ...`, and materialized fact records returned by `npx job-forge facts: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 `job-forge ledger:*` for cheap local workflow-state checks when available. `iso-ledger` is not an MCP and adds no prompt/tool schema tokens; it records tracker TSV writes, merge outcomes, rebuilt tracker snapshots, and pipeline items in `.jobforge-ledger/events.jsonl`.
58
- why: state-trace remains working memory, while iso-ledger is deterministic append-only workflow truth that can answer duplicate/status questions without loading growing markdown/TSV files into the model context
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 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].
104
- 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
- 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].
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, D19].
109
- 9. Merge contract-validated TSV outcomes [H6, D9].
110
- 10. Verify tracker and run postflight check before ending [H6, D17].
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, and `.jobforge-timeline.json` materializes due/overdue follow-up actions. None of these add always-on prompt or tool-schema tokens.
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
@@ -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)