job-forge 2.12.0 → 2.13.0

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.
@@ -1,11 +1,16 @@
1
1
  ---
2
2
  name: general-paid
3
- description: Quality-sensitive worker on paid model. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
3
+ description: Quality-sensitive worker on the strongest free-tier OpenCode model by default. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
4
4
  model: claude-opus-4-7
5
5
  ---
6
6
 
7
7
  You are the @general-paid subagent. The orchestrator delegated this task to you because it requires quality writing or judgment — the kind of work `@general-free` isn't well-suited for.
8
8
 
9
+ On OpenCode, this agent now defaults to a free OpenRouter model. On other
10
+ harnesses, the same role may still resolve to a premium model. Your job is
11
+ still the same: produce the best final writing you can from the context you
12
+ were given.
13
+
9
14
  ## Do These Tasks
10
15
 
11
16
  - Generate evaluation narratives (Blocks A-F) per `modes/offer.md`.
@@ -1,6 +1,6 @@
1
1
  # generated by @razroo/iso-route — do not hand-edit
2
- model = "claude-sonnet-4-6"
3
- model_provider = "anthropic"
2
+ model = "gpt-5.4"
3
+ model_provider = "openai"
4
4
 
5
5
  [profiles.fast]
6
6
  model = "gpt-5.4-mini"
@@ -15,11 +15,6 @@ model_reasoning_effort = "high"
15
15
  model = "gpt-5.4-nano"
16
16
  model_provider = "openai"
17
17
 
18
- [model_providers.anthropic]
19
- name = "Anthropic"
20
- base_url = "https://api.anthropic.com/v1"
21
- env_key = "ANTHROPIC_API_KEY"
22
-
23
18
  [model_providers.openai]
24
19
  name = "OpenAI"
25
20
  base_url = "https://api.openai.com/v1"
@@ -1,10 +1,15 @@
1
1
  ---
2
- description: Quality-sensitive worker on paid model. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
2
+ description: Quality-sensitive worker on the strongest free-tier OpenCode model by default. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
3
3
  alwaysApply: false
4
4
  ---
5
5
 
6
6
  You are the @general-paid subagent. The orchestrator delegated this task to you because it requires quality writing or judgment — the kind of work `@general-free` isn't well-suited for.
7
7
 
8
+ On OpenCode, this agent now defaults to a free OpenRouter model. On other
9
+ harnesses, the same role may still resolve to a premium model. Your job is
10
+ still the same: produce the best final writing you can from the context you
11
+ were given.
12
+
8
13
  ## Do These Tasks
9
14
 
10
15
  - Generate evaluation narratives (Blocks A-F) per `modes/offer.md`.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Procedural worker on free-tier model. Use for form filling via Geometra, tracker updates, TSV merges, scan dedup, OTP retrieval, and other mechanical/scripted tasks where quality-sensitive text generation is NOT required.
3
3
  mode: subagent
4
- model: opencode/big-pickle
4
+ model: openrouter/minimax/minimax-m2.5:free
5
5
  tools:
6
6
  geometra_connect: true
7
7
  geometra_page_model: true
@@ -16,6 +16,10 @@ tools:
16
16
  gmail_get_message: true
17
17
  temperature: 0.1
18
18
  reasoningEffort: minimal
19
+ fallback_models:
20
+ - openrouter/qwen/qwen3-coder:free
21
+ - openrouter/google/gemma-4-26b-a4b-it:free
22
+ - openrouter/openai/gpt-oss-20b:free
19
23
  ---
20
24
 
21
25
  You are the @general-free subagent. You run on a free-tier model, which means the orchestrator has delegated this task to you **specifically because the work is procedural**: deterministic steps, scripted outputs, no nuanced writing required.
@@ -1,16 +1,25 @@
1
1
  ---
2
- description: Quality-sensitive worker on paid model. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
2
+ description: Quality-sensitive worker on the strongest free-tier OpenCode model by default. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
3
3
  mode: subagent
4
- model: opencode-go/kimi-k2.5
4
+ model: openrouter/qwen/qwen3-next-80b-a3b-instruct:free
5
5
  tools:
6
6
  geometra_*: false
7
7
  gmail_*: false
8
8
  temperature: 0.3
9
9
  reasoningEffort: medium
10
+ fallback_models:
11
+ - openrouter/qwen/qwen3-coder:free
12
+ - openrouter/openai/gpt-oss-120b:free
13
+ - openrouter/z-ai/glm-4.5-air:free
10
14
  ---
11
15
 
12
16
  You are the @general-paid subagent. The orchestrator delegated this task to you because it requires quality writing or judgment — the kind of work `@general-free` isn't well-suited for.
13
17
 
18
+ On OpenCode, this agent now defaults to a free OpenRouter model. On other
19
+ harnesses, the same role may still resolve to a premium model. Your job is
20
+ still the same: produce the best final writing you can from the context you
21
+ were given.
22
+
14
23
  ## Do These Tasks
15
24
 
16
25
  - Generate evaluation narratives (Blocks A-F) per `modes/offer.md`.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  description: Narrow-scope extractor on free-tier model. Use for single-purpose tasks where the orchestrator passes the exact input and expects a small, structured output — e.g., "extract these 8 fields from this JD text" or "parse this form schema into a label→type map". NOT for multi-step workflows.
3
3
  mode: subagent
4
- model: opencode/minimax-m2.5-free
4
+ model: openrouter/google/gemma-4-26b-a4b-it:free
5
5
  tools:
6
6
  geometra_*: false
7
7
  gmail_*: false
@@ -13,6 +13,10 @@ tools:
13
13
  task: false
14
14
  temperature: 0
15
15
  reasoningEffort: none
16
+ fallback_models:
17
+ - openrouter/minimax/minimax-m2.5:free
18
+ - openrouter/openai/gpt-oss-20b:free
19
+ - openrouter/google/gemma-4-31b-it:free
16
20
  ---
17
21
 
18
22
  You are the @glm-minimal subagent. You handle narrow, one-shot extractions where the orchestrator has pre-digested the context and just needs you to do a specific transform.
@@ -0,0 +1,11 @@
1
+ {
2
+ "cooldown_seconds": 60,
3
+ "timeout_seconds": 30,
4
+ "notify_on_fallback": true,
5
+ "fallback_models": [
6
+ "openrouter/qwen/qwen3-next-80b-a3b-instruct:free",
7
+ "openrouter/openai/gpt-oss-120b:free",
8
+ "openrouter/google/gemma-4-26b-a4b-it:free",
9
+ "openrouter/z-ai/glm-4.5-air:free"
10
+ ]
11
+ }
package/README.md CHANGED
@@ -68,8 +68,8 @@ JobForge turns opencode into a full job search command center. Instead of manual
68
68
  | **Portal Scanner** | 45+ companies pre-configured with fuzzy dedup for reposts |
69
69
  | **Batch Processing** | Parallel evaluation with `opencode run` workers, with honest verification flagging |
70
70
  | **Pipeline Integrity** | Automated merge, dedup, status normalization, health checks |
71
- | **Cost-Aware Agent Routing** | Three subagents (`@general-free`, `@general-paid`, `@glm-minimal`) with per-task model tiers; procedural work runs on free-tier models, quality-sensitive work on paid. See [Subagent Routing in AGENTS.md](AGENTS.md) for the task-to-agent mapping. |
72
- | **Automatic Model Fallback** | When a model rate-limits or 5xx's, [`@razroo/opencode-model-fallback`](https://www.npmjs.com/package/@razroo/opencode-model-fallback) rotates the agent through a configured `fallback_models` chain and replays the request. Ships with sensible defaults: free-tier agents fall back to another free model then to paid as an escape hatch, paid agents fall back to a different paid provider. |
71
+ | **Cost-Aware Agent Routing** | Three subagents (`@general-free`, `@general-paid`, `@glm-minimal`) with per-task model tiers. On OpenCode, all three default to free OpenRouter models so the harness can run there without paid model spend. See [Subagent Routing in AGENTS.md](AGENTS.md) for the task-to-agent mapping. |
72
+ | **Automatic Model Fallback** | When a model rate-limits or 5xx's, [`@razroo/opencode-model-fallback`](https://www.npmjs.com/package/@razroo/opencode-model-fallback) rotates the agent through a configured `fallback_models` chain and replays the request. JobForge's OpenCode defaults stay on free models for both primaries and fallbacks. |
73
73
  | **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. |
