jobhunt-kit 0.4.0 → 0.5.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/.claude-plugin/marketplace.json +1 -1
- package/README.md +19 -2
- package/bin/jobhunt-kit.mjs +7 -3
- package/installer-assets/gitignore.txt +1 -0
- package/installer-assets/runtime-lock.json +56 -2
- package/installer-assets/workspace-lock.json +56 -2
- package/package.json +3 -1
- package/plugins/jobhunt-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/jobhunt-kit/.codex-plugin/plugin.json +1 -1
- package/plugins/jobhunt-kit/package-lock.json +56 -2
- package/plugins/jobhunt-kit/package.json +2 -1
- package/plugins/jobhunt-kit/references/cli.md +27 -1
- package/plugins/jobhunt-kit/references/privacy.md +24 -0
- package/plugins/jobhunt-kit/references/storage.md +11 -5
- package/plugins/jobhunt-kit/schemas/draft.schema.json +13 -0
- package/plugins/jobhunt-kit/schemas/finish.schema.json +11 -0
- package/plugins/jobhunt-kit/schemas/policy.schema.json +36 -0
- package/plugins/jobhunt-kit/schemas/profile.schema.json +80 -0
- package/plugins/jobhunt-kit/schemas/status.schema.json +12 -0
- package/plugins/jobhunt-kit/schemas/vacancy.schema.json +29 -0
- package/plugins/jobhunt-kit/scripts/commands.mjs +57 -11
- package/plugins/jobhunt-kit/scripts/extract-resume.mjs +5 -3
- package/plugins/jobhunt-kit/scripts/files.mjs +69 -0
- package/plugins/jobhunt-kit/scripts/maintenance.mjs +292 -0
- package/plugins/jobhunt-kit/scripts/profile.mjs +23 -20
- package/plugins/jobhunt-kit/scripts/resume.mjs +42 -38
- package/plugins/jobhunt-kit/scripts/setup.mjs +8 -10
- package/plugins/jobhunt-kit/scripts/tracker.mjs +188 -33
- package/plugins/jobhunt-kit/scripts/validation.mjs +30 -0
- package/plugins/jobhunt-kit/skills/job-apply/SKILL.md +4 -2
- package/plugins/jobhunt-kit/skills/job-resume/SKILL.md +3 -2
- package/plugins/jobhunt-kit/skills/job-track/SKILL.md +8 -0
- package/scripts/check-package.mjs +7 -0
- package/scripts/pack-smoke.mjs +53 -0
- package/tests/hardening.test.mjs +337 -0
- package/tests/installer.test.mjs +9 -2
- package/tests/tracker.test.mjs +3 -0
package/README.md
CHANGED
|
@@ -55,6 +55,11 @@ npx jobhunt-kit profile check
|
|
|
55
55
|
npx jobhunt-kit search
|
|
56
56
|
npx jobhunt-kit track
|
|
57
57
|
npx jobhunt-kit report
|
|
58
|
+
npx jobhunt-kit recover inspect
|
|
59
|
+
npx jobhunt-kit recover packet <attempt_id>
|
|
60
|
+
npx jobhunt-kit backup ../jobhunt-backup
|
|
61
|
+
npx jobhunt-kit backup-verify ../jobhunt-backup
|
|
62
|
+
npx jobhunt-kit privacy map
|
|
58
63
|
```
|
|
59
64
|
|
|
60
65
|
`resume` извлекает текст PDF, DOCX, TXT или Markdown и готовит материалы для проверки
|
|
@@ -77,7 +82,17 @@ npx jobhunt-kit report
|
|
|
77
82
|
| `reports/latest.md` | Сводный отчёт |
|
|
78
83
|
|
|
79
84
|
Папка `local/` исключена из Git. Храните личные файлы в ней; для резервной копии
|
|
80
|
-
|
|
85
|
+
используйте `backup` и затем `backup-verify`. Restore принимает только проверяемую
|
|
86
|
+
копию, требует точное подтверждение и предварительно делает сырой quarantine-снимок,
|
|
87
|
+
который сохраняется даже тогда, когда текущие JSON или SQLite уже повреждены.
|
|
88
|
+
Restore и очистка history всегда отзывают auto-разрешение и подтверждение профиля.
|
|
89
|
+
Данные на диске не зашифрованы.
|
|
90
|
+
|
|
91
|
+
`doctor` проверяет JSON Schema профиля/policy, SQLite integrity и foreign keys,
|
|
92
|
+
незавершённые поиски/отправки и журнал атомарных файловых операций. `privacy map`
|
|
93
|
+
показывает размещение PII; `privacy export`, `redact` и `purge` дают контролируемый
|
|
94
|
+
экспорт и удаление. Redact/purge требуют точных подтверждений, а purge не запускается
|
|
95
|
+
без отдельной резервной копии.
|
|
81
96
|
|
|
82
97
|
## Выбор агентов
|
|
83
98
|
|
|
@@ -142,12 +157,14 @@ OpenCode учитывает `OPENCODE_CONFIG_DIR` и `XDG_CONFIG_HOME`; Hermes
|
|
|
142
157
|
npm ci --ignore-scripts
|
|
143
158
|
npm test
|
|
144
159
|
npm run check
|
|
160
|
+
npm run pack:smoke
|
|
145
161
|
```
|
|
146
162
|
|
|
147
163
|
Тесты работают с вымышленными данными и не отправляют реальные отклики.
|
|
148
164
|
|
|
149
165
|
Руководства: [формат данных](plugins/jobhunt-kit/references/storage.md),
|
|
150
166
|
[проверка резюме](plugins/jobhunt-kit/references/resume-guidance.md),
|
|
151
|
-
[сопроводительные письма](plugins/jobhunt-kit/references/cover-guidance.md)
|
|
167
|
+
[сопроводительные письма](plugins/jobhunt-kit/references/cover-guidance.md),
|
|
168
|
+
[карта приватных данных](plugins/jobhunt-kit/references/privacy.md).
|
|
152
169
|
|
|
153
170
|
Автор этого шаблона никак не аффилирован с Hirify.
|
package/bin/jobhunt-kit.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync, realpathSync } from 'node:fs';
|
|
3
|
-
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
@@ -11,6 +11,10 @@ const SOURCE = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
11
11
|
const roots = ['bin', 'installer-assets', 'plugins/jobhunt-kit', 'scripts', 'tests',
|
|
12
12
|
'AGENTS.md', 'CLAUDE.md', 'README.md', 'package.json',
|
|
13
13
|
'.agents/plugins/marketplace.json', '.claude-plugin/marketplace.json'];
|
|
14
|
+
export function pathInside(parent, child, pathApi = { relative, isAbsolute, sep }) {
|
|
15
|
+
const delta = pathApi.relative(parent, child);
|
|
16
|
+
return delta === '' || (!pathApi.isAbsolute(delta) && delta !== '..' && !delta.startsWith(`..${pathApi.sep}`));
|
|
17
|
+
}
|
|
14
18
|
function collect(path) {
|
|
15
19
|
const stat = lstatSync(path);
|
|
16
20
|
if (stat.isSymbolicLink()) throw new Error(`Symlink in template: ${path}`);
|
|
@@ -33,7 +37,7 @@ export function install(destination, { source = SOURCE, installDependencies = tr
|
|
|
33
37
|
if (scope === 'global' && !agents.length) throw new Error('Global installation requires at least one agent');
|
|
34
38
|
const target = resolve(scope === 'global' ? home : destination);
|
|
35
39
|
source = resolve(source);
|
|
36
|
-
if (
|
|
40
|
+
if (pathInside(source, target)) throw new Error('Choose a destination outside the installer package');
|
|
37
41
|
const files = new Map();
|
|
38
42
|
if (scope === 'project') {
|
|
39
43
|
for (const root of roots) for (const path of collect(join(source, root))) files.set(relative(source, path), path);
|
|
@@ -94,7 +98,7 @@ export async function main(args) {
|
|
|
94
98
|
return;
|
|
95
99
|
}
|
|
96
100
|
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
97
|
-
console.log('Usage: jobhunt-kit <command> [arguments] [--workspace dir | --data dir]\n\ninstall [directory] Choose agents and install (default: ./my-jobhunt)\n --agents codex,cursor,... Select agents (or all); --providers is an alias\n agents List supported agents\n --scope project|global Workspace skills or user-wide skills\n --yes, -y Use detected agents and project scope\ninit <directory> Alias with an explicit destination\nprofile init|show|check Initialize/view/validate local profile\nprofile save --input file Save profile and clear confirmation\nprofile confirm --note text Record explicit candidate confirmation\nresume [file] Import file, fingerprint and mechanical checks\nresume check|reviewed Inspect file / record agent review (--input file)\nsearch [plan] Prepare context for agent; no live search\nsearch start|event|record|finish Persist search operations (--input file)\napply preview|export|begin slug Review/export/reserve application\napply prepare|approve|send|finish|resolve --input file\ntrack list|show slug|status slug --input file\nhistory | runs | report Inspect history or generate Markdown report\npolicy show|set --input file Inspect/set application policy\nschedule --input file Generate scheduler prompt; does not schedule\ndoctor Check
|
|
101
|
+
console.log('Usage: jobhunt-kit <command> [arguments] [--workspace dir | --data dir]\n\ninstall [directory] Choose agents and install (default: ./my-jobhunt)\n --agents codex,cursor,... Select agents (or all); --providers is an alias\n agents List supported agents\n --scope project|global Workspace skills or user-wide skills\n --yes, -y Use detected agents and project scope\ninit <directory> Alias with an explicit destination\nprofile init|show|check Initialize/view/validate local profile\nprofile save --input file Save profile and clear confirmation\nprofile confirm --note text Record explicit candidate confirmation\nresume [file] Import file, fingerprint and mechanical checks\nresume check|reviewed Inspect file / record agent review (--input file)\nsearch [plan] Prepare context for agent; no live search\nsearch start|event|record|finish Persist search operations (--input file)\napply preview|export|begin slug Review/export/reserve application\napply prepare|approve|send|finish|resolve --input file\ntrack list|show slug|status slug --input file\nhistory | runs | report Inspect history or generate Markdown report\npolicy show|set --input file Inspect/set application policy\nschedule --input file Generate scheduler prompt; does not schedule\nbackup/backup-verify <directory> Create or verify a local backup\nrestore --input file Restore after exact typed confirmation\nrecover inspect|apply|packet Inspect, resolve, or recreate an attempt packet\nprivacy map|export|redact|purge Inspect, export or remove local PII\ndoctor Check schemas, database and recovery state without network\n\nNode.js 24+ required. Default data: ./local/jobhunt-kit. Only apply send performs a live application call.');
|
|
98
102
|
return;
|
|
99
103
|
}
|
|
100
104
|
if (!['init', 'install'].includes(args[0])) {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jobhunt-kit-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "jobhunt-kit-plugin",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.5.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"ajv": "8.20.0",
|
|
11
12
|
"hirify-cli": "0.4.5",
|
|
12
13
|
"mammoth": "1.12.2",
|
|
13
14
|
"pdf-parse": "2.4.5"
|
|
@@ -224,6 +225,22 @@
|
|
|
224
225
|
"node": ">=10.0.0"
|
|
225
226
|
}
|
|
226
227
|
},
|
|
228
|
+
"node_modules/ajv": {
|
|
229
|
+
"version": "8.20.0",
|
|
230
|
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
|
231
|
+
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
|
232
|
+
"license": "MIT",
|
|
233
|
+
"dependencies": {
|
|
234
|
+
"fast-deep-equal": "^3.1.3",
|
|
235
|
+
"fast-uri": "^3.0.1",
|
|
236
|
+
"json-schema-traverse": "^1.0.0",
|
|
237
|
+
"require-from-string": "^2.0.2"
|
|
238
|
+
},
|
|
239
|
+
"funding": {
|
|
240
|
+
"type": "github",
|
|
241
|
+
"url": "https://github.com/sponsors/epoberezkin"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
227
244
|
"node_modules/argparse": {
|
|
228
245
|
"version": "1.0.10",
|
|
229
246
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
@@ -280,6 +297,28 @@
|
|
|
280
297
|
"underscore": "^1.13.1"
|
|
281
298
|
}
|
|
282
299
|
},
|
|
300
|
+
"node_modules/fast-deep-equal": {
|
|
301
|
+
"version": "3.1.3",
|
|
302
|
+
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
303
|
+
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
|
304
|
+
"license": "MIT"
|
|
305
|
+
},
|
|
306
|
+
"node_modules/fast-uri": {
|
|
307
|
+
"version": "3.1.7",
|
|
308
|
+
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
|
|
309
|
+
"integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
|
|
310
|
+
"funding": [
|
|
311
|
+
{
|
|
312
|
+
"type": "github",
|
|
313
|
+
"url": "https://github.com/sponsors/fastify"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"type": "opencollective",
|
|
317
|
+
"url": "https://opencollective.com/fastify"
|
|
318
|
+
}
|
|
319
|
+
],
|
|
320
|
+
"license": "BSD-3-Clause"
|
|
321
|
+
},
|
|
283
322
|
"node_modules/hirify-cli": {
|
|
284
323
|
"version": "0.4.5",
|
|
285
324
|
"resolved": "https://registry.npmjs.org/hirify-cli/-/hirify-cli-0.4.5.tgz",
|
|
@@ -310,6 +349,12 @@
|
|
|
310
349
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
|
311
350
|
"license": "MIT"
|
|
312
351
|
},
|
|
352
|
+
"node_modules/json-schema-traverse": {
|
|
353
|
+
"version": "1.0.0",
|
|
354
|
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
355
|
+
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
356
|
+
"license": "MIT"
|
|
357
|
+
},
|
|
313
358
|
"node_modules/jszip": {
|
|
314
359
|
"version": "3.10.1",
|
|
315
360
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
|
@@ -440,6 +485,15 @@
|
|
|
440
485
|
"util-deprecate": "~1.0.1"
|
|
441
486
|
}
|
|
442
487
|
},
|
|
488
|
+
"node_modules/require-from-string": {
|
|
489
|
+
"version": "2.0.2",
|
|
490
|
+
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
491
|
+
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
|
492
|
+
"license": "MIT",
|
|
493
|
+
"engines": {
|
|
494
|
+
"node": ">=0.10.0"
|
|
495
|
+
}
|
|
496
|
+
},
|
|
443
497
|
"node_modules/safe-buffer": {
|
|
444
498
|
"version": "5.1.2",
|
|
445
499
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jobhunt-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "jobhunt-kit",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.5.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"ajv": "8.20.0",
|
|
11
12
|
"hirify-cli": "0.4.5",
|
|
12
13
|
"mammoth": "1.12.2",
|
|
13
14
|
"pdf-parse": "2.4.5"
|
|
@@ -227,6 +228,22 @@
|
|
|
227
228
|
"node": ">=10.0.0"
|
|
228
229
|
}
|
|
229
230
|
},
|
|
231
|
+
"node_modules/ajv": {
|
|
232
|
+
"version": "8.20.0",
|
|
233
|
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
|
234
|
+
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
|
235
|
+
"license": "MIT",
|
|
236
|
+
"dependencies": {
|
|
237
|
+
"fast-deep-equal": "^3.1.3",
|
|
238
|
+
"fast-uri": "^3.0.1",
|
|
239
|
+
"json-schema-traverse": "^1.0.0",
|
|
240
|
+
"require-from-string": "^2.0.2"
|
|
241
|
+
},
|
|
242
|
+
"funding": {
|
|
243
|
+
"type": "github",
|
|
244
|
+
"url": "https://github.com/sponsors/epoberezkin"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
230
247
|
"node_modules/argparse": {
|
|
231
248
|
"version": "1.0.10",
|
|
232
249
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
@@ -283,6 +300,28 @@
|
|
|
283
300
|
"underscore": "^1.13.1"
|
|
284
301
|
}
|
|
285
302
|
},
|
|
303
|
+
"node_modules/fast-deep-equal": {
|
|
304
|
+
"version": "3.1.3",
|
|
305
|
+
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
306
|
+
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
|
307
|
+
"license": "MIT"
|
|
308
|
+
},
|
|
309
|
+
"node_modules/fast-uri": {
|
|
310
|
+
"version": "3.1.7",
|
|
311
|
+
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
|
|
312
|
+
"integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
|
|
313
|
+
"funding": [
|
|
314
|
+
{
|
|
315
|
+
"type": "github",
|
|
316
|
+
"url": "https://github.com/sponsors/fastify"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"type": "opencollective",
|
|
320
|
+
"url": "https://opencollective.com/fastify"
|
|
321
|
+
}
|
|
322
|
+
],
|
|
323
|
+
"license": "BSD-3-Clause"
|
|
324
|
+
},
|
|
286
325
|
"node_modules/hirify-cli": {
|
|
287
326
|
"version": "0.4.5",
|
|
288
327
|
"resolved": "https://registry.npmjs.org/hirify-cli/-/hirify-cli-0.4.5.tgz",
|
|
@@ -313,6 +352,12 @@
|
|
|
313
352
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
|
314
353
|
"license": "MIT"
|
|
315
354
|
},
|
|
355
|
+
"node_modules/json-schema-traverse": {
|
|
356
|
+
"version": "1.0.0",
|
|
357
|
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
358
|
+
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
359
|
+
"license": "MIT"
|
|
360
|
+
},
|
|
316
361
|
"node_modules/jszip": {
|
|
317
362
|
"version": "3.10.1",
|
|
318
363
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
|
@@ -443,6 +488,15 @@
|
|
|
443
488
|
"util-deprecate": "~1.0.1"
|
|
444
489
|
}
|
|
445
490
|
},
|
|
491
|
+
"node_modules/require-from-string": {
|
|
492
|
+
"version": "2.0.2",
|
|
493
|
+
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
494
|
+
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
|
495
|
+
"license": "MIT",
|
|
496
|
+
"engines": {
|
|
497
|
+
"node": ">=0.10.0"
|
|
498
|
+
}
|
|
499
|
+
},
|
|
446
500
|
"node_modules/safe-buffer": {
|
|
447
501
|
"version": "5.1.2",
|
|
448
502
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jobhunt-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"jobhunt-kit": "bin/jobhunt-kit.mjs"
|
|
6
6
|
},
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
"hirify": "hirify",
|
|
20
20
|
"test": "node --test tests/*.test.mjs",
|
|
21
21
|
"check": "node scripts/check-package.mjs",
|
|
22
|
+
"pack:smoke": "node scripts/pack-smoke.mjs",
|
|
22
23
|
"prepublishOnly": "npm test && npm run check"
|
|
23
24
|
},
|
|
24
25
|
"engines": {
|
|
25
26
|
"node": ">=24.0.0"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
29
|
+
"ajv": "8.20.0",
|
|
28
30
|
"hirify-cli": "0.4.5",
|
|
29
31
|
"mammoth": "1.12.2",
|
|
30
32
|
"pdf-parse": "2.4.5"
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jobhunt-kit-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "jobhunt-kit-plugin",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.5.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"ajv": "8.20.0",
|
|
11
12
|
"hirify-cli": "0.4.5",
|
|
12
13
|
"mammoth": "1.12.2",
|
|
13
14
|
"pdf-parse": "2.4.5"
|
|
@@ -224,6 +225,22 @@
|
|
|
224
225
|
"node": ">=10.0.0"
|
|
225
226
|
}
|
|
226
227
|
},
|
|
228
|
+
"node_modules/ajv": {
|
|
229
|
+
"version": "8.20.0",
|
|
230
|
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
|
231
|
+
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
|
232
|
+
"license": "MIT",
|
|
233
|
+
"dependencies": {
|
|
234
|
+
"fast-deep-equal": "^3.1.3",
|
|
235
|
+
"fast-uri": "^3.0.1",
|
|
236
|
+
"json-schema-traverse": "^1.0.0",
|
|
237
|
+
"require-from-string": "^2.0.2"
|
|
238
|
+
},
|
|
239
|
+
"funding": {
|
|
240
|
+
"type": "github",
|
|
241
|
+
"url": "https://github.com/sponsors/epoberezkin"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
227
244
|
"node_modules/argparse": {
|
|
228
245
|
"version": "1.0.10",
|
|
229
246
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
@@ -280,6 +297,28 @@
|
|
|
280
297
|
"underscore": "^1.13.1"
|
|
281
298
|
}
|
|
282
299
|
},
|
|
300
|
+
"node_modules/fast-deep-equal": {
|
|
301
|
+
"version": "3.1.3",
|
|
302
|
+
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
|
303
|
+
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
|
304
|
+
"license": "MIT"
|
|
305
|
+
},
|
|
306
|
+
"node_modules/fast-uri": {
|
|
307
|
+
"version": "3.1.7",
|
|
308
|
+
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
|
|
309
|
+
"integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
|
|
310
|
+
"funding": [
|
|
311
|
+
{
|
|
312
|
+
"type": "github",
|
|
313
|
+
"url": "https://github.com/sponsors/fastify"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"type": "opencollective",
|
|
317
|
+
"url": "https://opencollective.com/fastify"
|
|
318
|
+
}
|
|
319
|
+
],
|
|
320
|
+
"license": "BSD-3-Clause"
|
|
321
|
+
},
|
|
283
322
|
"node_modules/hirify-cli": {
|
|
284
323
|
"version": "0.4.5",
|
|
285
324
|
"resolved": "https://registry.npmjs.org/hirify-cli/-/hirify-cli-0.4.5.tgz",
|
|
@@ -310,6 +349,12 @@
|
|
|
310
349
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
|
311
350
|
"license": "MIT"
|
|
312
351
|
},
|
|
352
|
+
"node_modules/json-schema-traverse": {
|
|
353
|
+
"version": "1.0.0",
|
|
354
|
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
355
|
+
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
356
|
+
"license": "MIT"
|
|
357
|
+
},
|
|
313
358
|
"node_modules/jszip": {
|
|
314
359
|
"version": "3.10.1",
|
|
315
360
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
|
@@ -440,6 +485,15 @@
|
|
|
440
485
|
"util-deprecate": "~1.0.1"
|
|
441
486
|
}
|
|
442
487
|
},
|
|
488
|
+
"node_modules/require-from-string": {
|
|
489
|
+
"version": "2.0.2",
|
|
490
|
+
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
491
|
+
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
|
492
|
+
"license": "MIT",
|
|
493
|
+
"engines": {
|
|
494
|
+
"node": ">=0.10.0"
|
|
495
|
+
}
|
|
496
|
+
},
|
|
443
497
|
"node_modules/safe-buffer": {
|
|
444
498
|
"version": "5.1.2",
|
|
445
499
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jobhunt-kit-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=24.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
+
"ajv": "8.20.0",
|
|
10
11
|
"hirify-cli": "0.4.5",
|
|
11
12
|
"mammoth": "1.12.2",
|
|
12
13
|
"pdf-parse": "2.4.5"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
| job-resume | Копия по SHA-256, извлечение PDF/DOCX/TXT/MD, простые проверки текста, сохранение отчёта, запись завершённой проверки | Визуальная оценка, истинность фактов, соответствие роли и содержательные правки |
|
|
26
26
|
| job-search | Сбор профиля, бюджетов и известных вакансий; журнал запусков/результатов, запрет второго активного запуска через CLI | Актуальные фильтры Hirify, preview, живой поиск, оценка требований и ранжирование |
|
|
27
27
|
| job-apply | Снимок черновика, экспорт текста/ответов, согласование, резервирование и однократный вызов CLI, запись исхода | Написание письма из фактов, проверка живого профиля/квоты, получение разрешения, разбор ответа сервиса |
|
|
28
|
-
| job-track | Списки/история/статусы/Markdown
|
|
28
|
+
| job-track | Списки/история/статусы/Markdown, integrity/recovery, backup/restore, privacy-команды; заполнение prompt для расписания | Интерпретация сообщения кандидата, создание задачи в планировщике после запроса |
|
|
29
29
|
|
|
30
30
|
Технические функции: `profile.mjs`, `resume.mjs`, `extract-resume.mjs`, `commands.mjs`;
|
|
31
31
|
история и защита отправки переиспользуют `tracker.mjs` и `send-packet.mjs`.
|
|
@@ -129,3 +129,29 @@ schedule.json: `{"frequency":"По будням в 09:00","timezone":"Europe/Ber
|
|
|
129
129
|
materials/scheduled-search.md, а не включённая задача; auto-разрешение не выдаётся.
|
|
130
130
|
Нужен --workspace с установленным шаблоном, чтобы prompt не ссылался на временный
|
|
131
131
|
кеш npx. Планировщик выбирает агент по явному запросу пользователя.
|
|
132
|
+
|
|
133
|
+
## Целостность, резервирование и приватность
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
npx jobhunt-kit doctor
|
|
137
|
+
npx jobhunt-kit recover inspect
|
|
138
|
+
npx jobhunt-kit recover apply --input recovery.json
|
|
139
|
+
npx jobhunt-kit recover packet <attempt_id>
|
|
140
|
+
npx jobhunt-kit backup ../jobhunt-backup
|
|
141
|
+
npx jobhunt-kit backup-verify ../jobhunt-backup
|
|
142
|
+
npx jobhunt-kit restore --input restore.json
|
|
143
|
+
npx jobhunt-kit privacy map
|
|
144
|
+
npx jobhunt-kit privacy export ../jobhunt-private-export
|
|
145
|
+
npx jobhunt-kit privacy redact --input redact.json
|
|
146
|
+
npx jobhunt-kit privacy purge --input purge.json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`doctor` проверяет JSON Schema, SQLite integrity/foreign keys, активный run,
|
|
150
|
+
неразрешённые attempts и незавершённые файловые операции. Recovery ничего не угадывает:
|
|
151
|
+
для run нужны id/status/reason, для attempt — slug/outcome/evidence.
|
|
152
|
+
|
|
153
|
+
Restore требует `{"source":"...","confirmation":"RESTORE VERIFIED JOBHUNT BACKUP"}`
|
|
154
|
+
и перед заменой создаёт автоматический сырой pre-restore quarantine-снимок. Redact требует
|
|
155
|
+
`REDACT LOCAL JOBHUNT PII` и массив dotted profile fields. Purge требует фразу
|
|
156
|
+
`PURGE LOCAL JOBHUNT DATA`, scopes и отдельный backup_directory; удаление без
|
|
157
|
+
проверяемой резервной копии не выполняется.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Локальные данные и приватность
|
|
2
|
+
|
|
3
|
+
Jobhunt Kit не шифрует данные. Рабочая папка `D` должна быть доступна только
|
|
4
|
+
пользователю и не должна синхронизироваться или публиковаться без его решения.
|
|
5
|
+
|
|
6
|
+
| Путь | Возможные персональные данные | Назначение |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `profile.json` | Имя, контакты, опыт, ответы, разрешения на работу | Авторитетный профиль кандидата |
|
|
9
|
+
| `policy.json` | Текст auto-разрешения, срок и лимит | Авторитетная политика отправки |
|
|
10
|
+
| `history.sqlite` | Вакансии, письма, ответы, approvals, application snapshots; legacy v1 мог хранить полные снимки профиля | Авторитетная история |
|
|
11
|
+
| `resumes/` | Неизменяемые копии резюме | Проверка и отправочный контекст |
|
|
12
|
+
| `materials/` | Извлечённый текст, письма, ответы, attempt packets | Рабочие материалы агента |
|
|
13
|
+
| `reports/` | Названия вакансий, ссылки и статусы | Производное представление истории |
|
|
14
|
+
|
|
15
|
+
`privacy map` возвращает абсолютные пути этой карты. `privacy export` создаёт ту же
|
|
16
|
+
проверяемую копию, что backup. `privacy redact` меняет перечисленные dotted-поля
|
|
17
|
+
профиля, сбрасывает подтверждение и удаляет полные profile snapshots/user authorization
|
|
18
|
+
из legacy events; для полного удаления истории использовать purge scope `history`.
|
|
19
|
+
|
|
20
|
+
`privacy purge` требует точную фразу подтверждения и отдельный `backup_directory`.
|
|
21
|
+
До удаления создаётся и проверяется полная резервная копия. Scopes: `profile`,
|
|
22
|
+
`history`, `resumes`, `materials`, `reports`. Очистка `history` всегда очищает и
|
|
23
|
+
производные `reports`, отзывает auto-разрешение и подтверждение профиля. Purge не удаляет внешний файл, из которого ранее
|
|
24
|
+
импортировали резюме, и не отзывает уже отправленные заявления на стороне Hirify.
|
|
@@ -30,7 +30,8 @@ P/D — абсолютные пути из workflow.md. JSON-ответы ком
|
|
|
30
30
|
Дата confirmed_at — ISO 8601. Profile-команда отдаёт hash текущего JSON для разрешения
|
|
31
31
|
auto. Хеш зависит от сериализации объекта: изменение/перестановка ключей может
|
|
32
32
|
потребовать нового согласования (консервативное поведение).
|
|
33
|
-
resume.path — путь
|
|
33
|
+
resume.path — только относительный путь внутри D, штатно `resumes/<sha>.<ext>`;
|
|
34
|
+
внешний файл сначала импортируется командой resume. sha256 — хеш байтов файла.
|
|
34
35
|
Пример вычисления в PowerShell: `(Get-FileHash <file> -Algorithm SHA256).Hash.ToLower()`.
|
|
35
36
|
readiness и confirmed — утверждения агента по фактической проверке, не автоматическая
|
|
36
37
|
проверка истинности биографии. Не отмечать их только ради прохождения команды.
|
|
@@ -109,12 +110,17 @@ External или недостающие ответы → needs_user. После
|
|
|
109
110
|
можно dismissed. После отправки: interview / rejected / withdrawn / offer;
|
|
110
111
|
из offer: accepted / declined / withdrawn. Status — локальная запись, не действие сервиса.
|
|
111
112
|
|
|
112
|
-
Схема SQLite
|
|
113
|
+
Схема SQLite v2: runs, jobs, aliases, observations, attempts, dispatches, events,
|
|
114
|
+
file_revisions и pending_file_writes. Миграция v1→v2 сохраняет данные, закрывает
|
|
115
|
+
старые дублирующиеся running runs, записывается в schema_migrations и добавляет
|
|
116
|
+
immutable application snapshots.
|
|
113
117
|
В attempts UNIQUE(job_id), в dispatches PRIMARY KEY(attempt_id): повтор не проходит
|
|
114
118
|
после перезапуска процесса. Сбой после намерения требует ручного разбора.
|
|
115
119
|
Нет универсальной транзакции между SQLite и Hirify: невозможно обещать exactly-once
|
|
116
120
|
доставку через сеть. Здесь предотвращаются автоматические повторные отправки.
|
|
117
121
|
|
|
118
|
-
Историю читать через команды. Для резервирования
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
Историю читать через команды. Для резервирования использовать backup и backup-verify.
|
|
123
|
+
Restore сначала создаёт сырой автоматический pre-restore quarantine-снимок, не требующий
|
|
124
|
+
валидности текущих данных. Перед активацией восстановленной истории restore отзывает
|
|
125
|
+
auto-разрешение и подтверждение профиля. Doctor проверяет JSON Schema,
|
|
126
|
+
SQLite, foreign keys, незавершённые runs/attempts и журнал атомарных файловых операций.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "jobhunt-kit/draft",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["slug", "cover_letter", "hirify_profile_id", "claims", "answers", "unresolved"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"slug": { "type": "string", "minLength": 1 }, "cover_letter": { "type": "string", "minLength": 1 },
|
|
8
|
+
"hirify_profile_id": { "type": ["integer", "null"], "minimum": 1 },
|
|
9
|
+
"claims": { "type": "array", "items": { "type": "object", "required": ["text", "evidence_id"], "properties": { "text": { "type": "string", "minLength": 1 }, "evidence_id": { "type": "string", "minLength": 1 } }, "additionalProperties": false } },
|
|
10
|
+
"answers": { "type": "array" }, "unresolved": { "type": "array", "items": { "type": "string", "minLength": 1 } }
|
|
11
|
+
},
|
|
12
|
+
"additionalProperties": true
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "jobhunt-kit/finish",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["attempt_id", "outcome", "evidence"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"attempt_id": { "type": "string", "minLength": 1 }, "outcome": { "enum": ["submitted", "failed", "unknown"] },
|
|
8
|
+
"evidence": { "type": "string", "minLength": 1 }, "application_id": { "type": "string", "minLength": 1 }
|
|
9
|
+
},
|
|
10
|
+
"additionalProperties": true
|
|
11
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "jobhunt-kit/policy",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["schema_version", "mode", "search", "auto"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"schema_version": { "const": 1 },
|
|
8
|
+
"mode": { "enum": ["review_each", "auto"] },
|
|
9
|
+
"search": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["target", "max_cards", "max_reads", "max_reveals", "max_minutes"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"target": { "type": "integer", "minimum": 1 }, "max_cards": { "type": "integer", "minimum": 1 },
|
|
14
|
+
"max_reads": { "type": "integer", "minimum": 1 }, "max_reveals": { "type": "integer", "minimum": 0 },
|
|
15
|
+
"max_minutes": { "type": "integer", "minimum": 1 }
|
|
16
|
+
},
|
|
17
|
+
"additionalProperties": false
|
|
18
|
+
},
|
|
19
|
+
"auto": {
|
|
20
|
+
"anyOf": [
|
|
21
|
+
{ "type": "null" },
|
|
22
|
+
{
|
|
23
|
+
"type": "object", "required": ["user_authorization", "profile_hash", "expires_at", "max_attempts_per_utc_day"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"user_authorization": { "type": "string", "minLength": 1 },
|
|
26
|
+
"profile_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
27
|
+
"expires_at": { "type": "string", "format": "date-time" },
|
|
28
|
+
"max_attempts_per_utc_day": { "type": "integer", "minimum": 1 }
|
|
29
|
+
},
|
|
30
|
+
"additionalProperties": false
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": false
|
|
36
|
+
}
|