job-forge 2.14.34 → 2.14.36

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.
@@ -59,66 +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
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
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
109
64
 
110
65
  ## Procedure
111
66
 
112
67
  1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
113
68
  2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
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].
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].
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].
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].
117
72
  6. Keep multi-job form-filling out of the orchestrator [H4].
118
73
  7. Cross-check subagent facts against authoritative files [H7].
119
- 8. Apply score gate [D4, D19].
120
- 9. Merge contract-validated TSV outcomes [H6, D9].
121
- 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].
122
77
 
123
78
  ## Routing
124
79
 
@@ -153,6 +108,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
153
108
  The sections above are the shared contract. Load detailed context on demand:
154
109
 
155
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.
156
112
  - `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
157
113
  - `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
158
114
  - `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
package/AGENTS.md CHANGED
@@ -54,66 +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
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
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
104
59
 
105
60
  ## Procedure
106
61
 
107
62
  1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
108
63
  2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
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].
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].
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].
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].
112
67
  6. Keep multi-job form-filling out of the orchestrator [H4].
113
68
  7. Cross-check subagent facts against authoritative files [H7].
114
- 8. Apply score gate [D4, D19].
115
- 9. Merge contract-validated TSV outcomes [H6, D9].
116
- 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].
117
72
 
118
73
  ## Routing
119
74
 
@@ -148,6 +103,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
148
103
  The sections above are the shared contract. Load detailed context on demand:
149
104
 
150
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.
151
107
  - `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
152
108
  - `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
153
109
  - `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
package/CLAUDE.md CHANGED
@@ -54,66 +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
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
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
104
59
 
105
60
  ## Procedure
106
61
 
107
62
  1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
108
63
  2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
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].
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].
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].
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].
112
67
  6. Keep multi-job form-filling out of the orchestrator [H4].
113
68
  7. Cross-check subagent facts against authoritative files [H7].
114
- 8. Apply score gate [D4, D19].
115
- 9. Merge contract-validated TSV outcomes [H6, D9].
116
- 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].
117
72
 
118
73
  ## Routing
119
74
 
@@ -148,6 +103,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
148
103
  The sections above are the shared contract. Load detailed context on demand:
149
104
 
150
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.
151
107
  - `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
152
108
  - `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
