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.
@@ -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
+ }
@@ -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`);