@kaddo/cli 3.33.0 → 3.34.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 +243 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -529,6 +529,7 @@ create --from roadmap → owners → guard → explain`.
529
529
  | v3.31 | Kiro adapter: `kaddo adapters install kiro` (alias `kaddo export kiro`) generates an `AGENTS.md` projection reusing the shared adapter common core (`--dry-run`/`--force`/`--inject` + inject guard) |
530
530
  | v3.32 | Adapter discovery & status: `kaddo adapters list` (alias `ls`) and `kaddo adapters status` (alias `check`) — read-only catalog + per-adapter install state (missing/team-owned/injected/legacy-injected/full-generated/broken-markers), shared-`AGENTS.md` origin detection, `--json` |
531
531
  | v3.33 | Open questions resolution tracking: mark questions `[open]`/`[resolved]`/`[assumed]`/`[deferred]` (EN+ES); only `open` blocks readiness, so assumed/resolved/deferred decisions stop false blocks. `kaddo questions` shows status counts + `resolution_status` in JSON |
532
+ | v3.34 | Pre-AI onboarding: `kaddo onboarding` (alias `onboard`) / `kaddo report onboarding` — read-only diagnosis of an existing project's readiness (scan/understand/knowledge/questions/roadmap/work-items/adapters) with a single recommended next step; `--json` |
532
533
 
533
534
  **Optional modules (installed with `kaddo add`):**
534
535
 
package/dist/index.js CHANGED
@@ -704,6 +704,10 @@ var COMMAND_HELP = {
704
704
  "adapters install codex": {
705
705
  question: "How does Codex work with this Kaddo project?",
706
706
  next: "Open AGENTS.md, or regenerate it after knowledge changes"
707
+ },
708
+ onboarding: {
709
+ question: "How ready is this pre-AI project to work with agents?",
710
+ next: "Run the single recommended next step, then re-run `kaddo onboarding`"
707
711
  }
708
712
  };
709
713
  function commandFooterLines(name) {
@@ -3255,6 +3259,16 @@ on invisible assumptions. When you find unresolved questions, suggest marking ea
3255
3259
  token so Kaddo can track them: \`[open]\`, \`[resolved]\`, \`[assumed]\` or \`[deferred]\` (ES: \`[abierta]\`,
3256
3260
  \`[resuelta]\`, \`[asumida]\`, \`[diferida]\`). Only \`open\` questions block readiness.
3257
3261
 
3262
+ ## Pre-AI projects
3263
+
3264
+ For **pre-AI** projects (existing code, little structured knowledge), use \`kaddo onboarding\` as the
3265
+ compass: it diagnoses the current state and recommends a single next step along the cycle
3266
+ \`init \u2192 scan \u2192 understand \u2192 onboarding \u2192 questions \u2192 roadmap \u2192 create --from roadmap \u2192 adapter \u2192
3267
+ implement \u2192 guard\`. Use the \`scan\` and \`understand\` outputs as input \u2014 **do not invent project
3268
+ goals or capabilities**. Capture unknowns as \`[open]\` questions and safe, explicit defaults as
3269
+ \`[assumed]\`. Build \`knowledge/tech/current-state.md\` and \`knowledge/tech/codebase.md\` from real
3270
+ repo signals before drafting the roadmap or the first Work Item.
3271
+
3258
3272
  ## When to Use
3259
3273
 
3260
3274
  Use this agent after \`kaddo bootstrap\` and after the business artifacts are drafted.
@@ -12891,6 +12905,229 @@ function runAdaptersStatus(opts = {}) {
12891
12905
  }
12892
12906
  }
12893
12907
 
12908
+ // src/core/onboarding.ts
12909
+ var KNOWLEDGE_FILES = [
12910
+ { key: "current_state", path: "knowledge/tech/current-state.md", label: "knowledge/tech/current-state.md" },
12911
+ { key: "codebase", path: "knowledge/tech/codebase.md", label: "knowledge/tech/codebase.md" },
12912
+ { key: "capabilities", path: "knowledge/product/capabilities.md", label: "knowledge/product/capabilities.md" },
12913
+ { key: "product", path: "knowledge/product/product.md", label: "knowledge/product/product.md" },
12914
+ { key: "business", path: "knowledge/business/business.md", label: "knowledge/business/business.md" }
12915
+ ];
12916
+ function knowledgePresence(dir, rel) {
12917
+ const p2 = join(dir, rel);
12918
+ if (!exists(p2)) return "missing";
12919
+ let md;
12920
+ try {
12921
+ md = readFile(p2);
12922
+ } catch {
12923
+ return "missing";
12924
+ }
12925
+ const body = md.replace(/^---[\s\S]*?---/m, "").split(/\r?\n/).filter((l) => !/^\s*#{1,6}\s/.test(l) && !/^\s*$/.test(l) && !/^\s*<!--/.test(l)).join(" ").trim();
12926
+ return body.length >= 40 ? "present" : "weak";
12927
+ }
12928
+ function roadmapSignal(dir) {
12929
+ const p2 = join(dir, "knowledge/delivery/roadmap.md");
12930
+ if (!exists(p2)) return "missing";
12931
+ let md;
12932
+ try {
12933
+ md = readFile(p2);
12934
+ } catch {
12935
+ return "missing";
12936
+ }
12937
+ const stripped = md.replace(/^---[\s\S]*?---/m, "");
12938
+ const lines = stripped.split(/\r?\n/);
12939
+ let inOpenQuestions = false;
12940
+ let candidates = 0;
12941
+ for (const l of lines) {
12942
+ if (/^#{1,6}\s/.test(l)) inOpenQuestions = /open questions|preguntas abiertas/i.test(l);
12943
+ else if (!inOpenQuestions && /^\s*(?:[-*]\s+|\|)/.test(l)) candidates += 1;
12944
+ }
12945
+ return candidates > 0 ? "has-candidates" : "empty";
12946
+ }
12947
+ function workItemsSignal(dir) {
12948
+ const wis = discoverWorkItems(dir);
12949
+ if (wis.length === 0) return "none";
12950
+ if (wis.some((w) => w.lifecycle === "in-progress")) return "in-progress";
12951
+ if (wis.some((w) => w.lifecycle === "ready")) return "ready";
12952
+ return "none-ready";
12953
+ }
12954
+ function installedAdapters(dir) {
12955
+ return buildAdapterStatuses(dir).filter(
12956
+ (s) => s.state === "injected" || s.state === "legacy-injected" || s.state === "full-generated" && (s.originAdapter === s.id || s.originAdapter === null)
12957
+ ).map((s) => s.id);
12958
+ }
12959
+ function buildOnboardingReport(dir, now = /* @__PURE__ */ new Date()) {
12960
+ const config = loadConfig(dir);
12961
+ const ts = now.toISOString();
12962
+ const notReady = (status2, label, command) => ({
12963
+ generated_at: ts,
12964
+ project_name: config?.project.name ?? "unknown",
12965
+ project_type: config?.project.state ?? "unknown",
12966
+ status: status2,
12967
+ signals: {
12968
+ scan: "missing",
12969
+ understand: "missing",
12970
+ current_state: "missing",
12971
+ codebase: "missing",
12972
+ capabilities: "missing",
12973
+ product: "missing",
12974
+ business: "missing",
12975
+ roadmap: "missing",
12976
+ work_items: "none",
12977
+ adapters: [],
12978
+ blocking_open_questions: 0,
12979
+ assumed_questions: 0,
12980
+ resolved_questions: 0,
12981
+ deferred_questions: 0
12982
+ },
12983
+ recommended_next_step: { label, ...command ? { command } : {} }
12984
+ });
12985
+ if (!config) return notReady("not-initialized", "Run `kaddo init` to initialize Kaddo.", "kaddo init");
12986
+ if (config.project.state === "new") return notReady("not-applicable", "This guide is optimized for pre-AI projects. Use the standard new-project Kaddo flow.");
12987
+ if (config.project.state === "legacy") return notReady("legacy-project", "Use the legacy project flow. The onboarding guide targets pre-AI projects.");
12988
+ const scan2 = exists(join(dir, ".kaddo", "scan.json")) ? "available" : "missing";
12989
+ const understand = exists(join(dir, ".kaddo", "understand.md")) ? "available" : "missing";
12990
+ const presence = Object.fromEntries(KNOWLEDGE_FILES.map((f) => [f.key, knowledgePresence(dir, f.path)]));
12991
+ const roadmap = roadmapSignal(dir);
12992
+ const work_items = workItemsSignal(dir);
12993
+ const adapters = installedAdapters(dir);
12994
+ const oq = buildOpenQuestionsReport(dir, now);
12995
+ const signals = {
12996
+ scan: scan2,
12997
+ understand,
12998
+ current_state: presence.current_state,
12999
+ codebase: presence.codebase,
13000
+ capabilities: presence.capabilities,
13001
+ product: presence.product,
13002
+ business: presence.business,
13003
+ roadmap,
13004
+ work_items,
13005
+ adapters,
13006
+ blocking_open_questions: oq.summary.blocking_open,
13007
+ assumed_questions: oq.summary.resolution.assumed,
13008
+ resolved_questions: oq.summary.resolution.resolved,
13009
+ deferred_questions: oq.summary.resolution.deferred
13010
+ };
13011
+ let status;
13012
+ let next;
13013
+ const firstWeak = KNOWLEDGE_FILES.find((f) => presence[f.key] !== "present");
13014
+ if (scan2 === "missing") {
13015
+ status = "initialized";
13016
+ next = { label: "Run `kaddo scan` to capture deterministic signals from the existing code.", command: "kaddo scan" };
13017
+ } else if (understand === "missing") {
13018
+ status = "scanned";
13019
+ next = { label: "Run `kaddo understand` to summarize the project context.", command: "kaddo understand" };
13020
+ } else if (firstWeak) {
13021
+ status = "knowledge-incomplete";
13022
+ next = { label: `Complete \`${firstWeak.label}\` (it is ${presence[firstWeak.key]}).` };
13023
+ } else if (oq.summary.blocking_open > 0) {
13024
+ status = "needs-decisions";
13025
+ next = { label: "Resolve, assume or defer the blocking open questions (`kaddo questions`).", command: "kaddo questions" };
13026
+ } else if (roadmap !== "has-candidates") {
13027
+ status = "ready-for-roadmap";
13028
+ next = { label: "Run `kaddo roadmap` to draft the roadmap from the current knowledge.", command: "kaddo roadmap" };
13029
+ } else if (work_items === "none" || work_items === "none-ready") {
13030
+ status = "ready-for-work-item";
13031
+ next = { label: "Run `kaddo create --from roadmap` to materialize the first Work Item.", command: "kaddo create --from roadmap" };
13032
+ } else {
13033
+ status = "ready-for-implementation";
13034
+ next = adapters.length > 0 ? { label: "Implement the ready Work Item with an installed adapter, then run `kaddo guard`." } : { label: "Install an adapter, then implement the ready Work Item.", command: "kaddo adapters list" };
13035
+ }
13036
+ return { generated_at: ts, project_name: config.project.name, project_type: config.project.state, status, signals, recommended_next_step: next };
13037
+ }
13038
+ function serializeOnboardingJson(r) {
13039
+ return JSON.stringify(r, null, 2) + "\n";
13040
+ }
13041
+ function renderOnboardingMarkdown(r) {
13042
+ const s = r.signals;
13043
+ const L = [];
13044
+ L.push("# Pre-AI Onboarding Report", "");
13045
+ L.push("## Summary", "");
13046
+ L.push(`- Project: ${r.project_name}`);
13047
+ L.push(`- Project type: ${r.project_type}`);
13048
+ L.push(`- Status: ${r.status}`);
13049
+ L.push("");
13050
+ if (r.status === "not-initialized" || r.status === "not-applicable" || r.status === "legacy-project") {
13051
+ L.push("## Recommended Next Step", "", r.recommended_next_step.label, "");
13052
+ return L.join("\n");
13053
+ }
13054
+ L.push("## Signals", "");
13055
+ L.push(`- Scan: ${s.scan}`);
13056
+ L.push(`- Understand: ${s.understand}`);
13057
+ L.push(`- Current state: ${s.current_state}`);
13058
+ L.push(`- Codebase: ${s.codebase}`);
13059
+ L.push(`- Capabilities: ${s.capabilities}`);
13060
+ L.push(`- Product: ${s.product}`);
13061
+ L.push(`- Business: ${s.business}`);
13062
+ L.push(`- Roadmap: ${s.roadmap}`);
13063
+ L.push(`- Work Items: ${s.work_items}`);
13064
+ L.push(`- Adapters: ${s.adapters.length > 0 ? s.adapters.join(", ") + " installed" : "none installed"}`);
13065
+ L.push("");
13066
+ L.push("## Questions", "");
13067
+ L.push(`- Blocking open: ${s.blocking_open_questions}`);
13068
+ L.push(`- Assumed: ${s.assumed_questions}`);
13069
+ L.push(`- Resolved: ${s.resolved_questions}`);
13070
+ L.push(`- Deferred: ${s.deferred_questions}`);
13071
+ L.push("");
13072
+ L.push("## Recommended Next Step", "", r.recommended_next_step.label, "");
13073
+ return L.join("\n");
13074
+ }
13075
+
13076
+ // src/commands/onboarding.ts
13077
+ function printConsole(r) {
13078
+ const s = r.signals;
13079
+ console.log("");
13080
+ console.log("Pre-AI Onboarding");
13081
+ console.log("");
13082
+ console.log(`Project: ${r.project_name}`);
13083
+ console.log(`Project type: ${r.project_type}`);
13084
+ console.log("");
13085
+ console.log("Status:");
13086
+ console.log(` overall: ${r.status}`);
13087
+ if (r.status !== "not-initialized" && r.status !== "not-applicable" && r.status !== "legacy-project") {
13088
+ console.log(` scan: ${s.scan}`);
13089
+ console.log(` understand: ${s.understand}`);
13090
+ console.log(` current-state: ${s.current_state}`);
13091
+ console.log(` codebase: ${s.codebase}`);
13092
+ console.log(` capabilities: ${s.capabilities}`);
13093
+ console.log(` roadmap: ${s.roadmap}`);
13094
+ console.log(` work-items: ${s.work_items}`);
13095
+ console.log(` adapters: ${s.adapters.length > 0 ? s.adapters.join(", ") + " installed" : "none installed"}`);
13096
+ console.log(` blocking open questions: ${s.blocking_open_questions}`);
13097
+ console.log(` assumptions: ${s.assumed_questions}`);
13098
+ console.log(` deferred: ${s.deferred_questions}`);
13099
+ }
13100
+ console.log("");
13101
+ console.log("Recommended next step:");
13102
+ console.log(` ${r.recommended_next_step.label}`);
13103
+ }
13104
+ function runOnboarding(opts = {}) {
13105
+ const dir = cwd();
13106
+ const report = buildOnboardingReport(dir);
13107
+ if (opts.json) {
13108
+ console.log(serializeOnboardingJson(report));
13109
+ return;
13110
+ }
13111
+ printConsole(report);
13112
+ printCommandFooter("onboarding");
13113
+ }
13114
+ function runOnboardingReport(opts = {}) {
13115
+ const dir = cwd();
13116
+ const report = buildOnboardingReport(dir);
13117
+ if (report.status === "not-initialized") {
13118
+ console.error("Kaddo is not initialized here. Run `kaddo init` first.");
13119
+ return;
13120
+ }
13121
+ intro2("kaddo report onboarding");
13122
+ const base = ".kaddo/reports";
13123
+ writeFile(join(dir, base, "onboarding-report.md"), renderOnboardingMarkdown(report));
13124
+ writeFile(join(dir, base, "onboarding-report.json"), serializeOnboardingJson(report));
13125
+ log2.success(`Wrote ${base}/onboarding-report.md and ${base}/onboarding-report.json`);
13126
+ log2.info(`Status: ${report.status} \u2014 ${report.recommended_next_step.label}`);
13127
+ printCommandFooter("onboarding");
13128
+ outro2("Onboarding report written.");
13129
+ }
13130
+
12894
13131
  // src/index.ts
