@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.
- package/README.md +1 -0
- package/dist/index.js +71 -16
- 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
|
|
7209
|
-
if (!
|
|
7210
|
-
const { text: text3, resolution_status } = parseResolution(
|
|
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.
|
|
7327
|
-
L.push(`-
|
|
7328
|
-
L.push(`-
|
|
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
|
-
|
|
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}
|
|
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: "
|
|
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
|
-
|
|
13470
|
-
|
|
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(", ");
|