@kaddo/cli 3.25.1 → 3.26.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 +308 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -516,6 +516,7 @@ create --from roadmap → owners → guard → explain`.
|
|
|
516
516
|
| v3.24 | Estimated Savings Model: `kaddo savings` (+ `savings init`, `.kaddo/savings.yml`); evidence-based time/value estimates, confidence; MCP resource + tool |
|
|
517
517
|
| v3.25 | Guard history & drift trend: `kaddo guard --record`, `kaddo drift`; feeds impact Guard Activity + savings Drift Prevention; MCP drift/guard-history resources + tool |
|
|
518
518
|
| v3.25.1 | Savings guard-history messaging fix: distinguishes "no history" from "history with 0 resolved warnings" (drift prevention available at 0 h) |
|
|
519
|
+
| v3.26 | Open-questions readiness gate: `kaddo questions`/`readiness`, blocking/important/deferred classification; MCP open-questions + roadmap-readiness resources + tool; roadmap/work-item/implementation/bootstrap agents check it |
|
|
519
520
|
|
|
520
521
|
**Optional modules (installed with `kaddo add`):**
|
|
521
522
|
|
package/dist/index.js
CHANGED
|
@@ -696,6 +696,10 @@ var COMMAND_HELP = {
|
|
|
696
696
|
drift: {
|
|
697
697
|
question: "Are code and knowledge drifting apart over time?",
|
|
698
698
|
next: "Review open warnings; `kaddo guard --record` before commits"
|
|
699
|
+
},
|
|
700
|
+
questions: {
|
|
701
|
+
question: "Are there open questions to decide before the roadmap?",
|
|
702
|
+
next: "Resolve, assume or defer blocking questions, then generate the roadmap"
|
|
699
703
|
}
|
|
700
704
|
};
|
|
701
705
|
function commandFooterLines(name) {
|
|
@@ -2401,6 +2405,21 @@ open question):
|
|
|
2401
2405
|
- \`knowledge/knowledge.md\`
|
|
2402
2406
|
- business priorities
|
|
2403
2407
|
|
|
2408
|
+
## Readiness Gate (check first)
|
|
2409
|
+
|
|
2410
|
+
Before generating the roadmap, check **roadmap readiness** for open questions that affect scope,
|
|
2411
|
+
architecture or the MVP. Read \`kaddo://roadmap-readiness\` (MCP) or run \`kaddo questions\`.
|
|
2412
|
+
|
|
2413
|
+
If readiness is \`needs_decisions\` (there are **blocking** open questions), do **not** generate the
|
|
2414
|
+
roadmap yet. Instead, list the blocking questions, propose reasonable assumptions for each, and ask
|
|
2415
|
+
the user to confirm, e.g.:
|
|
2416
|
+
|
|
2417
|
+
> Before generating the roadmap I found blocking open questions that affect the MVP scope.
|
|
2418
|
+
> I can proceed with these assumptions: \u2026 Confirm and continue?
|
|
2419
|
+
|
|
2420
|
+
Only generate the roadmap once the user confirms the assumptions (or resolves/defers the
|
|
2421
|
+
questions). Record confirmed assumptions explicitly in the roadmap.
|
|
2422
|
+
|
|
2404
2423
|
## Expected Output
|
|
2405
2424
|
|
|
2406
2425
|
A single Markdown artifact intended to be saved as \`knowledge/delivery/roadmap.md\`.
|
|
@@ -2709,6 +2728,13 @@ Work Items into clear, traceable units of work.
|
|
|
2709
2728
|
You do not write code. You sharpen the problem, validate the Knowledge Level and make the
|
|
2710
2729
|
Work Item actionable for a human.
|
|
2711
2730
|
|
|
2731
|
+
## Readiness Gate (check first)
|
|
2732
|
+
|
|
2733
|
+
For high-impact Work Items, check \`kaddo://roadmap-readiness\` (or \`kaddo questions\`) for
|
|
2734
|
+
**blocking** open questions related to this Work Item's scope. If any are unresolved, surface them
|
|
2735
|
+
and propose assumptions for the user to confirm before refining \u2014 don't bake in invisible
|
|
2736
|
+
assumptions.
|
|
2737
|
+
|
|
2712
2738
|
## When to Use
|
|
2713
2739
|
|
|
2714
2740
|
Use this agent after a roadmap exists (\`knowledge/delivery/roadmap.md\`) or when an existing Work
|
|
@@ -3210,6 +3236,13 @@ You are the Kaddo Bootstrap Agent. You guide the transition from business defini
|
|
|
3210
3236
|
initial architecture direction, quality attributes, a roadmap and first Work Items for a
|
|
3211
3237
|
new project. You propose; the human decides.
|
|
3212
3238
|
|
|
3239
|
+
## Readiness Gate
|
|
3240
|
+
|
|
3241
|
+
Bootstrap surfaces \`## Open Questions\` in the knowledge files. Before moving to the roadmap,
|
|
3242
|
+
explicitly recommend reviewing them (\`kaddo questions\` / \`kaddo://roadmap-readiness\`) and turning
|
|
3243
|
+
**blocking** ones into resolved decisions or confirmed assumptions \u2014 so the roadmap isn't built on
|
|
3244
|
+
invisible assumptions.
|
|
3245
|
+
|
|
3213
3246
|
## When to Use
|
|
3214
3247
|
|
|
3215
3248
|
Use this agent after \`kaddo bootstrap\` and after the business artifacts are drafted.
|
|
@@ -3321,6 +3354,13 @@ may suggest a Git branch, and only by respecting the project's Git strategy.
|
|
|
3321
3354
|
You never run Git yourself. The Kaddo CLI never runs Git either. Every git action is the
|
|
3322
3355
|
human's, and commits/pushes/merges happen only with explicit human confirmation.
|
|
3323
3356
|
|
|
3357
|
+
## Readiness Gate (check first)
|
|
3358
|
+
|
|
3359
|
+
Before implementing a high-impact Work Item, check \`kaddo://roadmap-readiness\` (or
|
|
3360
|
+
\`kaddo questions\`) for **blocking** open questions about stack, architecture, persistence,
|
|
3361
|
+
authentication or the Work Item's scope. If any are unresolved, pause and ask the user to confirm
|
|
3362
|
+
assumptions or resolve them before writing code.
|
|
3363
|
+
|
|
3324
3364
|
## When to Use
|
|
3325
3365
|
|
|
3326
3366
|
Use this agent after the work-item-agent has produced a clear, traceable Work Item under
|
|
@@ -8162,6 +8202,224 @@ function renderDeliveryLifecycle(wi) {
|
|
|
8162
8202
|
];
|
|
8163
8203
|
}
|
|
8164
8204
|
|
|
8205
|
+
// src/core/open-questions.ts
|
|
8206
|
+
var SOURCES = [
|
|
8207
|
+
"knowledge/business/business.md",
|
|
8208
|
+
"knowledge/product/product.md",
|
|
8209
|
+
"knowledge/tech/codebase.md",
|
|
8210
|
+
"knowledge/delivery/roadmap.md"
|
|
8211
|
+
];
|
|
8212
|
+
var BLOCKING = [
|
|
8213
|
+
"mvp",
|
|
8214
|
+
"stack",
|
|
8215
|
+
"arquitect",
|
|
8216
|
+
"architecture",
|
|
8217
|
+
"api",
|
|
8218
|
+
"web app",
|
|
8219
|
+
"webapp",
|
|
8220
|
+
"cli",
|
|
8221
|
+
"backend",
|
|
8222
|
+
"auth",
|
|
8223
|
+
"autenticaci",
|
|
8224
|
+
"persist",
|
|
8225
|
+
"base de datos",
|
|
8226
|
+
"database",
|
|
8227
|
+
"roadmap",
|
|
8228
|
+
"alcance",
|
|
8229
|
+
"scope",
|
|
8230
|
+
"primera versi\xF3n",
|
|
8231
|
+
"primera version",
|
|
8232
|
+
"first version",
|
|
8233
|
+
"fastify",
|
|
8234
|
+
"nestjs",
|
|
8235
|
+
"framework"
|
|
8236
|
+
];
|
|
8237
|
+
var DEFERRED = [
|
|
8238
|
+
"integraci",
|
|
8239
|
+
"integration",
|
|
8240
|
+
"analytics",
|
|
8241
|
+
"notificaci",
|
|
8242
|
+
"notification",
|
|
8243
|
+
"google calendar",
|
|
8244
|
+
"eventbrite",
|
|
8245
|
+
"meetup",
|
|
8246
|
+
"dashboard",
|
|
8247
|
+
"multi-tenant",
|
|
8248
|
+
"multitenant",
|
|
8249
|
+
"mobile",
|
|
8250
|
+
"m\xF3vil",
|
|
8251
|
+
"pago",
|
|
8252
|
+
"payment",
|
|
8253
|
+
"ticketing",
|
|
8254
|
+
"multiple tracks",
|
|
8255
|
+
"m\xFAltiples tracks",
|
|
8256
|
+
"webhook"
|
|
8257
|
+
];
|
|
8258
|
+
var IMPORTANT = [
|
|
8259
|
+
"validaci",
|
|
8260
|
+
"validation",
|
|
8261
|
+
"paginaci",
|
|
8262
|
+
"pagination",
|
|
8263
|
+
"soft delete",
|
|
8264
|
+
"sponsor",
|
|
8265
|
+
"agenda",
|
|
8266
|
+
"ubicaci",
|
|
8267
|
+
"location",
|
|
8268
|
+
"rol",
|
|
8269
|
+
"role",
|
|
8270
|
+
"permis",
|
|
8271
|
+
"permission"
|
|
8272
|
+
];
|
|
8273
|
+
function matchesAny(text3, keywords) {
|
|
8274
|
+
return keywords.some((k) => text3.includes(k));
|
|
8275
|
+
}
|
|
8276
|
+
function classifyQuestion(question) {
|
|
8277
|
+
const t = question.toLowerCase();
|
|
8278
|
+
if (matchesAny(t, BLOCKING)) {
|
|
8279
|
+
return { classification: "blocking", reason: "Affects scope, architecture or the first Work Items." };
|
|
8280
|
+
}
|
|
8281
|
+
if (matchesAny(t, DEFERRED) && !matchesAny(t, IMPORTANT)) {
|
|
8282
|
+
return { classification: "deferred", reason: "Can be moved to a later phase." };
|
|
8283
|
+
}
|
|
8284
|
+
if (matchesAny(t, IMPORTANT)) {
|
|
8285
|
+
return { classification: "important", reason: "Relevant, but a temporary assumption can unblock progress." };
|
|
8286
|
+
}
|
|
8287
|
+
return { classification: "important", reason: "Relevant, but a temporary assumption can unblock progress." };
|
|
8288
|
+
}
|
|
8289
|
+
function extractFromMarkdown(md) {
|
|
8290
|
+
const lines = md.split(/\r?\n/);
|
|
8291
|
+
const start = lines.findIndex((l) => /^#{1,6}\s+open questions\s*$/i.test(l.trim()) || /^#{1,6}\s+preguntas abiertas\s*$/i.test(l.trim()));
|
|
8292
|
+
if (start < 0) return [];
|
|
8293
|
+
const out = [];
|
|
8294
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
8295
|
+
const line = lines[i];
|
|
8296
|
+
if (/^#{1,6}\s+/.test(line)) break;
|
|
8297
|
+
const m = line.match(/^\s*(?:[-*]|\d+\.)\s+(.+?)\s*$/);
|
|
8298
|
+
if (m) {
|
|
8299
|
+
const q = m[1].trim();
|
|
8300
|
+
if (q && !/^_.*_$/.test(q)) out.push(q);
|
|
8301
|
+
}
|
|
8302
|
+
}
|
|
8303
|
+
return out;
|
|
8304
|
+
}
|
|
8305
|
+
function suggestedAssumption(question) {
|
|
8306
|
+
const t = question.toLowerCase();
|
|
8307
|
+
if (matchesAny(t, ["api", "web app", "webapp", "cli", "backend"])) {
|
|
8308
|
+
return "Start as a backend API to keep the initial scope small.";
|
|
8309
|
+
}
|
|
8310
|
+
if (matchesAny(t, ["auth", "autenticaci"])) {
|
|
8311
|
+
return "No authentication in the MVP.";
|
|
8312
|
+
}
|
|
8313
|
+
if (matchesAny(t, ["fastify", "nestjs", "framework", "stack"])) {
|
|
8314
|
+
return "Choose the lighter stack option to minimize MVP scope.";
|
|
8315
|
+
}
|
|
8316
|
+
if (matchesAny(t, ["persist", "base de datos", "database"])) {
|
|
8317
|
+
return "Use a simple local datastore (e.g. SQLite) for the MVP.";
|
|
8318
|
+
}
|
|
8319
|
+
return "Proceed with the smallest reasonable MVP interpretation and revisit later.";
|
|
8320
|
+
}
|
|
8321
|
+
function buildOpenQuestionsReport(dir, now = /* @__PURE__ */ new Date()) {
|
|
8322
|
+
const project = loadConfig(dir)?.project.name ?? "unknown";
|
|
8323
|
+
const questions = [];
|
|
8324
|
+
let seq = 0;
|
|
8325
|
+
for (const source of SOURCES) {
|
|
8326
|
+
const p2 = join(dir, source);
|
|
8327
|
+
if (!exists(p2)) continue;
|
|
8328
|
+
let md;
|
|
8329
|
+
try {
|
|
8330
|
+
md = readFile(p2);
|
|
8331
|
+
} catch {
|
|
8332
|
+
continue;
|
|
8333
|
+
}
|
|
8334
|
+
for (const q of extractFromMarkdown(md)) {
|
|
8335
|
+
seq += 1;
|
|
8336
|
+
const { classification, reason } = classifyQuestion(q);
|
|
8337
|
+
questions.push({
|
|
8338
|
+
id: `OQ-${String(seq).padStart(3, "0")}`,
|
|
8339
|
+
source,
|
|
8340
|
+
section: "Open Questions",
|
|
8341
|
+
question: q,
|
|
8342
|
+
classification,
|
|
8343
|
+
reason,
|
|
8344
|
+
...classification === "blocking" ? { suggested_assumption: suggestedAssumption(q) } : {}
|
|
8345
|
+
});
|
|
8346
|
+
}
|
|
8347
|
+
}
|
|
8348
|
+
const blocking = questions.filter((q) => q.classification === "blocking");
|
|
8349
|
+
const important = questions.filter((q) => q.classification === "important");
|
|
8350
|
+
const deferred = questions.filter((q) => q.classification === "deferred");
|
|
8351
|
+
let readiness;
|
|
8352
|
+
if (questions.length === 0) readiness = "unknown";
|
|
8353
|
+
else if (blocking.length > 0) readiness = "needs_decisions";
|
|
8354
|
+
else readiness = "ready";
|
|
8355
|
+
const suggested_assumptions = blocking.map((q) => q.suggested_assumption).filter(Boolean);
|
|
8356
|
+
const recommended_next_step = readiness === "needs_decisions" ? "Confirm suggested assumptions with the user (resolve, assume or defer blocking questions) before generating the roadmap." : readiness === "ready" ? "No blocking questions \u2014 you can proceed to the roadmap (review important questions when convenient)." : "No open questions found. Run `kaddo bootstrap` to capture early questions, or proceed.";
|
|
8357
|
+
return {
|
|
8358
|
+
generated_at: now.toISOString(),
|
|
8359
|
+
project,
|
|
8360
|
+
summary: {
|
|
8361
|
+
open_questions: questions.length,
|
|
8362
|
+
roadmap_readiness: readiness,
|
|
8363
|
+
blocking: blocking.length,
|
|
8364
|
+
important: important.length,
|
|
8365
|
+
deferred: deferred.length
|
|
8366
|
+
},
|
|
8367
|
+
questions,
|
|
8368
|
+
blocking_questions: blocking,
|
|
8369
|
+
important_questions: important,
|
|
8370
|
+
deferred_questions: deferred,
|
|
8371
|
+
suggested_assumptions,
|
|
8372
|
+
recommended_next_step
|
|
8373
|
+
};
|
|
8374
|
+
}
|
|
8375
|
+
function renderOpenQuestionsMarkdown(r) {
|
|
8376
|
+
const L = [];
|
|
8377
|
+
L.push("# Kaddo Open Questions Readiness Report", "");
|
|
8378
|
+
L.push(`Generated at: ${r.generated_at}`);
|
|
8379
|
+
L.push(`Project: ${r.project}`);
|
|
8380
|
+
L.push("");
|
|
8381
|
+
L.push("## Summary", "");
|
|
8382
|
+
L.push(`- Open questions found: ${r.summary.open_questions}`);
|
|
8383
|
+
L.push(`- Roadmap readiness: ${r.summary.roadmap_readiness}`);
|
|
8384
|
+
L.push(`- Blocking: ${r.summary.blocking}`);
|
|
8385
|
+
L.push(`- Important: ${r.summary.important}`);
|
|
8386
|
+
L.push(`- Deferred: ${r.summary.deferred}`);
|
|
8387
|
+
L.push("");
|
|
8388
|
+
if (r.summary.open_questions === 0) {
|
|
8389
|
+
L.push("No `## Open Questions` sections found in business / product / codebase / roadmap.", "");
|
|
8390
|
+
L.push("## Recommended Next Step", "", r.recommended_next_step, "");
|
|
8391
|
+
return L.join("\n");
|
|
8392
|
+
}
|
|
8393
|
+
L.push("## Blocking Questions", "");
|
|
8394
|
+
if (r.blocking_questions.length === 0) L.push("_None._", "");
|
|
8395
|
+
for (const q of r.blocking_questions) {
|
|
8396
|
+
L.push(`### ${q.id}`, "");
|
|
8397
|
+
L.push(`- Source: \`${q.source}\``);
|
|
8398
|
+
L.push(`- Question: ${q.question}`);
|
|
8399
|
+
L.push(`- Reason: ${q.reason}`);
|
|
8400
|
+
if (q.suggested_assumption) L.push(`- Suggested assumption: ${q.suggested_assumption}`);
|
|
8401
|
+
L.push("");
|
|
8402
|
+
}
|
|
8403
|
+
L.push("## Important Questions", "");
|
|
8404
|
+
if (r.important_questions.length === 0) L.push("_None._");
|
|
8405
|
+
for (const q of r.important_questions) L.push(`- ${q.question}`);
|
|
8406
|
+
L.push("");
|
|
8407
|
+
L.push("## Deferred Questions", "");
|
|
8408
|
+
if (r.deferred_questions.length === 0) L.push("_None._");
|
|
8409
|
+
for (const q of r.deferred_questions) L.push(`- ${q.question}`);
|
|
8410
|
+
L.push("");
|
|
8411
|
+
if (r.suggested_assumptions.length > 0) {
|
|
8412
|
+
L.push("## Suggested Assumptions", "");
|
|
8413
|
+
for (const a of r.suggested_assumptions) L.push(`- ${a}`);
|
|
8414
|
+
L.push("");
|
|
8415
|
+
}
|
|
8416
|
+
L.push("## Recommended Next Step", "", r.recommended_next_step, "");
|
|
8417
|
+
return L.join("\n");
|
|
8418
|
+
}
|
|
8419
|
+
function serializeOpenQuestionsJson(r) {
|
|
8420
|
+
return JSON.stringify(r, null, 2) + "\n";
|
|
8421
|
+
}
|
|
8422
|
+
|
|
8165
8423
|
// src/commands/understand.ts
|
|
8166
8424
|
function runUnderstand() {
|
|
8167
8425
|
const dir = cwd();
|
|
@@ -8234,6 +8492,12 @@ function runUnderstand() {
|
|
|
8234
8492
|
console.log(" \u2192 Review graph hints before continuing with implementation.");
|
|
8235
8493
|
console.log(" Suggested agent: graph-agent (see .kaddo/graph-hints.md)");
|
|
8236
8494
|
}
|
|
8495
|
+
const oq = buildOpenQuestionsReport(dir);
|
|
8496
|
+
if (oq.summary.blocking > 0) {
|
|
8497
|
+
console.log("");
|
|
8498
|
+
console.log(`Open questions: ${oq.summary.blocking} blocking decision(s) before the roadmap (roadmap readiness: ${oq.summary.roadmap_readiness}).`);
|
|
8499
|
+
console.log(" \u2192 Run `kaddo questions` to review them, then resolve, assume or defer before `kaddo create --from roadmap`.");
|
|
8500
|
+
}
|
|
8237
8501
|
const active = activeWorkItems(dir);
|
|
8238
8502
|
if (active.length > 0) {
|
|
8239
8503
|
console.log("");
|
|
@@ -8291,35 +8555,35 @@ var DEP_PATTERNS = [
|
|
|
8291
8555
|
function normalizePath2(p2) {
|
|
8292
8556
|
return p2.split(path5.sep).join("/");
|
|
8293
8557
|
}
|
|
8294
|
-
function
|
|
8558
|
+
function matchesAny2(file, patterns) {
|
|
8295
8559
|
const normalized = normalizePath2(file);
|
|
8296
8560
|
return patterns.some((p2) => p2.test(normalized));
|
|
8297
8561
|
}
|
|
8298
8562
|
function detectSignals(touchedFiles) {
|
|
8299
8563
|
const signals = [];
|
|
8300
8564
|
for (const file of touchedFiles) {
|
|
8301
|
-
if (
|
|
8565
|
+
if (matchesAny2(file, MIGRATION_PATTERNS)) {
|
|
8302
8566
|
signals.push({
|
|
8303
8567
|
name: "DB migration",
|
|
8304
8568
|
file,
|
|
8305
8569
|
implication: "Data schema change \u2014 typically K4 or Migration type",
|
|
8306
8570
|
suggestedLevel: "K4"
|
|
8307
8571
|
});
|
|
8308
|
-
} else if (
|
|
8572
|
+
} else if (matchesAny2(file, CONTRACT_PATTERNS)) {
|
|
8309
8573
|
signals.push({
|
|
8310
8574
|
name: "API/event contract",
|
|
8311
8575
|
file,
|
|
8312
8576
|
implication: "Contract change affects consumers \u2014 typically K3/K4",
|
|
8313
8577
|
suggestedLevel: "K3"
|
|
8314
8578
|
});
|
|
8315
|
-
} else if (
|
|
8579
|
+
} else if (matchesAny2(file, INFRA_PATTERNS)) {
|
|
8316
8580
|
signals.push({
|
|
8317
8581
|
name: "Infrastructure",
|
|
8318
8582
|
file,
|
|
8319
8583
|
implication: "Infrastructure change \u2014 typically K3/K4",
|
|
8320
8584
|
suggestedLevel: "K3"
|
|
8321
8585
|
});
|
|
8322
|
-
} else if (
|
|
8586
|
+
} else if (matchesAny2(file, DEP_PATTERNS)) {
|
|
8323
8587
|
signals.push({
|
|
8324
8588
|
name: "Dependency",
|
|
8325
8589
|
file,
|
|
@@ -11995,6 +12259,42 @@ function runDrift(opts = {}) {
|
|
|
11995
12259
|
console.log(content);
|
|
11996
12260
|
}
|
|
11997
12261
|
|
|
12262
|
+
// src/commands/questions.ts
|
|
12263
|
+
function runQuestions(opts = {}) {
|
|
12264
|
+
const dir = cwd();
|
|
12265
|
+
requireConfig(dir);
|
|
12266
|
+
const report = buildOpenQuestionsReport(dir);
|
|
12267
|
+
if (opts.output) {
|
|
12268
|
+
intro2("kaddo questions");
|
|
12269
|
+
writeFile(join(dir, opts.output), opts.json ? serializeOpenQuestionsJson(report) : renderOpenQuestionsMarkdown(report));
|
|
12270
|
+
log2.success(`Wrote ${opts.output.replace(/\\/g, "/")}`);
|
|
12271
|
+
printCommandFooter("questions");
|
|
12272
|
+
outro2("Questions report written.");
|
|
12273
|
+
return;
|
|
12274
|
+
}
|
|
12275
|
+
if (opts.json) {
|
|
12276
|
+
console.log(serializeOpenQuestionsJson(report));
|
|
12277
|
+
return;
|
|
12278
|
+
}
|
|
12279
|
+
console.log("");
|
|
12280
|
+
console.log(`Open questions detected: ${report.summary.open_questions}`);
|
|
12281
|
+
console.log(`Roadmap readiness: ${report.summary.roadmap_readiness === "needs_decisions" ? "needs decisions" : report.summary.roadmap_readiness}`);
|
|
12282
|
+
const list2 = (title, qs) => {
|
|
12283
|
+
if (qs.length === 0) return;
|
|
12284
|
+
console.log("");
|
|
12285
|
+
console.log(`${title}:`);
|
|
12286
|
+
for (const q of qs.slice(0, 8)) console.log(`- ${q.question}`);
|
|
12287
|
+
if (qs.length > 8) console.log(` \u2026and ${qs.length - 8} more`);
|
|
12288
|
+
};
|
|
12289
|
+
list2("Blocking", report.blocking_questions);
|
|
12290
|
+
list2("Important", report.important_questions);
|
|
12291
|
+
list2("Deferred", report.deferred_questions);
|
|
12292
|
+
console.log("");
|
|
12293
|
+
console.log("Suggested next:");
|
|
12294
|
+
console.log(report.recommended_next_step);
|
|
12295
|
+
printCommandFooter("questions");
|
|
12296
|
+
}
|
|
12297
|
+
|
|
11998
12298
|
// src/index.ts
|
|
11999
12299
|
var require2 = createRequire(import.meta.url);
|
|
12000
12300
|
var { version } = require2("../package.json");
|
|
@@ -12045,6 +12345,9 @@ reportCmd.command("drift").description("Drift Trend Report from recorded guard h
|
|
|
12045
12345
|
program.command("drift").description("Drift Trend Report from recorded `kaddo guard --record` history").option("--json", "Output JSON instead of Markdown").option("--output <path>", "Write the report to a file").action((opts) => {
|
|
12046
12346
|
runDrift(opts);
|
|
12047
12347
|
});
|
|
12348
|
+
var questionsAction = (opts) => runQuestions(opts);
|
|
12349
|
+
program.command("questions").description("Open-questions readiness gate: blocking/important/deferred decisions before the roadmap").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file (e.g. .kaddo/reports/questions-report.md)").action(questionsAction);
|
|
12350
|
+
program.command("readiness").description("Alias for `kaddo questions`").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file").action(questionsAction);
|
|
12048
12351
|
program.command("guard").description("Check if modified code has related artifacts that were not updated").option("--staged", "Check only staged files").option("--no-interactive", "Disable interactive ignore prompts").option("--ci", "CI mode: output JSON, no prompts, non-blocking").option("--json", "Output JSON (alias for --ci)").option("--workspace", "Also check local mapped module repos from .kaddo/modules.yml (opt-in)").option("--include-archived", "Include archived Work Items in ownership matching (excluded by default)").option("--record", "Record this run to .kaddo/history/ for drift trend reporting").action(async (opts) => {
|
|
12049
12352
|
await runGuard(opts);
|
|
12050
12353
|
});
|