job-forge 2.14.7 → 2.14.9
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 +1 -0
- package/.claude/agents/general-paid.md +3 -1
- package/.codex/config.toml +5 -0
- package/.cursor/mcp.json +13 -0
- package/.cursor/rules/agent-general-free.mdc +1 -0
- package/.cursor/rules/agent-general-paid.mdc +3 -1
- package/.cursor/rules/main.mdc +25 -144
- package/.mcp.json +13 -0
- package/.opencode/agents/general-free.md +2 -0
- package/.opencode/agents/general-paid.md +15 -3
- package/.opencode/skills/job-forge.md +5 -1
- package/AGENTS.md +25 -144
- package/CLAUDE.md +25 -144
- package/README.md +7 -1
- package/docs/SETUP.md +1 -0
- package/iso/agents/general-free.md +2 -0
- package/iso/agents/general-paid.md +15 -3
- package/iso/commands/job-forge.md +5 -1
- package/iso/instructions.md +25 -144
- package/iso/mcp.json +9 -0
- package/modes/apply.md +29 -13
- package/modes/reference-geometra.md +3 -2
- package/modes/reference-portals.md +7 -6
- package/opencode.json +14 -0
- package/package.json +6 -3
- package/scripts/check-iso-smoke.mjs +43 -0
package/CLAUDE.md
CHANGED
|
@@ -4,14 +4,14 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
4
4
|
|
|
5
5
|
## Hard limits
|
|
6
6
|
|
|
7
|
-
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
8
|
-
why: higher parallelism blows through free-tier rate limits; each subagent requires post-cleanup and racing more than 2 reliably loses at least one result
|
|
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: higher parallelism blows through free-tier rate limits; 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-fallback 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
|
|
12
12
|
|
|
13
13
|
- [H3] Before every batch of `task` dispatches that will use Geometra, call `geometra_list_sessions` then `geometra_disconnect({closeBrowser: true})`. Every round, no exceptions. Name this cleanup as an explicit "step 0" in your first-response plan for any multi-apply request — it is the most frequently skipped guardrail in practice, and skipping it produces cascade "Not connected" failures on the next dispatch.
|
|
14
|
-
why:
|
|
14
|
+
why: aborted subagents can leave Chromium sessions stuck in the MCP pool. Forced disconnect is a safe no-op on an empty pool and prevents the next connect from failing. Naming it up front improves compliance
|
|
15
15
|
|
|
16
16
|
- [H4] In multi-job mode, the orchestrator session MUST NOT call `geometra_fill_form`, `geometra_run_actions`, `geometra_pick_listbox_option`, or `geometra_fill_otp` directly. Your first-response plan must name the `task` dispatches explicitly ("dispatch subagent for job 1, subagent for job 2, …") — do not describe the work in first person ("I'll visit each job, fill each form") when it will be delegated.
|
|
17
17
|
why: repeated Geometra calls in the orchestrator bloat the cache prefix — this is the 2026-04 "apply to 20 jobs" 341-msg incident where each turn re-processed 100K+ fresh tokens instead of reading from cache; first-person narration is a leading indicator that the agent is mentally queueing work for itself rather than a subagent
|
|
@@ -19,6 +19,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
19
19
|
- [H5] Re-dispatch the same company only AFTER the previous subagent returns. Never fire the same `task` twice while the first is still in flight.
|
|
20
20
|
why: two in-flight subagents for the same URL race on Geometra sessions and on tracker TSV writes, corrupting state and sometimes double-submitting
|
|
21
21
|
|
|
22
|
+
- [H5b] Do not use `task` to poll task status. If OpenCode returns a task/session id without a final result, record the id, stop dispatching new rounds, and tell the user the round is still in flight. When the user asks to check later, inspect authoritative files (`batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`, day files, or `iso-trace`) rather than spawning a "check task status" subagent.
|
|
23
|
+
why: OpenCode status prompts can be delivered into the target subagent as a new user message; a 2026-04-25 trace caused a subagent to call `task` recursively instead of finishing the application
|
|
24
|
+
|
|
22
25
|
- [H6] Application outcomes flow through `batch/tracker-additions/*.tsv`, not `data/pipeline.md`. After any multi-apply run, the orchestrator MUST run `npx job-forge merge` then `npx job-forge verify` before ending the session.
|
|
23
26
|
why: `pipeline.md` is the URL inbox (`[ ]` pending → `[x]` processed); `data/applications/YYYY-MM-DD.md` is the outcome log; the TSV pathway is the only safe bridge because `merge` handles column order and duplicate detection
|
|
24
27
|
|
|
@@ -33,13 +36,10 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
33
36
|
- [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.
|
|
34
37
|
why: GLM 5.1 doesn't discount cache reads so procedural work there costs ~10×; free-tier models handle procedural work fine empirically (`opencode/big-pickle` processed 1000+ messages at $0)
|
|
35
38
|
|
|
36
|
-
- [D3]
|
|
37
|
-
why:
|
|
38
|
-
|
|
39
|
-
- [D3f] **Provider-failure downgrade on `apply` (all harnesses; OpenCode + OpenRouter especially):** If you dispatched `@general-paid` per [D3] and that subagent fails or exhausts retries with provider-side errors — copy mentioning Venice / Diem / Chutes, "insufficient" USD/credits/funds/balance, HTTP 402/429, overload / temporarily unavailable — re-dispatch the **same apply URL** once on `@general-free` before marking FAILED. Do not abandon the role solely because the upgraded tier hit a pool-specific limit.
|
|
40
|
-
why: `@general-paid` on OpenCode still uses free OpenRouter model ids; Venice-style balance errors are a backend-route issue, not proof that procedural `@general-free` cannot complete the same Greenhouse-style flow after [D5]/[H2] gates pass
|
|
39
|
+
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
40
|
+
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
|
41
41
|
|
|
42
|
-
- [D4] Auto-submit for offers scoring 3.0+/5 without pausing for confirmation between steps — scan → evaluate →
|
|
42
|
+
- [D4] Auto-submit for offers scoring 3.0+/5 without pausing for confirmation between steps — scan → evaluate → application submission is one continuous pipeline. Mark SKIP for <3.0 and move on.
|
|
43
43
|
why: JobForge is designed for end-to-end automation; pausing between steps defeats the purpose and the 3.0 gate already enforces quality
|
|
44
44
|
|
|
45
45
|
- [D5] Before any batch-apply dispatch, run the Apply Preflight location filter from `modes/apply.md` to exclude location-incompatible candidates.
|
|
@@ -50,19 +50,16 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
50
50
|
|
|
51
51
|
## Procedure
|
|
52
52
|
|
|
53
|
-
1.
|
|
54
|
-
2. Pick the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
|
-
3.
|
|
56
|
-
4.
|
|
57
|
-
5.
|
|
58
|
-
6.
|
|
59
|
-
7.
|
|
60
|
-
8.
|
|
61
|
-
9.
|
|
62
|
-
10.
|
|
63
|
-
11. Write outcomes as TSVs [H6]; run `npx job-forge merge` then `verify` at end.
|
|
64
|
-
12. Offers scoring 3.0+/5 continue without confirmation [D4]; <3.0 is SKIP.
|
|
65
|
-
13. Confirm tracker is merged and verified before ending.
|
|
53
|
+
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
54
|
+
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
|
+
3. Read the active mode file [D3]; decide inline vs delegated work [D1].
|
|
56
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2].
|
|
57
|
+
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
58
|
+
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
59
|
+
7. Cross-check subagent facts against authoritative files [H7].
|
|
60
|
+
8. Apply score gate [D4].
|
|
61
|
+
9. Merge TSV outcomes [H6].
|
|
62
|
+
10. Verify tracker before ending [H6].
|
|
66
63
|
|
|
67
64
|
## Routing
|
|
68
65
|
|
|
@@ -94,127 +91,11 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
|
|
|
94
91
|
|
|
95
92
|
# Reference
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## Session Hygiene — ALWAYS enforce
|
|
102
|
-
|
|
103
|
-
**Multi-job workflows MUST delegate each job to its own subagent.** This rule applies even when the user does NOT explicitly invoke `/job-forge`.
|
|
104
|
-
|
|
105
|
-
Whenever the user says any variation of "apply to N jobs", "process the pipeline", "batch evaluate", or similar phrasing that implies more than one application/evaluation in sequence:
|
|
106
|
-
|
|
107
|
-
1. **Do not drive all N jobs from this session.** Repeated `geometra_fill_form` / `geometra_page_model` calls accumulate in conversation history and invalidate prompt caching — each new message ends up re-processing 100K+ tokens of fresh history instead of reading from cache.
|
|
108
|
-
2. **Launch one subagent per job, in parallel batches of ≤2** (see Hard Limits #1). Higher parallelism blows through free-tier rate limits and each subagent requires post-cleanup. Use the `task` tool / Agent with `subagent_type="general-purpose"`, passing the single URL and the relevant mode file content.
|
|
109
|
-
3. **This session acts as the orchestrator only**: plan, pick the jobs, dispatch subagents, aggregate results. No Geometra form-filling in this session unless it's a single one-off application.
|
|
110
|
-
|
|
111
|
-
**Why:** observed on a real run — a 341-msg "apply to 20 jobs" session had `cache_read ~1.8K` on 5 messages where input ballooned to 100K-144K tokens. A 40-msg orchestrator session that delegates instead stays under 40K input max with cache reads at full 100K+. Same work, ~5× fewer effective tokens.
|
|
112
|
-
|
|
113
|
-
**Verify after running:** `npx job-forge tokens --session <id>` — any message with `cache_read < 5K` and `input > 50K` is a cache-bust; next time split that work across subagents.
|
|
114
|
-
|
|
115
|
-
**Exception:** evaluation-only or tracker-only work (no Geometra, no repeated tool calls) can proceed in a single session. The rule targets tool-heavy multi-step loops.
|
|
116
|
-
|
|
117
|
-
**Before any batch-apply dispatch, run the Apply Preflight location filter from `modes/apply.md`** to exclude location-incompatible candidates. Catches the common case where an evaluated role has the right role-shape but a deal-breaking location that profile.yml already rules out.
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## Subagent Routing — which agent for which task
|
|
122
|
-
|
|
123
|
-
The harness ships three subagents (see `.opencode/agents/`). The orchestrator MUST route work by cost tier, not pick the default for everything. **GLM 5.1 does not discount cache reads**, so running procedural work on it costs ~10× what it would on a cache-discounting model. Free-tier models handle procedural work fine (confirmed empirically: `opencode/big-pickle` processed 1000+ messages at $0 in prior runs).
|
|
124
|
-
|
|
125
|
-
| Task type | Subagent | Why |
|
|
126
|
-
|-----------|----------|-----|
|
|
127
|
-
| Drive Geometra form-fill / submit (atomic `run_actions`) | `@general-free` | Procedural; label-driven; deterministic |
|
|
128
|
-
| Merge TSVs, run `verify-pipeline.mjs`, dedup | `@general-free` | Script-driven; no writing quality needed |
|
|
129
|
-
| OTP retrieval via Gmail MCP + `geometra_fill_otp` | `@general-free` | Fixed-shape lookup + input |
|
|
130
|
-
| Scan portals, extract offer metadata, return structured records (see schema below) | `@general-free` | Structured output; no judgment |
|
|
131
|
-
| Evaluation narrative — Blocks A-F per `modes/offer.md` | `@general-paid` | Judgment + writing quality |
|
|
132
|
-
| Cover letter, "Why X?" answers, Section G drafts | `@general-paid` | Tone and specificity matter |
|
|
133
|
-
| STAR+R interview stories, story-bank curation | `@general-paid` | Quality signals seniority |
|
|
134
|
-
| LinkedIn outreach messages (`modes/contact.md`) | `@general-paid` | First impression |
|
|
135
|
-
| "Extract N fields from this text → JSON" (≤5K input) | `@glm-minimal` | One-shot transform; no context needed |
|
|
136
|
-
| "Classify this JD as archetype X/Y/Z" | `@glm-minimal` | Narrow, structured output |
|
|
137
|
-
|
|
138
|
-
**Example JSON shape for the "extract / emit JSON" subagent rows above** (use this exact key set when delegating a portal-scan / extract task):
|
|
139
|
-
|
|
140
|
-
```json
|
|
141
|
-
{
|
|
142
|
-
"company": "Acme",
|
|
143
|
-
"role": "Senior Backend Engineer",
|
|
144
|
-
"location": "Remote (US)",
|
|
145
|
-
"comp_range_usd": "180000-220000",
|
|
146
|
-
"archetype": "backend-platform",
|
|
147
|
-
"url": "https://..."
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
**Rule:** when you (the orchestrator) delegate a task, pick the cheapest agent that can do it well. Do NOT route every subagent through the same tier. Auto-pipeline mode MUST split a single job across `@general-paid` (evaluation) and `@general-free` (PDF gen + tracker + apply), not run it all on one model.
|
|
152
|
-
|
|
153
|
-
**When to break this rule:** if the user explicitly asks for "quality over cost" or flags a high-stakes application (top-tier company, offer-stage negotiation, executive search), route everything through `@general-paid`. Document the exception in the session.
|
|
154
|
-
|
|
155
|
-
### When to delegate
|
|
156
|
-
|
|
157
|
-
**Delegate (`task` out) when the work involves repeated tool-heavy steps that bloat the orchestrator's cache prefix.** The concrete failure mode this prevents: a 341-message "apply to 20 jobs" session where repeated `geometra_fill_form` / `geometra_page_model` calls accumulated in history, forcing each new message to re-process 100K+ tokens of fresh input instead of reading from cache.
|
|
158
|
-
|
|
159
|
-
**Delegate when:**
|
|
160
|
-
- Applying to N≥2 jobs (repeated Geometra form-fill — the original cache-bust scenario)
|
|
161
|
-
- Batch portal scans hitting ≥3 companies (API loops + page-model reads stack up)
|
|
162
|
-
- Any explicit "apply to... / process pipeline / batch evaluate" phrasing from the user (multi-job intent)
|
|
163
|
-
|
|
164
|
-
**Do NOT delegate — orchestrate inline:**
|
|
165
|
-
- Single-offer evaluation (text-heavy, not tool-heavy)
|
|
166
|
-
- Development / bug-fix / file-editing tasks
|
|
167
|
-
- `tracker` and other read-only modes
|
|
168
|
-
- Single-company scan, single-URL check
|
|
169
|
-
- One-shot questions — "what does this mean?", "read X and summarize", "what's my next report number?"
|
|
170
|
-
|
|
171
|
-
**Detection signal:** if you're about to call `geometra_fill_form` for a second *different* job in the same session, STOP and delegate the remainder. For everything else, in-session execution is the expected default.
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Ethical Use -- CRITICAL
|
|
176
|
-
|
|
177
|
-
**Applying to jobs via Geometra MCP is NOT impersonation.** The agent uses the user's credentials, CV, and information to apply on their behalf. This is the same as the user applying themselves — the agent is an extension of the user's will. Think of it as a browser automation tool that fills forms with the user's data.
|
|
178
|
-
|
|
179
|
-
**This system is designed for quality, not quantity.** The goal is to help the user find and apply to roles where there is a genuine match -- not to spam companies with mass applications.
|
|
180
|
-
|
|
181
|
-
- **Continuous pipeline for 3.0+ offers:** When scanning, evaluating, and applying — run the full pipeline end-to-end without pausing for confirmation. Scan → evaluate → fill form → submit for any offer scoring 3.0/5 or above. Do NOT stop between steps to ask "want me to continue?" — just do it.
|
|
182
|
-
- **Auto-submit:** For offers scoring 3.0+/5, fill and submit the application automatically. For offers below 3.0/5, mark as SKIP and move on.
|
|
183
|
-
- **Still respect quality:** Only apply where there is a genuine match (3.0+ ensures this). Auto-SKIP anything below 3.0.
|
|
184
|
-
- **Respect recruiters' time.** Every application a human reads costs someone's attention. Only send what's worth reading.
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Offer Verification -- MANDATORY
|
|
189
|
-
|
|
190
|
-
**Read local artifacts before the network.** If `reports/` already contains this posting URL (or company+role with a full JD in the body), **Read** that report for verification or evaluation instead of WebFetch/Geometra. If `data/pipeline.md` or `jds/` points at frozen JD text (`local:jds/{file}` or pasted blocks), **Read** that first. Reuse JD text already in the same conversation — do not fetch the same URL twice. (The JD extraction section at the top of `modes/auto-pipeline.md` and its "at most once per session" rule are the detailed contract.)
|
|
191
|
-
|
|
192
|
-
**When Geometra MCP is available** (interactive sessions), ALWAYS use it to verify offers:
|
|
193
|
-
1. `geometra_connect` to the URL (via proxy)
|
|
194
|
-
2. `geometra_page_model` to read structured page content
|
|
195
|
-
3. Only footer/navbar without JD = closed. Title + description + Apply = active.
|
|
196
|
-
|
|
197
|
-
**When Geometra MCP is NOT available** (batch workers via `opencode run`, headless environments):
|
|
198
|
-
1. Use WebFetch to retrieve the page content
|
|
199
|
-
2. Check for JD text, job title, and apply button/link in the response
|
|
200
|
-
3. If WebFetch returns only a shell/navbar (no JD content), mark the offer as `**Verification: unconfirmed**` in the report header
|
|
201
|
-
4. Do NOT skip the evaluation — proceed but flag the uncertainty so the user can verify manually before applying
|
|
202
|
-
|
|
203
|
-
The goal is to never waste time on closed offers, but also never silently assume a role is active when verification was incomplete.
|
|
204
|
-
|
|
205
|
-
### Canonical MCP tools (quick reference)
|
|
206
|
-
|
|
207
|
-
Pick tools by name directly — reduces unnecessary tool discovery:
|
|
208
|
-
|
|
209
|
-
| Task | Preferred tools |
|
|
210
|
-
|------|------------------|
|
|
211
|
-
| JD from URL | Greenhouse boards API when the URL matches (see JD extraction in `modes/auto-pipeline.md`) → else `geometra_connect` + `geometra_page_model` → else WebFetch → WebSearch last |
|
|
212
|
-
| Offer still live? | Same as JD when Geometra is available; else WebFetch per above |
|
|
213
|
-
| One apply subagent (single job) | One `geometra_connect` per job URL; reuse `sessionId` through schema + fill; submit via atomic `geometra_run_actions` per `modes/apply.md` [H1]. Do **not** `geometra_disconnect` between `geometra_form_schema` and submit on the same form unless recovery requires it |
|
|
214
|
-
| Chromium pool between orchestrator dispatch rounds | `geometra_list_sessions` + `geometra_disconnect({ closeBrowser: true })` per Hard limit [H3] — orchestrator-only; not a substitute for finishing the in-subagent form flow |
|
|
215
|
-
|
|
216
|
-
@modes/reference-setup.md
|
|
94
|
+
The sections above are the shared contract. Load detailed context on demand:
|
|
217
95
|
|
|
218
|
-
|
|
96
|
+
- `modes/{mode}.md` for the active mode procedure, output shape, and mode-specific routing.
|
|
97
|
+
- `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
|
|
98
|
+
- `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
|
|
99
|
+
- `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
|
|
219
100
|
|
|
220
|
-
|
|
101
|
+
Do not pre-load all reference files. Read only the active mode file and the reference file needed for the current blocker.
|
package/README.md
CHANGED
|
@@ -25,7 +25,13 @@ npm install
|
|
|
25
25
|
opencode
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
The scaffolded `opencode.json` already has
|
|
28
|
+
The scaffolded `opencode.json` already has three MCPs wired up — they launch automatically the first time opencode starts:
|
|
29
|
+
|
|
30
|
+
- **Geometra** — browser automation + PDF generation
|
|
31
|
+
- **Gmail** — reads replies from recruiters
|
|
32
|
+
- **state-trace** — typed working memory for cross-session context (resumed batches, recent decisions, repeated portal quirks). Spawned via `uvx`; install once with `brew install uv` (or `pipx install uv`) — no other setup.
|
|
33
|
+
|
|
34
|
+
`npm install` also materializes symlinks for every supported agent harness — OpenCode, Cursor, Claude Code, and Codex — so you can run `opencode`, `cursor`, `claude`, or `codex` in the same project and each picks up the shared MCP config and instructions.
|
|
29
35
|
|
|
30
36
|
Then fill in `cv.md`, `config/profile.yml`, and `portals.yml` with your personal data, paste a job URL into opencode, and JobForge evaluates + tracks it.
|
|
31
37
|
|
package/docs/SETUP.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [opencode](https://opencode.ai) installed and configured
|
|
6
6
|
- Node.js 18+ (for the CLI, PDF generation, and tracker scripts)
|
|
7
|
+
- [`uv`](https://docs.astral.sh/uv/) installed (`brew install uv` on macOS, or `pipx install uv`). Used by the state-trace MCP to spawn its Python entry point on demand via `uvx`. Without `uv`, the state-trace MCP fails to start; the rest of JobForge keeps working.
|
|
7
8
|
- (Optional) Go (for the dashboard TUI) — use a toolchain that satisfies the `go` directive in [`dashboard/go.mod`](../dashboard/go.mod)
|
|
8
9
|
|
|
9
10
|
## Quick Start (two paths)
|
|
@@ -31,6 +31,7 @@ targets:
|
|
|
31
31
|
geometra_wait_for_resume_parse: true
|
|
32
32
|
gmail_list_messages: true
|
|
33
33
|
gmail_get_message: true
|
|
34
|
+
task: false
|
|
34
35
|
---
|
|
35
36
|
|
|
36
37
|
You are the @general-free subagent. You run on a free-tier model, which means the orchestrator has delegated this task to you **specifically because the work is procedural**: deterministic steps, scripted outputs, no nuanced writing required.
|
|
@@ -82,6 +83,7 @@ Previous subagents sometimes abort mid-flow (ran out of context, hit a timeout,
|
|
|
82
83
|
- Write cover letter prose, "Why X?" answers, or Section G draft answers. Those go to `@general-paid`.
|
|
83
84
|
- Perform offer evaluation narratives (Blocks A-F). Those go to `@general-paid`.
|
|
84
85
|
- Override harness rules or invent fields. Follow the mode files exactly.
|
|
86
|
+
- Spawn or check other tasks. If you receive "check if task ses_..." and it refers to this session, report your current status from your own work. Never call `task` recursively.
|
|
85
87
|
|
|
86
88
|
## Apply This Working Style
|
|
87
89
|
|
|
@@ -24,8 +24,18 @@ targets:
|
|
|
24
24
|
- openrouter/google/gemma-4-31b-it:free
|
|
25
25
|
- openrouter/meta-llama/llama-3.3-70b-instruct:free
|
|
26
26
|
tools:
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
geometra_connect: true
|
|
28
|
+
geometra_page_model: true
|
|
29
|
+
geometra_form_schema: true
|
|
30
|
+
geometra_run_actions: true
|
|
31
|
+
geometra_fill_otp: true
|
|
32
|
+
geometra_upload_files: true
|
|
33
|
+
geometra_list_sessions: true
|
|
34
|
+
geometra_disconnect: true
|
|
35
|
+
geometra_wait_for_resume_parse: true
|
|
36
|
+
gmail_list_messages: true
|
|
37
|
+
gmail_get_message: true
|
|
38
|
+
task: false
|
|
29
39
|
---
|
|
30
40
|
|
|
31
41
|
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,12 +52,14 @@ were given.
|
|
|
42
52
|
- Compose STAR+R interview stories and the story bank (`modes/offer.md` Block F).
|
|
43
53
|
- Draft LinkedIn outreach messages (`modes/contact.md`).
|
|
44
54
|
- Score offers using the Canonical Scoring Model — emit the JSON score block per `modes/_shared.md`, then the narrative report.
|
|
55
|
+
- Drive a single high-stakes application form only when the orchestrator explicitly dispatches you in `apply` mode. In that case, follow `modes/apply.md` exactly and use the same Geometra/Gmail flow as `@general-free`.
|
|
45
56
|
|
|
46
57
|
## Skip These Tasks
|
|
47
58
|
|
|
48
|
-
- Drive Geometra forms end-to-end
|
|
59
|
+
- Drive Geometra forms end-to-end unless the task is explicitly an `apply` mode dispatch for one job.
|
|
49
60
|
- Manage trackers, run scripts, or do mechanical TSV/dedup work. Those go to `@general-free`.
|
|
50
61
|
- Duplicate work. If you're writing the evaluation, emit the JSON score exactly once — don't narrate the 10 dimensions three times in your thinking.
|
|
62
|
+
- Spawn or check other tasks. If you receive "check if task ses_..." and it refers to this session, report your current status from your own work. Never call `task` recursively.
|
|
51
63
|
|
|
52
64
|
## Apply This Working Style
|
|
53
65
|
|
|
@@ -158,7 +158,11 @@ Step 4 — Loop in rounds of 2 (Hard Limit #1)
|
|
|
158
158
|
# Dispatch 1 or 2 task() calls in ONE message (never 3+)
|
|
159
159
|
task(subagent_type=<tier per AGENTS.md routing>, prompt=<apply prompt for pair[0]>)
|
|
160
160
|
task(subagent_type=<tier>, prompt=<apply prompt for pair[1]>) # only if pair has 2
|
|
161
|
-
# WAIT for both subagents to return
|
|
161
|
+
# WAIT for both subagents to return final APPLIED / APPLY FAILED / SKIP /
|
|
162
|
+
# Discarded outcomes or TSV paths before proceeding.
|
|
163
|
+
# A returned task/session id is only a launch receipt, not completion.
|
|
164
|
+
# Do not create a "check task status" task; inspect tracker files or
|
|
165
|
+
# iso-trace if the user asks for status later.
|
|
162
166
|
# Read their return values, log outcomes
|
|
163
167
|
|
|
164
168
|
Step 5 — Between rounds: clean sessions again
|
package/iso/instructions.md
CHANGED
|
@@ -4,14 +4,14 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
4
4
|
|
|
5
5
|
## Hard limits
|
|
6
6
|
|
|
7
|
-
- [H1] Max 2 parallel `task` dispatches per message. For N jobs, run `ceil(N/2)` sequential rounds of 2. Applies in all modes, for all user phrasings ("urgent", "apply to 10 jobs now").
|
|
8
|
-
why: higher parallelism blows through free-tier rate limits; each subagent requires post-cleanup and racing more than 2 reliably loses at least one result
|
|
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: higher parallelism blows through free-tier rate limits; 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-fallback 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
|
|
12
12
|
|
|
13
13
|
- [H3] Before every batch of `task` dispatches that will use Geometra, call `geometra_list_sessions` then `geometra_disconnect({closeBrowser: true})`. Every round, no exceptions. Name this cleanup as an explicit "step 0" in your first-response plan for any multi-apply request — it is the most frequently skipped guardrail in practice, and skipping it produces cascade "Not connected" failures on the next dispatch.
|
|
14
|
-
why:
|
|
14
|
+
why: aborted subagents can leave Chromium sessions stuck in the MCP pool. Forced disconnect is a safe no-op on an empty pool and prevents the next connect from failing. Naming it up front improves compliance
|
|
15
15
|
|
|
16
16
|
- [H4] In multi-job mode, the orchestrator session MUST NOT call `geometra_fill_form`, `geometra_run_actions`, `geometra_pick_listbox_option`, or `geometra_fill_otp` directly. Your first-response plan must name the `task` dispatches explicitly ("dispatch subagent for job 1, subagent for job 2, …") — do not describe the work in first person ("I'll visit each job, fill each form") when it will be delegated.
|
|
17
17
|
why: repeated Geometra calls in the orchestrator bloat the cache prefix — this is the 2026-04 "apply to 20 jobs" 341-msg incident where each turn re-processed 100K+ fresh tokens instead of reading from cache; first-person narration is a leading indicator that the agent is mentally queueing work for itself rather than a subagent
|
|
@@ -19,6 +19,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
19
19
|
- [H5] Re-dispatch the same company only AFTER the previous subagent returns. Never fire the same `task` twice while the first is still in flight.
|
|
20
20
|
why: two in-flight subagents for the same URL race on Geometra sessions and on tracker TSV writes, corrupting state and sometimes double-submitting
|
|
21
21
|
|
|
22
|
+
- [H5b] Do not use `task` to poll task status. If OpenCode returns a task/session id without a final result, record the id, stop dispatching new rounds, and tell the user the round is still in flight. When the user asks to check later, inspect authoritative files (`batch/tracker-additions/*.tsv`, `batch/tracker-additions/merged/*.tsv`, day files, or `iso-trace`) rather than spawning a "check task status" subagent.
|
|
23
|
+
why: OpenCode status prompts can be delivered into the target subagent as a new user message; a 2026-04-25 trace caused a subagent to call `task` recursively instead of finishing the application
|
|
24
|
+
|
|
22
25
|
- [H6] Application outcomes flow through `batch/tracker-additions/*.tsv`, not `data/pipeline.md`. After any multi-apply run, the orchestrator MUST run `npx job-forge merge` then `npx job-forge verify` before ending the session.
|
|
23
26
|
why: `pipeline.md` is the URL inbox (`[ ]` pending → `[x]` processed); `data/applications/YYYY-MM-DD.md` is the outcome log; the TSV pathway is the only safe bridge because `merge` handles column order and duplicate detection
|
|
24
27
|
|
|
@@ -33,13 +36,10 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
33
36
|
- [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.
|
|
34
37
|
why: GLM 5.1 doesn't discount cache reads so procedural work there costs ~10×; free-tier models handle procedural work fine empirically (`opencode/big-pickle` processed 1000+ messages at $0)
|
|
35
38
|
|
|
36
|
-
- [D3]
|
|
37
|
-
why:
|
|
38
|
-
|
|
39
|
-
- [D3f] **Provider-failure downgrade on `apply` (all harnesses; OpenCode + OpenRouter especially):** If you dispatched `@general-paid` per [D3] and that subagent fails or exhausts retries with provider-side errors — copy mentioning Venice / Diem / Chutes, "insufficient" USD/credits/funds/balance, HTTP 402/429, overload / temporarily unavailable — re-dispatch the **same apply URL** once on `@general-free` before marking FAILED. Do not abandon the role solely because the upgraded tier hit a pool-specific limit.
|
|
40
|
-
why: `@general-paid` on OpenCode still uses free OpenRouter model ids; Venice-style balance errors are a backend-route issue, not proof that procedural `@general-free` cannot complete the same Greenhouse-style flow after [D5]/[H2] gates pass
|
|
39
|
+
- [D3] Read the active mode file before dispatch. Mode files own score gates, provider fallback, portal runbooks, and output shape.
|
|
40
|
+
why: mode-specific rules change faster than global orchestration rules; keeping them out of the shared prefix preserves cache efficiency and prevents stale branches
|
|
41
41
|
|
|
42
|
-
- [D4] Auto-submit for offers scoring 3.0+/5 without pausing for confirmation between steps — scan → evaluate →
|
|
42
|
+
- [D4] Auto-submit for offers scoring 3.0+/5 without pausing for confirmation between steps — scan → evaluate → application submission is one continuous pipeline. Mark SKIP for <3.0 and move on.
|
|
43
43
|
why: JobForge is designed for end-to-end automation; pausing between steps defeats the purpose and the 3.0 gate already enforces quality
|
|
44
44
|
|
|
45
45
|
- [D5] Before any batch-apply dispatch, run the Apply Preflight location filter from `modes/apply.md` to exclude location-incompatible candidates.
|
|
@@ -50,19 +50,16 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
50
50
|
|
|
51
51
|
## Procedure
|
|
52
52
|
|
|
53
|
-
1.
|
|
54
|
-
2. Pick the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
|
-
3.
|
|
56
|
-
4.
|
|
57
|
-
5.
|
|
58
|
-
6.
|
|
59
|
-
7.
|
|
60
|
-
8.
|
|
61
|
-
9.
|
|
62
|
-
10.
|
|
63
|
-
11. Write outcomes as TSVs [H6]; run `npx job-forge merge` then `verify` at end.
|
|
64
|
-
12. Offers scoring 3.0+/5 continue without confirmation [D4]; <3.0 is SKIP.
|
|
65
|
-
13. Confirm tracker is merged and verified before ending.
|
|
53
|
+
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
54
|
+
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
|
+
3. Read the active mode file [D3]; decide inline vs delegated work [D1].
|
|
56
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2].
|
|
57
|
+
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
58
|
+
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
59
|
+
7. Cross-check subagent facts against authoritative files [H7].
|
|
60
|
+
8. Apply score gate [D4].
|
|
61
|
+
9. Merge TSV outcomes [H6].
|
|
62
|
+
10. Verify tracker before ending [H6].
|
|
66
63
|
|
|
67
64
|
## Routing
|
|
68
65
|
|
|
@@ -94,127 +91,11 @@ Output shape is mode-dependent — see `modes/{mode}.md` for each mode's expecte
|
|
|
94
91
|
|
|
95
92
|
# Reference
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## Session Hygiene — ALWAYS enforce
|
|
102
|
-
|
|
103
|
-
**Multi-job workflows MUST delegate each job to its own subagent.** This rule applies even when the user does NOT explicitly invoke `/job-forge`.
|
|
104
|
-
|
|
105
|
-
Whenever the user says any variation of "apply to N jobs", "process the pipeline", "batch evaluate", or similar phrasing that implies more than one application/evaluation in sequence:
|
|
106
|
-
|
|
107
|
-
1. **Do not drive all N jobs from this session.** Repeated `geometra_fill_form` / `geometra_page_model` calls accumulate in conversation history and invalidate prompt caching — each new message ends up re-processing 100K+ tokens of fresh history instead of reading from cache.
|
|
108
|
-
2. **Launch one subagent per job, in parallel batches of ≤2** (see Hard Limits #1). Higher parallelism blows through free-tier rate limits and each subagent requires post-cleanup. Use the `task` tool / Agent with `subagent_type="general-purpose"`, passing the single URL and the relevant mode file content.
|
|
109
|
-
3. **This session acts as the orchestrator only**: plan, pick the jobs, dispatch subagents, aggregate results. No Geometra form-filling in this session unless it's a single one-off application.
|
|
110
|
-
|
|
111
|
-
**Why:** observed on a real run — a 341-msg "apply to 20 jobs" session had `cache_read ~1.8K` on 5 messages where input ballooned to 100K-144K tokens. A 40-msg orchestrator session that delegates instead stays under 40K input max with cache reads at full 100K+. Same work, ~5× fewer effective tokens.
|
|
112
|
-
|
|
113
|
-
**Verify after running:** `npx job-forge tokens --session <id>` — any message with `cache_read < 5K` and `input > 50K` is a cache-bust; next time split that work across subagents.
|
|
114
|
-
|
|
115
|
-
**Exception:** evaluation-only or tracker-only work (no Geometra, no repeated tool calls) can proceed in a single session. The rule targets tool-heavy multi-step loops.
|
|
116
|
-
|
|
117
|
-
**Before any batch-apply dispatch, run the Apply Preflight location filter from `modes/apply.md`** to exclude location-incompatible candidates. Catches the common case where an evaluated role has the right role-shape but a deal-breaking location that profile.yml already rules out.
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## Subagent Routing — which agent for which task
|
|
122
|
-
|
|
123
|
-
The harness ships three subagents (see `.opencode/agents/`). The orchestrator MUST route work by cost tier, not pick the default for everything. **GLM 5.1 does not discount cache reads**, so running procedural work on it costs ~10× what it would on a cache-discounting model. Free-tier models handle procedural work fine (confirmed empirically: `opencode/big-pickle` processed 1000+ messages at $0 in prior runs).
|
|
124
|
-
|
|
125
|
-
| Task type | Subagent | Why |
|
|
126
|
-
|-----------|----------|-----|
|
|
127
|
-
| Drive Geometra form-fill / submit (atomic `run_actions`) | `@general-free` | Procedural; label-driven; deterministic |
|
|
128
|
-
| Merge TSVs, run `verify-pipeline.mjs`, dedup | `@general-free` | Script-driven; no writing quality needed |
|
|
129
|
-
| OTP retrieval via Gmail MCP + `geometra_fill_otp` | `@general-free` | Fixed-shape lookup + input |
|
|
130
|
-
| Scan portals, extract offer metadata, return structured records (see schema below) | `@general-free` | Structured output; no judgment |
|
|
131
|
-
| Evaluation narrative — Blocks A-F per `modes/offer.md` | `@general-paid` | Judgment + writing quality |
|
|
132
|
-
| Cover letter, "Why X?" answers, Section G drafts | `@general-paid` | Tone and specificity matter |
|
|
133
|
-
| STAR+R interview stories, story-bank curation | `@general-paid` | Quality signals seniority |
|
|
134
|
-
| LinkedIn outreach messages (`modes/contact.md`) | `@general-paid` | First impression |
|
|
135
|
-
| "Extract N fields from this text → JSON" (≤5K input) | `@glm-minimal` | One-shot transform; no context needed |
|
|
136
|
-
| "Classify this JD as archetype X/Y/Z" | `@glm-minimal` | Narrow, structured output |
|
|
137
|
-
|
|
138
|
-
**Example JSON shape for the "extract / emit JSON" subagent rows above** (use this exact key set when delegating a portal-scan / extract task):
|
|
139
|
-
|
|
140
|
-
```json
|
|
141
|
-
{
|
|
142
|
-
"company": "Acme",
|
|
143
|
-
"role": "Senior Backend Engineer",
|
|
144
|
-
"location": "Remote (US)",
|
|
145
|
-
"comp_range_usd": "180000-220000",
|
|
146
|
-
"archetype": "backend-platform",
|
|
147
|
-
"url": "https://..."
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
**Rule:** when you (the orchestrator) delegate a task, pick the cheapest agent that can do it well. Do NOT route every subagent through the same tier. Auto-pipeline mode MUST split a single job across `@general-paid` (evaluation) and `@general-free` (PDF gen + tracker + apply), not run it all on one model.
|
|
152
|
-
|
|
153
|
-
**When to break this rule:** if the user explicitly asks for "quality over cost" or flags a high-stakes application (top-tier company, offer-stage negotiation, executive search), route everything through `@general-paid`. Document the exception in the session.
|
|
154
|
-
|
|
155
|
-
### When to delegate
|
|
156
|
-
|
|
157
|
-
**Delegate (`task` out) when the work involves repeated tool-heavy steps that bloat the orchestrator's cache prefix.** The concrete failure mode this prevents: a 341-message "apply to 20 jobs" session where repeated `geometra_fill_form` / `geometra_page_model` calls accumulated in history, forcing each new message to re-process 100K+ tokens of fresh input instead of reading from cache.
|
|
158
|
-
|
|
159
|
-
**Delegate when:**
|
|
160
|
-
- Applying to N≥2 jobs (repeated Geometra form-fill — the original cache-bust scenario)
|
|
161
|
-
- Batch portal scans hitting ≥3 companies (API loops + page-model reads stack up)
|
|
162
|
-
- Any explicit "apply to... / process pipeline / batch evaluate" phrasing from the user (multi-job intent)
|
|
163
|
-
|
|
164
|
-
**Do NOT delegate — orchestrate inline:**
|
|
165
|
-
- Single-offer evaluation (text-heavy, not tool-heavy)
|
|
166
|
-
- Development / bug-fix / file-editing tasks
|
|
167
|
-
- `tracker` and other read-only modes
|
|
168
|
-
- Single-company scan, single-URL check
|
|
169
|
-
- One-shot questions — "what does this mean?", "read X and summarize", "what's my next report number?"
|
|
170
|
-
|
|
171
|
-
**Detection signal:** if you're about to call `geometra_fill_form` for a second *different* job in the same session, STOP and delegate the remainder. For everything else, in-session execution is the expected default.
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Ethical Use -- CRITICAL
|
|
176
|
-
|
|
177
|
-
**Applying to jobs via Geometra MCP is NOT impersonation.** The agent uses the user's credentials, CV, and information to apply on their behalf. This is the same as the user applying themselves — the agent is an extension of the user's will. Think of it as a browser automation tool that fills forms with the user's data.
|
|
178
|
-
|
|
179
|
-
**This system is designed for quality, not quantity.** The goal is to help the user find and apply to roles where there is a genuine match -- not to spam companies with mass applications.
|
|
180
|
-
|
|
181
|
-
- **Continuous pipeline for 3.0+ offers:** When scanning, evaluating, and applying — run the full pipeline end-to-end without pausing for confirmation. Scan → evaluate → fill form → submit for any offer scoring 3.0/5 or above. Do NOT stop between steps to ask "want me to continue?" — just do it.
|
|
182
|
-
- **Auto-submit:** For offers scoring 3.0+/5, fill and submit the application automatically. For offers below 3.0/5, mark as SKIP and move on.
|
|
183
|
-
- **Still respect quality:** Only apply where there is a genuine match (3.0+ ensures this). Auto-SKIP anything below 3.0.
|
|
184
|
-
- **Respect recruiters' time.** Every application a human reads costs someone's attention. Only send what's worth reading.
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Offer Verification -- MANDATORY
|
|
189
|
-
|
|
190
|
-
**Read local artifacts before the network.** If `reports/` already contains this posting URL (or company+role with a full JD in the body), **Read** that report for verification or evaluation instead of WebFetch/Geometra. If `data/pipeline.md` or `jds/` points at frozen JD text (`local:jds/{file}` or pasted blocks), **Read** that first. Reuse JD text already in the same conversation — do not fetch the same URL twice. (The JD extraction section at the top of `modes/auto-pipeline.md` and its "at most once per session" rule are the detailed contract.)
|
|
191
|
-
|
|
192
|
-
**When Geometra MCP is available** (interactive sessions), ALWAYS use it to verify offers:
|
|
193
|
-
1. `geometra_connect` to the URL (via proxy)
|
|
194
|
-
2. `geometra_page_model` to read structured page content
|
|
195
|
-
3. Only footer/navbar without JD = closed. Title + description + Apply = active.
|
|
196
|
-
|
|
197
|
-
**When Geometra MCP is NOT available** (batch workers via `opencode run`, headless environments):
|
|
198
|
-
1. Use WebFetch to retrieve the page content
|
|
199
|
-
2. Check for JD text, job title, and apply button/link in the response
|
|
200
|
-
3. If WebFetch returns only a shell/navbar (no JD content), mark the offer as `**Verification: unconfirmed**` in the report header
|
|
201
|
-
4. Do NOT skip the evaluation — proceed but flag the uncertainty so the user can verify manually before applying
|
|
202
|
-
|
|
203
|
-
The goal is to never waste time on closed offers, but also never silently assume a role is active when verification was incomplete.
|
|
204
|
-
|
|
205
|
-
### Canonical MCP tools (quick reference)
|
|
206
|
-
|
|
207
|
-
Pick tools by name directly — reduces unnecessary tool discovery:
|
|
208
|
-
|
|
209
|
-
| Task | Preferred tools |
|
|
210
|
-
|------|------------------|
|
|
211
|
-
| JD from URL | Greenhouse boards API when the URL matches (see JD extraction in `modes/auto-pipeline.md`) → else `geometra_connect` + `geometra_page_model` → else WebFetch → WebSearch last |
|
|
212
|
-
| Offer still live? | Same as JD when Geometra is available; else WebFetch per above |
|
|
213
|
-
| One apply subagent (single job) | One `geometra_connect` per job URL; reuse `sessionId` through schema + fill; submit via atomic `geometra_run_actions` per `modes/apply.md` [H1]. Do **not** `geometra_disconnect` between `geometra_form_schema` and submit on the same form unless recovery requires it |
|
|
214
|
-
| Chromium pool between orchestrator dispatch rounds | `geometra_list_sessions` + `geometra_disconnect({ closeBrowser: true })` per Hard limit [H3] — orchestrator-only; not a substitute for finishing the in-subagent form flow |
|
|
215
|
-
|
|
216
|
-
@modes/reference-setup.md
|
|
94
|
+
The sections above are the shared contract. Load detailed context on demand:
|
|
217
95
|
|
|
218
|
-
|
|
96
|
+
- `modes/{mode}.md` for the active mode procedure, output shape, and mode-specific routing.
|
|
97
|
+
- `modes/reference-setup.md` for onboarding, tracker layout, states, and profile/CV setup.
|
|
98
|
+
- `modes/reference-portals.md` for OTP, residential proxy, and MCP configuration.
|
|
99
|
+
- `modes/reference-geometra.md` for form-fill patterns, portal failures, cleanup runbooks, and session recovery.
|
|
219
100
|
|
|
220
|
-
|
|
101
|
+
Do not pre-load all reference files. Read only the active mode file and the reference file needed for the current blocker.
|
package/iso/mcp.json
CHANGED
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
"env": {
|
|
11
11
|
"DISABLE_HTTP": "true"
|
|
12
12
|
}
|
|
13
|
+
},
|
|
14
|
+
"state-trace": {
|
|
15
|
+
"command": "uvx",
|
|
16
|
+
"args": ["--from", "state-trace[mcp]", "state-trace-mcp"],
|
|
17
|
+
"env": {
|
|
18
|
+
"STATE_TRACE_STORAGE_PATH": ".state-trace/memory.db",
|
|
19
|
+
"STATE_TRACE_NAMESPACE": "job-forge",
|
|
20
|
+
"STATE_TRACE_CAPACITY_LIMIT": "256"
|
|
21
|
+
}
|
|
13
22
|
}
|
|
14
23
|
}
|
|
15
24
|
}
|