@rwendell/dossier 0.0.0-stage → 0.1.1

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.
Files changed (166) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +323 -2
  3. package/agents/dossier-answerer.md +168 -0
  4. package/agents/dossier-proposer.md +215 -0
  5. package/agents/dossier-tailor.md +232 -0
  6. package/dist/answer/prompt.d.ts +17 -0
  7. package/dist/answer/prompt.js +44 -0
  8. package/dist/answer/prompt.js.map +1 -0
  9. package/dist/answer/run.d.ts +21 -0
  10. package/dist/answer/run.js +272 -0
  11. package/dist/answer/run.js.map +1 -0
  12. package/dist/career/import-resume.d.ts +17 -0
  13. package/dist/career/import-resume.js +194 -0
  14. package/dist/career/import-resume.js.map +1 -0
  15. package/dist/career/load.d.ts +10 -0
  16. package/dist/career/load.js +96 -0
  17. package/dist/career/load.js.map +1 -0
  18. package/dist/career/schema.d.ts +147 -0
  19. package/dist/career/schema.js +95 -0
  20. package/dist/career/schema.js.map +1 -0
  21. package/dist/clean/run.d.ts +1 -0
  22. package/dist/clean/run.js +8 -0
  23. package/dist/clean/run.js.map +1 -0
  24. package/dist/cli/commands/answer.d.ts +23 -0
  25. package/dist/cli/commands/answer.js +110 -0
  26. package/dist/cli/commands/answer.js.map +1 -0
  27. package/dist/cli/commands/clean.d.ts +2 -0
  28. package/dist/cli/commands/clean.js +11 -0
  29. package/dist/cli/commands/clean.js.map +1 -0
  30. package/dist/cli/commands/doctor.d.ts +2 -0
  31. package/dist/cli/commands/doctor.js +77 -0
  32. package/dist/cli/commands/doctor.js.map +1 -0
  33. package/dist/cli/commands/init.d.ts +7 -0
  34. package/dist/cli/commands/init.js +80 -0
  35. package/dist/cli/commands/init.js.map +1 -0
  36. package/dist/cli/commands/paths.d.ts +7 -0
  37. package/dist/cli/commands/paths.js +42 -0
  38. package/dist/cli/commands/paths.js.map +1 -0
  39. package/dist/cli/commands/proposal.d.ts +30 -0
  40. package/dist/cli/commands/proposal.js +148 -0
  41. package/dist/cli/commands/proposal.js.map +1 -0
  42. package/dist/cli/commands/pull-private.d.ts +8 -0
  43. package/dist/cli/commands/pull-private.js +30 -0
  44. package/dist/cli/commands/pull-private.js.map +1 -0
  45. package/dist/cli/commands/score.d.ts +11 -0
  46. package/dist/cli/commands/score.js +58 -0
  47. package/dist/cli/commands/score.js.map +1 -0
  48. package/dist/cli/commands/sync.d.ts +13 -0
  49. package/dist/cli/commands/sync.js +65 -0
  50. package/dist/cli/commands/sync.js.map +1 -0
  51. package/dist/cli/commands/tailor.d.ts +24 -0
  52. package/dist/cli/commands/tailor.js +113 -0
  53. package/dist/cli/commands/tailor.js.map +1 -0
  54. package/dist/cli/commands/verify.d.ts +6 -0
  55. package/dist/cli/commands/verify.js +15 -0
  56. package/dist/cli/commands/verify.js.map +1 -0
  57. package/dist/cli/index.d.ts +2 -0
  58. package/dist/cli/index.js +87 -0
  59. package/dist/cli/index.js.map +1 -0
  60. package/dist/config/config.d.ts +36 -0
  61. package/dist/config/config.js +71 -0
  62. package/dist/config/config.js.map +1 -0
  63. package/dist/config/paths.d.ts +32 -0
  64. package/dist/config/paths.js +121 -0
  65. package/dist/config/paths.js.map +1 -0
  66. package/dist/evidence/numbers.d.ts +2 -0
  67. package/dist/evidence/numbers.js +26 -0
  68. package/dist/evidence/numbers.js.map +1 -0
  69. package/dist/evidence/verify.d.ts +109 -0
  70. package/dist/evidence/verify.js +445 -0
  71. package/dist/evidence/verify.js.map +1 -0
  72. package/dist/job/input.d.ts +9 -0
  73. package/dist/job/input.js +141 -0
  74. package/dist/job/input.js.map +1 -0
  75. package/dist/job/page.d.ts +14 -0
  76. package/dist/job/page.js +426 -0
  77. package/dist/job/page.js.map +1 -0
  78. package/dist/job/types.d.ts +30 -0
  79. package/dist/job/types.js +2 -0
  80. package/dist/job/types.js.map +1 -0
  81. package/dist/llm/agents.d.ts +7 -0
  82. package/dist/llm/agents.js +44 -0
  83. package/dist/llm/agents.js.map +1 -0
  84. package/dist/llm/opencode.d.ts +19 -0
  85. package/dist/llm/opencode.js +117 -0
  86. package/dist/llm/opencode.js.map +1 -0
  87. package/dist/llm/providers.d.ts +63 -0
  88. package/dist/llm/providers.js +207 -0
  89. package/dist/llm/providers.js.map +1 -0
  90. package/dist/private/pull.d.ts +7 -0
  91. package/dist/private/pull.js +168 -0
  92. package/dist/private/pull.js.map +1 -0
  93. package/dist/projects/rank.d.ts +17 -0
  94. package/dist/projects/rank.js +100 -0
  95. package/dist/projects/rank.js.map +1 -0
  96. package/dist/projects/store.d.ts +7 -0
  97. package/dist/projects/store.js +31 -0
  98. package/dist/projects/store.js.map +1 -0
  99. package/dist/projects/sync-github.d.ts +11 -0
  100. package/dist/projects/sync-github.js +269 -0
  101. package/dist/projects/sync-github.js.map +1 -0
  102. package/dist/projects/sync-local.d.ts +8 -0
  103. package/dist/projects/sync-local.js +318 -0
  104. package/dist/projects/sync-local.js.map +1 -0
  105. package/dist/projects/types.d.ts +71 -0
  106. package/dist/projects/types.js +2 -0
  107. package/dist/projects/types.js.map +1 -0
  108. package/dist/proposal/prompt.d.ts +20 -0
  109. package/dist/proposal/prompt.js +64 -0
  110. package/dist/proposal/prompt.js.map +1 -0
  111. package/dist/proposal/run.d.ts +28 -0
  112. package/dist/proposal/run.js +386 -0
  113. package/dist/proposal/run.js.map +1 -0
  114. package/dist/resume/basics.d.ts +4 -0
  115. package/dist/resume/basics.js +33 -0
  116. package/dist/resume/basics.js.map +1 -0
  117. package/dist/resume/find.d.ts +12 -0
  118. package/dist/resume/find.js +27 -0
  119. package/dist/resume/find.js.map +1 -0
  120. package/dist/resume/format.d.ts +3 -0
  121. package/dist/resume/format.js +53 -0
  122. package/dist/resume/format.js.map +1 -0
  123. package/dist/resume/one-page.d.ts +149 -0
  124. package/dist/resume/one-page.js +164 -0
  125. package/dist/resume/one-page.js.map +1 -0
  126. package/dist/resume/prompt.d.ts +10 -0
  127. package/dist/resume/prompt.js +23 -0
  128. package/dist/resume/prompt.js.map +1 -0
  129. package/dist/resume/render.d.ts +8 -0
  130. package/dist/resume/render.js +84 -0
  131. package/dist/resume/render.js.map +1 -0
  132. package/dist/resume/run.d.ts +21 -0
  133. package/dist/resume/run.js +350 -0
  134. package/dist/resume/run.js.map +1 -0
  135. package/dist/resume/skills.d.ts +6 -0
  136. package/dist/resume/skills.js +47 -0
  137. package/dist/resume/skills.js.map +1 -0
  138. package/dist/resume/trace.d.ts +13 -0
  139. package/dist/resume/trace.js +82 -0
  140. package/dist/resume/trace.js.map +1 -0
  141. package/dist/resume/types.d.ts +94 -0
  142. package/dist/resume/types.js +2 -0
  143. package/dist/resume/types.js.map +1 -0
  144. package/dist/resume/verify.d.ts +19 -0
  145. package/dist/resume/verify.js +193 -0
  146. package/dist/resume/verify.js.map +1 -0
  147. package/dist/upwork/profile.d.ts +50 -0
  148. package/dist/upwork/profile.js +302 -0
  149. package/dist/upwork/profile.js.map +1 -0
  150. package/dist/upwork/settings.d.ts +96 -0
  151. package/dist/upwork/settings.js +166 -0
  152. package/dist/upwork/settings.js.map +1 -0
  153. package/dist/util/open-file.d.ts +1 -0
  154. package/dist/util/open-file.js +24 -0
  155. package/dist/util/open-file.js.map +1 -0
  156. package/dist/util/slug.d.ts +2 -0
  157. package/dist/util/slug.js +13 -0
  158. package/dist/util/slug.js.map +1 -0
  159. package/dist/verify/run.d.ts +4 -0
  160. package/dist/verify/run.js +91 -0
  161. package/dist/verify/run.js.map +1 -0
  162. package/package.json +67 -4
  163. package/templates/career.example.yml +63 -0
  164. package/templates/career.private.example.yml +10 -0
  165. package/templates/config.example.yml +16 -0
  166. package/templates/freelance.example.yml +48 -0
