tor-to-proposal 2.1.4 → 2.1.6

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/bin/bid-pack.mjs CHANGED
@@ -117,7 +117,19 @@ function buildQuestions() {
117
117
  : f === 'financial-proposal.md' && /tax/.test(detail) ? 'TAXES'
118
118
  : null;
119
119
  const id = known ? `Q-FILL-${known}` : 'Q-FILL-' + crypto.createHash('md5').update(f + '|' + excerpt).digest('hex').slice(0, 8);
120
- add({ id, area: 'draft-fill', type: 'string', question: `${f}: a placeholder needs a real fact — “…${excerpt}…”. What is the fact?`, why: 'No invented facts. If you cannot supply it, it stays [FILL] and the audit blocks submission.' });
120
+ // known slots get plain-language questions; unknown ones keep the raw excerpt
121
+ const friendly = known === 'CONSULTANT'
122
+ ? `financial-proposal.md: whose name goes in the consultant line of the financial proposal? (Usually you — exactly as on your CV.)`
123
+ : known === 'REIMBURSABLES'
124
+ ? `financial-proposal.md: which costs does the client reimburse on top of your fee? Write ONE clear sentence — or write none if nothing is reimbursable (the row is then removed).`
125
+ : known === 'TAXES'
126
+ ? `financial-proposal.md: what is the tax treatment of your prices? ONE sentence, e.g. "All amounts are exclusive of VAT" or "All amounts are tax-inclusive".`
127
+ : null;
128
+ add({
129
+ id, area: 'draft-fill', type: 'string',
130
+ question: friendly || `${f}: a placeholder needs a real fact — “…${excerpt}…”. What is the fact?`,
131
+ why: 'No invented facts. If you cannot supply it, it stays [FILL] and the audit blocks submission.',
132
+ });
121
133
  }
122
134
  }
123
135
  // cv-tailor unanchored bullets -> evidence questions
@@ -383,20 +395,24 @@ function apply() {
383
395
  const stillYours = fresh.items.filter((i) => i.type !== 'client');
384
396
  const stillClient = fresh.items.filter((i) => i.type === 'client');
385
397
  const state = readState();
398
+ state.rounds = (state.rounds || 0) + 1;
399
+ const round = state.rounds;
386
400
  state.steps.questions = { status: 'done', open: fresh.openCount };
387
401
  state.steps.pricing = { status: inDir('pricing.json') ? 'done' : 'awaiting-user-numbers' };
388
402
  writeState(state);
389
403
  renderPreviews();
390
404
 
391
405
  process.stdout.write(
392
- `# Apply: ${applied} answer(s) recorded, ${fresh.openCount} still open\n\n` +
406
+ `# Apply (round ${round}): ${applied} answer(s) recorded, ${fresh.openCount} still open\n\n` +
393
407
  (stillYours.length
394
- ? `## Still open — answer these (bid-pack ask)\n${mdTable(['#', 'Question'], stillYours.map((i, ix) => [ix + 1, `**${i.id}** — ${i.question}`]))}\n`
395
- : '') +
408
+ ? `## Still open — answer these (bid-pack ask)\n${mdTable(['#', 'Question'], stillYours.map((i, ix) => [ix + 1, `**${i.id}** — ${i.question}`]))}\n` +
409
+ `THIS IS NORMAL AND CONVERGES: answering one round can reveal new questions when a document is filled or rendered for the first time (your pricing answer just created the financial proposal, whose gaps are now questions). Each round has fewer questions than the last — keep going until zero.\n` +
410
+ `NEXT STEP: run npx tor-to-proposal bid-pack ask --dir ${dir} — it asks each of these in plain language, one at a time.\n`
411
+ : `NEXT STEP: run npx tor-to-proposal bid-pack pack --dir ${dir} --fallback-pdf to build the submission pack.\n`) +
396
412
  (stillClient.length
397
413
  ? `## Reminders — ACTIONS for you, not answers\n(These describe things to DO outside the tool: contact the client, verify a fact. They never close by typing an answer here.)\n${mdTable(['#', 'Action'], stillClient.map((i, ix) => [ix + 1, `**${i.id}** — ${i.question}`]))}\n`
398
414
  : '') +
399
- (!fresh.openCount ? `All questions resolved. Draft/generate, then: bid-pack pack --dir ${dir}\n` : '') +
415
+ (!fresh.openCount ? `All questions resolved.\n` : '') +
400
416
  (fills.length ? `\nFill answers recorded in out/fill-answers.json — apply them to the drafts, re-run the lints, and the questions disappear once the [FILL]s are gone.\n` : '') +
401
417
  (evidence.length ? `\nCV evidence entries: ${evidence.length} (out/cv-evidence.json) — cv-tailor lint accepts these as user-input anchors.\n` : '')
402
418
  );
package/mcp/server.mjs CHANGED
@@ -322,7 +322,7 @@ function handle(msg) {
322
322
  return {
323
323
  protocolVersion: typeof params?.protocolVersion === 'string' ? params.protocolVersion : '2024-11-05',
324
324
  capabilities: { tools: {} },
325
- serverInfo: { name: 'tor-to-proposal', version: '2.1.4' },
325
+ serverInfo: { name: 'tor-to-proposal', version: '2.1.6' },
326
326
  };
327
327
  }
328
328
  if (typeof method === 'string' && method.startsWith('notifications/')) return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tor-to-proposal",
3
- "version": "2.1.4",
3
+ "version": "2.1.6",
4
4
  "description": "The bid tool that refuses to lie. ToR + CV in -> verified bid pack out: cover letter, tailored CV, technical response, financial proposal, submission checklist. Deterministic CLI + agent skill for UN / NGO / government consultants.",
5
5
  "type": "module",
6
6
  "bin": {