job-forge 2.14.9 → 2.14.11
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/.cursor/rules/main.mdc +4 -1
- package/.opencode/skills/job-forge.md +3 -0
- package/AGENTS.md +4 -1
- package/CLAUDE.md +4 -1
- package/bin/create-job-forge.mjs +7 -0
- package/bin/job-forge.mjs +58 -0
- package/docs/ARCHITECTURE.md +2 -0
- package/docs/CUSTOMIZATION.md +26 -3
- package/docs/SETUP.md +6 -0
- package/iso/commands/job-forge.md +3 -0
- package/iso/instructions.md +4 -1
- package/package.json +9 -5
- package/scripts/telemetry.mjs +643 -0
- package/scripts/trace.mjs +469 -0
package/.cursor/rules/main.mdc
CHANGED
|
@@ -33,6 +33,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
33
33
|
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, `batch/tracker-additions/*.tsv`.
|
|
34
34
|
why: 2026-04-18 scan subagent returned 30 fabricated Greenhouse IDs in prose (plausible-looking, non-existent); orchestrator dispatched 30 downstream subagents that all 404'd. Subagents can hallucinate IDs, scores, and confirmation text — round-trip through a file or don't trust the value
|
|
35
35
|
|
|
36
|
+
- [H8] Never paste proxy values from `config/profile.yml` into `task` prompts, status text, or summaries. If a proxy is configured, tell the subagent exactly: "Proxy is configured; read `config/profile.yml` and pass its top-level `proxy:` object to every `geometra_connect` call." Do not transcribe `server`, `username`, `password`, or `bypass`, even if you just read them from disk.
|
|
37
|
+
why: a 2026-04-25 OpenCode trace showed raw proxy credentials copied into an apply subagent prompt; trace logs are local, but prompts must still avoid replicating secrets across subagent sessions
|
|
38
|
+
|
|
36
39
|
## Defaults
|
|
37
40
|
|
|
38
41
|
- [D1] Delegate to a subagent (`task`) only when the work involves repeated tool-heavy steps that bloat the cache prefix: applying to N≥2 jobs, batch scans hitting ≥3 companies, or any "apply to… / process pipeline / batch evaluate" user phrasing. Single-offer evals, dev work, file edits, `tracker` mode, single-URL checks, and one-shot questions stay inline.
|
|
@@ -58,7 +61,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
58
61
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
59
62
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
60
63
|
3. Read the active mode file [D3]; decide inline vs delegated work [D1].
|
|
61
|
-
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2].
|
|
64
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2], proxy prompt hygiene [H8].
|
|
62
65
|
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
63
66
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
64
67
|
7. Cross-check subagent facts against authoritative files [H7].
|
|
@@ -152,6 +152,9 @@ Step 3 — Pre-flight cleanup (once, before the loop)
|
|
|
152
152
|
Step 4 — Loop in rounds of 2 (Hard Limit #1)
|
|
153
153
|
for round in ceil(len(candidates) / 2):
|
|
154
154
|
pair = candidates[round*2 : round*2 + 2]
|
|
155
|
+
# If proxy is configured, do not paste proxy values into prompts.
|
|
156
|
+
# Say: "Proxy is configured; read config/profile.yml and pass its
|
|
157
|
+
# top-level proxy object to every geometra_connect call."
|
|
155
158
|
# Dispatch 1 or 2 task() calls in ONE message (never 3+)
|
|
156
159
|
task(subagent_type=<tier per AGENTS.md routing>, prompt=<apply prompt for pair[0]>)
|
|
157
160
|
task(subagent_type=<tier>, prompt=<apply prompt for pair[1]>) # only if pair has 2
|
package/AGENTS.md
CHANGED
|
@@ -28,6 +28,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
28
28
|
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, `batch/tracker-additions/*.tsv`.
|
|
29
29
|
why: 2026-04-18 scan subagent returned 30 fabricated Greenhouse IDs in prose (plausible-looking, non-existent); orchestrator dispatched 30 downstream subagents that all 404'd. Subagents can hallucinate IDs, scores, and confirmation text — round-trip through a file or don't trust the value
|
|
30
30
|
|
|
31
|
+
- [H8] Never paste proxy values from `config/profile.yml` into `task` prompts, status text, or summaries. If a proxy is configured, tell the subagent exactly: "Proxy is configured; read `config/profile.yml` and pass its top-level `proxy:` object to every `geometra_connect` call." Do not transcribe `server`, `username`, `password`, or `bypass`, even if you just read them from disk.
|
|
32
|
+
why: a 2026-04-25 OpenCode trace showed raw proxy credentials copied into an apply subagent prompt; trace logs are local, but prompts must still avoid replicating secrets across subagent sessions
|
|
33
|
+
|
|
31
34
|
## Defaults
|
|
32
35
|
|
|
33
36
|
- [D1] Delegate to a subagent (`task`) only when the work involves repeated tool-heavy steps that bloat the cache prefix: applying to N≥2 jobs, batch scans hitting ≥3 companies, or any "apply to… / process pipeline / batch evaluate" user phrasing. Single-offer evals, dev work, file edits, `tracker` mode, single-URL checks, and one-shot questions stay inline.
|
|
@@ -53,7 +56,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
53
56
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
54
57
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
58
|
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].
|
|
59
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2], proxy prompt hygiene [H8].
|
|
57
60
|
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
58
61
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
59
62
|
7. Cross-check subagent facts against authoritative files [H7].
|
package/CLAUDE.md
CHANGED
|
@@ -28,6 +28,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
28
28
|
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, `batch/tracker-additions/*.tsv`.
|
|
29
29
|
why: 2026-04-18 scan subagent returned 30 fabricated Greenhouse IDs in prose (plausible-looking, non-existent); orchestrator dispatched 30 downstream subagents that all 404'd. Subagents can hallucinate IDs, scores, and confirmation text — round-trip through a file or don't trust the value
|
|
30
30
|
|
|
31
|
+
- [H8] Never paste proxy values from `config/profile.yml` into `task` prompts, status text, or summaries. If a proxy is configured, tell the subagent exactly: "Proxy is configured; read `config/profile.yml` and pass its top-level `proxy:` object to every `geometra_connect` call." Do not transcribe `server`, `username`, `password`, or `bypass`, even if you just read them from disk.
|
|
32
|
+
why: a 2026-04-25 OpenCode trace showed raw proxy credentials copied into an apply subagent prompt; trace logs are local, but prompts must still avoid replicating secrets across subagent sessions
|
|
33
|
+
|
|
31
34
|
## Defaults
|
|
32
35
|
|
|
33
36
|
- [D1] Delegate to a subagent (`task`) only when the work involves repeated tool-heavy steps that bloat the cache prefix: applying to N≥2 jobs, batch scans hitting ≥3 companies, or any "apply to… / process pipeline / batch evaluate" user phrasing. Single-offer evals, dev work, file edits, `tracker` mode, single-URL checks, and one-shot questions stay inline.
|
|
@@ -53,7 +56,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
53
56
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
54
57
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
58
|
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].
|
|
59
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2], proxy prompt hygiene [H8].
|
|
57
60
|
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
58
61
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
59
62
|
7. Cross-check subagent facts against authoritative files [H7].
|
package/bin/create-job-forge.mjs
CHANGED
|
@@ -110,6 +110,13 @@ const consumerPkg = {
|
|
|
110
110
|
tokens: 'job-forge tokens',
|
|
111
111
|
'tokens:today': 'job-forge tokens --days 1',
|
|
112
112
|
'tokens:log': 'job-forge tokens --days 1 --append',
|
|
113
|
+
'trace:list': 'job-forge trace:list',
|
|
114
|
+
'trace:stats': 'job-forge trace:stats',
|
|
115
|
+
'trace:show': 'job-forge trace:show',
|
|
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',
|
|
113
120
|
// One command to pull the latest harness, companion plugin, and any
|
|
114
121
|
// locally-pinned MCP packages. npm update is a no-op on packages not
|
|
115
122
|
// in package.json, so listing @razroo/gmail-mcp + @geometra/mcp is
|
package/bin/job-forge.mjs
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* pdf Run generate-pdf.mjs
|
|
18
18
|
* sync-check Run cv-sync-check.mjs
|
|
19
19
|
* tokens Run scripts/token-usage-report.mjs
|
|
20
|
+
* trace:* Inspect local agent transcripts via iso-trace
|
|
21
|
+
* telemetry:* Summarize JobForge pipeline status from traces + tracker files
|
|
20
22
|
* sync Re-run the harness symlink sync (bin/sync.mjs)
|
|
21
23
|
* help, --help Show this message
|
|
22
24
|
*/
|
|
@@ -28,6 +30,7 @@ import { existsSync } from 'fs';
|
|
|
28
30
|
|
|
29
31
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
32
|
const PKG_ROOT = resolve(__dirname, '..');
|
|
33
|
+
const PROJECT_DIR = process.env.JOB_FORGE_PROJECT || process.cwd();
|
|
31
34
|
|
|
32
35
|
const commands = {
|
|
33
36
|
merge: 'merge-tracker.mjs',
|
|
@@ -52,6 +55,19 @@ const commands = {
|
|
|
52
55
|
'render-report-header': 'scripts/render-report-header.mjs',
|
|
53
56
|
};
|
|
54
57
|
|
|
58
|
+
const traceAliases = {
|
|
59
|
+
'trace:list': 'list',
|
|
60
|
+
'trace:stats': 'stats',
|
|
61
|
+
'trace:show': 'show',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const telemetryAliases = {
|
|
65
|
+
'telemetry:list': 'list',
|
|
66
|
+
'telemetry:status': 'status',
|
|
67
|
+
'telemetry:show': 'show',
|
|
68
|
+
'telemetry:watch': 'watch',
|
|
69
|
+
};
|
|
70
|
+
|
|
55
71
|
const [, , cmd, ...rest] = process.argv;
|
|
56
72
|
|
|
57
73
|
function printHelp() {
|
|
@@ -68,6 +84,14 @@ Commands:
|
|
|
68
84
|
pdf Generate ATS-optimized CV PDF from cv.md
|
|
69
85
|
sync-check Lint: verify cv.md and profile.yml are filled in
|
|
70
86
|
tokens Show opencode token usage and cost by session/day
|
|
87
|
+
trace Pass through to iso-trace (e.g. job-forge trace sources)
|
|
88
|
+
trace:list List recent local agent sessions (defaults: --since 7d --cwd project)
|
|
89
|
+
trace:stats Show trace stats (defaults: --since 7d --cwd project)
|
|
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
|
|
71
95
|
sync Re-create harness symlinks in the current project
|
|
72
96
|
|
|
73
97
|
Deterministic helpers (prefer these over LLM-derived values):
|
|
@@ -90,6 +114,10 @@ Pass --help after a command to see its own flags, e.g.:
|
|
|
90
114
|
job-forge merge --help
|
|
91
115
|
job-forge tokens --days 1
|
|
92
116
|
job-forge slugify "Anthropic, PBC"
|
|
117
|
+
job-forge trace:list --since 24h
|
|
118
|
+
job-forge trace:show ses_...
|
|
119
|
+
job-forge telemetry:status
|
|
120
|
+
job-forge telemetry:show ses_...
|
|
93
121
|
|
|
94
122
|
Project directory resolves to $JOB_FORGE_PROJECT or cwd.`);
|
|
95
123
|
}
|
|
@@ -99,6 +127,36 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
|
99
127
|
process.exit(0);
|
|
100
128
|
}
|
|
101
129
|
|
|
130
|
+
if (cmd === 'trace' || traceAliases[cmd]) {
|
|
131
|
+
const traceArgs = cmd === 'trace'
|
|
132
|
+
? (rest.length === 0 ? ['help'] : rest)
|
|
133
|
+
: [traceAliases[cmd], ...rest];
|
|
134
|
+
|
|
135
|
+
const scriptPath = join(PKG_ROOT, 'scripts/trace.mjs');
|
|
136
|
+
const result = spawnSync(process.execPath, [scriptPath, ...traceArgs], {
|
|
137
|
+
stdio: 'inherit',
|
|
138
|
+
cwd: PROJECT_DIR,
|
|
139
|
+
env: process.env,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
process.exit(result.status ?? 1);
|
|
143
|
+
}
|
|
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
|
+
|
|
102
160
|
const rel = commands[cmd];
|
|
103
161
|
if (!rel) {
|
|
104
162
|
console.error(`Unknown command: ${cmd}\n`);
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -203,6 +203,8 @@ Scripts maintain data consistency. In a consumer project they're invoked via the
|
|
|
203
203
|
| `generate-pdf.mjs` | `npx job-forge pdf` | Renders HTML to PDF via Geometra MCP (`geometra_generate_pdf`) or standalone Playwright/Chromium (`npx job-forge pdf <input.html> <output.pdf>`) |
|
|
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
|
+
| `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 |
|
|
206
208
|
| `tracker-lib.mjs` | _(library)_ | Shared helpers for reading/writing day-based tracker files — imported by merge/dedup/verify/normalize |
|
|
207
209
|
| `bin/sync.mjs` | `npx job-forge sync` | Creates the harness symlinks in a consumer project (also runs as `postinstall`) |
|
|
208
210
|
| `bin/create-job-forge.mjs` | `npx create-job-forge <dir>` | Scaffolds a new personal project |
|
package/docs/CUSTOMIZATION.md
CHANGED
|
@@ -98,13 +98,36 @@ Some forks use a **single** `data/applications.md` instead. That is fine if you
|
|
|
98
98
|
|
|
99
99
|
## Transcript observability (iso-trace)
|
|
100
100
|
|
|
101
|
-
To inspect real agent sessions locally (tool mix, redundant fetches, Geometra churn) without uploading transcripts, use Razroo's [`@razroo/iso-trace`](https://github.com/razroo/iso/tree/main/packages/iso-trace).
|
|
101
|
+
To inspect real agent sessions locally (tool mix, redundant fetches, Geometra churn) without uploading transcripts, use the `job-forge trace:*` commands. JobForge depends on Razroo's [`@razroo/iso-trace`](https://github.com/razroo/iso/tree/main/packages/iso-trace), so consumer projects do not need to install it separately.
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
Common commands default to OpenCode sessions for the current project and use a 7-day window:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx job-forge trace:list
|
|
107
|
+
npx job-forge trace:stats
|
|
108
|
+
npx job-forge trace:show <session-id-or-prefix>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Scaffolded projects also include npm aliases: `npm run trace:list`, `npm run trace:stats`, and `npm run trace:show -- <id>`.
|
|
112
|
+
|
|
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
|
+
|
|
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.
|
|
104
127
|
|
|
105
128
|
**Where Claude Code writes JSONL:** `~/.claude/projects/<encoded-cwd>/*.jsonl`.
|
|
106
129
|
|
|
107
|
-
**CLI
|
|
130
|
+
**Direct CLI fallback:** `npx -y @razroo/iso-trace@latest stats --source "$HOME/.claude/projects/<encoded-dir>/<session>.jsonl"`
|
|
108
131
|
|
|
109
132
|
**Performance:** `iso-trace list --cwd /path/to/repo` walks all of `~/.claude/projects` before filtering; on large machines prefer `stats --source <one.jsonl>` or the library's `discoverSessions({ roots: ["<one encoded project dir>"] })` (see the iso-trace README).
|
|
110
133
|
|
package/docs/SETUP.md
CHANGED
|
@@ -130,6 +130,12 @@ From your project root, these commands maintain the tracker and pipeline checks.
|
|
|
130
130
|
| Generate ATS-optimized CV PDF | `npx job-forge pdf` | `npm run pdf` |
|
|
131
131
|
| Setup lint (cv.md + profile.yml) | `npx job-forge sync-check` | `npm run sync-check` |
|
|
132
132
|
| Token usage report (from opencode SQLite DB) | `npx job-forge tokens` | `npm run tokens` |
|
|
133
|
+
| List recent OpenCode traces for this project | `npx job-forge trace:list` | `npm run trace:list` |
|
|
134
|
+
| Summarize trace tool/file/token usage | `npx job-forge trace:stats` | `npm run trace:stats` |
|
|
135
|
+
| Show one trace by session id/prefix | `npx job-forge trace:show <id>` | `npm run trace:show -- <id>` |
|
|
136
|
+
| List recent JobForge runs with outcomes/issues | `npx job-forge telemetry:list` | `npm run telemetry:list` |
|
|
137
|
+
| Show latest run status + pending TSVs | `npx job-forge telemetry:status` | `npm run telemetry:status` |
|
|
138
|
+
| Show one JobForge run by session id/prefix | `npx job-forge telemetry:show <id>` | `npm run telemetry:show -- <id>` |
|
|
133
139
|
| Re-create harness symlinks | `npx job-forge sync` | `npm run sync` |
|
|
134
140
|
| Build optional dashboard TUI (Go on `PATH`) | `(cd node_modules/job-forge/dashboard && go build .)` | `npm run build:dashboard` (harness repo only) |
|
|
135
141
|
|
|
@@ -155,6 +155,9 @@ Step 3 — Pre-flight cleanup (once, before the loop)
|
|
|
155
155
|
Step 4 — Loop in rounds of 2 (Hard Limit #1)
|
|
156
156
|
for round in ceil(len(candidates) / 2):
|
|
157
157
|
pair = candidates[round*2 : round*2 + 2]
|
|
158
|
+
# If proxy is configured, do not paste proxy values into prompts.
|
|
159
|
+
# Say: "Proxy is configured; read config/profile.yml and pass its
|
|
160
|
+
# top-level proxy object to every geometra_connect call."
|
|
158
161
|
# Dispatch 1 or 2 task() calls in ONE message (never 3+)
|
|
159
162
|
task(subagent_type=<tier per AGENTS.md routing>, prompt=<apply prompt for pair[0]>)
|
|
160
163
|
task(subagent_type=<tier>, prompt=<apply prompt for pair[1]>) # only if pair has 2
|
package/iso/instructions.md
CHANGED
|
@@ -28,6 +28,9 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
28
28
|
- [H7] Load-bearing facts passed to downstream subagents must originate from a file, not from prior subagent prose. Authoritative sources: `data/pipeline.md`, `data/scan-history.tsv`, `batch/scan-output-*.md`, `reports/{num}-*.md` with `**URL:**` / `**Score:**` headers, `batch/tracker-additions/*.tsv`.
|
|
29
29
|
why: 2026-04-18 scan subagent returned 30 fabricated Greenhouse IDs in prose (plausible-looking, non-existent); orchestrator dispatched 30 downstream subagents that all 404'd. Subagents can hallucinate IDs, scores, and confirmation text — round-trip through a file or don't trust the value
|
|
30
30
|
|
|
31
|
+
- [H8] Never paste proxy values from `config/profile.yml` into `task` prompts, status text, or summaries. If a proxy is configured, tell the subagent exactly: "Proxy is configured; read `config/profile.yml` and pass its top-level `proxy:` object to every `geometra_connect` call." Do not transcribe `server`, `username`, `password`, or `bypass`, even if you just read them from disk.
|
|
32
|
+
why: a 2026-04-25 OpenCode trace showed raw proxy credentials copied into an apply subagent prompt; trace logs are local, but prompts must still avoid replicating secrets across subagent sessions
|
|
33
|
+
|
|
31
34
|
## Defaults
|
|
32
35
|
|
|
33
36
|
- [D1] Delegate to a subagent (`task`) only when the work involves repeated tool-heavy steps that bloat the cache prefix: applying to N≥2 jobs, batch scans hitting ≥3 companies, or any "apply to… / process pipeline / batch evaluate" user phrasing. Single-offer evals, dev work, file edits, `tracker` mode, single-URL checks, and one-shot questions stay inline.
|
|
@@ -53,7 +56,7 @@ AI-powered job search pipeline: scans portals, evaluates offers, generates CVs v
|
|
|
53
56
|
1. Check `cv.md`, `profile.yml`, and `portals.yml`; onboard if any file is missing.
|
|
54
57
|
2. Pick and name the mode from **Routing** [D6]. No match → ask; do not guess.
|
|
55
58
|
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].
|
|
59
|
+
4. Prepare Geometra dispatches: cleanup [H3], dedupe [H2], location filter [D5], routing [D2], proxy prompt hygiene [H8].
|
|
57
60
|
5. Dispatch at most 2 tasks per round [H1]; wait for final outcomes, not just task ids [H5b].
|
|
58
61
|
6. Keep multi-job form-filling out of the orchestrator [H4].
|
|
59
62
|
7. Cross-check subagent facts against authoritative files [H7].
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "job-forge",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.11",
|
|
4
4
|
"description": "AI-powered job search pipeline built on opencode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,9 +18,13 @@
|
|
|
18
18
|
"tokens": "node scripts/token-usage-report.mjs",
|
|
19
19
|
"tokens:today": "node scripts/token-usage-report.mjs --days 1",
|
|
20
20
|
"tokens:log": "node scripts/token-usage-report.mjs --days 1 --append",
|
|
21
|
-
"trace:list": "
|
|
22
|
-
"trace:stats": "
|
|
23
|
-
"trace:show": "
|
|
21
|
+
"trace:list": "node bin/job-forge.mjs trace:list",
|
|
22
|
+
"trace:stats": "node bin/job-forge.mjs trace:stats",
|
|
23
|
+
"trace:show": "node bin/job-forge.mjs trace:show",
|
|
24
|
+
"telemetry:list": "node bin/job-forge.mjs telemetry:list",
|
|
25
|
+
"telemetry:status": "node bin/job-forge.mjs telemetry:status",
|
|
26
|
+
"telemetry:show": "node bin/job-forge.mjs telemetry:show",
|
|
27
|
+
"telemetry:watch": "node bin/job-forge.mjs telemetry:watch",
|
|
24
28
|
"plan": "iso plan .",
|
|
25
29
|
"lint:agentmd": "agentmd lint iso/instructions.md",
|
|
26
30
|
"lint:modes": "isolint lint modes/",
|
|
@@ -85,6 +89,7 @@
|
|
|
85
89
|
"node": ">=18"
|
|
86
90
|
},
|
|
87
91
|
"dependencies": {
|
|
92
|
+
"@razroo/iso-trace": "^0.4.0",
|
|
88
93
|
"playwright": "^1.58.1"
|
|
89
94
|
},
|
|
90
95
|
"devDependencies": {
|
|
@@ -93,7 +98,6 @@
|
|
|
93
98
|
"@razroo/iso-eval": "^0.4.0",
|
|
94
99
|
"@razroo/iso-harness": "^0.6.1",
|
|
95
100
|
"@razroo/iso-route": "^0.5.3",
|
|
96
|
-
"@razroo/iso-trace": "^0.4.0",
|
|
97
101
|
"@razroo/opencode-model-fallback": "^0.3.1"
|
|
98
102
|
}
|
|
99
103
|
}
|