@kaddo/mcp 3.103.0 → 3.104.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/dist/index.js +199 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10815,18 +10815,23 @@ import fs4 from "fs";
|
|
|
10815
10815
|
import matter82 from "gray-matter";
|
|
10816
10816
|
import matter92 from "gray-matter";
|
|
10817
10817
|
import { parse as parseYaml92, stringify as stringifyYaml5 } from "yaml";
|
|
10818
|
-
|
|
10819
|
-
|
|
10818
|
+
import { parse as parseYaml102, stringify as stringifyYaml6 } from "yaml";
|
|
10819
|
+
function exists2(p) {
|
|
10820
|
+
return fs3.existsSync(p);
|
|
10820
10821
|
}
|
|
10821
|
-
function readFile2(
|
|
10822
|
-
return fs3.readFileSync(
|
|
10822
|
+
function readFile2(p) {
|
|
10823
|
+
return fs3.readFileSync(p, "utf-8");
|
|
10824
|
+
}
|
|
10825
|
+
function writeFile2(filePath, content) {
|
|
10826
|
+
fs3.mkdirSync(path3.dirname(filePath), { recursive: true });
|
|
10827
|
+
fs3.writeFileSync(filePath, content, "utf-8");
|
|
10823
10828
|
}
|
|
10824
10829
|
function readDir2(dirPath) {
|
|
10825
10830
|
if (!exists2(dirPath)) return [];
|
|
10826
10831
|
return fs3.readdirSync(dirPath);
|
|
10827
10832
|
}
|
|
10828
|
-
function isFile2(
|
|
10829
|
-
return exists2(
|
|
10833
|
+
function isFile2(p) {
|
|
10834
|
+
return exists2(p) && fs3.statSync(p).isFile();
|
|
10830
10835
|
}
|
|
10831
10836
|
function join3(...parts) {
|
|
10832
10837
|
return path3.join(...parts);
|
|
@@ -11051,8 +11056,8 @@ function isActiveState2(s) {
|
|
|
11051
11056
|
return ACTIVE_STATES3.includes(s);
|
|
11052
11057
|
}
|
|
11053
11058
|
function lifecycleFolderOf2(filePath) {
|
|
11054
|
-
const
|
|
11055
|
-
const m2 =
|
|
11059
|
+
const p = filePath.replace(/\\/g, "/");
|
|
11060
|
+
const m2 = p.match(/\/delivery\/work-items\/([^/]+)\//);
|
|
11056
11061
|
if (m2 && isLifecycleState2(m2[1])) return m2[1];
|
|
11057
11062
|
return null;
|
|
11058
11063
|
}
|
|
@@ -11065,8 +11070,8 @@ function lifecycleStateOf2(item) {
|
|
|
11065
11070
|
return "ready";
|
|
11066
11071
|
}
|
|
11067
11072
|
var ARCH_DIR3 = "knowledge";
|
|
11068
|
-
function toPosix6(
|
|
11069
|
-
return
|
|
11073
|
+
function toPosix6(p) {
|
|
11074
|
+
return p.replace(/\\/g, "/");
|
|
11070
11075
|
}
|
|
11071
11076
|
function relativeTo2(dir, filePath) {
|
|
11072
11077
|
const base = toPosix6(dir).replace(/\/+$/, "");
|
|
@@ -12311,10 +12316,10 @@ ${QUALITY2}
|
|
|
12311
12316
|
`;
|
|
12312
12317
|
var EXTERNAL_PATH2 = ".kaddo/external.yml";
|
|
12313
12318
|
function loadExternalRegistry2(dir) {
|
|
12314
|
-
const
|
|
12315
|
-
if (!exists2(
|
|
12319
|
+
const p = join3(dir, EXTERNAL_PATH2);
|
|
12320
|
+
if (!exists2(p)) return [];
|
|
12316
12321
|
try {
|
|
12317
|
-
const parsed = parseYaml62(readFile2(
|
|
12322
|
+
const parsed = parseYaml62(readFile2(p));
|
|
12318
12323
|
return Array.isArray(parsed?.external) ? parsed.external : [];
|
|
12319
12324
|
} catch {
|
|
12320
12325
|
return [];
|
|
@@ -12326,8 +12331,8 @@ var ALL_STATUSES2 = ["draft", "ready", "in-progress", "blocked", "completed"];
|
|
|
12326
12331
|
function scopeStatuses2(scope) {
|
|
12327
12332
|
return scope === "all" ? { included: ALL_STATUSES2, excluded: ["archived"] } : { included: ACTIVE_STATUSES2, excluded: ["completed", "archived"] };
|
|
12328
12333
|
}
|
|
12329
|
-
function toPosix22(
|
|
12330
|
-
return
|
|
12334
|
+
function toPosix22(p) {
|
|
12335
|
+
return p.replace(/\\/g, "/");
|
|
12331
12336
|
}
|
|
12332
12337
|
function slug3(s) {
|
|
12333
12338
|
return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -12465,8 +12470,8 @@ function buildGraph2(dir, config, opts = {}, now = /* @__PURE__ */ new Date()) {
|
|
|
12465
12470
|
};
|
|
12466
12471
|
}
|
|
12467
12472
|
var KNOWLEDGE32 = "knowledge";
|
|
12468
|
-
function toPosix32(
|
|
12469
|
-
return
|
|
12473
|
+
function toPosix32(p) {
|
|
12474
|
+
return p.replace(/\\/g, "/");
|
|
12470
12475
|
}
|
|
12471
12476
|
function slug22(s) {
|
|
12472
12477
|
return s.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -12475,9 +12480,9 @@ function isAdr22(a2) {
|
|
|
12475
12480
|
return toPosix32(a2.filePath).includes("/tech/decisions/") && Boolean(a2.type);
|
|
12476
12481
|
}
|
|
12477
12482
|
function capabilityHeadings2(dir) {
|
|
12478
|
-
const
|
|
12479
|
-
if (!exists2(
|
|
12480
|
-
return readFile2(
|
|
12483
|
+
const p = join3(dir, KNOWLEDGE32, "product", "capabilities.md");
|
|
12484
|
+
if (!exists2(p)) return [];
|
|
12485
|
+
return readFile2(p).split(/\r?\n/).map((l2) => l2.match(/^#{2,3}\s+(.+?)\s*$/)).filter((m2) => Boolean(m2)).map((m2) => m2[1].trim()).filter((h2) => !/^(summary|resumen|overview|capabilities|capacidades)$/i.test(h2));
|
|
12481
12486
|
}
|
|
12482
12487
|
function humanMissing2(field) {
|
|
12483
12488
|
switch (field) {
|
|
@@ -15783,7 +15788,7 @@ var AGENT_PROMPTS2 = [
|
|
|
15783
15788
|
// Graph relationship quality (metadata hints → precise front matter — VS-056)
|
|
15784
15789
|
{ fileName: "graph-agent.md", content: GRAPH_AGENT2 }
|
|
15785
15790
|
// Every official prompt ends with its responsibility boundaries + Agent Trace footer.
|
|
15786
|
-
].map((
|
|
15791
|
+
].map((p) => ({ fileName: p.fileName, content: withResponsibilityTrace2(p.fileName, p.content) }));
|
|
15787
15792
|
function withAgentFrontMatter2(fileName, content) {
|
|
15788
15793
|
const name = fileName.replace(/\.md$/, "");
|
|
15789
15794
|
const fm = [
|
|
@@ -16422,8 +16427,8 @@ var TECHNICAL_RELATIONSHIP_TYPES = /* @__PURE__ */ new Set([
|
|
|
16422
16427
|
"implemented-by"
|
|
16423
16428
|
]);
|
|
16424
16429
|
var PROVENANCE = /* @__PURE__ */ new Set(["declared", "derived", "agent-reviewed"]);
|
|
16425
|
-
function isRelative(
|
|
16426
|
-
return typeof
|
|
16430
|
+
function isRelative(p) {
|
|
16431
|
+
return typeof p === "string" && p.trim() !== "" && !/^([a-zA-Z]:[\\/]|\/)/.test(p) && !p.includes("..");
|
|
16427
16432
|
}
|
|
16428
16433
|
function strList(v) {
|
|
16429
16434
|
return Array.isArray(v) ? v.map((x2) => typeof x2 === "string" ? x2.trim() : "").filter(Boolean) : [];
|
|
@@ -16466,9 +16471,9 @@ function parseTopologyContent(raw, dir) {
|
|
|
16466
16471
|
const moduleRaw = typeof e.module === "string" ? e.module.trim() : void 0;
|
|
16467
16472
|
if (moduleRaw && !validModules.has(moduleRaw)) findings.push({ level: "warning", message: `Entity "${id}" references unregistered module "${moduleRaw}".` });
|
|
16468
16473
|
const rawImpl = e.implementation ?? e.implementation_refs;
|
|
16469
|
-
const implementation = strList(rawImpl).filter((
|
|
16470
|
-
if (isRelative(
|
|
16471
|
-
findings.push({ level: "warning", message: `Entity "${id}" implementation ref "${
|
|
16474
|
+
const implementation = strList(rawImpl).filter((p) => {
|
|
16475
|
+
if (isRelative(p)) return true;
|
|
16476
|
+
findings.push({ level: "warning", message: `Entity "${id}" implementation ref "${p}" is not a safe relative path and was dropped.` });
|
|
16472
16477
|
return false;
|
|
16473
16478
|
});
|
|
16474
16479
|
const prov = e.provenance;
|
|
@@ -16676,8 +16681,8 @@ function splitSections(body) {
|
|
|
16676
16681
|
flush();
|
|
16677
16682
|
return sections;
|
|
16678
16683
|
}
|
|
16679
|
-
function isPlaceholder(
|
|
16680
|
-
const t =
|
|
16684
|
+
function isPlaceholder(text22) {
|
|
16685
|
+
const t = text22.trim();
|
|
16681
16686
|
if (!t) return true;
|
|
16682
16687
|
if (/^tbd$/i.test(t)) return true;
|
|
16683
16688
|
if (/^_[^_]*_$/.test(t) && !t.includes("\n")) return true;
|
|
@@ -16704,15 +16709,15 @@ function extractBullets(body) {
|
|
|
16704
16709
|
for (const line of body.split(/\r?\n/)) {
|
|
16705
16710
|
const m2 = line.match(/^\s*[-*+]\s+(.*)$/);
|
|
16706
16711
|
if (!m2) continue;
|
|
16707
|
-
let
|
|
16712
|
+
let text22 = m2[1].trim();
|
|
16708
16713
|
let checked = null;
|
|
16709
|
-
const cb =
|
|
16714
|
+
const cb = text22.match(/^\[([ xX])\]\s*(.*)$/);
|
|
16710
16715
|
if (cb) {
|
|
16711
16716
|
checked = cb[1].toLowerCase() === "x";
|
|
16712
|
-
|
|
16717
|
+
text22 = cb[2].trim();
|
|
16713
16718
|
}
|
|
16714
|
-
if (!
|
|
16715
|
-
out.push({ text:
|
|
16719
|
+
if (!text22 || isPlaceholder(text22)) continue;
|
|
16720
|
+
out.push({ text: text22, checked });
|
|
16716
16721
|
}
|
|
16717
16722
|
return out;
|
|
16718
16723
|
}
|
|
@@ -17457,7 +17462,7 @@ var SECRET_PATTERNS = [
|
|
|
17457
17462
|
/\.pfx$/i
|
|
17458
17463
|
];
|
|
17459
17464
|
function filterSecretPaths(paths) {
|
|
17460
|
-
return paths.filter((
|
|
17465
|
+
return paths.filter((p) => !SECRET_PATTERNS.some((re) => re.test(p)));
|
|
17461
17466
|
}
|
|
17462
17467
|
function collectImplementationEvidence(dir, workItemId, input) {
|
|
17463
17468
|
const artifacts = discoverWorkItems2(dir);
|
|
@@ -18488,6 +18493,92 @@ function createDefaultRegistry() {
|
|
|
18488
18493
|
return registry22;
|
|
18489
18494
|
}
|
|
18490
18495
|
var registry = createDefaultRegistry();
|
|
18496
|
+
var CURRENT_CONSENT_VERSION = 1;
|
|
18497
|
+
var DEFERRAL_DURATION_MS = 24 * 60 * 60 * 1e3;
|
|
18498
|
+
function getConsentState(config) {
|
|
18499
|
+
if (!config) return "unset";
|
|
18500
|
+
const t = config.telemetry;
|
|
18501
|
+
if (!t) return "unset";
|
|
18502
|
+
if (t.consent === "enabled") return "enabled";
|
|
18503
|
+
if (t.consent === "disabled") return "disabled";
|
|
18504
|
+
if (t.consent === void 0) {
|
|
18505
|
+
if (t.enabled === true) return "enabled";
|
|
18506
|
+
if (t.enabled === false) return "disabled";
|
|
18507
|
+
}
|
|
18508
|
+
return "unset";
|
|
18509
|
+
}
|
|
18510
|
+
function persistConsent(dir, consent) {
|
|
18511
|
+
const configPath = join3(dir, ".kaddo", "config.yml");
|
|
18512
|
+
if (!exists2(configPath)) return;
|
|
18513
|
+
const raw = readFile2(configPath);
|
|
18514
|
+
const doc = parseYaml102(raw) ?? {};
|
|
18515
|
+
const prev = doc.telemetry ?? {};
|
|
18516
|
+
delete prev.enabled;
|
|
18517
|
+
doc.telemetry = { ...prev, consent, consentVersion: CURRENT_CONSENT_VERSION };
|
|
18518
|
+
writeFile2(configPath, stringifyYaml6(doc));
|
|
18519
|
+
}
|
|
18520
|
+
function isDeferralActive(dir) {
|
|
18521
|
+
const p = join3(dir, ".kaddo", "telemetry-deferred.json");
|
|
18522
|
+
if (!exists2(p)) return false;
|
|
18523
|
+
try {
|
|
18524
|
+
const data = JSON.parse(readFile2(p));
|
|
18525
|
+
return data.deferredUntil > Date.now();
|
|
18526
|
+
} catch {
|
|
18527
|
+
return false;
|
|
18528
|
+
}
|
|
18529
|
+
}
|
|
18530
|
+
function deferConsent(dir) {
|
|
18531
|
+
const p = join3(dir, ".kaddo", "telemetry-deferred.json");
|
|
18532
|
+
writeFile2(p, JSON.stringify({ deferredUntil: Date.now() + DEFERRAL_DURATION_MS }));
|
|
18533
|
+
}
|
|
18534
|
+
function consentNotice() {
|
|
18535
|
+
return '[Telemetry consent] Anonymous usage telemetry has not been configured.\n Collects: command usage, version, lifecycle events.\n Never collects: source code, knowledge, prompts or PII.\n Use kaddo_set_telemetry_consent to enable, disable, or defer ("not-now").';
|
|
18536
|
+
}
|
|
18537
|
+
var TELEMETRY_DIR = ".kaddo/telemetry";
|
|
18538
|
+
var IDENTITY_FILE = "identity.json";
|
|
18539
|
+
function identityPath(dir) {
|
|
18540
|
+
return join3(dir, TELEMETRY_DIR, IDENTITY_FILE);
|
|
18541
|
+
}
|
|
18542
|
+
function loadIdentity(dir) {
|
|
18543
|
+
const p = identityPath(dir);
|
|
18544
|
+
if (!exists2(p)) return null;
|
|
18545
|
+
try {
|
|
18546
|
+
return JSON.parse(readFile2(p));
|
|
18547
|
+
} catch {
|
|
18548
|
+
return null;
|
|
18549
|
+
}
|
|
18550
|
+
}
|
|
18551
|
+
var TELEMETRY_DIR2 = ".kaddo/telemetry";
|
|
18552
|
+
var BUFFER_FILE = "buffer.json";
|
|
18553
|
+
function bufferPath(dir) {
|
|
18554
|
+
return join3(dir, TELEMETRY_DIR2, BUFFER_FILE);
|
|
18555
|
+
}
|
|
18556
|
+
function readBuffer(dir) {
|
|
18557
|
+
const p = bufferPath(dir);
|
|
18558
|
+
if (!exists2(p)) return [];
|
|
18559
|
+
try {
|
|
18560
|
+
const data = JSON.parse(readFile2(p));
|
|
18561
|
+
return Array.isArray(data) ? data : [];
|
|
18562
|
+
} catch {
|
|
18563
|
+
return [];
|
|
18564
|
+
}
|
|
18565
|
+
}
|
|
18566
|
+
function bufferSize(dir) {
|
|
18567
|
+
return readBuffer(dir).length;
|
|
18568
|
+
}
|
|
18569
|
+
function getStatus(dir) {
|
|
18570
|
+
const config = loadConfig2(dir);
|
|
18571
|
+
const consent = getConsentState(config);
|
|
18572
|
+
const enabled = consent === "enabled";
|
|
18573
|
+
const identity = loadIdentity(dir);
|
|
18574
|
+
return {
|
|
18575
|
+
consent,
|
|
18576
|
+
enabled,
|
|
18577
|
+
registered: identity?.registered ?? false,
|
|
18578
|
+
pendingEvents: enabled ? bufferSize(dir) : 0,
|
|
18579
|
+
lastError: null
|
|
18580
|
+
};
|
|
18581
|
+
}
|
|
18491
18582
|
|
|
18492
18583
|
// src/tools.ts
|
|
18493
18584
|
var ok = (data) => ({ ok: true, data });
|
|
@@ -18719,12 +18810,45 @@ function verifyWorkItemTool(root, args) {
|
|
|
18719
18810
|
return fail("Work Item verification failed.");
|
|
18720
18811
|
}
|
|
18721
18812
|
}
|
|
18813
|
+
function telemetryStatusTool(root) {
|
|
18814
|
+
const status = getStatus(root);
|
|
18815
|
+
const result = {
|
|
18816
|
+
consent: status.consent,
|
|
18817
|
+
registered: status.registered,
|
|
18818
|
+
pendingEvents: status.pendingEvents
|
|
18819
|
+
};
|
|
18820
|
+
if (status.consent === "unset" && !isDeferralActive(root)) {
|
|
18821
|
+
result.notice = consentNotice();
|
|
18822
|
+
}
|
|
18823
|
+
return ok(result);
|
|
18824
|
+
}
|
|
18825
|
+
function setTelemetryConsentTool(root, args) {
|
|
18826
|
+
const valid = ["enabled", "disabled", "not-now"];
|
|
18827
|
+
if (!valid.includes(args.consent)) {
|
|
18828
|
+
return fail(`consent must be one of: ${valid.join(", ")}`);
|
|
18829
|
+
}
|
|
18830
|
+
if (!args.confirm) {
|
|
18831
|
+
const preview = {
|
|
18832
|
+
action: args.consent,
|
|
18833
|
+
effect: args.consent === "enabled" ? "Anonymous usage telemetry will be activated. Kaddo will send command usage, version, and lifecycle events to telemetry.kaddo.org. No source code, knowledge, prompts or PII is ever transmitted." : args.consent === "disabled" ? "Telemetry will be permanently disabled. No data will be sent. Kaddo will not ask again." : "Consent decision deferred for 24 hours. Telemetry remains inactive. Kaddo will remind again after the deferral expires.",
|
|
18834
|
+
instruction: "Call again with confirm=true to apply."
|
|
18835
|
+
};
|
|
18836
|
+
return ok(preview);
|
|
18837
|
+
}
|
|
18838
|
+
if (args.consent === "not-now") {
|
|
18839
|
+
deferConsent(root);
|
|
18840
|
+
return ok({ applied: true, consent: "unset", deferred: true, message: "Consent deferred for 24 hours." });
|
|
18841
|
+
}
|
|
18842
|
+
const consent = args.consent;
|
|
18843
|
+
persistConsent(root, consent);
|
|
18844
|
+
return ok({ applied: true, consent, message: `Telemetry ${consent}.` });
|
|
18845
|
+
}
|
|
18722
18846
|
|
|
18723
18847
|
// src/multirepo.ts
|
|
18724
18848
|
import fs5 from "fs";
|
|
18725
18849
|
import path4 from "path";
|
|
18726
18850
|
import matter12 from "gray-matter";
|
|
18727
|
-
import { parse as parseYaml11, stringify as
|
|
18851
|
+
import { parse as parseYaml11, stringify as stringifyYaml7 } from "yaml";
|
|
18728
18852
|
var ok2 = (data) => ({ ok: true, data });
|
|
18729
18853
|
var fail2 = (message) => ({ ok: false, message });
|
|
18730
18854
|
function moduleRepoPath(m2) {
|
|
@@ -18733,7 +18857,7 @@ function moduleRepoPath(m2) {
|
|
|
18733
18857
|
function loadModulesDescriptor(root) {
|
|
18734
18858
|
return readYaml(root, ".kaddo/modules.yml") ?? { modules: [] };
|
|
18735
18859
|
}
|
|
18736
|
-
function
|
|
18860
|
+
function loadConfig4(root) {
|
|
18737
18861
|
return readYaml(root, ".kaddo/config.yml");
|
|
18738
18862
|
}
|
|
18739
18863
|
function projectRole2(config) {
|
|
@@ -18799,7 +18923,7 @@ function slugify3(s) {
|
|
|
18799
18923
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
18800
18924
|
}
|
|
18801
18925
|
function modulesListTool(root, args) {
|
|
18802
|
-
const config =
|
|
18926
|
+
const config = loadConfig4(root);
|
|
18803
18927
|
if (!config) return fail2("No Kaddo config found. Run `kaddo init` first.");
|
|
18804
18928
|
if (!isCore2(config)) return fail2("kaddo_modules_list can only be called from a core repository (project.role: core).");
|
|
18805
18929
|
const descriptor = loadModulesDescriptor(root);
|
|
@@ -18827,7 +18951,7 @@ function modulesListTool(root, args) {
|
|
|
18827
18951
|
});
|
|
18828
18952
|
}
|
|
18829
18953
|
function getModuleContextTool(root, args) {
|
|
18830
|
-
const config =
|
|
18954
|
+
const config = loadConfig4(root);
|
|
18831
18955
|
if (!config) return fail2("No Kaddo config found.");
|
|
18832
18956
|
const descriptor = loadModulesDescriptor(root);
|
|
18833
18957
|
const mod = (descriptor.modules ?? []).find((m2) => m2.id === args.module);
|
|
@@ -18921,7 +19045,7 @@ function validateWorkItemModulesTool(root, args) {
|
|
|
18921
19045
|
});
|
|
18922
19046
|
}
|
|
18923
19047
|
function getWorkItemContextTool(root, args) {
|
|
18924
|
-
const config =
|
|
19048
|
+
const config = loadConfig4(root);
|
|
18925
19049
|
if (!config) return fail2("No Kaddo config found.");
|
|
18926
19050
|
const items = listWorkItems(root);
|
|
18927
19051
|
const wi = items.find((w3) => w3.id === args.workItemId);
|
|
@@ -19027,7 +19151,7 @@ function suggestBranchStrategyTool(root, args) {
|
|
|
19027
19151
|
});
|
|
19028
19152
|
}
|
|
19029
19153
|
function exportCapsuleTool(root, args) {
|
|
19030
|
-
const config =
|
|
19154
|
+
const config = loadConfig4(root);
|
|
19031
19155
|
if (!config) return fail2("No Kaddo config found.");
|
|
19032
19156
|
const role = projectRole2(config);
|
|
19033
19157
|
const warnings = [];
|
|
@@ -19157,7 +19281,7 @@ function exportCapsuleTool(root, args) {
|
|
|
19157
19281
|
return ok2({ exported: true, type: capsuleType, module: args.module ?? void 0, paths: { json: jsonPath, md: mdPath }, warnings });
|
|
19158
19282
|
}
|
|
19159
19283
|
function modulesDiscoverTool(root, args) {
|
|
19160
|
-
const config =
|
|
19284
|
+
const config = loadConfig4(root);
|
|
19161
19285
|
if (!config) return fail2("No Kaddo config found.");
|
|
19162
19286
|
if (!isCore2(config)) return fail2("Module discovery is only available from a core repository.");
|
|
19163
19287
|
const sysName = config.system?.name ?? config.project?.name ?? "";
|
|
@@ -19214,7 +19338,7 @@ function modulesDiscoverTool(root, args) {
|
|
|
19214
19338
|
descriptor.modules.push({ id: d3.id, name: d3.id, path: d3.path, parent_system: sysName, status: "configured" });
|
|
19215
19339
|
}
|
|
19216
19340
|
}
|
|
19217
|
-
const ymlContent =
|
|
19341
|
+
const ymlContent = stringifyYaml7({ version: descriptor.version ?? 1, system: sysName, workspace_roots: workspaceRoots2, modules: descriptor.modules ?? [] });
|
|
19218
19342
|
writeDerived(root, ".kaddo/modules.yml", ymlContent);
|
|
19219
19343
|
return ok2({ discovered, applied: true });
|
|
19220
19344
|
}
|
|
@@ -19260,7 +19384,7 @@ ${list3(data.owners)}
|
|
|
19260
19384
|
}
|
|
19261
19385
|
|
|
19262
19386
|
// ../cli/src/core/system-topology.ts
|
|
19263
|
-
import { parse as parseYaml12, stringify as
|
|
19387
|
+
import { parse as parseYaml12, stringify as stringifyYaml8 } from "yaml";
|
|
19264
19388
|
import fs6 from "fs";
|
|
19265
19389
|
import path5 from "path";
|
|
19266
19390
|
import crypto from "crypto";
|
|
@@ -19775,7 +19899,7 @@ function systemImpactCandidatesTool(root, args) {
|
|
|
19775
19899
|
|
|
19776
19900
|
// ../cli/src/services/integrations.ts
|
|
19777
19901
|
import matter14 from "gray-matter";
|
|
19778
|
-
import { parse as parseYaml13, stringify as
|
|
19902
|
+
import { parse as parseYaml13, stringify as stringifyYaml9 } from "yaml";
|
|
19779
19903
|
|
|
19780
19904
|
// ../cli/src/core/work-item-write.ts
|
|
19781
19905
|
import fs7 from "fs";
|
|
@@ -22019,7 +22143,16 @@ function createServer(root) {
|
|
|
22019
22143
|
server.registerTool(
|
|
22020
22144
|
"kaddo_project_status",
|
|
22021
22145
|
{ title: "Kaddo project status", description: "Compact project status (state, phase, work items, ownership, graph quality, capsules).", inputSchema: {} },
|
|
22022
|
-
async () =>
|
|
22146
|
+
async () => {
|
|
22147
|
+
const result = guarded(root, () => projectStatus(root));
|
|
22148
|
+
if (result.ok) {
|
|
22149
|
+
const config = loadConfig2(root);
|
|
22150
|
+
if (getConsentState(config) === "unset" && !isDeferralActive(root)) {
|
|
22151
|
+
result.data.telemetryNotice = consentNotice();
|
|
22152
|
+
}
|
|
22153
|
+
}
|
|
22154
|
+
return toolText(result);
|
|
22155
|
+
}
|
|
22023
22156
|
);
|
|
22024
22157
|
server.registerTool(
|
|
22025
22158
|
"kaddo_list_work_items",
|
|
@@ -22344,6 +22477,27 @@ function createServer(root) {
|
|
|
22344
22477
|
},
|
|
22345
22478
|
async (args) => toolText(guarded(root, () => verifyWorkItemTool(root, args)))
|
|
22346
22479
|
);
|
|
22480
|
+
server.registerTool(
|
|
22481
|
+
"kaddo_telemetry_status",
|
|
22482
|
+
{
|
|
22483
|
+
title: "Telemetry status",
|
|
22484
|
+
description: "Read-only telemetry consent state, registration status, and pending events. Includes a consent notice when telemetry has not been configured.",
|
|
22485
|
+
inputSchema: {}
|
|
22486
|
+
},
|
|
22487
|
+
async () => toolText(guarded(root, () => telemetryStatusTool(root)))
|
|
22488
|
+
);
|
|
22489
|
+
server.registerTool(
|
|
22490
|
+
"kaddo_set_telemetry_consent",
|
|
22491
|
+
{
|
|
22492
|
+
title: "Set telemetry consent",
|
|
22493
|
+
description: "Set telemetry consent to enabled, disabled, or not-now (defer 24h). Without confirm=true returns a preview of the action. With confirm=true applies the change. Writes only .kaddo/config.yml (consent field).",
|
|
22494
|
+
inputSchema: {
|
|
22495
|
+
consent: z4.enum(["enabled", "disabled", "not-now"]).describe("Consent decision: enable telemetry, disable it, or defer for 24 hours"),
|
|
22496
|
+
confirm: z4.boolean().optional().describe("Must be true to apply the change")
|
|
22497
|
+
}
|
|
22498
|
+
},
|
|
22499
|
+
async (args) => toolText(guarded(root, () => setTelemetryConsentTool(root, args)))
|
|
22500
|
+
);
|
|
22347
22501
|
let installedSkills = [];
|
|
22348
22502
|
try {
|
|
22349
22503
|
assertKaddoProject(root);
|
package/package.json
CHANGED