@@ -0,0 +1,350 @@
1
+ import { mkdirSync, rmSync, writeFileSync, } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { loadCareer } from '../career/load.js';
4
+ import { loadConfig } from '../config/config.js';
5
+ import { displayPath, getCacheDir, getRuntimeDir, resolveOutputDir, } from '../config/paths.js';
6
+ import { readJobInput } from '../job/input.js';
7
+ import { ensureAgents, reloadOpencode } from '../llm/agents.js';
8
+ import { LlmError, runAgent } from '../llm/providers.js';
9
+ import { hasProjectCache, loadCandidates, } from '../projects/store.js';
10
+ import { slugify } from '../util/slug.js';
11
+ import { openFile } from '../util/open-file.js';
12
+ import { applyProfileToCareer, loadUpworkProfile, } from '../upwork/profile.js';
13
+ import { loadFreelanceConfig } from '../upwork/settings.js';
14
+ import { applyBasicsUrlPolicy } from './basics.js';
15
+ import { normalizeNumberSpacing, normalizeThemePunctuation, } from './format.js';
16
+ import { MIN_FILL_HEIGHT, PAGE_CONTENT_HEIGHT, appendAchievement, collectUnusedAchievements, removeLastHighlight, trimResume, TRIM_PLANS, } from './one-page.js';
17
+ import { buildTailorPrompt } from './prompt.js';
18
+ import { createPageMeasurer, getPdfPageCount, renderHtml, renderPdf, } from './render.js';
19
+ import { filterExcludedSkills } from './skills.js';
20
+ import { fillProjectBulletTrace, hasTraceCoverage } from './trace.js';
21
+ import { verifyTailoredResume } from './verify.js';
22
+ export async function runTailor(options) {
23
+ const { config } = loadConfig();
24
+ const { config: freelanceConfig } = loadFreelanceConfig();
25
+ const configuredProfileUrl = typeof freelanceConfig.profile === 'string'
26
+ ? freelanceConfig.profile
27
+ : freelanceConfig.profile?.url;
28
+ const profileUrl = options.profile ||
29
+ (!options.noProfile ? configuredProfileUrl : '') ||
30
+ '';
31
+ const { career } = loadCareer();
32
+ if (profileUrl) {
33
+ try {
34
+ const profile = await loadUpworkProfile(profileUrl, {
35
+ refresh: options.refresh,
36
+ log: (message) => console.log(`dossier: ${message}`),
37
+ warn: (message) => console.warn(`dossier: ${message}`),
38
+ });
39
+ applyProfileToCareer(career, profile);
40
+ }
41
+ catch (error) {
42
+ if (options.profile)
43
+ throw error;
44
+ console.warn(`dossier: could not load configured Upwork profile: ${error.message}`);
45
+ }
46
+ }
47
+ const autoGeneric = !options.generic &&
48
+ !options.input &&
49
+ !options.description &&
50
+ !options.url;
51
+ const generic = Boolean(options.generic || autoGeneric);
52
+ let job;
53
+ if (generic) {
54
+ if (options.input) {
55
+ throw new Error('--generic builds a general resume and does not take a job file or URL.');
56
+ }
57
+ if (autoGeneric) {
58
+ console.log('dossier: no job source provided; building the generic resume');
59
+ }
60
+ const genericConfig = career.generic ?? {};
61
+ job = {
62
+ title: options.title ||
63
+ String(genericConfig.title ?? 'Software Engineer'),
64
+ company: options.company || '',
65
+ url: options.url || '',
66
+ body: options.description ||
67
+ String(genericConfig.description ??
68
+ 'Build a general-purpose software engineering resume using the strongest and most broadly relevant evidence in the fact bank.'),
69
+ source: 'generic',
70
+ details: {},
71
+ };
72
+ }
73
+ else {
74
+ job = await readJobInput({
75
+ input: options.input,
76
+ title: options.title,
77
+ company: options.company,
78
+ url: options.url,
79
+ description: options.description,
80
+ });
81
+ }
82
+ if (!job.title) {
83
+ throw new Error('Could not determine a job title. Pass --title, or use a job URL/file with a title.');
84
+ }
85
+ const theme = options.theme || config.theme;
86
+ const slug = generic
87
+ ? 'generic'
88
+ : slugify([job.company, job.title].filter(Boolean).join(' ')) ||
89
+ 'application';
90
+ const outDir = resolveOutputDir(config.output.dir, options.out);
91
+ mkdirSync(outDir, { recursive: true });
92
+ const nameSlug = options.name
93
+ ? slugify(options.name).slice(0, 70) || 'resume'
94
+ : '';
95
+ const base = resolve(outDir, `resume-${slug}${nameSlug ? `.${nameSlug}` : ''}`);
96
+ const resumePath = `${base}.json`;
97
+ const tracePath = `${base}.trace.json`;
98
+ const pdfPath = `${base}.pdf`;
99
+ const workDir = resolve(getCacheDir(), 'tailor', slug);
100
+ mkdirSync(workDir, { recursive: true });
101
+ const htmlPath = resolve(workDir, 'measure.html');
102
+ const candidates = loadCandidates(career, job);
103
+ if (candidates.length === 0 && !hasProjectCache()) {
104
+ console.warn('dossier: no project metadata cached; run `dossier sync github` or `dossier sync local` to include repositories.');
105
+ }
106
+ const prompt = buildTailorPrompt({ career, job, slug, candidates });
107
+ console.log(`dossier: ${job.company ? `${job.company} — ` : ''}${job.title}`);
108
+ console.log(`dossier: output ${displayPath(options.noRender ? resumePath : pdfPath)}`);
109
+ if (options.debug) {
110
+ writeFileSync(`${base}.prompt.txt`, prompt);
111
+ }
112
+ ensureAgents();
113
+ reloadOpencode();
114
+ let generated;
115
+ try {
116
+ generated = runAgent({
117
+ prompt,
118
+ agent: 'dossier-tailor',
119
+ title: `Tailor: ${slug}`,
120
+ timeout: options.timeout ?? 10 * 60 * 1000,
121
+ cwd: getRuntimeDir(),
122
+ provider: options.provider,
123
+ model: options.model,
124
+ accept: (value) => {
125
+ if (!value ||
126
+ typeof value.resume !== 'object' ||
127
+ value.resume === null ||
128
+ typeof value.trace !== 'object' ||
129
+ value.trace === null) {
130
+ return false;
131
+ }
132
+ const draft = value;
133
+ fillProjectBulletTrace(draft);
134
+ return hasTraceCoverage(draft.resume, draft.trace);
135
+ },
136
+ onAttempt: ({ phase, label, reason, index, total }) => {
137
+ if (phase !== 'failed')
138
+ return;
139
+ const next = index + 1 < total ? '; trying the next provider' : '';
140
+ console.warn(`dossier: ${label} failed: ${reason}${next}`);
141
+ },
142
+ });
143
+ }
144
+ catch (error) {
145
+ const raw = error instanceof LlmError ? error.raw : '';
146
+ if (raw || options.debug) {
147
+ writeFileSync(`${base}.opencode-output.jsonl`, raw);
148
+ }
149
+ if (!(error instanceof LlmError))
150
+ throw error;
151
+ const saved = raw
152
+ ? ` Raw output saved to ${base}.opencode-output.jsonl.`
153
+ : '';
154
+ throw new Error(`${error.message}${saved}`);
155
+ }
156
+ const draft = generated.output;
157
+ if (!draft.resume || typeof draft.resume !== 'object') {
158
+ throw new Error('Model response is missing the "resume" object.');
159
+ }
160
+ if (!draft.trace || typeof draft.trace !== 'object') {
161
+ throw new Error('Model response is missing the "trace" object.');
162
+ }
163
+ if (!draft.resume.$schema) {
164
+ draft.resume.$schema =
165
+ 'https://raw.githubusercontent.com/jsonresume/resume-schema/master/schema.json';
166
+ }
167
+ normalizeNumberSpacing(draft.resume);
168
+ normalizeThemePunctuation(draft.resume);
169
+ const basicsChange = applyBasicsUrlPolicy(draft.resume, career);
170
+ if (basicsChange)
171
+ console.log(`dossier: ${basicsChange}`);
172
+ const removedSkills = filterExcludedSkills(draft.resume, career);
173
+ if (removedSkills.length > 0) {
174
+ console.log(`dossier: removed vague skills: ${removedSkills.join(', ')}`);
175
+ }
176
+ writeResumeFiles(resumePath, tracePath, draft.resume, draft.trace);
177
+ const initialVerification = await verifyTailoredResume({
178
+ resume: draft.resume,
179
+ trace: draft.trace,
180
+ career,
181
+ candidates,
182
+ });
183
+ if (initialVerification.errors.length > 0) {
184
+ writeFileSync(`${base}.opencode-output.jsonl`, generated.raw || '');
185
+ for (const error of initialVerification.errors) {
186
+ console.error(` error: ${error}`);
187
+ }
188
+ throw new Error(`Resume failed verification. Files are preserved at ${resumePath} and ${tracePath}.`);
189
+ }
190
+ const providerLabel = generated.model
191
+ ? `${generated.provider.label} (${generated.model})`
192
+ : `${generated.provider.label} (default model)`;
193
+ console.log(`dossier: draft from ${providerLabel}`);
194
+ if (!options.noRender) {
195
+ let measurer = null;
196
+ try {
197
+ measurer = await createPageMeasurer();
198
+ await ensureOnePage({
199
+ resume: draft.resume,
200
+ trace: draft.trace,
201
+ resumePath,
202
+ tracePath,
203
+ pdfPath,
204
+ htmlPath,
205
+ theme,
206
+ career,
207
+ measurer,
208
+ });
209
+ }
210
+ finally {
211
+ if (measurer)
212
+ await measurer.close();
213
+ rmSync(htmlPath, { force: true });
214
+ }
215
+ console.log('dossier: PDF is 1 page');
216
+ }
217
+ const finalVerification = await verifyTailoredResume({
218
+ resume: draft.resume,
219
+ trace: draft.trace,
220
+ career,
221
+ candidates,
222
+ });
223
+ if (finalVerification.errors.length > 0) {
224
+ for (const error of finalVerification.errors) {
225
+ console.error(` error: ${error}`);
226
+ }
227
+ throw new Error(`Resume failed final verification. Files are preserved at ${resumePath} and ${tracePath}.`);
228
+ }
229
+ for (const warning of finalVerification.warnings) {
230
+ console.warn(`dossier: warning: ${warning}`);
231
+ }
232
+ console.log(`dossier: saved ${displayPath(resumePath)}`);
233
+ console.log(`dossier: saved ${displayPath(tracePath)}`);
234
+ if (!options.noRender) {
235
+ console.log(`dossier: saved ${displayPath(pdfPath)}`);
236
+ }
237
+ if (finalVerification.gaps.length > 0) {
238
+ console.log('dossier: gaps:');
239
+ for (const gap of finalVerification.gaps)
240
+ console.log(` - ${gap}`);
241
+ }
242
+ const shouldOpen = options.open ?? config.output.open;
243
+ if (!options.noRender && shouldOpen) {
244
+ if (!openFile(pdfPath)) {
245
+ console.warn(`dossier: could not open the PDF preview. Open ${pdfPath} manually or pass --no-open.`);
246
+ }
247
+ }
248
+ }
249
+ async function ensureOnePage({ resume, trace, resumePath, tracePath, pdfPath, htmlPath, theme, career, measurer, }) {
250
+ writeResumeFiles(resumePath, tracePath, resume, trace);
251
+ renderHtml(resumePath, htmlPath, theme);
252
+ let height = await measurer.measure(htmlPath);
253
+ console.log(`dossier: draft fill ${Math.round(height)}px (page ${PAGE_CONTENT_HEIGHT}px)`);
254
+ let pages = null;
255
+ if (height <= PAGE_CONTENT_HEIGHT) {
256
+ renderPdf(resumePath, pdfPath, theme);
257
+ pages = await getPdfPageCount(pdfPath);
258
+ if (pages === 1) {
259
+ await ensureFilled({
260
+ resume,
261
+ trace,
262
+ resumePath,
263
+ tracePath,
264
+ pdfPath,
265
+ htmlPath,
266
+ theme,
267
+ career,
268
+ measurer,
269
+ height,
270
+ });
271
+ return;
272
+ }
273
+ console.log(`dossier: HTML fits but PDF is ${pages} pages; trimming further`);
274
+ }
275
+ else {
276
+ console.log(`dossier: draft is over one page (${Math.round(height)}px); trimming`);
277
+ }
278
+ for (let level = 0; level < TRIM_PLANS.length; level += 1) {
279
+ if (!trimResume(resume, trace, level))
280
+ continue;
281
+ writeResumeFiles(resumePath, tracePath, resume, trace);
282
+ renderHtml(resumePath, htmlPath, theme);
283
+ height = await measurer.measure(htmlPath);
284
+ if (height > PAGE_CONTENT_HEIGHT) {
285
+ console.log(`dossier: trim attempt ${level + 1}: ${Math.round(height)}px; still too tall`);
286
+ continue;
287
+ }
288
+ renderPdf(resumePath, pdfPath, theme);
289
+ pages = await getPdfPageCount(pdfPath);
290
+ if (pages === 1) {
291
+ console.log('dossier: PDF now fits on one page');
292
+ await ensureFilled({
293
+ resume,
294
+ trace,
295
+ resumePath,
296
+ tracePath,
297
+ pdfPath,
298
+ htmlPath,
299
+ theme,
300
+ career,
301
+ measurer,
302
+ height,
303
+ });
304
+ return;
305
+ }
306
+ console.log(`dossier: trim attempt ${level + 1}: HTML fits but PDF is ${pages} pages`);
307
+ }
308
+ throw new Error(pages == null
309
+ ? `Resume is still too tall after trimming. Files are preserved at ${resumePath} and ${tracePath}.`
310
+ : `PDF is still ${pages} pages after trimming. Files are preserved at ${resumePath} and ${tracePath}.`);
311
+ }
312
+ async function ensureFilled({ resume, trace, resumePath, tracePath, pdfPath, htmlPath, theme, career, measurer, height: initialHeight, }) {
313
+ let height = initialHeight;
314
+ console.log(`dossier: content fill ${Math.round(height)}px (minimum ${MIN_FILL_HEIGHT}px, page ${PAGE_CONTENT_HEIGHT}px)`);
315
+ if (height >= MIN_FILL_HEIGHT)
316
+ return;
317
+ const unused = collectUnusedAchievements(career, trace);
318
+ console.log(`dossier: page is sparse; trying ${unused.length} unused achievement(s)`);
319
+ for (const candidate of unused) {
320
+ const insertion = appendAchievement(resume, trace, candidate);
321
+ if (!insertion)
322
+ continue;
323
+ writeResumeFiles(resumePath, tracePath, resume, trace);
324
+ renderHtml(resumePath, htmlPath, theme);
325
+ const next = await measurer.measure(htmlPath);
326
+ if (next > PAGE_CONTENT_HEIGHT) {
327
+ removeLastHighlight(resume, trace, insertion.index);
328
+ writeResumeFiles(resumePath, tracePath, resume, trace);
329
+ continue;
330
+ }
331
+ height = next;
332
+ console.log(`dossier: added ${candidate.achievement.id}; fill ${Math.round(height)}px`);
333
+ if (height >= MIN_FILL_HEIGHT)
334
+ break;
335
+ }
336
+ if (height < MIN_FILL_HEIGHT) {
337
+ renderPdf(resumePath, pdfPath, theme);
338
+ throw new Error(`PDF fits on one page but is too sparse (${Math.round(height)}px; minimum ${MIN_FILL_HEIGHT}px). Add more achievements to career.yml. Files are preserved at ${resumePath} and ${tracePath}.`);
339
+ }
340
+ renderPdf(resumePath, pdfPath, theme);
341
+ const pages = await getPdfPageCount(pdfPath);
342
+ if (pages !== 1) {
343
+ throw new Error(`PDF is ${pages} pages after filling. Files are preserved at ${resumePath} and ${tracePath}.`);
344
+ }
345
+ }
346
+ function writeResumeFiles(resumePath, tracePath, resume, trace) {
347
+ writeFileSync(resumePath, `${JSON.stringify(resume, null, '\t')}\n`);
348
+ writeFileSync(tracePath, `${JSON.stringify(trace, null, '\t')}\n`);
349
+ }
350
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/resume/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Career } from '../career/schema.js';
2
+ import type { Resume } from './types.js';
3
+ export declare function filterExcludedSkills(resume: Resume, career: Career): string[];
4
+ export declare function findExcludedSkills(resume: Resume, career: Career): string[];
5
+ export declare function excludedSkillSet(career: Career): Set<string>;
6
+ export declare function normalizeSkill(value: unknown): string;
@@ -0,0 +1,47 @@
1
+ export function filterExcludedSkills(resume, career) {
2
+ const excluded = excludedSkillSet(career);
3
+ if (excluded.size === 0)
4
+ return [];
5
+ const groups = Array.isArray(resume.skills) ? resume.skills : [];
6
+ const removed = [];
7
+ for (const group of groups) {
8
+ if (!Array.isArray(group.keywords))
9
+ continue;
10
+ group.keywords = group.keywords.filter((keyword) => {
11
+ if (!excluded.has(normalizeSkill(keyword)))
12
+ return true;
13
+ removed.push(String(keyword));
14
+ return false;
15
+ });
16
+ }
17
+ for (let index = groups.length - 1; index >= 0; index -= 1) {
18
+ const keywords = groups[index].keywords;
19
+ if (!Array.isArray(keywords) || keywords.length === 0) {
20
+ groups.splice(index, 1);
21
+ }
22
+ }
23
+ return [...new Set(removed)];
24
+ }
25
+ export function findExcludedSkills(resume, career) {
26
+ const excluded = excludedSkillSet(career);
27
+ if (excluded.size === 0)
28
+ return [];
29
+ const found = [];
30
+ for (const group of resume.skills ?? []) {
31
+ for (const keyword of group.keywords ?? []) {
32
+ if (excluded.has(normalizeSkill(keyword)))
33
+ found.push(String(keyword));
34
+ }
35
+ }
36
+ return [...new Set(found)];
37
+ }
38
+ export function excludedSkillSet(career) {
39
+ return new Set(career.skillExclude.map((skill) => normalizeSkill(skill)));
40
+ }
41
+ export function normalizeSkill(value) {
42
+ return String(value ?? '')
43
+ .toLowerCase()
44
+ .replace(/[^a-z0-9]+/g, ' ')
45
+ .trim();
46
+ }
47
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/resume/skills.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,MAAc;IAEd,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,SAAS;QAC7C,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;YACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC,QAAQ,CAAC;QACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAc,EACd,MAAc;IAEd,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACvB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Resume, TailoredDraft, Trace } from './types.js';
2
+ /**
3
+ * Catch the common failure where a resume bullet has no trace receipt before
4
+ * running the full verifier.
5
+ */
6
+ export declare function hasTraceCoverage(resume: Resume, trace: Trace): boolean;
7
+ /**
8
+ * Some drafts list project evidence at the project level but omit the
9
+ * per-highlight trace bullets. Fill those in from the project trace when the
10
+ * evidence count makes the mapping unambiguous; otherwise attach the project's
11
+ * evidence list to each missing highlight. Returns true when anything changed.
12
+ */
13
+ export declare function fillProjectBulletTrace(draft: TailoredDraft): boolean;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Catch the common failure where a resume bullet has no trace receipt before
3
+ * running the full verifier.
4
+ */
5
+ export function hasTraceCoverage(resume, trace) {
6
+ if (!resume || typeof resume !== 'object')
7
+ return false;
8
+ if (!trace || typeof trace !== 'object')
9
+ return false;
10
+ const bulletPaths = new Set((Array.isArray(trace.bullets) ? trace.bullets : [])
11
+ .map((entry) => entry?.path)
12
+ .filter(Boolean));
13
+ const projectNames = new Set((Array.isArray(trace.projects) ? trace.projects : [])
14
+ .map((entry) => entry?.name)
15
+ .filter(Boolean));
16
+ for (const [workIndex, work] of (resume.work ?? []).entries()) {
17
+ const highlights = Array.isArray(work.highlights) ? work.highlights : [];
18
+ for (let highlightIndex = 0; highlightIndex < highlights.length; highlightIndex += 1) {
19
+ if (!bulletPaths.has(`work[${workIndex}].highlights[${highlightIndex}]`)) {
20
+ return false;
21
+ }
22
+ }
23
+ }
24
+ for (const [projectIndex, project] of (resume.projects ?? []).entries()) {
25
+ if (!projectNames.has(project.name ?? ''))
26
+ return false;
27
+ const highlights = Array.isArray(project.highlights)
28
+ ? project.highlights
29
+ : [];
30
+ for (let highlightIndex = 0; highlightIndex < highlights.length; highlightIndex += 1) {
31
+ if (!bulletPaths.has(`projects[${projectIndex}].highlights[${highlightIndex}]`)) {
32
+ return false;
33
+ }
34
+ }
35
+ }
36
+ return true;
37
+ }
38
+ /**
39
+ * Some drafts list project evidence at the project level but omit the
40
+ * per-highlight trace bullets. Fill those in from the project trace when the
41
+ * evidence count makes the mapping unambiguous; otherwise attach the project's
42
+ * evidence list to each missing highlight. Returns true when anything changed.
43
+ */
44
+ export function fillProjectBulletTrace(draft) {
45
+ let changed = false;
46
+ const bullets = Array.isArray(draft.trace.bullets)
47
+ ? draft.trace.bullets
48
+ : [];
49
+ const paths = new Set(bullets.map((entry) => entry.path));
50
+ const projectTrace = new Map((draft.trace.projects ?? []).map((entry) => [entry.name, entry]));
51
+ for (const [projectIndex, project] of (draft.resume.projects ?? []).entries()) {
52
+ const traceProject = projectTrace.get(project.name ?? '');
53
+ if (!traceProject)
54
+ continue;
55
+ const evidence = Array.isArray(traceProject.evidence)
56
+ ? traceProject.evidence
57
+ : [];
58
+ const highlights = Array.isArray(project.highlights)
59
+ ? project.highlights
60
+ : [];
61
+ for (let highlightIndex = 0; highlightIndex < highlights.length; highlightIndex += 1) {
62
+ const path = `projects[${projectIndex}].highlights[${highlightIndex}]`;
63
+ if (paths.has(path))
64
+ continue;
65
+ const chosen = evidence.length === highlights.length
66
+ ? [evidence[highlightIndex]]
67
+ : evidence;
68
+ if (chosen.length === 0)
69
+ continue;
70
+ bullets.push({
71
+ path,
72
+ evidence: chosen,
73
+ source: traceProject.source ?? 'career',
74
+ });
75
+ paths.add(path);
76
+ changed = true;
77
+ }
78
+ }
79
+ draft.trace.bullets = bullets;
80
+ return changed;
81
+ }
82
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/resume/trace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ export interface ResumeLocation {
2
+ address?: string;
3
+ postalCode?: string;
4
+ city?: string;
5
+ countryCode?: string;
6
+ region?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export interface ResumeProfile {
10
+ network?: string;
11
+ username?: string;
12
+ url?: string;
13
+ [key: string]: unknown;
14
+ }
15
+ export interface ResumeBasics {
16
+ name?: string;
17
+ label?: string;
18
+ image?: string;
19
+ email?: string;
20
+ phone?: string;
21
+ url?: string;
22
+ summary?: string;
23
+ location?: ResumeLocation;
24
+ profiles?: ResumeProfile[];
25
+ [key: string]: unknown;
26
+ }
27
+ export interface ResumeWork {
28
+ name?: string;
29
+ position?: string;
30
+ url?: string;
31
+ startDate?: string;
32
+ endDate?: string;
33
+ summary?: string;
34
+ highlights?: string[];
35
+ [key: string]: unknown;
36
+ }
37
+ export interface ResumeProject {
38
+ name?: string;
39
+ description?: string;
40
+ highlights?: string[];
41
+ keywords?: string[];
42
+ url?: string;
43
+ [key: string]: unknown;
44
+ }
45
+ export interface ResumeSkillGroup {
46
+ name?: string;
47
+ level?: string;
48
+ keywords?: string[];
49
+ [key: string]: unknown;
50
+ }
51
+ export interface ResumeEducation {
52
+ institution?: string;
53
+ url?: string;
54
+ area?: string;
55
+ studyType?: string;
56
+ startDate?: string;
57
+ endDate?: string;
58
+ score?: string;
59
+ courses?: string[];
60
+ [key: string]: unknown;
61
+ }
62
+ export interface Resume {
63
+ $schema?: string;
64
+ basics?: ResumeBasics;
65
+ work?: ResumeWork[];
66
+ projects?: ResumeProject[];
67
+ skills?: ResumeSkillGroup[];
68
+ education?: ResumeEducation[];
69
+ [key: string]: unknown;
70
+ }
71
+ export interface TraceBullet {
72
+ path: string;
73
+ evidence?: string[];
74
+ source?: string;
75
+ [key: string]: unknown;
76
+ }
77
+ export interface TraceProject {
78
+ name: string;
79
+ evidence?: string[];
80
+ source?: string;
81
+ [key: string]: unknown;
82
+ }
83
+ export interface Trace {
84
+ summary_evidence?: string[];
85
+ bullets?: TraceBullet[];
86
+ projects?: TraceProject[];
87
+ requirements?: unknown[];
88
+ gaps?: unknown[];
89
+ [key: string]: unknown;
90
+ }
91
+ export interface TailoredDraft {
92
+ resume: Resume;
93
+ trace: Trace;
94
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/resume/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import type { Career } from '../career/schema.js';
2
+ import { type Candidate } from '../evidence/verify.js';
3
+ import type { Resume, Trace } from './types.js';
4
+ export interface VerifyResumeInput {
5
+ resume: Resume;
6
+ trace: Trace;
7
+ career: Career;
8
+ candidates?: Candidate[];
9
+ }
10
+ export interface VerifyResumeResult {
11
+ errors: string[];
12
+ warnings: string[];
13
+ gaps: string[];
14
+ }
15
+ export declare function verifyTailoredResume({ resume, trace, career, candidates, }: VerifyResumeInput): Promise<VerifyResumeResult>;
16
+ export declare function validateResumeSchema(resume: Resume): Promise<{
17
+ valid: boolean;
18
+ errors: string[];
19
+ }>;