careerclaw-js 1.0.6 → 1.1.0
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/CHANGELOG.md +583 -494
- package/README.md +366 -330
- package/SKILL.md +331 -331
- package/dist/briefing.d.ts +14 -55
- package/dist/briefing.d.ts.map +1 -1
- package/dist/briefing.js +50 -69
- package/dist/briefing.js.map +1 -1
- package/dist/cli.d.ts +0 -19
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +45 -97
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/execution-context.d.ts +40 -0
- package/dist/execution-context.d.ts.map +1 -0
- package/dist/execution-context.js +42 -0
- package/dist/execution-context.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +33 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +55 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +71 -59
package/CHANGELOG.md
CHANGED
|
@@ -1,495 +1,584 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to careerclaw-js are documented here.
|
|
4
|
-
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
-
Versioning follows [Semantic Versioning](https://semver.org/).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## [Unreleased]
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## [1.0
|
|
14
|
-
|
|
15
|
-
###
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
(`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
###
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
###
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
`
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
`
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- `
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- `
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
- `
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
- `
|
|
382
|
-
- `
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
`
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
###
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
- `src/
|
|
430
|
-
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
- `src/
|
|
434
|
-
|
|
435
|
-
- `src/
|
|
436
|
-
|
|
437
|
-
- `src/tests/
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to careerclaw-js are documented here.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
Versioning follows [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## [1.1.0] - 2026-03-26
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `src/execution-context.ts` — dual execution-context architecture for CareerClaw
|
|
18
|
+
runtimes; `ClawOsExecutionContext` (trusted platform path, `verified: true`,
|
|
19
|
+
feature list passed from upstream entitlement) and `StandaloneExecutionContext`
|
|
20
|
+
(local CLI / direct package use with Gumroad license validation);
|
|
21
|
+
`CAREERCLAW_FEATURES` constant registry with four feature flags
|
|
22
|
+
(`LLM_OUTREACH_DRAFT`, `TAILORED_COVER_LETTER`, `RESUME_GAP_ANALYSIS`,
|
|
23
|
+
`TOPK_EXTENDED`); `createClawOsExecutionContext()` and
|
|
24
|
+
`createStandaloneExecutionContext()` factory functions;
|
|
25
|
+
`hasCareerClawFeature()` type-safe feature check helper;
|
|
26
|
+
`CareerClawFeatureKey` union type derived from `CAREERCLAW_FEATURES`
|
|
27
|
+
- `src/runtime.ts` — programmatic runtime wrappers providing the clean
|
|
28
|
+
import boundary for both ClawOS and standalone consumers;
|
|
29
|
+
`runCareerClawStandalone(input, options)` delegates to `runBriefing()` with
|
|
30
|
+
standalone license flow; `runCareerClawWithContext(input, context, options)`
|
|
31
|
+
delegates to `runBriefingWithContext()` with trusted platform context;
|
|
32
|
+
`resolveResumeIntelligence()` centralises resume-intel construction from
|
|
33
|
+
profile + optional resume text, eliminating duplicate logic across callers;
|
|
34
|
+
`CareerClawRunInput`, `CareerClawRunSupportOptions`, and
|
|
35
|
+
`CareerClawStandaloneRunOptions` interfaces for typed consumer APIs
|
|
36
|
+
- `src/index.ts` — public API barrel export; re-exports `models`, `briefing`,
|
|
37
|
+
`runtime`, `resume-intel`, `execution-context`, `license`, `tracking`, and
|
|
38
|
+
`sources` modules; enables `import { ... } from "careerclaw-js"` for all
|
|
39
|
+
public types and functions
|
|
40
|
+
- `src/tests/runtime.test.ts` — 4 integration tests covering the trust
|
|
41
|
+
boundary security matrix: standalone with Pro key (license validated via
|
|
42
|
+
Gumroad → LLM drafts active), standalone without Pro key (no license check →
|
|
43
|
+
template drafts only), ClawOS with `LLM_OUTREACH_DRAFT` feature (no Gumroad
|
|
44
|
+
call → LLM drafts active), ClawOS without feature (no Gumroad call → template
|
|
45
|
+
drafts only); mocks `checkLicense` and `enhanceDraft` to verify call isolation
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- `src/briefing.ts` — refactored from single `runBriefing()` entry point to
|
|
50
|
+
dual-mode architecture via internal strategy pattern; added
|
|
51
|
+
`runBriefingWithContext(profile, context, options)` as the trusted ClawOS
|
|
52
|
+
entry point; extracted `runBriefingInternal()` as the shared pipeline with
|
|
53
|
+
`InternalExecutionMode` discriminated union (`"standalone"` | `"clawos"`);
|
|
54
|
+
extracted `resolvePremiumDraftAccess(executionMode, resumeIntel)` to resolve
|
|
55
|
+
Pro activation per mode — standalone validates via `checkLicense()`, ClawOS
|
|
56
|
+
checks `tier === "pro"` + `hasCareerClawFeature(LLM_OUTREACH_DRAFT)`;
|
|
57
|
+
fixed unsafe `resumeIntel!` non-null assertion to safe `isProActive && resumeIntel`
|
|
58
|
+
guard; added `ContextBriefingOptions` interface (excludes `proKey`,
|
|
59
|
+
`licenseFetchFn`, `licenseCachePath` — not applicable in trusted mode);
|
|
60
|
+
removed inline JSDoc comments from `BriefingOptions` fields (types are
|
|
61
|
+
self-documenting)
|
|
62
|
+
- `src/cli.ts` — added `--version` / `-v` flag using `createRequire` to read
|
|
63
|
+
version from `package.json`; version check exits before any profile or config
|
|
64
|
+
loading; updated `printHelp()` to document the new flag; replaced direct
|
|
65
|
+
`runBriefing()` call with `runCareerClawStandalone()` from `runtime.ts`,
|
|
66
|
+
delegating resume-intel construction and option wiring to the runtime layer
|
|
67
|
+
- `package.json` — description updated to reflect dual-runtime identity
|
|
68
|
+
(ClawOS + standalone); `"clawos"` keyword added; `exports` map added with
|
|
69
|
+
three subpath entries: `"."` (main library, `dist/index.js`), `"./cli"`
|
|
70
|
+
(CLI entry, `dist/cli.js`), `"./package.json"` (self-reference for
|
|
71
|
+
`createRequire` version reads)
|
|
72
|
+
- `README.md` — full rewrite aligned with dual execution-context architecture;
|
|
73
|
+
added [ClawOS](https://clawoshq.com/) links throughout; added
|
|
74
|
+
[ClawHub](https://clawhub.ai/) and [OpenClaw](https://openclaw.org/)
|
|
75
|
+
references for standalone skill distribution; split Pro pricing into two
|
|
76
|
+
channels (ClawOS $9/month recommended, Standalone $39 lifetime via Gumroad);
|
|
77
|
+
added programmatic integration examples for both `runCareerClawWithContext()`
|
|
78
|
+
(with `createClawOsExecutionContext()`) and `runCareerClawStandalone()`;
|
|
79
|
+
added `--version` flag to CLI options; updated project structure tree with
|
|
80
|
+
`execution-context.ts`, `index.ts`, and `runtime.ts`
|
|
81
|
+
|
|
82
|
+
### Security
|
|
83
|
+
|
|
84
|
+
- ClawOS execution path never touches Gumroad — entitlement is resolved
|
|
85
|
+
upstream by the platform; the `ClawOsExecutionContext.verified: true`
|
|
86
|
+
literal type enforces that only pre-verified contexts are accepted
|
|
87
|
+
- Standalone execution path always validates through `checkLicense()` when a
|
|
88
|
+
`proKey` is provided — no bypass flag exists on the public CLI
|
|
89
|
+
- `resumeIntel!` non-null assertion removed from the draft enhancement call;
|
|
90
|
+
replaced with an explicit `isProActive && resumeIntel` guard to prevent
|
|
91
|
+
runtime errors if `resumeIntel` is undefined
|
|
92
|
+
|
|
93
|
+
### Notes
|
|
94
|
+
|
|
95
|
+
274 tests across 17 files, all passing. `tsc --noEmit` clean.
|
|
96
|
+
No new production dependencies. The `exports` map in `package.json` makes
|
|
97
|
+
the package a proper ESM citizen with subpath resolution for ClawOS
|
|
98
|
+
direct-import consumption.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## [1.0.6] - 2026-03-19
|
|
103
|
+
|
|
104
|
+
### Fixed
|
|
105
|
+
|
|
106
|
+
- Triggered by the fast-xml-parser 5.5.7, upgrade (CVE-2026-33349),
|
|
107
|
+
which Entity Expansion Limits Bypassed When Set to Zero Due to JavaScript
|
|
108
|
+
Falsy Evaluation in fast-xml-parser
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## [1.0.5] - 2026-03-18
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- Fixed hex and decimal numeric HTML entities (e.g. `/`, `/`) leaking
|
|
117
|
+
undecoded into job titles, descriptions, and outreach drafts
|
|
118
|
+
(`src/adapters/remoteok.ts`). Added generic catch-all decoding for both
|
|
119
|
+
`&#xHH;` and `&#DD;` forms before the named-entity block in `stripHtml`.
|
|
120
|
+
Triggered by the fast-xml-parser v5 upgrade (CVE-2026-26278), which stopped
|
|
121
|
+
silently pre-decoding entities inside CDATA content that v4 had handled
|
|
122
|
+
transparently.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## [1.0.4] - 2026-03-08
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
- Runtime check replaced — no more auto-install, just a non-blocking update nudge
|
|
130
|
+
- Write-failure gate added in Step 3
|
|
131
|
+
- Resume write failed row added to error table
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## [1.0.3] - 2026-03-08
|
|
136
|
+
|
|
137
|
+
### Fixed
|
|
138
|
+
- Agent no longer presents a multi-question setup form when profile is missing — redirects to resume upload only
|
|
139
|
+
- Agent no longer invents career frameworks, phases, or methodologies not defined in this file
|
|
140
|
+
- Agent no longer enters consultant mode during first-time setup
|
|
141
|
+
|
|
142
|
+
### Changed
|
|
143
|
+
- Rewrote SKILL.md from persona/behavior narrative format to numbered runbook format
|
|
144
|
+
- Added hard Rules section at top with six explicit prohibitions
|
|
145
|
+
- Added profile existence check (Step 1) as hard gate before any command runs
|
|
146
|
+
- Setup flow now asks one question at a time — work mode first, salary second
|
|
147
|
+
- Removed Agent Persona, Behavior 1, and Behavior 2 sections entirely
|
|
148
|
+
- Bumped runtime self-healing check expected version to 1.0.3
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## [1.0.2] - 2026-03-07
|
|
153
|
+
|
|
154
|
+
### Fixed
|
|
155
|
+
- Behavior 2 (Strategic Gap Closing) no longer fires during First-Time Setup.
|
|
156
|
+
The agent was entering consultant mode after resume intake and ending setup
|
|
157
|
+
with open-ended targeting questions instead of proceeding to the first briefing.
|
|
158
|
+
|
|
159
|
+
### Changed
|
|
160
|
+
- Added explicit activation gate to Behavior 2: only applies after setup is
|
|
161
|
+
complete and only when the user asks a listed trigger phrase.
|
|
162
|
+
- Step 2 of First-Time Setup now specifies a strict exit condition: collect
|
|
163
|
+
work mode and salary floor, then proceed directly to Step 3 with no
|
|
164
|
+
analysis, strategy suggestions, or targeting options.
|
|
165
|
+
- Added three entries to "What Not to Do" to reinforce setup boundaries.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## [1.0.1] - 2026-03-06
|
|
170
|
+
|
|
171
|
+
### Changed
|
|
172
|
+
- Hardened the public `SKILL.md` contract for ClawHub/OpenClaw deployment.
|
|
173
|
+
- Standardized runtime behavior to a single install/execute approach:
|
|
174
|
+
- self-healing install with `npm install -g careerclaw-js@"$EXPECTED"`
|
|
175
|
+
- direct execution with `careerclaw-js ...`
|
|
176
|
+
- Updated required runtime bins to match the Node/npm execution path.
|
|
177
|
+
- Scoped CareerClaw behavior more clearly as an invoked skill instead of a session-wide assistant.
|
|
178
|
+
- Simplified first-run onboarding around canonical `.careerclaw/resume.txt` handling.
|
|
179
|
+
- Reduced first-run friction by keeping setup resume-first and minimizing follow-up questions.
|
|
180
|
+
|
|
181
|
+
### Improved
|
|
182
|
+
- Restored Strategic Gap Closing behavior so CareerClaw can act more like a practical career consultant when the fit is imperfect.
|
|
183
|
+
- Improved recommendation tone and guidance for fatal, acceptable, and bridgeable gaps.
|
|
184
|
+
- Cleaned up Pro activation flow so premium setup is only introduced when it is actually needed.
|
|
185
|
+
- Restored the public Gumroad purchase link for CareerClaw Pro while keeping internal product IDs out of user-facing setup.
|
|
186
|
+
|
|
187
|
+
### Removed
|
|
188
|
+
- Removed internal Gumroad product ID exposure from the public skill surface.
|
|
189
|
+
- Removed Python compatibility messaging from `SKILL.md` to keep the public skill contract focused on the current Node-based experience.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## [1.0.0] — 2026-03-06
|
|
194
|
+
|
|
195
|
+
### Added
|
|
196
|
+
|
|
197
|
+
- `SKILL.md` full rewrite (Phase 12): Agent Persona section; zero-config resume
|
|
198
|
+
intake; Daily Stand-up behavior (reads `tracking.json` on session start,
|
|
199
|
+
surfaces still-live and undrafted jobs); Strategic Gap Closing (coach tone
|
|
200
|
+
for matches with gaps > 0.6 score); Sunday Night Strategy (first weekday of
|
|
201
|
+
month = HN priority, Sunday evening prompt, Monday/Friday timing context);
|
|
202
|
+
Tier-1 upsell trigger (Google, Meta, Apple, Stripe, Airbnb, Netflix);
|
|
203
|
+
Free vs Pro comparison table; `optionalEnv` frontmatter for all 12 env vars
|
|
204
|
+
- `RELEASE_CHECKLIST.md` — pre-publish gate, npm publish steps, VirusTotal
|
|
205
|
+
scan instructions, OpenClaw test gate, ClawHub submission checklist
|
|
206
|
+
|
|
207
|
+
### Changed
|
|
208
|
+
|
|
209
|
+
- `src/llm-enhance.ts` — OpenAI dual-transport support: `gpt-4o` family uses
|
|
210
|
+
`/v1/chat/completions` with `max_completion_tokens`; newer models (gpt-5.x+)
|
|
211
|
+
use `/v1/responses` with `max_output_tokens`; transport auto-detected via
|
|
212
|
+
`defaultOpenAITransport(model)` and injectable per `ChainCandidate`;
|
|
213
|
+
`SYSTEM_PROMPT` rewritten with Bridge Sentence method as core doctrine,
|
|
214
|
+
250/300-word hard limits, 22 banned phrases by name; `buildPrompt()` updated
|
|
215
|
+
with explicit word limit and Bridge Sentence paragraph-level instruction
|
|
216
|
+
- `src/config.ts` — `CAREERCLAW_DIR` empty-string guard: `??` replaced with
|
|
217
|
+
`.trim().length > 0` check so blank `CAREERCLAW_DIR=` in `.env` correctly
|
|
218
|
+
falls back to `.careerclaw/`
|
|
219
|
+
- `scripts/smoke_llm.ts` — Pro key section now calls `checkLicense()` live
|
|
220
|
+
against Gumroad when both keys are set; stale "not yet implemented" message
|
|
221
|
+
removed; Polar.sh URL replaced with Gumroad URL
|
|
222
|
+
- `README.md` — Polar.sh references replaced with Gumroad; CLI commands
|
|
223
|
+
corrected (no `briefing` subcommand); `--resume-pdf` removed (not
|
|
224
|
+
implemented); env vars table updated; roadmap updated through Phase 13
|
|
225
|
+
|
|
226
|
+
### Notes
|
|
227
|
+
|
|
228
|
+
270 tests across 16 files, all passing. `tsc --noEmit` clean.
|
|
229
|
+
No new production dependencies. First ClawHub-ready release.
|
|
230
|
+
OpenAI transport validated against gpt-4o-mini (chat) and gpt-5.2 (responses)
|
|
231
|
+
in live smoke testing.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## [0.11.0] — 2026-03-05
|
|
236
|
+
|
|
237
|
+
### Added
|
|
238
|
+
|
|
239
|
+
- `src/license.ts` — `checkLicense(key, options?)` → `Promise<LicenseResult>`:
|
|
240
|
+
Gumroad Pro license validation with 7-day offline cache; raw key never
|
|
241
|
+
written to disk — only `sha256(key)` cached; `{ valid: false, source: "none" }`
|
|
242
|
+
returned immediately when `CAREERCLAW_GUMROAD_PRODUCT_ID` is unset so Free
|
|
243
|
+
tier users are unaffected; `fetchFn` and `cachePath` injectable for offline tests
|
|
244
|
+
- `src/tests/license.test.ts` — 12 offline tests covering the missing product ID
|
|
245
|
+
guard, fresh/stale/missing/wrong-key cache branches, all Gumroad API response
|
|
246
|
+
variants (success, refunded, chargebacked, 404, 500), never-throws invariant,
|
|
247
|
+
and hash safety (raw key must not appear in cache file)
|
|
248
|
+
|
|
249
|
+
### Changed
|
|
250
|
+
|
|
251
|
+
- `src/briefing.ts` — bare `proKey` presence check replaced with
|
|
252
|
+
`await checkLicense(proKey)`; `isProActive` is now driven by
|
|
253
|
+
`licenseResult.valid`; `BriefingOptions` gains `licenseFetchFn` and
|
|
254
|
+
`licenseCachePath` for test injection
|
|
255
|
+
- `src/config.ts` — added `GUMROAD_PRODUCT_ID`, `GUMROAD_API_BASE`,
|
|
256
|
+
`LICENSE_CACHE_TTL_MS` (7 days in ms); `POLAR_PRODUCT_SLUG` and
|
|
257
|
+
`POLAR_API_BASE` retained and marked `@deprecated` with
|
|
258
|
+
`TODO: Phase 11-Polar` migration comment
|
|
259
|
+
- `.env.example` — Pro purchase URL updated to Gumroad;
|
|
260
|
+
`CAREERCLAW_GUMROAD_PRODUCT_ID=` added with dashboard instructions
|
|
261
|
+
|
|
262
|
+
### Security
|
|
263
|
+
|
|
264
|
+
- Raw license key is never written to disk; only `sha256(key)` is persisted
|
|
265
|
+
- Gumroad validation uses `increment_uses_count=false` — validation calls
|
|
266
|
+
do not consume customer usage quota
|
|
267
|
+
|
|
268
|
+
### Notes
|
|
269
|
+
|
|
270
|
+
270 tests across 16 files, all passing. `tsc --noEmit` clean.
|
|
271
|
+
No new production dependencies. Polar migration path preserved via
|
|
272
|
+
`@deprecated` constants and `TODO: Phase 11-Polar` comment in `config.ts`.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## [0.10.0] — 2026-03-05
|
|
277
|
+
|
|
278
|
+
### Added
|
|
279
|
+
|
|
280
|
+
- `src/llm-enhance.ts` — `enhanceDraft(job, profile, resumeIntel, draft, gapKeywords, options)`:
|
|
281
|
+
Pro tier LLM-powered outreach draft generation; parses `LLM_CHAIN` into a left-to-right failover
|
|
282
|
+
list; per-candidate retry loop up to `LLM_MAX_RETRIES`; circuit breaker opens after
|
|
283
|
+
`LLM_CIRCUIT_BREAKER_FAILS` consecutive failures; `_chainOverride` for offline testing
|
|
284
|
+
- `src/tests/llm-enhance.test.ts` — 12 offline tests covering Anthropic path, OpenAI path,
|
|
285
|
+
HTTP error fallback, unparseable response fallback, never-throws invariant, circuit breaker
|
|
286
|
+
call-count bounds, privacy (raw resume text must not appear in outbound request payload),
|
|
287
|
+
and empty-chain no-op
|
|
288
|
+
|
|
289
|
+
### Changed
|
|
290
|
+
|
|
291
|
+
- `src/briefing.ts` — `BriefingOptions` gains `resumeIntel?: ResumeIntelligence`,
|
|
292
|
+
`proKey?: string`, `enhanceFetchFn?`; draft stage converted to `async`; calls `enhanceDraft()`
|
|
293
|
+
per match when `proKey` is set — falls back to deterministic baseline on any LLM failure
|
|
294
|
+
- `src/cli.ts` — calls `buildResumeIntelligence()` after resume load; passes `resumeIntel` and
|
|
295
|
+
`PRO_KEY` to `runBriefing()`; Pro enhancement path is now live from the CLI
|
|
296
|
+
|
|
297
|
+
### Security
|
|
298
|
+
|
|
299
|
+
- LLM prompt contains only extracted keyword signals (`impact_signals` ≤ 12 tokens,
|
|
300
|
+
`gap_keywords` ≤ 6 tokens) — raw resume text and `resume_summary` are never sent to
|
|
301
|
+
any external API
|
|
302
|
+
|
|
303
|
+
### Notes
|
|
304
|
+
|
|
305
|
+
258 tests across 15 files, all passing. `tsc --noEmit` clean. No new production dependencies.
|
|
306
|
+
License validation (`CAREERCLAW_PRO_KEY` checked against Gumroad) is deferred to Phase 11 (v0.11.0) —
|
|
307
|
+
`proKey` is trusted by presence only in this version.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## [0.8.1] — 2026-03-04
|
|
312
|
+
|
|
313
|
+
### Fixed
|
|
314
|
+
|
|
315
|
+
- **Dentist problem**: replaced additive composite score with a multiplicative model (`total = sqrt(keyword) × qualityBase`);
|
|
316
|
+
zero keyword overlap now always produces a score of 0.0 regardless of metadata alignment — irrelevant jobs can no longer float to the
|
|
317
|
+
top on neutral dimension scores
|
|
318
|
+
- Signal gate added to `rankJobs()`: jobs with keyword score below `minKeywordScore` (default: 0.01) are hard-filtered before ranking
|
|
319
|
+
- `matched_keywords` and `gap_keywords` were hardcoded empty in `engine.ts`; now wired from `compositeScore()` output
|
|
320
|
+
- HTML entity `/` (and all `&#x[hex];` sequences) now decoded in `stripHtml()` — fixes `ML/AI` appearing in HN job titles and
|
|
321
|
+
gap tokens
|
|
322
|
+
- `stripHtml()` now applied to parsed HN job title and company name (previously body text only)
|
|
323
|
+
- Contraction tokens (`i'm`, `i've`, `don't`, etc.) added to `STOPWORDS` — eliminates noise in gap keyword output
|
|
324
|
+
|
|
325
|
+
### Changed
|
|
326
|
+
|
|
327
|
+
- `MatchBreakdown` field names renamed: `keyword_score → keyword`, `experience_score → experience`, `salary_score → salary`,
|
|
328
|
+
`work_mode_score → work_mode`
|
|
329
|
+
- `compositeScore()` return type extended: now includes `matched` and `gaps` string arrays alongside `total` and `breakdown`
|
|
330
|
+
- Default LLM model updated: `claude-sonnet-4-20250514` → `claude-haiku-4-5-20251001`
|
|
331
|
+
- `scripts/smoke_briefing.ts` refactored to multi-profile mode; select profile via `PROFILE=0|1|2` env var
|
|
332
|
+
|
|
333
|
+
### Added
|
|
334
|
+
|
|
335
|
+
- `.env.example` — full credential reference (OpenClaw gateway, agent LLM keys, Pro license, draft enhancement keys, failover chain config)
|
|
336
|
+
- `SECURITY.md` — local-first security architecture, credential handling policy, external network call inventory, LLM data disclosure
|
|
337
|
+
- `src/config.ts`: `LLM_ANTHROPIC_KEY`, `LLM_OPENAI_KEY`, `LLM_CHAIN`, `LLM_MAX_RETRIES`, `LLM_CIRCUIT_BREAKER_FAILS`
|
|
338
|
+
- `scripts/smoke_llm.ts` — LLM connectivity and Pro key smoke test; `npm run smoke:llm`
|
|
339
|
+
|
|
340
|
+
### Notes
|
|
341
|
+
|
|
342
|
+
234 tests across 13 files, all passing. No new production dependencies.
|
|
343
|
+
`MatchBreakdown` rename is a breaking internal change — no public API consumers exist prior to the CLI (Phase 9).
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## [0.8.0] — 2026-03-04
|
|
348
|
+
|
|
349
|
+
### Added
|
|
350
|
+
|
|
351
|
+
- `src/briefing.ts` — `runBriefing(profile, options)`: end-to-end pipeline orchestrator; four timed stages (fetch, rank, draft,
|
|
352
|
+
persist); skill-first design — profile is a parameter, never loaded from disk; `fetchFn` and `repo` are injectable for testing; dry-run
|
|
353
|
+
suppresses all writes while keeping counts accurate; catastrophic fetch failure returns empty result rather than throwing;
|
|
354
|
+
`run_id` generated via `crypto.randomUUID()` (Node built-in); `version` read from package.json at runtime via `createRequire`
|
|
355
|
+
- `BriefingResult` interface added to `src/models.ts` — stable JSON output schema for OpenClaw/ClawHub agent consumption: `run`,
|
|
356
|
+
`matches`, `drafts`, `tracking`, `dry_run`
|
|
357
|
+
- `src/tests/briefing.test.ts` — 17 integration tests; all offline via stubbed `fetchFn` and `tmpdir`-backed `TrackingRepository`
|
|
358
|
+
|
|
359
|
+
### Fixed
|
|
360
|
+
|
|
361
|
+
- `draftOutreach()` and `upsertEntries()` were being passed `ScoredJob` where `NormalizedJob` was required; `ScoredJob` wraps `NormalizedJob`
|
|
362
|
+
as `.job` and does not extend it — both callsites corrected to unwrap `.job`; corresponding test assertion corrected from
|
|
363
|
+
`scored.job_id` to `scored.job.job_id`
|
|
364
|
+
|
|
365
|
+
### Notes
|
|
366
|
+
|
|
367
|
+
243 tests across 13 files, all passing. No new dependencies. The pipeline is now end-to-end complete. Every module from Phase 1 through
|
|
368
|
+
Phase 7 is wired into a single callable function. Phase 9 (CLI entry point) will expose `runBriefing()` as an executable with `--dry-run`,
|
|
369
|
+
`--top-k`, and `--json` flags, matching the Python careerclaw CLI surface.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## [0.7.0] — 2026-03-04
|
|
374
|
+
|
|
375
|
+
### Added
|
|
376
|
+
|
|
377
|
+
- `src/tracking.ts` — `TrackingRepository` class managing two runtime files under `.careerclaw/`:
|
|
378
|
+
- `tracking.json` — keyed object of `TrackingEntry` records; new jobs saved with status `"saved"`; re-encountered jobs have
|
|
379
|
+
`last_seen_at` and `updated_at` refreshed, all other fields (including user-set status) preserved; one disk write per
|
|
380
|
+
`upsertEntries()` call regardless of batch size
|
|
381
|
+
- `runs.jsonl` — append-only newline-delimited JSON log; one `BriefingRun` per line via `appendRun()`
|
|
382
|
+
- Constructor accepts `trackingPath`, `runsPath`, and `dryRun` overrides; defaults from `config.ts`
|
|
383
|
+
- `load()` returns empty store on a missing or corrupt file — no crash
|
|
384
|
+
- `ensureDir()` creates parent directory recursively on first writing
|
|
385
|
+
- `upsertEntries()` returns accurate `{ created, already_present }` counts even in dry-run mode
|
|
386
|
+
- `ScoredJob?` parameter on `upsertEntries()` reserved for Phase 8 score snapshot attachment
|
|
387
|
+
- `src/tests/tracking.test.ts` — 23 unit tests; per-test isolated `tmpdir` directories; covers load, upsert (new + re-encounter),
|
|
388
|
+
disk writes, JSONL append, and dry-run suppression
|
|
389
|
+
|
|
390
|
+
### Notes
|
|
391
|
+
|
|
392
|
+
226 tests across 12 files, all passing. No new dependencies. The `TrackingRepository` is the last infrastructure module before the
|
|
393
|
+
Phase 8 briefing orchestrator wires everything into the full pipeline.
|
|
394
|
+
Dry-run mode is a first-class concern throughout: all writing paths are suppressed, all read and count paths remain fully functional, matching
|
|
395
|
+
the Python careerclaw `--dry-run` behaviour.
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## [0.6.0] — 2026-03-04
|
|
400
|
+
|
|
401
|
+
### Added
|
|
402
|
+
|
|
403
|
+
- `src/drafting.ts` — `draftOutreach(job, profile, matchedKeywords)`:
|
|
404
|
+
deterministic outreach email generator; subject line follows `Interest in {title} at {company}` format; body inserts experience
|
|
405
|
+
clause (years or "extensive experience" fallback), up to 3 matched keywords formatted as natural language, and 3 fixed
|
|
406
|
+
reliability/collaboration/instrumentation bullet highlights; word count 161–168 words depending on a keyword path, inside 150–250 word
|
|
407
|
+
spec; `llm_enhanced: false` always; `formatList()` helper for natural-language list formatting
|
|
408
|
+
- `src/tests/drafting.test.ts` — 20 unit tests
|
|
409
|
+
|
|
410
|
+
### Fixed
|
|
411
|
+
|
|
412
|
+
- Deterministic template body was 127 words on the first pass — below the 150-word MVP spec floor; fixed by expanding opening and closing
|
|
413
|
+
paragraphs; both keyword and fallback paths re-verified at 161 and 168 words respectively
|
|
414
|
+
|
|
415
|
+
### Notes
|
|
416
|
+
|
|
417
|
+
203 tests across 11 files, all passing. No new dependencies. `llm_enhanced` is always false in this phase — LLM enhancement
|
|
418
|
+
(Phase 7+) will set this flag to true when the Pro key is configured and the call succeeds. The deterministic template remains the permanent
|
|
419
|
+
fallback for the Free tier and for LLM failure scenarios.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## [0.5.0] — 2026-03-04
|
|
424
|
+
|
|
425
|
+
### Added
|
|
426
|
+
|
|
427
|
+
- `src/requirements.ts` — `extractJobRequirements(job)`: tokenizes job title and description into a deduplicated keyword and phrase corpus for
|
|
428
|
+
use as the job-side input to gap analysis
|
|
429
|
+
- `src/resume-intel.ts` — `buildResumeIntelligence(params)`:
|
|
430
|
+
section-aware keyword/phrase extraction across skills (weight 1.0), summary + target_roles (weight 0.8), and optional resume_text (weight
|
|
431
|
+
0.6); per-keyword weight is the max across sections; `impact_signals` are keywords with weight >= 0.8; `source` flag indicates which inputs
|
|
432
|
+
contributed; PR-E fix (skills injection) baked in from day one
|
|
433
|
+
- `src/gap.ts` — `gapAnalysis(intel, job)`: weighted `fit_score` (sum of matched keyword_weights / job keyword count), `fit_score_unweighted`
|
|
434
|
+
(Jaccard), `signals` (resume ∩ job), `gaps` (job − resume), and top-5 `summary` for display
|
|
435
|
+
- `JobRequirements`, `ResumeIntelligence`, `GapAnalysisResult` interfaces added to `src/models.ts`; `ResumeIntelligence` schema is
|
|
436
|
+
JSON-compatible with Python careerclaw output
|
|
437
|
+
- `src/tests/resume-intel.test.ts` — 19 unit tests
|
|
438
|
+
- `src/tests/gap.test.ts` — 16 unit tests
|
|
439
|
+
|
|
440
|
+
### Fixed
|
|
441
|
+
|
|
442
|
+
- Added `"am"` to `STOPWORDS` in `src/core/text-processing.ts` — missed from an initial set alongside `"is"`, `"are"`, `"was"`, `"were"`, `"be"`;
|
|
443
|
+
caught by resume-intel stopword filter test
|
|
444
|
+
|
|
445
|
+
### Notes
|
|
446
|
+
|
|
447
|
+
183 tests across 10 files, all passing. No new dependencies. The `fit_score` weighted formula is identical to the Python careerclaw
|
|
448
|
+
implementation: skills listed in UserProfile. Skills receive weight 1.0 and will never appear as gaps. The practical fit_score ceiling against
|
|
449
|
+
real job postings is ~50% due to company names and location tokens in the denominator.
|
|
450
|
+
|
|
451
|
+
### Future Work
|
|
452
|
+
|
|
453
|
+
- CorpusCache: Entropy-based token filtering (IDF) to suppress tokens that appear in >80% of fetched jobs. Gated behind corpus_size >= 50.
|
|
454
|
+
Planned for a future release after job tracking accumulates sufficient data.
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## [0.4.0] — 2026-03-04
|
|
459
|
+
|
|
460
|
+
### Added
|
|
461
|
+
|
|
462
|
+
- `src/matching/scoring.ts` — four pure scoring functions:
|
|
463
|
+
`scoreKeyword()` (Jaccard token overlap, returns matched and gap keyword lists), `scoreExperience()` (clamped linear user/job years ratio),
|
|
464
|
+
`scoreSalary()` (proportional against a user minimum),
|
|
465
|
+
`scoreWorkMode()` (exact=1.0, hybrid=0.5 partial, mismatch=0.0);
|
|
466
|
+
`compositeScore()` with `WEIGHTS` (keyword=0.50, experience=0.20, salary=0.15, work_mode=0.15)
|
|
467
|
+
- `src/matching/engine.ts` — `rankJobs(jobs, profile, topK)` scores all jobs, sorts descending by composite score, returns top-K `ScoredJob[]`
|
|
468
|
+
with full breakdown and keyword lists; scores rounded to 4 d.p.
|
|
469
|
+
- `src/matching/index.ts` — barrel export for matching public API
|
|
470
|
+
- `src/tests/matching.scoring.test.ts` — 36 unit tests
|
|
471
|
+
- `src/tests/matching.engine.test.ts` — 10 end-to-end tests using real model types
|
|
472
|
+
|
|
473
|
+
### Notes
|
|
474
|
+
|
|
475
|
+
148 tests across 8 files, all passing. No new dependencies. Neutral score (0.5) is used for all null data cases, so missing job fields
|
|
476
|
+
neither reward nor penalize the composite — consistent with Python careerclaw behavior. Gap keywords from `scoreKeyword()` feed directly
|
|
477
|
+
into Phase 5 gap analysis.
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## [0.3.0] — 2026-03-04
|
|
482
|
+
|
|
483
|
+
### Added
|
|
484
|
+
|
|
485
|
+
- `src/sources.ts` — source aggregation layer: `fetchAllJobs()` runs both
|
|
486
|
+
adapters concurrently with per-source error isolation; `deduplicate()`
|
|
487
|
+
removes duplicate `job_id` entries (first-seen wins); returns `FetchResult`
|
|
488
|
+
with job list, per-source counts, and error map for run instrumentation
|
|
489
|
+
- `src/core/text-processing.ts` — shared text processing library:
|
|
490
|
+
`STOPWORDS` (English function words and full PR-E recruitment boilerplate set),
|
|
491
|
+
`SECTION_WEIGHTS` (skills=1.0, summary=0.8, experience=0.6, education=0.4),
|
|
492
|
+
`tokenize()`, `tokenizeUnique()`, `extractPhrases()`,
|
|
493
|
+
`extractPhrasesFromText()`, `tokenOverlap()`, `matchedTokens()`,
|
|
494
|
+
`gapTokens()`
|
|
495
|
+
- `src/tests/text-processing.test.ts` — 34 unit tests
|
|
496
|
+
- `src/tests/sources.test.ts` — 10 unit tests (ESM-safe adapter stubs via
|
|
497
|
+
`vi.doMock()` + `vi.resetModules()`; no network)
|
|
498
|
+
|
|
499
|
+
### Notes
|
|
500
|
+
|
|
501
|
+
102 tests across 6 files, all passing. No new production dependencies.
|
|
502
|
+
`SECTION_WEIGHTS` is defined here and will be consumed by resume intelligence
|
|
503
|
+
in Phase 5. The `FetchResult.errors` map feeds into `BriefingRun.sources`
|
|
504
|
+
instrumentation in Phase 8.
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## [0.2.0] — 2026-03-03
|
|
509
|
+
|
|
510
|
+
### Added
|
|
511
|
+
|
|
512
|
+
- `src/adapters/remoteok.ts` — RemoteOK RSS adapter; parses RSS XML into
|
|
513
|
+
`NormalizedJob[]`; `parseRss()` exported separately from `fetchRemoteOkJobs()`
|
|
514
|
+
so contract tests call pure parsing functions without network mocking
|
|
515
|
+
- `src/adapters/hackernews.ts` — HN Firebase adapter; fetches "Who is Hiring?"
|
|
516
|
+
thread comments in parallel; `parseComment()` exported for offline testing;
|
|
517
|
+
handles deleted/dead items gracefully
|
|
518
|
+
- `src/adapters/index.ts` — barrel export for all adapter public API
|
|
519
|
+
- `src/tests/fixtures/remoteok.xml` — RSS fixture covering full fields, no-salary,
|
|
520
|
+
and k-suffix salary variants
|
|
521
|
+
- `src/tests/fixtures/hn-thread.json` — HN thread fixture with `kids` array
|
|
522
|
+
- `src/tests/fixtures/hn-comment-job.json` — HN job comment fixture (pipe-separated
|
|
523
|
+
header, HTML body, salary, experience years)
|
|
524
|
+
- `src/tests/fixtures/hn-comment-deleted.json` — deleted comment fixture (adapter
|
|
525
|
+
must skip)
|
|
526
|
+
- `src/tests/adapters.remoteok.test.ts` — 25 offline contract tests (title/company
|
|
527
|
+
splitting, salary parsing, work-mode inference, HTML stripping, `stableId`)
|
|
528
|
+
- `src/tests/adapters.hackernews.test.ts` — 18 offline contract tests (header
|
|
529
|
+
parsing, timestamp conversion, HTML decoding, skip logic for deleted items)
|
|
530
|
+
- `scripts/smoke_sources.ts` — live smoke test hitting real RemoteOK RSS and HN
|
|
531
|
+
Firebase APIs; run manually before releases with `npm run smoke`
|
|
532
|
+
- `fast-xml-parser` added as a production dependency (RSS parsing)
|
|
533
|
+
- `tsx` added as a dev dependency (runs a smoke script without a compiler step)
|
|
534
|
+
|
|
535
|
+
### Changed
|
|
536
|
+
|
|
537
|
+
- `stripHtml()` fixed: opening `<p>` tags now convert to `\n` (was `""`) so HN
|
|
538
|
+
comment header and body lines split correctly after HTML stripping
|
|
539
|
+
- `README.md` — roadmap updated; Phase 2 marked complete; note updated to
|
|
540
|
+
reference v0.2.0
|
|
541
|
+
- **Payment processor:** Pro license switched from Gumroad to **Polar.sh**
|
|
542
|
+
(`https://polar.sh/orestes-garcia-martinez/careerclaw-pro`); `CAREERCLAW_PRO_KEY`
|
|
543
|
+
env var name and SHA-256 cache behavior unchanged
|
|
544
|
+
|
|
545
|
+
### Notes
|
|
546
|
+
|
|
547
|
+
58 tests across 4 test files, all passing. No network calls in CI — all adapter
|
|
548
|
+
tests use offline fixtures. Run `npm run smoke` manually before each release to
|
|
549
|
+
validate live sources.
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
## [0.1.0] — 2026-03-03
|
|
553
|
+
|
|
554
|
+
### Added
|
|
555
|
+
|
|
556
|
+
- Initial repository scaffold: `package.json`, `tsconfig.json`, `vitest.config.ts`
|
|
557
|
+
- `src/models.ts` — canonical data schemas (`NormalizedJob`, `UserProfile`,
|
|
558
|
+
`TrackingEntry`, `BriefingRun`, `ScoredJob`, `OutreachDraft`); identical
|
|
559
|
+
JSON serialization format to Python careerclaw for cross-implementation
|
|
560
|
+
file compatibility
|
|
561
|
+
- `src/config.ts` — centralised environment and source configuration
|
|
562
|
+
(runtime paths, HTTP defaults, RemoteOK RSS URL, HN thread ID, LLM and
|
|
563
|
+
license env vars)
|
|
564
|
+
- `SKILL.md` — OpenClaw skill definition with Node-native self-healing
|
|
565
|
+
install check (`npm install -g careerclaw-js`)
|
|
566
|
+
- `CHANGELOG.md`
|
|
567
|
+
- Unit tests for `models.ts` and `config.ts` (Vitest)
|
|
568
|
+
|
|
569
|
+
### Notes
|
|
570
|
+
|
|
571
|
+
This release establishes the Phase 1 foundation types. No adapters,
|
|
572
|
+
matching, or CLI are included yet — those follow in Phases 2–8 per the
|
|
573
|
+
Node Migration Decision (ADR, March 2026).
|
|
574
|
+
|
|
575
|
+
[Unreleased]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.8.0...HEAD
|
|
576
|
+
[0.8.1]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.8.0...v0.8.1
|
|
577
|
+
[0.8.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.7.0...v0.8.0
|
|
578
|
+
[0.7.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.6.0...v0.7.0
|
|
579
|
+
[0.6.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.5.0...v0.6.0
|
|
580
|
+
[0.5.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.4.0...v0.5.0
|
|
581
|
+
[0.4.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.3.0...v0.4.0
|
|
582
|
+
[0.3.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.2.0...v0.3.0
|
|
583
|
+
[0.2.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/compare/v0.1.0...v0.2.0
|
|
495
584
|
[0.1.0]: https://github.com/orestes-garcia-martinez/careerclaw-js/releases/tag/v0.1.0
|