@kaddo/cli 3.0.0 → 3.2.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 (4) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +2 -0
  3. package/dist/index.js +333 -60
  4. package/package.json +1 -1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Judlup Luna
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Judlup Luna
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -432,6 +432,8 @@ create --from roadmap → owners → guard → explain`.
432
432
  | v2.7 | Multirepo hardening: module artifacts from the template registry, module-aware `context`/`explain`, opt-in `guard --workspace` |
433
433
  | v2.8 | `kaddo bootstrap` for new projects (Business → Product → Tech → Delivery); business templates + bootstrap agents |
434
434
  | v3.0 | Knowledge-centric realignment: `architecture/` → `knowledge/` with layers Business → Product → Tech → Delivery; context/explain by layer (breaking) |
435
+ | v3.1 | Minimum Sufficient Knowledge: bootstrap one consolidated file per layer; progressive `add agents` by group (state default, `--all`, `--group`) |
436
+ | v3.2 | New-project flow hardening: agents in per-layer folders; `new` recommends capability+architecture agents; explain Work Item parser fix; intent vs reality (codebase vs current-state) |
435
437
 
436
438
  **Optional modules (installed with `kaddo add`):**
437
439
 
package/dist/index.js CHANGED
@@ -566,8 +566,8 @@ function loadConfig(dir) {
566
566
  const parsed = configSchema.safeParse(raw ?? {});
567
567
  if (!parsed.success) {
568
568
  const issues = parsed.error.issues.map((i) => {
569
- const path6 = i.path.join(".");
570
- return path6 ? ` - ${path6}: ${i.message}` : ` - ${i.message}`;
569
+ const path5 = i.path.join(".");
570
+ return path5 ? ` - ${path5}: ${i.message}` : ` - ${i.message}`;
571
571
  }).join("\n");
572
572
  throw new ConfigError(`Invalid .kaddo/config.yml:
