@kaddo/cli 3.37.1 → 3.38.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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +71 -16
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -534,6 +534,7 @@ create --from roadmap → owners → guard → explain`.
534
534
  | v3.36 | State-aware bootstrap: `kaddo bootstrap` creates the full knowledge baseline for any `project.state` (new/pre-ai/legacy) with state-specific templates — no more new-only warning; idempotent, never overwrites, ensures `tech/decisions/` and `delivery/work-items/` |
535
535
  | v3.37 | Placeholder-aware readiness: knowledge files are classified missing/placeholder/weak/useful; a bootstrap file isn't treated as ready knowledge. Layers downgrade to Placeholder/Weak, a new Knowledge Refinement phase recommends the right agent, and `create --from roadmap` is never suggested with 0 candidates |
536
536
  | v3.37.1 | Unified next-step: one shared resolver (`core/next-step.ts`) powers `context`, `understand` and `explain` (Phase + Readiness) so they never diverge; agent JSON exposes `nextStepRecommendation`. Fixes duplicate `capabilities` line in explain |
537
+ | v3.38 | Open-question source locations: `kaddo questions` shows each question's `Source` (path:line), `Status`, `Severity`, `Note` + a copy/paste resolution example and localized how-to-resolve guide; JSON/report/MCP carry `sourcePath`, `line`, `raw`, `note` |
537
538
 
538
539
  **Optional modules (installed with `kaddo add`):**
539
540
 
package/dist/index.js CHANGED
@@ -7205,10 +7205,10 @@ function extractFromMarkdown(md) {
7205
7205
  }
7206
7206
  const m = line.match(/^\s*(?:[-*]|\d+\.)\s+(.+?)\s*$/);
7207
7207
  if (m) {
7208
- const raw = m[1].trim();
7209
- if (!raw || /^_.*_$/.test(raw)) continue;
7210
- const { text: text3, resolution_status } = parseResolution(raw);
7211
- if (text3) out.push({ text: text3, resolution_status });
7208
+ const bullet = m[1].trim();
7209
+ if (!bullet || /^_.*_$/.test(bullet)) continue;
7210
+ const { text: text3, resolution_status } = parseResolution(bullet);
7211
+ if (text3) out.push({ text: text3, resolution_status, line: i + 1, raw: line.trim() });
7212
7212
  }
7213
7213
  }
7214
7214
  return out;
@@ -7248,12 +7248,15 @@ function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
7248
7248
  questions.push({
7249
7249
  id: `OQ-${String(seq).padStart(3, "0")}`,
7250
7250
  source,
7251
+ sourcePath: source,
7252
+ line: eq.line,
7253
+ raw: eq.raw,
7251
7254
  section: "Open Questions",
7252
7255
  question: eq.text,
7253
7256
  classification,
7254
7257
  resolution_status: eq.resolution_status,
7255
7258
  reason,
7256
- ...eq.resolution_note ? { resolution_note: eq.resolution_note } : {},
7259
+ ...eq.resolution_note ? { resolution_note: eq.resolution_note, note: eq.resolution_note } : {},
7257
7260
  ...classification === "blocking" && eq.resolution_status === "open" ? { suggested_assumption: suggestedAssumption(eq.text) } : {}
7258
7261
  });
7259
7262
  }
@@ -7323,17 +7326,23 @@ function renderOpenQuestionsMarkdown(r) {
7323
7326
  L.push("## Blocking Open Questions", "");
7324
7327
  if (blockingOpen.length === 0) L.push("_None \u2014 nothing blocks readiness._", "");
7325
7328
  for (const q of blockingOpen) {
7326
- L.push(`### ${q.id}`, "");
7327
- L.push(`- Source: \`${q.source}\``);
7328
- L.push(`- Question: ${q.question}`);
7329
+ L.push(`### ${q.question}`, "");
7330
+ L.push(`- Status: ${q.resolution_status}`);
7331
+ L.push(`- Severity: ${q.classification}`);
7332
+ L.push(`- Source: \`${q.sourcePath}:${q.line}\``);
7329
7333
  L.push(`- Reason: ${q.reason}`);
7330
- if (q.suggested_assumption) L.push(`- Suggested assumption: ${q.suggested_assumption}`);
7334
+ L.push("");
7335
+ L.push("Suggested action:", "");
7336
+ L.push("```md");
7337
+ L.push(`- [assumed] ${q.question}`);
7338
+ L.push(` - note: ${q.suggested_assumption ?? "<editable assumption for the MVP>"}`);
7339
+ L.push("```");
7331
7340
  L.push("");
7332
7341
  }
7333
7342
  const renderStatusList = (title, items) => {
7334
7343
  L.push(`## ${title}`, "");
7335
7344
  if (items.length === 0) L.push("_None._");
7336
- for (const q of items) L.push(`- ${q.question}${q.resolution_note ? ` \u2014 _${q.resolution_note}_` : ""}`);
7345
+ for (const q of items) L.push(`- ${q.question} \u2014 \`${q.sourcePath}:${q.line}\`${q.note ? ` \u2014 _${q.note}_` : ""}`);
7337
7346
  L.push("");
7338
7347
  };
7339
7348
  renderStatusList("Resolved", r.resolved_questions);
@@ -7833,7 +7842,7 @@ function resolveNextStep(dir, now = /* @__PURE__ */ new Date()) {
7833
7842
  }
7834
7843
  const oq = buildOpenQuestionsReport(dir, now);