153
109
  - `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
@@ -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,13 @@ 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',
167
180
  'prioritize:status': 'job-forge prioritize:status',
168
181
  'prioritize:items': 'job-forge prioritize:items',
169
182
  'prioritize:build': 'job-forge prioritize:build',
@@ -178,6 +191,10 @@ const consumerPkg = {
178
191
  'lineage:stale': 'job-forge lineage:stale',
179
192
  'lineage:verify': 'job-forge lineage:verify',
180
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',
181
198
  'migrate:plan': 'job-forge migrate:plan',
182
199
  'migrate:apply': 'job-forge migrate:apply',
183
200
  'migrate:check': 'job-forge migrate:check',
@@ -377,14 +394,18 @@ data/applications.md
377
394
  data/pipeline.md
378
395
  data/scan-history.tsv
379
396
  data/token-usage.tsv
397
+ data/timeline-events.jsonl
380
398
  .jobforge-ledger/
381
399
  .jobforge-cache/
382
400
  .jobforge-index.json
383
401
  .jobforge-facts.json
402
+ .jobforge-timeline.json
403
+ .jobforge-timeline-events.jsonl
384
404
  .jobforge-prioritize.json
385
405
  .jobforge-prioritize-items.json
386
406
  .jobforge-lineage.json
387
407
  .jobforge-runs/
408
+ .jobforge-redacted/
388
409
  reports/
389
410
  !reports/.gitkeep
390
411
  batch/batch-state.tsv
@@ -234,7 +234,7 @@ When the tracker file is missing, checks 1-6 and 8 are skipped; checks 7, 9, 10,
234
234
 
235
235
  Prefer one focused change per pull request: a single mode under `modes/`, one repository-root `.mjs` utility, documentation under `docs/`, fictional samples under [`examples/`](../examples/README.md), templates such as [`templates/portals.example.yml`](../templates/portals.example.yml), the batch flow described in [`batch/README.md`](../batch/README.md), or the Go TUI under `dashboard/` — not a repo-wide refactor across 3+ of those at once. Branch workflow, the verify + dashboard build gate, and starter ideas are in [CONTRIBUTING.md](../CONTRIBUTING.md) (**What to Contribute** and **Development**). To look for in-repo `TODO`, `FIXME`, or `HACK` markers before choosing a task, use the `rg` one-liner in [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations). Upstream PRs MUST stay generic: do not commit real candidate data (`cv.md`, `config/profile.yml`, personalized `portals.yml`, `data/applications.md`, `reports/`, or similar paths called out in CONTRIBUTING and `.gitignore`).
236
236
 
237
- **PR / maintainer gate:** Before opening a pull request against `razroo/JobForge`, run `npm run verify` and `npm run build:dashboard` (or `(cd dashboard && go build .)`) from the harness repo root (same as [CONTRIBUTING.md](../CONTRIBUTING.md#development)). For optional scripted iterations that repeat that gate and commit one small change per pass, see [`scripts/cursor-agent-loop.sh`](../scripts/cursor-agent-loop.sh) (environment variables and usage in the script header; overview in [CONTRIBUTING.md](../CONTRIBUTING.md#optional-scripted-agent-iterations)).
237
+ **PR / maintainer gate:** Before opening a pull request against `razroo/JobForge`, run `npm run verify`, `npm run smoke:iso`, and `npm run build:dashboard` (or `(cd dashboard && go build .)`) from the harness repo root (same as [CONTRIBUTING.md](../CONTRIBUTING.md#development)). `smoke:iso` includes `npm run lint:helpers`, which prevents local helper dependencies, CLI aliases, scaffolder scripts, migrations, generated ignores, templates, docs, and helper reference from drifting. For optional scripted iterations that repeat that gate and commit one small change per pass, see [`scripts/cursor-agent-loop.sh`](../scripts/cursor-agent-loop.sh) (environment variables and usage in the script header; overview in [CONTRIBUTING.md](../CONTRIBUTING.md#optional-scripted-agent-iterations)).
238
238
 
239
239
  Scripts maintain data consistency. In a consumer project they're invoked via the `job-forge` CLI (`npx job-forge <cmd>`); in the harness repo they're also directly runnable as `node <script>.mjs`.
240
240
 
@@ -251,9 +251,13 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
251
251
  | `scripts/telemetry.mjs` | `npx job-forge telemetry:status` / `telemetry:show` | JobForge operational telemetry derived from OpenCode traces plus tracker TSV state |
252
252
  | `scripts/guard.mjs` | `npx job-forge guard:audit` / `guard:explain` | Deterministic `@razroo/iso-guard` policy audits over local OpenCode traces |
253
253
  | `scripts/ledger.mjs` | `npx job-forge ledger:status` / `ledger:has` / `ledger:rebuild` | Deterministic `@razroo/iso-ledger` state over tracker, TSV, and pipeline files |
254
+ | `scripts/capabilities.mjs` | `npx job-forge capabilities:check` / `capabilities:explain` | Deterministic `@razroo/iso-capabilities` role boundary checks for tools, MCPs, commands, filesystem, and network access |
255
+ | `scripts/cache.mjs` | `npx job-forge cache:has` / `cache:get` / `cache:put` | Deterministic `@razroo/iso-cache` JD and artifact reuse keyed by stable job/url inputs |
254
256
  | `scripts/index.mjs` | `npx job-forge index:status` / `index:has` / `index:query` | Deterministic `@razroo/iso-index` lookup over reports, tracker rows, TSVs, pipeline, scan history, and ledger events |
255
257
  | `scripts/facts.mjs` | `npx job-forge facts:status` / `facts:has` / `facts:query` | Deterministic `@razroo/iso-facts` materialization over job URLs, scores, application statuses, preflight candidates, scan history, and ledger events |
256
258
  | `scripts/timeline.mjs` | `npx job-forge timeline:due` / `timeline:check` / `timeline:build` | Deterministic `@razroo/iso-timeline` follow-up and next-action planning over tracker rows and dated pipeline items |
259
+ | `scripts/prioritize.mjs` | `npx job-forge prioritize:build` / `prioritize:select` / `prioritize:check` | Deterministic `@razroo/iso-prioritize` next-action ranking over materialized facts and due timeline items |
260
+ | `scripts/lineage.mjs` | `npx job-forge lineage:record` / `lineage:check` / `lineage:explain` | Deterministic `@razroo/iso-lineage` stale-output checks for generated reports, PDFs, and their source inputs |
257
261
  | `scripts/score.mjs` | `npx job-forge score:check` / `score:gate` / `score:explain` | Deterministic `@razroo/iso-score` checks for weighted offer scores, threshold booleans, recommendations, and score gates |
258
262
  | `scripts/canon.mjs` | `npx job-forge canon:normalize` / `canon:key` / `canon:compare` | Deterministic `@razroo/iso-canon` identity normalization for URLs, companies, roles, and company+role pairs |
259
263
  | `scripts/context.mjs` | `npx job-forge context:list` / `context:plan` / `context:check` / `context:render` | Deterministic `@razroo/iso-context` mode/reference context bundle planning and rendering |
@@ -261,6 +265,7 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
261
265
  | `scripts/postflight.mjs` | `npx job-forge postflight:status` / `postflight:check` / `postflight:explain` | Deterministic `@razroo/iso-postflight` settlement for dispatch outcomes, required tracker TSV artifacts, and merge/verify post-steps |
262
266
  | `scripts/redact.mjs` | `npx job-forge redact:scan` / `redact:apply` / `redact:verify` | Deterministic `@razroo/iso-redact` safe-export scanning and sanitization for traces, prompts, reports, and fixtures |
263
267
  | `scripts/migrate.mjs` | `npx job-forge migrate:plan` / `migrate:apply` / `migrate:check` | Deterministic `@razroo/iso-migrate` consumer-project upgrades for scripts and generated-artifact ignores |
268
+ | `scripts/check-helper-integration.mjs` | `npm run lint:helpers` | Integration lint that keeps helper packages, scripts, scaffolder defaults, migrations, generated ignores, docs, and `modes/reference-local-helpers.md` aligned |
264
269
  | `tracker-lib.mjs` | _(library)_ | Shared helpers for reading/writing day-based tracker files — imported by merge/dedup/verify/normalize |
265
270
  | `bin/sync.mjs` | `npx job-forge sync` | Creates the harness symlinks in a consumer project and applies safe migrations (also runs as `postinstall`) |
266
271
  | `bin/create-job-forge.mjs` | `npx create-job-forge <dir>` | Scaffolds a new personal project |
package/docs/README.md CHANGED
@@ -31,10 +31,10 @@ The harness exposes a single CLI (`job-forge`) installed as a `bin` entry. In a
31
31
 
32
32
  | What you need | Where to read |
33
33
  |---------------|---------------|
34
- | Full command list (`verify`, `merge`, `dedup`, `normalize`, `pdf`, `sync-check`, `tokens`, `trace`, `telemetry`, `guard`, `ledger`, `canon`, `context`, `index`, `facts`, `timeline`, `preflight`, `postflight`, `redact`, `sync`). | [SETUP.md — Tracker and scripts (terminal)](SETUP.md#tracker-and-scripts-terminal). |
34
+ | Full command list (`verify`, `merge`, `dedup`, `normalize`, `pdf`, `sync-check`, `tokens`, `trace`, `telemetry`, `guard`, `ledger`, `capabilities`, `context`, `cache`, `index`, `facts`, `score`, `canon`, `timeline`, `prioritize`, `lineage`, `preflight`, `postflight`, `redact`, `migrate`, `sync`). | [SETUP.md — Tracker and scripts (terminal)](SETUP.md#tracker-and-scripts-terminal). |
35
35
  | What each harness `.mjs` script does. | [ARCHITECTURE.md — Pipeline integrity](ARCHITECTURE.md#pipeline-integrity) and the scripts table underneath. |
36
36
  | Batch runner, TSV layout, and `batch/tracker-additions/` merge flow. | [batch/README.md](../batch/README.md). |
37
- | PR gate for harness contributions (`npm run verify` + `npm run build:dashboard`). | [CONTRIBUTING.md — Development](../CONTRIBUTING.md#development). |
37
+ | PR gate for harness contributions (`npm run verify` + `npm run smoke:iso` + `npm run build:dashboard`). | [CONTRIBUTING.md — Development](../CONTRIBUTING.md#development). |
38
38
  | Optional scripted iterations (harness repo only). | [scripts/cursor-agent-loop.sh](../scripts/cursor-agent-loop.sh). Usage and env vars live in the script header and in [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations). Verbose JSON output is formatted by [cursor-agent-stream-format.py](../scripts/cursor-agent-stream-format.py). |
39
39
  | Work-marker search (`T`ODO, `F`IXME, `H`ACK strings in the source) before picking work. | [CONTRIBUTING.md — Optional: scripted agent iterations](../CONTRIBUTING.md#optional-scripted-agent-iterations) — `rg` one-liner from the harness repo root. |
40
40
 
@@ -54,66 +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
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
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
104
59
 
105
60
  ## Procedure
106
61
 
107
62
  1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
108
63
  2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
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].
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].
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].
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].
112
67
  6. Keep multi-job form-filling out of the orchestrator [H4].
113
68
  7. Cross-check subagent facts against authoritative files [H7].
114
- 8. Apply score gate [D4, D19].
115
- 9. Merge contract-validated TSV outcomes [H6, D9].
116
- 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].
117
72
 
118
73
  ## Routing
119
74
 
@@ -148,6 +103,7 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
148
103
  The sections above are the shared contract. Load detailed context on demand:
149
104
 
150
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.
151
107
  - `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