74
74
 
75
75
  ## Usage
@@ -135,6 +135,11 @@ write('package.json', JSON.stringify(consumerPkg, null, 2) + '\n');
135
135
 
136
136
  const opencodeCfg = {
137
137
  $schema: 'https://opencode.ai/config.json',
138
+ // Keep the top-level orchestrator on a free model too. Subagents pin
139
+ // their own models in .opencode/agents/*.md; this covers the main chat
140
+ // session and any commands that don't hop to a subagent immediately.
141
+ model: 'openrouter/qwen/qwen3-coder:free',
142
+ small_model: 'openrouter/google/gemma-4-26b-a4b-it:free',
138
143
  // Model-fallback plugin: on rate-limit / 5xx / known provider errors,
139
144
  // rotates the agent's model to the next entry in its fallback_models
140
145
  // chain (see `agent` below) and replays the request. Without this, a
@@ -170,6 +175,22 @@ const opencodeCfg = {
170
175
  environment: { DISABLE_HTTP: 'true' },
171
176
  },
172
177
  },
178
+ // Register the exact OpenRouter free models the harness uses so they're
179
+ // selectable even if they are not in OpenCode's built-in preloaded set.
180
+ provider: {
181
+ openrouter: {
182
+ models: {
183
+ 'qwen/qwen3-coder:free': {},
184
+ 'minimax/minimax-m2.5:free': {},
185
+ 'qwen/qwen3-next-80b-a3b-instruct:free': {},
186
+ 'google/gemma-4-26b-a4b-it:free': {},
187
+ 'google/gemma-4-31b-it:free': {},
188
+ 'openai/gpt-oss-120b:free': {},
189
+ 'openai/gpt-oss-20b:free': {},
190
+ 'z-ai/glm-4.5-air:free': {},
191
+ },
192
+ },
193
+ },
173
194
  // Restrict the primary orchestrator to dispatching only the three harness
174
195
  // subagents. Prevents accidental self-calls or unregistered agents.
175
196
  // Override locally in opencode.json if you add project-specific agents.