7835
7844
  if (oq.summary.blocking_open > 0) {
7836
- return { id: "questions", phase: "Knowledge Refinement", label: "Resolve, assume or defer the blocking open questions (`kaddo questions`).", command: "kaddo questions", reason: `${oq.summary.blocking_open} blocking open question(s) remain.` };
7845
+ return { id: "questions", phase: "Knowledge Refinement", label: "Run `kaddo questions` to see source locations and resolution guidance, then resolve, assume or defer the blocking open questions.", command: "kaddo questions", reason: `${oq.summary.blocking_open} blocking open question(s) remain.` };
7837
7846
  }
7838
7847
  const roadmap = roadmapSignal(dir);
7839
7848
  if (roadmap !== "has-candidates") {
@@ -13443,7 +13452,8 @@ function runDrift(opts = {}) {
13443
13452
  // src/commands/questions.ts
13444
13453
  function runQuestions(opts = {}) {
13445
13454
  const dir = cwd();
13446
- requireConfig(dir);
13455
+ const config = requireConfig(dir);
13456
+ const es = projectLanguage(config) === "es";
13447
13457
  const report = buildOpenQuestionsReport(dir);
13448
13458
  if (opts.output) {
13449
13459
  intro2("kaddo questions");
@@ -13462,22 +13472,67 @@ function runQuestions(opts = {}) {
13462
13472
  console.log(`Open questions detected: ${s.open_questions}`);
13463
13473
  console.log(`By resolution \u2014 open: ${s.resolution.open}, resolved: ${s.resolution.resolved}, assumed: ${s.resolution.assumed}, deferred: ${s.resolution.deferred}`);
13464
13474
  console.log(`Roadmap readiness: ${s.roadmap_readiness === "needs_decisions" ? "needs decisions" : s.roadmap_readiness} (blocking open: ${s.blocking_open}, important open: ${s.important_open})`);
13465
- const list2 = (title, qs) => {
13475
+ const list2 = (title, qs, opts2 = {}) => {
13466
13476
  if (qs.length === 0) return;
13467
13477
  console.log("");
13468
13478
  console.log(`${title}:`);
13469
- for (const q of qs.slice(0, 8)) console.log(`- ${q.question}${q.resolution_note ? ` \u2014 ${q.resolution_note}` : ""}`);
13470
- if (qs.length > 8) console.log(` \u2026and ${qs.length - 8} more`);
13479
+ console.log("");
13480
+ qs.slice(0, 12).forEach((q, i) => {
13481
+ console.log(`${i + 1}. ${q.question}`);
13482
+ console.log(` Source: ${q.sourcePath}:${q.line}`);
13483
+ console.log(` Status: ${q.resolution_status}`);
13484
+ console.log(` Severity: ${q.classification}`);
13485
+ if (q.note) console.log(` Note: ${q.note}`);
13486
+ if (opts2.example && q.resolution_status === "open") {
13487
+ console.log(" Suggested action:");
13488
+ console.log(` ${es ? "Cambia [open] por [resolved], [assumed] o [deferred]." : "Change [open] to [resolved], [assumed] or [deferred]."}`);
13489
+ console.log(" Example:");
13490
+ console.log(` - [assumed] ${q.question}`);
13491
+ console.log(` - note: ${es ? "<supuesto editable para el MVP>" : "<editable assumption for the MVP>"}`);
13492
+ }
13493
+ console.log("");
13494
+ });
13495
+ if (qs.length > 12) console.log(` \u2026and ${qs.length - 12} more`);
13471
13496
  };
13472
- list2("Blocking (open)", report.blocking_questions.filter((q) => q.resolution_status === "open"));
13497
+ list2("Blocking (open)", report.blocking_questions.filter((q) => q.resolution_status === "open"), { example: true });
13498
+ list2("Important (open)", report.important_questions.filter((q) => q.resolution_status === "open"));
13473
13499
  list2("Resolved", report.resolved_questions);
13474
13500
  list2("Assumed", report.assumed_questions);
13475
13501
  list2("Deferred", report.deferred_status_questions);
13502
+ printResolutionGuide(es);
13476
13503
  console.log("");
13477
13504
  console.log("Suggested next:");
13478
13505
  console.log(report.recommended_next_step);
13479
13506
  printCommandFooter("questions");
13480
13507
  }
13508
+ function printResolutionGuide(es) {
13509
+ console.log("");
13510
+ if (es) {
13511
+ console.log("C\xF3mo resolver");
13512
+ console.log("");
13513
+ console.log("Edita el archivo indicado en Source y cambia el marcador:");
13514
+ console.log(" [open] \u2192 sigue abierta");
13515
+ console.log(" [resolved] \u2192 respuesta confirmada");
13516
+ console.log(" [assumed] \u2192 supuesto seguro por ahora");
13517
+ console.log(" [deferred] \u2192 decisi\xF3n aplazada");
13518
+ console.log("");
13519
+ console.log("Agrega una nota debajo de la pregunta cuando sea posible:");
13520
+ console.log(" - [assumed] \xBFPregunta?");
13521
+ console.log(" - note: Se asume X para el MVP porque Y.");
13522
+ } else {
13523
+ console.log("How to resolve");
13524
+ console.log("");
13525
+ console.log("Edit the file shown in Source and change the marker:");
13526
+ console.log(" [open] \u2192 still unresolved");
13527
+ console.log(" [resolved] \u2192 confirmed answer");
13528
+ console.log(" [assumed] \u2192 safe assumption for now");
13529
+ console.log(" [deferred] \u2192 intentionally postponed");
13530
+ console.log("");
13531
+ console.log("Add a note below the question when possible:");
13532
+ console.log(" - [assumed] Question?");
13533
+ console.log(" - note: Assume X for the MVP because Y.");
13534
+ }
13535
+ }
13481
13536
 
13482
13537
  // src/commands/adapters.ts
13483
13538
  var ADAPTER_LIST = ADAPTERS.map((a) => a.id).join(", ");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.37.1",
3
+ "version": "3.38.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {