@kaddo/cli 3.3.0 → 3.5.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 +225 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -435,6 +435,8 @@ create --from roadmap → owners → guard → explain`.
|
|
|
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
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) |
|
|
439
|
+
| v3.5 | Knowledge discovery by front-matter type with per-layer maturity (explain/understand/context); context pack carries Operating Rules so agents never commit without confirmation |
|
|
438
440
|
|
|
439
441
|
**Optional modules (installed with `kaddo add`):**
|
|
440
442
|
|
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
|
|
|
@@ -2573,6 +2592,14 @@ var agentReadme = {
|
|
|
2573
2592
|
"",
|
|
2574
2593
|
"**Kaddo does not execute these agents.** The CLI prepares context; the LLM interprets.",
|
|
2575
2594
|
"",
|
|
2595
|
+
"## Operating rules (apply to every agent)",
|
|
2596
|
+
"",
|
|
2597
|
+
"- **Never run `git commit`, `git push` or `git merge` without explicit human confirmation.**",
|
|
2598
|
+
"- Never push or merge automatically. Suggest a Conventional Commit message and wait.",
|
|
2599
|
+
"- When implementing a Work Item, create a branch first (per the Git strategy in",
|
|
2600
|
+
" `.kaddo/git.yml`); never work directly on `main`.",
|
|
2601
|
+
"- The Kaddo CLI never calls an LLM and never runs git \u2014 every git action is the human\u2019s.",
|
|
2602
|
+
"",
|
|
2576
2603
|
"## How to use",
|
|
2577
2604
|
"",
|
|
2578
2605
|
"1. Run `kaddo scan` then `kaddo context` to generate `.kaddo/context-pack.md`.",
|
|
@@ -4244,59 +4271,158 @@ function runIgnoreRemove(artifactId) {
|
|
|
4244
4271
|
import matter2 from "gray-matter";
|
|
4245
4272
|
import { parse as parseYaml8 } from "yaml";
|
|
4246
4273
|
|
|
4247
|
-
// src/core/
|
|
4274
|
+
// src/core/knowledge-discovery.ts
|
|
4248
4275
|
var KNOWLEDGE = "knowledge";
|
|
4249
|
-
var
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4276
|
+
var CONSOLIDATED_TYPE = {
|
|
4277
|
+
Business: "business",
|
|
4278
|
+
Product: "product",
|
|
4279
|
+
Tech: "codebase"
|
|
4280
|
+
};
|
|
4281
|
+
var STRUCTURED_TYPES = {
|
|
4282
|
+
Business: /* @__PURE__ */ new Set(["problem", "users", "value-proposition", "business-rules", "constraints", "glossary"]),
|
|
4283
|
+
Product: /* @__PURE__ */ new Set(["product-brief", "capabilities"]),
|
|
4284
|
+
Tech: /* @__PURE__ */ new Set([
|
|
4285
|
+
"current-state",
|
|
4286
|
+
"architecture-notes",
|
|
4287
|
+
"decision-candidates",
|
|
4288
|
+
"quality-attributes",
|
|
4289
|
+
"stack",
|
|
4290
|
+
"standards",
|
|
4291
|
+
"security",
|
|
4292
|
+
"git-strategy",
|
|
4293
|
+
"module-design",
|
|
4294
|
+
"adr",
|
|
4295
|
+
"decision"
|
|
4296
|
+
]),
|
|
4297
|
+
Delivery: /* @__PURE__ */ new Set([])
|
|
4298
|
+
};
|
|
4299
|
+
var WORK_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
4300
|
+
"work-item",
|
|
4301
|
+
"feature",
|
|
4302
|
+
"bugfix",
|
|
4303
|
+
"hotfix",
|
|
4304
|
+
"spike"
|
|
4305
|
+
]);
|
|
4306
|
+
function layerForType(type) {
|
|
4307
|
+
if (!type) return null;
|
|
4308
|
+
if (type === CONSOLIDATED_TYPE.Business || STRUCTURED_TYPES.Business.has(type)) return "Business";
|
|
4309
|
+
if (type === CONSOLIDATED_TYPE.Product || STRUCTURED_TYPES.Product.has(type)) return "Product";
|
|
4310
|
+
if (type === CONSOLIDATED_TYPE.Tech || STRUCTURED_TYPES.Tech.has(type) || type === "knowledge")
|
|
4311
|
+
return "Tech";
|
|
4312
|
+
if (type === "roadmap" || WORK_ITEM_TYPES.has(type)) return "Delivery";
|
|
4313
|
+
return null;
|
|
4314
|
+
}
|
|
4315
|
+
function layerFromPath(filePath) {
|
|
4316
|
+
const p2 = filePath.replace(/\\/g, "/");
|
|
4317
|
+
if (p2.includes(`/${KNOWLEDGE}/business/`)) return "Business";
|
|
4318
|
+
if (p2.includes(`/${KNOWLEDGE}/product/`)) return "Product";
|
|
4319
|
+
if (p2.includes(`/${KNOWLEDGE}/tech/`)) return "Tech";
|
|
4320
|
+
if (p2.includes(`/${KNOWLEDGE}/delivery/`)) return "Delivery";
|
|
4321
|
+
return null;
|
|
4322
|
+
}
|
|
4323
|
+
function basename(p2) {
|
|
4324
|
+
return p2.replace(/\\/g, "/").split("/").pop() ?? p2;
|
|
4325
|
+
}
|
|
4326
|
+
function discoverLayers(dir) {
|
|
4327
|
+
const acc = {
|
|
4328
|
+
Business: blank(),
|
|
4329
|
+
Product: blank(),
|
|
4330
|
+
Tech: blank(),
|
|
4331
|
+
Delivery: blank()
|
|
4332
|
+
};
|
|
4333
|
+
const archDir = join(dir, KNOWLEDGE);
|
|
4334
|
+
const artifacts = exists(archDir) ? readArtifacts(archDir) : [];
|
|
4335
|
+
for (const a of artifacts) {
|
|
4336
|
+
const type = a.type;
|
|
4337
|
+
const layer = layerForType(type) ?? layerFromPath(a.filePath);
|
|
4338
|
+
if (!layer) continue;
|
|
4339
|
+
const slot = acc[layer];
|
|
4340
|
+
slot.detected.add(basename(a.filePath));
|
|
4341
|
+
if (layer === "Delivery") {
|
|
4342
|
+
if (type === "roadmap" || basename(a.filePath) === "roadmap.md") slot.hasRoadmap = true;
|
|
4343
|
+
if (WORK_ITEM_TYPES.has(type) || a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) {
|
|
4344
|
+
if (a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/")) slot.hasWorkItem = true;
|
|
4345
|
+
}
|
|
4346
|
+
continue;
|
|
4347
|
+
}
|
|
4348
|
+
if (type === CONSOLIDATED_TYPE[layer]) slot.consolidated = true;
|
|
4349
|
+
else if (STRUCTURED_TYPES[layer].has(type)) slot.structured = true;
|
|
4350
|
+
else if (!type) {
|
|
4351
|
+
slot.consolidated = true;
|
|
4352
|
+
}
|
|
4353
|
+
if (type === "adr" || type === "decision") slot.hasDecision = true;
|
|
4281
4354
|
}
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
return LAYER_SPEC.map(({ layer, items }) => ({
|
|
4355
|
+
if (existsDirWithMd(join(dir, KNOWLEDGE, "tech", "decisions"))) acc.Tech.structured = true;
|
|
4356
|
+
return ["Business", "Product", "Tech", "Delivery"].map((layer) => ({
|
|
4285
4357
|
layer,
|
|
4286
|
-
|
|
4358
|
+
status: statusFor(layer, acc[layer]),
|
|
4359
|
+
detected: [...acc[layer].detected].sort()
|
|
4287
4360
|
}));
|
|
4288
4361
|
}
|
|
4362
|
+
function blank() {
|
|
4363
|
+
return {
|
|
4364
|
+
consolidated: false,
|
|
4365
|
+
structured: false,
|
|
4366
|
+
hasRoadmap: false,
|
|
4367
|
+
hasWorkItem: false,
|
|
4368
|
+
hasDecision: false,
|
|
4369
|
+
detected: /* @__PURE__ */ new Set()
|
|
4370
|
+
};
|
|
4371
|
+
}
|
|
4372
|
+
function existsDirWithMd(d) {
|
|
4373
|
+
if (!exists(d)) return false;
|
|
4374
|
+
try {
|
|
4375
|
+
return readDir(d).some((e) => e.endsWith(".md") && isFile(join(d, e)));
|
|
4376
|
+
} catch {
|
|
4377
|
+
return false;
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
function statusFor(layer, a) {
|
|
4381
|
+
if (layer === "Delivery") {
|
|
4382
|
+
if (a.hasWorkItem) return "Traceable";
|
|
4383
|
+
if (a.hasRoadmap) return "Partial";
|
|
4384
|
+
return "Missing";
|
|
4385
|
+
}
|
|
4386
|
+
if (a.structured) return "Structured";
|
|
4387
|
+
if (a.consolidated) return "Consolidated";
|
|
4388
|
+
return "Missing";
|
|
4389
|
+
}
|
|
4390
|
+
function roadmapHasUnmaterializedCandidates(dir) {
|
|
4391
|
+
const roadmap = join(dir, KNOWLEDGE, "delivery", "roadmap.md");
|
|
4392
|
+
if (!exists(roadmap)) return false;
|
|
4393
|
+
let hasCandidates = false;
|
|
4394
|
+
try {
|
|
4395
|
+
hasCandidates = /WI-[A-Z0-9-]*\d/i.test(readFile(roadmap));
|
|
4396
|
+
} catch {
|
|
4397
|
+
return false;
|
|
4398
|
+
}
|
|
4399
|
+
if (!hasCandidates) return false;
|
|
4400
|
+
const wiDir = join(dir, KNOWLEDGE, "delivery", "work-items");
|
|
4401
|
+
return !existsDirWithMd(wiDir);
|
|
4402
|
+
}
|
|
4403
|
+
|
|
4404
|
+
// src/core/layers.ts
|
|
4405
|
+
function knowledgeLayers(dir) {
|
|
4406
|
+
return discoverLayers(dir);
|
|
4407
|
+
}
|
|
4408
|
+
var COMPLETE = {
|
|
4409
|
+
Business: (s) => s !== "Missing",
|
|
4410
|
+
Product: (s) => s !== "Missing",
|
|
4411
|
+
Tech: (s) => s !== "Missing",
|
|
4412
|
+
Delivery: (s) => s === "Traceable"
|
|
4413
|
+
};
|
|
4289
4414
|
function currentPhase(layers) {
|
|
4290
|
-
for (const
|
|
4291
|
-
if (
|
|
4415
|
+
for (const l of layers) {
|
|
4416
|
+
if (!COMPLETE[l.layer](l.status)) return l.layer;
|
|
4292
4417
|
}
|
|
4293
4418
|
return "Delivery";
|
|
4294
4419
|
}
|
|
4295
4420
|
function renderLayersMarkdown(layers) {
|
|
4296
4421
|
const lines = [];
|
|
4297
|
-
for (const { layer,
|
|
4298
|
-
lines.push(`### ${layer}`);
|
|
4299
|
-
for (const
|
|
4422
|
+
for (const { layer, status, detected } of layers) {
|
|
4423
|
+
lines.push(`### ${layer} \u2014 ${status}`);
|
|
4424
|
+
if (detected.length > 0) for (const d of detected) lines.push(`- \u2713 ${d}`);
|
|
4425
|
+
else lines.push("- \u2717 none");
|
|
4300
4426
|
lines.push("");
|
|
4301
4427
|
}
|
|
4302
4428
|
return lines.join("\n").trimEnd();
|
|
@@ -4367,14 +4493,16 @@ function buildProjectExplanation(dir) {
|
|
|
4367
4493
|
contractFiles: scan2.contractFiles,
|
|
4368
4494
|
infrastructureFiles: scan2.infrastructureFiles
|
|
4369
4495
|
} : null;
|
|
4496
|
+
const layers = knowledgeLayers(dir);
|
|
4497
|
+
const layerStatus = (name) => layers.find((l) => l.layer === name)?.status ?? "Missing";
|
|
4370
4498
|
const knowledge = {
|
|
4371
4499
|
hasScan: scan2 !== null,
|
|
4372
4500
|
hasInventory: exists(join(dir, ARCH_DIR3, "inventory.md")),
|
|
4373
4501
|
hasContextPack: exists(join(dir, ".kaddo", "context-pack.md")),
|
|
4374
4502
|
hasUnderstand: exists(join(dir, ".kaddo", "understand.md")),
|
|
4375
|
-
hasCapabilities:
|
|
4376
|
-
hasArchitecture:
|
|
4377
|
-
hasRoadmap:
|
|
4503
|
+
hasCapabilities: layerStatus("Product") !== "Missing",
|
|
4504
|
+
hasArchitecture: layerStatus("Tech") !== "Missing",
|
|
4505
|
+
hasRoadmap: layerStatus("Delivery") !== "Missing",
|
|
4378
4506
|
hasAgents: hasAgents(dir)
|
|
4379
4507
|
};
|
|
4380
4508
|
const archDir = join(dir, ARCH_DIR3);
|
|
@@ -4410,10 +4538,8 @@ function buildProjectExplanation(dir) {
|
|
|
4410
4538
|
if (!knowledge.hasScan) missingKnowledge.push("Scan baseline (.kaddo/scan.json)");
|
|
4411
4539
|
if (!knowledge.hasContextPack) missingKnowledge.push("Context pack (.kaddo/context-pack.md)");
|
|
4412
4540
|
if (!knowledge.hasInventory) missingKnowledge.push("Inventory (knowledge/inventory.md)");
|
|
4413
|
-
if (!knowledge.hasCapabilities)
|
|
4414
|
-
|
|
4415
|
-
if (!knowledge.hasArchitecture)
|
|
4416
|
-
missingKnowledge.push("Architecture baseline (knowledge/tech/current-state.md)");
|
|
4541
|
+
if (!knowledge.hasCapabilities) missingKnowledge.push("Product knowledge (knowledge/product/)");
|
|
4542
|
+
if (!knowledge.hasArchitecture) missingKnowledge.push("Tech knowledge (knowledge/tech/)");
|
|
4417
4543
|
if (!knowledge.hasRoadmap) missingKnowledge.push("Roadmap (knowledge/delivery/roadmap.md)");
|
|
4418
4544
|
if (!knowledge.hasAgents) missingKnowledge.push("Agents (knowledge/agents/)");
|
|
4419
4545
|
if (items.length === 0) missingKnowledge.push("Work items (knowledge/delivery/work-items/)");
|
|
@@ -4449,7 +4575,7 @@ function buildProjectExplanation(dir) {
|
|
|
4449
4575
|
workItems,
|
|
4450
4576
|
ownership,
|
|
4451
4577
|
domains,
|
|
4452
|
-
layers
|
|
4578
|
+
layers,
|
|
4453
4579
|
mappedModules,
|
|
4454
4580
|
missingKnowledge,
|
|
4455
4581
|
suggestedNextSteps
|
|
@@ -4484,14 +4610,14 @@ function renderExplanationHuman(exp) {
|
|
|
4484
4610
|
lines.push(`- Infrastructure: ${exp.stack.infrastructureFiles.join(", ")}`);
|
|
4485
4611
|
lines.push("");
|
|
4486
4612
|
}
|
|
4613
|
+
const ls = (name) => exp.layers.find((l) => l.layer === name)?.status ?? "Missing";
|
|
4487
4614
|
lines.push("## Knowledge Status");
|
|
4488
4615
|
lines.push(`- Inventory: ${exp.knowledge.hasInventory ? "available" : "missing"}`);
|
|
4489
4616
|
lines.push(`- Context pack: ${exp.knowledge.hasContextPack ? "available" : "missing"}`);
|
|
4490
|
-
lines.push(`-
|
|
4491
|
-
lines.push(
|
|
4492
|
-
|
|
4493
|
-
);
|
|
4494
|
-
lines.push(`- Roadmap: ${exp.knowledge.hasRoadmap ? "available" : "missing"}`);
|
|
4617
|
+
lines.push(`- Business: ${ls("Business")}`);
|
|
4618
|
+
lines.push(`- Product: ${ls("Product")}`);
|
|
4619
|
+
lines.push(`- Tech: ${ls("Tech")}`);
|
|
4620
|
+
lines.push(`- Delivery: ${ls("Delivery")}`);
|
|
4495
4621
|
lines.push(`- Agents: ${exp.knowledge.hasAgents ? "available" : "missing"}`);
|
|
4496
4622
|
lines.push(`- Work items: ${exp.workItems.total}`);
|
|
4497
4623
|
lines.push(
|
|
@@ -4799,6 +4925,13 @@ var LLM_INSTRUCTIONS = [
|
|
|
4799
4925
|
"First extract: system capabilities, architecture notes, risks, open questions and roadmap candidates.",
|
|
4800
4926
|
"This pack is deterministic CLI output \u2014 it does not interpret the system. That is your job."
|
|
4801
4927
|
];
|
|
4928
|
+
var OPERATING_RULES = [
|
|
4929
|
+
"**Never run `git commit`, `git push` or `git merge` without explicit human confirmation.**",
|
|
4930
|
+
"Never push or merge automatically \u2014 ever. Suggest a Conventional Commit message and wait.",
|
|
4931
|
+
"When implementing a Work Item, create a branch FIRST (per the project Git strategy, `.kaddo/git.yml`, default `feature/<id>-<slug>`). Never work directly on `main`.",
|
|
4932
|
+
"After significant changes run `kaddo scan`, `kaddo owners suggest` and `kaddo guard`, and update the affected knowledge (ADR / capabilities / current-state).",
|
|
4933
|
+
"Kaddo itself never calls an LLM and never runs git \u2014 every git action is the human\u2019s."
|
|
4934
|
+
];
|
|
4802
4935
|
function toContextWorkItem(a) {
|
|
4803
4936
|
return {
|
|
4804
4937
|
id: a.id,
|
|
@@ -4874,7 +5007,8 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
4874
5007
|
handoff: {
|
|
4875
5008
|
recommendedAgents: recommendedAgentsForState(state),
|
|
4876
5009
|
nextSteps: nextStepsForState2(state),
|
|
4877
|
-
instructions: LLM_INSTRUCTIONS
|
|
5010
|
+
instructions: LLM_INSTRUCTIONS,
|
|
5011
|
+
operatingRules: OPERATING_RULES
|
|
4878
5012
|
}
|
|
4879
5013
|
};
|
|
4880
5014
|
}
|
|
@@ -4893,6 +5027,8 @@ function renderContextPack(pack) {
|
|
|
4893
5027
|
parts.push(
|
|
4894
5028
|
"> Generated by `kaddo context`. Deterministic CLI output \u2014 not an interpretation of the system.\n"
|
|
4895
5029
|
);
|
|
5030
|
+
parts.push("## Operating Rules (read first)\n");
|
|
5031
|
+
parts.push(handoff.operatingRules.map((r) => `- ${r}`).join("\n") + "\n");
|
|
4896
5032
|
parts.push("## Project Metadata\n");
|
|
4897
5033
|
parts.push(
|
|
4898
5034
|
[
|
|
@@ -4906,6 +5042,9 @@ function renderContextPack(pack) {
|
|
|
4906
5042
|
parts.push(
|
|
4907
5043
|
"Project knowledge is organized in four layers: **Business \u2192 Product \u2192 Tech \u2192 Delivery**.\n"
|
|
4908
5044
|
);
|
|
5045
|
+
const maturity = pack.layers.map((l) => `${l.layer}: ${l.status}`).join(" \xB7 ");
|
|
5046
|
+
parts.push(`Knowledge maturity \u2014 ${maturity}
|
|
5047
|
+
`);
|
|
4909
5048
|
parts.push(renderLayersMarkdown(pack.layers) + "\n");
|
|
4910
5049
|
parts.push("## Technical Inventory\n");
|
|
4911
5050
|
if (scan2.available) {
|
|
@@ -5186,19 +5325,21 @@ function renderUnderstandTerminal(plan) {
|
|
|
5186
5325
|
}
|
|
5187
5326
|
|
|
5188
5327
|
// src/core/delivery.ts
|
|
5328
|
+
import { parse as parseYaml9 } from "yaml";
|
|
5189
5329
|
function slugify2(s) {
|
|
5190
5330
|
return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5191
5331
|
}
|
|
5192
5332
|
function isWorkItem(a) {
|
|
5193
5333
|
return a.filePath.replace(/\\/g, "/").includes("/delivery/work-items/") && Boolean(a.type);
|
|
5194
5334
|
}
|
|
5335
|
+
function toActive(a) {
|
|
5336
|
+
const id = a.id || a.title || "WI";
|
|
5337
|
+
return { id, title: a.title || id, type: a.type, slug: slugify2(a.title || id) };
|
|
5338
|
+
}
|
|
5195
5339
|
function activeWorkItems(dir) {
|
|
5196
5340
|
const archDir = join(dir, "knowledge");
|
|
5197
5341
|
if (!exists(archDir)) return [];
|
|
5198
|
-
return readArtifacts(archDir).filter((a) => isWorkItem(a) && a.status === "in-progress").map(
|
|
5199
|
-
const id = a.id || a.title || "WI";
|
|
5200
|
-
return { id, title: a.title || id, type: a.type, slug: slugify2(a.title || id) };
|
|
5201
|
-
});
|
|
5342
|
+
return readArtifacts(archDir).filter((a) => isWorkItem(a) && a.status === "in-progress").map(toActive);
|
|
5202
5343
|
}
|
|
5203
5344
|
function branchPrefix(type) {
|
|
5204
5345
|
switch (type) {
|
|
@@ -5233,15 +5374,15 @@ function renderDeliveryLifecycle(wi) {
|
|
|
5233
5374
|
return [
|
|
5234
5375
|
`Active work item: ${wi.id} \u2014 ${wi.title}`,
|
|
5235
5376
|
"",
|
|
5236
|
-
"Delivery lifecycle (Kaddo never
|
|
5237
|
-
` 1. Create a branch
|
|
5377
|
+
"Delivery lifecycle (the building agent follows this; Kaddo CLI never touches git):",
|
|
5378
|
+
` 1. Create a branch ${suggestedBranch(wi)} (per your Git strategy)`,
|
|
5238
5379
|
" 2. Implement the work item",
|
|
5239
5380
|
" 3. Run `kaddo scan` (after new modules/migrations/contracts)",
|
|
5240
5381
|
" 4. Run `kaddo owners suggest` \u2192 confirm code: globs",
|
|
5241
5382
|
" 5. Run `kaddo guard` before committing (detect knowledge drift)",
|
|
5242
5383
|
" 6. Update knowledge ADR / capabilities.md / current-state.md as needed",
|
|
5243
5384
|
" 7. Review (human)",
|
|
5244
|
-
` 8. Commit
|
|
5385
|
+
` 8. Commit only with human confirmation e.g. ${suggestedCommit(wi)}`
|
|
5245
5386
|
];
|
|
5246
5387
|
}
|
|
5247
5388
|
|
|
@@ -5297,6 +5438,12 @@ function runUnderstand() {
|
|
|
5297
5438
|
],
|
|
5298
5439
|
utilities: ["Use legacy-agent to surface risks and unknowns"]
|
|
5299
5440
|
};
|
|
5441
|
+
if (roadmapHasUnmaterializedCandidates(dir)) {
|
|
5442
|
+
console.log("");
|
|
5443
|
+
console.log("The roadmap has Work Item candidates that are not materialized yet.");
|
|
5444
|
+
console.log(" \u2192 Run `kaddo create --from roadmap`, or use the work-item-agent to");
|
|
5445
|
+
console.log(" materialize them into knowledge/delivery/work-items/.");
|
|
5446
|
+
}
|
|
5300
5447
|
console.log("");
|
|
5301
5448
|
console.log(`Current phase: ${phase}`);
|
|
5302
5449
|
console.log("Recommended next steps:");
|
|
@@ -5539,14 +5686,14 @@ async function runClassify(opts = {}) {
|
|
|
5539
5686
|
}
|
|
5540
5687
|
|
|
5541
5688
|
// src/commands/status.ts
|
|
5542
|
-
import { parse as
|
|
5689
|
+
import { parse as parseYaml10 } from "yaml";
|
|
5543
5690
|
var ARCH_DIR7 = "knowledge";
|
|
5544
5691
|
var CONFIG_PATH4 = ".kaddo/config.yml";
|
|
5545
5692
|
function loadConfig3(dir) {
|
|
5546
5693
|
const p2 = join(dir, CONFIG_PATH4);
|
|
5547
5694
|
if (!exists(p2)) return {};
|
|
5548
5695
|
try {
|
|
5549
|
-
return
|
|
5696
|
+
return parseYaml10(readFile(p2));
|
|
5550
5697
|
} catch {
|
|
5551
5698
|
return {};
|
|
5552
5699
|
}
|
|
@@ -5748,13 +5895,13 @@ function runHistory(opts = {}) {
|
|
|
5748
5895
|
}
|
|
5749
5896
|
|
|
5750
5897
|
// src/commands/add.ts
|
|
5751
|
-
import { parse as
|
|
5898
|
+
import { parse as parseYaml11, stringify as stringifyYaml3 } from "yaml";
|
|
5752
5899
|
var CONFIG_PATH5 = ".kaddo/config.yml";
|
|
5753
5900
|
function readProjectState(dir) {
|
|
5754
5901
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5755
5902
|
if (!exists(configPath)) return void 0;
|
|
5756
5903
|
try {
|
|
5757
|
-
const config =
|
|
5904
|
+
const config = parseYaml11(readFile(configPath));
|
|
5758
5905
|
return config.project?.state;
|
|
5759
5906
|
} catch {
|
|
5760
5907
|
return void 0;
|
|
@@ -5772,7 +5919,7 @@ function markModuleInstalled(dir, configKey, moduleName) {
|
|
|
5772
5919
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5773
5920
|
if (!exists(configPath)) return;
|
|
5774
5921
|
try {
|
|
5775
|
-
const config =
|
|
5922
|
+
const config = parseYaml11(readFile(configPath));
|
|
5776
5923
|
config[configKey] = { installed: true, installed_at: (/* @__PURE__ */ new Date()).toISOString().split("T")[0] };
|
|
5777
5924
|
const modules = config.modules ?? [];
|
|
5778
5925
|
if (!modules.includes(moduleName)) modules.push(moduleName);
|
|
@@ -5785,7 +5932,7 @@ function isModuleInstalled(dir, configKey) {
|
|
|
5785
5932
|
const configPath = join(dir, CONFIG_PATH5);
|
|
5786
5933
|
if (!exists(configPath)) return false;
|
|
5787
5934
|
try {
|
|
5788
|
-
const config =
|
|
5935
|
+
const config = parseYaml11(readFile(configPath));
|
|
5789
5936
|
const moduleConfig = config[configKey];
|
|
5790
5937
|
return moduleConfig?.installed === true;
|
|
5791
5938
|
} catch {
|
|
@@ -6109,13 +6256,13 @@ ${globs.map((g) => ` - ${g}`).join("\n")}`);
|
|
|
6109
6256
|
}
|
|
6110
6257
|
|
|
6111
6258
|
// src/commands/module-descriptor.ts
|
|
6112
|
-
import { parse as
|
|
6259
|
+
import { parse as parseYaml12, stringify as stringifyYaml4 } from "yaml";
|
|
6113
6260
|
var DESCRIPTOR_PATH2 = "knowledge/module.yml";
|
|
6114
6261
|
function readDescriptor(dir) {
|
|
6115
6262
|
const path5 = join(dir, DESCRIPTOR_PATH2);
|
|
6116
6263
|
if (!exists(path5)) return null;
|
|
6117
6264
|
try {
|
|
6118
|
-
return
|
|
6265
|
+
return parseYaml12(readFile(path5));
|
|
6119
6266
|
} catch {
|
|
6120
6267
|
return null;
|
|
6121
6268
|
}
|
|
@@ -6216,7 +6363,7 @@ function printDescriptor(d) {
|
|
|
6216
6363
|
}
|
|
6217
6364
|
|
|
6218
6365
|
// src/commands/modules-map.ts
|
|
6219
|
-
import { parse as
|
|
6366
|
+
import { parse as parseYaml13, stringify as stringifyYaml5 } from "yaml";
|
|
6220
6367
|
|
|
6221
6368
|
// src/templates/registry.ts
|
|
6222
6369
|
var QUALITY = "## Quality checklist";
|
|
@@ -7714,7 +7861,7 @@ function readModulesDescriptor(dir) {
|
|
|
7714
7861
|
const path5 = join(dir, DESCRIPTOR_PATH3);
|
|
7715
7862
|
if (!exists(path5)) return { version: 1, modules: [] };
|
|
7716
7863
|
try {
|
|
7717
|
-
const parsed =
|
|
7864
|
+
const parsed = parseYaml13(readFile(path5));
|
|
7718
7865
|
return { version: parsed.version ?? 1, modules: parsed.modules ?? [] };
|
|
7719
7866
|
} catch {
|
|
7720
7867
|
return { version: 1, modules: [] };
|
|
@@ -7987,6 +8134,10 @@ async function runBootstrap(dir = cwd()) {
|
|
|
7987
8134
|
for (const p2 of result.skipped) console.log(` - ${p2}`);
|
|
7988
8135
|
}
|
|
7989
8136
|
console.log("");
|
|
8137
|
+
console.log("");
|
|
8138
|
+
log2.info(
|
|
8139
|
+
"When you pass the context pack to your LLM/coding agent, it must never commit, push or merge without your confirmation \u2014 and create a branch before implementing."
|
|
8140
|
+
);
|
|
7990
8141
|
outro2(
|
|
7991
8142
|
"Minimal knowledge base ready (Business \u2192 Product \u2192 Tech). Run `kaddo context` and `kaddo add agents`, then refine with the business-agent, bootstrap-agent and codebase-agent. Roadmap and work items come next under knowledge/delivery/."
|
|
7992
8143
|
);
|
|
@@ -7994,7 +8145,7 @@ async function runBootstrap(dir = cwd()) {
|
|
|
7994
8145
|
|
|
7995
8146
|
// src/index.ts
|
|
7996
8147
|
var program = new Command();
|
|
7997
|
-
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.
|
|
8148
|
+
program.name("kaddo").description("Knowledge Driven Development toolkit").version("3.5.0");
|
|
7998
8149
|
program.command("init").description("Initialize Kaddo in the current project").action(async () => {
|
|
7999
8150
|
await runInit();
|
|
8000
8151
|
});
|