@kaddo/cli 3.41.0 → 3.42.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 +1 -0
- package/dist/index.js +232 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -540,6 +540,7 @@ create --from roadmap → owners → guard → explain`.
|
|
|
540
540
|
| v3.40 | ADR materialization: `kaddo adr` (alias `decisions`) detects decision candidates + ADRs and hands off the ADR files to create; `tech_decisions` status (none/candidates/draft-adrs/accepted-adrs) surfaced in `explain`/`context`/`understand`; adr-writing skill formalized |
|
|
541
541
|
| v3.40.1 | ADR slug cleanup + MCP: suggested ADR filenames strip list/heading prefixes (no `ADR-001-1-…`) and normalize acronyms; new read-only MCP resource `kaddo://tech-decisions` sharing `buildTechDecisions` with `kaddo adr` |
|
|
542
542
|
| v3.41 | Tech knowledge structure: `knowledge/tech/discovery/` for architecture-notes/decision-candidates (core vs decisions vs discovery); `kaddo adr` reads discovery-first with legacy fallback; `kaddo tech organize` migrates safely; `explain` shows `## Tech Knowledge` |
|
|
543
|
+
| v3.42 | Agent & skill version metadata: installed agents/skills carry a `version:`; `kaddo agents status` / `kaddo skills status` classify up-to-date/outdated/unknown-version/modified/missing; `agents update` / `skills update` refresh outdated safely (never overwrite edits without `--force`); MCP `kaddo://installed-assets` |
|
|
543
544
|
|
|
544
545
|
**Optional modules (installed with `kaddo add`):**
|
|
545
546
|
|
package/dist/index.js
CHANGED
|
@@ -712,6 +712,14 @@ var COMMAND_HELP = {
|
|
|
712
712
|
"tech organize": {
|
|
713
713
|
question: "Is knowledge/tech/ cleanly separated (core vs discovery vs decisions)?",
|
|
714
714
|
next: "Discovery notes now live under knowledge/tech/discovery/"
|
|
715
|
+
},
|
|
716
|
+
"agents status": {
|
|
717
|
+
question: "Are the installed agents aligned with the current Kaddo version?",
|
|
718
|
+
next: "Run `kaddo agents update` to refresh outdated agents"
|
|
719
|
+
},
|
|
720
|
+
"skills status": {
|
|
721
|
+
question: "Are the installed skills aligned with the current Kaddo version?",
|
|
722
|
+
next: "Run `kaddo skills update` to refresh outdated skills"
|
|
715
723
|
}
|
|
716
724
|
};
|
|
717
725
|
function commandFooterLines(name) {
|
|
@@ -1515,14 +1523,38 @@ var guardAdvancedModule = {
|
|
|
1515
1523
|
]
|
|
1516
1524
|
};
|
|
1517
1525
|
|
|
1526
|
+
// src/core/version.ts
|
|
1527
|
+
import { fileURLToPath } from "url";
|
|
1528
|
+
import { dirname, join as join2, parse } from "path";
|
|
1529
|
+
import { existsSync, readFileSync } from "fs";
|
|
1530
|
+
function resolveVersion() {
|
|
1531
|
+
try {
|
|
1532
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
1533
|
+
const root = parse(dir).root;
|
|
1534
|
+
for (; ; ) {
|
|
1535
|
+
const pkg = join2(dir, "package.json");
|
|
1536
|
+
if (existsSync(pkg)) {
|
|
1537
|
+
const v = JSON.parse(readFileSync(pkg, "utf-8")).version;
|
|
1538
|
+
if (v) return v;
|
|
1539
|
+
}
|
|
1540
|
+
if (dir === root) break;
|
|
1541
|
+
dir = dirname(dir);
|
|
1542
|
+
}
|
|
1543
|
+
} catch {
|
|
1544
|
+
}
|
|
1545
|
+
return "0.0.0";
|
|
1546
|
+
}
|
|
1547
|
+
var KADDO_VERSION = resolveVersion();
|
|
1548
|
+
|
|
1518
1549
|
// src/skills/skills.ts
|
|
1519
1550
|
function skill(id, title, group, appliesTo, body) {
|
|
1520
1551
|
const frontMatter2 = [
|
|
1521
1552
|
"---",
|
|
1522
1553
|
"type: skill",
|
|
1523
1554
|
`id: ${id}`,
|
|
1555
|
+
`name: ${id}`,
|
|
1524
1556
|
`title: ${title}`,
|
|
1525
|
-
|
|
1557
|
+
`version: ${KADDO_VERSION}`,
|
|
1526
1558
|
`group: ${group}`,
|
|
1527
1559
|
"applies_to:",
|
|
1528
1560
|
...appliesTo.map((a) => ` - ${a}`),
|
|
@@ -4050,6 +4082,19 @@ function selectAgentFiles(opts) {
|
|
|
4050
4082
|
}
|
|
4051
4083
|
|
|
4052
4084
|
// src/modules/agents.ts
|
|
4085
|
+
function withAgentFrontMatter(fileName, content) {
|
|
4086
|
+
const name = fileName.replace(/\.md$/, "");
|
|
4087
|
+
const fm2 = [
|
|
4088
|
+
"---",
|
|
4089
|
+
"type: agent",
|
|
4090
|
+
`name: ${name}`,
|
|
4091
|
+
`version: ${KADDO_VERSION}`,
|
|
4092
|
+
`group: ${agentGroupOf(fileName)}`,
|
|
4093
|
+
"---",
|
|
4094
|
+
""
|
|
4095
|
+
].join("\n");
|
|
4096
|
+
return fm2 + content.replace(/^\s+/, "");
|
|
4097
|
+
}
|
|
4053
4098
|
var agentReadme = {
|
|
4054
4099
|
path: "knowledge/agents/README.md",
|
|
4055
4100
|
content: [
|
|
@@ -4121,7 +4166,7 @@ var agentReadme = {
|
|
|
4121
4166
|
};
|
|
4122
4167
|
var agentFiles = AGENT_PROMPTS.map((a) => ({
|
|
4123
4168
|
path: agentInstallPath(a.fileName),
|
|
4124
|
-
content: a.content
|
|
4169
|
+
content: withAgentFrontMatter(a.fileName, a.content)
|
|
4125
4170
|
}));
|
|
4126
4171
|
var agentsModule = {
|
|
4127
4172
|
name: "agents",
|
|
@@ -6202,7 +6247,7 @@ function runIgnoreRemove(artifactId) {
|
|
|
6202
6247
|
}
|
|
6203
6248
|
|
|
6204
6249
|
// src/commands/explain.ts
|
|
6205
|
-
import
|
|
6250
|
+
import matter5 from "gray-matter";
|
|
6206
6251
|
import { parse as parseYaml9 } from "yaml";
|
|
6207
6252
|
|
|
6208
6253
|
// src/core/delivery-phase.ts
|
|
@@ -8214,6 +8259,72 @@ function buildTechDecisions(dir) {
|
|
|
8214
8259
|
};
|
|
8215
8260
|
}
|
|
8216
8261
|
|
|
8262
|
+
// src/core/assets.ts
|
|
8263
|
+
import matter4 from "gray-matter";
|
|
8264
|
+
function canonicalAgents() {
|
|
8265
|
+
return AGENT_PROMPTS.map((a) => ({
|
|
8266
|
+
name: a.fileName.replace(/\.md$/, ""),
|
|
8267
|
+
path: agentInstallPath(a.fileName),
|
|
8268
|
+
content: withAgentFrontMatter(a.fileName, a.content)
|
|
8269
|
+
}));
|
|
8270
|
+
}
|
|
8271
|
+
function canonicalSkills() {
|
|
8272
|
+
return SKILLS.map((s) => ({ name: s.id, path: skillInstallPath(s.id), content: s.content }));
|
|
8273
|
+
}
|
|
8274
|
+
function versionOf(content) {
|
|
8275
|
+
try {
|
|
8276
|
+
const v = matter4(content).data.version;
|
|
8277
|
+
return v === void 0 || v === null ? null : String(v);
|
|
8278
|
+
} catch {
|
|
8279
|
+
return null;
|
|
8280
|
+
}
|
|
8281
|
+
}
|
|
8282
|
+
function cmpVersion(a, b) {
|
|
8283
|
+
const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
|
|
8284
|
+
const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
|
|
8285
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
8286
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
8287
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
8288
|
+
}
|
|
8289
|
+
return 0;
|
|
8290
|
+
}
|
|
8291
|
+
function classify(dir, asset) {
|
|
8292
|
+
const full = join(dir, asset.path);
|
|
8293
|
+
const base = { name: asset.name, path: asset.path, available: KADDO_VERSION };
|
|
8294
|
+
if (!exists(full)) return { ...base, installed: null, state: "missing" };
|
|
8295
|
+
let content = "";
|
|
8296
|
+
try {
|
|
8297
|
+
content = readFile(full);
|
|
8298
|
+
} catch {
|
|
8299
|
+
return { ...base, installed: null, state: "missing" };
|
|
8300
|
+
}
|
|
8301
|
+
const installed = versionOf(content);
|
|
8302
|
+
if (installed === null) return { ...base, installed: null, state: "unknown-version" };
|
|
8303
|
+
const cmp = cmpVersion(installed, KADDO_VERSION);
|
|
8304
|
+
if (cmp < 0) return { ...base, installed, state: "outdated" };
|
|
8305
|
+
if (content.trim() !== asset.content.trim()) return { ...base, installed, state: "modified" };
|
|
8306
|
+
return { ...base, installed, state: "up-to-date" };
|
|
8307
|
+
}
|
|
8308
|
+
function summarize(items) {
|
|
8309
|
+
const count = (s) => items.filter((i) => i.state === s).length;
|
|
8310
|
+
return {
|
|
8311
|
+
total: items.length,
|
|
8312
|
+
up_to_date: count("up-to-date"),
|
|
8313
|
+
outdated: count("outdated"),
|
|
8314
|
+
missing: count("missing"),
|
|
8315
|
+
unknown_version: count("unknown-version"),
|
|
8316
|
+
modified: count("modified"),
|
|
8317
|
+
items
|
|
8318
|
+
};
|
|
8319
|
+
}
|
|
8320
|
+
function assetStatus(dir, kind) {
|
|
8321
|
+
const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
|
|
8322
|
+
return summarize(catalog.map((a) => classify(dir, a)));
|
|
8323
|
+
}
|
|
8324
|
+
function installedAssetsSummary(dir) {
|
|
8325
|
+
return { version: KADDO_VERSION, agents: assetStatus(dir, "agent"), skills: assetStatus(dir, "skill") };
|
|
8326
|
+
}
|
|
8327
|
+
|
|
8217
8328
|
// src/core/project-explain.ts
|
|
8218
8329
|
var ARCH_DIR4 = "knowledge";
|
|
8219
8330
|
function normalizeTitle(t) {
|
|
@@ -8437,7 +8548,8 @@ function buildProjectExplanation(dir) {
|
|
|
8437
8548
|
decisionCandidates: exists(join(dir, "knowledge/tech/discovery/decision-candidates.md")) || exists(join(dir, "knowledge/tech/decision-candidates.md")),
|
|
8438
8549
|
legacyLocation: exists(join(dir, "knowledge/tech/architecture-notes.md")) || exists(join(dir, "knowledge/tech/decision-candidates.md"))
|
|
8439
8550
|
}
|
|
8440
|
-
}
|
|
8551
|
+
},
|
|
8552
|
+
installedAssets: installedAssetsSummary(dir)
|
|
8441
8553
|
};
|
|
8442
8554
|
}
|
|
8443
8555
|
function stateLabel(state) {
|
|
@@ -8672,6 +8784,21 @@ function renderExplanationHuman(exp) {
|
|
|
8672
8784
|
lines.push("Tech discovery files are in the legacy `knowledge/tech/` root. Suggested cleanup: run `kaddo tech organize`.");
|
|
8673
8785
|
lines.push("");
|
|
8674
8786
|
}
|
|
8787
|
+
const ia = exp.installedAssets;
|
|
8788
|
+
const agentsInstalled = ia.agents.total - ia.agents.missing;
|
|
8789
|
+
const skillsInstalled = ia.skills.total - ia.skills.missing;
|
|
8790
|
+
if (agentsInstalled > 0 || skillsInstalled > 0) {
|
|
8791
|
+
const issues = (s2) => [s2.outdated ? `${s2.outdated} outdated` : "", s2.unknown_version ? `${s2.unknown_version} unknown-version` : "", s2.modified ? `${s2.modified} modified` : ""].filter(Boolean).join(", ");
|
|
8792
|
+
lines.push("## Installed Assets");
|
|
8793
|
+
lines.push(`- CLI version: ${ia.version}`);
|
|
8794
|
+
lines.push(`- Agents: ${agentsInstalled} installed${issues(ia.agents) ? ` (${issues(ia.agents)})` : ""}`);
|
|
8795
|
+
lines.push(`- Skills: ${skillsInstalled} installed${issues(ia.skills) ? ` (${issues(ia.skills)})` : ""}`);
|
|
8796
|
+
if (ia.agents.outdated + ia.agents.unknown_version + ia.skills.outdated + ia.skills.unknown_version > 0) {
|
|
8797
|
+
lines.push("");
|
|
8798
|
+
lines.push("Suggested: run `kaddo agents status` and `kaddo skills status`.");
|
|
8799
|
+
}
|
|
8800
|
+
lines.push("");
|
|
8801
|
+
}
|
|
8675
8802
|
return lines.join("\n").trimEnd() + "\n";
|
|
8676
8803
|
}
|
|
8677
8804
|
function renderExplanationAgent(exp) {
|
|
@@ -8687,7 +8814,7 @@ function readKnowledge(dir) {
|
|
|
8687
8814
|
if (!exists(knowledgePath)) return null;
|
|
8688
8815
|
try {
|
|
8689
8816
|
const raw = readFile(knowledgePath);
|
|
8690
|
-
const { data, content } =
|
|
8817
|
+
const { data, content } = matter5(raw);
|
|
8691
8818
|
return { content, data };
|
|
8692
8819
|
} catch {
|
|
8693
8820
|
return null;
|
|
@@ -8698,7 +8825,7 @@ function readRoadmap(dir) {
|
|
|
8698
8825
|
if (!exists(roadmapPath)) return null;
|
|
8699
8826
|
try {
|
|
8700
8827
|
const raw = readFile(roadmapPath);
|
|
8701
|
-
const { content } =
|
|
8828
|
+
const { content } = matter5(raw);
|
|
8702
8829
|
return content.trim();
|
|
8703
8830
|
} catch {
|
|
8704
8831
|
return null;
|
|
@@ -8867,7 +8994,7 @@ function runExplain(opts) {
|
|
|
8867
8994
|
}
|
|
8868
8995
|
|
|
8869
8996
|
// src/core/context-pack.ts
|
|
8870
|
-
import
|
|
8997
|
+
import matter6 from "gray-matter";
|
|
8871
8998
|
var CONTEXT_PACK_VERSION = "1";
|
|
8872
8999
|
var ARCH_DIR6 = "knowledge";
|
|
8873
9000
|
function readScanJson(dir) {
|
|
@@ -8880,7 +9007,7 @@ function readScanJson(dir) {
|
|
|
8880
9007
|
}
|
|
8881
9008
|
}
|
|
8882
9009
|
function firstParagraph2(markdown) {
|
|
8883
|
-
const body =
|
|
9010
|
+
const body = matter6(markdown).content.trim();
|
|
8884
9011
|
const para = body.split("\n\n").map((p2) => p2.trim()).find((p2) => p2 && !p2.startsWith("#"));
|
|
8885
9012
|
return para ?? "";
|
|
8886
9013
|
}
|
|
@@ -9075,6 +9202,11 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
9075
9202
|
nextStepRecommendation,
|
|
9076
9203
|
techDecisions,
|
|
9077
9204
|
techKnowledge,
|
|
9205
|
+
installedAssets: (() => {
|
|
9206
|
+
const s = installedAssetsSummary(dir);
|
|
9207
|
+
const compact = (a) => ({ total: a.total, installed: a.total - a.missing, outdated: a.outdated, unknown_version: a.unknown_version, modified: a.modified });
|
|
9208
|
+
return { version: s.version, agents: compact(s.agents), skills: compact(s.skills) };
|
|
9209
|
+
})(),
|
|
9078
9210
|
deliveryMix,
|
|
9079
9211
|
external: loadExternalCapsules(dir),
|
|
9080
9212
|
graph: loadGraphSummary(dir),
|
|
@@ -9616,6 +9748,17 @@ function runUnderstand() {
|
|
|
9616
9748
|
console.log(" \u2192 Use the adr-writing skill to create ADR drafts from `knowledge/tech/decision-candidates.md`");
|
|
9617
9749
|
console.log(" into `knowledge/tech/decisions/` before implementing affected technical Work Items (`kaddo adr`).");
|
|
9618
9750
|
}
|
|
9751
|
+
const ia = exp.installedAssets;
|
|
9752
|
+
const outdatedRecommended = ia.agents.items.filter(
|
|
9753
|
+
(a) => (a.state === "outdated" || a.state === "unknown-version") && assessment.recommendedAgents.includes(a.name)
|
|
9754
|
+
);
|
|
9755
|
+
if (outdatedRecommended.length > 0) {
|
|
9756
|
+
console.log("");
|
|
9757
|
+
for (const a of outdatedRecommended) {
|
|
9758
|
+
console.log(`Recommended agent ${a.name} is ${a.state} (installed ${a.installed ?? "unknown"}, available ${a.available}).`);
|
|
9759
|
+
}
|
|
9760
|
+
console.log(" \u2192 Run `kaddo agents update` or review `kaddo agents status`.");
|
|
9761
|
+
}
|
|
9619
9762
|
if (exp.externalCapsules.length > 0) {
|
|
9620
9763
|
console.log("");
|
|
9621
9764
|
console.log("External knowledge:");
|
|
@@ -9776,7 +9919,7 @@ var DECLARED_LEVEL = {
|
|
|
9776
9919
|
incident: "K2",
|
|
9777
9920
|
rfc: "K3"
|
|
9778
9921
|
};
|
|
9779
|
-
function
|
|
9922
|
+
function classify2(declaredType, declaredLevel, touchedFiles) {
|
|
9780
9923
|
const signals = detectSignals(touchedFiles);
|
|
9781
9924
|
const observedLevel = highestLevel(signals);
|
|
9782
9925
|
const expectedLevel = DECLARED_LEVEL[declaredType] ?? declaredLevel ?? "K2";
|
|
@@ -9856,7 +9999,7 @@ async function runClassify(opts = {}) {
|
|
|
9856
9999
|
return;
|
|
9857
10000
|
}
|
|
9858
10001
|
if (opts.type) {
|
|
9859
|
-
const result2 =
|
|
10002
|
+
const result2 = classify2(opts.type, opts.level ?? "", touchedFiles);
|
|
9860
10003
|
printResult2(result2);
|
|
9861
10004
|
return;
|
|
9862
10005
|
}
|
|
@@ -9867,7 +10010,7 @@ async function runClassify(opts = {}) {
|
|
|
9867
10010
|
console.log("Or create one with: kaddo create <type>");
|
|
9868
10011
|
return;
|
|
9869
10012
|
}
|
|
9870
|
-
const result =
|
|
10013
|
+
const result = classify2(activeItem.type, activeItem.knowledgeLevel, touchedFiles);
|
|
9871
10014
|
printResult2(result, activeItem.id || activeItem.title);
|
|
9872
10015
|
}
|
|
9873
10016
|
|
|
@@ -9936,7 +10079,7 @@ function runStatus() {
|
|
|
9936
10079
|
}
|
|
9937
10080
|
|
|
9938
10081
|
// src/commands/learn.ts
|
|
9939
|
-
import
|
|
10082
|
+
import matter7 from "gray-matter";
|
|
9940
10083
|
var ARCH_DIR9 = "knowledge";
|
|
9941
10084
|
var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
|
|
9942
10085
|
function findWorkItemFile(dir, id) {
|
|
@@ -9948,7 +10091,7 @@ function findWorkItemFile(dir, id) {
|
|
|
9948
10091
|
}
|
|
9949
10092
|
function updateWorkItemFile(filePath, learning) {
|
|
9950
10093
|
const raw = readFile(filePath);
|
|
9951
|
-
const { data, content } =
|
|
10094
|
+
const { data, content } = matter7(raw);
|
|
9952
10095
|
data.status = "done";
|
|
9953
10096
|
data.completed_at = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9954
10097
|
let updatedContent = content;
|
|
@@ -9973,7 +10116,7 @@ ${learning.trim()}
|
|
|
9973
10116
|
${learning.trim()}
|
|
9974
10117
|
`;
|
|
9975
10118
|
}
|
|
9976
|
-
const newRaw =
|
|
10119
|
+
const newRaw = matter7.stringify(updatedContent, data);
|
|
9977
10120
|
writeFile(filePath, newRaw);
|
|
9978
10121
|
}
|
|
9979
10122
|
async function runLearn(artifactId) {
|
|
@@ -10223,7 +10366,7 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
|
10223
10366
|
}
|
|
10224
10367
|
|
|
10225
10368
|
// src/core/ownership-suggest.ts
|
|
10226
|
-
import
|
|
10369
|
+
import matter8 from "gray-matter";
|
|
10227
10370
|
var SCAN_PATH = ".kaddo/scan.json";
|
|
10228
10371
|
function normalizeGlob(input) {
|
|
10229
10372
|
let g = input.trim().replace(/\\/g, "/");
|
|
@@ -10345,11 +10488,11 @@ function suggestGlobs(artifact, signals) {
|
|
|
10345
10488
|
return [...new Set(out)];
|
|
10346
10489
|
}
|
|
10347
10490
|
function applyOwnership(raw, globs, mode = "replace") {
|
|
10348
|
-
const parsed =
|
|
10491
|
+
const parsed = matter8(raw);
|
|
10349
10492
|
const existing = toStringArray3(parsed.data.code);
|
|
10350
10493
|
const next = mode === "append" ? [.../* @__PURE__ */ new Set([...existing, ...globs])] : [...new Set(globs)];
|
|
10351
10494
|
const data = { ...parsed.data, code: next };
|
|
10352
|
-
return
|
|
10495
|
+
return matter8.stringify(parsed.content, data);
|
|
10353
10496
|
}
|
|
10354
10497
|
|
|
10355
10498
|
// src/commands/owners.ts
|
|
@@ -12961,7 +13104,7 @@ function runGraphExport(opts = {}) {
|
|
|
12961
13104
|
}
|
|
12962
13105
|
|
|
12963
13106
|
// src/core/impact-report.ts
|
|
12964
|
-
import
|
|
13107
|
+
import matter9 from "gray-matter";
|
|
12965
13108
|
function isBroadGlob(glob) {
|
|
12966
13109
|
if (!glob.endsWith("/**")) return false;
|
|
12967
13110
|
const prefix = glob.slice(0, -3);
|
|
@@ -13030,7 +13173,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
13030
13173
|
}
|
|
13031
13174
|
}
|
|
13032
13175
|
try {
|
|
13033
|
-
const body =
|
|
13176
|
+
const body = matter9(readFile(wi.filePath)).content;
|
|
13034
13177
|
if (hasSection(body, /acceptance|criterios de aceptaci/i)) withAcceptance++;
|
|
13035
13178
|
else gaps.missing_acceptance_criteria.push(gapItem(wi, "Add an `## Acceptance Criteria` section."));
|
|
13036
13179
|
if (hasSection(body, /definition of done|^#{1,6}\s*dod\b|definici[oó]n de (terminado|hecho)/i)) withDoD++;
|
|
@@ -14141,6 +14284,70 @@ function runTechOrganize(dir = cwd()) {
|
|
|
14141
14284
|
outro2("Tech knowledge organized.");
|
|
14142
14285
|
}
|
|
14143
14286
|
|
|
14287
|
+
// src/commands/assets.ts
|
|
14288
|
+
var LABEL = { agent: "Agents", skill: "Skills" };
|
|
14289
|
+
function runAssetsStatus(kind, opts = {}) {
|
|
14290
|
+
const dir = cwd();
|
|
14291
|
+
requireConfig(dir);
|
|
14292
|
+
const summary = assetStatus(dir, kind);
|
|
14293
|
+
if (opts.json) {
|
|
14294
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
14295
|
+
return;
|
|
14296
|
+
}
|
|
14297
|
+
console.log("");
|
|
14298
|
+
console.log(LABEL[kind]);
|
|
14299
|
+
console.log("");
|
|
14300
|
+
const installed = summary.items.filter((i) => i.state !== "missing");
|
|
14301
|
+
for (const a of installed) {
|
|
14302
|
+
console.log(`${a.path}`);
|
|
14303
|
+
console.log(` Name: ${a.name}`);
|
|
14304
|
+
console.log(` Installed: ${a.installed ?? "unknown"}`);
|
|
14305
|
+
console.log(` Available: ${a.available}`);
|
|
14306
|
+
console.log(` Status: ${a.state}`);
|
|
14307
|
+
console.log("");
|
|
14308
|
+
}
|
|
14309
|
+
if (installed.length === 0) console.log(`No ${kind}s installed. Run \`kaddo add ${kind}s\`.`);
|
|
14310
|
+
console.log(
|
|
14311
|
+
`Summary: ${summary.up_to_date} up-to-date, ${summary.outdated} outdated, ${summary.unknown_version} unknown-version, ${summary.modified} modified, ${summary.missing} not installed.`
|
|
14312
|
+
);
|
|
14313
|
+
if (summary.outdated > 0 || summary.unknown_version > 0) {
|
|
14314
|
+
console.log(`Run \`kaddo ${kind}s update\` to refresh outdated ${kind}s (\`--force\` for unknown/modified).`);
|
|
14315
|
+
}
|
|
14316
|
+
printCommandFooter(`${kind}s status`);
|
|
14317
|
+
}
|
|
14318
|
+
function runAssetsUpdate(kind, opts = {}) {
|
|
14319
|
+
const dir = cwd();
|
|
14320
|
+
requireConfig(dir);
|
|
14321
|
+
intro2(`kaddo ${kind}s update`);
|
|
14322
|
+
const summary = assetStatus(dir, kind);
|
|
14323
|
+
const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
|
|
14324
|
+
const byPath = new Map(catalog.map((a) => [a.path, a.content]));
|
|
14325
|
+
const updated = [];
|
|
14326
|
+
const skipped = [];
|
|
14327
|
+
for (const item of summary.items) {
|
|
14328
|
+
const canonical = byPath.get(item.path);
|
|
14329
|
+
if (!canonical) continue;
|
|
14330
|
+
const safe = item.state === "outdated";
|
|
14331
|
+
const needsForce = item.state === "unknown-version" || item.state === "modified";
|
|
14332
|
+
if (safe || needsForce && opts.force) {
|
|
14333
|
+
writeFile(join(dir, item.path), canonical);
|
|
14334
|
+
updated.push(`${item.path} (${item.installed ?? "unknown"} \u2192 ${item.available})`);
|
|
14335
|
+
} else if (needsForce) {
|
|
14336
|
+
skipped.push(`${item.path} \u2014 ${item.state} (use --force to overwrite local changes)`);
|
|
14337
|
+
}
|
|
14338
|
+
}
|
|
14339
|
+
if (updated.length > 0) {
|
|
14340
|
+
log2.success("Updated:");
|
|
14341
|
+
for (const u of updated) console.log(` - ${u}`);
|
|
14342
|
+
} else {
|
|
14343
|
+
log2.info(`No ${kind}s to update.`);
|
|
14344
|
+
}
|
|
14345
|
+
for (const s of skipped) log2.warn(`Skipped ${s}`);
|
|
14346
|
+
if (summary.missing > 0) log2.info(`${summary.missing} ${kind}(s) not installed \u2014 run \`kaddo add ${kind}s\` to add them.`);
|
|
14347
|
+
printCommandFooter(`${kind}s status`);
|
|
14348
|
+
outro2(`${LABEL[kind]} update complete.`);
|
|
14349
|
+
}
|
|
14350
|
+
|
|
14144
14351
|
// src/index.ts
|
|
14145
14352
|
var require2 = createRequire(import.meta.url);
|
|
14146
14353
|
var { version } = require2("../package.json");
|
|
@@ -14194,6 +14401,12 @@ program.command("drift").description("Drift Trend Report from recorded `kaddo gu
|
|
|
14194
14401
|
var questionsAction = (opts) => runQuestions(opts);
|
|
14195
14402
|
program.command("questions").description("Open-questions readiness gate: blocking/important/deferred decisions before the roadmap").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file (e.g. .kaddo/reports/questions-report.md)").action(questionsAction);
|
|
14196
14403
|
program.command("readiness").description("Alias for `kaddo questions`").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file").action(questionsAction);
|
|
14404
|
+
var agentsCmd = program.command("agents").description("Inspect and update installed Kaddo agents (version status)");
|
|
14405
|
+
agentsCmd.command("status").description("Show installed agents, their version and whether they are up to date").option("--json", "Output JSON").action((opts) => runAssetsStatus("agent", opts));
|
|
14406
|
+
agentsCmd.command("update").description("Refresh outdated agents (never overwrites modified files without --force)").option("--force", "Overwrite unknown-version / locally-modified agents").action((opts) => runAssetsUpdate("agent", opts));
|
|
14407
|
+
var skillsCmd = program.command("skills").description("Inspect and update installed Kaddo skills (version status)");
|
|
14408
|
+
skillsCmd.command("status").description("Show installed skills, their version and whether they are up to date").option("--json", "Output JSON").action((opts) => runAssetsStatus("skill", opts));
|
|
14409
|
+
skillsCmd.command("update").description("Refresh outdated skills (never overwrites modified files without --force)").option("--force", "Overwrite unknown-version / locally-modified skills").action((opts) => runAssetsUpdate("skill", opts));
|
|
14197
14410
|
var techCmd = program.command("tech").description("Organize the knowledge/tech/ structure (core vs discovery vs decisions)");
|
|
14198
14411
|
techCmd.command("organize").description("Move discovery artifacts into knowledge/tech/discovery/ (never overwrites, no content change)").action(() => {
|
|
14199
14412
|
runTechOrganize();
|