152
108
  - `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
153
109
  - `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
package/modes/README.md CHANGED
@@ -3,11 +3,13 @@
3
3
  Markdown prompts used together with the root [`AGENTS.md`](../AGENTS.md). Each file aligns with a `/job-forge …` entry point or shared behavior described there.
4
4
 
5
5
  - **`_shared.md`** — Archetypes, scoring dimensions, negotiation scaffolding. Edit this first when you change how offers are classified or weighted.
6
+ - **`reference-local-helpers.md`** — On-demand map of deterministic local helpers and when they replace prose, broad file reads, or manual policy checks.
6
7
  - **Per-command files** — Each `*.md` here pairs with a `/job-forge …` entry in [`AGENTS.md`](../AGENTS.md). How modes connect to batch, tracker, and scripts is spelled out in [**Architecture — Modes**](../docs/ARCHITECTURE.md#modes-modes).
7
8
 
8
9
  | File | Role |
9
10
  |------|------|
10
11
  | [`_shared.md`](_shared.md) | Shared archetypes, scoring, negotiation scaffolding |
12
+ | [`reference-local-helpers.md`](reference-local-helpers.md) | Deterministic helper selection, mandatory uses, and integration enforcement |
11
13
  | [`auto-pipeline.md`](auto-pipeline.md) | Default path when the user pastes a JD or URL — full evaluate → report → PDF → tracker flow |
12
14
  | [`offer.md`](offer.md) | Explicit full evaluation (blocks A–F) for a single offer |
13
15
  | [`compare.md`](compare.md) | Side-by-side comparison of multiple offers |
@@ -8,7 +8,7 @@ Fetch the JD content once. If the input is a **URL** (not pasted JD text), fetch
8
8
 
9
9
  **Pick exactly one method, in this priority order:**
10
10
 
11
- 1. **Greenhouse JSON API (first try, if the URL is Greenhouse-backed):** If the pipeline.md entry carries `| gh={slug}/{id}` OR the URL host matches `*.greenhouse.io` / a known Greenhouse customer front-end (`*.pinterestcareers.com`, `okta.com/company/careers/opportunity/*`, `samsara.com/company/careers/roles/*`, `zoominfo.com/careers?gh_jid=*`, `collibra.com/.../?gh_jid=*`, `careers.toasttab.com/jobs?gh_jid=*`, `careers.airbnb.com/positions/*?gh_jid=*`, `coinbase.com/careers/positions/*?gh_jid=*`, `instacart.careers/job/?gh_jid=*`), extract `slug` and `id` and WebFetch `https://boards-api.greenhouse.io/v1/boards/{slug}/jobs/{id}`. 200 + JSON with `content` is the authoritative JD. 404 = genuinely closed (mark CLOSED and stop). **If 200, STOP — do not fall back to Geometra or WebFetch of the front-end.** The API is faster, cheaper (no Geometra session), and never returns a bot-shell.
11
+ 1. **Greenhouse JSON API (first try, if the URL is Greenhouse-backed):** If the pipeline.md entry carries `| gh={slug}/{id}` OR the URL host matches `*.greenhouse.io` / a known Greenhouse customer front-end (`*.pinterestcareers.com`, `okta.com/company/careers/opportunity/*`, `samsara.com/company/careers/roles/*`, `zoominfo.com/careers?gh_jid=*`, `collibra.com/.../?gh_jid=*`, `careers.toasttab.com/jobs?gh_jid=*`, `careers.airbnb.com/positions/*?gh_jid=*`, `coinbase.com/careers/positions/*?gh_jid=*`, `instacart.careers/job/?gh_jid=*`), extract `slug` and `id` and WebFetch `https://boards-api.greenhouse.io/v1/boards/{slug}/jobs/{id}`. 200 + JSON with `content` is the authoritative JD. 404 = genuinely closed (mark CLOSED and stop). **OpenCode WebFetch compatibility:** do not pass `format: "json"`; omit `format` or use `format: "text"` and parse the returned JSON text. **If 200, STOP — do not fall back to Geometra or WebFetch of the front-end.** The API is faster, cheaper (no Geometra session), and never returns a bot-shell.
12
12
  2. **Geometra MCP:** Most non-Greenhouse job portals (Lever, Ashby, Workday) are SPAs. Use `geometra_connect` + `geometra_page_model` to render and read the JD. **If this returns non-empty JD text, STOP — do not WebFetch the same URL.**
13
13
  3. **WebFetch (only if Geometra is unavailable OR returned only a shell with no JD text):** For static pages (ZipRecruiter, WeLoveProduct, company career pages).
14
14
  4. **WebSearch (only if methods 1–3 all failed):** Search for the role title + company on secondary portals that index the JD in static HTML.
package/modes/pipeline.md CHANGED
@@ -33,7 +33,7 @@ Processes accumulated job offer URLs from `data/pipeline.md`. The user adds URLs
33
33
 
34
34
  ## Detect JD From URL
35
35
 
36
- 1. **Greenhouse JSON API (FIRST, when the entry has `| gh={slug}/{id}` OR the host looks Greenhouse-backed):** WebFetch `https://boards-api.greenhouse.io/v1/boards/{slug}/jobs/{id}`. 200 + JSON with `content` = LIVE, use it as the JD; 404 = genuinely CLOSED (mark `- [!]` and continue). Bot-hostile customer fronts (`pinterestcareers.com`, `okta.com`, `samsara.com`, `zoominfo.com`, `collibra.com`, `careers.toasttab.com`, `careers.airbnb.com`, `coinbase.com`, `instacart.careers`, `careers.toasttab.com`) MUST be verified via this API first — WebFetch/Geometra of those domains returns a shell or 403 and causes false CLOSED marks.
36
+ 1. **Greenhouse JSON API (FIRST, when the entry has `| gh={slug}/{id}` OR the host looks Greenhouse-backed):** WebFetch `https://boards-api.greenhouse.io/v1/boards/{slug}/jobs/{id}`. 200 + JSON with `content` = LIVE, use it as the JD; 404 = genuinely CLOSED (mark `- [!]` and continue). **OpenCode WebFetch compatibility:** do not pass `format: "json"`; omit `format` or use `format: "text"` and parse the returned JSON text. Bot-hostile customer fronts (`pinterestcareers.com`, `okta.com`, `samsara.com`, `zoominfo.com`, `collibra.com`, `careers.toasttab.com`, `careers.airbnb.com`, `coinbase.com`, `instacart.careers`, `careers.toasttab.com`) MUST be verified via this API first — WebFetch/Geometra of those domains returns a shell or 403 and causes false CLOSED marks.
37
37
  2. **Geometra MCP:** `geometra_connect` + `geometra_page_model`. Works with non-Greenhouse SPAs (Lever, Ashby, Workday), uses fewer tokens than raw DOM snapshots.
38
38
  3. **WebFetch (fallback):** For static pages or when Geometra is not available.
39
39
  4. **WebSearch (last resort):** Search on secondary portals that index the JD.
@@ -0,0 +1,55 @@
1
+ # Reference: Local Helpers
2
+
3
+ JobForge's architectural helpers are local CLIs and JSON policies, not MCPs. They add no always-on prompt or tool-schema tokens. Use them when they can answer a question or validate an artifact more deterministically than prose.
4
+
5
+ ## Selection Rule
6
+
7
+ Prefer a local helper when the workflow needs:
8
+
9
+ - Identity, duplicate, or status truth.
10
+ - Machine-readable artifact validation.
11
+ - Context, capability, or migration policy.
12
+ - Dispatch planning or settlement.
13
+ - Scoring, timing, priority, or lineage decisions.
14
+ - Safe export checks.
15
+
16
+ Do not paste whole helper outputs into prompts unless the downstream agent needs that exact file-backed result. Prefer passing paths, ids, keys, and short summaries.
17
+
18
+ ## Helper Map
19
+
20
+ | Need | Source / state | Command |
21
+ |---|---|---|
22
+ | Trace inspection | Local OpenCode transcripts | `npx job-forge trace:*` |
23
+ | Run telemetry | Local traces + tracker TSV state | `npx job-forge telemetry:*` |
24
+ | Guard audits | `templates/guards/jobforge-baseline.yaml` | `npx job-forge guard:*` |
25
+ | Workflow state | `.jobforge-ledger/events.jsonl` | `npx job-forge ledger:*` |
26
+ | Artifact contracts | `templates/contracts.json` | `npx job-forge tracker-line ... --write`; `npx job-forge verify` |
27
+ | Role capability policy | `templates/capabilities.json` | `npx job-forge capabilities:*` |
28
+ | Context bundle policy | `templates/context.json` | `npx job-forge context:*` |
29
+ | JD/artifact reuse | `.jobforge-cache/` | `npx job-forge cache:*` |
30
+ | Artifact lookup | `.jobforge-index.json` from `templates/index.json` | `npx job-forge index:*` |
31
+ | Source-backed facts | `.jobforge-facts.json` from `templates/facts.json` | `npx job-forge facts:*` |
32
+ | Consumer upgrades | `templates/migrations.json` | `npx job-forge migrate:*` |
33
+ | Identity keys | `templates/canon.json` | `npx job-forge canon:*` |
34
+ | Apply dispatch safety | `templates/preflight.json` | `npx job-forge preflight:*` |
35
+ | Dispatch settlement | `templates/postflight.json` | `npx job-forge postflight:*` |
36
+ | Safe export | `templates/redact.json` | `npx job-forge redact:*` |
37
+ | Offer scoring | `templates/score.json` | `npx job-forge score:*` |
38
+ | Follow-up timing | `templates/timeline.json` | `npx job-forge timeline:*` |
39
+ | Next-action ranking | `templates/prioritize.json` | `npx job-forge prioritize:*` |
40
+ | Artifact lineage | `.jobforge-lineage.json` | `npx job-forge lineage:*` |
41
+
42
+ ## Mandatory Uses
43
+
44
+ - Before duplicate-sensitive apply dispatches, use `canon:key`, `index:has`, `facts:has`, or `ledger:has` as cheap prefilters when useful, then still apply the H2 four-source grep unless the candidate JSON already materializes those sources.
45
+ - For tracker additions, prefer `tracker-line --write`; if TSV is emitted manually, `merge` and `verify` must validate it through `templates/contracts.json`.
46
+ - For score-driven apply/PDF decisions, run `score:check --input <file>` and `score:gate --input <file> --gate apply`.
47
+ - For follow-up triage, run `timeline:due`; use `timeline:check --fail-on overdue` when stale follow-ups should fail the workflow.
48
+ - For next-action or replacement-candidate selection, run `prioritize:build` or `prioritize:select --limit N`.
49
+ - For generated reports or PDFs reused after input changes, run `lineage:check --artifact <file>` if lineage exists; after creating derived artifacts, record them with `lineage:record --artifact <file> --input <source>...`.
50
+ - Before exporting traces, prompts, reports, or fixtures outside the project, run `redact:scan`, `redact:apply`, or `redact:verify`.
51
+ - When diagnosing consumer harness drift, run `migrate:plan` or `migrate:check`; `job-forge sync` applies safe migrations automatically unless `JOB_FORGE_SKIP_MIGRATIONS=1` is set.
52
+
53
+ ## Enforcement
54
+
55
+ The integration surface is checked by `npm run lint:helpers`. That check verifies helper dependencies, package scripts, scaffolder scripts, migration scripts, generated ignores, templates, and this reference stay aligned.
package/modes/scan.md CHANGED
@@ -38,6 +38,8 @@ Read `portals.yml` which contains:
38
38
 
39
39
  For companies using an ATS or aggregator that exposes a public JSON/RSS API, fetch structured data directly. APIs are faster than Geometra and harder to hallucinate (the response is load-bearing — record IDs verbatim from the response, never reconstruct them). Use as a complement to Level 1.
40
40
 
41
+ **OpenCode WebFetch compatibility:** when fetching JSON/RSS API endpoints, do not pass `format: "json"`. OpenCode accepts `text`, `markdown`, or `html`; omit `format` or use `format: "text"` and parse JSON/RSS from the returned body.
42
+
41
43
  Supported API shapes:
42
44
 
43
45
  #### Greenhouse (JSON, per-company board)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job-forge",
3
- "version": "2.14.34",
3
+ "version": "2.14.36",
4
4
  "description": "AI-powered job search pipeline built on opencode",
5
5
  "type": "module",
6
6
  "bin": {
@@ -110,11 +110,12 @@
110
110
  "plan": "iso plan .",
111
111
  "lint:agentmd": "agentmd lint iso/instructions.md",
112
112
  "lint:modes": "isolint lint modes/",
113
+ "lint:helpers": "node scripts/check-helper-integration.mjs .",
113
114
  "test:agentmd": "agentmd test iso/instructions.md --fixtures fixtures/instructions.yml --via claude-code --model claude-haiku-4-5 --concurrency 2",
114
115
  "test:agentmd:baseline": "agentmd test iso/instructions.md --fixtures fixtures/instructions.yml --via claude-code --model claude-haiku-4-5 --concurrency 2 --trials 3 --format json --out fixtures/baseline.json",
115
116
  "test:agentmd:apply": "agentmd test modes/apply.md --fixtures fixtures/modes/apply.yml --via claude-code --model claude-haiku-4-5 --concurrency 2 --trials 3",
116
117
  "lint:agentmd:modes": "agentmd lint modes/apply.md",
117
- "smoke:iso": "iso plan . && iso build . --dry-run && iso-route verify models.yaml && node scripts/check-iso-smoke.mjs . && JOBFORGE_ROOT=$PWD iso-eval run fixtures/iso-smoke/eval.yml",
118
+ "smoke:iso": "iso plan . && iso build . --dry-run && iso-route verify models.yaml && node scripts/check-iso-smoke.mjs . && node scripts/check-helper-integration.mjs . && JOBFORGE_ROOT=$PWD iso-eval run fixtures/iso-smoke/eval.yml",
118
119
  "build:config": "iso build .",
119
120
  "prepack": "iso build .",
120
121
  "release:check-source": "node ./scripts/release/check-source.mjs",
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, readFileSync } from 'node:fs';
4
+ import { join, resolve } from 'node:path';
5
+
6
+ const root = resolve(process.argv[2] || '.');
7
+
8
+ const pkg = readJson('package.json');
9
+ const migrations = readJson('templates/migrations.json');
10
+ const bin = readText('bin/job-forge.mjs');
11
+ const create = readText('bin/create-job-forge.mjs');
12
+ const reference = readText('modes/reference-local-helpers.md');
13
+ const rootIgnore = readText('.gitignore');
14
+ const architecture = readText('docs/ARCHITECTURE.md');
15
+
16
+ const migrationScripts = migrationValue('jobforge-managed-scripts', '/scripts');
17
+ const migrationIgnores = migrationValue('jobforge-generated-ignores');
18
+
19
+ const groups = [
20
+ helper('trace', '@razroo/iso-trace', ['list', 'stats', 'show']),
21
+ helper('telemetry', '', ['list', 'status', 'show', 'watch']),
22
+ helper('guard', '@razroo/iso-guard', ['audit', 'explain'], { template: 'templates/guards/jobforge-baseline.yaml' }),
23
+ helper('ledger', '@razroo/iso-ledger', ['status', 'rebuild', 'verify', 'has', 'query'], { artifacts: ['.jobforge-ledger/'] }),
24
+ helper('capabilities', '@razroo/iso-capabilities', ['list', 'explain', 'check', 'render'], { template: 'templates/capabilities.json', migrated: true }),
25
+ helper('context', '@razroo/iso-context', ['list', 'explain', 'plan', 'check', 'render'], { template: 'templates/context.json', migrated: true }),
26
+ helper('cache', '@razroo/iso-cache', ['key', 'has', 'get', 'put', 'status', 'list', 'verify', 'prune'], { artifacts: ['.jobforge-cache/'], migrated: true }),
27
+ helper('index', '@razroo/iso-index', ['build', 'status', 'query', 'has', 'verify', 'explain'], { template: 'templates/index.json', artifacts: ['.jobforge-index.json'], migrated: true }),
28
+ helper('facts', '@razroo/iso-facts', ['build', 'status', 'verify', 'check', 'has', 'query', 'explain'], { template: 'templates/facts.json', artifacts: ['.jobforge-facts.json'], migrated: true }),
29
+ helper('score', '@razroo/iso-score', ['compute', 'verify', 'check', 'gate', 'compare', 'explain'], { template: 'templates/score.json', migrated: true }),
30
+ helper('canon', '@razroo/iso-canon', ['normalize', 'key', 'compare', 'explain'], { template: 'templates/canon.json', migrated: true }),
31
+ helper('preflight', '@razroo/iso-preflight', ['plan', 'check', 'explain'], { template: 'templates/preflight.json', artifacts: ['batch/preflight-candidates.json', 'batch/preflight-plan.json'], migrated: true }),
32
+ helper('postflight', '@razroo/iso-postflight', ['status', 'check', 'explain'], { template: 'templates/postflight.json', artifacts: ['batch/postflight-outcomes.json'], migrated: true }),
33
+ helper('timeline', '@razroo/iso-timeline', ['status', 'build', 'plan', 'due', 'check', 'verify', 'explain'], { template: 'templates/timeline.json', artifacts: ['.jobforge-timeline.json', '.jobforge-timeline-events.jsonl', 'data/timeline-events.jsonl'], migrated: true }),
34
+ helper('prioritize', '@razroo/iso-prioritize', ['status', 'items', 'build', 'rank', 'select', 'check', 'verify', 'explain'], { template: 'templates/prioritize.json', artifacts: ['.jobforge-prioritize.json', '.jobforge-prioritize-items.json'], migrated: true }),
35
+ helper('lineage', '@razroo/iso-lineage', ['status', 'record', 'check', 'stale', 'verify', 'explain'], { artifacts: ['.jobforge-lineage.json'], migrated: true }),
36
+ helper('redact', '@razroo/iso-redact', ['scan', 'verify', 'apply', 'explain'], { template: 'templates/redact.json', artifacts: ['.jobforge-redacted/'], migrated: true }),
37
+ helper('migrate', '@razroo/iso-migrate', ['plan', 'apply', 'check', 'explain'], { template: 'templates/migrations.json', migrated: true }),
38
+ ];
39
+
40
+ const packageOnly = [
41
+ { id: 'contract', pkg: '@razroo/iso-contract', template: 'templates/contracts.json', needles: ['templates/contracts.json', 'tracker-line'] },
42
+ { id: 'orchestrator', pkg: '@razroo/iso-orchestrator', file: 'scripts/batch-orchestrator.mjs', needles: ['iso-orchestrator'] },
43
+ ];
44
+
45
+ const errors = [];
46
+
47
+ for (const group of groups) {
48
+ if (group.pkg) hasDependency(group.pkg, group.id);
49
+ if (group.template) fileExists(group.template, group.id);
50
+ fileExists(`scripts/${group.id}.mjs`, group.id);
51
+
52
+ if (!bin.includes(`const ${group.id}Aliases`)) {
53
+ errors.push(`${group.id}: missing ${group.id}Aliases in bin/job-forge.mjs`);
54
+ }
55
+ if (!bin.includes(`scripts/${group.id}.mjs`)) {
56
+ errors.push(`${group.id}: bin/job-forge.mjs does not dispatch scripts/${group.id}.mjs`);
57
+ }
58
+ if (!reference.includes(`job-forge ${group.id}:*`)) {
59
+ errors.push(`${group.id}: modes/reference-local-helpers.md does not mention job-forge ${group.id}:*`);
60
+ }
61
+ if (!architecture.includes(`scripts/${group.id}.mjs`)) {
62
+ errors.push(`${group.id}: docs/ARCHITECTURE.md script table does not mention scripts/${group.id}.mjs`);
63
+ }
64
+
65
+ for (const alias of group.aliases) {
66
+ if (!pkg.scripts?.[alias]) errors.push(`${group.id}: package.json missing script ${alias}`);
67
+ if (!createIncludesScript(alias)) errors.push(`${group.id}: create-job-forge missing script ${alias}`);
68
+ if (group.migrated && migrationScripts?.[alias] !== `job-forge ${alias}`) {
69
+ errors.push(`${group.id}: migrations.json missing managed script ${alias}`);
70
+ }
71
+ }
72
+
73
+ for (const artifact of group.artifacts) {
74
+ if (!rootIgnore.includes(artifact)) errors.push(`${group.id}: .gitignore missing ${artifact}`);
75
+ if (!create.includes(artifact)) errors.push(`${group.id}: create-job-forge .gitignore template missing ${artifact}`);
76
+ if (group.migrated && !migrationIgnores.includes(artifact)) {
77
+ errors.push(`${group.id}: migrations.json generated ignores missing ${artifact}`);
78
+ }
79
+ }
80
+ }
81
+
82
+ for (const item of packageOnly) {
83
+ hasDependency(item.pkg, item.id);
84
+ if (item.template) fileExists(item.template, item.id);
85
+ if (item.file) fileExists(item.file, item.id);
86
+ for (const needle of item.needles || []) {
87
+ if (!reference.includes(needle) && !architecture.includes(needle)) {
88
+ errors.push(`${item.id}: expected documentation needle "${needle}"`);
89
+ }
90
+ }
91
+ }
92
+
93
+ if (/\[D(?:9|1\d|2[0-9])\]/.test(readText('iso/instructions.md'))) {
94
+ errors.push('iso/instructions.md still has detailed helper D-rules; keep helper details in modes/reference-local-helpers.md');
95
+ }
96
+
97
+ if (errors.length) {
98
+ console.error('JobForge helper integration check failed:');
99
+ for (const error of errors) console.error(`- ${error}`);
100
+ process.exit(1);
101
+ }
102
+
103
+ console.log(`JobForge helper integration passed (${groups.length + packageOnly.length} helpers).`);
104
+
105
+ function helper(id, pkg, commands, options = {}) {
106
+ return {
107
+ id,
108
+ pkg,
109
+ aliases: commands.map((command) => `${id}:${command}`),
110
+ template: options.template || '',
111
+ artifacts: options.artifacts || [],
112
+ migrated: Boolean(options.migrated),
113
+ };
114
+ }
115
+
116
+ function readJson(path) {
117
+ return JSON.parse(readText(path));
118
+ }
119
+
120
+ function readText(path) {
121
+ return readFileSync(join(root, path), 'utf8');
122
+ }
123
+
124
+ function fileExists(path, id) {
125
+ if (!existsSync(join(root, path))) errors.push(`${id}: missing ${path}`);
126
+ }
127
+
128
+ function hasDependency(name, id) {
129
+ if (!pkg.dependencies?.[name] && !pkg.devDependencies?.[name]) {
130
+ errors.push(`${id}: package.json missing dependency ${name}`);
131
+ }
132
+ }
133
+
134
+ function migrationValue(id, pointer = '') {
135
+ const migration = migrations.migrations?.find((item) => item.id === id);
136
+ const operation = migration?.operations?.find((item) => pointer ? item.pointer === pointer : item.type === 'ensure-lines');
137
+ return pointer ? operation?.value : operation?.lines || [];
138
+ }
139
+
140
+ function createIncludesScript(alias) {
141
+ return create.includes(`'${alias}': 'job-forge ${alias}'`) ||
142
+ create.includes(`"${alias}": "job-forge ${alias}"`);
143
+ }
@@ -5,6 +5,7 @@ import { resolve } from "node:path";
5
5
  const root = resolve(process.argv[2] ?? ".");
6
6
  const files = {
7
7
  instructions: readFileSync(resolve(root, "iso/instructions.md"), "utf8"),
8
+ helpers: readFileSync(resolve(root, "modes/reference-local-helpers.md"), "utf8"),
8
9
  apply: readFileSync(resolve(root, "modes/apply.md"), "utf8"),
9
10
  models: readFileSync(resolve(root, "models.yaml"), "utf8"),
10
11
  config: readFileSync(resolve(root, "iso/config.json"), "utf8"),
@@ -19,10 +20,9 @@ const checks = [
19
20
  ["H5 blocks same-company concurrent retry", () => every(files.instructions, ["Re-dispatch the same company only AFTER", "previous subagent returns"])],
20
21
  ["H6 requires merge and verify", () => every(files.instructions, ["batch/tracker-additions/*.tsv", "npx job-forge merge", "npx job-forge verify"])],
21
22
  ["H7 distrusts subagent prose", () => every(files.instructions, ["must originate from a file", "not from prior subagent prose"])],
22
- ["score policy points to local helper", () => every(files.instructions, ["[D19]", "templates/score.json", "npx job-forge score:check", "npx job-forge score:gate"])],
23
- ["timeline policy points to local helper", () => every(files.instructions, ["[D20]", "templates/timeline.json", "npx job-forge timeline:due", "npx job-forge timeline:check --fail-on overdue"])],
24
- ["prioritize policy points to local helper", () => every(files.instructions, ["[D21]", "templates/prioritize.json", "npx job-forge prioritize:build", "npx job-forge prioritize:select --limit N"])],
25
- ["lineage policy points to local helper", () => every(files.instructions, ["[D22]", ".jobforge-lineage.json", "npx job-forge lineage:record", "npx job-forge lineage:check"])],
23
+ ["root points to consolidated helper reference", () => every(files.instructions, ["[D8]", "modes/reference-local-helpers.md", "deterministic local helpers"])],
24
+ ["helper reference covers score/timeline/prioritize/lineage", () => every(files.helpers, ["templates/score.json", "npx job-forge score:*", "templates/timeline.json", "npx job-forge timeline:*", "templates/prioritize.json", "npx job-forge prioritize:*", ".jobforge-lineage.json", "npx job-forge lineage:*"])],
25
+ ["root helper defaults are consolidated", () => !/\[D(?:9|1\d|2[0-9])\]/.test(files.instructions)],
26
26
  ["shared prompt points to on-demand references", () => every(files.instructions, ["modes/{mode}.md", "modes/reference-setup.md", "modes/reference-portals.md", "modes/reference-geometra.md"])],
27
27
  ["apply mode owns high-stakes upgrade", () => every(files.apply, ["[D8]", "@general-paid", "4.0/5", "high-stakes"])],
28
28
  ["apply mode blocks provider auto-downgrade", () => every(files.apply, ["[D9]", "do not auto-downgrade", "inspect telemetry before retrying"])],