@kaddo/cli 3.2.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.js +103 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -434,6 +434,8 @@ create --from roadmap → owners → guard → explain`.
|
|
|
434
434
|
| v3.0 | Knowledge-centric realignment: `architecture/` → `knowledge/` with layers Business → Product → Tech → Delivery; context/explain by layer (breaking) |
|
|
435
435
|
| v3.1 | Minimum Sufficient Knowledge: bootstrap one consolidated file per layer; progressive `add agents` by group (state default, `--all`, `--group`) |
|
|
436
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) |
|
|
437
|
+
| v3.3 | Work Item delivery lifecycle: `understand` shows branch → scan → ownership → guard → knowledge → commit for active Work Items (suggestions only; Kaddo never runs git) |
|
|
438
|
+
| v3.4 | Delivery protocol in the `work-item-agent`: branch first per the Git strategy, commit only with human confirmation (CLI never touches git) |
|
|
437
439
|
|
|
438
440
|
**Optional modules (installed with `kaddo add`):**
|
|
439
441
|
|
package/dist/index.js
CHANGED
|
@@ -1950,6 +1950,24 @@ A refined Work Item intended to be saved as \`knowledge/delivery/work-items/*.md
|
|
|
1950
1950
|
|
|
1951
1951
|
Save the output as a file under \`knowledge/delivery/work-items/\`.
|
|
1952
1952
|
|
|
1953
|
+
## Delivery workflow
|
|
1954
|
+
|
|
1955
|
+
When this Work Item is **implemented** (by you or the coding agent), follow the project's
|
|
1956
|
+
delivery protocol. **Never run git mutating commands without the human's confirmation.**
|
|
1957
|
+
|
|
1958
|
+
1. **Branch first.** Before changing any code, create a branch following the project's Git
|
|
1959
|
+
strategy (\`.kaddo/git.yml\` \u2192 \`branchNaming.pattern\`, default
|
|
1960
|
+
\`feature/<work-item-id>-<slug>\`; also \`bugfix/\`, \`hotfix/\`, \`spike/\`). This keeps work
|
|
1961
|
+
off the default branch so nothing lands on \`main\` by accident.
|
|
1962
|
+
2. Implement the change.
|
|
1963
|
+
3. Run \`kaddo scan\` after adding modules, migrations, contracts or significant structure.
|
|
1964
|
+
4. Run \`kaddo owners suggest\` and confirm the \`code:\` globs.
|
|
1965
|
+
5. Run \`kaddo guard\` before committing to detect possible knowledge drift.
|
|
1966
|
+
6. Update the affected knowledge (ADR / capabilities.md / current-state.md).
|
|
1967
|
+
7. **Commit only with explicit human confirmation.** Never commit, push or merge on your
|
|
1968
|
+
own \u2014 suggest a Conventional Commit message and wait for the human. The Kaddo CLI itself
|
|
1969
|
+
never touches git.
|
|
1970
|
+
|
|
1953
1971
|
## Quality Checklist
|
|
1954
1972
|
|
|
1955
1973
|
- The problem is one clear sentence.
|
|
@@ -1957,6 +1975,7 @@ Save the output as a file under \`knowledge/delivery/work-items/\`.
|
|
|
1957
1975
|
- Knowledge Level is justified.
|
|
1958
1976
|
- Acceptance criteria are testable.
|
|
1959
1977
|
- Open questions are explicit.
|
|
1978
|
+
- Delivery: branch first, commit only with human confirmation.
|
|
1960
1979
|
`;
|
|
1961
1980
|
var GIT_STRATEGY_AGENT = `# Git Strategy Agent
|
|
1962
1981
|
|
|
@@ -5185,6 +5204,68 @@ function renderUnderstandTerminal(plan) {
|
|
|
5185
5204
|
return lines.join("\n");
|
|
5186
5205
|
}
|
|
5187
5206
|
|
|
5207
|
+
// src/core/delivery.ts
|
|
5208
|
+
import { parse as parseYaml9 } from "yaml";
|
|
5209
|
+
function slugify2(s) {
|
|
5210
|
+
return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5211
|
+
}
|
|
5212
|
+
function isWorkItem(a) {
|
|
5213
|
+
return a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type);
|
|
5214
|
+
}
|
|
5215
|
+
function toActive(a) {
|
|
5216
|
+
const id = a.id || a.title || "WI";
|
|
5217
|
+
return { id, title: a.title || id, type: a.type, slug: slugify2(a.title || id) };
|
|
5218
|
+
}
|
|
5219
|
+
function activeWorkItems(dir) {
|
|
5220
|
+
const archDir = join(dir, "knowledge");
|
|
5221
|
+
if (!exists(archDir)) return [];
|
|
5222
|
+
return readArtifacts(archDir).filter((a) => isWorkItem(a) && a.status === "in-progress").map(toActive);
|
|
5223
|
+
}
|
|
5224
|
+
function branchPrefix(type) {
|
|
5225
|
+
switch (type) {
|
|
5226
|
+
case "bugfix":
|
|
5227
|
+
return "bugfix";
|
|
5228
|
+
case "hotfix":
|
|
5229
|
+
return "hotfix";
|
|
5230
|
+
case "spike":
|
|
5231
|
+
return "spike";
|
|
5232
|
+
default:
|
|
5233
|
+
return "feature";
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
5236
|
+
function commitPrefix(type) {
|
|
5237
|
+
switch (type) {
|
|
5238
|
+
case "bugfix":
|
|
5239
|
+
case "hotfix":
|
|
5240
|
+
return "fix";
|
|
5241
|
+
case "spike":
|
|
5242
|
+
return "chore";
|
|
5243
|
+
default:
|
|
5244
|
+
return "feat";
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
function suggestedBranch(wi) {
|
|
5248
|
+
return `${branchPrefix(wi.type)}/${wi.id}-${wi.slug}`;
|
|
5249
|
+
}
|
|
5250
|
+
function suggestedCommit(wi) {
|
|
5251
|
+
return `${commitPrefix(wi.type)}: ${wi.title.toLowerCase()}`;
|
|
5252
|
+
}
|
|
5253
|
+
function renderDeliveryLifecycle(wi) {
|
|
5254
|
+
return [
|
|
5255
|
+
`Active work item: ${wi.id} \u2014 ${wi.title}`,
|
|
5256
|
+
"",
|
|
5257
|
+
"Delivery lifecycle (the building agent follows this; Kaddo CLI never touches git):",
|
|
5258
|
+
` 1. Create a branch ${suggestedBranch(wi)} (per your Git strategy)`,
|
|
5259
|
+
" 2. Implement the work item",
|
|
5260
|
+
" 3. Run `kaddo scan` (after new modules/migrations/contracts)",
|
|
5261
|
+
" 4. Run `kaddo owners suggest` \u2192 confirm code: globs",
|
|
5262
|
+
" 5. Run `kaddo guard` before committing (detect knowledge drift)",
|
|
5263
|
+
" 6. Update knowledge ADR / capabilities.md / current-state.md as needed",
|
|
5264
|
+
" 7. Review (human)",
|
|
5265
|
+
` 8. Commit only with human confirmation e.g. ${suggestedCommit(wi)}`
|
|
5266
|
+
];
|
|
5267
|
+
}
|
|
5268
|
+
|
|
5188
5269
|
// src/commands/understand.ts
|
|
5189
5270
|
function runUnderstand() {
|
|
5190
5271
|
const dir = cwd();
|
|
@@ -5247,6 +5328,15 @@ function runUnderstand() {
|
|
|
5247
5328
|
if (groupAgents.length > 0) {
|
|
5248
5329
|
console.log(`Agents for this phase: ${groupAgents.join(", ")}`);
|
|
5249
5330
|
}
|
|
5331
|
+
const active = activeWorkItems(dir);
|
|
5332
|
+
if (active.length > 0) {
|
|
5333
|
+
console.log("");
|
|
5334
|
+
for (const line of renderDeliveryLifecycle(active[0])) console.log(line);
|
|
5335
|
+
if (active.length > 1) {
|
|
5336
|
+
console.log("");
|
|
5337
|
+
console.log(`Other active work items: ${active.slice(1).map((w) => w.id).join(", ")}`);
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5250
5340
|
writeFile(join(dir, ".kaddo", "understand.md"), renderUnderstand(plan));
|
|
5251
5341
|
log2.success("Wrote .kaddo/understand.md");
|
|
5252
5342
|
outro2("Handoff ready. CLI prepares context \u2014 your LLM creates the understanding.");
|
|
@@ -5470,14 +5560,14 @@ async function runClassify(opts = {}) {
|
|
|
5470
5560
|
}
|
|
5471
5561
|
|
|
5472
5562
|
// src/commands/status.ts
|
|
5473
|
-
import { parse as
|
|
5563
|
+
import { parse as parseYaml10 } from "yaml";
|
|
5474
5564
|
var ARCH_DIR7 = "knowledge";
|
|
5475
5565
|
var CONFIG_PATH4 = ".kaddo/config.yml";
|
|
5476
5566
|
function loadConfig3(dir) {
|
|
5477
5567
|
const p2 = join(dir, CONFIG_PATH4);
|
|
5478
5568
|
if (!exists(p2)) return {};
|
|
5479
5569
|
try {
|
|
5480
|
-
return
|
|
5570
|
+
return parseYaml10(readFile(p2));
|
|
5481
5571
|
} catch {
|
|
5482
5572
|
return {};
|
|
5483
5573
|
}
|
|
@@ -5679,13 +5769,13 @@ function runHistory(opts = {}) {
|
|
|
5679
5769
|
}
|
|
5680
5770
|
|
|
5681
5771
|
// src/commands/add.ts
|
|
5682
|
-
import { parse as
|
|
5772
|
+
import { parse as parseYaml11, stringify as stringifyYaml3 } from "yaml";
|
|
5683
5773
|
var CONFIG_PATH5 = ".kaddo/config.yml";
|
|
5684
5774
|
function readProjectState(dir) {
|
|
5685
5775
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5686
5776
|
if (!exists(configPath)) return void 0;
|
|
5687
5777
|
try {
|
|
5688
|
-
const config =
|
|
5778
|
+
const config = parseYaml11(readFile(configPath));
|
|
5689
5779
|
return config.project?.state;
|
|
5690
5780
|
} catch {
|
|
5691
5781
|
return void 0;
|
|
@@ -5703,7 +5793,7 @@ function markModuleInstalled(dir, configKey, moduleName) {
|
|
|
5703
5793
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5704
5794
|
if (!exists(configPath)) return;
|
|
5705
5795
|
try {
|
|
5706
|
-
const config =
|
|
5796
|
+
const config = parseYaml11(readFile(configPath));
|
|
5707
5797
|
config[configKey] = { installed: true, installed_at: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] };
|
|
5708
5798
|
const modules = config.modules ?? [];
|
|
5709
5799
|
if (!modules.includes(moduleName)) modules.push(moduleName);
|
|
@@ -5716,7 +5806,7 @@ function isModuleInstalled(dir, configKey) {
|
|
|
5716
5806
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5717
5807
|
if (!exists(configPath)) return false;
|
|
5718
5808
|
try {
|
|
5719
|
-
const config =
|
|
5809
|
+
const config = parseYaml11(readFile(configPath));
|
|
5720
5810
|
const moduleConfig = config[configKey];
|
|
5721
5811
|
return moduleConfig?.installed === true;
|
|
5722
5812
|
} catch {
|
|
@@ -6040,13 +6130,13 @@ ${globs.map((g) => ` - ${g}`).join("\n")}`);
|
|
|
6040
6130
|
}
|
|
6041
6131
|
|
|
6042
6132
|
// src/commands/module-descriptor.ts
|
|
6043
|
-
import { parse as
|
|
6133
|
+
import { parse as parseYaml12, stringify as stringifyYaml4 } from "yaml";
|
|
6044
6134
|
var DESCRIPTOR_PATH2 = "knowledge/module.yml";
|
|
6045
6135
|
function readDescriptor(dir) {
|
|
6046
6136
|
const path5 = join(dir, DESCRIPTOR_PATH2);
|
|
6047
6137
|
if (!exists(path5)) return null;
|
|
6048
6138
|
try {
|
|
6049
|
-
return
|
|
6139
|
+
return parseYaml12(readFile(path5));
|
|
6050
6140
|
} catch {
|
|
6051
6141
|
return null;
|
|
6052
6142
|
}
|
|
@@ -6147,7 +6237,7 @@ function printDescriptor(d) {
|
|
|
6147
6237
|
}
|
|
6148
6238
|
|
|
6149
6239
|
// src/commands/modules-map.ts
|
|
6150
|
-
import { parse as
|
|
6240
|
+
import { parse as parseYaml13, stringify as stringifyYaml5 } from "yaml";
|
|
6151
6241
|
|
|
6152
6242
|
// src/templates/registry.ts
|
|
6153
6243
|
var QUALITY = "## Quality checklist";
|
|
@@ -7638,14 +7728,14 @@ var MODULE_TYPES = [
|
|
|
7638
7728
|
"data",
|
|
7639
7729
|
"unknown"
|
|
7640
7730
|
];
|
|
7641
|
-
function
|
|
7731
|
+
function slugify3(name) {
|
|
7642
7732
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7643
7733
|
}
|
|
7644
7734
|
function readModulesDescriptor(dir) {
|
|
7645
7735
|
const path5 = join(dir, DESCRIPTOR_PATH3);
|
|
7646
7736
|
if (!exists(path5)) return { version: 1, modules: [] };
|
|
7647
7737
|
try {
|
|
7648
|
-
const parsed =
|
|
7738
|
+
const parsed = parseYaml13(readFile(path5));
|
|
7649
7739
|
return { version: parsed.version ?? 1, modules: parsed.modules ?? [] };
|
|
7650
7740
|
} catch {
|
|
7651
7741
|
return { version: 1, modules: [] };
|
|
@@ -7658,7 +7748,7 @@ function moduleDir(id) {
|
|
|
7658
7748
|
return `knowledge/tech/modules/${id}`;
|
|
7659
7749
|
}
|
|
7660
7750
|
function buildModule(input) {
|
|
7661
|
-
const id =
|
|
7751
|
+
const id = slugify3(input.name);
|
|
7662
7752
|
const base = moduleDir(id);
|
|
7663
7753
|
return {
|
|
7664
7754
|
id,
|
|
@@ -7925,7 +8015,7 @@ async function runBootstrap(dir = cwd()) {
|
|
|
7925
8015
|
|
|
7926
8016
|
// src/index.ts
|
|
7927
8017
|
var program = new Command();
|
|
7928
|
-
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.
|
|
8018
|
+
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.4.0");
|
|
7929
8019
|
program.command("init").description("Initialize Kaddo in the current project").action(async () => {
|
|
7930
8020
|
await runInit();
|
|
7931
8021
|
});
|