@kaddo/cli 3.0.0 → 3.1.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 +1 -0
- package/dist/index.js +278 -53
- 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,7 @@ 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`) |
|
|
435
436
|
|
|
436
437
|
**Optional modules (installed with `kaddo add`):**
|
|
437
438
|
|
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}`);
|
|
@@ -3518,9 +3518,8 @@ function readArtifacts(archDir) {
|
|
|
3518
3518
|
|
|
3519
3519
|
// src/core/diff-analysis.ts
|
|
3520
3520
|
import { minimatch } from "minimatch";
|
|
3521
|
-
import path3 from "path";
|
|
3522
3521
|
function normalizePath(p2) {
|
|
3523
|
-
return p2.
|
|
3522
|
+
return p2.replace(/\\/g, "/");
|
|
3524
3523
|
}
|
|
3525
3524
|
function fileMatchesGlob(file, glob) {
|
|
3526
3525
|
return minimatch(normalizePath(file), glob, { matchBase: false, dot: true });
|
|
@@ -3578,10 +3577,10 @@ function analyzeGuard(touchedFiles, artifacts, silentWithoutOwnership) {
|
|
|
3578
3577
|
import { parse as parseYaml4, stringify as stringifyYaml2 } from "yaml";
|
|
3579
3578
|
var IGNORE_FILE = ".kaddo/ignores.yml";
|
|
3580
3579
|
function loadIgnores(dir) {
|
|
3581
|
-
const
|
|
3582
|
-
if (!exists(
|
|
3580
|
+
const path5 = join(dir, IGNORE_FILE);
|
|
3581
|
+
if (!exists(path5)) return [];
|
|
3583
3582
|
try {
|
|
3584
|
-
const raw = readFile(
|
|
3583
|
+
const raw = readFile(path5);
|
|
3585
3584
|
const parsed = parseYaml4(raw);
|
|
3586
3585
|
return Array.isArray(parsed) ? parsed : [];
|
|
3587
3586
|
} catch {
|
|
@@ -3589,7 +3588,7 @@ function loadIgnores(dir) {
|
|
|
3589
3588
|
}
|
|
3590
3589
|
}
|
|
3591
3590
|
function saveIgnore(dir, entry) {
|
|
3592
|
-
const
|
|
3591
|
+
const path5 = join(dir, IGNORE_FILE);
|
|
3593
3592
|
const existing = loadIgnores(dir);
|
|
3594
3593
|
const idx = existing.findIndex((e) => e.artifact_id === entry.artifact_id);
|
|
3595
3594
|
if (idx >= 0) {
|
|
@@ -3597,17 +3596,17 @@ function saveIgnore(dir, entry) {
|
|
|
3597
3596
|
} else {
|
|
3598
3597
|
existing.push(entry);
|
|
3599
3598
|
}
|
|
3600
|
-
writeFile(
|
|
3599
|
+
writeFile(path5, stringifyYaml2(existing));
|
|
3601
3600
|
}
|
|
3602
3601
|
function isIgnored(ignores, artifactId) {
|
|
3603
3602
|
return ignores.find((e) => e.artifact_id === artifactId);
|
|
3604
3603
|
}
|
|
3605
3604
|
function removeIgnore(dir, artifactId) {
|
|
3606
|
-
const
|
|
3605
|
+
const path5 = join(dir, IGNORE_FILE);
|
|
3607
3606
|
const existing = loadIgnores(dir);
|
|
3608
3607
|
const filtered = existing.filter((e) => e.artifact_id !== artifactId);
|
|
3609
3608
|
if (filtered.length === existing.length) return false;
|
|
3610
|
-
writeFile(
|
|
3609
|
+
writeFile(path5, stringifyYaml2(filtered));
|
|
3611
3610
|
return true;
|
|
3612
3611
|
}
|
|
3613
3612
|
|
|
@@ -3629,11 +3628,11 @@ function moduleArtifactCoverage(dir, id) {
|
|
|
3629
3628
|
};
|
|
3630
3629
|
}
|
|
3631
3630
|
function loadMappedModules(dir) {
|
|
3632
|
-
const
|
|
3633
|
-
if (!exists(
|
|
3631
|
+
const path5 = join(dir, DESCRIPTOR_PATH);
|
|
3632
|
+
if (!exists(path5)) return [];
|
|
3634
3633
|
let parsed;
|
|
3635
3634
|
try {
|
|
3636
|
-
parsed = parseYaml5(readFile(
|
|
3635
|
+
parsed = parseYaml5(readFile(path5));
|
|
3637
3636
|
} catch {
|
|
3638
3637
|
return [];
|
|
3639
3638
|
}
|
|
@@ -3725,7 +3724,7 @@ async function collectWorkspaceChanges(dir, mode = "head", deps = defaultDeps) {
|
|
|
3725
3724
|
}
|
|
3726
3725
|
|
|
3727
3726
|
// src/commands/guard.ts
|
|
3728
|
-
import
|
|
3727
|
+
import path3 from "path";
|
|
3729
3728
|
import { parse as parseYaml7 } from "yaml";
|
|
3730
3729
|
|
|
3731
3730
|
// src/plugins/prisma.ts
|
|
@@ -3929,7 +3928,7 @@ function printHeader(touchedFiles) {
|
|
|
3929
3928
|
function artifactLabel(artifact, dir) {
|
|
3930
3929
|
if (artifact.id) return artifact.id;
|
|
3931
3930
|
if (artifact.title) return artifact.title;
|
|
3932
|
-
const rel =
|
|
3931
|
+
const rel = path3.relative(dir, artifact.filePath).split(path3.sep).join("/");
|
|
3933
3932
|
return rel || artifact.filePath;
|
|
3934
3933
|
}
|
|
3935
3934
|
function printWorkspaceHeader(scan2) {
|
|
@@ -4212,6 +4211,12 @@ function knowledgeLayers(dir) {
|
|
|
4212
4211
|
items: items.map((it) => ({ name: it.name, present: exists(join(dir, it.path)) }))
|
|
4213
4212
|
}));
|
|
4214
4213
|
}
|
|
4214
|
+
function currentPhase(layers) {
|
|
4215
|
+
for (const { layer, items } of layers) {
|
|
4216
|
+
if (items.some((i) => !i.present)) return layer;
|
|
4217
|
+
}
|
|
4218
|
+
return "Delivery";
|
|
4219
|
+
}
|
|
4215
4220
|
function renderLayersMarkdown(layers) {
|
|
4216
4221
|
const lines = [];
|
|
4217
4222
|
for (const { layer, items } of layers) {
|
|
@@ -5090,6 +5095,69 @@ function renderUnderstandTerminal(plan) {
|
|
|
5090
5095
|
return lines.join("\n");
|
|
5091
5096
|
}
|
|
5092
5097
|
|
|
5098
|
+
// src/agents/groups.ts
|
|
5099
|
+
var AGENT_GROUPS = {
|
|
5100
|
+
business: ["business-agent.md"],
|
|
5101
|
+
product: ["bootstrap-agent.md", "capability-agent.md"],
|
|
5102
|
+
tech: [
|
|
5103
|
+
"architecture-agent.md",
|
|
5104
|
+
"codebase-agent.md",
|
|
5105
|
+
"stack-agent.md",
|
|
5106
|
+
"security-agent.md",
|
|
5107
|
+
"standards-agent.md",
|
|
5108
|
+
"module-design-agent.md",
|
|
5109
|
+
"adr-agent.md"
|
|
5110
|
+
],
|
|
5111
|
+
delivery: ["roadmap-agent.md", "work-item-agent.md", "git-strategy-agent.md"],
|
|
5112
|
+
utilities: ["legacy-agent.md"]
|
|
5113
|
+
};
|
|
5114
|
+
var AGENT_GROUP_NAMES = Object.keys(AGENT_GROUPS);
|
|
5115
|
+
var RECOMMENDED_BY_STATE = {
|
|
5116
|
+
new: [
|
|
5117
|
+
"business-agent.md",
|
|
5118
|
+
"bootstrap-agent.md",
|
|
5119
|
+
"codebase-agent.md",
|
|
5120
|
+
"roadmap-agent.md",
|
|
5121
|
+
"work-item-agent.md"
|
|
5122
|
+
],
|
|
5123
|
+
"pre-ai": [
|
|
5124
|
+
"capability-agent.md",
|
|
5125
|
+
"architecture-agent.md",
|
|
5126
|
+
"roadmap-agent.md",
|
|
5127
|
+
"work-item-agent.md"
|
|
5128
|
+
],
|
|
5129
|
+
legacy: [
|
|
5130
|
+
"legacy-agent.md",
|
|
5131
|
+
"architecture-agent.md",
|
|
5132
|
+
"capability-agent.md",
|
|
5133
|
+
"roadmap-agent.md",
|
|
5134
|
+
"work-item-agent.md"
|
|
5135
|
+
]
|
|
5136
|
+
};
|
|
5137
|
+
function recommendedAgents(state) {
|
|
5138
|
+
return RECOMMENDED_BY_STATE[state ?? "pre-ai"] ?? RECOMMENDED_BY_STATE["pre-ai"];
|
|
5139
|
+
}
|
|
5140
|
+
function selectAgentFiles(opts) {
|
|
5141
|
+
if (opts.all) {
|
|
5142
|
+
const all = AGENT_GROUP_NAMES.flatMap((g) => AGENT_GROUPS[g]);
|
|
5143
|
+
return { files: all, label: "all agents" };
|
|
5144
|
+
}
|
|
5145
|
+
if (opts.group) {
|
|
5146
|
+
const group = opts.group;
|
|
5147
|
+
const files = AGENT_GROUPS[group];
|
|
5148
|
+
if (!files) {
|
|
5149
|
+
throw new Error(
|
|
5150
|
+
`Unknown agent group "${opts.group}". Valid groups: ${AGENT_GROUP_NAMES.join(", ")}.`
|
|
5151
|
+
);
|
|
5152
|
+
}
|
|
5153
|
+
return { files, label: `group: ${group}` };
|
|
5154
|
+
}
|
|
5155
|
+
return {
|
|
5156
|
+
files: recommendedAgents(opts.state),
|
|
5157
|
+
label: `recommended for state: ${opts.state ?? "pre-ai"}`
|
|
5158
|
+
};
|
|
5159
|
+
}
|
|
5160
|
+
|
|
5093
5161
|
// src/commands/understand.ts
|
|
5094
5162
|
function runUnderstand() {
|
|
5095
5163
|
const dir = cwd();
|
|
@@ -5122,13 +5190,22 @@ function runUnderstand() {
|
|
|
5122
5190
|
);
|
|
5123
5191
|
}
|
|
5124
5192
|
console.log(renderUnderstandTerminal(plan));
|
|
5193
|
+
const phase = currentPhase(knowledgeLayers(dir));
|
|
5194
|
+
const group = phase.toLowerCase();
|
|
5195
|
+
const groupAgents = (AGENT_GROUPS[group] ?? []).map((a) => a.replace(/\.md$/, ""));
|
|
5196
|
+
if (groupAgents.length > 0) {
|
|
5197
|
+
console.log("");
|
|
5198
|
+
console.log(`Current phase: ${phase}`);
|
|
5199
|
+
console.log("Recommended agents for this phase:");
|
|
5200
|
+
for (const a of groupAgents) console.log(` - ${a}`);
|
|
5201
|
+
}
|
|
5125
5202
|
writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(plan));
|
|
5126
5203
|
log2.success("Wrote .kaddo/understand.md");
|
|
5127
5204
|
outro2("Handoff ready. CLI prepares context \u2014 your LLM creates the understanding.");
|
|
5128
5205
|
}
|
|
5129
5206
|
|
|
5130
5207
|
// src/core/classifier.ts
|
|
5131
|
-
import
|
|
5208
|
+
import path4 from "path";
|
|
5132
5209
|
var MIGRATION_PATTERNS = [
|
|
5133
5210
|
/supabase\/migrations\//,
|
|
5134
5211
|
/prisma\/migrations\//,
|
|
@@ -5167,7 +5244,7 @@ var DEP_PATTERNS = [
|
|
|
5167
5244
|
/^pom\.xml$/
|
|
5168
5245
|
];
|
|
5169
5246
|
function normalizePath2(p2) {
|
|
5170
|
-
return p2.split(
|
|
5247
|
+
return p2.split(path4.sep).join("/");
|
|
5171
5248
|
}
|
|
5172
5249
|
function matchesAny(file, patterns) {
|
|
5173
5250
|
const normalized = normalizePath2(file);
|
|
@@ -5556,6 +5633,24 @@ function runHistory(opts = {}) {
|
|
|
5556
5633
|
// src/commands/add.ts
|
|
5557
5634
|
import { parse as parseYaml10, stringify as stringifyYaml3 } from "yaml";
|
|
5558
5635
|
var CONFIG_PATH5 = ".kaddo/config.yml";
|
|
5636
|
+
function readProjectState(dir) {
|
|
5637
|
+
const configPath = join(dir, CONFIG_PATH5);
|
|
5638
|
+
if (!exists(configPath)) return void 0;
|
|
5639
|
+
try {
|
|
5640
|
+
const config = parseYaml10(readFile(configPath));
|
|
5641
|
+
return config.project?.state;
|
|
5642
|
+
} catch {
|
|
5643
|
+
return void 0;
|
|
5644
|
+
}
|
|
5645
|
+
}
|
|
5646
|
+
function selectAgentModuleFiles(files, opts, state) {
|
|
5647
|
+
const { files: names, label } = selectAgentFiles({ all: opts.all, group: opts.group, state });
|
|
5648
|
+
const wanted = new Set(names);
|
|
5649
|
+
const selected = files.filter(
|
|
5650
|
+
(f) => f.path.endsWith("README.md") || names.some((n) => f.path.endsWith(n)) || wanted.has(f.path)
|
|
5651
|
+
);
|
|
5652
|
+
return { files: selected, label };
|
|
5653
|
+
}
|
|
5559
5654
|
function markModuleInstalled(dir, configKey, moduleName) {
|
|
5560
5655
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5561
5656
|
if (!exists(configPath)) return;
|
|
@@ -5580,7 +5675,7 @@ function isModuleInstalled(dir, configKey) {
|
|
|
5580
5675
|
return false;
|
|
5581
5676
|
}
|
|
5582
5677
|
}
|
|
5583
|
-
function runAdd(moduleName, dir = cwd()) {
|
|
5678
|
+
function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
5584
5679
|
if (!moduleName) {
|
|
5585
5680
|
console.log("");
|
|
5586
5681
|
console.log("Available modules:");
|
|
@@ -5606,9 +5701,20 @@ function runAdd(moduleName, dir = cwd()) {
|
|
|
5606
5701
|
for (const d of mod.dirs) {
|
|
5607
5702
|
ensureDir(join(dir, d));
|
|
5608
5703
|
}
|
|
5704
|
+
let filesToInstall = mod.files;
|
|
5705
|
+
if (mod.name === "agents") {
|
|
5706
|
+
try {
|
|
5707
|
+
const sel = selectAgentModuleFiles(mod.files, opts, readProjectState(dir));
|
|
5708
|
+
filesToInstall = sel.files;
|
|
5709
|
+
log2.info(`Installing agents (${sel.label}).`);
|
|
5710
|
+
} catch (err) {
|
|
5711
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
5712
|
+
process.exit(1);
|
|
5713
|
+
}
|
|
5714
|
+
}
|
|
5609
5715
|
const written = [];
|
|
5610
5716
|
const skipped = [];
|
|
5611
|
-
for (const file of
|
|
5717
|
+
for (const file of filesToInstall) {
|
|
5612
5718
|
const fullPath = join(dir, file.path);
|
|
5613
5719
|
if (exists(fullPath)) {
|
|
5614
5720
|
skipped.push(file.path);
|
|
@@ -5631,6 +5737,7 @@ function runAdd(moduleName, dir = cwd()) {
|
|
|
5631
5737
|
console.log(" 2. Open your preferred LLM chat");
|
|
5632
5738
|
console.log(" 3. Paste `.kaddo/context-pack.md`");
|
|
5633
5739
|
console.log(" 4. Use the recommended agent for your project state");
|
|
5740
|
+
log2.info("More agents: `kaddo add agents --all` or `--group <business|product|tech|delivery|utilities>`.");
|
|
5634
5741
|
outro2("Agents installed. Kaddo prepares context \u2014 your LLM does the interpretation.");
|
|
5635
5742
|
return;
|
|
5636
5743
|
}
|
|
@@ -5888,10 +5995,10 @@ ${globs.map((g) => ` - ${g}`).join("\n")}`);
|
|
|
5888
5995
|
import { parse as parseYaml11, stringify as stringifyYaml4 } from "yaml";
|
|
5889
5996
|
var DESCRIPTOR_PATH2 = "knowledge/module.yml";
|
|
5890
5997
|
function readDescriptor(dir) {
|
|
5891
|
-
const
|
|
5892
|
-
if (!exists(
|
|
5998
|
+
const path5 = join(dir, DESCRIPTOR_PATH2);
|
|
5999
|
+
if (!exists(path5)) return null;
|
|
5893
6000
|
try {
|
|
5894
|
-
return parseYaml11(readFile(
|
|
6001
|
+
return parseYaml11(readFile(path5));
|
|
5895
6002
|
} catch {
|
|
5896
6003
|
return null;
|
|
5897
6004
|
}
|
|
@@ -6920,47 +7027,138 @@ ${QUALITY}
|
|
|
6920
7027
|
- [ ] Attributes are prioritized, not all "high".
|
|
6921
7028
|
- [ ] Trade-offs are explicit.
|
|
6922
7029
|
`;
|
|
7030
|
+
var BUSINESS_CONSOLIDATED = `---
|
|
7031
|
+
type: business
|
|
7032
|
+
status: draft
|
|
7033
|
+
---
|
|
7034
|
+
|
|
7035
|
+
# Business
|
|
7036
|
+
|
|
7037
|
+
> Created by \`kaddo bootstrap\`. The minimal **why** of the project. Refine with the
|
|
7038
|
+
> business-agent. As this matures it can split into problem.md, users.md, \u2026
|
|
7039
|
+
|
|
7040
|
+
## Problem
|
|
7041
|
+
|
|
7042
|
+
TBD
|
|
7043
|
+
|
|
7044
|
+
## Users
|
|
7045
|
+
|
|
7046
|
+
TBD
|
|
7047
|
+
|
|
7048
|
+
## Value Proposition
|
|
7049
|
+
|
|
7050
|
+
TBD
|
|
7051
|
+
|
|
7052
|
+
## Business Rules
|
|
7053
|
+
|
|
7054
|
+
- TBD
|
|
7055
|
+
|
|
7056
|
+
## Constraints
|
|
7057
|
+
|
|
7058
|
+
- TBD
|
|
7059
|
+
|
|
7060
|
+
## Assumptions
|
|
7061
|
+
|
|
7062
|
+
- ...
|
|
7063
|
+
|
|
7064
|
+
## Open Questions
|
|
7065
|
+
|
|
7066
|
+
- ...
|
|
7067
|
+
|
|
7068
|
+
${QUALITY}
|
|
7069
|
+
|
|
7070
|
+
- [ ] The problem is stated without assuming the solution.
|
|
7071
|
+
- [ ] Users have goals, not just labels.
|
|
7072
|
+
`;
|
|
7073
|
+
var PRODUCT_CONSOLIDATED = `---
|
|
7074
|
+
type: product
|
|
7075
|
+
status: draft
|
|
7076
|
+
---
|
|
7077
|
+
|
|
7078
|
+
# Product
|
|
7079
|
+
|
|
7080
|
+
> Created by \`kaddo bootstrap\`. The minimal **what** of the project. Refine with the
|
|
7081
|
+
> bootstrap-agent / capability-agent. As this matures it can split into product-brief.md
|
|
7082
|
+
> and capabilities.md.
|
|
7083
|
+
|
|
7084
|
+
## Product Brief
|
|
7085
|
+
|
|
7086
|
+
TBD
|
|
7087
|
+
|
|
7088
|
+
## Capabilities
|
|
7089
|
+
|
|
7090
|
+
- TBD
|
|
7091
|
+
|
|
7092
|
+
## Scope
|
|
7093
|
+
|
|
7094
|
+
- TBD
|
|
7095
|
+
|
|
7096
|
+
## Out of Scope
|
|
7097
|
+
|
|
7098
|
+
- TBD
|
|
7099
|
+
|
|
7100
|
+
## Success Criteria
|
|
7101
|
+
|
|
7102
|
+
- TBD
|
|
7103
|
+
|
|
7104
|
+
## Assumptions
|
|
7105
|
+
|
|
7106
|
+
- ...
|
|
7107
|
+
|
|
7108
|
+
## Open Questions
|
|
7109
|
+
|
|
7110
|
+
- ...
|
|
7111
|
+
|
|
7112
|
+
${QUALITY}
|
|
7113
|
+
|
|
7114
|
+
- [ ] The product fits in one page.
|
|
7115
|
+
- [ ] Scope and out-of-scope are explicit.
|
|
7116
|
+
`;
|
|
6923
7117
|
var CODEBASE_FOUNDATION = `---
|
|
6924
|
-
type: codebase
|
|
7118
|
+
type: codebase
|
|
6925
7119
|
status: draft
|
|
6926
7120
|
---
|
|
6927
7121
|
|
|
6928
|
-
# Codebase
|
|
7122
|
+
# Codebase
|
|
6929
7123
|
|
|
6930
|
-
> Created by \`kaddo bootstrap\`. Refine with the
|
|
6931
|
-
>
|
|
7124
|
+
> Created by \`kaddo bootstrap\`. The minimal **how** of the project. Refine with the
|
|
7125
|
+
> codebase-agent. It describes the intended base \u2014 it does **not** generate code.
|
|
6932
7126
|
|
|
6933
|
-
##
|
|
7127
|
+
## Repository Structure
|
|
6934
7128
|
|
|
6935
7129
|
TBD
|
|
6936
7130
|
|
|
6937
|
-
##
|
|
7131
|
+
## Candidate Stack
|
|
7132
|
+
|
|
7133
|
+
- TBD
|
|
7134
|
+
|
|
7135
|
+
## Quality Attributes
|
|
6938
7136
|
|
|
6939
7137
|
- TBD
|
|
6940
7138
|
|
|
6941
|
-
##
|
|
7139
|
+
## Development Standards
|
|
6942
7140
|
|
|
6943
7141
|
- TBD
|
|
6944
7142
|
|
|
6945
|
-
## Git
|
|
7143
|
+
## Git Strategy
|
|
6946
7144
|
|
|
6947
|
-
See \`
|
|
7145
|
+
GitHub Flow + Conventional Commits + SemVer (default). See \`kaddo add git-strategy\`.
|
|
6948
7146
|
|
|
6949
|
-
##
|
|
7147
|
+
## Initial Modules
|
|
6950
7148
|
|
|
6951
|
-
-
|
|
7149
|
+
- TBD
|
|
6952
7150
|
|
|
6953
7151
|
## Assumptions
|
|
6954
7152
|
|
|
6955
7153
|
- ...
|
|
6956
7154
|
|
|
6957
|
-
## Open
|
|
7155
|
+
## Open Questions
|
|
6958
7156
|
|
|
6959
7157
|
- ...
|
|
6960
7158
|
|
|
6961
7159
|
${QUALITY}
|
|
6962
7160
|
|
|
6963
|
-
- [ ] Structure follows
|
|
7161
|
+
- [ ] Structure follows business and product, not a framework default.
|
|
6964
7162
|
- [ ] No production code is described here \u2014 only the foundation.
|
|
6965
7163
|
`;
|
|
6966
7164
|
var BOOTSTRAP_SUMMARY = `---
|
|
@@ -7034,6 +7232,7 @@ var KADDO_TEMPLATES = [
|
|
|
7034
7232
|
description: "What the system can do from the product point of view.",
|
|
7035
7233
|
whenToUse: "When mapping product capabilities to the system.",
|
|
7036
7234
|
relatedAgent: "capability-agent",
|
|
7235
|
+
advanced: true,
|
|
7037
7236
|
content: CAPABILITIES
|
|
7038
7237
|
},
|
|
7039
7238
|
{
|
|
@@ -7046,7 +7245,30 @@ var KADDO_TEMPLATES = [
|
|
|
7046
7245
|
relatedCommand: "kaddo init",
|
|
7047
7246
|
content: KNOWLEDGE2
|
|
7048
7247
|
},
|
|
7049
|
-
// business (bootstrap)
|
|
7248
|
+
// business / product (bootstrap — consolidated, minimal)
|
|
7249
|
+
{
|
|
7250
|
+
id: "business",
|
|
7251
|
+
name: "Business",
|
|
7252
|
+
category: "business",
|
|
7253
|
+
outputPath: "knowledge/business/business.md",
|
|
7254
|
+
description: "The minimal why: problem, users, value, rules, constraints (one file).",
|
|
7255
|
+
whenToUse: "Generated by kaddo bootstrap for new projects.",
|
|
7256
|
+
relatedCommand: "kaddo bootstrap",
|
|
7257
|
+
relatedAgent: "business-agent",
|
|
7258
|
+
content: BUSINESS_CONSOLIDATED
|
|
7259
|
+
},
|
|
7260
|
+
{
|
|
7261
|
+
id: "product",
|
|
7262
|
+
name: "Product",
|
|
7263
|
+
category: "product",
|
|
7264
|
+
outputPath: "knowledge/product/product.md",
|
|
7265
|
+
description: "The minimal what: product brief, capabilities, scope (one file).",
|
|
7266
|
+
whenToUse: "Generated by kaddo bootstrap for new projects.",
|
|
7267
|
+
relatedCommand: "kaddo bootstrap",
|
|
7268
|
+
relatedAgent: "bootstrap-agent",
|
|
7269
|
+
content: PRODUCT_CONSOLIDATED
|
|
7270
|
+
},
|
|
7271
|
+
// business (advanced — split out as knowledge matures, not generated by bootstrap)
|
|
7050
7272
|
{
|
|
7051
7273
|
id: "business-product-brief",
|
|
7052
7274
|
name: "Product Brief",
|
|
@@ -7056,6 +7278,7 @@ var KADDO_TEMPLATES = [
|
|
|
7056
7278
|
whenToUse: "At the start of a new project (kaddo bootstrap).",
|
|
7057
7279
|
relatedCommand: "kaddo bootstrap",
|
|
7058
7280
|
relatedAgent: "business-agent",
|
|
7281
|
+
advanced: true,
|
|
7059
7282
|
content: BUSINESS_PRODUCT_BRIEF
|
|
7060
7283
|
},
|
|
7061
7284
|
{
|
|
@@ -7067,6 +7290,7 @@ var KADDO_TEMPLATES = [
|
|
|
7067
7290
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7068
7291
|
relatedCommand: "kaddo bootstrap",
|
|
7069
7292
|
relatedAgent: "business-agent",
|
|
7293
|
+
advanced: true,
|
|
7070
7294
|
content: BUSINESS_PROBLEM
|
|
7071
7295
|
},
|
|
7072
7296
|
{
|
|
@@ -7078,6 +7302,7 @@ var KADDO_TEMPLATES = [
|
|
|
7078
7302
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7079
7303
|
relatedCommand: "kaddo bootstrap",
|
|
7080
7304
|
relatedAgent: "business-agent",
|
|
7305
|
+
advanced: true,
|
|
7081
7306
|
content: BUSINESS_USERS
|
|
7082
7307
|
},
|
|
7083
7308
|
{
|
|
@@ -7089,6 +7314,7 @@ var KADDO_TEMPLATES = [
|
|
|
7089
7314
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7090
7315
|
relatedCommand: "kaddo bootstrap",
|
|
7091
7316
|
relatedAgent: "business-agent",
|
|
7317
|
+
advanced: true,
|
|
7092
7318
|
content: BUSINESS_VALUE_PROPOSITION
|
|
7093
7319
|
},
|
|
7094
7320
|
{
|
|
@@ -7100,6 +7326,7 @@ var KADDO_TEMPLATES = [
|
|
|
7100
7326
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7101
7327
|
relatedCommand: "kaddo bootstrap",
|
|
7102
7328
|
relatedAgent: "business-agent",
|
|
7329
|
+
advanced: true,
|
|
7103
7330
|
content: BUSINESS_RULES
|
|
7104
7331
|
},
|
|
7105
7332
|
{
|
|
@@ -7111,6 +7338,7 @@ var KADDO_TEMPLATES = [
|
|
|
7111
7338
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7112
7339
|
relatedCommand: "kaddo bootstrap",
|
|
7113
7340
|
relatedAgent: "business-agent",
|
|
7341
|
+
advanced: true,
|
|
7114
7342
|
content: BUSINESS_CONSTRAINTS
|
|
7115
7343
|
},
|
|
7116
7344
|
{
|
|
@@ -7122,6 +7350,7 @@ var KADDO_TEMPLATES = [
|
|
|
7122
7350
|
whenToUse: "When defining a new project (kaddo bootstrap).",
|
|
7123
7351
|
relatedCommand: "kaddo bootstrap",
|
|
7124
7352
|
relatedAgent: "business-agent",
|
|
7353
|
+
advanced: true,
|
|
7125
7354
|
content: BUSINESS_GLOSSARY
|
|
7126
7355
|
},
|
|
7127
7356
|
// architecture
|
|
@@ -7163,6 +7392,7 @@ var KADDO_TEMPLATES = [
|
|
|
7163
7392
|
whenToUse: "During bootstrap, to record what matters most technically.",
|
|
7164
7393
|
relatedCommand: "kaddo bootstrap",
|
|
7165
7394
|
relatedAgent: "bootstrap-agent",
|
|
7395
|
+
advanced: true,
|
|
7166
7396
|
content: QUALITY_ATTRIBUTES
|
|
7167
7397
|
},
|
|
7168
7398
|
{
|
|
@@ -7364,10 +7594,10 @@ function slugify2(name) {
|
|
|
7364
7594
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7365
7595
|
}
|
|
7366
7596
|
function readModulesDescriptor(dir) {
|
|
7367
|
-
const
|
|
7368
|
-
if (!exists(
|
|
7597
|
+
const path5 = join(dir, DESCRIPTOR_PATH3);
|
|
7598
|
+
if (!exists(path5)) return { version: 1, modules: [] };
|
|
7369
7599
|
try {
|
|
7370
|
-
const parsed = parseYaml12(readFile(
|
|
7600
|
+
const parsed = parseYaml12(readFile(path5));
|
|
7371
7601
|
return { version: parsed.version ?? 1, modules: parsed.modules ?? [] };
|
|
7372
7602
|
} catch {
|
|
7373
7603
|
return { version: 1, modules: [] };
|
|
@@ -7574,16 +7804,11 @@ function runModulesList(dir = cwd()) {
|
|
|
7574
7804
|
// src/commands/bootstrap.ts
|
|
7575
7805
|
var CONFIG_PATH8 = ".kaddo/config.yml";
|
|
7576
7806
|
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
|
|
7807
|
+
// Minimum sufficient knowledge: one consolidated file per layer. Specialized
|
|
7808
|
+
// artifacts (problem.md, users.md, capabilities.md, …) appear later, as the project
|
|
7809
|
+
// matures, via agents and refinement — not at bootstrap.
|
|
7810
|
+
{ layer: "Business", path: "knowledge/business/business.md", templateId: "business" },
|
|
7811
|
+
{ layer: "Product", path: "knowledge/product/product.md", templateId: "product" },
|
|
7587
7812
|
{ layer: "Tech", path: "knowledge/tech/codebase.md", templateId: "codebase" }
|
|
7588
7813
|
];
|
|
7589
7814
|
var BOOTSTRAP_LAYERS = ["Business", "Product", "Tech"];
|
|
@@ -7652,7 +7877,7 @@ async function runBootstrap(dir = cwd()) {
|
|
|
7652
7877
|
|
|
7653
7878
|
// src/index.ts
|
|
7654
7879
|
var program = new Command();
|
|
7655
|
-
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.
|
|
7880
|
+
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.1.0");
|
|
7656
7881
|
program.command("init").description("Initialize Kaddo in the current project").action(async () => {
|
|
7657
7882
|
await runInit();
|
|
7658
7883
|
});
|
|
@@ -7716,8 +7941,8 @@ modulesCmd.command("map").description("Register a secondary repository as a modu
|
|
|
7716
7941
|
modulesCmd.command("list").description("List mapped modules").action(() => {
|
|
7717
7942
|
runModulesList();
|
|
7718
7943
|
});
|
|
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 ?? "");
|
|
7944
|
+
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) => {
|
|
7945
|
+
runAdd(moduleName ?? "", { all: opts.all, group: opts.group });
|
|
7721
7946
|
});
|
|
7722
7947
|
program.parseAsync(process.argv).catch((err) => {
|
|
7723
7948
|
console.error(err);
|