12895
13132
  var require2 = createRequire(import.meta.url);
12896
13133
  var { version } = require2("../package.json");
@@ -12938,12 +13175,18 @@ savingsCmd.command("init").description("Create an editable `.kaddo/savings.yml`
12938
13175
  reportCmd.command("drift").description("Drift Trend Report from recorded guard history (deterministic, no LLM)").option("--json", "Output JSON instead of Markdown").option("--output <path>", "Write the report to a file (e.g. .kaddo/reports/drift-report.md)").action((opts) => {
12939
13176
  runDrift(opts);
12940
13177
  });
13178
+ reportCmd.command("onboarding").description("Write the pre-AI onboarding report to .kaddo/reports/ (deterministic, no LLM)").action(() => {
13179
+ runOnboardingReport();
13180
+ });
12941
13181
  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) => {
12942
13182
  runDrift(opts);
12943
13183
  });
12944
13184
  var questionsAction = (opts) => runQuestions(opts);
12945
13185
  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);
12946
13186
  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);
13187
+ program.command("onboarding").alias("onboard").description("Diagnose a pre-AI project and recommend the next step (read-only)").option("--json", "Output JSON").action((opts) => {
13188
+ runOnboarding(opts);
13189
+ });
12947
13190
  var adaptersCmd = program.command("adapters").description("Generate adapters that project Kaddo knowledge for external coding agents");
12948
13191
  adaptersCmd.command("install <adapter>").description("Generate an adapter file (codex/opencode/antigravity/kiro \u2192 AGENTS.md, claude \u2192 CLAUDE.md) from Kaddo knowledge").option("--force", "Overwrite an existing output file").option("--inject", "Add or update only the Kaddo block in an existing file, preserving the rest").option("--dry-run", "Print the content without writing files").action((adapter, opts) => {
12949
13192
  runAdaptersInstall(adapter, opts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.33.0",
3
+ "version": "3.34.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {