job-forge 2.14.30 → 2.14.32
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-paid.md +1 -1
- package/.cursor/rules/agent-general-paid.mdc +1 -1
- package/.cursor/rules/main.mdc +11 -5
- package/.opencode/agents/general-paid.md +1 -1
- package/.opencode/skills/job-forge.md +8 -0
- package/AGENTS.md +11 -5
- package/CLAUDE.md +11 -5
- package/README.md +9 -6
- package/bin/create-job-forge.mjs +10 -0
- package/bin/job-forge.mjs +68 -0
- package/docs/ARCHITECTURE.md +12 -4
- package/docs/CUSTOMIZATION.md +8 -0
- package/docs/README.md +1 -1
- package/docs/SETUP.md +4 -0
- package/iso/agents/general-paid.md +1 -1
- package/iso/commands/job-forge.md +8 -0
- package/iso/instructions.md +11 -5
- package/lib/jobforge-facts.mjs +178 -0
- package/lib/jobforge-score.mjs +212 -0
- package/modes/_shared.md +4 -3
- package/package.json +16 -1
- package/scripts/check-iso-smoke.mjs +1 -0
- package/scripts/facts.mjs +238 -0
- package/scripts/score.mjs +209 -0
- package/templates/facts.json +200 -0
- package/templates/migrations.json +14 -0
- package/templates/score.json +128 -0
- package/verify-pipeline.mjs +20 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"profiles": [
|
|
4
|
+
{
|
|
5
|
+
"name": "jobforge",
|
|
6
|
+
"description": "Canonical JobForge job-fit rubric. Agents choose dimension scores; iso-score owns weighted math, bands, and gates.",
|
|
7
|
+
"scale": {
|
|
8
|
+
"min": 1,
|
|
9
|
+
"max": 5,
|
|
10
|
+
"precision": 1
|
|
11
|
+
},
|
|
12
|
+
"dimensions": [
|
|
13
|
+
{
|
|
14
|
+
"id": "north_star",
|
|
15
|
+
"label": "North Star alignment",
|
|
16
|
+
"weight": 0.25,
|
|
17
|
+
"required": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "cv_match",
|
|
21
|
+
"label": "CV match",
|
|
22
|
+
"weight": 0.15,
|
|
23
|
+
"required": true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "seniority_fit",
|
|
27
|
+
"label": "Seniority fit",
|
|
28
|
+
"weight": 0.15,
|
|
29
|
+
"required": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "comp",
|
|
33
|
+
"label": "Comp estimate",
|
|
34
|
+
"weight": 0.1,
|
|
35
|
+
"required": true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "growth",
|
|
39
|
+
"label": "Growth trajectory",
|
|
40
|
+
"weight": 0.1,
|
|
41
|
+
"required": true
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "remote",
|
|
45
|
+
"label": "Remote quality",
|
|
46
|
+
"weight": 0.05,
|
|
47
|
+
"required": true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "company",
|
|
51
|
+
"label": "Company reputation",
|
|
52
|
+
"weight": 0.05,
|
|
53
|
+
"required": true
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "stack",
|
|
57
|
+
"label": "Tech stack modernity",
|
|
58
|
+
"weight": 0.05,
|
|
59
|
+
"required": true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "speed",
|
|
63
|
+
"label": "Speed to offer",
|
|
64
|
+
"weight": 0.05,
|
|
65
|
+
"required": true
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "culture",
|
|
69
|
+
"label": "Cultural signals",
|
|
70
|
+
"weight": 0.05,
|
|
71
|
+
"required": true
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"bands": [
|
|
75
|
+
{
|
|
76
|
+
"id": "strong",
|
|
77
|
+
"label": "Strong match",
|
|
78
|
+
"min": 4.5
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "apply",
|
|
82
|
+
"label": "Apply",
|
|
83
|
+
"min": 3.5
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"id": "apply_with_caveats",
|
|
87
|
+
"label": "Apply with caveats",
|
|
88
|
+
"min": 3
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "skip",
|
|
92
|
+
"label": "Skip",
|
|
93
|
+
"min": 1
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"gates": [
|
|
97
|
+
{
|
|
98
|
+
"id": "pdf",
|
|
99
|
+
"label": "Generate PDF",
|
|
100
|
+
"min": 3,
|
|
101
|
+
"blockOnMissingRequired": true,
|
|
102
|
+
"blockOnIssues": true
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "draft_answers",
|
|
106
|
+
"label": "Draft application answers",
|
|
107
|
+
"min": 3.5,
|
|
108
|
+
"blockOnMissingRequired": true,
|
|
109
|
+
"blockOnIssues": true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "apply",
|
|
113
|
+
"label": "Apply or queue application",
|
|
114
|
+
"min": 3,
|
|
115
|
+
"blockOnMissingRequired": true,
|
|
116
|
+
"blockOnIssues": true
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "strong",
|
|
120
|
+
"label": "Strong match",
|
|
121
|
+
"min": 4.5,
|
|
122
|
+
"requireBand": "strong",
|
|
123
|
+
"blockOnIssues": true
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
package/verify-pipeline.mjs
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* 9. Drift warning if states.yml ids differ from the built-in fallback list
|
|
19
19
|
* 10. Ledger file verifies if .jobforge-ledger/events.jsonl exists
|
|
20
20
|
* 11. Artifact index verifies if .jobforge-index.json exists
|
|
21
|
+
* 12. Fact set verifies if .jobforge-facts.json exists
|
|
21
22
|
*
|
|
22
23
|
* Run: node verify-pipeline.mjs (from repo root; same as npm run verify)
|
|
23
24
|
*/
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
} from './tracker-lib.mjs';
|
|
32
33
|
import { jobForgeLedgerPath, ledgerExists, verifyJobForgeLedger } from './lib/jobforge-ledger.mjs';
|
|
33
34
|
import { indexExists, jobForgeIndexPath, verifyJobForgeIndex } from './lib/jobforge-index.mjs';
|
|
35
|
+
import { factsExist, jobForgeFactsPath, verifyJobForgeFacts } from './lib/jobforge-facts.mjs';
|
|
34
36
|
import {
|
|
35
37
|
canonicalStatusValues,
|
|
36
38
|
formatContractIssues,
|
|
@@ -171,6 +173,22 @@ function verifyIndexIfPresent() {
|
|
|
171
173
|
}
|
|
172
174
|
}
|
|
173
175
|
|
|
176
|
+
function verifyFactsIfPresent() {
|
|
177
|
+
if (!factsExist(PROJECT_DIR)) {
|
|
178
|
+
ok('Fact set not initialized');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const result = verifyJobForgeFacts({ rebuild: false }, PROJECT_DIR);
|
|
182
|
+
for (const issue of result.issues) {
|
|
183
|
+
const msg = `facts: ${issue.kind}: ${issue.message}`;
|
|
184
|
+
if (issue.severity === 'error') error(msg);
|
|
185
|
+
else warn(msg);
|
|
186
|
+
}
|
|
187
|
+
if (result.ok) {
|
|
188
|
+
ok(`Fact set valid (${result.facts} facts at ${relative(PROJECT_DIR, jobForgeFactsPath(PROJECT_DIR))})`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
174
192
|
// --- Read entries ---
|
|
175
193
|
const { entries, source } = readAllEntries();
|
|
176
194
|
|
|
@@ -181,6 +199,7 @@ if (entries.length === 0) {
|
|
|
181
199
|
verifyStatesYamlDrift();
|
|
182
200
|
verifyLedgerIfPresent();
|
|
183
201
|
verifyIndexIfPresent();
|
|
202
|
+
verifyFactsIfPresent();
|
|
184
203
|
console.log('\n' + '='.repeat(50));
|
|
185
204
|
console.log(`📊 Pipeline Health: ${errors} errors, ${warnings} warnings`);
|
|
186
205
|
if (errors === 0 && warnings === 0) console.log('🟢 Pipeline is clean!');
|
|
@@ -317,6 +336,7 @@ if (boldScores === 0) ok('No bold in scores');
|
|
|
317
336
|
verifyStatesYamlDrift();
|
|
318
337
|
verifyLedgerIfPresent();
|
|
319
338
|
verifyIndexIfPresent();
|
|
339
|
+
verifyFactsIfPresent();
|
|
320
340
|
|
|
321
341
|
console.log('\n' + '='.repeat(50));
|
|
322
342
|
console.log(`📊 Pipeline Health: ${errors} errors, ${warnings} warnings`);
|