@rwendell/dossier 0.0.0-stage → 0.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.
Files changed (166) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -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 +83 -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 +85 -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 +34 -0
  64. package/dist/config/paths.js +126 -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 +46 -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,386 @@
1
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import clipboard from 'clipboardy';
4
+ import { loadCareer } from '../career/load.js';
5
+ import { loadConfig } from '../config/config.js';
6
+ import { displayPath, getRuntimeDir, resolveOutputDir, } from '../config/paths.js';
7
+ import { verifyProposal, } from '../evidence/verify.js';
8
+ import { readJobInput } from '../job/input.js';
9
+ import { ensureAgents, reloadOpencode } from '../llm/agents.js';
10
+ import { LlmError, runAgent } from '../llm/providers.js';
11
+ import { hasProjectCache, loadCandidates, } from '../projects/store.js';
12
+ import { findTailoredResume } from '../resume/find.js';
13
+ import { slugify } from '../util/slug.js';
14
+ import { applyProfileToCareer, loadUpworkProfile, mapProfilePortfolio, } from '../upwork/profile.js';
15
+ import { buildProposalSettings, describeBudget, extractRequiredOpening, formatRate, loadFreelanceConfig, parseBudget, } from '../upwork/settings.js';
16
+ import { buildProposalPrompt } from './prompt.js';
17
+ export async function runProposal(options) {
18
+ const { config } = loadConfig();
19
+ const { config: freelanceConfig, path: freelanceConfigPath } = loadFreelanceConfig();
20
+ const configuredProfileUrl = typeof freelanceConfig.profile === 'string'
21
+ ? freelanceConfig.profile
22
+ : freelanceConfig.profile?.url;
23
+ const profileUrl = options.profile ||
24
+ (!options.noProfile ? configuredProfileUrl : '') ||
25
+ '';
26
+ let profile = null;
27
+ if (profileUrl) {
28
+ try {
29
+ profile = await loadUpworkProfile(profileUrl, {
30
+ refresh: options.refresh,
31
+ log: (message) => console.log(`dossier: ${message}`),
32
+ warn: (message) => console.warn(`dossier: ${message}`),
33
+ });
34
+ }
35
+ catch (error) {
36
+ if (options.profile)
37
+ throw error;
38
+ console.warn(`dossier: could not load configured Upwork profile: ${error.message}`);
39
+ }
40
+ }
41
+ const { career } = loadCareer();
42
+ if (profile)
43
+ applyProfileToCareer(career, profile);
44
+ const settings = buildProposalSettings(freelanceConfig, {
45
+ rate: options.rate,
46
+ rateType: options.rateType,
47
+ noRate: options.noRate,
48
+ availability: options.availability,
49
+ timeline: options.timeline,
50
+ profile: options.profile,
51
+ noProfile: options.noProfile,
52
+ }, profile);
53
+ const questions = readQuestions(options);
54
+ const hint = readHints(options.hint);
55
+ const client = readTextInput(options.client);
56
+ const job = await readJobInput({
57
+ input: options.input,
58
+ title: options.title,
59
+ company: options.company,
60
+ url: options.url,
61
+ description: options.description,
62
+ });
63
+ if (!job.title) {
64
+ throw new Error('Could not determine a job title. Pass --title, or use a job URL/file with a title.');
65
+ }
66
+ const slug = slugify([job.company, job.title].filter(Boolean).join(' ')) ||
67
+ 'upwork-job';
68
+ const candidates = loadCandidates(career, job);
69
+ if (candidates.length === 0 && !hasProjectCache()) {
70
+ console.warn('dossier: no project metadata cached; run `dossier sync github` or `dossier sync local` to include repositories.');
71
+ }
72
+ const mappedPortfolio = mapProfilePortfolio(profile, career, candidates);
73
+ if (profile) {
74
+ profile.portfolio = mappedPortfolio.portfolio;
75
+ profile.preferredSamples = mappedPortfolio.preferredSamples;
76
+ if (!Array.isArray(freelanceConfig.preferredSamples) ||
77
+ freelanceConfig.preferredSamples.length === 0) {
78
+ settings.preferredSamples = mappedPortfolio.preferredSamples;
79
+ }
80
+ }
81
+ const requiredOpening = extractRequiredOpening(job.body);
82
+ warnAboutBudget(job, settings);
83
+ const outDir = resolveOutputDir(config.output.dir, options.out);
84
+ mkdirSync(outDir, { recursive: true });
85
+ const nameSlug = options.name
86
+ ? slugify(options.name).slice(0, 70) || 'proposal'
87
+ : '';
88
+ const base = resolve(outDir, `proposal-${slug}${nameSlug ? `.${nameSlug}` : ''}`);
89
+ const markdownPath = `${base}.md`;
90
+ const jsonPath = `${base}.json`;
91
+ const tailored = findTailoredResume(slug, outDir);
92
+ if (tailored) {
93
+ console.log(`dossier: using tailored resume ${displayPath(tailored.resumePath)}`);
94
+ }
95
+ const prompt = buildProposalPrompt({
96
+ career,
97
+ job,
98
+ slug,
99
+ candidates,
100
+ profile,
101
+ client,
102
+ hint,
103
+ settings,
104
+ questions,
105
+ requiredOpening,
106
+ resume: tailored?.resume,
107
+ trace: tailored?.trace,
108
+ });
109
+ console.log(`dossier: ${job.company ? `${job.company} — ` : ''}${job.title}`);
110
+ if (job.details?.budget) {
111
+ console.log(`dossier: client budget ${describeBudget(job.details)}`);
112
+ }
113
+ if (profile) {
114
+ const location = [
115
+ profile.location.city,
116
+ profile.location.region,
117
+ profile.location.countryCode,
118
+ ]
119
+ .filter(Boolean)
120
+ .join(', ');
121
+ console.log(`dossier: profile ${profile.name || profile.url}${profile.rate ? ` — ${formatRate(profile.rate)}` : ''}${location ? ` — ${location}` : ''}`);
122
+ }
123
+ console.log(`dossier: ${questions.length} screening question(s); output ${displayPath(markdownPath)}`);
124
+ if (options.debug) {
125
+ writeFileSync(`${base}.prompt.txt`, prompt);
126
+ }
127
+ ensureAgents();
128
+ reloadOpencode();
129
+ let generated;
130
+ try {
131
+ generated = runAgent({
132
+ prompt,
133
+ agent: 'dossier-proposer',
134
+ title: `Proposal: ${slug}`,
135
+ timeout: options.timeout ?? 10 * 60 * 1000,
136
+ cwd: getRuntimeDir(),
137
+ provider: options.provider,
138
+ model: options.model,
139
+ accept: (value) => Boolean(value &&
140
+ typeof value.proposal === 'string' &&
141
+ value.proposal.trim()),
142
+ onAttempt: ({ phase, label, reason, index, total }) => {
143
+ if (phase !== 'failed')
144
+ return;
145
+ const next = index + 1 < total ? '; trying the next provider' : '';
146
+ console.warn(`dossier: ${label} failed: ${reason}${next}`);
147
+ },
148
+ });
149
+ }
150
+ catch (error) {
151
+ const raw = error instanceof LlmError ? error.raw : '';
152
+ if (raw || options.debug) {
153
+ writeFileSync(`${base}.opencode-output.jsonl`, raw);
154
+ }
155
+ if (!(error instanceof LlmError))
156
+ throw error;
157
+ const saved = raw
158
+ ? ` Raw output saved to ${base}.opencode-output.jsonl.`
159
+ : '';
160
+ throw new Error(`${error.message}${saved}`);
161
+ }
162
+ const output = generated.output;
163
+ if (typeof output.proposal !== 'string' || !output.proposal.trim()) {
164
+ throw new Error('Model response is missing a non-empty "proposal" string.');
165
+ }
166
+ const providerLabel = generated.model
167
+ ? `${generated.provider.label} (${generated.model})`
168
+ : `${generated.provider.label} (default model)`;
169
+ console.log(`dossier: draft from ${providerLabel}`);
170
+ if ((generated.stats?.cost ?? 0) > 0) {
171
+ const stats = generated.stats;
172
+ const tokens = stats.input != null
173
+ ? `, ${stats.input} in / ${stats.output ?? '?'} out tokens`
174
+ : '';
175
+ console.log(`dossier: model cost $${stats.cost.toFixed(4)}${tokens}`);
176
+ }
177
+ const verification = verifyProposal({
178
+ output,
179
+ career,
180
+ candidates,
181
+ hint,
182
+ client,
183
+ settings,
184
+ job,
185
+ questions,
186
+ requiredOpening,
187
+ timeline: settings.timeline,
188
+ profile,
189
+ });
190
+ if (verification.errors.length > 0) {
191
+ writeFileSync(`${base}.opencode-output.jsonl`, generated.raw || '');
192
+ for (const error of verification.errors) {
193
+ console.error(` error: ${error}`);
194
+ }
195
+ for (const warning of verification.warnings) {
196
+ console.error(` warning: ${warning}`);
197
+ }
198
+ throw new Error(`Proposal failed verification. Raw output saved to ${base}.opencode-output.jsonl.`);
199
+ }
200
+ if (options.debug) {
201
+ writeFileSync(`${base}.prompt.txt`, prompt);
202
+ writeFileSync(`${base}.opencode-output.jsonl`, generated.raw || '');
203
+ }
204
+ const proposal = output.proposal.trim();
205
+ const screeningAnswers = Array.isArray(output.screening_answers)
206
+ ? output.screening_answers
207
+ : [];
208
+ const samples = Array.isArray(output.samples) ? output.samples : [];
209
+ const rate = output.rate ?? settings.rate ?? null;
210
+ const timeline = output.timeline ?? settings.timeline ?? null;
211
+ const availability = output.availability ?? settings.availability ?? null;
212
+ writeFileSync(markdownPath, `${proposal}\n`);
213
+ writeFileSync(jsonPath, `${JSON.stringify({
214
+ job: {
215
+ company: job.company,
216
+ title: job.title,
217
+ url: job.url,
218
+ slug,
219
+ details: job.details ?? {},
220
+ },
221
+ client: client || job.details?.client || null,
222
+ profile: profile
223
+ ? {
224
+ url: profile.url,
225
+ name: profile.name,
226
+ title: profile.title,
227
+ location: profile.location,
228
+ rate: profile.rate,
229
+ hoursPerWeek: profile.hoursPerWeek,
230
+ summary: profile.summary,
231
+ skills: profile.skills,
232
+ portfolio: profile.portfolio,
233
+ fetchedAt: profile.fetchedAt,
234
+ cached: Boolean(profile.cached),
235
+ }
236
+ : null,
237
+ questions,
238
+ requiredOpening: requiredOpening || null,
239
+ proposal,
240
+ hook: output.hook ?? null,
241
+ screeningAnswers,
242
+ rate,
243
+ timeline,
244
+ availability,
245
+ samples,
246
+ claims: output.claims ?? [],
247
+ evidence: output.evidence ?? [],
248
+ gaps: output.gaps ?? [],
249
+ fit: output.fit ?? null,
250
+ settings: {
251
+ targetWords: settings.targetWords,
252
+ minWords: settings.minWords,
253
+ maxWords: settings.maxWords,
254
+ maxChars: settings.maxChars,
255
+ includeRate: settings.includeRate,
256
+ includeAvailability: settings.includeAvailability,
257
+ profileUrl: settings.profileUrl || null,
258
+ },
259
+ provider: generated.provider.label,
260
+ model: generated.model,
261
+ cost: generated.stats?.cost ?? 0,
262
+ generatedAt: new Date().toISOString(),
263
+ sources: {
264
+ freelance: freelanceConfigPath,
265
+ profile: profile?.cachePath ?? null,
266
+ resume: tailored?.resumePath ?? null,
267
+ trace: tailored?.tracePath ?? null,
268
+ },
269
+ }, null, '\t')}\n`);
270
+ for (const warning of verification.warnings) {
271
+ console.warn(`dossier: warning: ${warning}`);
272
+ }
273
+ console.log(`dossier: verified ${verification.claimCount} claim(s), ${verification.evidenceCount} evidence id(s), ${verification.wordCount} words`);
274
+ console.log(`dossier: saved ${markdownPath}`);
275
+ if (!options.noCopy) {
276
+ try {
277
+ await clipboard.write(proposal);
278
+ console.log('dossier: copied to clipboard');
279
+ }
280
+ catch {
281
+ console.warn(`dossier: could not copy to clipboard. Proposal saved at ${markdownPath}.`);
282
+ }
283
+ }
284
+ console.log('');
285
+ console.log(proposal);
286
+ const logistics = [];
287
+ if (rate)
288
+ logistics.push(`rate: ${formatRate(rate)}`);
289
+ if (timeline)
290
+ logistics.push(`timeline: ${timeline}`);
291
+ if (availability)
292
+ logistics.push(`availability: ${availability}`);
293
+ if (logistics.length > 0) {
294
+ console.log('');
295
+ for (const line of logistics)
296
+ console.log(`dossier: ${line}`);
297
+ }
298
+ if (screeningAnswers.length > 0) {
299
+ console.log('');
300
+ console.log('dossier: screening answers:');
301
+ for (const entry of screeningAnswers) {
302
+ console.log(` Q: ${entry.question ?? ''}`);
303
+ console.log(` A: ${entry.answer}`);
304
+ console.log('');
305
+ }
306
+ }
307
+ if (samples.length > 0) {
308
+ console.log('dossier: suggested samples:');
309
+ for (const sample of samples) {
310
+ const label = sample.title || sample.evidence;
311
+ console.log(` - ${label} (${sample.evidence})${sample.why ? ` — ${sample.why}` : ''}`);
312
+ }
313
+ }
314
+ if (output.fit) {
315
+ const fit = output.fit;
316
+ console.log('');
317
+ console.log(`dossier: fit ${fit.verdict}${Array.isArray(fit.reasons) && fit.reasons.length > 0
318
+ ? ` — ${fit.reasons.join('; ')}`
319
+ : ''}`);
320
+ for (const concern of fit.concerns ?? []) {
321
+ console.log(` concern: ${concern}`);
322
+ }
323
+ }
324
+ if ((output.gaps ?? []).length > 0) {
325
+ console.log('');
326
+ console.log('dossier: gaps:');
327
+ for (const gap of output.gaps ?? [])
328
+ console.log(` - ${gap}`);
329
+ }
330
+ }
331
+ function readQuestions(options) {
332
+ const questions = [];
333
+ for (const value of options.question ?? []) {
334
+ const text = readTextInput(value);
335
+ if (!text)
336
+ continue;
337
+ questions.push(...text
338
+ .split(/\n\s*\n/)
339
+ .map((entry) => entry.trim())
340
+ .filter(Boolean));
341
+ }
342
+ if (options.questions) {
343
+ const path = resolve(process.cwd(), options.questions);
344
+ if (!existsSync(path) || !statSync(path).isFile()) {
345
+ throw new Error(`Questions file not found: ${options.questions}`);
346
+ }
347
+ const text = readFileSync(path, 'utf8');
348
+ for (const line of text.split('\n')) {
349
+ const trimmed = line.replace(/^\s*(?:[-*]|\d+[.)])\s*/, '').trim();
350
+ if (trimmed)
351
+ questions.push(trimmed);
352
+ }
353
+ }
354
+ return [...new Set(questions)];
355
+ }
356
+ function readHints(values) {
357
+ if (!Array.isArray(values))
358
+ return '';
359
+ return values
360
+ .map((value) => readTextInput(value))
361
+ .filter(Boolean)
362
+ .join('\n\n');
363
+ }
364
+ function readTextInput(value) {
365
+ if (!value)
366
+ return '';
367
+ const path = resolve(process.cwd(), value);
368
+ if (existsSync(path) && statSync(path).isFile()) {
369
+ return readFileSync(path, 'utf8').trim();
370
+ }
371
+ return String(value).trim();
372
+ }
373
+ function warnAboutBudget(job, settings) {
374
+ const budget = parseBudget(job.details?.budget);
375
+ if (budget &&
376
+ settings.minHourlyRate &&
377
+ job.details?.budgetType !== 'fixed' &&
378
+ budget.max < settings.minHourlyRate) {
379
+ console.warn(`dossier: job budget ${describeBudget(job.details)} is below your minimum hourly rate ${formatRate({
380
+ type: 'hourly',
381
+ amount: settings.minHourlyRate,
382
+ currency: settings.currency,
383
+ })}`);
384
+ }
385
+ }
386
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/proposal/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Career } from '../career/schema.js';
2
+ import type { Resume } from './types.js';
3
+ export declare function applyBasicsUrlPolicy(resume: Resume, career: Career): string | null;
4
+ export declare function checkBasicsUrl(resume: Resume, career: Career): string | null;
@@ -0,0 +1,33 @@
1
+ export function applyBasicsUrlPolicy(resume, career) {
2
+ const basics = resume?.basics;
3
+ if (!basics || typeof basics !== 'object')
4
+ return null;
5
+ const sourceUrl = normalizeUrl(career.basics?.url);
6
+ if (sourceUrl) {
7
+ if (basics.url === sourceUrl)
8
+ return null;
9
+ basics.url = sourceUrl;
10
+ return 'basics.url set from the career fact bank';
11
+ }
12
+ if (basics.url == null)
13
+ return null;
14
+ delete basics.url;
15
+ return 'removed basics.url because the career fact bank has no website';
16
+ }
17
+ export function checkBasicsUrl(resume, career) {
18
+ const resumeUrl = normalizeUrl(resume.basics?.url);
19
+ const careerUrl = normalizeUrl(career.basics?.url);
20
+ if (resumeUrl && !careerUrl) {
21
+ return `basics.url "${resumeUrl}" is not in the career fact bank; add it there or remove it from the resume`;
22
+ }
23
+ if (resumeUrl && careerUrl && resumeUrl !== careerUrl) {
24
+ return `basics.url changed: "${resumeUrl}" != "${careerUrl}"`;
25
+ }
26
+ return null;
27
+ }
28
+ function normalizeUrl(value) {
29
+ if (typeof value !== 'string')
30
+ return null;
31
+ return value.trim() || null;
32
+ }
33
+ //# sourceMappingURL=basics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basics.js","sourceRoot":"","sources":["../../src/resume/basics.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,MAAc;IAEd,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC;QACvB,OAAO,0CAA0C,CAAC;IACpD,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,MAAM,CAAC,GAAG,CAAC;IAClB,OAAO,gEAAgE,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,MAAc;IAEd,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnD,IAAI,SAAS,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,OAAO,eAAe,SAAS,6EAA6E,CAAC;IAC/G,CAAC;IACD,IAAI,SAAS,IAAI,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO,wBAAwB,SAAS,SAAS,SAAS,GAAG,CAAC;IAChE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Resume, Trace } from './types.js';
2
+ export interface FoundTailoredResume {
3
+ resume: Resume;
4
+ trace: Trace | null;
5
+ resumePath: string;
6
+ tracePath: string | null;
7
+ }
8
+ /**
9
+ * Find a resume produced by `dossier tailor` for the same job slug. Proposal
10
+ * and answer use it as primary framing when present.
11
+ */
12
+ export declare function findTailoredResume(slug: string, outDir: string, cwd?: string): FoundTailoredResume | null;
@@ -0,0 +1,27 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * Find a resume produced by `dossier tailor` for the same job slug. Proposal
5
+ * and answer use it as primary framing when present.
6
+ */
7
+ export function findTailoredResume(slug, outDir, cwd = process.cwd()) {
8
+ const candidates = [
9
+ join(outDir, `resume-${slug}.json`),
10
+ join(cwd, `resume-${slug}.json`),
11
+ ];
12
+ for (const resumePath of [...new Set(candidates)]) {
13
+ if (!existsSync(resumePath))
14
+ continue;
15
+ const tracePath = resumePath.replace(/\.json$/i, '.trace.json');
16
+ return {
17
+ resume: JSON.parse(readFileSync(resumePath, 'utf8')),
18
+ trace: existsSync(tracePath)
19
+ ? JSON.parse(readFileSync(tracePath, 'utf8'))
20
+ : null,
21
+ resumePath,
22
+ tracePath: existsSync(tracePath) ? tracePath : null,
23
+ };
24
+ }
25
+ return null;
26
+ }
27
+ //# sourceMappingURL=find.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../src/resume/find.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAUjC;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,MAAc,EACd,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAEnB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,MAAM,EAAE,UAAU,IAAI,OAAO,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,UAAU,IAAI,OAAO,CAAC;KACjC,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QACtC,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAChE,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAW;YAC9D,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC;gBAC1B,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAW;gBACxD,CAAC,CAAC,IAAI;YACR,UAAU;YACV,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;SACpD,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Resume } from './types.js';
2
+ export declare function normalizeNumberSpacing(resume: Resume): boolean;
3
+ export declare function normalizeThemePunctuation(resume: Resume): boolean;
@@ -0,0 +1,53 @@
1
+ export function normalizeNumberSpacing(resume) {
2
+ let changed = false;
3
+ const fix = (value) => {
4
+ const text = String(value);
5
+ const next = text.replace(/(\d)\.\s+(\d)/g, '$1.$2');
6
+ if (next !== text)
7
+ changed = true;
8
+ return next;
9
+ };
10
+ if (resume.basics?.summary) {
11
+ resume.basics.summary = fix(resume.basics.summary);
12
+ }
13
+ for (const role of resume.work ?? []) {
14
+ if (role.summary)
15
+ role.summary = fix(role.summary);
16
+ if (Array.isArray(role.highlights)) {
17
+ role.highlights = role.highlights.map(fix);
18
+ }
19
+ }
20
+ for (const project of resume.projects ?? []) {
21
+ if (project.description)
22
+ project.description = fix(project.description);
23
+ if (Array.isArray(project.highlights)) {
24
+ project.highlights = project.highlights.map(fix);
25
+ }
26
+ }
27
+ return changed;
28
+ }
29
+ export function normalizeThemePunctuation(resume) {
30
+ let changed = false;
31
+ for (const project of resume.projects ?? []) {
32
+ if (!Array.isArray(project.highlights))
33
+ continue;
34
+ project.highlights = project.highlights.map((highlight) => {
35
+ const cleaned = String(highlight).replace(/[.!?]+$/, '').trim();
36
+ if (cleaned !== highlight)
37
+ changed = true;
38
+ return cleaned;
39
+ });
40
+ }
41
+ for (const group of resume.skills ?? []) {
42
+ if (!Array.isArray(group.keywords))
43
+ continue;
44
+ group.keywords = group.keywords.map((keyword) => {
45
+ const cleaned = String(keyword).replace(/[.!?]+$/, '').trim();
46
+ if (cleaned !== keyword)
47
+ changed = true;
48
+ return cleaned;
49
+ });
50
+ }
51
+ return changed;
52
+ }
53
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/resume/format.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,GAAG,GAAG,CAAC,KAAa,EAAU,EAAE;QACpC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACrD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,GAAG,IAAI,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,WAAW;YAAE,OAAO,CAAC,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACxE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;YAAE,SAAS;QACjD,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;YACxD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAChE,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,GAAG,IAAI,CAAC;YAC1C,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,SAAS;QAC7C,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9D,IAAI,OAAO,KAAK,OAAO;gBAAE,OAAO,GAAG,IAAI,CAAC;YACxC,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}