package/bin/sync.mjs CHANGED
@@ -75,6 +75,7 @@ const links = [
75
75
 
76
76
  // OpenCode: skill router + subagent definitions. Users can override any
77
77
  // single subagent by replacing its symlink with a local file.
78
+ { src: '.opencode/opencode-model-fallback.json', dst: '.opencode/opencode-model-fallback.json' },
78
79
  { src: '.opencode/skills/job-forge.md', dst: '.opencode/skills/job-forge.md' },
79
80
  { src: '.opencode/agents', dst: '.opencode/agents' },
80
81
 
@@ -43,7 +43,7 @@ The consumer's `opencode.json` loads a small set of stable files as always-prese
43
43
 
44
44
  The skill router (`.opencode/skills/job-forge.md`) loads mode and data files on demand, keeping per-session input tokens low (~20-40K for most modes instead of ~130-170K when everything was force-loaded).
45
45
 
46
- **Cost-tiered subagents** live in `.opencode/agents/` (`general-free`, `general-paid`, `glm-minimal`) the orchestrator delegates procedural work to free-tier models and reserves paid models for quality-sensitive writing. See [MODEL-ROUTING.md](MODEL-ROUTING.md) for the routing architecture, why it exists, and how to customize.
46
+ **Cost-tiered subagents** live in `.opencode/agents/` (`general-free`, `general-paid`, `glm-minimal`). On OpenCode, all three now resolve to free OpenRouter models by default, with different quality/latency tiers per task shape. See [MODEL-ROUTING.md](MODEL-ROUTING.md) for the routing architecture, why it exists, and how to customize.
47
47
 
48
48
  **Multi-harness support.** Because `iso/` is the single source of truth, publishing ships config for OpenCode, Cursor, Claude Code, and Codex in one tarball. Consumers run any of `opencode`, `cursor`, `claude`, or `codex` in the project and each picks up the shared MCP config + instructions via the symlinks above.
49
49
 
@@ -7,8 +7,8 @@ JobForge routes each piece of work to the cheapest model that can do it well, in
7
7
  A two-day trace early in development showed `$48` in spend, with **84% coming from GLM 5.1** despite the majority of the work being procedural (form fills, tracker updates, OTP retrieval). The root cause:
8
8
 
9
9
  - **GLM 5.1's provider doesn't discount cache reads.** On Anthropic, a 10K-token cached prefix costs ~$0.03. On GLM 5.1 it bills near-full input rate (~$0.35). Every session that re-loads the prefix pays full price.
10
- - **Procedural work is the high-volume work.** 1000+ messages per day go to form filling, TSV merges, scan dedup. Running that on GLM 5.1 is ~10× more expensive than running it on a free-tier model that can handle the task just fine.
11
- - **Free-tier opencode models are genuinely free and genuinely capable.** `opencode/big-pickle` processed 1000+ messages at $0 over the same window with acceptable quality on procedural tasks.
10
+ - **Procedural work is the high-volume work.** 1000+ messages per day go to form filling, TSV merges, scan dedup. Running that on a paid model is unnecessary when current free OpenRouter models can handle the task.
11
+ - **Current OpenRouter free models are strong enough to cover the whole OpenCode path.** JobForge now defaults every OpenCode role to a free model, including the quality-sensitive writer tier.
12
12
 
13
13
  Conclusion: route procedural work to free tier, reserve paid models for tasks that actually need the quality.
14
14
 
@@ -18,9 +18,9 @@ Defined in `.opencode/agents/*.md` (shipped in the harness, symlinked into consu
18
18
 
19
19
  | Agent | Model | Reasoning | Use for |
20
20
  |-------|-------|-----------|---------|
21
- | `@general-free` | `opencode/big-pickle` (free) | `minimal` | Geometra form fills, tracker TSV merges, scan dedup, OTP retrieval via Gmail, scripted pipeline steps |
22
- | `@general-paid` | `opencode/glm-5.1` | `medium` | Offer evaluation narratives (Blocks A-F), cover letters, "Why X?" answers, STAR+R interview stories, LinkedIn outreach prose |
23
- | `@glm-minimal` | `opencode/minimax-m2.5-free` (free) | `none` | Narrow one-shot transforms: "extract these 8 fields from this JD text → JSON", "classify this archetype" |
21
+ | `@general-free` | `openrouter/minimax/minimax-m2.5:free` | `minimal` | Geometra form fills, tracker TSV merges, scan dedup, OTP retrieval via Gmail, scripted pipeline steps |
22
+ | `@general-paid` | `openrouter/qwen/qwen3-next-80b-a3b-instruct:free` | `medium` | Offer evaluation narratives (Blocks A-F), cover letters, "Why X?" answers, STAR+R interview stories, LinkedIn outreach prose |
23
+ | `@glm-minimal` | `openrouter/google/gemma-4-26b-a4b-it:free` | `none` | Narrow one-shot transforms: "extract these 8 fields from this JD text → JSON", "classify this archetype" |
24
24
 
25
25
  The full task-to-agent mapping lives in [AGENTS.md → Subagent Routing](../AGENTS.md#subagent-routing--which-agent-for-which-task). The orchestrator (your primary session) is expected to delegate before taking any multi-step action — see the **Pre-flight delegation** rule in AGENTS.md.
26
26
 
@@ -66,7 +66,7 @@ All three layers are designed to be edited — this is your search, your cost bu
66
66
 
67
67
  ### Swap the paid model
68
68
 
69
- The default `@general-paid` is `opencode/glm-5.1`. To use Claude instead, edit `.opencode/agents/general-paid.md`:
69
+ The default `@general-paid` is `openrouter/qwen/qwen3-next-80b-a3b-instruct:free`. To use Claude instead, edit `.opencode/agents/general-paid.md`:
70
70
 
71
71
  ```yaml
72
72
  ---
@@ -79,7 +79,7 @@ The `.opencode/agents/general-paid.md` file is a symlink into `node_modules/job-
79
79
 
80
80
  ### Swap the free tier
81
81
 
82
- Same idea — edit `.opencode/agents/general-free.md`'s `model:` field. `opencode/minimax-m2.5-free` is another zero-cost option the data shows handles ~900 messages per day cleanly. If you run into quality issues on forms, bump this agent's model to a small paid tier (e.g., Haiku) rather than routing everything through paid.
82
+ Same idea — edit `.opencode/agents/general-free.md`'s `model:` field. If you run into quality issues on forms, swap to a different free OpenRouter model first before considering a paid tier.
83
83
 
84
84
  ### Add a custom agent
85
85
 
@@ -122,8 +122,8 @@ npx job-forge tokens --session <session-id>
122
122
  ```
123
123
 
124
124
  Healthy pattern after this architecture lands:
125
- - **`opencode/big-pickle`** (or your free-tier choice) handles the message majority at $0
126
- - **`opencode/glm-5.1`** (or your paid choice) costs per session stay under $1 for most evaluations
125
+ - **Free OpenRouter defaults** now cover procedural, quality-sensitive, and extractor work on OpenCode
126
+ - If you opt back into a paid model, do it deliberately and only for the role that needs it
127
127
  - Session titles prefixed `@general-free`, `@general-paid`, `@glm-minimal` appear in the list — confirms delegation actually happened
128
128
  - `cache_read` >> `cache_creation` on parallel subagent runs within a 5-min window
129
129
 
@@ -139,13 +139,13 @@ Default chains ship upstream in each agent's YAML frontmatter (`node_modules/job
139
139
 
140
140
  | Agent | Primary | Fallback chain (in order) |
141
141
  |-------|---------|---------------------------|
142
- | `@general-free` | `opencode/big-pickle` | `opencode/minimax-m2.5-free` `opencode/nemotron-3-super-free` → `opencode-go/minimax-m2.7` → `opencode/glm-5.1` (paid escape hatch) |
143
- | `@general-paid` | `opencode/glm-5.1` | `opencode/claude-haiku-4-5` |
144
- | `@glm-minimal` | `opencode/minimax-m2.5-free` | `opencode/big-pickle` → `opencode/nemotron-3-super-free` |
142
+ | `@general-free` | `openrouter/minimax/minimax-m2.5:free` | `openrouter/qwen/qwen3-coder:free` → `openrouter/google/gemma-4-26b-a4b-it:free` → `openrouter/openai/gpt-oss-20b:free` |
143
+ | `@general-paid` | `openrouter/qwen/qwen3-next-80b-a3b-instruct:free` | `openrouter/qwen/qwen3-coder:free` → `openrouter/openai/gpt-oss-120b:free` → `openrouter/z-ai/glm-4.5-air:free` |
144
+ | `@glm-minimal` | `openrouter/google/gemma-4-26b-a4b-it:free` | `openrouter/minimax/minimax-m2.5:free` `openrouter/openai/gpt-oss-20b:free` → `openrouter/google/gemma-4-31b-it:free` |
145
145
 
146
- Free-tier agents exhaust free models first, then try minimax 2.7 as a cheap buffer before escalating to glm-5.1. Paid agents fall back to Haiku (cheaper unstick escape hatch). **Note:** all model IDs use the `opencode/` or `opencode-go/` prefix the `anthropic/` prefix does not exist in opencode's model registry and will throw `ProviderModelNotFoundError`.
146
+ These chains are deliberately free-only so the default OpenCode path never needs to pay. **Note:** OpenCode model IDs must use the provider prefix it expects (`openrouter/...`, `opencode/...`, etc.). The raw OpenRouter model slug by itself is not enough.
147
147
 
148
- Consumers **do not need to configure anything** to get these defaults: the chains arrive via the symlinked agent MD files, and `@razroo/opencode-model-fallback` (≥0.3.1) reads them from the `options.fallback_models` field that opencode relocates unknown frontmatter keys into. The consumer's `opencode.json` only needs `"plugin": ["@razroo/opencode-model-fallback"]` — which the scaffolder sets automatically.
148
+ Consumers **do not need to configure anything** to get these defaults: the subagent chains arrive via the symlinked agent MD files, and the harness also ships `.opencode/opencode-model-fallback.json` for the main orchestrator / any agent without its own list. `@razroo/opencode-model-fallback` (≥0.3.1) reads per-agent chains from the frontmatter-derived `fallback_models` field and falls through to the global file when no per-agent list exists. The consumer's `opencode.json` only needs `"plugin": ["@razroo/opencode-model-fallback"]` — which the scaffolder sets automatically.
149
149
 
150
150
  **When fallback fires:** the plugin pattern-matches rate-limit / 5xx / quota / "overloaded" / "insufficient credits" errors. Failed models enter a 60-second cooldown before they're retried. Every rotation logs to `~/.config/opencode/opencode-model-fallback.log` with the trigger error, original model, and target model — grep for `"Auto-retrying with fallback model"` to confirm it fired.
151
151
 
@@ -172,7 +172,7 @@ Plugin-level config at `.opencode/opencode-model-fallback.json` — applies to a
172
172
  "cooldown_seconds": 60,
173
173
  "timeout_seconds": 30,
174
174
  "notify_on_fallback": true,
175
- "fallback_models": ["opencode/minimax-m2.5-free", "opencode/glm-5.1"]
175
+ "fallback_models": ["openrouter/minimax/minimax-m2.5:free", "openrouter/qwen/qwen3-coder:free"]
176
176
  }
177
177
  ```
178
178
 
@@ -10,6 +10,10 @@ targets:
10
10
  mode: subagent
11
11
  temperature: 0.1
12
12
  reasoningEffort: minimal
13
+ fallback_models:
14
+ - openrouter/qwen/qwen3-coder:free
15
+ - openrouter/google/gemma-4-26b-a4b-it:free
16
+ - openrouter/openai/gpt-oss-20b:free
13
17
  tools:
14
18
  geometra_connect: true
15
19
  geometra_page_model: true
@@ -1,15 +1,20 @@
1
1
  ---
2
- description: Quality-sensitive worker on paid model. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
2
+ description: Quality-sensitive worker on the strongest free-tier OpenCode model by default. Use for offer evaluation narratives (Blocks A-F), cover letter generation, "Why X?" form answers, interview STAR stories, and other tasks where writing quality and judgment matter.
3
3
  role: quality
4
4
  targets:
5
- # No inline model: iso-route's "standard" preset maps role "quality" to
6
- # each harness's top-tier reasoning-capable model. Claude Code reads
5
+ # No inline model: JobForge's models.yaml maps role "quality" to a
6
+ # free OpenRouter model on OpenCode, while Claude/Codex keep their
7
+ # quality-tier defaults from the standard preset. Claude Code reads
7
8
  # .claude/iso-route.resolved.json; OpenCode reads opencode.json's
8
9
  # agent.quality.model (iso-harness 0.6.0+).
9
10
  opencode:
10
11
  mode: subagent
11
12
  temperature: 0.3
12
13
  reasoningEffort: medium
14
+ fallback_models:
15
+ - openrouter/qwen/qwen3-coder:free
16
+ - openrouter/openai/gpt-oss-120b:free
17
+ - openrouter/z-ai/glm-4.5-air:free
13
18
  tools:
14
19
  geometra_*: false
15
20
  gmail_*: false
@@ -17,6 +22,11 @@ targets:
17
22
 
18
23
  You are the @general-paid subagent. The orchestrator delegated this task to you because it requires quality writing or judgment — the kind of work `@general-free` isn't well-suited for.
19
24
 
25
+ On OpenCode, this agent now defaults to a free OpenRouter model. On other
26
+ harnesses, the same role may still resolve to a premium model. Your job is
27
+ still the same: produce the best final writing you can from the context you
28
+ were given.
29
+
20
30
  ## Do These Tasks
21
31
 
22
32
  - Generate evaluation narratives (Blocks A-F) per `modes/offer.md`.
@@ -10,6 +10,10 @@ targets:
10
10
  mode: subagent
11
11
  temperature: 0
12
12
  reasoningEffort: none
13
+ fallback_models:
14
+ - openrouter/minimax/minimax-m2.5:free
15
+ - openrouter/openai/gpt-oss-20b:free
16
+ - openrouter/google/gemma-4-31b-it:free
13
17
  tools:
14
18
  geometra_*: false
15
19
  gmail_*: false
package/iso/config.json CHANGED
@@ -1,7 +1,23 @@
1
1
  {
2
2
  "targets": {
3
3
  "opencode": {
4
- "instructions": ["templates/states.yml"]
4
+ "plugin": ["@razroo/opencode-model-fallback"],
5
+ "instructions": ["templates/states.yml"],
6
+ "small_model": "openrouter/google/gemma-4-26b-a4b-it:free",
7
+ "provider": {
8
+ "openrouter": {
9
+ "models": {
10
+ "qwen/qwen3-coder:free": {},
11
+ "minimax/minimax-m2.5:free": {},
12
+ "qwen/qwen3-next-80b-a3b-instruct:free": {},
13
+ "google/gemma-4-26b-a4b-it:free": {},
14
+ "google/gemma-4-31b-it:free": {},
15
+ "openai/gpt-oss-120b:free": {},
16
+ "openai/gpt-oss-20b:free": {},
17
+ "z-ai/glm-4.5-air:free": {}
18
+ }
19
+ }
20
+ }
5
21
  }
6
22
  }
7
23
  }
package/models.yaml CHANGED
@@ -1,15 +1,17 @@
1
1
  # JobForge model policy.
2
2
  #
3
- # Extends @razroo/iso-route's bundled "standard" preset — a curated
4
- # cost-tiered routing config verified against 2026-04 provider catalogs.
5
- # Preset content lives in node_modules/@razroo/iso-route/presets/standard.yaml;
6
- # run `npx iso-route plan models.yaml` to see the resolved policy.
3
+ # Extends @razroo/iso-route's bundled "openrouter-free" preset — a
4
+ # curated zero-cost routing config that keeps Claude Code / Codex on
5
+ # their native providers but routes OpenCode through explicit free
6
+ # OpenRouter model IDs. Preset content lives in
7
+ # node_modules/@razroo/iso-route/presets/openrouter-free.yaml; run
8
+ # `npx iso-route plan models.yaml` to see the resolved policy.
7
9
  #
8
10
  # JobForge's subagents bind to preset roles via the `role:` field in
9
11
  # iso/agents/<slug>.md:
10
- # @general-free → role: fast (Haiku / opencode/big-pickle / gpt-5.4-mini)
11
- # @general-paid → role: quality (Opus 4.7 / opencode-go/kimi-k2.5 / gpt-5.4)
12
- # @glm-minimal → role: minimal (Haiku / opencode/minimax-m2.5-free / gpt-5.4-nano)
12
+ # @general-free → role: fast (Haiku / OpenRouter MiniMax M2.5 free / gpt-5.4-mini)
13
+ # @general-paid → role: quality (Opus 4.7 / OpenRouter Qwen3 Next 80B free / gpt-5.4)
14
+ # @glm-minimal → role: minimal (Haiku / OpenRouter Gemma 4 26B free / gpt-5.4-nano)
13
15
  #
14
16
  # Override anything by adding fields here. For example, to pin Opus on
15
17
  # Claude Code for the @general-paid (quality) role:
@@ -27,4 +29,14 @@
27
29
  # provider: openai
28
30
  # model: gpt-5.4
29
31
 
30
- extends: standard
32
+ extends: openrouter-free
33
+
34
+ # Only override the preset where we prefer a different OpenRouter pick.
35
+ # The preset's quality-tier OpenCode pick is openai/gpt-oss-120b:free;
36
+ # we prefer Qwen3 Next 80B for job-application writing quality.
37
+ roles:
38
+ quality:
39
+ targets:
40
+ opencode:
41
+ provider: openrouter
42
+ model: qwen/qwen3-next-80b-a3b-instruct:free
package/opencode.json CHANGED
@@ -1,15 +1,29 @@
1
1
  {
2
2
  "$schema": "https://opencode.ai/config.json",
3
- "model": "opencode/glm-5.1",
3
+ "model": "openrouter/qwen/qwen3-coder:free",
4
4
  "agent": {
5
5
  "fast": {
6
- "model": "opencode/big-pickle"
6
+ "model": "openrouter/minimax/minimax-m2.5:free"
7
7
  },
8
8
  "quality": {
9
- "model": "opencode-go/kimi-k2.5"
9
+ "model": "openrouter/qwen/qwen3-next-80b-a3b-instruct:free"
10
10
  },
11
11
  "minimal": {
12
- "model": "opencode/minimax-m2.5-free"
12
+ "model": "openrouter/google/gemma-4-26b-a4b-it:free"
13
+ }
14
+ },
15
+ "provider": {
16
+ "openrouter": {
17
+ "models": {
18
+ "qwen/qwen3-coder:free": {},
19
+ "minimax/minimax-m2.5:free": {},
20
+ "qwen/qwen3-next-80b-a3b-instruct:free": {},
21
+ "google/gemma-4-26b-a4b-it:free": {},
22
+ "google/gemma-4-31b-it:free": {},
23
+ "openai/gpt-oss-120b:free": {},
24
+ "openai/gpt-oss-20b:free": {},
25
+ "z-ai/glm-4.5-air:free": {}
26
+ }
13
27
  }
14
28
  },
15
29
  "mcp": {
@@ -34,7 +48,11 @@
34
48
  }
35
49
  }
36
50
  },
51
+ "plugin": [
52
+ "@razroo/opencode-model-fallback"
53
+ ],
37
54
  "instructions": [
38
55
  "templates/states.yml"
39
- ]
56
+ ],
57
+ "small_model": "openrouter/google/gemma-4-26b-a4b-it:free"
40
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job-forge",
3
- "version": "2.12.0",
3
+ "version": "2.13.0",
4
4
  "description": "AI-powered job search pipeline built on opencode",
5
5
  "type": "module",
6
6
  "bin": {
@@ -87,9 +87,10 @@
87
87
  "playwright": "^1.58.1"
88
88
  },
89
89
  "devDependencies": {
90
- "@razroo/iso": "^0.2.4",
90
+ "@razroo/iso": "^0.2.5",
91
91
  "@razroo/iso-harness": "^0.6.0",
92
- "@razroo/iso-route": "^0.3.0",
93
- "@razroo/iso-trace": "^0.1.0"
92
+ "@razroo/iso-route": "^0.5.0",
93
+ "@razroo/iso-trace": "^0.1.0",
94
+ "@razroo/opencode-model-fallback": "^0.3.1"
94
95
  }
95
96
  }