job-forge 2.14.10 → 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 +14 -48
- package/bin/job-forge.mjs +29 -0
- package/bin/sync.mjs +0 -1
- package/docs/ARCHITECTURE.md +3 -2
- package/docs/CUSTOMIZATION.md +13 -0
- package/docs/MODEL-ROUTING.md +43 -76
- package/docs/README.md +1 -1
- package/docs/SETUP.md +3 -0
- 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 +6 -3
- package/scripts/check-iso-smoke.mjs +7 -3
- package/scripts/telemetry.mjs +643 -0
- 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
|
@@ -113,22 +113,18 @@ const consumerPkg = {
|
|
|
113
113
|
'trace:list': 'job-forge trace:list',
|
|
114
114
|
'trace:stats': 'job-forge trace:stats',
|
|
115
115
|
'trace:show': 'job-forge trace:show',
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
'telemetry:list': 'job-forge telemetry:list',
|
|
117
|
+
'telemetry:status': 'job-forge telemetry:status',
|
|
118
|
+
'telemetry:show': 'job-forge telemetry:show',
|
|
119
|
+
'telemetry:watch': 'job-forge telemetry:watch',
|
|
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)"',
|
|
121
125
|
},
|
|
122
126
|
dependencies: {
|
|
123
127
|
'job-forge': '^2.0.0',
|
|
124
|
-
// Model-fallback plugin: rotates agents through their fallback_models
|
|
125
|
-
// chain on rate-limit / 5xx errors so a rate-limited free-tier model
|
|
126
|
-
// doesn't wedge the whole flow. The chains live upstream in each
|
|
127
|
-
// agent's MD frontmatter (`.opencode/agents/*.md` in the harness);
|
|
128
|
-
// consumers can override individual chains by adding their own
|
|
129
|
-
// agent.<name>.fallback_models block to opencode.json. Requires
|
|
130
|
-
// 0.3.1+ for the frontmatter-merge path.
|
|
131
|
-
'@razroo/opencode-model-fallback': '^0.3.1',
|
|
132
128
|
},
|
|
133
129
|
engines: { node: '>=18' },
|
|
134
130
|
};
|
|
@@ -138,16 +134,11 @@ write('package.json', JSON.stringify(consumerPkg, null, 2) + '\n');
|
|
|
138
134
|
|
|
139
135
|
const opencodeCfg = {
|
|
140
136
|
$schema: 'https://opencode.ai/config.json',
|
|
141
|
-
// Keep the top-level orchestrator on
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
model: '
|
|
145
|
-
small_model: '
|
|
146
|
-
// Model-fallback plugin: on rate-limit / 5xx / known provider errors,
|
|
147
|
-
// rotates the agent's model to the next entry in its fallback_models
|
|
148
|
-
// chain (see `agent` below) and replays the request. Without this, a
|
|
149
|
-
// rate-limited free-tier model wedges the whole subagent flow.
|
|
150
|
-
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',
|
|
151
142
|
// Files listed here load into every session's cached prefix, so they're
|
|
152
143
|
// cached once (on Anthropic) instead of Read-as-tool-call on every session.
|
|
153
144
|
// AGENTS.harness.md → symlink to node_modules/job-forge/AGENTS.md (harness rules)
|
|
@@ -178,31 +169,6 @@ const opencodeCfg = {
|
|
|
178
169
|
environment: { DISABLE_HTTP: 'true' },
|
|
179
170
|
},
|
|
180
171
|
},
|
|
181
|
-
// Register the exact OpenRouter free models the harness uses so they're
|
|
182
|
-
// selectable even if they are not in OpenCode's built-in preloaded set.
|
|
183
|
-
// This list is a superset: role primaries, per-agent fallback chains,
|
|
184
|
-
// and the orchestrator fallback chain.
|
|
185
|
-
provider: {
|
|
186
|
-
openrouter: {
|
|
187
|
-
models: {
|
|
188
|
-
// Orchestrator + agentic coding (role default)
|
|
189
|
-
'qwen/qwen3-coder:free': {},
|
|
190
|
-
// Role primaries
|
|
191
|
-
'z-ai/glm-4.5-air:free': {}, // fast
|
|
192
|
-
'qwen/qwen3-next-80b-a3b-instruct:free': {}, // quality
|
|
193
|
-
'openai/gpt-oss-20b:free': {}, // minimal
|
|
194
|
-
// Common fallbacks
|
|
195
|
-
'openai/gpt-oss-120b:free': {},
|
|
196
|
-
'minimax/minimax-m2.5:free': {},
|
|
197
|
-
'nvidia/nemotron-3-super-120b-a12b:free': {},
|
|
198
|
-
'nvidia/nemotron-3-nano-30b-a3b:free': {},
|
|
199
|
-
'nvidia/nemotron-nano-9b-v2:free': {},
|
|
200
|
-
'google/gemma-4-26b-a4b-it:free': {},
|
|
201
|
-
'google/gemma-4-31b-it:free': {},
|
|
202
|
-
'meta-llama/llama-3.3-70b-instruct:free': {},
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
172
|
// Restrict the primary orchestrator to dispatching only the three harness
|
|
207
173
|
// subagents. Prevents accidental self-calls or unregistered agents.
|
|
208
174
|
// Override locally in opencode.json if you add project-specific agents.
|
package/bin/job-forge.mjs
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* sync-check Run cv-sync-check.mjs
|
|
19
19
|
* tokens Run scripts/token-usage-report.mjs
|
|
20
20
|
* trace:* Inspect local agent transcripts via iso-trace
|
|
21
|
+
* telemetry:* Summarize JobForge pipeline status from traces + tracker files
|
|
21
22
|
* sync Re-run the harness symlink sync (bin/sync.mjs)
|
|
22
23
|
* help, --help Show this message
|
|
23
24
|
*/
|
|
@@ -60,6 +61,13 @@ const traceAliases = {
|
|
|
60
61
|
'trace:show': 'show',
|
|
61
62
|
};
|
|
62
63
|
|
|
64
|
+
const telemetryAliases = {
|
|
65
|
+
'telemetry:list': 'list',
|
|
66
|
+
'telemetry:status': 'status',
|
|
67
|
+
'telemetry:show': 'show',
|
|
68
|
+
'telemetry:watch': 'watch',
|
|
69
|
+
};
|
|
70
|
+
|
|
63
71
|
const [, , cmd, ...rest] = process.argv;
|
|
64
72
|
|
|
65
73
|
function printHelp() {
|
|
@@ -80,6 +88,10 @@ Commands:
|
|
|
80
88
|
trace:list List recent local agent sessions (defaults: --since 7d --cwd project)
|
|
81
89
|
trace:stats Show trace stats (defaults: --since 7d --cwd project)
|
|
82
90
|
trace:show ID Show one trace by id or prefix
|
|
91
|
+
telemetry:list List recent JobForge runs with tasks/outcomes/issues
|
|
92
|
+
telemetry:status Show latest JobForge run + pending tracker state
|
|
93
|
+
telemetry:show ID Show one run with child sessions, provider errors, next actions
|
|
94
|
+
telemetry:watch Watch latest run status
|
|
83
95
|
sync Re-create harness symlinks in the current project
|
|
84
96
|
|
|
85
97
|
Deterministic helpers (prefer these over LLM-derived values):
|
|
@@ -104,6 +116,8 @@ Pass --help after a command to see its own flags, e.g.:
|
|
|
104
116
|
job-forge slugify "Anthropic, PBC"
|
|
105
117
|
job-forge trace:list --since 24h
|
|
106
118
|
job-forge trace:show ses_...
|
|
119
|
+
job-forge telemetry:status
|
|
120
|
+
job-forge telemetry:show ses_...
|
|
107
121
|
|
|
108
122
|
Project directory resolves to $JOB_FORGE_PROJECT or cwd.`);
|
|
109
123
|
}
|
|
@@ -128,6 +142,21 @@ if (cmd === 'trace' || traceAliases[cmd]) {
|
|
|
128
142
|
process.exit(result.status ?? 1);
|
|
129
143
|
}
|
|
130
144
|
|
|
145
|
+
if (cmd === 'telemetry' || telemetryAliases[cmd]) {
|
|
146
|
+
const telemetryArgs = cmd === 'telemetry'
|
|
147
|
+
? (rest.length === 0 ? ['help'] : rest)
|
|
148
|
+
: [telemetryAliases[cmd], ...rest];
|
|
149
|
+
|
|
150
|
+
const scriptPath = join(PKG_ROOT, 'scripts/telemetry.mjs');
|
|
151
|
+
const result = spawnSync(process.execPath, [scriptPath, ...telemetryArgs], {
|
|
152
|
+
stdio: 'inherit',
|
|
153
|
+
cwd: PROJECT_DIR,
|
|
154
|
+
env: process.env,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
process.exit(result.status ?? 1);
|
|
158
|
+
}
|
|
159
|
+
|
|
131
160
|
const rel = commands[cmd];
|
|
132
161
|
if (!rel) {
|
|
133
162
|
console.error(`Unknown command: ${cmd}\n`);
|
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
|
|
|
@@ -204,6 +204,7 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
|
|
|
204
204
|
| `cv-sync-check.mjs` | `npx job-forge sync-check` | Setup lint: `cv.md` + `config/profile.yml`, hardcoded-metric scan on `modes/_shared.md` and `batch/batch-prompt.md`, optional `article-digest.md` freshness |
|
|
205
205
|
| `scripts/token-usage-report.mjs` | `npx job-forge tokens` | Per-session opencode token/cost report from the SQLite DB |
|
|
206
206
|
| `scripts/trace.mjs` | `npx job-forge trace:list` / `trace:stats` / `trace:show` | Local transcript observability via `@razroo/iso-trace`; common commands default to OpenCode sessions for the consumer project |
|
|
207
|
+
| `scripts/telemetry.mjs` | `npx job-forge telemetry:status` / `telemetry:show` | JobForge operational telemetry derived from OpenCode traces plus tracker TSV state |
|
|
207
208
|
| `tracker-lib.mjs` | _(library)_ | Shared helpers for reading/writing day-based tracker files — imported by merge/dedup/verify/normalize |
|
|
208
209
|
| `bin/sync.mjs` | `npx job-forge sync` | Creates the harness symlinks in a consumer project (also runs as `postinstall`) |
|
|
209
210
|
| `bin/create-job-forge.mjs` | `npx create-job-forge <dir>` | Scaffolds a new personal project |
|
package/docs/CUSTOMIZATION.md
CHANGED
|
@@ -112,6 +112,19 @@ Scaffolded projects also include npm aliases: `npm run trace:list`, `npm run tra
|
|
|
112
112
|
|
|
113
113
|
For raw iso-trace commands, use `npx job-forge trace sources`, `npx job-forge trace where`, or any other `iso-trace` subcommand after `trace`.
|
|
114
114
|
|
|
115
|
+
## JobForge telemetry
|
|
116
|
+
|
|
117
|
+
Trace is the raw transcript view. Telemetry is the JobForge operational view: it summarizes task dispatches, child session outcomes, provider errors, policy issues, and pending tracker TSVs.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npx job-forge telemetry:list
|
|
121
|
+
npx job-forge telemetry:status
|
|
122
|
+
npx job-forge telemetry:show <session-id-or-prefix>
|
|
123
|
+
npx job-forge telemetry:watch
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Telemetry is also local-only and passive. It reads OpenCode's SQLite DB and files under `batch/tracker-additions/`; agents do not need to remember to emit custom events.
|
|
127
|
+
|
|
115
128
|
**Where Claude Code writes JSONL:** `~/.claude/projects/<encoded-cwd>/*.jsonl`.
|
|
116
129
|
|
|
117
130
|
**Direct CLI fallback:** `npx -y @razroo/iso-trace@latest stats --source "$HOME/.claude/projects/<encoded-dir>/<session>.jsonl"`
|