job-forge 2.14.11 → 2.14.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/general-free.md +2 -2
- package/.claude/agents/general-paid.md +5 -5
- package/.claude/agents/glm-minimal.md +1 -1
- package/.cursor/rules/agent-general-free.mdc +2 -2
- package/.cursor/rules/agent-general-paid.mdc +5 -5
- package/.cursor/rules/agent-glm-minimal.mdc +1 -1
- package/.cursor/rules/main.mdc +2 -2
- package/.opencode/agents/general-free.md +3 -8
- package/.opencode/agents/general-paid.md +6 -13
- package/.opencode/agents/glm-minimal.md +2 -7
- package/AGENTS.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.md +2 -2
- package/bin/create-job-forge.mjs +10 -48
- package/bin/sync.mjs +0 -1
- package/docs/ARCHITECTURE.md +2 -2
- package/docs/MODEL-ROUTING.md +43 -76
- package/docs/README.md +1 -1
- package/iso/agents/general-free.md +5 -13
- package/iso/agents/general-paid.md +8 -20
- package/iso/agents/glm-minimal.md +4 -11
- package/iso/config.json +1 -42
- package/iso/instructions.md +2 -2
- package/models.yaml +25 -11
- package/modes/apply.md +8 -8
- package/opencode.json +5 -26
- package/package.json +2 -3
- package/scripts/check-iso-smoke.mjs +7 -3
- package/.opencode/opencode-model-fallback.json +0 -22
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: general-free
|
|
3
|
-
description: Procedural worker on
|
|
3
|
+
description: Procedural worker on the low-cost DeepSeek V4 Flash OpenCode route. 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.
|
|
4
4
|
model: claude-haiku-4-5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
You are the @general-free subagent. You run on
|
|
7
|
+
You are the @general-free subagent. You run on JobForge's low-cost procedural 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.
|
|
8
8
|
|
|
9
9
|
## Run This Pre-Flight First Every Time
|
|
10
10
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: general-paid
|
|
3
|
-
description: Quality-sensitive worker on the
|
|
3
|
+
description: Quality-sensitive worker on the low-cost DeepSeek V4 Flash OpenCode route 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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
were given.
|
|
9
|
+
On OpenCode, this agent defaults to DeepSeek V4 Flash so application work
|
|
10
|
+
does not fall back into overloaded free OpenRouter pools. On other harnesses,
|
|
11
|
+
the same role may still resolve to a premium model. Your job is still the
|
|
12
|
+
same: produce the best final writing you can from the context you were given.
|
|
13
13
|
|
|
14
14
|
## Do These Tasks
|
|
15
15
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: glm-minimal
|
|
3
|
-
description: Narrow-scope extractor on
|
|
3
|
+
description: Narrow-scope extractor on the low-cost DeepSeek V4 Flash OpenCode route. 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.
|
|
4
4
|
model: claude-haiku-4-5
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Procedural worker on
|
|
2
|
+
description: Procedural worker on the low-cost DeepSeek V4 Flash OpenCode route. 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
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
You are the @general-free subagent. You run on
|
|
6
|
+
You are the @general-free subagent. You run on JobForge's low-cost procedural 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.
|
|
7
7
|
|
|
8
8
|
## Run This Pre-Flight First Every Time
|
|
9
9
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Quality-sensitive worker on the
|
|
2
|
+
description: Quality-sensitive worker on the low-cost DeepSeek V4 Flash OpenCode route 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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
were given.
|
|
8
|
+
On OpenCode, this agent defaults to DeepSeek V4 Flash so application work
|
|
9
|
+
does not fall back into overloaded free OpenRouter pools. On other harnesses,
|
|
10
|
+
the same role may still resolve to a premium model. Your job is still the
|
|
11
|
+
same: produce the best final writing you can from the context you were given.
|
|
12
12
|
|
|
13
13
|
## Do These Tasks
|
|
14
14
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Narrow-scope extractor on
|
|
2
|
+
description: Narrow-scope extractor on the low-cost DeepSeek V4 Flash OpenCode route. 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
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
|
package/.cursor/rules/main.mdc
CHANGED
|
@@ -10,7 +10,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
10
10
|
## Hard limits
|
|
11
11
|
|
|
12
12
|
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. A round is not complete until both subagents return a final outcome (`APPLIED`, `APPLY FAILED`, `SKIP`, `Discarded`, or a written TSV path). A `task` tool result that only gives a session id / title is a launch acknowledgement, not completion. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
13
|
-
why:
|
|
13
|
+
why: each subagent requires post-cleanup and racing more than 2 reliably loses at least one result. On 2026-04-25 the orchestrator launched round 2 while round 1 had only returned task ids, leaving four application subagents in flight and losing two provider recoveries
|
|
14
14
|
|
|
15
15
|
- [H2] Max 1 application per company+role. Before every `apply` dispatch, grep all four sources for the URL and for `company+role`: `data/pipeline.md`, all `data/applications/*.md` day files, `batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`. If any source shows APPLIED / Applied, skip the dispatch.
|
|
16
16
|
why: 2026-04 same-day batch collision — when two batches target the same role, `npx job-forge merge` updates the existing day-file row rather than appending, so grepping day files alone misses earlier-batch applies; merged/*.tsv is the only place the breadcrumb remains
|
|
@@ -42,7 +42,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
42
42
|
why: iso-trace showed 0.25% Agent calls across 5174 turns under a prior over-broad "delegate before 2nd tool call" rule — the rule was ignored in practice; narrowing matches the original cache-bust incident
|
|
43
43
|
|
|
44
44
|
- [D2] Route subagent work by cost tier. `@general-free`: procedural — form-fill, TSV merge, verify, OTP retrieval, portal scan metadata extraction, one-shot structured-field transforms. `@general-paid`: quality-sensitive — offer evaluation narrative Blocks A-F, cover letters, "Why X?" answers, STAR interview stories, LinkedIn outreach. `@glm-minimal`: narrow ≤5K-input one-shot extract/classify jobs that do not need context.
|
|
45
|
-
why:
|
|
45
|
+
why: OpenCode routes all JobForge tiers through DeepSeek V4 Flash by default now; recent traces showed free OpenRouter fallbacks freezing or hitting provider balance errors during applications
|
|
46
46
|
|
|
47
47
|
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
48
48
|
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Procedural worker on
|
|
2
|
+
description: Procedural worker on the low-cost DeepSeek V4 Flash OpenCode route. 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/
|
|
4
|
+
model: opencode-go/deepseek-v4-flash
|
|
5
5
|
tools:
|
|
6
6
|
geometra_connect: true
|
|
7
7
|
geometra_page_model: true
|
|
@@ -17,14 +17,9 @@ tools:
|
|
|
17
17
|
task: false
|
|
18
18
|
temperature: 0.1
|
|
19
19
|
reasoningEffort: minimal
|
|
20
|
-
fallback_models:
|
|
21
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
22
|
-
- openrouter/openai/gpt-oss-20b:free
|
|
23
|
-
- openrouter/nvidia/nemotron-3-nano-30b-a3b:free
|
|
24
|
-
- openrouter/qwen/qwen3-coder:free
|
|
25
20
|
---
|
|
26
21
|
|
|
27
|
-
You are the @general-free subagent. You run on
|
|
22
|
+
You are the @general-free subagent. You run on JobForge's low-cost procedural 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.
|
|
28
23
|
|
|
29
24
|
## Run This Pre-Flight First Every Time
|
|
30
25
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Quality-sensitive worker on the
|
|
2
|
+
description: Quality-sensitive worker on the low-cost DeepSeek V4 Flash OpenCode route 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:
|
|
4
|
+
model: opencode-go/deepseek-v4-flash
|
|
5
5
|
tools:
|
|
6
6
|
geometra_connect: true
|
|
7
7
|
geometra_page_model: true
|
|
@@ -17,21 +17,14 @@ tools:
|
|
|
17
17
|
task: false
|
|
18
18
|
temperature: 0.3
|
|
19
19
|
reasoningEffort: medium
|
|
20
|
-
fallback_models:
|
|
21
|
-
- openrouter/openai/gpt-oss-120b:free
|
|
22
|
-
- openrouter/nvidia/nemotron-3-super-120b-a12b:free
|
|
23
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
24
|
-
- openrouter/qwen/qwen3-coder:free
|
|
25
|
-
- openrouter/google/gemma-4-31b-it:free
|
|
26
|
-
- openrouter/meta-llama/llama-3.3-70b-instruct:free
|
|
27
20
|
---
|
|
28
21
|
|
|
29
22
|
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.
|
|
30
23
|
|
|
31
|
-
On OpenCode, this agent
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
were given.
|
|
24
|
+
On OpenCode, this agent defaults to DeepSeek V4 Flash so application work
|
|
25
|
+
does not fall back into overloaded free OpenRouter pools. On other harnesses,
|
|
26
|
+
the same role may still resolve to a premium model. Your job is still the
|
|
27
|
+
same: produce the best final writing you can from the context you were given.
|
|
35
28
|
|
|
36
29
|
## Do These Tasks
|
|
37
30
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Narrow-scope extractor on
|
|
2
|
+
description: Narrow-scope extractor on the low-cost DeepSeek V4 Flash OpenCode route. 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:
|
|
4
|
+
model: opencode-go/deepseek-v4-flash
|
|
5
5
|
tools:
|
|
6
6
|
geometra_*: false
|
|
7
7
|
gmail_*: false
|
|
@@ -13,11 +13,6 @@ tools:
|
|
|
13
13
|
task: false
|
|
14
14
|
temperature: 0
|
|
15
15
|
reasoningEffort: none
|
|
16
|
-
fallback_models:
|
|
17
|
-
- openrouter/google/gemma-4-26b-a4b-it:free
|
|
18
|
-
- openrouter/nvidia/nemotron-nano-9b-v2:free
|
|
19
|
-
- openrouter/google/gemma-4-31b-it:free
|
|
20
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
21
16
|
---
|
|
22
17
|
|
|
23
18
|
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.
|
package/AGENTS.md
CHANGED
|
@@ -5,7 +5,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
5
5
|
## Hard limits
|
|
6
6
|
|
|
7
7
|
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. A round is not complete until both subagents return a final outcome (`APPLIED`, `APPLY FAILED`, `SKIP`, `Discarded`, or a written TSV path). A `task` tool result that only gives a session id / title is a launch acknowledgement, not completion. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
8
|
-
why:
|
|
8
|
+
why: each subagent requires post-cleanup and racing more than 2 reliably loses at least one result. On 2026-04-25 the orchestrator launched round 2 while round 1 had only returned task ids, leaving four application subagents in flight and losing two provider recoveries
|
|
9
9
|
|
|
10
10
|
- [H2] Max 1 application per company+role. Before every `apply` dispatch, grep all four sources for the URL and for `company+role`: `data/pipeline.md`, all `data/applications/*.md` day files, `batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`. If any source shows APPLIED / Applied, skip the dispatch.
|
|
11
11
|
why: 2026-04 same-day batch collision — when two batches target the same role, `npx job-forge merge` updates the existing day-file row rather than appending, so grepping day files alone misses earlier-batch applies; merged/*.tsv is the only place the breadcrumb remains
|
|
@@ -37,7 +37,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
37
37
|
why: iso-trace showed 0.25% Agent calls across 5174 turns under a prior over-broad "delegate before 2nd tool call" rule — the rule was ignored in practice; narrowing matches the original cache-bust incident
|
|
38
38
|
|
|
39
39
|
- [D2] Route subagent work by cost tier. `@general-free`: procedural — form-fill, TSV merge, verify, OTP retrieval, portal scan metadata extraction, one-shot structured-field transforms. `@general-paid`: quality-sensitive — offer evaluation narrative Blocks A-F, cover letters, "Why X?" answers, STAR interview stories, LinkedIn outreach. `@glm-minimal`: narrow ≤5K-input one-shot extract/classify jobs that do not need context.
|
|
40
|
-
why:
|
|
40
|
+
why: OpenCode routes all JobForge tiers through DeepSeek V4 Flash by default now; recent traces showed free OpenRouter fallbacks freezing or hitting provider balance errors during applications
|
|
41
41
|
|
|
42
42
|
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
43
43
|
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
package/CLAUDE.md
CHANGED
|
@@ -5,7 +5,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
5
5
|
## Hard limits
|
|
6
6
|
|
|
7
7
|
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. A round is not complete until both subagents return a final outcome (`APPLIED`, `APPLY FAILED`, `SKIP`, `Discarded`, or a written TSV path). A `task` tool result that only gives a session id / title is a launch acknowledgement, not completion. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
8
|
-
why:
|
|
8
|
+
why: each subagent requires post-cleanup and racing more than 2 reliably loses at least one result. On 2026-04-25 the orchestrator launched round 2 while round 1 had only returned task ids, leaving four application subagents in flight and losing two provider recoveries
|
|
9
9
|
|
|
10
10
|
- [H2] Max 1 application per company+role. Before every `apply` dispatch, grep all four sources for the URL and for `company+role`: `data/pipeline.md`, all `data/applications/*.md` day files, `batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`. If any source shows APPLIED / Applied, skip the dispatch.
|
|
11
11
|
why: 2026-04 same-day batch collision — when two batches target the same role, `npx job-forge merge` updates the existing day-file row rather than appending, so grepping day files alone misses earlier-batch applies; merged/*.tsv is the only place the breadcrumb remains
|
|
@@ -37,7 +37,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
37
37
|
why: iso-trace showed 0.25% Agent calls across 5174 turns under a prior over-broad "delegate before 2nd tool call" rule — the rule was ignored in practice; narrowing matches the original cache-bust incident
|
|
38
38
|
|
|
39
39
|
- [D2] Route subagent work by cost tier. `@general-free`: procedural — form-fill, TSV merge, verify, OTP retrieval, portal scan metadata extraction, one-shot structured-field transforms. `@general-paid`: quality-sensitive — offer evaluation narrative Blocks A-F, cover letters, "Why X?" answers, STAR interview stories, LinkedIn outreach. `@glm-minimal`: narrow ≤5K-input one-shot extract/classify jobs that do not need context.
|
|
40
|
-
why:
|
|
40
|
+
why: OpenCode routes all JobForge tiers through DeepSeek V4 Flash by default now; recent traces showed free OpenRouter fallbacks freezing or hitting provider balance errors during applications
|
|
41
41
|
|
|
42
42
|
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
43
43
|
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
package/README.md
CHANGED
|
@@ -74,8 +74,8 @@ JobForge turns opencode into a full job search command center. Instead of manual
|
|
|
74
74
|
| **Portal Scanner** | 45+ companies pre-configured with fuzzy dedup for reposts |
|
|
75
75
|
| **Batch Processing** | Parallel evaluation with `opencode run` workers, with honest verification flagging |
|
|
76
76
|
| **Pipeline Integrity** | Automated merge, dedup, status normalization, health checks |
|
|
77
|
-
| **Cost-Aware Agent Routing** | Three subagents (`@general-free`, `@general-paid`, `@glm-minimal`) with per-task
|
|
78
|
-
| **
|
|
77
|
+
| **Cost-Aware Agent Routing** | Three subagents (`@general-free`, `@general-paid`, `@glm-minimal`) with per-task tool surfaces. On OpenCode, JobForge pins all tiers to `opencode-go/deepseek-v4-flash` so application runs avoid overloaded free-model pools. See [Subagent Routing in AGENTS.md](AGENTS.md) for the task-to-agent mapping. |
|
|
78
|
+
| **Trace + Telemetry** | `job-forge trace:*` exposes local OpenCode transcripts, and `job-forge telemetry:*` summarizes runs, child outcomes, provider errors, and pending tracker TSVs. |
|
|
79
79
|
| **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. |
|
|
80
80
|
|
|
81
81
|
## Usage
|
package/bin/create-job-forge.mjs
CHANGED
|
@@ -117,22 +117,14 @@ const consumerPkg = {
|
|
|
117
117
|
'telemetry:status': 'job-forge telemetry:status',
|
|
118
118
|
'telemetry:show': 'job-forge telemetry:show',
|
|
119
119
|
'telemetry:watch': 'job-forge telemetry:watch',
|
|
120
|
-
// One command to pull the latest harness
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
'update-harness': 'npm update job-forge @razroo/
|
|
120
|
+
// One command to pull the latest harness and any locally-pinned MCP
|
|
121
|
+
// packages. npm update is a no-op on packages not in package.json, so
|
|
122
|
+
// listing @razroo/gmail-mcp + @geometra/mcp is safe for consumers that
|
|
123
|
+
// invoke them via `npx -y` without pinning.
|
|
124
|
+
'update-harness': 'npm update job-forge @razroo/gmail-mcp @geometra/mcp && job-forge sync && node -e "console.log(\'✅ harness at\', require(\'./package-lock.json\').packages[\'node_modules/job-forge\'].resolved)"',
|
|
125
125
|
},
|
|
126
126
|
dependencies: {
|
|
127
127
|
'job-forge': '^2.0.0',
|
|
128
|
-
// Model-fallback plugin: rotates agents through their fallback_models
|
|
129
|
-
// chain on rate-limit / 5xx errors so a rate-limited free-tier model
|
|
130
|
-
// doesn't wedge the whole flow. The chains live upstream in each
|
|
131
|
-
// agent's MD frontmatter (`.opencode/agents/*.md` in the harness);
|
|
132
|
-
// consumers can override individual chains by adding their own
|
|
133
|
-
// agent.<name>.fallback_models block to opencode.json. Requires
|
|
134
|
-
// 0.3.1+ for the frontmatter-merge path.
|
|
135
|
-
'@razroo/opencode-model-fallback': '^0.3.1',
|
|
136
128
|
},
|
|
137
129
|
engines: { node: '>=18' },
|
|
138
130
|
};
|
|
@@ -142,16 +134,11 @@ write('package.json', JSON.stringify(consumerPkg, null, 2) + '\n');
|
|
|
142
134
|
|
|
143
135
|
const opencodeCfg = {
|
|
144
136
|
$schema: 'https://opencode.ai/config.json',
|
|
145
|
-
// Keep the top-level orchestrator on
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
model: '
|
|
149
|
-
small_model: '
|
|
150
|
-
// Model-fallback plugin: on rate-limit / 5xx / known provider errors,
|
|
151
|
-
// rotates the agent's model to the next entry in its fallback_models
|
|
152
|
-
// chain (see `agent` below) and replays the request. Without this, a
|
|
153
|
-
// rate-limited free-tier model wedges the whole subagent flow.
|
|
154
|
-
plugin: ['@razroo/opencode-model-fallback'],
|
|
137
|
+
// Keep the top-level orchestrator on JobForge's low-cost paid OpenCode
|
|
138
|
+
// route. Subagents pin the same route in .opencode/agents/*.md so job
|
|
139
|
+
// applications do not fall through overloaded free OpenRouter pools.
|
|
140
|
+
model: 'opencode-go/deepseek-v4-flash',
|
|
141
|
+
small_model: 'opencode-go/deepseek-v4-flash',
|
|
155
142
|
// Files listed here load into every session's cached prefix, so they're
|
|
156
143
|
// cached once (on Anthropic) instead of Read-as-tool-call on every session.
|
|
157
144
|
// AGENTS.harness.md → symlink to node_modules/job-forge/AGENTS.md (harness rules)
|
|
@@ -182,31 +169,6 @@ const opencodeCfg = {
|
|
|
182
169
|
environment: { DISABLE_HTTP: 'true' },
|
|
183
170
|
},
|
|
184
171
|
},
|
|
185
|
-
// Register the exact OpenRouter free models the harness uses so they're
|
|
186
|
-
// selectable even if they are not in OpenCode's built-in preloaded set.
|
|
187
|
-
// This list is a superset: role primaries, per-agent fallback chains,
|
|
188
|
-
// and the orchestrator fallback chain.
|
|
189
|
-
provider: {
|
|
190
|
-
openrouter: {
|
|
191
|
-
models: {
|
|
192
|
-
// Orchestrator + agentic coding (role default)
|
|
193
|
-
'qwen/qwen3-coder:free': {},
|
|
194
|
-
// Role primaries
|
|
195
|
-
'z-ai/glm-4.5-air:free': {}, // fast
|
|
196
|
-
'qwen/qwen3-next-80b-a3b-instruct:free': {}, // quality
|
|
197
|
-
'openai/gpt-oss-20b:free': {}, // minimal
|
|
198
|
-
// Common fallbacks
|
|
199
|
-
'openai/gpt-oss-120b:free': {},
|
|
200
|
-
'minimax/minimax-m2.5:free': {},
|
|
201
|
-
'nvidia/nemotron-3-super-120b-a12b:free': {},
|
|
202
|
-
'nvidia/nemotron-3-nano-30b-a3b:free': {},
|
|
203
|
-
'nvidia/nemotron-nano-9b-v2:free': {},
|
|
204
|
-
'google/gemma-4-26b-a4b-it:free': {},
|
|
205
|
-
'google/gemma-4-31b-it:free': {},
|
|
206
|
-
'meta-llama/llama-3.3-70b-instruct:free': {},
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
172
|
// Restrict the primary orchestrator to dispatching only the three harness
|
|
211
173
|
// subagents. Prevents accidental self-calls or unregistered agents.
|
|
212
174
|
// Override locally in opencode.json if you add project-specific agents.
|
package/bin/sync.mjs
CHANGED
|
@@ -75,7 +75,6 @@ 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' },
|
|
79
78
|
{ src: '.opencode/skills/job-forge.md', dst: '.opencode/skills/job-forge.md' },
|
|
80
79
|
{ src: '.opencode/agents', dst: '.opencode/agents' },
|
|
81
80
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -43,11 +43,11 @@ 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`). On OpenCode, JobForge
|
|
46
|
+
**Cost-tiered subagents** live in `.opencode/agents/` (`general-free`, `general-paid`, `glm-minimal`). On OpenCode, JobForge pins all three tiers to `opencode-go/deepseek-v4-flash` by default, while the tiers still differ by tool surface, reasoning budget, and task prompt. 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
|
|
|
50
|
-
**Upgrading** the harness in a consumer project is `npm run update-harness` — pulls the latest `job-forge` from npm, refreshes
|
|
50
|
+
**Upgrading** the harness in a consumer project is `npm run update-harness` — pulls the latest `job-forge` from npm, refreshes pinned MCPs, re-runs symlink sync, and prints the resolved version.
|
|
51
51
|
|
|
52
52
|
## System Overview
|
|
53
53
|
|
package/docs/MODEL-ROUTING.md
CHANGED
|
@@ -4,13 +4,13 @@ JobForge routes each piece of work to the cheapest model that can do it well, in
|
|
|
4
4
|
|
|
5
5
|
## Why routing matters (the cost math)
|
|
6
6
|
|
|
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).
|
|
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). Later traces showed the opposite failure mode: free OpenRouter routes hit shared-pool contention and Venice balance errors during application subagents.
|
|
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.
|
|
11
|
-
- **
|
|
10
|
+
- **Procedural work is the high-volume work.** 1000+ messages per day go to form filling, TSV merges, scan dedup. It needs a cheap reliable route, not the absolute strongest model.
|
|
11
|
+
- **Free pools are not reliable enough for application runs.** A 2026-04-25 trace showed `@general-paid` hitting `openrouter/qwen/...:free` Venice 402 errors, while `@general-free` fell through `opencode/big-pickle` into `z-ai/glm-4.5-air:free` and `gpt-oss-20b:free`.
|
|
12
12
|
|
|
13
|
-
Conclusion:
|
|
13
|
+
Conclusion: keep the subagent split for tool permissions and prompting, but route OpenCode to `opencode-go/deepseek-v4-flash` across all JobForge tiers. It is the best current "affordable and reliable" default for applications.
|
|
14
14
|
|
|
15
15
|
## The three subagents
|
|
16
16
|
|
|
@@ -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/
|
|
22
|
-
| `@general-paid` | `
|
|
23
|
-
| `@glm-minimal` | `
|
|
21
|
+
| `@general-free` | `opencode-go/deepseek-v4-flash` | `minimal` | Geometra form fills, tracker TSV merges, scan dedup, OTP retrieval via Gmail, scripted pipeline steps |
|
|
22
|
+
| `@general-paid` | `opencode-go/deepseek-v4-flash` | `medium` | Offer evaluation narratives (Blocks A-F), cover letters, "Why X?" answers, STAR+R interview stories, LinkedIn outreach prose |
|
|
23
|
+
| `@glm-minimal` | `opencode-go/deepseek-v4-flash` | `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
|
|
|
@@ -64,25 +64,35 @@ Disables ~30 MCP tool schemas globally; each agent re-enables only what it needs
|
|
|
64
64
|
|
|
65
65
|
All three layers are designed to be edited — this is your search, your cost budget, your model preferences.
|
|
66
66
|
|
|
67
|
-
### Swap the
|
|
67
|
+
### Swap the quality model
|
|
68
68
|
|
|
69
|
-
The default `@general-paid` is `
|
|
69
|
+
The default `@general-paid` OpenCode model is `opencode-go/deepseek-v4-flash`. To use a stronger OpenCode route for quality writing, edit `models.yaml`:
|
|
70
70
|
|
|
71
71
|
```yaml
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
roles:
|
|
73
|
+
quality:
|
|
74
|
+
targets:
|
|
75
|
+
opencode:
|
|
76
|
+
provider: opencode
|
|
77
|
+
model: opencode-go/deepseek-v4-pro
|
|
76
78
|
```
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
Run `npm run build:config` if you are editing a harness checkout. In a consumer project, keep local overrides in `opencode.json` or replace a symlinked `.opencode/agents/<name>.md` with a real file.
|
|
79
81
|
|
|
80
|
-
### Swap the
|
|
82
|
+
### Swap the procedural route
|
|
81
83
|
|
|
82
|
-
The
|
|
83
|
-
|
|
84
|
-
default
|
|
85
|
-
|
|
84
|
+
The `@general-free` model is set in `models.yaml` via the `fast` role's
|
|
85
|
+
`targets.opencode` override. Change that if you want a different procedural
|
|
86
|
+
default:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
roles:
|
|
90
|
+
fast:
|
|
91
|
+
targets:
|
|
92
|
+
opencode:
|
|
93
|
+
provider: opencode
|
|
94
|
+
model: opencode-go/deepseek-v4-flash
|
|
95
|
+
```
|
|
86
96
|
|
|
87
97
|
### Add a custom agent
|
|
88
98
|
|
|
@@ -125,8 +135,8 @@ npx job-forge tokens --session <session-id>
|
|
|
125
135
|
```
|
|
126
136
|
|
|
127
137
|
Healthy pattern after this architecture lands:
|
|
128
|
-
- **
|
|
129
|
-
- If you opt
|
|
138
|
+
- **DeepSeek V4 Flash defaults** cover procedural, quality-sensitive, and extractor work on OpenCode
|
|
139
|
+
- If you opt into a stronger model, do it deliberately and only for the role that needs it
|
|
130
140
|
- Session titles prefixed `@general-free`, `@general-paid`, `@glm-minimal` appear in the list — confirms delegation actually happened
|
|
131
141
|
- `cache_read` >> `cache_creation` on parallel subagent runs within a 5-min window
|
|
132
142
|
|
|
@@ -134,67 +144,24 @@ Failure pattern to watch for:
|
|
|
134
144
|
- **All messages showing up under your primary model** (no `@general-*` titles) → orchestrator isn't delegating. Check the Pre-flight delegation rule in AGENTS.md is being followed; tighten wording if not.
|
|
135
145
|
- **High cache-creation with near-zero cache-read across parallel workers** → workers aren't firing within the 5-min cache TTL, or the shared prefix isn't byte-identical (see [batch/README.md](../batch/README.md) for the prompt-cache-friendly batch pattern).
|
|
136
146
|
|
|
137
|
-
##
|
|
138
|
-
|
|
139
|
-
A rate-limited or overloaded free-tier model would otherwise wedge the whole subagent flow — the delegated task errors and the orchestrator sits stuck. The harness ships with [`@razroo/opencode-model-fallback`](https://www.npmjs.com/package/@razroo/opencode-model-fallback) (added as a dependency in the scaffolder) to rotate agents through a configured `fallback_models` chain automatically.
|
|
140
|
-
|
|
141
|
-
Default chains ship upstream in each agent's YAML frontmatter (`node_modules/job-forge/.opencode/agents/*.md`, symlinked into your project's `.opencode/agents/`):
|
|
142
|
-
|
|
143
|
-
| Agent | Primary | Fallback chain (in order) |
|
|
144
|
-
|-------|---------|---------------------------|
|
|
145
|
-
| `@general-free` | `opencode/big-pickle` | `openrouter/z-ai/glm-4.5-air:free` → `openrouter/openai/gpt-oss-20b:free` → `openrouter/nvidia/nemotron-3-nano-30b-a3b:free` → `openrouter/qwen/qwen3-coder:free` |
|
|
146
|
-
| `@general-paid` | `openrouter/qwen/qwen3-next-80b-a3b-instruct:free` | `openrouter/openai/gpt-oss-120b:free` → `openrouter/nvidia/nemotron-3-super-120b-a12b:free` → `openrouter/z-ai/glm-4.5-air:free` → `openrouter/qwen/qwen3-coder:free` → `openrouter/google/gemma-4-31b-it:free` → `openrouter/meta-llama/llama-3.3-70b-instruct:free` |
|
|
147
|
-
| `@glm-minimal` | `openrouter/openai/gpt-oss-20b:free` | `openrouter/google/gemma-4-26b-a4b-it:free` → `openrouter/nvidia/nemotron-nano-9b-v2:free` → `openrouter/google/gemma-4-31b-it:free` → `openrouter/z-ai/glm-4.5-air:free` |
|
|
148
|
-
|
|
149
|
-
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.
|
|
150
|
-
|
|
151
|
-
Consumers **do not need to configure anything** to get these defaults: the subagent chains arrive via the symlinked agent MD files, and the harness ships `.opencode/opencode-model-fallback.json` for the main orchestrator / any agent without its own list. That JSON is **generated by `@razroo/iso-harness`** from the top-level `opencodeModelFallback` object in the harness's `iso/config.json` (same `iso build` pass as `opencode.json`), so it stays in sync with published releases — not a hand-edited file in git. `@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.
|
|
152
|
-
|
|
153
|
-
**When fallback fires:** the plugin pattern-matches rate-limit / 5xx / quota / "overloaded" / insufficient-balance style errors (including Venice / Diem copy — see `retryable_error_patterns` in the harness source). Failed models enter a 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.
|
|
154
|
-
|
|
155
|
-
**Orchestrator policy (all harnesses):** if an upgraded `@general-paid` apply still fails after model fallback, follow **[D3f]** in the shared instructions (`AGENTS.md` / `CLAUDE.md` / Cursor rules / Codex `AGENTS.md`) — re-dispatch the same URL once on `@general-free` before marking FAILED.
|
|
156
|
-
|
|
157
|
-
### Overriding an upstream chain
|
|
158
|
-
|
|
159
|
-
Add an `agent.<name>.fallback_models` block to your project's `opencode.json`. Top-level entries win over upstream frontmatter:
|
|
160
|
-
|
|
161
|
-
```json
|
|
162
|
-
{
|
|
163
|
-
"agent": {
|
|
164
|
-
"general-free": {
|
|
165
|
-
"fallback_models": ["my/preferred-free", "my/preferred-paid"]
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Global fallback chain (agents without their own)
|
|
172
|
-
|
|
173
|
-
Source of truth: **`iso/config.json` → `opencodeModelFallback`** (iso-harness writes `.opencode/opencode-model-fallback.json` on `npm run build:config` / `prepack`). Applies to the orchestrator and any agent whose `fallback_models` is empty. Example shape:
|
|
174
|
-
|
|
175
|
-
```json
|
|
176
|
-
{
|
|
177
|
-
"cooldown_seconds": 60,
|
|
178
|
-
"timeout_seconds": 30,
|
|
179
|
-
"notify_on_fallback": true,
|
|
180
|
-
"fallback_models": [
|
|
181
|
-
"openrouter/openai/gpt-oss-120b:free",
|
|
182
|
-
"openrouter/z-ai/glm-4.5-air:free"
|
|
183
|
-
],
|
|
184
|
-
"retryable_error_patterns": ["(?i)venice.*insufficient"]
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
`retryable_error_patterns` extends the plugin's built-in matchers — use it for provider-specific strings (Venice Diem balance, etc.) that do not match the stock regexes.
|
|
147
|
+
## Fallback policy
|
|
189
148
|
|
|
190
|
-
|
|
149
|
+
JobForge no longer ships automatic free-model fallback for OpenCode. The
|
|
150
|
+
previous free fallback chain solved some transient model outages, but real
|
|
151
|
+
application traces showed it could also freeze runs upstream or route into
|
|
152
|
+
provider balance failures. The default is now simpler: each OpenCode role uses
|
|
153
|
+
`opencode-go/deepseek-v4-flash`, and errors surface directly in telemetry.
|
|
191
154
|
|
|
192
|
-
|
|
155
|
+
Use `npm run telemetry:status` or `npm run telemetry:show -- <session>` to
|
|
156
|
+
inspect provider errors, child outcomes, and pending TSVs after a run. If you
|
|
157
|
+
want a local fallback chain anyway, add it explicitly in your own
|
|
158
|
+
`opencode.json` or agent frontmatter so the cost/reliability tradeoff is
|
|
159
|
+
visible in your project rather than hidden in the harness defaults.
|
|
193
160
|
|
|
194
161
|
## Known limitations
|
|
195
162
|
|
|
196
163
|
- **opencode's 5-minute cache TTL is hardcoded.** The 1-hour cache (Anthropic beta, `extended-cache-ttl-2025-04-11`) is not plumbed through opencode as of 2026-04-15. Long batch runs (>5 min between workers) will miss cache every cycle. Upstream fix would be 2 lines in `packages/opencode/src/provider/`.
|
|
197
|
-
- **`instructions` is top-level, not per-agent.** Files listed in `opencode.json:instructions` load for every agent
|
|
164
|
+
- **`instructions` is top-level, not per-agent.** Files listed in `opencode.json:instructions` load for every agent. This is fine for `cv.md` and `_shared.md` (they're small and useful everywhere), but means you can't hide heavy context from lower-cost agents via instructions — use per-agent `prompt:` files for that.
|
|
198
165
|
- **`reasoningEffort` support varies by provider.** Anthropic accepts `thinking: { type: "disabled" }`; opencode-labs models may need the `variant` pattern. See the `reasoningEffort` values in the opencode docs.
|
|
199
166
|
|
|
200
167
|
## See also
|
package/docs/README.md
CHANGED
|
@@ -20,7 +20,7 @@ See [SETUP.md](SETUP.md) for both paths.
|
|
|
20
20
|
| [SETUP.md](SETUP.md) | Prerequisites, both install paths, profile and CV, portals, `npx job-forge verify`, optional Go dashboard, token usage tracking, [troubleshooting](SETUP.md#troubleshooting) |
|
|
21
21
|
| [ARCHITECTURE.md](ARCHITECTURE.md) | [Package architecture](ARCHITECTURE.md#package-architecture-v200) (consumer vs harness split), modes under `modes/`, single-offer flow, batch runner, tracker and scripts, [contributor touchpoints](ARCHITECTURE.md#contributing-touchpoints) |
|
|
22
22
|
| [CUSTOMIZATION.md](CUSTOMIZATION.md) | Profile, archetypes in `_shared.md`, `portals.yml`, CV template, canonical states, optional story bank and opencode hooks. Also: how to customize a symlinked mode file locally |
|
|
23
|
-
| [MODEL-ROUTING.md](MODEL-ROUTING.md) | Why the harness uses three cost-tiered subagents (`@general-free`, `@general-paid`, `@glm-minimal`), how routing is enforced (permission + tool-surface trim + reasoningEffort), how to swap models or add agents
|
|
23
|
+
| [MODEL-ROUTING.md](MODEL-ROUTING.md) | Why the harness uses three cost-tiered subagents (`@general-free`, `@general-paid`, `@glm-minimal`), how routing is enforced (permission + tool-surface trim + reasoningEffort), and how to swap models or add agents |
|
|
24
24
|
| [examples/README.md](../examples/README.md) | Fictional CV samples (per-role markdown), optional digest, fictional [`sample-jd.md`](../examples/sample-jd.md) for `local:jds/…` shape, and sample report — starting point for new `cv.md`, JD-on-disk layout, or contributor archetypes (cloud infrastructure, agent platform) |
|
|
25
25
|
| [batch/README.md](../batch/README.md) | Batch TSV format, `batch-runner.sh`, `tracker-additions/` merge flow with `npx job-forge merge` |
|
|
26
26
|
| [jds/README.md](../jds/README.md) | Markdown JDs on disk; `local:jds/{file}.md` lines in `data/pipeline.md` |
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Procedural worker on
|
|
2
|
+
description: Procedural worker on the low-cost DeepSeek V4 Flash OpenCode route. 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
|
role: fast
|
|
4
4
|
targets:
|
|
5
|
-
# No inline model:
|
|
6
|
-
#
|
|
5
|
+
# No inline model: JobForge's models.yaml maps role "fast" to each
|
|
6
|
+
# harness's cheapest reliable model. On OpenCode that is pinned to
|
|
7
|
+
# opencode-go/deepseek-v4-flash. Claude Code reads
|
|
7
8
|
# .claude/iso-route.resolved.json; OpenCode reads opencode.json's
|
|
8
9
|
# agent.fast.model (iso-harness 0.6.0+).
|
|
9
10
|
opencode:
|
|
10
11
|
mode: subagent
|
|
11
12
|
temperature: 0.1
|
|
12
13
|
reasoningEffort: minimal
|
|
13
|
-
# Primary comes from models.yaml: opencode/big-pickle on OpenCode.
|
|
14
|
-
# Fallback chain stays free-only and intentionally excludes
|
|
15
|
-
# openrouter/minimax/minimax-m2.5:free because recent traces showed
|
|
16
|
-
# repeated read({ path|file_path }) schema drift on that route.
|
|
17
|
-
fallback_models:
|
|
18
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
19
|
-
- openrouter/openai/gpt-oss-20b:free
|
|
20
|
-
- openrouter/nvidia/nemotron-3-nano-30b-a3b:free
|
|
21
|
-
- openrouter/qwen/qwen3-coder:free
|
|
22
14
|
tools:
|
|
23
15
|
geometra_connect: true
|
|
24
16
|
geometra_page_model: true
|
|
@@ -34,7 +26,7 @@ targets:
|
|
|
34
26
|
task: false
|
|
35
27
|
---
|
|
36
28
|
|
|
37
|
-
You are the @general-free subagent. You run on
|
|
29
|
+
You are the @general-free subagent. You run on JobForge's low-cost procedural 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.
|
|
38
30
|
|
|
39
31
|
## Run This Pre-Flight First Every Time
|
|
40
32
|
|
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Quality-sensitive worker on the
|
|
2
|
+
description: Quality-sensitive worker on the low-cost DeepSeek V4 Flash OpenCode route 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: JobForge's models.yaml maps role "quality" to
|
|
6
|
-
#
|
|
7
|
-
# quality-tier defaults from the standard preset. Claude Code reads
|
|
5
|
+
# No inline model: JobForge's models.yaml maps role "quality" to
|
|
6
|
+
# opencode-go/deepseek-v4-flash on OpenCode, while Claude/Codex keep
|
|
7
|
+
# their quality-tier defaults from the standard preset. Claude Code reads
|
|
8
8
|
# .claude/iso-route.resolved.json; OpenCode reads opencode.json's
|
|
9
9
|
# agent.quality.model (iso-harness 0.6.0+).
|
|
10
10
|
opencode:
|
|
11
11
|
mode: subagent
|
|
12
12
|
temperature: 0.3
|
|
13
13
|
reasoningEffort: medium
|
|
14
|
-
# Primary (qwen/qwen3-next-80b-a3b-instruct:free) resolves from the
|
|
15
|
-
# openrouter-free preset. First fallbacks intentionally avoid another
|
|
16
|
-
# immediate hop through the same Venice/Qwen pool when OpenRouter
|
|
17
|
-
# returns "[Venice] insufficient …" — gpt-oss-120b + nemotron are
|
|
18
|
-
# usually different backends. Remaining picks stay free-only.
|
|
19
|
-
fallback_models:
|
|
20
|
-
- openrouter/openai/gpt-oss-120b:free
|
|
21
|
-
- openrouter/nvidia/nemotron-3-super-120b-a12b:free
|
|
22
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
23
|
-
- openrouter/qwen/qwen3-coder:free
|
|
24
|
-
- openrouter/google/gemma-4-31b-it:free
|
|
25
|
-
- openrouter/meta-llama/llama-3.3-70b-instruct:free
|
|
26
14
|
tools:
|
|
27
15
|
geometra_connect: true
|
|
28
16
|
geometra_page_model: true
|
|
@@ -40,10 +28,10 @@ targets:
|
|
|
40
28
|
|
|
41
29
|
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.
|
|
42
30
|
|
|
43
|
-
On OpenCode, this agent
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
were given.
|
|
31
|
+
On OpenCode, this agent defaults to DeepSeek V4 Flash so application work
|
|
32
|
+
does not fall back into overloaded free OpenRouter pools. On other harnesses,
|
|
33
|
+
the same role may still resolve to a premium model. Your job is still the
|
|
34
|
+
same: produce the best final writing you can from the context you were given.
|
|
47
35
|
|
|
48
36
|
## Do These Tasks
|
|
49
37
|
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Narrow-scope extractor on
|
|
2
|
+
description: Narrow-scope extractor on the low-cost DeepSeek V4 Flash OpenCode route. 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
|
role: minimal
|
|
4
4
|
targets:
|
|
5
|
-
# No inline model:
|
|
6
|
-
#
|
|
5
|
+
# No inline model: JobForge's models.yaml maps role "minimal" to each
|
|
6
|
+
# harness's smallest credible model. On OpenCode that is pinned to
|
|
7
|
+
# opencode-go/deepseek-v4-flash. Claude Code reads
|
|
7
8
|
# .claude/iso-route.resolved.json; OpenCode reads opencode.json's
|
|
8
9
|
# agent.minimal.model (iso-harness 0.6.0+).
|
|
9
10
|
opencode:
|
|
10
11
|
mode: subagent
|
|
11
12
|
temperature: 0
|
|
12
13
|
reasoningEffort: none
|
|
13
|
-
# Primary (openai/gpt-oss-20b:free) resolves from openrouter-free
|
|
14
|
-
# preset. Fallback chain sticks to small dense models with reliable
|
|
15
|
-
# structured-output behavior — no creative generation upstream.
|
|
16
|
-
fallback_models:
|
|
17
|
-
- openrouter/google/gemma-4-26b-a4b-it:free
|
|
18
|
-
- openrouter/nvidia/nemotron-nano-9b-v2:free
|
|
19
|
-
- openrouter/google/gemma-4-31b-it:free
|
|
20
|
-
- openrouter/z-ai/glm-4.5-air:free
|
|
21
14
|
tools:
|
|
22
15
|
geometra_*: false
|
|
23
16
|
gmail_*: false
|
package/iso/config.json
CHANGED
|
@@ -1,49 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"opencodeModelFallback": {
|
|
3
|
-
"cooldown_seconds": 60,
|
|
4
|
-
"timeout_seconds": 30,
|
|
5
|
-
"notify_on_fallback": true,
|
|
6
|
-
"fallback_models": [
|
|
7
|
-
"openrouter/openai/gpt-oss-120b:free",
|
|
8
|
-
"openrouter/z-ai/glm-4.5-air:free",
|
|
9
|
-
"openrouter/nvidia/nemotron-3-super-120b-a12b:free",
|
|
10
|
-
"openrouter/qwen/qwen3-next-80b-a3b-instruct:free"
|
|
11
|
-
],
|
|
12
|
-
"retryable_error_patterns": [
|
|
13
|
-
"\\bvenice\\b",
|
|
14
|
-
"insufficient\\s+usd",
|
|
15
|
-
"insufficient\\s+.*\\s+diem",
|
|
16
|
-
"diem\\s+balance",
|
|
17
|
-
"add\\s+credits",
|
|
18
|
-
"chutes",
|
|
19
|
-
"insufficient\\s+(?:credits?|funds?|balance)",
|
|
20
|
-
"credit.*balance.*too.*low",
|
|
21
|
-
"(?:temporarily\\s+)?unavailable|overloaded|try\\s+again"
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
2
|
"targets": {
|
|
25
3
|
"opencode": {
|
|
26
|
-
"plugin": ["@razroo/opencode-model-fallback"],
|
|
27
4
|
"instructions": ["templates/states.yml"],
|
|
28
|
-
"small_model": "
|
|
29
|
-
"provider": {
|
|
30
|
-
"openrouter": {
|
|
31
|
-
"models": {
|
|
32
|
-
"qwen/qwen3-coder:free": {},
|
|
33
|
-
"z-ai/glm-4.5-air:free": {},
|
|
34
|
-
"qwen/qwen3-next-80b-a3b-instruct:free": {},
|
|
35
|
-
"openai/gpt-oss-20b:free": {},
|
|
36
|
-
"openai/gpt-oss-120b:free": {},
|
|
37
|
-
"minimax/minimax-m2.5:free": {},
|
|
38
|
-
"nvidia/nemotron-3-super-120b-a12b:free": {},
|
|
39
|
-
"nvidia/nemotron-3-nano-30b-a3b:free": {},
|
|
40
|
-
"nvidia/nemotron-nano-9b-v2:free": {},
|
|
41
|
-
"google/gemma-4-26b-a4b-it:free": {},
|
|
42
|
-
"google/gemma-4-31b-it:free": {},
|
|
43
|
-
"meta-llama/llama-3.3-70b-instruct:free": {}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
5
|
+
"small_model": "opencode-go/deepseek-v4-flash"
|
|
47
6
|
}
|
|
48
7
|
}
|
|
49
8
|
}
|
package/iso/instructions.md
CHANGED
|
@@ -5,7 +5,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
5
5
|
## Hard limits
|
|
6
6
|
|
|
7
7
|
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. A round is not complete until both subagents return a final outcome (`APPLIED`, `APPLY FAILED`, `SKIP`, `Discarded`, or a written TSV path). A `task` tool result that only gives a session id / title is a launch acknowledgement, not completion. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
8
|
-
why:
|
|
8
|
+
why: each subagent requires post-cleanup and racing more than 2 reliably loses at least one result. On 2026-04-25 the orchestrator launched round 2 while round 1 had only returned task ids, leaving four application subagents in flight and losing two provider recoveries
|
|
9
9
|
|
|
10
10
|
- [H2] Max 1 application per company+role. Before every `apply` dispatch, grep all four sources for the URL and for `company+role`: `data/pipeline.md`, all `data/applications/*.md` day files, `batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`. If any source shows APPLIED / Applied, skip the dispatch.
|
|
11
11
|
why: 2026-04 same-day batch collision — when two batches target the same role, `npx job-forge merge` updates the existing day-file row rather than appending, so grepping day files alone misses earlier-batch applies; merged/*.tsv is the only place the breadcrumb remains
|
|
@@ -37,7 +37,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
37
37
|
why: iso-trace showed 0.25% Agent calls across 5174 turns under a prior over-broad "delegate before 2nd tool call" rule — the rule was ignored in practice; narrowing matches the original cache-bust incident
|
|
38
38
|
|
|
39
39
|
- [D2] Route subagent work by cost tier. `@general-free`: procedural — form-fill, TSV merge, verify, OTP retrieval, portal scan metadata extraction, one-shot structured-field transforms. `@general-paid`: quality-sensitive — offer evaluation narrative Blocks A-F, cover letters, "Why X?" answers, STAR interview stories, LinkedIn outreach. `@glm-minimal`: narrow ≤5K-input one-shot extract/classify jobs that do not need context.
|
|
40
|
-
why:
|
|
40
|
+
why: OpenCode routes all JobForge tiers through DeepSeek V4 Flash by default now; recent traces showed free OpenRouter fallbacks freezing or hitting provider balance errors during applications
|
|
41
41
|
|
|
42
42
|
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
43
43
|
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
package/models.yaml
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
# JobForge model policy.
|
|
2
2
|
#
|
|
3
|
-
# Extends @razroo/iso-route's bundled "
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# node_modules/@razroo/iso-route/presets/openrouter-free.yaml; run
|
|
8
|
-
# `npx iso-route plan models.yaml` to see the resolved policy.
|
|
3
|
+
# Extends @razroo/iso-route's bundled "standard" preset, then pins every
|
|
4
|
+
# OpenCode route to DeepSeek V4 Flash. Recent traces showed free OpenRouter
|
|
5
|
+
# routes freezing or falling through Venice balance errors, so JobForge's
|
|
6
|
+
# OpenCode default is now "best affordable paid" rather than "free".
|
|
9
7
|
#
|
|
10
8
|
# JobForge's subagents bind to preset roles via the `role:` field in
|
|
11
9
|
# iso/agents/<slug>.md:
|
|
12
|
-
# @general-free → role: fast (Haiku /
|
|
13
|
-
# @general-paid → role: quality (Opus 4.7 /
|
|
14
|
-
# @glm-minimal → role: minimal (Haiku /
|
|
10
|
+
# @general-free → role: fast (Haiku / DeepSeek V4 Flash / gpt-5.4-mini)
|
|
11
|
+
# @general-paid → role: quality (Opus 4.7 / DeepSeek V4 Flash / gpt-5.4)
|
|
12
|
+
# @glm-minimal → role: minimal (Haiku / DeepSeek V4 Flash / gpt-5.4-nano)
|
|
15
13
|
#
|
|
16
14
|
# Override anything by adding fields here. For example, to pin Opus on
|
|
17
15
|
# Claude Code for the @general-paid (quality) role:
|
|
@@ -29,11 +27,27 @@
|
|
|
29
27
|
# provider: openai
|
|
30
28
|
# model: gpt-5.4
|
|
31
29
|
|
|
32
|
-
extends:
|
|
30
|
+
extends: standard
|
|
31
|
+
|
|
32
|
+
default:
|
|
33
|
+
targets:
|
|
34
|
+
opencode:
|
|
35
|
+
provider: opencode
|
|
36
|
+
model: opencode-go/deepseek-v4-flash
|
|
33
37
|
|
|
34
38
|
roles:
|
|
35
39
|
fast:
|
|
36
40
|
targets:
|
|
37
41
|
opencode:
|
|
38
42
|
provider: opencode
|
|
39
|
-
model: opencode/
|
|
43
|
+
model: opencode-go/deepseek-v4-flash
|
|
44
|
+
quality:
|
|
45
|
+
targets:
|
|
46
|
+
opencode:
|
|
47
|
+
provider: opencode
|
|
48
|
+
model: opencode-go/deepseek-v4-flash
|
|
49
|
+
minimal:
|
|
50
|
+
targets:
|
|
51
|
+
opencode:
|
|
52
|
+
provider: opencode
|
|
53
|
+
model: opencode-go/deepseek-v4-flash
|
package/modes/apply.md
CHANGED
|
@@ -17,7 +17,7 @@ Live application assistant. Reads the active application form in Chrome (via Geo
|
|
|
17
17
|
why: prior aborted subagents leave Chromium sessions stuck in the pool; next `geometra_connect` fails with "Not connected" (see root `[H3]`)
|
|
18
18
|
|
|
19
19
|
- [H5] Max 2 parallel `task` dispatches per round. For N jobs, run `ceil(N/2)` sequential rounds of 2. Never emit 3+ dispatches in a single message. Do not start the next round until both current-round subagents return final outcomes (`APPLIED`, `APPLY FAILED`, `SKIP`, `Discarded`, or a written TSV path); task/session ids are only launch receipts.
|
|
20
|
-
why:
|
|
20
|
+
why: subagent post-cleanup cost and portal state make racing more than 2 unreliable (see root `[H1]`). A 2026-04-25 OpenCode trace launched round 2 while round 1 was still running, then lost two provider recoveries
|
|
21
21
|
|
|
22
22
|
## Defaults
|
|
23
23
|
|
|
@@ -46,10 +46,10 @@ Live application assistant. Reads the active application form in Chrome (via Geo
|
|
|
46
46
|
why: class-B Ashby / Cloudflare-fronted portals need a residential outbound IP; the fix is wired in Geometra MCP v1.59.0 but the orchestrator owns the config pipe. See "BYO Residential Proxy" in modes/reference-portals.md.
|
|
47
47
|
|
|
48
48
|
- [D8] Upgrade application routing to `@general-paid` when the offer score is ≥ 4.0/5, the user flags "top-tier", "dream job", or "high-stakes", or the candidate is late-stage/post-screen.
|
|
49
|
-
why:
|
|
49
|
+
why: high-stakes applications need the quality-sensitive prompt and medium reasoning budget even though OpenCode now routes both application tiers through DeepSeek V4 Flash by default
|
|
50
50
|
|
|
51
|
-
- [D9] If
|
|
52
|
-
why: OpenCode
|
|
51
|
+
- [D9] If a subagent fails with provider-side errors, do not auto-downgrade or re-dispatch the same URL. Report the provider failure, leave any TSV untouched unless there is a confirmed outcome, and inspect telemetry before retrying.
|
|
52
|
+
why: OpenCode now pins all JobForge application tiers to DeepSeek V4 Flash; switching `@general-paid` → `@general-free` changes the prompt/tool budget but not the provider route, so automatic duplicate dispatches add risk without fixing provider availability
|
|
53
53
|
|
|
54
54
|
## Procedure
|
|
55
55
|
|
|
@@ -65,7 +65,7 @@ Live application assistant. Reads the active application form in Chrome (via Geo
|
|
|
65
65
|
10. Generate answers from Block B + Block F + Section G + JD.
|
|
66
66
|
11. Submit as ONE `run_actions` call [H1] using labels [D6] with `imeFriendly: true` [D4].
|
|
67
67
|
12. On session error, run the 4-step recovery; only one retry [H2].
|
|
68
|
-
13. On
|
|
68
|
+
13. On provider failure, stop and inspect telemetry before any retry [D9].
|
|
69
69
|
14. On OTP prompt, fetch the code from Gmail via `gmail_get_message`.
|
|
70
70
|
15. Submit the OTP with `geometra_fill_otp` and click Submit.
|
|
71
71
|
16. Write outcome as `batch/tracker-additions/*.tsv` [H3].
|
|
@@ -98,7 +98,7 @@ Or, on failure:
|
|
|
98
98
|
APPLY FAILED AFTER RECOVERY: <url>
|
|
99
99
|
Error 1: <first error>
|
|
100
100
|
Error 2: <post-recovery error>
|
|
101
|
-
Recommend:
|
|
101
|
+
Recommend: inspect telemetry before retrying this URL
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
---
|
|
@@ -359,10 +359,10 @@ Call 4: geometra_run_actions({
|
|
|
359
359
|
APPLY FAILED AFTER RECOVERY: <URL>
|
|
360
360
|
Error 1: <first error message>
|
|
361
361
|
Error 2: <error after recovery>
|
|
362
|
-
Recommend:
|
|
362
|
+
Recommend: inspect telemetry before retrying this URL
|
|
363
363
|
```
|
|
364
364
|
|
|
365
|
-
Do NOT try a third time. Do NOT try a different approach. The orchestrator will decide whether to
|
|
365
|
+
Do NOT try a third time. Do NOT try a different approach. The orchestrator will decide whether to retry after inspecting telemetry.
|
|
366
366
|
|
|
367
367
|
### Skip schema re-fetches mid-flow (Rule D)
|
|
368
368
|
|
package/opencode.json
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://opencode.ai/config.json",
|
|
3
|
-
"model": "
|
|
3
|
+
"model": "opencode-go/deepseek-v4-flash",
|
|
4
4
|
"agent": {
|
|
5
5
|
"fast": {
|
|
6
|
-
"model": "opencode/
|
|
6
|
+
"model": "opencode-go/deepseek-v4-flash"
|
|
7
7
|
},
|
|
8
8
|
"quality": {
|
|
9
|
-
"model": "
|
|
9
|
+
"model": "opencode-go/deepseek-v4-flash"
|
|
10
10
|
},
|
|
11
11
|
"minimal": {
|
|
12
|
-
"model": "
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"provider": {
|
|
16
|
-
"openrouter": {
|
|
17
|
-
"models": {
|
|
18
|
-
"qwen/qwen3-coder:free": {},
|
|
19
|
-
"z-ai/glm-4.5-air:free": {},
|
|
20
|
-
"qwen/qwen3-next-80b-a3b-instruct:free": {},
|
|
21
|
-
"openai/gpt-oss-20b:free": {},
|
|
22
|
-
"openai/gpt-oss-120b:free": {},
|
|
23
|
-
"minimax/minimax-m2.5:free": {},
|
|
24
|
-
"nvidia/nemotron-3-super-120b-a12b:free": {},
|
|
25
|
-
"nvidia/nemotron-3-nano-30b-a3b:free": {},
|
|
26
|
-
"nvidia/nemotron-nano-9b-v2:free": {},
|
|
27
|
-
"google/gemma-4-26b-a4b-it:free": {},
|
|
28
|
-
"google/gemma-4-31b-it:free": {},
|
|
29
|
-
"meta-llama/llama-3.3-70b-instruct:free": {}
|
|
30
|
-
}
|
|
12
|
+
"model": "opencode-go/deepseek-v4-flash"
|
|
31
13
|
}
|
|
32
14
|
},
|
|
33
15
|
"mcp": {
|
|
@@ -66,11 +48,8 @@
|
|
|
66
48
|
}
|
|
67
49
|
}
|
|
68
50
|
},
|
|
69
|
-
"plugin": [
|
|
70
|
-
"@razroo/opencode-model-fallback"
|
|
71
|
-
],
|
|
72
51
|
"instructions": [
|
|
73
52
|
"templates/states.yml"
|
|
74
53
|
],
|
|
75
|
-
"small_model": "
|
|
54
|
+
"small_model": "opencode-go/deepseek-v4-flash"
|
|
76
55
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "job-forge",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.12",
|
|
4
4
|
"description": "AI-powered job search pipeline built on opencode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -97,7 +97,6 @@
|
|
|
97
97
|
"@razroo/iso": "^0.2.5",
|
|
98
98
|
"@razroo/iso-eval": "^0.4.0",
|
|
99
99
|
"@razroo/iso-harness": "^0.6.1",
|
|
100
|
-
"@razroo/iso-route": "^0.5.3"
|
|
101
|
-
"@razroo/opencode-model-fallback": "^0.3.1"
|
|
100
|
+
"@razroo/iso-route": "^0.5.3"
|
|
102
101
|
}
|
|
103
102
|
}
|
|
@@ -21,9 +21,9 @@ const checks = [
|
|
|
21
21
|
["H7 distrusts subagent prose", () => every(files.instructions, ["must originate from a file", "not from prior subagent prose"])],
|
|
22
22
|
["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"])],
|
|
23
23
|
["apply mode owns high-stakes upgrade", () => every(files.apply, ["[D8]", "@general-paid", "4.0/5", "high-stakes"])],
|
|
24
|
-
["apply mode
|
|
25
|
-
["models policy
|
|
26
|
-
["OpenCode fallback plugin is configured", () => every(files.config, ["opencodeModelFallback", "@razroo/opencode-model-fallback"])],
|
|
24
|
+
["apply mode blocks provider auto-downgrade", () => every(files.apply, ["[D9]", "do not auto-downgrade", "inspect telemetry before retrying"])],
|
|
25
|
+
["models policy pins OpenCode to DeepSeek V4 Flash", () => /extends:\s*standard/.test(files.models) && count(files.models, "opencode-go/deepseek-v4-flash") >= 4],
|
|
26
|
+
["OpenCode fallback plugin is not configured", () => !every(files.config, ["opencodeModelFallback", "@razroo/opencode-model-fallback"])],
|
|
27
27
|
];
|
|
28
28
|
|
|
29
29
|
const failures = checks
|
|
@@ -41,3 +41,7 @@ console.log(`JobForge iso smoke passed (${checks.length} checks).`);
|
|
|
41
41
|
function every(source, needles) {
|
|
42
42
|
return needles.every((needle) => source.includes(needle));
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
function count(source, needle) {
|
|
46
|
+
return source.split(needle).length - 1;
|
|
47
|
+
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cooldown_seconds": 60,
|
|
3
|
-
"timeout_seconds": 30,
|
|
4
|
-
"notify_on_fallback": true,
|
|
5
|
-
"fallback_models": [
|
|
6
|
-
"openrouter/openai/gpt-oss-120b:free",
|
|
7
|
-
"openrouter/z-ai/glm-4.5-air:free",
|
|
8
|
-
"openrouter/nvidia/nemotron-3-super-120b-a12b:free",
|
|
9
|
-
"openrouter/qwen/qwen3-next-80b-a3b-instruct:free"
|
|
10
|
-
],
|
|
11
|
-
"retryable_error_patterns": [
|
|
12
|
-
"\\bvenice\\b",
|
|
13
|
-
"insufficient\\s+usd",
|
|
14
|
-
"insufficient\\s+.*\\s+diem",
|
|
15
|
-
"diem\\s+balance",
|
|
16
|
-
"add\\s+credits",
|
|
17
|
-
"chutes",
|
|
18
|
-
"insufficient\\s+(?:credits?|funds?|balance)",
|
|
19
|
-
"credit.*balance.*too.*low",
|
|
20
|
-
"(?:temporarily\\s+)?unavailable|overloaded|try\\s+again"
|
|
21
|
-
]
|
|
22
|
-
}
|