573
573
  ${issues}`);
@@ -2487,6 +2487,81 @@ var AGENT_PROMPTS = [
2487
2487
  { fileName: "codebase-agent.md", content: CODEBASE_FOUNDATION_AGENT }
2488
2488
  ];
2489
2489
 
2490
+ // src/agents/groups.ts
2491
+ var AGENT_GROUPS = {
2492
+ business: ["business-agent.md"],
2493
+ product: ["bootstrap-agent.md", "capability-agent.md"],
2494
+ tech: [
2495
+ "architecture-agent.md",
2496
+ "codebase-agent.md",
2497
+ "stack-agent.md",
2498
+ "security-agent.md",
2499
+ "standards-agent.md",
2500
+ "module-design-agent.md",
2501
+ "adr-agent.md"
2502
+ ],
2503
+ delivery: ["roadmap-agent.md", "work-item-agent.md", "git-strategy-agent.md"],
2504
+ utilities: ["legacy-agent.md"]
2505
+ };
2506
+ var AGENT_GROUP_NAMES = Object.keys(AGENT_GROUPS);
2507
+ function agentGroupOf(fileName) {
2508
+ for (const g of AGENT_GROUP_NAMES) {
2509
+ if (AGENT_GROUPS[g].includes(fileName)) return g;
2510
+ }
2511
+ return "utilities";
2512
+ }
2513
+ function agentInstallPath(fileName) {
2514
+ return `knowledge/agents/${agentGroupOf(fileName)}/${fileName}`;
2515
+ }
2516
+ var RECOMMENDED_BY_STATE = {
2517
+ new: [
2518
+ "business-agent.md",
2519
+ "bootstrap-agent.md",
2520
+ "capability-agent.md",
2521
+ "architecture-agent.md",
2522
+ "codebase-agent.md",
2523
+ "roadmap-agent.md",
2524
+ "work-item-agent.md",
2525
+ "adr-agent.md"
2526
+ ],
2527
+ "pre-ai": [
2528
+ "capability-agent.md",
2529
+ "architecture-agent.md",
2530
+ "roadmap-agent.md",
2531
+ "work-item-agent.md"
2532
+ ],
2533
+ legacy: [
2534
+ "legacy-agent.md",
2535
+ "architecture-agent.md",
2536
+ "capability-agent.md",
2537
+ "roadmap-agent.md",
2538
+ "work-item-agent.md"
2539
+ ]
2540
+ };
2541
+ function recommendedAgents(state) {
2542
+ return RECOMMENDED_BY_STATE[state ?? "pre-ai"] ?? RECOMMENDED_BY_STATE["pre-ai"];
2543
+ }
2544
+ function selectAgentFiles(opts) {
2545
+ if (opts.all) {
2546
+ const all = AGENT_GROUP_NAMES.flatMap((g) => AGENT_GROUPS[g]);
2547
+ return { files: all, label: "all agents" };
2548
+ }
2549
+ if (opts.group) {
2550
+ const group = opts.group;
2551
+ const files = AGENT_GROUPS[group];
2552
+ if (!files) {
2553
+ throw new Error(
2554
+ `Unknown agent group "${opts.group}". Valid groups: ${AGENT_GROUP_NAMES.join(", ")}.`
2555
+ );
2556
+ }
2557
+ return { files, label: `group: ${group}` };
2558
+ }
2559
+ return {
2560
+ files: recommendedAgents(opts.state),
2561
+ label: `recommended for state: ${opts.state ?? "pre-ai"}`
2562
+ };
2563
+ }
2564
+
2490
2565
  // src/modules/agents.ts
2491
2566
  var agentReadme = {
2492
2567
  path: "knowledge/agents/README.md",
@@ -2538,7 +2613,7 @@ var agentReadme = {
2538
2613
  ].join("\n")
2539
2614
  };
2540
2615
  var agentFiles = AGENT_PROMPTS.map((a) => ({
2541
- path: `knowledge/agents/${a.fileName}`,
2616
+ path: agentInstallPath(a.fileName),
2542
2617
  content: a.content
2543
2618
  }));
2544
2619
  var agentsModule = {
@@ -3518,9 +3593,8 @@ function readArtifacts(archDir) {
3518
3593
 
3519
3594
  // src/core/diff-analysis.ts
3520
3595
  import { minimatch } from "minimatch";
3521
- import path3 from "path";
3522
3596
  function normalizePath(p2) {
3523
- return p2.split(path3.sep).join("/");
3597
+ return p2.replace(/\\/g, "/");
3524
3598
  }
3525
3599
  function fileMatchesGlob(file, glob) {
3526
3600
  return minimatch(normalizePath(file), glob, { matchBase: false, dot: true });
@@ -3578,10 +3652,10 @@ function analyzeGuard(touchedFiles, artifacts, silentWithoutOwnership) {
3578
3652
  import { parse as parseYaml4, stringify as stringifyYaml2 } from "yaml";
3579
3653
  var IGNORE_FILE = ".kaddo/ignores.yml";
3580
3654
  function loadIgnores(dir) {
3581
- const path6 = join(dir, IGNORE_FILE);
3582
- if (!exists(path6)) return [];
3655
+ const path5 = join(dir, IGNORE_FILE);
3656
+ if (!exists(path5)) return [];
3583
3657
  try {
3584
- const raw = readFile(path6);
3658
+ const raw = readFile(path5);
3585
3659
  const parsed = parseYaml4(raw);
3586
3660
  return Array.isArray(parsed) ? parsed : [];
3587
3661
  } catch {
@@ -3589,7 +3663,7 @@ function loadIgnores(dir) {
3589
3663
  }
3590
3664
  }
3591
3665
  function saveIgnore(dir, entry) {
3592
- const path6 = join(dir, IGNORE_FILE);
3666
+ const path5 = join(dir, IGNORE_FILE);
3593
3667
  const existing = loadIgnores(dir);
3594
3668
  const idx = existing.findIndex((e) => e.artifact_id === entry.artifact_id);
3595
3669
  if (idx >= 0) {
@@ -3597,17 +3671,17 @@ function saveIgnore(dir, entry) {
3597
3671
  } else {
3598
3672
  existing.push(entry);
3599
3673
  }
3600
- writeFile(path6, stringifyYaml2(existing));
3674
+ writeFile(path5, stringifyYaml2(existing));
3601
3675
  }
3602
3676
  function isIgnored(ignores, artifactId) {
3603
3677
  return ignores.find((e) => e.artifact_id === artifactId);
3604
3678
  }
3605
3679
  function removeIgnore(dir, artifactId) {
3606
- const path6 = join(dir, IGNORE_FILE);
3680
+ const path5 = join(dir, IGNORE_FILE);
3607
3681
  const existing = loadIgnores(dir);
3608
3682
  const filtered = existing.filter((e) => e.artifact_id !== artifactId);
3609
3683
  if (filtered.length === existing.length) return false;
3610
- writeFile(path6, stringifyYaml2(filtered));
3684
+ writeFile(path5, stringifyYaml2(filtered));
3611
3685
  return true;
3612
3686
  }
3613
3687
 
@@ -3629,11 +3703,11 @@ function moduleArtifactCoverage(dir, id) {
3629
3703
  };
3630
3704
  }
3631
3705
  function loadMappedModules(dir) {
3632
- const path6 = join(dir, DESCRIPTOR_PATH);
3633
- if (!exists(path6)) return [];
3706
+ const path5 = join(dir, DESCRIPTOR_PATH);
3707
+ if (!exists(path5)) return [];
3634
3708
  let parsed;
3635
3709
  try {
3636
- parsed = parseYaml5(readFile(path6));
3710
+ parsed = parseYaml5(readFile(path5));
3637
3711
  } catch {
3638
3712
  return [];
3639
3713
  }
@@ -3725,7 +3799,7 @@ async function collectWorkspaceChanges(dir, mode = "head", deps = defaultDeps) {
3725
3799
  }
3726
3800
 
3727
3801
  // src/commands/guard.ts
3728
- import path4 from "path";
3802
+ import path3 from "path";
3729
3803
  import { parse as parseYaml7 } from "yaml";
3730
3804
 
3731
3805
  // src/plugins/prisma.ts
@@ -3929,7 +4003,7 @@ function printHeader(touchedFiles) {
3929
4003
  function artifactLabel(artifact, dir) {
3930
4004
  if (artifact.id) return artifact.id;
3931
4005
  if (artifact.title) return artifact.title;
3932
- const rel = path4.relative(dir, artifact.filePath).split(path4.sep).join("/");
4006
+ const rel = path3.relative(dir, artifact.filePath).split(path3.sep).join("/");
3933
4007
  return rel || artifact.filePath;
3934
4008
  }
3935
4009
  function printWorkspaceHeader(scan2) {
@@ -4212,6 +4286,12 @@ function knowledgeLayers(dir) {
4212
4286
  items: items.map((it) => ({ name: it.name, present: exists(join(dir, it.path)) }))
4213
4287
  }));
4214
4288
  }
4289
+ function currentPhase(layers) {
4290
+ for (const { layer, items } of layers) {
4291
+ if (items.some((i) => !i.present)) return layer;
4292
+ }
4293
+ return "Delivery";
4294
+ }
4215
4295
  function renderLayersMarkdown(layers) {
4216
4296
  const lines = [];
4217
4297
  for (const { layer, items } of layers) {
@@ -4256,7 +4336,18 @@ function loadScan(dir) {
4256
4336
  function hasAgents(dir) {
4257
4337
  const agentsDir = join(dir, ARCH_DIR3, "agents");
4258
4338
  if (!exists(agentsDir)) return false;
4259
- return readDir(agentsDir).some((e) => e.endsWith(".md") && isFile(join(agentsDir, e)));
4339
+ function hasAgentMd(d) {
4340
+ for (const e of readDir(d)) {
4341
+ const full = join(d, e);
4342
+ if (isFile(full)) {
4343
+ if (e.endsWith("-agent.md")) return true;
4344
+ } else if (hasAgentMd(full)) {
4345
+ return true;
4346
+ }
4347
+ }
4348
+ return false;
4349
+ }
4350
+ return hasAgentMd(agentsDir);
4260
4351
  }
4261
4352
  function buildProjectExplanation(dir) {
4262
4353
  const config = loadConfig(dir);
@@ -4288,9 +4379,10 @@ function buildProjectExplanation(dir) {
4288
4379
  };
4289
4380
  const archDir = join(dir, ARCH_DIR3);
4290
4381
  const allArtifacts = exists(archDir) ? readArtifacts(archDir) : [];
4291
- const workItemArtifacts = allArtifacts.filter(
4292
- (a) => a.type !== "current-state" && a.type !== "roadmap"
4293
- );
4382
+ const workItemArtifacts = allArtifacts.filter((a) => {
4383
+ const p2 = a.filePath.replace(/\\/g, "/");
4384
+ return p2.includes("/delivery/work-items/") && Boolean(a.type);
4385
+ });
4294
4386
  const items = workItemArtifacts.map((a) => ({
4295
4387
  id: a.id || a.title,
4296
4388
  title: a.title,
@@ -4520,7 +4612,7 @@ function explainForHuman(dir, artifacts, opts) {
4520
4612
  console.log("");
4521
4613
  }
4522
4614
  const workItems = artifacts.filter(
4523
- (a) => a.type !== "current-state" && a.type !== "roadmap" && a.status === "in-progress"
4615
+ (a) => a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type) && a.status === "in-progress"
4524
4616
  );
4525
4617
  if (workItems.length > 0) {
4526
4618
  console.log("## Active work items");
@@ -4940,6 +5032,9 @@ function runContext(opts = {}) {
4940
5032
  }
4941
5033
 
4942
5034
  // src/core/understand.ts
5035
+ function agentIsInstalled(dir, fileName) {
5036
+ return exists(join(dir, agentInstallPath(fileName))) || exists(join(dir, "knowledge", "agents", fileName));
5037
+ }
4943
5038
  function flowForState(state) {
4944
5039
  switch (state) {
4945
5040
  case "new":
@@ -4967,7 +5062,7 @@ function buildUnderstandPlan(dir, config) {
4967
5062
  const state = config.project.state;
4968
5063
  const flow = flowForState(state);
4969
5064
  const steps = flow.map((s) => {
4970
- const installed = exists(join(dir, "knowledge", "agents", s.agent));
5065
+ const installed = agentIsInstalled(dir, s.agent);
4971
5066
  return { agent: s.agent, output: s.output, installed };
4972
5067
  });
4973
5068
  const missingAgents = steps.filter((s) => !s.installed).map((s) => s.agent);
@@ -5122,13 +5217,43 @@ function runUnderstand() {
5122
5217
  );
5123
5218
  }
5124
5219
  console.log(renderUnderstandTerminal(plan));
5220
+ const phase = currentPhase(knowledgeLayers(dir));
5221
+ const group = phase.toLowerCase();
5222
+ const groupAgents = (AGENT_GROUPS[group] ?? []).map((a) => a.replace(/\.md$/, ""));
5223
+ const NEXT_STEPS = {
5224
+ business: ["Use business-agent \u2192 refine knowledge/business/business.md"],
5225
+ product: [
5226
+ "Use bootstrap-agent \u2192 refine knowledge/product/product.md",
5227
+ "Use capability-agent \u2192 knowledge/product/capabilities.md"
5228
+ ],
5229
+ tech: [
5230
+ "Use architecture-agent \u2192 knowledge/tech/current-state.md (reality)",
5231
+ "Use codebase-agent \u2192 knowledge/tech/codebase.md (intent)",
5232
+ "Record decisions as ADRs in knowledge/tech/decisions/"
5233
+ ],
5234
+ delivery: [
5235
+ "Use roadmap-agent \u2192 knowledge/delivery/roadmap.md",
5236
+ "Run `kaddo create --from roadmap`, then `kaddo owners suggest`"
5237
+ ],
5238
+ utilities: ["Use legacy-agent to surface risks and unknowns"]
5239
+ };
5240
+ console.log("");
5241
+ console.log(`Current phase: ${phase}`);
5242
+ console.log("Recommended next steps:");
5243
+ console.log(" 1. Run `kaddo scan` (technical signals \u2192 knowledge/inventory.md)");
5244
+ console.log(" 2. Run `kaddo context` (package knowledge for your LLM)");
5245
+ let n = 3;
5246
+ for (const step of NEXT_STEPS[group] ?? []) console.log(` ${n++}. ${step}`);
5247
+ if (groupAgents.length > 0) {
5248
+ console.log(`Agents for this phase: ${groupAgents.join(", ")}`);
5249
+ }
5125
5250
  writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(plan));
5126
5251
  log2.success("Wrote .kaddo/understand.md");
5127
5252
  outro2("Handoff ready. CLI prepares context \u2014 your LLM creates the understanding.");
5128
5253
  }
5129
5254
 
5130
5255
  // src/core/classifier.ts
5131
- import path5 from "path";
5256
+ import path4 from "path";
5132
5257
  var MIGRATION_PATTERNS = [
5133
5258
  /supabase\/migrations\//,
5134
5259
  /prisma\/migrations\//,
@@ -5167,7 +5292,7 @@ var DEP_PATTERNS = [
5167
5292
  /^pom\.xml$/
5168
5293
  ];
5169
5294
  function normalizePath2(p2) {
5170
- return p2.split(path5.sep).join("/");
5295
+ return p2.split(path4.sep).join("/");
5171
5296
  }
5172
5297
  function matchesAny(file, patterns) {
5173
5298
  const normalized = normalizePath2(file);
@@ -5556,6 +5681,24 @@ function runHistory(opts = {}) {
5556
5681
  // src/commands/add.ts
5557
5682
  import { parse as parseYaml10, stringify as stringifyYaml3 } from "yaml";
5558
5683
  var CONFIG_PATH5 = ".kaddo/config.yml";
5684
+ function readProjectState(dir) {
5685
+ const configPath = join(dir, CONFIG_PATH5);
5686
+ if (!exists(configPath)) return void 0;
5687
+ try {
5688
+ const config = parseYaml10(readFile(configPath));
5689
+ return config.project?.state;
5690
+ } catch {
5691
+ return void 0;
5692
+ }
5693
+ }
5694
+ function selectAgentModuleFiles(files, opts, state) {
5695
+ const { files: names, label } = selectAgentFiles({ all: opts.all, group: opts.group, state });
5696
+ const wanted = new Set(names);
5697
+ const selected = files.filter(
5698
+ (f) => f.path.endsWith("README.md") || names.some((n) => f.path.endsWith(n)) || wanted.has(f.path)
5699
+ );
5700
+ return { files: selected, label };
5701
+ }
5559
5702
  function markModuleInstalled(dir, configKey, moduleName) {
5560
5703
  const configPath = join(dir, CONFIG_PATH5);
5561
5704
  if (!exists(configPath)) return;
@@ -5580,7 +5723,7 @@ function isModuleInstalled(dir, configKey) {
5580
5723
  return false;
5581
5724
  }
5582
5725
  }
5583
- function runAdd(moduleName, dir = cwd()) {
5726
+ function runAdd(moduleName, opts = {}, dir = cwd()) {
5584
5727
  if (!moduleName) {
5585
5728
  console.log("");
5586
5729
  console.log("Available modules:");
@@ -5606,9 +5749,20 @@ function runAdd(moduleName, dir = cwd()) {
5606
5749
  for (const d of mod.dirs) {
5607
5750
  ensureDir(join(dir, d));
5608
5751
  }
5752
+ let filesToInstall = mod.files;
5753
+ if (mod.name === "agents") {
5754
+ try {
5755
+ const sel = selectAgentModuleFiles(mod.files, opts, readProjectState(dir));
5756
+ filesToInstall = sel.files;
5757
+ log2.info(`Installing agents (${sel.label}).`);
5758
+ } catch (err) {
5759
+ console.error(err instanceof Error ? err.message : String(err));
5760
+ process.exit(1);
5761
+ }
5762
+ }
5609
5763
  const written = [];
5610
5764
  const skipped = [];
5611
- for (const file of mod.files) {
5765
+ for (const file of filesToInstall) {
5612
5766
  const fullPath = join(dir, file.path);
5613
5767
  if (exists(fullPath)) {
5614
5768
  skipped.push(file.path);
@@ -5631,6 +5785,7 @@ function runAdd(moduleName, dir = cwd()) {
5631
5785
  console.log(" 2. Open your preferred LLM chat");
5632
5786
  console.log(" 3. Paste `.kaddo/context-pack.md`");
5633
5787
  console.log(" 4. Use the recommended agent for your project state");
5788
+ log2.info("More agents: `kaddo add agents --all` or `--group <business|product|tech|delivery|utilities>`.");
5634
5789
  outro2("Agents installed. Kaddo prepares context \u2014 your LLM does the interpretation.");
5635
5790
  return;
5636
5791
  }
@@ -5888,10 +6043,10 @@ ${globs.map((g) => ` - ${g}`).join("\n")}`);
5888
6043
  import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
