@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.
- package/LICENSE +21 -21
- package/README.md +2 -0
- package/dist/index.js +333 -60
- 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
|
|
570
|
-
return
|
|
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:
|
|
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.
|
|
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
|
|
3582
|
-
if (!exists(
|
|
3655
|
+
const path5 = join(dir, IGNORE_FILE);
|
|
3656
|
+
if (!exists(path5)) return [];
|
|
3583
3657
|
try {
|
|
3584
|
-
const raw = readFile(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
3633
|
-
if (!exists(
|
|
3706
|
+
const path5 = join(dir, DESCRIPTOR_PATH);
|
|
3707
|
+
if (!exists(path5)) return [];
|
|
3634
3708
|
let parsed;
|
|
3635
3709
|
try {
|
|
3636
|
-
parsed = parseYaml5(readFile(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
5892
|
-
if (!exists(
|
|
6046
|
+
const path5 = join(dir, DESCRIPTOR_PATH2);
|
|
6047
|
+
if (!exists(path5)) return null;
|
|
5893
6048
|
try {
|
|
5894
|
-
return parseYaml11(readFile(
|
|
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
|
|
7166
|
+
type: codebase
|
|
6925
7167
|
status: draft
|
|
6926
7168
|
---
|
|
6927
7169
|
|
|
6928
|
-
# Codebase
|
|
7170
|
+
# Codebase
|
|
6929
7171
|
|
|
6930
|
-
> Created by \`kaddo bootstrap\`. Refine with the
|
|
6931
|
-
>
|
|
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
|
-
##
|
|
7175
|
+
## Repository Structure
|
|
6934
7176
|
|
|
6935
7177
|
TBD
|
|
6936
7178
|
|
|
6937
|
-
##
|
|
7179
|
+
## Candidate Stack
|
|
6938
7180
|
|
|
6939
7181
|
- TBD
|
|
6940
7182
|
|
|
6941
|
-
##
|
|
7183
|
+
## Quality Attributes
|
|
6942
7184
|
|
|
6943
7185
|
- TBD
|
|
6944
7186
|
|
|
6945
|
-
##
|
|
7187
|
+
## Development Standards
|
|
6946
7188
|
|
|
6947
|
-
|
|
7189
|
+
- TBD
|
|
6948
7190
|
|
|
6949
|
-
##
|
|
7191
|
+
## Git Strategy
|
|
6950
7192
|
|
|
6951
|
-
|
|
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
|
|
7203
|
+
## Open Questions
|
|
6958
7204
|
|
|
6959
7205
|
- ...
|
|
6960
7206
|
|
|
6961
7207
|
${QUALITY}
|
|
6962
7208
|
|
|
6963
|
-
- [ ] Structure follows
|
|
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
|
|
7368
|
-
if (!exists(
|
|
7645
|
+
const path5 = join(dir, DESCRIPTOR_PATH3);
|
|
7646
|
+
if (!exists(path5)) return { version: 1, modules: [] };
|
|
7369
7647
|
try {
|
|
7370
|
-
const parsed = parseYaml12(readFile(
|
|
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
|
-
//
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
{ layer: "Business", path: "knowledge/business/
|
|
7581
|
-
{ layer: "
|
|
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.
|
|
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);
|