5889
6044
  var DESCRIPTOR_PATH2 = "knowledge/module.yml";
5890
6045
  function readDescriptor(dir) {
5891
- const path6 = join(dir, DESCRIPTOR_PATH2);
5892
- if (!exists(path6)) return null;
6046
+ const path5 = join(dir, DESCRIPTOR_PATH2);
6047
+ if (!exists(path5)) return null;
5893
6048
  try {
5894
- return parseYaml11(readFile(path6));
6049
+ return parseYaml11(readFile(path5));
5895
6050
  } catch {
5896
6051
  return null;
5897
6052
  }
@@ -6920,47 +7075,138 @@ ${QUALITY}
6920
7075
  - [ ] Attributes are prioritized, not all "high".
6921
7076
  - [ ] Trade-offs are explicit.
6922
7077
  `;
7078
+ var BUSINESS_CONSOLIDATED = `---
7079
+ type: business
7080
+ status: draft
7081
+ ---
7082
+
7083
+ # Business
7084
+
7085
+ > Created by \`kaddo bootstrap\`. The minimal **why** of the project. Refine with the
7086
+ > business-agent. As this matures it can split into problem.md, users.md, \u2026
7087
+
7088
+ ## Problem
7089
+
7090
+ TBD
7091
+
7092
+ ## Users
7093
+
7094
+ TBD
7095
+
7096
+ ## Value Proposition
7097
+
7098
+ TBD
7099
+
7100
+ ## Business Rules
7101
+
7102
+ - TBD
7103
+
7104
+ ## Constraints
7105
+
7106
+ - TBD
7107
+
7108
+ ## Assumptions
7109
+
7110
+ - ...
7111
+
7112
+ ## Open Questions
7113
+
7114
+ - ...
7115
+
7116
+ ${QUALITY}
7117
+
7118
+ - [ ] The problem is stated without assuming the solution.
7119
+ - [ ] Users have goals, not just labels.
7120
+ `;
7121
+ var PRODUCT_CONSOLIDATED = `---
7122
+ type: product
7123
+ status: draft
7124
+ ---
7125
+
7126
+ # Product
7127
+
7128
+ > Created by \`kaddo bootstrap\`. The minimal **what** of the project. Refine with the
7129
+ > bootstrap-agent / capability-agent. As this matures it can split into product-brief.md
7130
+ > and capabilities.md.
7131
+
7132
+ ## Product Brief
7133
+
7134
+ TBD
7135
+
7136
+ ## Capabilities
7137
+
7138
+ - TBD
7139
+
7140
+ ## Scope
7141
+
7142
+ - TBD
7143
+
7144
+ ## Out of Scope
7145
+
7146
+ - TBD
7147
+
7148
+ ## Success Criteria
7149
+
7150
+ - TBD
7151
+
7152
+ ## Assumptions
7153
+
7154
+ - ...
7155
+
7156
+ ## Open Questions
7157
+
7158
+ - ...
7159
+
7160
+ ${QUALITY}
7161
+
7162
+ - [ ] The product fits in one page.
7163
+ - [ ] Scope and out-of-scope are explicit.
7164
+ `;
6923
7165
  var CODEBASE_FOUNDATION = `---
6924
- type: codebase-foundation
7166
+ type: codebase
6925
7167
  status: draft
6926
7168
  ---
6927
7169
 
6928
- # Codebase Foundation
7170
+ # Codebase
6929
7171
 
6930
- > Created by \`kaddo bootstrap\`. Refine with the codebase-agent.
6931
- > This describes the intended base \u2014 it does **not** generate code.
7172
+ > Created by \`kaddo bootstrap\`. The minimal **how** of the project. Refine with the
7173
+ > codebase-agent. It describes the intended base \u2014 it does **not** generate code.
6932
7174
 
6933
- ## Suggested structure
7175
+ ## Repository Structure
6934
7176
 
6935
7177
  TBD
6936
7178
 
6937
- ## Initial modules / boundaries
7179
+ ## Candidate Stack
6938
7180
 
6939
7181
  - TBD
6940
7182
 
6941
- ## Conventions
7183
+ ## Quality Attributes
6942
7184
 
6943
7185
  - TBD
6944
7186
 
6945
- ## Git strategy
7187
+ ## Development Standards
6946
7188
 
6947
- See \`knowledge/tech/git-strategy.md\`.
7189
+ - TBD
6948
7190
 
6949
- ## Minimum criteria to start development
7191
+ ## Git Strategy
6950
7192
 
6951
- - [ ] TBD
7193
+ GitHub Flow + Conventional Commits + SemVer (default). See \`kaddo add git-strategy\`.
7194
+
7195
+ ## Initial Modules
7196
+
7197
+ - TBD
6952
7198
 
6953
7199
  ## Assumptions
6954
7200
 
6955
7201
  - ...
6956
7202
 
6957
- ## Open questions
7203
+ ## Open Questions
6958
7204
 
6959
7205
  - ...
6960
7206
 
6961
7207
  ${QUALITY}
6962
7208
 
6963
- - [ ] Structure follows the business and architecture, not a framework default.
7209
+ - [ ] Structure follows business and product, not a framework default.
6964
7210
  - [ ] No production code is described here \u2014 only the foundation.
6965
7211
  `;
6966
7212
  var BOOTSTRAP_SUMMARY = `---
@@ -7034,6 +7280,7 @@ var KADDO_TEMPLATES = [
7034
7280
  description: "What the system can do from the product point of view.",
7035
7281
  whenToUse: "When mapping product capabilities to the system.",
7036
7282
  relatedAgent: "capability-agent",
7283
+ advanced: true,
7037
7284
  content: CAPABILITIES
7038
7285
  },
7039
7286
  {
@@ -7046,7 +7293,30 @@ var KADDO_TEMPLATES = [
7046
7293
  relatedCommand: "kaddo init",
7047
7294
  content: KNOWLEDGE2
7048
7295
  },
7049
- // business (bootstrap)
7296
+ // business / product (bootstrap — consolidated, minimal)
7297
+ {
7298
+ id: "business",
7299
+ name: "Business",
7300
+ category: "business",
7301
+ outputPath: "knowledge/business/business.md",
7302
+ description: "The minimal why: problem, users, value, rules, constraints (one file).",
7303
+ whenToUse: "Generated by kaddo bootstrap for new projects.",
7304
+ relatedCommand: "kaddo bootstrap",
7305
+ relatedAgent: "business-agent",
7306
+ content: BUSINESS_CONSOLIDATED
7307
+ },
7308
+ {
7309
+ id: "product",
7310
+ name: "Product",
7311
+ category: "product",
7312
+ outputPath: "knowledge/product/product.md",
7313
+ description: "The minimal what: product brief, capabilities, scope (one file).",
7314
+ whenToUse: "Generated by kaddo bootstrap for new projects.",
7315
+ relatedCommand: "kaddo bootstrap",
7316
+ relatedAgent: "bootstrap-agent",
7317
+ content: PRODUCT_CONSOLIDATED
7318
+ },
7319
+ // business (advanced — split out as knowledge matures, not generated by bootstrap)
7050
7320
  {
7051
7321
  id: "business-product-brief",
7052
7322
  name: "Product Brief",
@@ -7056,6 +7326,7 @@ var KADDO_TEMPLATES = [
7056
7326
  whenToUse: "At the start of a new project (kaddo bootstrap).",
7057
7327
  relatedCommand: "kaddo bootstrap",
7058
7328
  relatedAgent: "business-agent",
7329
+ advanced: true,
7059
7330
  content: BUSINESS_PRODUCT_BRIEF
7060
7331
  },
7061
7332
  {
@@ -7067,6 +7338,7 @@ var KADDO_TEMPLATES = [
7067
7338
  whenToUse: "When defining a new project (kaddo bootstrap).",
7068
7339
  relatedCommand: "kaddo bootstrap",
7069
7340
  relatedAgent: "business-agent",
7341
+ advanced: true,
7070
7342
  content: BUSINESS_PROBLEM
7071
7343
  },
7072
7344
  {
@@ -7078,6 +7350,7 @@ var KADDO_TEMPLATES = [
7078
7350
  whenToUse: "When defining a new project (kaddo bootstrap).",
7079
7351
  relatedCommand: "kaddo bootstrap",
7080
7352
  relatedAgent: "business-agent",
7353
+ advanced: true,
7081
7354
  content: BUSINESS_USERS
7082
7355
  },
7083
7356
  {
@@ -7089,6 +7362,7 @@ var KADDO_TEMPLATES = [
7089
7362
  whenToUse: "When defining a new project (kaddo bootstrap).",
7090
7363
  relatedCommand: "kaddo bootstrap",
7091
7364
  relatedAgent: "business-agent",
7365
+ advanced: true,
7092
7366
  content: BUSINESS_VALUE_PROPOSITION
7093
7367
  },
7094
7368
  {
@@ -7100,6 +7374,7 @@ var KADDO_TEMPLATES = [
7100
7374
  whenToUse: "When defining a new project (kaddo bootstrap).",
7101
7375
  relatedCommand: "kaddo bootstrap",
7102
7376
  relatedAgent: "business-agent",
7377
+ advanced: true,
7103
7378
  content: BUSINESS_RULES
7104
7379
  },
7105
7380
  {
@@ -7111,6 +7386,7 @@ var KADDO_TEMPLATES = [
7111
7386
  whenToUse: "When defining a new project (kaddo bootstrap).",
7112
7387
  relatedCommand: "kaddo bootstrap",
7113
7388
  relatedAgent: "business-agent",
7389
+ advanced: true,
7114
7390
  content: BUSINESS_CONSTRAINTS
7115
7391
  },
7116
7392
  {
@@ -7122,6 +7398,7 @@ var KADDO_TEMPLATES = [
7122
7398
  whenToUse: "When defining a new project (kaddo bootstrap).",
7123
7399
  relatedCommand: "kaddo bootstrap",
7124
7400
  relatedAgent: "business-agent",
7401
+ advanced: true,
7125
7402
  content: BUSINESS_GLOSSARY
7126
7403
  },
7127
7404
  // architecture
@@ -7163,6 +7440,7 @@ var KADDO_TEMPLATES = [
7163
7440
  whenToUse: "During bootstrap, to record what matters most technically.",
7164
7441
  relatedCommand: "kaddo bootstrap",
7165
7442
  relatedAgent: "bootstrap-agent",
7443
+ advanced: true,
7166
7444
  content: QUALITY_ATTRIBUTES
7167
7445
  },
7168
7446
  {
@@ -7364,10 +7642,10 @@ function slugify2(name) {
7364
7642
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
7365
7643
  }
7366
7644
  function readModulesDescriptor(dir) {
7367
- const path6 = join(dir, DESCRIPTOR_PATH3);
7368
- if (!exists(path6)) return { version: 1, modules: [] };
7645
+ const path5 = join(dir, DESCRIPTOR_PATH3);
7646
+ if (!exists(path5)) return { version: 1, modules: [] };
7369
7647
  try {
7370
- const parsed = parseYaml12(readFile(path6));
7648
+ const parsed = parseYaml12(readFile(path5));
7371
7649
  return { version: parsed.version ?? 1, modules: parsed.modules ?? [] };
7372
7650
  } catch {
7373
7651
  return { version: 1, modules: [] };
@@ -7574,16 +7852,11 @@ function runModulesList(dir = cwd()) {
7574
7852
  // src/commands/bootstrap.ts
7575
7853
  var CONFIG_PATH8 = ".kaddo/config.yml";
7576
7854
  var TARGETS = [
7577
- // Business why it exists
7578
- { layer: "Business", path: "knowledge/business/problem.md", templateId: "business-problem" },
7579
- { layer: "Business", path: "knowledge/business/users.md", templateId: "business-users" },
7580
- { layer: "Business", path: "knowledge/business/value-proposition.md", templateId: "business-value-proposition" },
7581
- { layer: "Business", path: "knowledge/business/constraints.md", templateId: "business-constraints" },
7582
- { layer: "Business", path: "knowledge/business/business-rules.md", templateId: "business-rules" },
7583
- // Product — what we build
7584
- { layer: "Product", path: "knowledge/product/product-brief.md", templateId: "business-product-brief" },
7585
- { layer: "Product", path: "knowledge/product/capabilities.md", templateId: "capabilities" },
7586
- // Tech — how we build it
7855
+ // Minimum sufficient knowledge: one consolidated file per layer. Specialized
7856
+ // artifacts (problem.md, users.md, capabilities.md, …) appear later, as the project
7857
+ // matures, via agents and refinement — not at bootstrap.
7858
+ { layer: "Business", path: "knowledge/business/business.md", templateId: "business" },
7859
+ { layer: "Product", path: "knowledge/product/product.md", templateId: "product" },
7587
7860
  { layer: "Tech", path: "knowledge/tech/codebase.md", templateId: "codebase" }
7588
7861
  ];
7589
7862
  var BOOTSTRAP_LAYERS = ["Business", "Product", "Tech"];
@@ -7652,7 +7925,7 @@ async function runBootstrap(dir = cwd()) {
7652
7925
 
7653
7926
  // src/index.ts
7654
7927
  var program = new Command();
7655
- program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.0.0");
7928
+ program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.2.0");
7656
7929
  program.command("init").description("Initialize Kaddo in the current project").action(async () => {
7657
7930
  await runInit();
7658
7931
  });
@@ -7716,8 +7989,8 @@ modulesCmd.command("map").description("Register a secondary repository as a modu
7716
7989
  modulesCmd.command("list").description("List mapped modules").action(() => {
7717
7990
  runModulesList();
7718
7991
  });
7719
- program.command("add [module]").description("Install an optional Kaddo module (adr, incident, rfc, migration, legacy, agents, standards, security, stack, git-strategy)").action((moduleName) => {
7720
- runAdd(moduleName ?? "");
7992
+ program.command("add [module]").description("Install an optional Kaddo module (adr, incident, rfc, migration, legacy, agents, standards, security, stack, git-strategy)").option("--all", "For `add agents`: install every agent (not just the recommended set)").option("--group <name>", "For `add agents`: install one layer group (business, product, tech, delivery, utilities)").action((moduleName, opts) => {
7993
+ runAdd(moduleName ?? "", { all: opts.all, group: opts.group });
7721
7994
  });
7722
7995
  program.parseAsync(process.argv).catch((err) => {
7723
7996
  console.error(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {