contract-driven-delivery 2.0.21 → 2.1.1
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/CHANGELOG.md +42 -0
- package/README.md +45 -0
- package/assets/agents/bug-fix-engineer.md +97 -0
- package/assets/agents/change-classifier.md +1 -1
- package/assets/agents/frontend-engineer.md +4 -4
- package/assets/agents/qa-reviewer.md +1 -1
- package/assets/cdd/model-policy.json +1 -0
- package/assets/code-map/python_scanner.py +39 -0
- package/assets/skills/cdd-new/SKILL.md +5 -2
- package/assets/skills/contract-driven-delivery/references/code-map-protocol.md +24 -2
- package/dist/cli/index.js +1456 -146
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2774,7 +2774,7 @@ var require_fast_deep_equal = __commonJS({
|
|
|
2774
2774
|
var require_json_schema_traverse = __commonJS({
|
|
2775
2775
|
"node_modules/json-schema-traverse/index.js"(exports, module) {
|
|
2776
2776
|
"use strict";
|
|
2777
|
-
var
|
|
2777
|
+
var traverse2 = module.exports = function(schema, opts, cb) {
|
|
2778
2778
|
if (typeof opts == "function") {
|
|
2779
2779
|
cb = opts;
|
|
2780
2780
|
opts = {};
|
|
@@ -2786,7 +2786,7 @@ var require_json_schema_traverse = __commonJS({
|
|
|
2786
2786
|
};
|
|
2787
2787
|
_traverse(opts, pre, post, schema, "", schema);
|
|
2788
2788
|
};
|
|
2789
|
-
|
|
2789
|
+
traverse2.keywords = {
|
|
2790
2790
|
additionalItems: true,
|
|
2791
2791
|
items: true,
|
|
2792
2792
|
contains: true,
|
|
@@ -2797,20 +2797,20 @@ var require_json_schema_traverse = __commonJS({
|
|
|
2797
2797
|
then: true,
|
|
2798
2798
|
else: true
|
|
2799
2799
|
};
|
|
2800
|
-
|
|
2800
|
+
traverse2.arrayKeywords = {
|
|
2801
2801
|
items: true,
|
|
2802
2802
|
allOf: true,
|
|
2803
2803
|
anyOf: true,
|
|
2804
2804
|
oneOf: true
|
|
2805
2805
|
};
|
|
2806
|
-
|
|
2806
|
+
traverse2.propsKeywords = {
|
|
2807
2807
|
$defs: true,
|
|
2808
2808
|
definitions: true,
|
|
2809
2809
|
properties: true,
|
|
2810
2810
|
patternProperties: true,
|
|
2811
2811
|
dependencies: true
|
|
2812
2812
|
};
|
|
2813
|
-
|
|
2813
|
+
traverse2.skipKeywords = {
|
|
2814
2814
|
default: true,
|
|
2815
2815
|
enum: true,
|
|
2816
2816
|
const: true,
|
|
@@ -2836,16 +2836,16 @@ var require_json_schema_traverse = __commonJS({
|
|
|
2836
2836
|
for (var key in schema) {
|
|
2837
2837
|
var sch = schema[key];
|
|
2838
2838
|
if (Array.isArray(sch)) {
|
|
2839
|
-
if (key in
|
|
2839
|
+
if (key in traverse2.arrayKeywords) {
|
|
2840
2840
|
for (var i = 0; i < sch.length; i++)
|
|
2841
2841
|
_traverse(opts, pre, post, sch[i], jsonPtr + "/" + key + "/" + i, rootSchema, jsonPtr, key, schema, i);
|
|
2842
2842
|
}
|
|
2843
|
-
} else if (key in
|
|
2843
|
+
} else if (key in traverse2.propsKeywords) {
|
|
2844
2844
|
if (sch && typeof sch == "object") {
|
|
2845
2845
|
for (var prop in sch)
|
|
2846
2846
|
_traverse(opts, pre, post, sch[prop], jsonPtr + "/" + key + "/" + escapeJsonPtr(prop), rootSchema, jsonPtr, key, schema, prop);
|
|
2847
2847
|
}
|
|
2848
|
-
} else if (key in
|
|
2848
|
+
} else if (key in traverse2.keywords || opts.allKeys && !(key in traverse2.skipKeywords)) {
|
|
2849
2849
|
_traverse(opts, pre, post, sch, jsonPtr + "/" + key, rootSchema, jsonPtr, key, schema);
|
|
2850
2850
|
}
|
|
2851
2851
|
}
|
|
@@ -2866,7 +2866,7 @@ var require_resolve = __commonJS({
|
|
|
2866
2866
|
exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = void 0;
|
|
2867
2867
|
var util_1 = require_util();
|
|
2868
2868
|
var equal = require_fast_deep_equal();
|
|
2869
|
-
var
|
|
2869
|
+
var traverse2 = require_json_schema_traverse();
|
|
2870
2870
|
var SIMPLE_INLINED = /* @__PURE__ */ new Set([
|
|
2871
2871
|
"type",
|
|
2872
2872
|
"format",
|
|
@@ -2962,7 +2962,7 @@ var require_resolve = __commonJS({
|
|
|
2962
2962
|
const pathPrefix = getFullPath(uriResolver, schId, false);
|
|
2963
2963
|
const localRefs = {};
|
|
2964
2964
|
const schemaRefs = /* @__PURE__ */ new Set();
|
|
2965
|
-
|
|
2965
|
+
traverse2(schema, { allKeys: true }, (sch, jsonPtr, _, parentJsonPtr) => {
|
|
2966
2966
|
if (parentJsonPtr === void 0)
|
|
2967
2967
|
return;
|
|
2968
2968
|
const fullPath = pathPrefix + jsonPtr;
|
|
@@ -8608,6 +8608,351 @@ var init_index_reader = __esm({
|
|
|
8608
8608
|
}
|
|
8609
8609
|
});
|
|
8610
8610
|
|
|
8611
|
+
// src/code-graph/builder.ts
|
|
8612
|
+
import { createHash as createHash5 } from "crypto";
|
|
8613
|
+
import { posix } from "path";
|
|
8614
|
+
function stableId(parts) {
|
|
8615
|
+
return createHash5("sha1").update(parts.join("\0")).digest("hex").slice(0, 16);
|
|
8616
|
+
}
|
|
8617
|
+
function nodeId(filePath, kind, name, startLine) {
|
|
8618
|
+
return `n:${stableId([filePath, kind, name, String(startLine)])}`;
|
|
8619
|
+
}
|
|
8620
|
+
function edgeId(source, target, kind, line, name) {
|
|
8621
|
+
return `e:${stableId([source, target, kind, String(line ?? 0), name ?? ""])}`;
|
|
8622
|
+
}
|
|
8623
|
+
function fileNode(path, totalLines) {
|
|
8624
|
+
return {
|
|
8625
|
+
id: nodeId(path, "file", path, 1),
|
|
8626
|
+
kind: "file",
|
|
8627
|
+
name: posix.basename(path),
|
|
8628
|
+
qualified_name: path,
|
|
8629
|
+
file_path: path,
|
|
8630
|
+
start_line: totalLines > 0 ? 1 : 0,
|
|
8631
|
+
end_line: totalLines
|
|
8632
|
+
};
|
|
8633
|
+
}
|
|
8634
|
+
function symbolNode(filePath, kind, name, lines, exported) {
|
|
8635
|
+
const start = lines[0] ?? 1;
|
|
8636
|
+
const end = lines[1] ?? start;
|
|
8637
|
+
return {
|
|
8638
|
+
id: nodeId(filePath, kind, name, start),
|
|
8639
|
+
kind,
|
|
8640
|
+
name,
|
|
8641
|
+
qualified_name: `${filePath}::${name}`,
|
|
8642
|
+
file_path: filePath,
|
|
8643
|
+
start_line: start,
|
|
8644
|
+
end_line: end,
|
|
8645
|
+
...exported !== void 0 ? { exported } : {}
|
|
8646
|
+
};
|
|
8647
|
+
}
|
|
8648
|
+
function addEdge(edges, source, target, kind, line, provenance, metadata) {
|
|
8649
|
+
edges.push({
|
|
8650
|
+
id: edgeId(source, target, kind, line, metadata?.name),
|
|
8651
|
+
source,
|
|
8652
|
+
target,
|
|
8653
|
+
kind,
|
|
8654
|
+
...line ? { line } : {},
|
|
8655
|
+
provenance,
|
|
8656
|
+
...metadata ? { metadata } : {}
|
|
8657
|
+
});
|
|
8658
|
+
}
|
|
8659
|
+
function isLocalImport(moduleName) {
|
|
8660
|
+
return moduleName.startsWith(".");
|
|
8661
|
+
}
|
|
8662
|
+
function resolvePythonRelativeImport(importerPath, moduleName) {
|
|
8663
|
+
const match = moduleName.match(/^(\.+)(.*)$/);
|
|
8664
|
+
if (!match)
|
|
8665
|
+
return moduleName;
|
|
8666
|
+
const upLevels = Math.max(0, match[1].length - 1);
|
|
8667
|
+
let baseDir = posix.dirname(importerPath);
|
|
8668
|
+
for (let i = 0; i < upLevels; i++) {
|
|
8669
|
+
baseDir = posix.dirname(baseDir);
|
|
8670
|
+
}
|
|
8671
|
+
const rest = match[2].replace(/^\./, "").replace(/\./g, "/");
|
|
8672
|
+
return rest ? posix.normalize(posix.join(baseDir, rest)) : baseDir;
|
|
8673
|
+
}
|
|
8674
|
+
function resolutionCandidates(base) {
|
|
8675
|
+
const ext = posix.extname(base);
|
|
8676
|
+
const candidates = [];
|
|
8677
|
+
if (ext) {
|
|
8678
|
+
candidates.push(base);
|
|
8679
|
+
const withoutExt = base.slice(0, -ext.length);
|
|
8680
|
+
if ([".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
|
|
8681
|
+
candidates.push(`${withoutExt}.ts`, `${withoutExt}.tsx`, `${withoutExt}.vue`);
|
|
8682
|
+
}
|
|
8683
|
+
} else {
|
|
8684
|
+
for (const candidateExt of RESOLUTION_EXTENSIONS) {
|
|
8685
|
+
candidates.push(`${base}${candidateExt}`);
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8688
|
+
for (const candidateExt of RESOLUTION_EXTENSIONS) {
|
|
8689
|
+
candidates.push(posix.join(base, `index${candidateExt}`));
|
|
8690
|
+
}
|
|
8691
|
+
candidates.push(posix.join(base, "__init__.py"));
|
|
8692
|
+
return [...new Set(candidates)];
|
|
8693
|
+
}
|
|
8694
|
+
function resolveLocalModule(importerPath, moduleName, pathSet) {
|
|
8695
|
+
if (!isLocalImport(moduleName))
|
|
8696
|
+
return void 0;
|
|
8697
|
+
const base = moduleName.startsWith("./") || moduleName.startsWith("../") ? posix.normalize(posix.join(posix.dirname(importerPath), moduleName)) : resolvePythonRelativeImport(importerPath, moduleName);
|
|
8698
|
+
for (const candidate of resolutionCandidates(base)) {
|
|
8699
|
+
if (pathSet.has(candidate))
|
|
8700
|
+
return candidate;
|
|
8701
|
+
}
|
|
8702
|
+
return void 0;
|
|
8703
|
+
}
|
|
8704
|
+
function importedBindings(imp, resolvedPath) {
|
|
8705
|
+
const out = [];
|
|
8706
|
+
for (const item of imp.items ?? []) {
|
|
8707
|
+
if (item.startsWith("default:")) {
|
|
8708
|
+
const local = item.slice("default:".length);
|
|
8709
|
+
out.push({ local, imported: "default", ...resolvedPath ? { resolvedPath } : {} });
|
|
8710
|
+
} else if (item.startsWith("*:")) {
|
|
8711
|
+
const local = item.slice("*:".length);
|
|
8712
|
+
out.push({ local, imported: "*", ...resolvedPath ? { resolvedPath } : {} });
|
|
8713
|
+
} else if (/^[A-Za-z_$][\w$]*:[A-Za-z_$][\w$]*$/.test(item)) {
|
|
8714
|
+
const [imported, local] = item.split(":");
|
|
8715
|
+
out.push({ local, imported, ...resolvedPath ? { resolvedPath } : {} });
|
|
8716
|
+
} else {
|
|
8717
|
+
out.push({ local: item, imported: item, ...resolvedPath ? { resolvedPath } : {} });
|
|
8718
|
+
}
|
|
8719
|
+
}
|
|
8720
|
+
return out;
|
|
8721
|
+
}
|
|
8722
|
+
function simpleName(name) {
|
|
8723
|
+
return name.replace(/^async\s+/, "").split(".").pop() ?? name;
|
|
8724
|
+
}
|
|
8725
|
+
function isWithin(node, line) {
|
|
8726
|
+
return node.start_line <= line && line <= node.end_line;
|
|
8727
|
+
}
|
|
8728
|
+
function findCallerNode(nodes, caller, line) {
|
|
8729
|
+
const exact = nodes.find((n) => n.name === caller || n.qualified_name.endsWith(`::${caller}`));
|
|
8730
|
+
if (exact)
|
|
8731
|
+
return exact;
|
|
8732
|
+
return nodes.filter((n) => (n.kind === "function" || n.kind === "method") && isWithin(n, line)).sort((a, b) => a.end_line - a.start_line - (b.end_line - b.start_line))[0];
|
|
8733
|
+
}
|
|
8734
|
+
function buildCodeGraph(entries, opts) {
|
|
8735
|
+
const nodes = [];
|
|
8736
|
+
const edges = [];
|
|
8737
|
+
const unresolved = [];
|
|
8738
|
+
const files = [];
|
|
8739
|
+
const pathSet = new Set(entries.map((e) => e.path));
|
|
8740
|
+
const fileNodes = /* @__PURE__ */ new Map();
|
|
8741
|
+
const nodesByFile = /* @__PURE__ */ new Map();
|
|
8742
|
+
const symbolsByFile = /* @__PURE__ */ new Map();
|
|
8743
|
+
const globalSymbols = /* @__PURE__ */ new Map();
|
|
8744
|
+
const registerSymbol = (filePath, node, exported) => {
|
|
8745
|
+
nodes.push(node);
|
|
8746
|
+
const fileMap = symbolsByFile.get(filePath) ?? /* @__PURE__ */ new Map();
|
|
8747
|
+
const target = { node, exported };
|
|
8748
|
+
fileMap.set(node.name, [...fileMap.get(node.name) ?? [], target]);
|
|
8749
|
+
const shortName = simpleName(node.name);
|
|
8750
|
+
if (shortName !== node.name) {
|
|
8751
|
+
fileMap.set(shortName, [...fileMap.get(shortName) ?? [], target]);
|
|
8752
|
+
}
|
|
8753
|
+
symbolsByFile.set(filePath, fileMap);
|
|
8754
|
+
globalSymbols.set(node.name, [...globalSymbols.get(node.name) ?? [], target]);
|
|
8755
|
+
if (shortName !== node.name) {
|
|
8756
|
+
globalSymbols.set(shortName, [...globalSymbols.get(shortName) ?? [], target]);
|
|
8757
|
+
}
|
|
8758
|
+
};
|
|
8759
|
+
for (const entry of entries) {
|
|
8760
|
+
const file = fileNode(entry.path, entry.total_lines);
|
|
8761
|
+
fileNodes.set(entry.path, file);
|
|
8762
|
+
nodesByFile.set(entry.path, [file]);
|
|
8763
|
+
nodes.push(file);
|
|
8764
|
+
}
|
|
8765
|
+
for (const entry of entries) {
|
|
8766
|
+
const file = fileNodes.get(entry.path);
|
|
8767
|
+
const localNodes = nodesByFile.get(entry.path);
|
|
8768
|
+
for (const c of entry.classes) {
|
|
8769
|
+
const n = symbolNode(entry.path, "class", c.name, c.lines, c.exported);
|
|
8770
|
+
localNodes.push(n);
|
|
8771
|
+
registerSymbol(entry.path, n, c.exported === true);
|
|
8772
|
+
addEdge(edges, file.id, n.id, "contains", c.lines[0], "codemap");
|
|
8773
|
+
for (const m of c.methods ?? []) {
|
|
8774
|
+
const methodName = `${c.name}.${m.name}`;
|
|
8775
|
+
const mn = symbolNode(entry.path, "method", methodName, m.lines);
|
|
8776
|
+
localNodes.push(mn);
|
|
8777
|
+
registerSymbol(entry.path, mn, false);
|
|
8778
|
+
addEdge(edges, n.id, mn.id, "contains", m.lines[0], "codemap");
|
|
8779
|
+
}
|
|
8780
|
+
}
|
|
8781
|
+
for (const f of entry.functions) {
|
|
8782
|
+
const n = symbolNode(entry.path, "function", f.name, f.lines, f.exported);
|
|
8783
|
+
localNodes.push(n);
|
|
8784
|
+
registerSymbol(entry.path, n, f.exported === true);
|
|
8785
|
+
addEdge(edges, file.id, n.id, "contains", f.lines[0], "codemap");
|
|
8786
|
+
}
|
|
8787
|
+
for (const t of entry.interfaces ?? []) {
|
|
8788
|
+
const n = symbolNode(entry.path, "interface", t.name, t.lines, t.exported);
|
|
8789
|
+
localNodes.push(n);
|
|
8790
|
+
registerSymbol(entry.path, n, t.exported === true);
|
|
8791
|
+
addEdge(edges, file.id, n.id, "contains", t.lines[0], "codemap");
|
|
8792
|
+
}
|
|
8793
|
+
for (const t of entry.types ?? []) {
|
|
8794
|
+
const n = symbolNode(entry.path, "type_alias", t.name, t.lines, t.exported);
|
|
8795
|
+
localNodes.push(n);
|
|
8796
|
+
registerSymbol(entry.path, n, t.exported === true);
|
|
8797
|
+
addEdge(edges, file.id, n.id, "contains", t.lines[0], "codemap");
|
|
8798
|
+
}
|
|
8799
|
+
for (const e of entry.enums ?? []) {
|
|
8800
|
+
const n = symbolNode(entry.path, "enum", e.name, e.lines, e.exported);
|
|
8801
|
+
localNodes.push(n);
|
|
8802
|
+
registerSymbol(entry.path, n, e.exported === true);
|
|
8803
|
+
addEdge(edges, file.id, n.id, "contains", e.lines[0], "codemap");
|
|
8804
|
+
}
|
|
8805
|
+
for (const c of entry.constants) {
|
|
8806
|
+
const n = symbolNode(entry.path, "constant", c.name, [c.line, c.line], true);
|
|
8807
|
+
localNodes.push(n);
|
|
8808
|
+
registerSymbol(entry.path, n, true);
|
|
8809
|
+
addEdge(edges, file.id, n.id, "contains", c.line, "codemap");
|
|
8810
|
+
}
|
|
8811
|
+
}
|
|
8812
|
+
const importBindingsByFile = /* @__PURE__ */ new Map();
|
|
8813
|
+
for (const entry of entries) {
|
|
8814
|
+
const file = fileNodes.get(entry.path);
|
|
8815
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
8816
|
+
importBindingsByFile.set(entry.path, bindings);
|
|
8817
|
+
for (const imp of entry.imports) {
|
|
8818
|
+
const resolved = resolveLocalModule(entry.path, imp.module, pathSet);
|
|
8819
|
+
if (resolved) {
|
|
8820
|
+
addEdge(edges, file.id, fileNodes.get(resolved).id, "imports", imp.line, "ast", { module: imp.module });
|
|
8821
|
+
}
|
|
8822
|
+
for (const binding of importedBindings(imp, resolved)) {
|
|
8823
|
+
if (!binding.resolvedPath)
|
|
8824
|
+
continue;
|
|
8825
|
+
const fileSymbols = symbolsByFile.get(binding.resolvedPath);
|
|
8826
|
+
const candidates = binding.imported === "*" ? Array.from(fileSymbols?.values() ?? []).flat() : fileSymbols?.get(binding.imported) ?? [];
|
|
8827
|
+
const exported = candidates.filter((c) => c.exported || candidates.length === 1);
|
|
8828
|
+
if (exported.length > 0) {
|
|
8829
|
+
bindings.set(binding.local, [...bindings.get(binding.local) ?? [], ...exported]);
|
|
8830
|
+
}
|
|
8831
|
+
}
|
|
8832
|
+
}
|
|
8833
|
+
}
|
|
8834
|
+
for (const entry of entries) {
|
|
8835
|
+
const localNodes = nodesByFile.get(entry.path) ?? [];
|
|
8836
|
+
const localSymbols = symbolsByFile.get(entry.path) ?? /* @__PURE__ */ new Map();
|
|
8837
|
+
const importBindings = importBindingsByFile.get(entry.path) ?? /* @__PURE__ */ new Map();
|
|
8838
|
+
for (const c of entry.classes) {
|
|
8839
|
+
const source = localSymbols.get(c.name)?.[0]?.node;
|
|
8840
|
+
if (!source)
|
|
8841
|
+
continue;
|
|
8842
|
+
for (const base of c.extends ?? []) {
|
|
8843
|
+
const target = resolveSymbol(base, entry.path, localSymbols, importBindings, globalSymbols);
|
|
8844
|
+
if (target)
|
|
8845
|
+
addEdge(edges, source.id, target.node.id, "extends", c.lines[0], "ast", { name: base });
|
|
8846
|
+
else
|
|
8847
|
+
unresolved.push({ from: source.id, kind: "extends", name: base, line: c.lines[0], file_path: entry.path });
|
|
8848
|
+
}
|
|
8849
|
+
for (const iface of c.implements ?? []) {
|
|
8850
|
+
const target = resolveSymbol(iface, entry.path, localSymbols, importBindings, globalSymbols);
|
|
8851
|
+
if (target)
|
|
8852
|
+
addEdge(edges, source.id, target.node.id, "implements", c.lines[0], "ast", { name: iface });
|
|
8853
|
+
else
|
|
8854
|
+
unresolved.push({ from: source.id, kind: "implements", name: iface, line: c.lines[0], file_path: entry.path });
|
|
8855
|
+
}
|
|
8856
|
+
}
|
|
8857
|
+
for (const call of entry.calls ?? []) {
|
|
8858
|
+
const caller = findCallerNode(localNodes, call.caller, call.line);
|
|
8859
|
+
if (!caller)
|
|
8860
|
+
continue;
|
|
8861
|
+
const target = resolveSymbol(call.callee, entry.path, localSymbols, importBindings, globalSymbols);
|
|
8862
|
+
if (target) {
|
|
8863
|
+
addEdge(edges, caller.id, target.node.id, "calls", call.line, "ast", { name: call.callee });
|
|
8864
|
+
} else {
|
|
8865
|
+
unresolved.push({ from: caller.id, kind: "calls", name: call.callee, line: call.line, file_path: entry.path });
|
|
8866
|
+
}
|
|
8867
|
+
}
|
|
8868
|
+
}
|
|
8869
|
+
const uniqueNodes = dedupeBy(nodes, (n) => n.id);
|
|
8870
|
+
const uniqueEdges = dedupeBy(edges, (e) => e.id);
|
|
8871
|
+
for (const entry of entries) {
|
|
8872
|
+
files.push({
|
|
8873
|
+
path: entry.path,
|
|
8874
|
+
total_lines: entry.total_lines,
|
|
8875
|
+
node_count: uniqueNodes.filter((n) => n.file_path === entry.path).length
|
|
8876
|
+
});
|
|
8877
|
+
}
|
|
8878
|
+
return {
|
|
8879
|
+
schema_version: "1.0",
|
|
8880
|
+
generator: opts.generator,
|
|
8881
|
+
sources_digest: opts.sourcesDigest,
|
|
8882
|
+
files,
|
|
8883
|
+
nodes: uniqueNodes.sort((a, b) => a.file_path.localeCompare(b.file_path) || a.start_line - b.start_line || a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name)),
|
|
8884
|
+
edges: uniqueEdges.sort((a, b) => a.source.localeCompare(b.source) || a.kind.localeCompare(b.kind) || a.target.localeCompare(b.target)),
|
|
8885
|
+
unresolved: unresolved.sort((a, b) => a.file_path.localeCompare(b.file_path) || a.line - b.line || a.name.localeCompare(b.name))
|
|
8886
|
+
};
|
|
8887
|
+
}
|
|
8888
|
+
function resolveSymbol(rawName, filePath, localSymbols, importBindings, globalSymbols) {
|
|
8889
|
+
const candidates = symbolLookupNames(rawName);
|
|
8890
|
+
for (const name of candidates) {
|
|
8891
|
+
const imported = importBindings.get(name);
|
|
8892
|
+
if (imported?.length === 1)
|
|
8893
|
+
return imported[0];
|
|
8894
|
+
}
|
|
8895
|
+
for (const name of candidates) {
|
|
8896
|
+
const local = localSymbols.get(name);
|
|
8897
|
+
if (local?.length === 1)
|
|
8898
|
+
return local[0];
|
|
8899
|
+
}
|
|
8900
|
+
for (const name of candidates) {
|
|
8901
|
+
const global = (globalSymbols.get(name) ?? []).filter((t) => t.node.file_path !== filePath || t.exported);
|
|
8902
|
+
if (global.length === 1)
|
|
8903
|
+
return global[0];
|
|
8904
|
+
}
|
|
8905
|
+
return void 0;
|
|
8906
|
+
}
|
|
8907
|
+
function symbolLookupNames(name) {
|
|
8908
|
+
const cleaned = name.replace(/^this\./, "").replace(/^self\./, "");
|
|
8909
|
+
const parts = cleaned.split(".").filter(Boolean);
|
|
8910
|
+
return [.../* @__PURE__ */ new Set([cleaned, parts[parts.length - 1] ?? cleaned])];
|
|
8911
|
+
}
|
|
8912
|
+
function dedupeBy(items, key) {
|
|
8913
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8914
|
+
const out = [];
|
|
8915
|
+
for (const item of items) {
|
|
8916
|
+
const k = key(item);
|
|
8917
|
+
if (seen.has(k))
|
|
8918
|
+
continue;
|
|
8919
|
+
seen.add(k);
|
|
8920
|
+
out.push(item);
|
|
8921
|
+
}
|
|
8922
|
+
return out;
|
|
8923
|
+
}
|
|
8924
|
+
var RESOLUTION_EXTENSIONS;
|
|
8925
|
+
var init_builder = __esm({
|
|
8926
|
+
"src/code-graph/builder.ts"() {
|
|
8927
|
+
"use strict";
|
|
8928
|
+
RESOLUTION_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".vue", ".py"];
|
|
8929
|
+
}
|
|
8930
|
+
});
|
|
8931
|
+
|
|
8932
|
+
// src/code-graph/reader.ts
|
|
8933
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
|
|
8934
|
+
function graphPathFor(mapPath) {
|
|
8935
|
+
const match = mapPath.match(/^(.*?)(?:code-map)(.*)\.ya?ml$/i);
|
|
8936
|
+
if (match)
|
|
8937
|
+
return `${match[1]}code-graph${match[2]}.index.json`;
|
|
8938
|
+
return `${mapPath.replace(/\.ya?ml$/i, "")}.graph.json`;
|
|
8939
|
+
}
|
|
8940
|
+
function loadCodeGraph(graphPath) {
|
|
8941
|
+
if (!existsSync18(graphPath)) {
|
|
8942
|
+
throw new Error(`${graphPath} is missing; run \`cdd-kit code-map\` first.`);
|
|
8943
|
+
}
|
|
8944
|
+
const raw = JSON.parse(readFileSync17(graphPath, "utf8"));
|
|
8945
|
+
if (!raw || raw.schema_version !== "1.0" || !Array.isArray(raw.nodes) || !Array.isArray(raw.edges)) {
|
|
8946
|
+
throw new Error(`${graphPath} is not a cdd-kit code graph v1 index.`);
|
|
8947
|
+
}
|
|
8948
|
+
return raw;
|
|
8949
|
+
}
|
|
8950
|
+
var init_reader = __esm({
|
|
8951
|
+
"src/code-graph/reader.ts"() {
|
|
8952
|
+
"use strict";
|
|
8953
|
+
}
|
|
8954
|
+
});
|
|
8955
|
+
|
|
8611
8956
|
// src/code-map/worker-dispatch.ts
|
|
8612
8957
|
var worker_dispatch_exports = {};
|
|
8613
8958
|
__export(worker_dispatch_exports, {
|
|
@@ -8864,14 +9209,20 @@ var init_python = __esm({
|
|
|
8864
9209
|
name: m.name,
|
|
8865
9210
|
lines: [m.lines[0], m.lines[1]],
|
|
8866
9211
|
async: m.async
|
|
8867
|
-
}))
|
|
9212
|
+
})),
|
|
9213
|
+
extends: c.extends ?? [],
|
|
9214
|
+
implements: c.implements ?? [],
|
|
9215
|
+
exported: c.exported
|
|
8868
9216
|
})),
|
|
8869
9217
|
functions: (r.functions ?? []).map((f) => ({
|
|
8870
9218
|
name: f.name,
|
|
8871
9219
|
lines: [f.lines[0], f.lines[1]],
|
|
8872
9220
|
decorators: f.decorators ?? [],
|
|
8873
|
-
async: f.async
|
|
8874
|
-
|
|
9221
|
+
async: f.async,
|
|
9222
|
+
exported: f.exported
|
|
9223
|
+
})),
|
|
9224
|
+
calls: r.calls ?? [],
|
|
9225
|
+
exports: r.exports ?? []
|
|
8875
9226
|
});
|
|
8876
9227
|
}
|
|
8877
9228
|
if (exitCode === 2) {
|
|
@@ -8897,7 +9248,7 @@ __export(javascript_exports, {
|
|
|
8897
9248
|
parseJsSource: () => parseJsSource,
|
|
8898
9249
|
parseSourceWithPlugins: () => parseSourceWithPlugins
|
|
8899
9250
|
});
|
|
8900
|
-
import { readFileSync as
|
|
9251
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
8901
9252
|
import { parse } from "@babel/parser";
|
|
8902
9253
|
function parseSourceWithPlugins(source, plugins) {
|
|
8903
9254
|
return parse(source, {
|
|
@@ -8930,6 +9281,51 @@ function getLineRange(node) {
|
|
|
8930
9281
|
const end = node.loc?.end.line ?? start;
|
|
8931
9282
|
return [start, end];
|
|
8932
9283
|
}
|
|
9284
|
+
function expressionName(node) {
|
|
9285
|
+
if (!node)
|
|
9286
|
+
return null;
|
|
9287
|
+
if (node.type === "Identifier")
|
|
9288
|
+
return node.name;
|
|
9289
|
+
if (node.type === "ThisExpression")
|
|
9290
|
+
return "this";
|
|
9291
|
+
if (node.type === "Super")
|
|
9292
|
+
return "super";
|
|
9293
|
+
if (node.type === "PrivateName")
|
|
9294
|
+
return `#${node.id?.name ?? "private"}`;
|
|
9295
|
+
if (node.type === "StringLiteral")
|
|
9296
|
+
return node.value;
|
|
9297
|
+
if (node.type === "MemberExpression" || node.type === "OptionalMemberExpression") {
|
|
9298
|
+
const object = expressionName(node.object);
|
|
9299
|
+
const prop = node.computed ? expressionName(node.property) : expressionName(node.property);
|
|
9300
|
+
if (object && prop)
|
|
9301
|
+
return `${object}.${prop}`;
|
|
9302
|
+
return prop ?? object;
|
|
9303
|
+
}
|
|
9304
|
+
if (node.type === "CallExpression" || node.type === "OptionalCallExpression")
|
|
9305
|
+
return expressionName(node.callee);
|
|
9306
|
+
if (node.type === "TSExpressionWithTypeArguments")
|
|
9307
|
+
return expressionName(node.expression);
|
|
9308
|
+
return null;
|
|
9309
|
+
}
|
|
9310
|
+
function collectCalls(node, caller, calls) {
|
|
9311
|
+
if (!node || typeof node !== "object")
|
|
9312
|
+
return;
|
|
9313
|
+
if (node.type === "CallExpression" || node.type === "OptionalCallExpression" || node.type === "NewExpression") {
|
|
9314
|
+
const callee = expressionName(node.callee);
|
|
9315
|
+
if (callee)
|
|
9316
|
+
calls.push({ caller, callee, line: node.loc?.start.line ?? 1 });
|
|
9317
|
+
}
|
|
9318
|
+
for (const value of Object.values(node)) {
|
|
9319
|
+
if (!value)
|
|
9320
|
+
continue;
|
|
9321
|
+
if (Array.isArray(value)) {
|
|
9322
|
+
for (const item of value)
|
|
9323
|
+
collectCalls(item, caller, calls);
|
|
9324
|
+
} else if (typeof value === "object" && "type" in value) {
|
|
9325
|
+
collectCalls(value, caller, calls);
|
|
9326
|
+
}
|
|
9327
|
+
}
|
|
9328
|
+
}
|
|
8933
9329
|
function processImportDeclaration(node) {
|
|
8934
9330
|
const items = [];
|
|
8935
9331
|
for (const spec of node.specifiers) {
|
|
@@ -8939,7 +9335,8 @@ function processImportDeclaration(node) {
|
|
|
8939
9335
|
items.push(`*:${spec.local.name}`);
|
|
8940
9336
|
} else if (spec.type === "ImportSpecifier") {
|
|
8941
9337
|
const imported = spec.imported;
|
|
8942
|
-
|
|
9338
|
+
const importedName = imported.type === "Identifier" ? imported.name : imported.value;
|
|
9339
|
+
items.push(spec.local.name !== importedName ? `${importedName}:${spec.local.name}` : importedName);
|
|
8943
9340
|
}
|
|
8944
9341
|
}
|
|
8945
9342
|
return {
|
|
@@ -8948,7 +9345,7 @@ function processImportDeclaration(node) {
|
|
|
8948
9345
|
line: node.loc?.start.line ?? 1
|
|
8949
9346
|
};
|
|
8950
9347
|
}
|
|
8951
|
-
function processFunctionDeclaration(node, nameOverride) {
|
|
9348
|
+
function processFunctionDeclaration(node, nameOverride, exported = false) {
|
|
8952
9349
|
const name = nameOverride ?? node.id?.name;
|
|
8953
9350
|
if (!name)
|
|
8954
9351
|
return null;
|
|
@@ -8956,10 +9353,11 @@ function processFunctionDeclaration(node, nameOverride) {
|
|
|
8956
9353
|
name,
|
|
8957
9354
|
lines: getLineRange(node),
|
|
8958
9355
|
decorators: [],
|
|
8959
|
-
async: node.async
|
|
9356
|
+
async: node.async,
|
|
9357
|
+
exported
|
|
8960
9358
|
};
|
|
8961
9359
|
}
|
|
8962
|
-
function processClassDeclaration(node, nameOverride) {
|
|
9360
|
+
function processClassDeclaration(node, nameOverride, exported = false) {
|
|
8963
9361
|
const name = nameOverride ?? node.id?.name;
|
|
8964
9362
|
if (!name)
|
|
8965
9363
|
return null;
|
|
@@ -8985,10 +9383,13 @@ function processClassDeclaration(node, nameOverride) {
|
|
|
8985
9383
|
return {
|
|
8986
9384
|
name,
|
|
8987
9385
|
lines: getLineRange(node),
|
|
8988
|
-
methods
|
|
9386
|
+
methods,
|
|
9387
|
+
extends: node.superClass ? [expressionName(node.superClass) ?? "<computed>"] : [],
|
|
9388
|
+
implements: (node.implements ?? []).map((impl) => impl?.expression ? expressionName(impl.expression) : impl?.id?.name).filter(Boolean),
|
|
9389
|
+
exported
|
|
8989
9390
|
};
|
|
8990
9391
|
}
|
|
8991
|
-
function processVariableDeclaration(node, imports, constants, functions) {
|
|
9392
|
+
function processVariableDeclaration(node, imports, constants, functions, calls, exports, exportedFromWrapper = false) {
|
|
8992
9393
|
for (const decl of node.declarations) {
|
|
8993
9394
|
if (!decl.id || decl.id.type !== "Identifier")
|
|
8994
9395
|
continue;
|
|
@@ -9003,6 +9404,8 @@ function processVariableDeclaration(node, imports, constants, functions) {
|
|
|
9003
9404
|
}
|
|
9004
9405
|
if (isAllCapsConst(varName) && init2 !== null && init2 !== void 0) {
|
|
9005
9406
|
constants.push({ name: varName, line: node.loc?.start.line ?? 1 });
|
|
9407
|
+
if (exportedFromWrapper)
|
|
9408
|
+
exports.push({ name: varName, kind: "constant", line: node.loc?.start.line ?? 1 });
|
|
9006
9409
|
continue;
|
|
9007
9410
|
}
|
|
9008
9411
|
if (init2 && (init2.type === "ArrowFunctionExpression" || init2.type === "FunctionExpression")) {
|
|
@@ -9010,15 +9413,23 @@ function processVariableDeclaration(node, imports, constants, functions) {
|
|
|
9010
9413
|
name: varName,
|
|
9011
9414
|
lines: getLineRange(node),
|
|
9012
9415
|
decorators: [],
|
|
9013
|
-
async: init2.async
|
|
9416
|
+
async: init2.async,
|
|
9417
|
+
exported: exportedFromWrapper
|
|
9014
9418
|
});
|
|
9419
|
+
collectCalls(init2.body, varName, calls);
|
|
9420
|
+
if (exportedFromWrapper)
|
|
9421
|
+
exports.push({ name: varName, kind: "function", line: node.loc?.start.line ?? 1 });
|
|
9015
9422
|
} else if (init2 && init2.type === "CallExpression" && /^[A-Z]/.test(varName)) {
|
|
9016
9423
|
functions.push({
|
|
9017
9424
|
name: varName,
|
|
9018
9425
|
lines: getLineRange(node),
|
|
9019
9426
|
decorators: [],
|
|
9020
|
-
async: false
|
|
9427
|
+
async: false,
|
|
9428
|
+
exported: exportedFromWrapper
|
|
9021
9429
|
});
|
|
9430
|
+
collectCalls(init2, varName, calls);
|
|
9431
|
+
if (exportedFromWrapper)
|
|
9432
|
+
exports.push({ name: varName, kind: "function", line: node.loc?.start.line ?? 1 });
|
|
9022
9433
|
}
|
|
9023
9434
|
}
|
|
9024
9435
|
}
|
|
@@ -9070,16 +9481,31 @@ function processStatement(stmt, buckets, extractTsTypes, exportedFromWrapper = f
|
|
|
9070
9481
|
processStatement(stmt.declaration, buckets, extractTsTypes, true);
|
|
9071
9482
|
return;
|
|
9072
9483
|
}
|
|
9484
|
+
if (stmt.type === "ExportNamedDeclaration" && !stmt.declaration) {
|
|
9485
|
+
for (const spec of stmt.specifiers ?? []) {
|
|
9486
|
+
if (spec.type === "ExportSpecifier") {
|
|
9487
|
+
const exported = spec.exported.type === "Identifier" ? spec.exported.name : spec.exported.value;
|
|
9488
|
+
buckets.exports.push({ name: exported, kind: "unknown", line: stmt.loc?.start.line ?? 1 });
|
|
9489
|
+
}
|
|
9490
|
+
}
|
|
9491
|
+
return;
|
|
9492
|
+
}
|
|
9073
9493
|
if (stmt.type === "ExportDefaultDeclaration") {
|
|
9074
9494
|
const decl = stmt.declaration;
|
|
9075
9495
|
if (decl.type === "FunctionDeclaration") {
|
|
9076
|
-
const fe = processFunctionDeclaration(decl, decl.id?.name ?? "default");
|
|
9496
|
+
const fe = processFunctionDeclaration(decl, decl.id?.name ?? "default", true);
|
|
9077
9497
|
if (fe)
|
|
9078
9498
|
buckets.functions.push(fe);
|
|
9499
|
+
if (fe)
|
|
9500
|
+
buckets.exports.push({ name: fe.name, kind: "function", line: fe.lines[0] });
|
|
9501
|
+
if (fe)
|
|
9502
|
+
collectCalls(decl.body, fe.name, buckets.calls);
|
|
9079
9503
|
} else if (decl.type === "ClassDeclaration") {
|
|
9080
|
-
const ce = processClassDeclaration(decl, decl.id?.name ?? "default");
|
|
9504
|
+
const ce = processClassDeclaration(decl, decl.id?.name ?? "default", true);
|
|
9081
9505
|
if (ce)
|
|
9082
9506
|
buckets.classes.push(ce);
|
|
9507
|
+
if (ce)
|
|
9508
|
+
buckets.exports.push({ name: ce.name, kind: "class", line: ce.lines[0] });
|
|
9083
9509
|
}
|
|
9084
9510
|
return;
|
|
9085
9511
|
}
|
|
@@ -9088,19 +9514,35 @@ function processStatement(stmt, buckets, extractTsTypes, exportedFromWrapper = f
|
|
|
9088
9514
|
return;
|
|
9089
9515
|
}
|
|
9090
9516
|
if (stmt.type === "FunctionDeclaration") {
|
|
9091
|
-
const fe = processFunctionDeclaration(stmt);
|
|
9517
|
+
const fe = processFunctionDeclaration(stmt, void 0, exportedFromWrapper);
|
|
9092
9518
|
if (fe)
|
|
9093
9519
|
buckets.functions.push(fe);
|
|
9520
|
+
if (fe) {
|
|
9521
|
+
collectCalls(stmt.body, fe.name, buckets.calls);
|
|
9522
|
+
if (exportedFromWrapper)
|
|
9523
|
+
buckets.exports.push({ name: fe.name, kind: "function", line: fe.lines[0] });
|
|
9524
|
+
}
|
|
9094
9525
|
return;
|
|
9095
9526
|
}
|
|
9096
9527
|
if (stmt.type === "ClassDeclaration") {
|
|
9097
|
-
const ce = processClassDeclaration(stmt);
|
|
9528
|
+
const ce = processClassDeclaration(stmt, void 0, exportedFromWrapper);
|
|
9098
9529
|
if (ce)
|
|
9099
9530
|
buckets.classes.push(ce);
|
|
9531
|
+
if (ce && exportedFromWrapper)
|
|
9532
|
+
buckets.exports.push({ name: ce.name, kind: "class", line: ce.lines[0] });
|
|
9533
|
+
if (ce) {
|
|
9534
|
+
for (const member of stmt.body.body) {
|
|
9535
|
+
if (member.type === "ClassMethod" || member.type === "ClassPrivateMethod") {
|
|
9536
|
+
const method = ce.methods.find((m) => m.lines[0] === (member.loc?.start.line ?? 0));
|
|
9537
|
+
if (method)
|
|
9538
|
+
collectCalls(member.body, `${ce.name}.${method.name}`, buckets.calls);
|
|
9539
|
+
}
|
|
9540
|
+
}
|
|
9541
|
+
}
|
|
9100
9542
|
return;
|
|
9101
9543
|
}
|
|
9102
9544
|
if (stmt.type === "VariableDeclaration") {
|
|
9103
|
-
processVariableDeclaration(stmt, buckets.imports, buckets.constants, buckets.functions);
|
|
9545
|
+
processVariableDeclaration(stmt, buckets.imports, buckets.constants, buckets.functions, buckets.calls, buckets.exports, exportedFromWrapper);
|
|
9104
9546
|
return;
|
|
9105
9547
|
}
|
|
9106
9548
|
if (extractTsTypes) {
|
|
@@ -9109,18 +9551,24 @@ function processStatement(stmt, buckets, extractTsTypes, exportedFromWrapper = f
|
|
|
9109
9551
|
const e = processTsInterfaceDeclaration(anyStmt, exportedFromWrapper);
|
|
9110
9552
|
if (e)
|
|
9111
9553
|
buckets.interfaces.push(e);
|
|
9554
|
+
if (e && exportedFromWrapper)
|
|
9555
|
+
buckets.exports.push({ name: e.name, kind: "interface", line: e.lines[0] });
|
|
9112
9556
|
return;
|
|
9113
9557
|
}
|
|
9114
9558
|
if (anyStmt.type === "TSTypeAliasDeclaration") {
|
|
9115
9559
|
const e = processTsTypeAliasDeclaration(anyStmt, exportedFromWrapper);
|
|
9116
9560
|
if (e)
|
|
9117
9561
|
buckets.types.push(e);
|
|
9562
|
+
if (e && exportedFromWrapper)
|
|
9563
|
+
buckets.exports.push({ name: e.name, kind: "type", line: e.lines[0] });
|
|
9118
9564
|
return;
|
|
9119
9565
|
}
|
|
9120
9566
|
if (anyStmt.type === "TSEnumDeclaration") {
|
|
9121
9567
|
const e = processTsEnumDeclaration(anyStmt, exportedFromWrapper);
|
|
9122
9568
|
if (e)
|
|
9123
9569
|
buckets.enums.push(e);
|
|
9570
|
+
if (e && exportedFromWrapper)
|
|
9571
|
+
buckets.exports.push({ name: e.name, kind: "enum", line: e.lines[0] });
|
|
9124
9572
|
return;
|
|
9125
9573
|
}
|
|
9126
9574
|
}
|
|
@@ -9148,7 +9596,9 @@ function parseAndExtract(source, opts) {
|
|
|
9148
9596
|
classes: [],
|
|
9149
9597
|
interfaces: [],
|
|
9150
9598
|
types: [],
|
|
9151
|
-
enums: []
|
|
9599
|
+
enums: [],
|
|
9600
|
+
calls: [],
|
|
9601
|
+
exports: []
|
|
9152
9602
|
};
|
|
9153
9603
|
for (const stmt of ast.program.body) {
|
|
9154
9604
|
processStatement(stmt, buckets, !!opts.extractTsTypes);
|
|
@@ -9171,7 +9621,9 @@ function parseJsSource(source, relPath) {
|
|
|
9171
9621
|
imports: r.imports,
|
|
9172
9622
|
constants: r.constants,
|
|
9173
9623
|
classes: r.classes,
|
|
9174
|
-
functions: r.functions
|
|
9624
|
+
functions: r.functions,
|
|
9625
|
+
calls: r.calls,
|
|
9626
|
+
exports: r.exports
|
|
9175
9627
|
};
|
|
9176
9628
|
}
|
|
9177
9629
|
var COMMON_PLUGINS, JS_PLUGINS, JavaScriptScanner, jsScanner;
|
|
@@ -9199,7 +9651,7 @@ var init_javascript = __esm({
|
|
|
9199
9651
|
async scan(absolutePath, repoRoot) {
|
|
9200
9652
|
let source;
|
|
9201
9653
|
try {
|
|
9202
|
-
source =
|
|
9654
|
+
source = readFileSync19(absolutePath, "utf8");
|
|
9203
9655
|
} catch (err) {
|
|
9204
9656
|
throw err;
|
|
9205
9657
|
}
|
|
@@ -9219,7 +9671,7 @@ var typescript_exports = {};
|
|
|
9219
9671
|
__export(typescript_exports, {
|
|
9220
9672
|
tsScanner: () => tsScanner
|
|
9221
9673
|
});
|
|
9222
|
-
import { readFileSync as
|
|
9674
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
9223
9675
|
var TypeScriptScanner, tsScanner;
|
|
9224
9676
|
var init_typescript = __esm({
|
|
9225
9677
|
"src/code-map/scanners/typescript.ts"() {
|
|
@@ -9231,7 +9683,7 @@ var init_typescript = __esm({
|
|
|
9231
9683
|
async scan(absolutePath, repoRoot) {
|
|
9232
9684
|
let source;
|
|
9233
9685
|
try {
|
|
9234
|
-
source =
|
|
9686
|
+
source = readFileSync20(absolutePath, "utf8");
|
|
9235
9687
|
} catch (err) {
|
|
9236
9688
|
throw err;
|
|
9237
9689
|
}
|
|
@@ -9252,6 +9704,8 @@ var init_typescript = __esm({
|
|
|
9252
9704
|
constants: r.constants,
|
|
9253
9705
|
classes: r.classes,
|
|
9254
9706
|
functions: r.functions,
|
|
9707
|
+
calls: r.calls,
|
|
9708
|
+
exports: r.exports,
|
|
9255
9709
|
interfaces: r.interfaces,
|
|
9256
9710
|
types: r.types,
|
|
9257
9711
|
enums: r.enums
|
|
@@ -9267,7 +9721,7 @@ var vue_exports = {};
|
|
|
9267
9721
|
__export(vue_exports, {
|
|
9268
9722
|
vueScanner: () => vueScanner
|
|
9269
9723
|
});
|
|
9270
|
-
import { readFileSync as
|
|
9724
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
9271
9725
|
import { parse as parse2 } from "@vue/compiler-sfc";
|
|
9272
9726
|
var VueScanner, vueScanner;
|
|
9273
9727
|
var init_vue = __esm({
|
|
@@ -9280,7 +9734,7 @@ var init_vue = __esm({
|
|
|
9280
9734
|
async scan(absolutePath, repoRoot) {
|
|
9281
9735
|
let source;
|
|
9282
9736
|
try {
|
|
9283
|
-
source =
|
|
9737
|
+
source = readFileSync21(absolutePath, "utf8");
|
|
9284
9738
|
} catch (err) {
|
|
9285
9739
|
throw err;
|
|
9286
9740
|
}
|
|
@@ -9294,6 +9748,8 @@ var init_vue = __esm({
|
|
|
9294
9748
|
const allConstants = [];
|
|
9295
9749
|
const allFunctions = [];
|
|
9296
9750
|
const allClasses = [];
|
|
9751
|
+
const allCalls = [];
|
|
9752
|
+
const allExports = [];
|
|
9297
9753
|
const warnings = [];
|
|
9298
9754
|
const scriptBlocks = [descriptor.script, descriptor.scriptSetup].filter(Boolean);
|
|
9299
9755
|
if (scriptBlocks.length === 0) {
|
|
@@ -9346,6 +9802,12 @@ var init_vue = __esm({
|
|
|
9346
9802
|
}))
|
|
9347
9803
|
});
|
|
9348
9804
|
}
|
|
9805
|
+
for (const call of scriptEntry.calls ?? []) {
|
|
9806
|
+
allCalls.push({ ...call, line: call.line + offset });
|
|
9807
|
+
}
|
|
9808
|
+
for (const exp of scriptEntry.exports ?? []) {
|
|
9809
|
+
allExports.push({ ...exp, line: exp.line + offset });
|
|
9810
|
+
}
|
|
9349
9811
|
}
|
|
9350
9812
|
return {
|
|
9351
9813
|
path: relPath,
|
|
@@ -9353,7 +9815,9 @@ var init_vue = __esm({
|
|
|
9353
9815
|
imports: allImports,
|
|
9354
9816
|
constants: allConstants,
|
|
9355
9817
|
classes: allClasses,
|
|
9356
|
-
functions: allFunctions
|
|
9818
|
+
functions: allFunctions,
|
|
9819
|
+
calls: allCalls,
|
|
9820
|
+
exports: allExports
|
|
9357
9821
|
};
|
|
9358
9822
|
}
|
|
9359
9823
|
};
|
|
@@ -9367,9 +9831,9 @@ __export(code_map_exports, {
|
|
|
9367
9831
|
codeMap: () => codeMap,
|
|
9368
9832
|
computeSourcesDigest: () => computeSourcesDigest
|
|
9369
9833
|
});
|
|
9370
|
-
import { existsSync as
|
|
9834
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, readFileSync as readFileSync22, writeFileSync as writeFileSync11 } from "fs";
|
|
9371
9835
|
import { resolve, dirname as dirname5, relative as relative6 } from "path";
|
|
9372
|
-
import { createHash as
|
|
9836
|
+
import { createHash as createHash6 } from "crypto";
|
|
9373
9837
|
import { createRequire } from "module";
|
|
9374
9838
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9375
9839
|
import { join as join21 } from "path";
|
|
@@ -9379,7 +9843,7 @@ function computeSourcesDigest(absolutePaths, cwd) {
|
|
|
9379
9843
|
const contentHash = sha256OfFileNormalized(p) || "missing";
|
|
9380
9844
|
return `${rel}:${contentHash}`;
|
|
9381
9845
|
});
|
|
9382
|
-
return
|
|
9846
|
+
return createHash6("sha256").update(lines.join("\n")).digest("hex");
|
|
9383
9847
|
}
|
|
9384
9848
|
function slugifySurface(surface) {
|
|
9385
9849
|
return surface.replace(/^[./]+/, "").replace(/\/+$/, "").replace(/[\\/]+/g, "-") || "root";
|
|
@@ -9388,7 +9852,7 @@ async function codeMap(opts) {
|
|
|
9388
9852
|
const start = Date.now();
|
|
9389
9853
|
if (opts.surface) {
|
|
9390
9854
|
const resolvedSurface = resolve(process.cwd(), opts.surface);
|
|
9391
|
-
if (!
|
|
9855
|
+
if (!existsSync19(resolvedSurface)) {
|
|
9392
9856
|
log.error(`code-map --surface path not found: ${opts.surface}`);
|
|
9393
9857
|
return 1;
|
|
9394
9858
|
}
|
|
@@ -9473,7 +9937,7 @@ async function codeMap(opts) {
|
|
|
9473
9937
|
log.warn(`${w.path}: ${w.message}`);
|
|
9474
9938
|
}
|
|
9475
9939
|
if (opts.check) {
|
|
9476
|
-
const existing =
|
|
9940
|
+
const existing = existsSync19(out) ? readFileSync22(out, "utf8") : "";
|
|
9477
9941
|
const normalize = (s) => s.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/^# generated: [^\n]+\n/m, "# generated: <normalized>\n");
|
|
9478
9942
|
if (normalize(existing) !== normalize(yamlBody)) {
|
|
9479
9943
|
if (!opts.silent)
|
|
@@ -9493,6 +9957,16 @@ async function codeMap(opts) {
|
|
|
9493
9957
|
if (!rel.startsWith("..")) {
|
|
9494
9958
|
ensureGitignoreEntry(process.cwd(), rel, "cdd-kit local cache (do not commit)");
|
|
9495
9959
|
}
|
|
9960
|
+
const graphPath = graphPathFor(out);
|
|
9961
|
+
const graph2 = buildCodeGraph(result.entries, {
|
|
9962
|
+
generator: `cdd-kit ${_pkg.version}`,
|
|
9963
|
+
sourcesDigest
|
|
9964
|
+
});
|
|
9965
|
+
writeFileSync11(graphPath, JSON.stringify(graph2, null, 2) + "\n", "utf8");
|
|
9966
|
+
const graphRel = relative6(process.cwd(), graphPath).replace(/\\/g, "/");
|
|
9967
|
+
if (!graphRel.startsWith("..")) {
|
|
9968
|
+
ensureGitignoreEntry(process.cwd(), graphRel, "cdd-kit local cache (do not commit)");
|
|
9969
|
+
}
|
|
9496
9970
|
} catch {
|
|
9497
9971
|
}
|
|
9498
9972
|
if (!opts.silent)
|
|
@@ -9508,11 +9982,13 @@ var init_code_map = __esm({
|
|
|
9508
9982
|
init_orchestrator();
|
|
9509
9983
|
init_config();
|
|
9510
9984
|
init_index_reader();
|
|
9985
|
+
init_builder();
|
|
9986
|
+
init_reader();
|
|
9511
9987
|
init_digest();
|
|
9512
9988
|
init_gitignore();
|
|
9513
9989
|
_require = createRequire(import.meta.url);
|
|
9514
9990
|
_pkgPath = join21(fileURLToPath2(import.meta.url), "..", "..", "..", "package.json");
|
|
9515
|
-
_pkg = JSON.parse(
|
|
9991
|
+
_pkg = JSON.parse(readFileSync22(_pkgPath, "utf8"));
|
|
9516
9992
|
}
|
|
9517
9993
|
});
|
|
9518
9994
|
|
|
@@ -9521,15 +9997,15 @@ var refresh_exports = {};
|
|
|
9521
9997
|
__export(refresh_exports, {
|
|
9522
9998
|
refresh: () => refresh
|
|
9523
9999
|
});
|
|
9524
|
-
import { existsSync as
|
|
10000
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, readdirSync as readdirSync10, copyFileSync as copyFileSync4, readFileSync as readFileSync23, writeFileSync as writeFileSync12 } from "fs";
|
|
9525
10001
|
import { dirname as dirname6, join as join22, relative as relative7 } from "path";
|
|
9526
|
-
import { createHash as
|
|
10002
|
+
import { createHash as createHash7 } from "crypto";
|
|
9527
10003
|
function fileHash2(filePath) {
|
|
9528
|
-
return
|
|
10004
|
+
return createHash7("sha256").update(readFileSync23(filePath)).digest("hex");
|
|
9529
10005
|
}
|
|
9530
10006
|
function planForceRefresh(srcDir, destDir, sectionLabel) {
|
|
9531
10007
|
const plan = [];
|
|
9532
|
-
if (!
|
|
10008
|
+
if (!existsSync20(srcDir))
|
|
9533
10009
|
return plan;
|
|
9534
10010
|
function walk(curSrc, curDest) {
|
|
9535
10011
|
let items;
|
|
@@ -9548,7 +10024,7 @@ function planForceRefresh(srcDir, destDir, sectionLabel) {
|
|
|
9548
10024
|
if (!item.isFile())
|
|
9549
10025
|
continue;
|
|
9550
10026
|
const rel = join22(sectionLabel, relative7(srcDir, sp)).replace(/\\/g, "/");
|
|
9551
|
-
if (!
|
|
10027
|
+
if (!existsSync20(dp)) {
|
|
9552
10028
|
plan.push({ src: sp, dest: dp, rel, action: "add" });
|
|
9553
10029
|
} else if (fileHash2(sp) !== fileHash2(dp)) {
|
|
9554
10030
|
plan.push({ src: sp, dest: dp, rel, action: "overwrite" });
|
|
@@ -9561,9 +10037,9 @@ function planForceRefresh(srcDir, destDir, sectionLabel) {
|
|
|
9561
10037
|
return plan;
|
|
9562
10038
|
}
|
|
9563
10039
|
function planSingleFile(src, dest, rel) {
|
|
9564
|
-
if (!
|
|
10040
|
+
if (!existsSync20(src))
|
|
9565
10041
|
return null;
|
|
9566
|
-
if (!
|
|
10042
|
+
if (!existsSync20(dest))
|
|
9567
10043
|
return { src, dest, rel, action: "add" };
|
|
9568
10044
|
if (fileHash2(src) !== fileHash2(dest))
|
|
9569
10045
|
return { src, dest, rel, action: "overwrite" };
|
|
@@ -9607,12 +10083,12 @@ function parseAgentFrontmatter(content) {
|
|
|
9607
10083
|
function resyncModelPolicy(cwd) {
|
|
9608
10084
|
const policyPath = join22(cwd, ".cdd", "model-policy.json");
|
|
9609
10085
|
const result = { changed: false, diff: [], policyPath };
|
|
9610
|
-
if (!
|
|
10086
|
+
if (!existsSync20(AGENTS_HOME))
|
|
9611
10087
|
return result;
|
|
9612
10088
|
const desired = {};
|
|
9613
10089
|
const agentFiles = readdirSync10(AGENTS_HOME, { withFileTypes: true }).filter((d) => d.isFile() && d.name.endsWith(".md"));
|
|
9614
10090
|
for (const f of agentFiles) {
|
|
9615
|
-
const content =
|
|
10091
|
+
const content = readFileSync23(join22(AGENTS_HOME, f.name), "utf8");
|
|
9616
10092
|
const fm = parseAgentFrontmatter(content);
|
|
9617
10093
|
if (fm.name && fm.model)
|
|
9618
10094
|
desired[fm.name] = fm.model;
|
|
@@ -9620,9 +10096,9 @@ function resyncModelPolicy(cwd) {
|
|
|
9620
10096
|
if (Object.keys(desired).length === 0)
|
|
9621
10097
|
return result;
|
|
9622
10098
|
let existing = {};
|
|
9623
|
-
if (
|
|
10099
|
+
if (existsSync20(policyPath)) {
|
|
9624
10100
|
try {
|
|
9625
|
-
existing = JSON.parse(
|
|
10101
|
+
existing = JSON.parse(readFileSync23(policyPath, "utf8"));
|
|
9626
10102
|
} catch {
|
|
9627
10103
|
}
|
|
9628
10104
|
}
|
|
@@ -9658,7 +10134,7 @@ function planTemplateRefresh(cwd) {
|
|
|
9658
10134
|
plan: planForceRefresh(ASSET.testsTemplates, join22(cwd, "tests", "templates"), "tests/templates")
|
|
9659
10135
|
});
|
|
9660
10136
|
const ciTemplatesAsset = join22(ASSET.ci, "..", "ci-templates");
|
|
9661
|
-
if (
|
|
10137
|
+
if (existsSync20(ciTemplatesAsset)) {
|
|
9662
10138
|
sections.push({
|
|
9663
10139
|
name: "ci-templates",
|
|
9664
10140
|
plan: planForceRefresh(ciTemplatesAsset, join22(cwd, "ci-templates"), "ci-templates")
|
|
@@ -9741,7 +10217,7 @@ async function refresh(opts) {
|
|
|
9741
10217
|
log.blank();
|
|
9742
10218
|
if (!opts.noHooks) {
|
|
9743
10219
|
const markerPath = join22(cwd, HOOKS_MARKER_PATH);
|
|
9744
|
-
if (
|
|
10220
|
+
if (existsSync20(markerPath)) {
|
|
9745
10221
|
log.info("[4/6] re-install code-map pre-commit hook (marker found)");
|
|
9746
10222
|
if (apply) {
|
|
9747
10223
|
try {
|
|
@@ -9834,7 +10310,7 @@ __export(lint_agents_exports, {
|
|
|
9834
10310
|
lintAgentContent: () => lintAgentContent,
|
|
9835
10311
|
lintAgents: () => lintAgents
|
|
9836
10312
|
});
|
|
9837
|
-
import { readdirSync as readdirSync11, readFileSync as
|
|
10313
|
+
import { readdirSync as readdirSync11, readFileSync as readFileSync24 } from "fs";
|
|
9838
10314
|
import { join as join23 } from "path";
|
|
9839
10315
|
import { load as yamlLoad2 } from "js-yaml";
|
|
9840
10316
|
function extractRequiredArtifactsSection(content) {
|
|
@@ -9975,7 +10451,7 @@ function collectAgentViolations(cwd, opts = {}) {
|
|
|
9975
10451
|
for (const filename of files) {
|
|
9976
10452
|
let content;
|
|
9977
10453
|
try {
|
|
9978
|
-
content =
|
|
10454
|
+
content = readFileSync24(join23(agentsDir, filename), "utf8");
|
|
9979
10455
|
} catch {
|
|
9980
10456
|
violations.push({
|
|
9981
10457
|
file: filename,
|
|
@@ -10024,14 +10500,14 @@ var doctor_exports = {};
|
|
|
10024
10500
|
__export(doctor_exports, {
|
|
10025
10501
|
doctor: () => doctor
|
|
10026
10502
|
});
|
|
10027
|
-
import { existsSync as
|
|
10028
|
-
import { createHash as
|
|
10503
|
+
import { existsSync as existsSync21, readdirSync as readdirSync12, readFileSync as readFileSync25 } from "fs";
|
|
10504
|
+
import { createHash as createHash8 } from "crypto";
|
|
10029
10505
|
import { join as join24, relative as relative8 } from "path";
|
|
10030
10506
|
function fileExists(cwd, relPath) {
|
|
10031
|
-
return
|
|
10507
|
+
return existsSync21(join24(cwd, relPath));
|
|
10032
10508
|
}
|
|
10033
10509
|
function findFiles(dir, predicate, found = []) {
|
|
10034
|
-
if (!
|
|
10510
|
+
if (!existsSync21(dir))
|
|
10035
10511
|
return found;
|
|
10036
10512
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
10037
10513
|
const fullPath = join24(dir, entry.name);
|
|
@@ -10047,12 +10523,12 @@ function inputDigest(paths, cwd) {
|
|
|
10047
10523
|
const rel = relative8(cwd, p).replace(/\\/g, "/");
|
|
10048
10524
|
return `${rel}:${sha256OfFileNormalized(p)}`;
|
|
10049
10525
|
}).join("\n");
|
|
10050
|
-
return
|
|
10526
|
+
return createHash8("sha256").update(combined).digest("hex");
|
|
10051
10527
|
}
|
|
10052
10528
|
function readContextIndexMetadata(filePath) {
|
|
10053
|
-
if (!
|
|
10529
|
+
if (!existsSync21(filePath))
|
|
10054
10530
|
return {};
|
|
10055
|
-
const text =
|
|
10531
|
+
const text = readFileSync25(filePath, "utf8");
|
|
10056
10532
|
const out = {};
|
|
10057
10533
|
const digestMatch = text.match(/^inputs-digest:\s*([a-f0-9]+)/m);
|
|
10058
10534
|
if (digestMatch)
|
|
@@ -10071,7 +10547,7 @@ function checkContextFreshness(cwd) {
|
|
|
10071
10547
|
join24(cwd, "contracts"),
|
|
10072
10548
|
(name) => name.endsWith(".md") && name !== "INDEX.md" && name !== "CHANGELOG.md"
|
|
10073
10549
|
);
|
|
10074
|
-
if (!
|
|
10550
|
+
if (!existsSync21(projectMap) || !existsSync21(contractsIndex)) {
|
|
10075
10551
|
findings.push({
|
|
10076
10552
|
level: "warning",
|
|
10077
10553
|
message: "specs/context indexes are missing; run cdd-kit context-scan before classification"
|
|
@@ -10080,7 +10556,7 @@ function checkContextFreshness(cwd) {
|
|
|
10080
10556
|
}
|
|
10081
10557
|
const projectMapMeta = readContextIndexMetadata(projectMap);
|
|
10082
10558
|
const contractsIndexMeta = readContextIndexMetadata(contractsIndex);
|
|
10083
|
-
const projectInputDigest = inputDigest([contextPolicy].filter(
|
|
10559
|
+
const projectInputDigest = inputDigest([contextPolicy].filter(existsSync21), cwd);
|
|
10084
10560
|
if (projectMapMeta.inputsDigest === void 0) {
|
|
10085
10561
|
findings.push({
|
|
10086
10562
|
level: "warning",
|
|
@@ -10117,7 +10593,7 @@ function checkContextFreshness(cwd) {
|
|
|
10117
10593
|
}
|
|
10118
10594
|
function readAgentModel(path) {
|
|
10119
10595
|
try {
|
|
10120
|
-
const text =
|
|
10596
|
+
const text = readFileSync25(path, "utf8");
|
|
10121
10597
|
const m = text.match(/^model:\s*(\S+)/m);
|
|
10122
10598
|
return m ? m[1] : null;
|
|
10123
10599
|
} catch {
|
|
@@ -10126,11 +10602,11 @@ function readAgentModel(path) {
|
|
|
10126
10602
|
}
|
|
10127
10603
|
function checkModelPolicyDrift(cwd) {
|
|
10128
10604
|
const policyPath = join24(cwd, ".cdd", "model-policy.json");
|
|
10129
|
-
if (!
|
|
10605
|
+
if (!existsSync21(policyPath))
|
|
10130
10606
|
return [];
|
|
10131
10607
|
let policy;
|
|
10132
10608
|
try {
|
|
10133
|
-
policy = JSON.parse(
|
|
10609
|
+
policy = JSON.parse(readFileSync25(policyPath, "utf8"));
|
|
10134
10610
|
} catch {
|
|
10135
10611
|
return [{ level: "warning", message: ".cdd/model-policy.json is not valid JSON" }];
|
|
10136
10612
|
}
|
|
@@ -10145,7 +10621,7 @@ function checkModelPolicyDrift(cwd) {
|
|
|
10145
10621
|
join24(cwd, ".claude", "agents"),
|
|
10146
10622
|
process.env.HOME ? join24(process.env.HOME, ".claude", "agents") : "",
|
|
10147
10623
|
process.env.USERPROFILE ? join24(process.env.USERPROFILE, ".claude", "agents") : ""
|
|
10148
|
-
].filter((p) => p &&
|
|
10624
|
+
].filter((p) => p && existsSync21(p));
|
|
10149
10625
|
if (candidateDirs.length === 0)
|
|
10150
10626
|
return [];
|
|
10151
10627
|
const findings = [];
|
|
@@ -10153,7 +10629,7 @@ function checkModelPolicyDrift(cwd) {
|
|
|
10153
10629
|
let foundAny = false;
|
|
10154
10630
|
for (const dir of candidateDirs) {
|
|
10155
10631
|
const path = join24(dir, `${role}.md`);
|
|
10156
|
-
if (!
|
|
10632
|
+
if (!existsSync21(path))
|
|
10157
10633
|
continue;
|
|
10158
10634
|
foundAny = true;
|
|
10159
10635
|
const actual = readAgentModel(path);
|
|
@@ -10174,7 +10650,7 @@ function checkModelPolicyDrift(cwd) {
|
|
|
10174
10650
|
}
|
|
10175
10651
|
function checkAgentLint(cwd) {
|
|
10176
10652
|
const agentsDir = join24(cwd, ".claude", "agents");
|
|
10177
|
-
if (!
|
|
10653
|
+
if (!existsSync21(agentsDir))
|
|
10178
10654
|
return [];
|
|
10179
10655
|
const violations = collectAgentViolations(cwd);
|
|
10180
10656
|
if (violations === null) {
|
|
@@ -10195,7 +10671,7 @@ function checkAgentLint(cwd) {
|
|
|
10195
10671
|
function checkCodeMap(cwd) {
|
|
10196
10672
|
const findings = [];
|
|
10197
10673
|
const mapPath = join24(cwd, ".cdd", "code-map.yml");
|
|
10198
|
-
if (!
|
|
10674
|
+
if (!existsSync21(mapPath)) {
|
|
10199
10675
|
const probe2 = checkCodeMapFreshness(cwd);
|
|
10200
10676
|
if (probe2.status === "config-error") {
|
|
10201
10677
|
findings.push({ level: "warning", message: `.cdd/code-map-config.yml is invalid: ${probe2.configError}` });
|
|
@@ -10214,7 +10690,7 @@ function checkCodeMap(cwd) {
|
|
|
10214
10690
|
const more = probe.staleCount > 3 ? ` (+${probe.staleCount - 3} more)` : "";
|
|
10215
10691
|
findings.push({ level: "warning", message: `code-map stale: ${top}${more}; run \`cdd-kit code-map\`` });
|
|
10216
10692
|
}
|
|
10217
|
-
const text =
|
|
10693
|
+
const text = readFileSync25(mapPath, "utf8");
|
|
10218
10694
|
const m = text.match(/^# files: (\d+), src-lines: (\d+), map-lines: (\d+), compression: ([\d.]+)x/m);
|
|
10219
10695
|
if (m) {
|
|
10220
10696
|
findings.push({ level: "ok", message: `code-map: ${m[1]} files, ${m[4]}x compression` });
|
|
@@ -10294,7 +10770,7 @@ async function attemptAutoFixes(cwd, report) {
|
|
|
10294
10770
|
try {
|
|
10295
10771
|
let existing = {};
|
|
10296
10772
|
try {
|
|
10297
|
-
existing = JSON.parse(
|
|
10773
|
+
existing = JSON.parse(readFileSync25(policyPath, "utf8"));
|
|
10298
10774
|
} catch {
|
|
10299
10775
|
}
|
|
10300
10776
|
const merged = {
|
|
@@ -10305,6 +10781,7 @@ async function attemptAutoFixes(cwd, report) {
|
|
|
10305
10781
|
"qa-reviewer": "opus",
|
|
10306
10782
|
"contract-reviewer": "sonnet",
|
|
10307
10783
|
"test-strategist": "sonnet",
|
|
10784
|
+
"bug-fix-engineer": "sonnet",
|
|
10308
10785
|
"backend-engineer": "sonnet",
|
|
10309
10786
|
"frontend-engineer": "sonnet",
|
|
10310
10787
|
"ci-cd-gatekeeper": "sonnet",
|
|
@@ -10397,7 +10874,7 @@ var code_map_scan_worker_exports = {};
|
|
|
10397
10874
|
__export(code_map_scan_worker_exports, {
|
|
10398
10875
|
runScanWorker: () => runScanWorker
|
|
10399
10876
|
});
|
|
10400
|
-
import { readFileSync as
|
|
10877
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
10401
10878
|
async function runScanWorker(opts) {
|
|
10402
10879
|
let scanner;
|
|
10403
10880
|
switch (opts.lang) {
|
|
@@ -10417,7 +10894,7 @@ async function runScanWorker(opts) {
|
|
|
10417
10894
|
}
|
|
10418
10895
|
let files;
|
|
10419
10896
|
try {
|
|
10420
|
-
files =
|
|
10897
|
+
files = readFileSync26(opts.batchFile, "utf8").split("\n").map((s) => s.trim()).filter(Boolean);
|
|
10421
10898
|
} catch (err) {
|
|
10422
10899
|
process.stderr.write(`__code-map-scan: cannot read --batch-file: ${err.message}
|
|
10423
10900
|
`);
|
|
@@ -10437,9 +10914,10 @@ var init_code_map_scan_worker = __esm({
|
|
|
10437
10914
|
// src/commands/index-query.ts
|
|
10438
10915
|
var index_query_exports = {};
|
|
10439
10916
|
__export(index_query_exports, {
|
|
10440
|
-
indexQuery: () => indexQuery
|
|
10917
|
+
indexQuery: () => indexQuery,
|
|
10918
|
+
queryEntries: () => queryEntries
|
|
10441
10919
|
});
|
|
10442
|
-
import { existsSync as
|
|
10920
|
+
import { existsSync as existsSync22 } from "fs";
|
|
10443
10921
|
async function indexQuery(term, opts) {
|
|
10444
10922
|
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
10445
10923
|
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 10;
|
|
@@ -10449,7 +10927,7 @@ async function indexQuery(term, opts) {
|
|
|
10449
10927
|
return printFailure(freshness.error, opts.json);
|
|
10450
10928
|
}
|
|
10451
10929
|
refreshed = freshness.refreshed;
|
|
10452
|
-
if (!
|
|
10930
|
+
if (!existsSync22(mapPath)) {
|
|
10453
10931
|
return printFailure(`${mapPath} is missing; run \`cdd-kit code-map\` first.`, opts.json);
|
|
10454
10932
|
}
|
|
10455
10933
|
let entries;
|
|
@@ -10617,8 +11095,8 @@ var index_impact_exports = {};
|
|
|
10617
11095
|
__export(index_impact_exports, {
|
|
10618
11096
|
indexImpact: () => indexImpact
|
|
10619
11097
|
});
|
|
10620
|
-
import { existsSync as
|
|
10621
|
-
import { posix } from "path";
|
|
11098
|
+
import { existsSync as existsSync23 } from "fs";
|
|
11099
|
+
import { posix as posix2 } from "path";
|
|
10622
11100
|
async function indexImpact(term, opts) {
|
|
10623
11101
|
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
10624
11102
|
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
@@ -10626,7 +11104,7 @@ async function indexImpact(term, opts) {
|
|
|
10626
11104
|
if (freshness.error) {
|
|
10627
11105
|
return printFailure2(freshness.error, opts.json);
|
|
10628
11106
|
}
|
|
10629
|
-
if (!
|
|
11107
|
+
if (!existsSync23(mapPath)) {
|
|
10630
11108
|
return printFailure2(`${mapPath} is missing; run \`cdd-kit code-map\` first.`, opts.json);
|
|
10631
11109
|
}
|
|
10632
11110
|
let entries;
|
|
@@ -10643,7 +11121,7 @@ async function indexImpact(term, opts) {
|
|
|
10643
11121
|
const target = targetResult.entry;
|
|
10644
11122
|
const targetImports = target.imports.map((imp) => resolveImport(target.path, imp, pathSet));
|
|
10645
11123
|
const imports = targetImports.filter((imp) => imp.resolved);
|
|
10646
|
-
const unresolvedLocalImports = targetImports.filter((imp) => !imp.resolved &&
|
|
11124
|
+
const unresolvedLocalImports = targetImports.filter((imp) => !imp.resolved && isLocalImport2(imp.module));
|
|
10647
11125
|
const dependents = entries.filter((entry) => entry.path !== target.path).map((entry) => ({
|
|
10648
11126
|
entry,
|
|
10649
11127
|
imports: entry.imports.map((imp) => resolveImport(entry.path, imp, pathSet)).filter((imp) => imp.resolved === target.path)
|
|
@@ -10679,7 +11157,7 @@ function findTarget(entries, term) {
|
|
|
10679
11157
|
if (exact)
|
|
10680
11158
|
return { entry: exact };
|
|
10681
11159
|
const pathMatches2 = entries.filter(
|
|
10682
|
-
(entry) => entry.path.toLowerCase().includes(query.toLowerCase()) ||
|
|
11160
|
+
(entry) => entry.path.toLowerCase().includes(query.toLowerCase()) || posix2.basename(entry.path).toLowerCase() === query.toLowerCase()
|
|
10683
11161
|
);
|
|
10684
11162
|
if (pathMatches2.length === 1)
|
|
10685
11163
|
return { entry: pathMatches2[0] };
|
|
@@ -10715,7 +11193,7 @@ function normalizeQueryPath(term) {
|
|
|
10715
11193
|
return term.trim().replace(/\\/g, "/").replace(/^\.\//, "");
|
|
10716
11194
|
}
|
|
10717
11195
|
function resolveImport(importerPath, imp, pathSet) {
|
|
10718
|
-
const resolved =
|
|
11196
|
+
const resolved = resolveLocalModule2(importerPath, imp.module, pathSet);
|
|
10719
11197
|
return {
|
|
10720
11198
|
module: imp.module,
|
|
10721
11199
|
items: Array.isArray(imp.items) ? imp.items : [],
|
|
@@ -10723,30 +11201,30 @@ function resolveImport(importerPath, imp, pathSet) {
|
|
|
10723
11201
|
...resolved ? { resolved } : {}
|
|
10724
11202
|
};
|
|
10725
11203
|
}
|
|
10726
|
-
function
|
|
10727
|
-
if (!
|
|
11204
|
+
function resolveLocalModule2(importerPath, moduleName, pathSet) {
|
|
11205
|
+
if (!isLocalImport2(moduleName))
|
|
10728
11206
|
return void 0;
|
|
10729
|
-
const base = moduleName.startsWith("./") || moduleName.startsWith("../") ?
|
|
10730
|
-
for (const candidate of
|
|
11207
|
+
const base = moduleName.startsWith("./") || moduleName.startsWith("../") ? posix2.normalize(posix2.join(posix2.dirname(importerPath), moduleName)) : resolvePythonRelativeImport2(importerPath, moduleName);
|
|
11208
|
+
for (const candidate of resolutionCandidates2(base)) {
|
|
10731
11209
|
if (pathSet.has(candidate))
|
|
10732
11210
|
return candidate;
|
|
10733
11211
|
}
|
|
10734
11212
|
return void 0;
|
|
10735
11213
|
}
|
|
10736
|
-
function
|
|
11214
|
+
function resolvePythonRelativeImport2(importerPath, moduleName) {
|
|
10737
11215
|
const match = moduleName.match(/^(\.+)(.*)$/);
|
|
10738
11216
|
if (!match)
|
|
10739
11217
|
return moduleName;
|
|
10740
11218
|
const upLevels = Math.max(0, match[1].length - 1);
|
|
10741
|
-
let baseDir =
|
|
11219
|
+
let baseDir = posix2.dirname(importerPath);
|
|
10742
11220
|
for (let i = 0; i < upLevels; i++) {
|
|
10743
|
-
baseDir =
|
|
11221
|
+
baseDir = posix2.dirname(baseDir);
|
|
10744
11222
|
}
|
|
10745
11223
|
const rest = match[2].replace(/^\./, "").replace(/\./g, "/");
|
|
10746
|
-
return rest ?
|
|
11224
|
+
return rest ? posix2.normalize(posix2.join(baseDir, rest)) : baseDir;
|
|
10747
11225
|
}
|
|
10748
|
-
function
|
|
10749
|
-
const ext =
|
|
11226
|
+
function resolutionCandidates2(base) {
|
|
11227
|
+
const ext = posix2.extname(base);
|
|
10750
11228
|
const candidates = [];
|
|
10751
11229
|
if (ext) {
|
|
10752
11230
|
candidates.push(base);
|
|
@@ -10755,17 +11233,17 @@ function resolutionCandidates(base) {
|
|
|
10755
11233
|
candidates.push(`${withoutExt}.ts`, `${withoutExt}.tsx`, `${withoutExt}.vue`);
|
|
10756
11234
|
}
|
|
10757
11235
|
} else {
|
|
10758
|
-
for (const candidateExt of
|
|
11236
|
+
for (const candidateExt of RESOLUTION_EXTENSIONS2) {
|
|
10759
11237
|
candidates.push(`${base}${candidateExt}`);
|
|
10760
11238
|
}
|
|
10761
11239
|
}
|
|
10762
|
-
for (const candidateExt of
|
|
10763
|
-
candidates.push(
|
|
11240
|
+
for (const candidateExt of RESOLUTION_EXTENSIONS2) {
|
|
11241
|
+
candidates.push(posix2.join(base, `index${candidateExt}`));
|
|
10764
11242
|
}
|
|
10765
|
-
candidates.push(
|
|
11243
|
+
candidates.push(posix2.join(base, "__init__.py"));
|
|
10766
11244
|
return [...new Set(candidates)];
|
|
10767
11245
|
}
|
|
10768
|
-
function
|
|
11246
|
+
function isLocalImport2(moduleName) {
|
|
10769
11247
|
return moduleName.startsWith(".");
|
|
10770
11248
|
}
|
|
10771
11249
|
function summarizeSymbols(entry) {
|
|
@@ -10855,12 +11333,795 @@ function printFailure2(message, json) {
|
|
|
10855
11333
|
}
|
|
10856
11334
|
return 1;
|
|
10857
11335
|
}
|
|
10858
|
-
var
|
|
11336
|
+
var RESOLUTION_EXTENSIONS2;
|
|
10859
11337
|
var init_index_impact = __esm({
|
|
10860
11338
|
"src/commands/index-impact.ts"() {
|
|
10861
11339
|
"use strict";
|
|
10862
11340
|
init_index_reader();
|
|
10863
|
-
|
|
11341
|
+
RESOLUTION_EXTENSIONS2 = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".vue", ".py"];
|
|
11342
|
+
}
|
|
11343
|
+
});
|
|
11344
|
+
|
|
11345
|
+
// src/code-graph/queries.ts
|
|
11346
|
+
function searchGraph(graph2, term, limit) {
|
|
11347
|
+
const query = term.trim().toLowerCase();
|
|
11348
|
+
if (!query)
|
|
11349
|
+
return [];
|
|
11350
|
+
return graph2.nodes.map((node) => {
|
|
11351
|
+
const score = Math.max(
|
|
11352
|
+
scoreText2(node.name, query, 120),
|
|
11353
|
+
scoreText2(node.qualified_name, query, 100),
|
|
11354
|
+
scoreText2(node.file_path, query, 80)
|
|
11355
|
+
);
|
|
11356
|
+
return {
|
|
11357
|
+
node,
|
|
11358
|
+
score,
|
|
11359
|
+
edges: {
|
|
11360
|
+
incoming: graph2.edges.filter((e) => e.target === node.id).length,
|
|
11361
|
+
outgoing: graph2.edges.filter((e) => e.source === node.id).length
|
|
11362
|
+
}
|
|
11363
|
+
};
|
|
11364
|
+
}).filter((result) => result.score > 0).sort((a, b) => b.score - a.score || a.node.file_path.localeCompare(b.node.file_path) || a.node.start_line - b.node.start_line).slice(0, limit);
|
|
11365
|
+
}
|
|
11366
|
+
function findGraphNode(graph2, term) {
|
|
11367
|
+
const query = term.trim().toLowerCase().replace(/\\/g, "/").replace(/^\.\//, "");
|
|
11368
|
+
const exact = graph2.nodes.find((n) => n.id === term || n.qualified_name.toLowerCase() === query || n.file_path.toLowerCase() === query);
|
|
11369
|
+
if (exact)
|
|
11370
|
+
return exact;
|
|
11371
|
+
const pathMatches2 = graph2.nodes.filter((n) => n.kind === "file" && n.file_path.toLowerCase().includes(query));
|
|
11372
|
+
if (pathMatches2.length === 1)
|
|
11373
|
+
return pathMatches2[0];
|
|
11374
|
+
const symbolMatches = graph2.nodes.filter((n) => n.name.toLowerCase() === query || n.qualified_name.toLowerCase().endsWith(`::${query}`));
|
|
11375
|
+
if (symbolMatches.length === 1)
|
|
11376
|
+
return symbolMatches[0];
|
|
11377
|
+
return searchGraph(graph2, term, 1)[0]?.node;
|
|
11378
|
+
}
|
|
11379
|
+
function graphImpact(graph2, term, depth, limit) {
|
|
11380
|
+
const target = findGraphNode(graph2, term);
|
|
11381
|
+
if (!target)
|
|
11382
|
+
return void 0;
|
|
11383
|
+
return traverse(graph2, target, ["calls", "imports", "references", "extends", "implements"], "both", depth, limit);
|
|
11384
|
+
}
|
|
11385
|
+
function graphContext(graph2, task, maxNodes) {
|
|
11386
|
+
const entryPoints = searchGraph(graph2, task, Math.min(maxNodes, 10));
|
|
11387
|
+
const nodeIds = new Set(entryPoints.map((r) => r.node.id));
|
|
11388
|
+
const edgeMap = /* @__PURE__ */ new Map();
|
|
11389
|
+
for (const entry of entryPoints) {
|
|
11390
|
+
const neighborhood = traverse(graph2, entry.node, ["contains", "calls", "imports", "references", "extends", "implements"], "both", 1, maxNodes);
|
|
11391
|
+
for (const node of neighborhood.nodes)
|
|
11392
|
+
nodeIds.add(node.id);
|
|
11393
|
+
for (const edge of neighborhood.edges)
|
|
11394
|
+
edgeMap.set(edge.id, edge);
|
|
11395
|
+
}
|
|
11396
|
+
const nodes = graph2.nodes.filter((n) => nodeIds.has(n.id)).slice(0, maxNodes);
|
|
11397
|
+
return { query: task, entry_points: entryPoints, nodes, edges: [...edgeMap.values()] };
|
|
11398
|
+
}
|
|
11399
|
+
function traverse(graph2, target, kinds, direction, depth, limit) {
|
|
11400
|
+
const maxDepth = Math.max(1, depth || 1);
|
|
11401
|
+
const maxNodes = Math.max(1, limit || 50);
|
|
11402
|
+
const nodeById = new Map(graph2.nodes.map((n) => [n.id, n]));
|
|
11403
|
+
const visited = /* @__PURE__ */ new Set([target.id]);
|
|
11404
|
+
const keptEdges = /* @__PURE__ */ new Map();
|
|
11405
|
+
let frontier = [target.id];
|
|
11406
|
+
for (let d = 0; d < maxDepth && frontier.length > 0 && visited.size < maxNodes; d++) {
|
|
11407
|
+
const next = [];
|
|
11408
|
+
for (const nodeId2 of frontier) {
|
|
11409
|
+
const edges = graph2.edges.filter(
|
|
11410
|
+
(e) => kinds.includes(e.kind) && (direction === "both" ? e.source === nodeId2 || e.target === nodeId2 : direction === "incoming" ? e.target === nodeId2 : e.source === nodeId2)
|
|
11411
|
+
);
|
|
11412
|
+
for (const edge of edges) {
|
|
11413
|
+
const other = edge.source === nodeId2 ? edge.target : edge.source;
|
|
11414
|
+
if (!nodeById.has(other))
|
|
11415
|
+
continue;
|
|
11416
|
+
keptEdges.set(edge.id, edge);
|
|
11417
|
+
if (!visited.has(other)) {
|
|
11418
|
+
visited.add(other);
|
|
11419
|
+
next.push(other);
|
|
11420
|
+
if (visited.size >= maxNodes)
|
|
11421
|
+
break;
|
|
11422
|
+
}
|
|
11423
|
+
}
|
|
11424
|
+
}
|
|
11425
|
+
frontier = next;
|
|
11426
|
+
}
|
|
11427
|
+
return {
|
|
11428
|
+
target,
|
|
11429
|
+
depth: maxDepth,
|
|
11430
|
+
nodes: [...visited].map((id) => nodeById.get(id)).filter((node) => !!node),
|
|
11431
|
+
edges: [...keptEdges.values()]
|
|
11432
|
+
};
|
|
11433
|
+
}
|
|
11434
|
+
function scoreText2(text, query, weight) {
|
|
11435
|
+
const haystack = text.toLowerCase();
|
|
11436
|
+
if (haystack === query)
|
|
11437
|
+
return weight + 40;
|
|
11438
|
+
if (haystack.endsWith(`/${query}`) || haystack.endsWith(`.${query}`) || haystack.endsWith(`::${query}`))
|
|
11439
|
+
return weight + 30;
|
|
11440
|
+
if (haystack.startsWith(query))
|
|
11441
|
+
return weight + 20;
|
|
11442
|
+
if (haystack.includes(query))
|
|
11443
|
+
return weight;
|
|
11444
|
+
return 0;
|
|
11445
|
+
}
|
|
11446
|
+
var init_queries = __esm({
|
|
11447
|
+
"src/code-graph/queries.ts"() {
|
|
11448
|
+
"use strict";
|
|
11449
|
+
}
|
|
11450
|
+
});
|
|
11451
|
+
|
|
11452
|
+
// src/commands/graph.ts
|
|
11453
|
+
var graph_exports = {};
|
|
11454
|
+
__export(graph_exports, {
|
|
11455
|
+
graphContext: () => graphContext2,
|
|
11456
|
+
graphImpact: () => graphImpact2,
|
|
11457
|
+
graphQuery: () => graphQuery,
|
|
11458
|
+
graphStatus: () => graphStatus,
|
|
11459
|
+
graphSync: () => graphSync
|
|
11460
|
+
});
|
|
11461
|
+
import { existsSync as existsSync24 } from "fs";
|
|
11462
|
+
import { join as join25 } from "path";
|
|
11463
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
11464
|
+
function codeGraphCommand() {
|
|
11465
|
+
return process.env.CDD_CODEGRAPH_BIN || "codegraph";
|
|
11466
|
+
}
|
|
11467
|
+
function runCodeGraph(args, cwd = process.cwd()) {
|
|
11468
|
+
const command = codeGraphCommand();
|
|
11469
|
+
if (command.toLowerCase().endsWith(".js")) {
|
|
11470
|
+
return spawnSync3(process.execPath, [command, ...args], { cwd, encoding: "buffer" });
|
|
11471
|
+
}
|
|
11472
|
+
return spawnSync3(command, args, { cwd, encoding: "buffer" });
|
|
11473
|
+
}
|
|
11474
|
+
function probeCodeGraph(cwd = process.cwd()) {
|
|
11475
|
+
const command = codeGraphCommand();
|
|
11476
|
+
const initialized = existsSync24(join25(cwd, ".codegraph"));
|
|
11477
|
+
const version = runCodeGraph(["--version"], cwd);
|
|
11478
|
+
if (version.error) {
|
|
11479
|
+
return {
|
|
11480
|
+
available: false,
|
|
11481
|
+
command,
|
|
11482
|
+
initialized,
|
|
11483
|
+
reason: version.error.message
|
|
11484
|
+
};
|
|
11485
|
+
}
|
|
11486
|
+
if (version.status !== 0) {
|
|
11487
|
+
return {
|
|
11488
|
+
available: false,
|
|
11489
|
+
command,
|
|
11490
|
+
initialized,
|
|
11491
|
+
reason: (version.stderr?.toString("utf8") || version.stdout?.toString("utf8") || `exit ${version.status}`).trim()
|
|
11492
|
+
};
|
|
11493
|
+
}
|
|
11494
|
+
return { available: true, command, initialized };
|
|
11495
|
+
}
|
|
11496
|
+
function selectEngine(opts, cwd = process.cwd()) {
|
|
11497
|
+
const requested = opts.engine ?? "auto";
|
|
11498
|
+
const probe = probeCodeGraph(cwd);
|
|
11499
|
+
if (!["auto", "native", "codegraph", "codemap"].includes(requested)) {
|
|
11500
|
+
return { error: `Invalid graph engine: ${requested}. Use auto, native, codegraph, or codemap.`, probe };
|
|
11501
|
+
}
|
|
11502
|
+
if (requested === "codemap")
|
|
11503
|
+
return { engine: "codemap", probe };
|
|
11504
|
+
if (requested === "native" || requested === "auto")
|
|
11505
|
+
return { engine: "native", probe };
|
|
11506
|
+
if (requested === "codegraph") {
|
|
11507
|
+
if (!probe.available) {
|
|
11508
|
+
return {
|
|
11509
|
+
error: `CodeGraph is not available (${probe.command}): ${probe.reason ?? "command not found"}`,
|
|
11510
|
+
probe
|
|
11511
|
+
};
|
|
11512
|
+
}
|
|
11513
|
+
return { engine: "codegraph", probe };
|
|
11514
|
+
}
|
|
11515
|
+
return { engine: "native", probe };
|
|
11516
|
+
}
|
|
11517
|
+
function writeJson(value) {
|
|
11518
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
11519
|
+
`);
|
|
11520
|
+
}
|
|
11521
|
+
function pipeResult(result) {
|
|
11522
|
+
if (result.stdout?.length)
|
|
11523
|
+
process.stdout.write(result.stdout);
|
|
11524
|
+
if (result.stderr?.length)
|
|
11525
|
+
process.stderr.write(result.stderr);
|
|
11526
|
+
if (result.error) {
|
|
11527
|
+
process.stderr.write(`${result.error.message}
|
|
11528
|
+
`);
|
|
11529
|
+
return 1;
|
|
11530
|
+
}
|
|
11531
|
+
return result.status ?? 1;
|
|
11532
|
+
}
|
|
11533
|
+
function printEngineError(message, json, probe) {
|
|
11534
|
+
if (json) {
|
|
11535
|
+
writeJson({ error: message, codegraph: probe });
|
|
11536
|
+
} else {
|
|
11537
|
+
console.error(message);
|
|
11538
|
+
}
|
|
11539
|
+
return 1;
|
|
11540
|
+
}
|
|
11541
|
+
async function ensureNativeGraph(mapPath, refresh2) {
|
|
11542
|
+
const freshness = await ensureCodeMapFresh(mapPath, refresh2);
|
|
11543
|
+
if (freshness.error)
|
|
11544
|
+
return { graphPath: graphPathFor(mapPath), refreshed: freshness.refreshed, error: freshness.error };
|
|
11545
|
+
const graphPath = graphPathFor(mapPath);
|
|
11546
|
+
if (!existsSync24(graphPath) && refresh2) {
|
|
11547
|
+
const { codeMap: codeMap2 } = await Promise.resolve().then(() => (init_code_map(), code_map_exports));
|
|
11548
|
+
const exit = await codeMap2({
|
|
11549
|
+
path: ".",
|
|
11550
|
+
out: mapPath,
|
|
11551
|
+
include: [],
|
|
11552
|
+
exclude: [],
|
|
11553
|
+
check: false,
|
|
11554
|
+
maxLines: 1e5,
|
|
11555
|
+
silent: true
|
|
11556
|
+
});
|
|
11557
|
+
if (exit !== 0) {
|
|
11558
|
+
return { graphPath, refreshed: freshness.refreshed, error: `could not refresh ${graphPath}; run \`cdd-kit code-map\` for details.` };
|
|
11559
|
+
}
|
|
11560
|
+
return { graphPath, refreshed: true };
|
|
11561
|
+
}
|
|
11562
|
+
return { graphPath, refreshed: freshness.refreshed };
|
|
11563
|
+
}
|
|
11564
|
+
async function graphStatus(opts = {}) {
|
|
11565
|
+
const cwd = process.cwd();
|
|
11566
|
+
const selected = selectEngine(opts, cwd);
|
|
11567
|
+
if ("error" in selected)
|
|
11568
|
+
return printEngineError(selected.error, opts.json, selected.probe);
|
|
11569
|
+
if (selected.engine === "codegraph") {
|
|
11570
|
+
const args = ["status"];
|
|
11571
|
+
if (opts.path)
|
|
11572
|
+
args.push(opts.path);
|
|
11573
|
+
return pipeResult(runCodeGraph(args, cwd));
|
|
11574
|
+
}
|
|
11575
|
+
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
11576
|
+
const graphPath = graphPathFor(mapPath);
|
|
11577
|
+
const freshness = checkCodeMapFreshness(cwd, mapPath);
|
|
11578
|
+
let graphStats;
|
|
11579
|
+
if (existsSync24(graphPath)) {
|
|
11580
|
+
try {
|
|
11581
|
+
const graph2 = loadCodeGraph(graphPath);
|
|
11582
|
+
graphStats = { graph: graphPath, nodes: graph2.nodes.length, edges: graph2.edges.length, unresolved: graph2.unresolved.length };
|
|
11583
|
+
} catch {
|
|
11584
|
+
graphStats = { graph: graphPath, nodes: 0, edges: 0, unresolved: 0 };
|
|
11585
|
+
}
|
|
11586
|
+
}
|
|
11587
|
+
const payload = {
|
|
11588
|
+
engine: selected.engine,
|
|
11589
|
+
codegraph: selected.probe,
|
|
11590
|
+
code_map: {
|
|
11591
|
+
map: mapPath,
|
|
11592
|
+
status: freshness.status,
|
|
11593
|
+
stale_count: "staleCount" in freshness ? freshness.staleCount : 0,
|
|
11594
|
+
stale_files: "staleFiles" in freshness ? freshness.staleFiles.slice(0, 10) : [],
|
|
11595
|
+
config_error: "configError" in freshness ? freshness.configError : void 0
|
|
11596
|
+
},
|
|
11597
|
+
native_graph: graphStats ?? { graph: graphPath, missing: true }
|
|
11598
|
+
};
|
|
11599
|
+
if (opts.json) {
|
|
11600
|
+
writeJson(payload);
|
|
11601
|
+
} else {
|
|
11602
|
+
console.log(`graph engine: ${selected.engine === "native" ? "native cdd-kit graph" : "code-map fallback"}`);
|
|
11603
|
+
console.log(`code-map: ${payload.code_map.status}`);
|
|
11604
|
+
if (graphStats) {
|
|
11605
|
+
console.log(`code-graph: ${graphStats.nodes} nodes, ${graphStats.edges} edges, ${graphStats.unresolved} unresolved`);
|
|
11606
|
+
} else {
|
|
11607
|
+
console.log(`code-graph: missing (${graphPath}); run cdd-kit code-map`);
|
|
11608
|
+
}
|
|
11609
|
+
if (!selected.probe.available) {
|
|
11610
|
+
console.log(`CodeGraph: unavailable (${selected.probe.command})`);
|
|
11611
|
+
} else if (!selected.probe.initialized) {
|
|
11612
|
+
console.log("CodeGraph: available but project is not initialized (.codegraph/ missing)");
|
|
11613
|
+
}
|
|
11614
|
+
console.log("Next: run `codegraph init -i` to enable semantic graph queries, or continue with code-map fallback.");
|
|
11615
|
+
}
|
|
11616
|
+
return freshness.status === "config-error" ? 1 : 0;
|
|
11617
|
+
}
|
|
11618
|
+
async function graphSync(opts = {}) {
|
|
11619
|
+
const selected = selectEngine({ ...opts, engine: opts.engine ?? "codegraph" });
|
|
11620
|
+
if ("error" in selected)
|
|
11621
|
+
return printEngineError(selected.error, opts.json, selected.probe);
|
|
11622
|
+
if (selected.engine !== "codegraph") {
|
|
11623
|
+
return printEngineError("graph sync requires CodeGraph; code-map fallback refreshes during query/impact.", opts.json, selected.probe);
|
|
11624
|
+
}
|
|
11625
|
+
const args = ["sync"];
|
|
11626
|
+
if (opts.path)
|
|
11627
|
+
args.push(opts.path);
|
|
11628
|
+
return pipeResult(runCodeGraph(args));
|
|
11629
|
+
}
|
|
11630
|
+
async function graphQuery(term, opts) {
|
|
11631
|
+
const selected = selectEngine(opts);
|
|
11632
|
+
if ("error" in selected)
|
|
11633
|
+
return printEngineError(selected.error, opts.json, selected.probe);
|
|
11634
|
+
if (selected.engine === "codegraph") {
|
|
11635
|
+
const args = ["query", term, "--limit", String(opts.limit)];
|
|
11636
|
+
if (opts.json)
|
|
11637
|
+
args.push("--json");
|
|
11638
|
+
return pipeResult(runCodeGraph(args));
|
|
11639
|
+
}
|
|
11640
|
+
if (selected.engine === "native") {
|
|
11641
|
+
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
11642
|
+
const ensured = await ensureNativeGraph(mapPath, opts.refresh !== false);
|
|
11643
|
+
if (ensured.error)
|
|
11644
|
+
return printEngineError(ensured.error, opts.json, selected.probe);
|
|
11645
|
+
try {
|
|
11646
|
+
const graph2 = loadCodeGraph(ensured.graphPath);
|
|
11647
|
+
const results = searchGraph(graph2, term, opts.limit);
|
|
11648
|
+
if (opts.json) {
|
|
11649
|
+
writeJson({ engine: "native", graph: ensured.graphPath, query: term, refreshed: ensured.refreshed, results });
|
|
11650
|
+
} else {
|
|
11651
|
+
console.log(`graph: ${ensured.graphPath}${ensured.refreshed ? " (refreshed)" : ""}`);
|
|
11652
|
+
console.log(`query: ${term}`);
|
|
11653
|
+
console.log(`results: ${results.length}`);
|
|
11654
|
+
for (const result of results) {
|
|
11655
|
+
const n = result.node;
|
|
11656
|
+
console.log(`- ${n.kind}: ${n.qualified_name} lines ${n.start_line}-${n.end_line}`);
|
|
11657
|
+
console.log(` edges: ${result.edges.incoming} incoming, ${result.edges.outgoing} outgoing`);
|
|
11658
|
+
}
|
|
11659
|
+
console.log("Next: run cdd-kit graph impact <node/file/symbol> before editing.");
|
|
11660
|
+
}
|
|
11661
|
+
return results.length === 0 ? 1 : 0;
|
|
11662
|
+
} catch (err) {
|
|
11663
|
+
return printEngineError(err.message, opts.json, selected.probe);
|
|
11664
|
+
}
|
|
11665
|
+
}
|
|
11666
|
+
return indexQuery(term, {
|
|
11667
|
+
map: opts.map || ".cdd/code-map.yml",
|
|
11668
|
+
limit: opts.limit,
|
|
11669
|
+
json: opts.json === true,
|
|
11670
|
+
refresh: opts.refresh !== false
|
|
11671
|
+
});
|
|
11672
|
+
}
|
|
11673
|
+
async function graphImpact2(term, opts) {
|
|
11674
|
+
const selected = selectEngine(opts);
|
|
11675
|
+
if ("error" in selected)
|
|
11676
|
+
return printEngineError(selected.error, opts.json, selected.probe);
|
|
11677
|
+
if (selected.engine === "codegraph") {
|
|
11678
|
+
const args = ["impact", term, "--depth", String(opts.depth)];
|
|
11679
|
+
if (opts.json)
|
|
11680
|
+
args.push("--json");
|
|
11681
|
+
return pipeResult(runCodeGraph(args));
|
|
11682
|
+
}
|
|
11683
|
+
if (selected.engine === "native") {
|
|
11684
|
+
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
11685
|
+
const ensured = await ensureNativeGraph(mapPath, opts.refresh !== false);
|
|
11686
|
+
if (ensured.error)
|
|
11687
|
+
return printEngineError(ensured.error, opts.json, selected.probe);
|
|
11688
|
+
try {
|
|
11689
|
+
const graph2 = loadCodeGraph(ensured.graphPath);
|
|
11690
|
+
const impact = graphImpact(graph2, term, opts.depth, opts.limit);
|
|
11691
|
+
if (!impact)
|
|
11692
|
+
return printEngineError(`No graph node matched "${term}". Try \`cdd-kit graph query "${term}"\` first.`, opts.json, selected.probe);
|
|
11693
|
+
if (opts.json) {
|
|
11694
|
+
writeJson({ engine: "native", graph: ensured.graphPath, query: term, refreshed: ensured.refreshed, ...impact });
|
|
11695
|
+
} else {
|
|
11696
|
+
console.log(`graph: ${ensured.graphPath}${ensured.refreshed ? " (refreshed)" : ""}`);
|
|
11697
|
+
console.log(`target: ${impact.target.qualified_name} (${impact.target.kind})`);
|
|
11698
|
+
console.log(`impact depth: ${impact.depth}`);
|
|
11699
|
+
console.log("nodes:");
|
|
11700
|
+
for (const node of impact.nodes) {
|
|
11701
|
+
console.log(`- ${node.kind}: ${node.qualified_name} lines ${node.start_line}-${node.end_line}`);
|
|
11702
|
+
}
|
|
11703
|
+
console.log("edges:");
|
|
11704
|
+
for (const edge of impact.edges.slice(0, opts.limit)) {
|
|
11705
|
+
const source = graph2.nodes.find((n) => n.id === edge.source)?.qualified_name ?? edge.source;
|
|
11706
|
+
const target = graph2.nodes.find((n) => n.id === edge.target)?.qualified_name ?? edge.target;
|
|
11707
|
+
console.log(`- ${edge.kind}: ${source} -> ${target}${edge.line ? ` line ${edge.line}` : ""} (${edge.provenance})`);
|
|
11708
|
+
}
|
|
11709
|
+
console.log("Next: inspect target plus listed callers/callees/imports before editing.");
|
|
11710
|
+
}
|
|
11711
|
+
return 0;
|
|
11712
|
+
} catch (err) {
|
|
11713
|
+
return printEngineError(err.message, opts.json, selected.probe);
|
|
11714
|
+
}
|
|
11715
|
+
}
|
|
11716
|
+
if (!opts.json && opts.depth > 1) {
|
|
11717
|
+
console.log("graph engine: code-map fallback (depth is limited to direct imports/dependents)");
|
|
11718
|
+
}
|
|
11719
|
+
return indexImpact(term, {
|
|
11720
|
+
map: opts.map || ".cdd/code-map.yml",
|
|
11721
|
+
limit: opts.limit,
|
|
11722
|
+
json: opts.json === true,
|
|
11723
|
+
refresh: opts.refresh !== false
|
|
11724
|
+
});
|
|
11725
|
+
}
|
|
11726
|
+
async function graphContext2(task, opts) {
|
|
11727
|
+
const selected = selectEngine(opts);
|
|
11728
|
+
if ("error" in selected)
|
|
11729
|
+
return printEngineError(selected.error, opts.json, selected.probe);
|
|
11730
|
+
if (selected.engine === "codegraph") {
|
|
11731
|
+
const args = ["context", task, "--max-nodes", String(opts.maxNodes), "--format", opts.json ? "json" : "markdown"];
|
|
11732
|
+
return pipeResult(runCodeGraph(args));
|
|
11733
|
+
}
|
|
11734
|
+
if (selected.engine === "native") {
|
|
11735
|
+
const mapPath2 = opts.map || ".cdd/code-map.yml";
|
|
11736
|
+
const ensured = await ensureNativeGraph(mapPath2, opts.refresh !== false);
|
|
11737
|
+
if (ensured.error)
|
|
11738
|
+
return printEngineError(ensured.error, opts.json, selected.probe);
|
|
11739
|
+
try {
|
|
11740
|
+
const graph2 = loadCodeGraph(ensured.graphPath);
|
|
11741
|
+
const context2 = graphContext(graph2, task, opts.maxNodes);
|
|
11742
|
+
if (opts.json) {
|
|
11743
|
+
writeJson({ engine: "native", graph: ensured.graphPath, refreshed: ensured.refreshed, ...context2 });
|
|
11744
|
+
} else {
|
|
11745
|
+
console.log(`graph: ${ensured.graphPath}${ensured.refreshed ? " (refreshed)" : ""}`);
|
|
11746
|
+
console.log(`task: ${task}`);
|
|
11747
|
+
console.log("entry-points:");
|
|
11748
|
+
for (const entry of context2.entry_points) {
|
|
11749
|
+
console.log(`- ${entry.node.kind}: ${entry.node.qualified_name} lines ${entry.node.start_line}-${entry.node.end_line}`);
|
|
11750
|
+
}
|
|
11751
|
+
console.log("related edges:");
|
|
11752
|
+
for (const edge of context2.edges.slice(0, opts.maxNodes)) {
|
|
11753
|
+
const source = graph2.nodes.find((n) => n.id === edge.source)?.qualified_name ?? edge.source;
|
|
11754
|
+
const target = graph2.nodes.find((n) => n.id === edge.target)?.qualified_name ?? edge.target;
|
|
11755
|
+
console.log(`- ${edge.kind}: ${source} -> ${target}${edge.line ? ` line ${edge.line}` : ""}`);
|
|
11756
|
+
}
|
|
11757
|
+
console.log("Next: run cdd-kit graph impact on the most relevant entry point before editing.");
|
|
11758
|
+
}
|
|
11759
|
+
return context2.entry_points.length === 0 ? 1 : 0;
|
|
11760
|
+
} catch (err) {
|
|
11761
|
+
return printEngineError(err.message, opts.json, selected.probe);
|
|
11762
|
+
}
|
|
11763
|
+
}
|
|
11764
|
+
const mapPath = opts.map || ".cdd/code-map.yml";
|
|
11765
|
+
const freshness = await ensureCodeMapFresh(mapPath, opts.refresh !== false);
|
|
11766
|
+
if (freshness.error)
|
|
11767
|
+
return printEngineError(freshness.error, opts.json, selected.probe);
|
|
11768
|
+
if (!existsSync24(mapPath))
|
|
11769
|
+
return printEngineError(`${mapPath} is missing; run \`cdd-kit code-map\` first.`, opts.json, selected.probe);
|
|
11770
|
+
let entries;
|
|
11771
|
+
try {
|
|
11772
|
+
entries = loadCodeMapEntries(mapPath);
|
|
11773
|
+
} catch (err) {
|
|
11774
|
+
return printEngineError(`${mapPath} is not readable YAML: ${err.message}`, opts.json, selected.probe);
|
|
11775
|
+
}
|
|
11776
|
+
const results = queryEntries(entries, task).slice(0, opts.maxNodes);
|
|
11777
|
+
const payload = {
|
|
11778
|
+
engine: "codemap",
|
|
11779
|
+
query: task,
|
|
11780
|
+
refreshed: freshness.refreshed,
|
|
11781
|
+
warning: "CodeGraph is not active; context is built from code-map symbol/file matches only.",
|
|
11782
|
+
candidates: results,
|
|
11783
|
+
next: results.length > 0 ? "Run cdd-kit graph impact <candidate path or symbol> before editing." : "Try a symbol name, file stem, route/component name, or initialize CodeGraph for semantic context."
|
|
11784
|
+
};
|
|
11785
|
+
if (opts.json) {
|
|
11786
|
+
writeJson(payload);
|
|
11787
|
+
} else {
|
|
11788
|
+
console.log(`graph engine: code-map fallback${freshness.refreshed ? " (refreshed)" : ""}`);
|
|
11789
|
+
console.log(`task: ${task}`);
|
|
11790
|
+
if (results.length === 0) {
|
|
11791
|
+
console.log("candidates: none");
|
|
11792
|
+
console.log(payload.next);
|
|
11793
|
+
return 1;
|
|
11794
|
+
}
|
|
11795
|
+
console.log("candidates:");
|
|
11796
|
+
for (const result of results) {
|
|
11797
|
+
console.log(`- ${result.path} (${result.total_lines} lines)`);
|
|
11798
|
+
for (const match of result.matches.slice(0, 5)) {
|
|
11799
|
+
const loc = match.lines ? ` lines ${match.lines}` : match.line ? ` line ${match.line}` : "";
|
|
11800
|
+
console.log(` - ${match.kind}: ${match.name}${loc}`);
|
|
11801
|
+
}
|
|
11802
|
+
}
|
|
11803
|
+
console.log(payload.next);
|
|
11804
|
+
}
|
|
11805
|
+
return results.length === 0 ? 1 : 0;
|
|
11806
|
+
}
|
|
11807
|
+
var init_graph = __esm({
|
|
11808
|
+
"src/commands/graph.ts"() {
|
|
11809
|
+
"use strict";
|
|
11810
|
+
init_freshness();
|
|
11811
|
+
init_index_reader();
|
|
11812
|
+
init_reader();
|
|
11813
|
+
init_queries();
|
|
11814
|
+
init_index_query();
|
|
11815
|
+
init_index_impact();
|
|
11816
|
+
}
|
|
11817
|
+
});
|
|
11818
|
+
|
|
11819
|
+
// src/mcp/server.ts
|
|
11820
|
+
var server_exports = {};
|
|
11821
|
+
__export(server_exports, {
|
|
11822
|
+
runMcpServer: () => runMcpServer
|
|
11823
|
+
});
|
|
11824
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
11825
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11826
|
+
import { createInterface } from "readline";
|
|
11827
|
+
async function runMcpServer(opts) {
|
|
11828
|
+
const rl = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
11829
|
+
for await (const line of rl) {
|
|
11830
|
+
if (!line.trim())
|
|
11831
|
+
continue;
|
|
11832
|
+
let request;
|
|
11833
|
+
try {
|
|
11834
|
+
request = JSON.parse(line);
|
|
11835
|
+
} catch (err) {
|
|
11836
|
+
writeError(null, -32700, `Parse error: ${err.message}`);
|
|
11837
|
+
continue;
|
|
11838
|
+
}
|
|
11839
|
+
if (!request.method) {
|
|
11840
|
+
if ("id" in request)
|
|
11841
|
+
writeError(request.id ?? null, -32600, "Invalid Request: missing method");
|
|
11842
|
+
continue;
|
|
11843
|
+
}
|
|
11844
|
+
try {
|
|
11845
|
+
const result = await handleRequest(request, opts);
|
|
11846
|
+
if ("id" in request)
|
|
11847
|
+
writeResult(request.id ?? null, result);
|
|
11848
|
+
} catch (err) {
|
|
11849
|
+
if ("id" in request)
|
|
11850
|
+
writeError(request.id ?? null, -32e3, err.message);
|
|
11851
|
+
}
|
|
11852
|
+
}
|
|
11853
|
+
}
|
|
11854
|
+
async function handleRequest(request, opts) {
|
|
11855
|
+
switch (request.method) {
|
|
11856
|
+
case "initialize": {
|
|
11857
|
+
const params = asObject(request.params);
|
|
11858
|
+
return {
|
|
11859
|
+
protocolVersion: typeof params.protocolVersion === "string" ? params.protocolVersion : "2024-11-05",
|
|
11860
|
+
capabilities: {
|
|
11861
|
+
tools: { listChanged: false },
|
|
11862
|
+
resources: {},
|
|
11863
|
+
prompts: {}
|
|
11864
|
+
},
|
|
11865
|
+
serverInfo: {
|
|
11866
|
+
name: "cdd-kit",
|
|
11867
|
+
version: opts.version
|
|
11868
|
+
}
|
|
11869
|
+
};
|
|
11870
|
+
}
|
|
11871
|
+
case "ping":
|
|
11872
|
+
return {};
|
|
11873
|
+
case "tools/list":
|
|
11874
|
+
return { tools };
|
|
11875
|
+
case "tools/call": {
|
|
11876
|
+
const params = asObject(request.params);
|
|
11877
|
+
const name = requireString(params, "name");
|
|
11878
|
+
const args = asObject(params.arguments);
|
|
11879
|
+
return callTool(name, args);
|
|
11880
|
+
}
|
|
11881
|
+
case "resources/list":
|
|
11882
|
+
return { resources: [] };
|
|
11883
|
+
case "prompts/list":
|
|
11884
|
+
return { prompts: [] };
|
|
11885
|
+
case "notifications/initialized":
|
|
11886
|
+
return {};
|
|
11887
|
+
default:
|
|
11888
|
+
throw new Error(`Method not found: ${request.method}`);
|
|
11889
|
+
}
|
|
11890
|
+
}
|
|
11891
|
+
function callTool(name, args) {
|
|
11892
|
+
switch (name) {
|
|
11893
|
+
case "cdd_graph_status":
|
|
11894
|
+
return runCddJson([
|
|
11895
|
+
"graph",
|
|
11896
|
+
"status",
|
|
11897
|
+
"--engine",
|
|
11898
|
+
optionalString(args.engine, "auto"),
|
|
11899
|
+
"--map",
|
|
11900
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11901
|
+
"--json"
|
|
11902
|
+
]);
|
|
11903
|
+
case "cdd_graph_query":
|
|
11904
|
+
return runCddJson([
|
|
11905
|
+
"graph",
|
|
11906
|
+
"query",
|
|
11907
|
+
requireString(args, "query"),
|
|
11908
|
+
"--engine",
|
|
11909
|
+
optionalString(args.engine, "auto"),
|
|
11910
|
+
"--map",
|
|
11911
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11912
|
+
"--limit",
|
|
11913
|
+
String(optionalInt(args.limit, 10)),
|
|
11914
|
+
"--json",
|
|
11915
|
+
...refreshArgs(args)
|
|
11916
|
+
]);
|
|
11917
|
+
case "cdd_graph_context":
|
|
11918
|
+
return runCddJson([
|
|
11919
|
+
"graph",
|
|
11920
|
+
"context",
|
|
11921
|
+
requireString(args, "task"),
|
|
11922
|
+
"--engine",
|
|
11923
|
+
optionalString(args.engine, "auto"),
|
|
11924
|
+
"--map",
|
|
11925
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11926
|
+
"--max-nodes",
|
|
11927
|
+
String(optionalInt(args.maxNodes, 20)),
|
|
11928
|
+
"--json",
|
|
11929
|
+
...refreshArgs(args)
|
|
11930
|
+
]);
|
|
11931
|
+
case "cdd_graph_impact":
|
|
11932
|
+
return runCddJson([
|
|
11933
|
+
"graph",
|
|
11934
|
+
"impact",
|
|
11935
|
+
requireString(args, "target"),
|
|
11936
|
+
"--engine",
|
|
11937
|
+
optionalString(args.engine, "auto"),
|
|
11938
|
+
"--map",
|
|
11939
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11940
|
+
"--limit",
|
|
11941
|
+
String(optionalInt(args.limit, 20)),
|
|
11942
|
+
"--depth",
|
|
11943
|
+
String(optionalInt(args.depth, 2)),
|
|
11944
|
+
"--json",
|
|
11945
|
+
...refreshArgs(args)
|
|
11946
|
+
]);
|
|
11947
|
+
case "cdd_index_query":
|
|
11948
|
+
return runCddJson([
|
|
11949
|
+
"index",
|
|
11950
|
+
"query",
|
|
11951
|
+
requireString(args, "query"),
|
|
11952
|
+
"--map",
|
|
11953
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11954
|
+
"--limit",
|
|
11955
|
+
String(optionalInt(args.limit, 10)),
|
|
11956
|
+
"--json",
|
|
11957
|
+
...refreshArgs(args)
|
|
11958
|
+
]);
|
|
11959
|
+
case "cdd_index_impact":
|
|
11960
|
+
return runCddJson([
|
|
11961
|
+
"index",
|
|
11962
|
+
"impact",
|
|
11963
|
+
requireString(args, "target"),
|
|
11964
|
+
"--map",
|
|
11965
|
+
optionalString(args.map, DEFAULT_MAP),
|
|
11966
|
+
"--limit",
|
|
11967
|
+
String(optionalInt(args.limit, 20)),
|
|
11968
|
+
"--json",
|
|
11969
|
+
...refreshArgs(args)
|
|
11970
|
+
]);
|
|
11971
|
+
default:
|
|
11972
|
+
return {
|
|
11973
|
+
isError: true,
|
|
11974
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }]
|
|
11975
|
+
};
|
|
11976
|
+
}
|
|
11977
|
+
}
|
|
11978
|
+
function runCddJson(args) {
|
|
11979
|
+
const cliPath = process.argv[1] || fileURLToPath3(import.meta.url);
|
|
11980
|
+
const result = spawnSync4(process.execPath, [cliPath, ...args], {
|
|
11981
|
+
cwd: process.cwd(),
|
|
11982
|
+
env: process.env,
|
|
11983
|
+
encoding: "utf8"
|
|
11984
|
+
});
|
|
11985
|
+
const stdout = result.stdout?.trim() ?? "";
|
|
11986
|
+
const stderr = result.stderr?.trim() ?? "";
|
|
11987
|
+
const isError = !!result.error || (result.status ?? 1) !== 0;
|
|
11988
|
+
if (stdout) {
|
|
11989
|
+
return {
|
|
11990
|
+
isError: isError || void 0,
|
|
11991
|
+
content: [{ type: "text", text: stdout }]
|
|
11992
|
+
};
|
|
11993
|
+
}
|
|
11994
|
+
return {
|
|
11995
|
+
isError: true,
|
|
11996
|
+
content: [{ type: "text", text: result.error?.message || stderr || `cdd-kit exited with status ${result.status}` }]
|
|
11997
|
+
};
|
|
11998
|
+
}
|
|
11999
|
+
function refreshArgs(args) {
|
|
12000
|
+
return args.refresh === false ? ["--no-refresh"] : [];
|
|
12001
|
+
}
|
|
12002
|
+
function asObject(value) {
|
|
12003
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
12004
|
+
}
|
|
12005
|
+
function requireString(args, key) {
|
|
12006
|
+
const value = args[key];
|
|
12007
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
12008
|
+
throw new Error(`Missing required string argument: ${key}`);
|
|
12009
|
+
}
|
|
12010
|
+
return value;
|
|
12011
|
+
}
|
|
12012
|
+
function optionalString(value, fallback) {
|
|
12013
|
+
return typeof value === "string" && value.trim() ? value : fallback;
|
|
12014
|
+
}
|
|
12015
|
+
function optionalInt(value, fallback) {
|
|
12016
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number.parseInt(value, 10) : fallback;
|
|
12017
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
|
|
12018
|
+
}
|
|
12019
|
+
function writeResult(id, result) {
|
|
12020
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, result })}
|
|
12021
|
+
`);
|
|
12022
|
+
}
|
|
12023
|
+
function writeError(id, code, message) {
|
|
12024
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } })}
|
|
12025
|
+
`);
|
|
12026
|
+
}
|
|
12027
|
+
var DEFAULT_MAP, tools;
|
|
12028
|
+
var init_server = __esm({
|
|
12029
|
+
"src/mcp/server.ts"() {
|
|
12030
|
+
"use strict";
|
|
12031
|
+
DEFAULT_MAP = ".cdd/code-map.yml";
|
|
12032
|
+
tools = [
|
|
12033
|
+
{
|
|
12034
|
+
name: "cdd_graph_status",
|
|
12035
|
+
description: "Show the active cdd-kit graph engine and code-map/code-graph freshness for the current workspace.",
|
|
12036
|
+
inputSchema: {
|
|
12037
|
+
type: "object",
|
|
12038
|
+
properties: {
|
|
12039
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12040
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" }
|
|
12041
|
+
},
|
|
12042
|
+
additionalProperties: false
|
|
12043
|
+
}
|
|
12044
|
+
},
|
|
12045
|
+
{
|
|
12046
|
+
name: "cdd_graph_query",
|
|
12047
|
+
description: "Search native graph symbols/files and return candidate nodes with line ranges.",
|
|
12048
|
+
inputSchema: {
|
|
12049
|
+
type: "object",
|
|
12050
|
+
properties: {
|
|
12051
|
+
query: { type: "string", description: "Symbol, file path, file stem, class, function, component, or route term." },
|
|
12052
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
12053
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12054
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12055
|
+
refresh: { type: "boolean", default: true }
|
|
12056
|
+
},
|
|
12057
|
+
required: ["query"],
|
|
12058
|
+
additionalProperties: false
|
|
12059
|
+
}
|
|
12060
|
+
},
|
|
12061
|
+
{
|
|
12062
|
+
name: "cdd_graph_context",
|
|
12063
|
+
description: "Build graph-first task context from a task, symptom, or known feature term.",
|
|
12064
|
+
inputSchema: {
|
|
12065
|
+
type: "object",
|
|
12066
|
+
properties: {
|
|
12067
|
+
task: { type: "string", description: "Task, bug symptom, feature name, screen name, or domain term." },
|
|
12068
|
+
maxNodes: { type: "integer", minimum: 1, maximum: 100, default: 20 },
|
|
12069
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12070
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12071
|
+
refresh: { type: "boolean", default: true }
|
|
12072
|
+
},
|
|
12073
|
+
required: ["task"],
|
|
12074
|
+
additionalProperties: false
|
|
12075
|
+
}
|
|
12076
|
+
},
|
|
12077
|
+
{
|
|
12078
|
+
name: "cdd_graph_impact",
|
|
12079
|
+
description: "Analyze callers, callees, imports, references, and dependents for a file or symbol before editing.",
|
|
12080
|
+
inputSchema: {
|
|
12081
|
+
type: "object",
|
|
12082
|
+
properties: {
|
|
12083
|
+
target: { type: "string", description: "Candidate file path, symbol, graph node id, or qualified name." },
|
|
12084
|
+
depth: { type: "integer", minimum: 1, maximum: 10, default: 2 },
|
|
12085
|
+
limit: { type: "integer", minimum: 1, maximum: 200, default: 20 },
|
|
12086
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12087
|
+
engine: { type: "string", enum: ["auto", "native", "codegraph", "codemap"], default: "auto" },
|
|
12088
|
+
refresh: { type: "boolean", default: true }
|
|
12089
|
+
},
|
|
12090
|
+
required: ["target"],
|
|
12091
|
+
additionalProperties: false
|
|
12092
|
+
}
|
|
12093
|
+
},
|
|
12094
|
+
{
|
|
12095
|
+
name: "cdd_index_query",
|
|
12096
|
+
description: "Fallback code-map query for files, symbols, imports, and line ranges.",
|
|
12097
|
+
inputSchema: {
|
|
12098
|
+
type: "object",
|
|
12099
|
+
properties: {
|
|
12100
|
+
query: { type: "string", description: "Symbol, file path, import module, enum member, or substring." },
|
|
12101
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
12102
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12103
|
+
refresh: { type: "boolean", default: true }
|
|
12104
|
+
},
|
|
12105
|
+
required: ["query"],
|
|
12106
|
+
additionalProperties: false
|
|
12107
|
+
}
|
|
12108
|
+
},
|
|
12109
|
+
{
|
|
12110
|
+
name: "cdd_index_impact",
|
|
12111
|
+
description: "Fallback code-map impact query for local imports and direct dependents.",
|
|
12112
|
+
inputSchema: {
|
|
12113
|
+
type: "object",
|
|
12114
|
+
properties: {
|
|
12115
|
+
target: { type: "string", description: "File path or unique symbol." },
|
|
12116
|
+
limit: { type: "integer", minimum: 1, maximum: 200, default: 20 },
|
|
12117
|
+
map: { type: "string", description: "Code-map YAML path.", default: DEFAULT_MAP },
|
|
12118
|
+
refresh: { type: "boolean", default: true }
|
|
12119
|
+
},
|
|
12120
|
+
required: ["target"],
|
|
12121
|
+
additionalProperties: false
|
|
12122
|
+
}
|
|
12123
|
+
}
|
|
12124
|
+
];
|
|
10864
12125
|
}
|
|
10865
12126
|
});
|
|
10866
12127
|
|
|
@@ -10869,28 +12130,28 @@ var archive_exports = {};
|
|
|
10869
12130
|
__export(archive_exports, {
|
|
10870
12131
|
archive: () => archive
|
|
10871
12132
|
});
|
|
10872
|
-
import { join as
|
|
10873
|
-
import { existsSync as
|
|
12133
|
+
import { join as join26 } from "path";
|
|
12134
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync10, renameSync as renameSync2, readFileSync as readFileSync27, writeFileSync as writeFileSync13, appendFileSync, cpSync as cpSync3, rmSync as rmSync3 } from "fs";
|
|
10874
12135
|
import yaml4 from "js-yaml";
|
|
10875
12136
|
async function archive(changeId) {
|
|
10876
12137
|
const cwd = process.cwd();
|
|
10877
|
-
const changeDir =
|
|
12138
|
+
const changeDir = join26(cwd, "specs", "changes", changeId);
|
|
10878
12139
|
const archiveYear = (/* @__PURE__ */ new Date()).getFullYear().toString();
|
|
10879
|
-
const archiveBase =
|
|
10880
|
-
const archiveDir =
|
|
10881
|
-
const indexPath =
|
|
10882
|
-
if (!
|
|
12140
|
+
const archiveBase = join26(cwd, "specs", "archive", archiveYear);
|
|
12141
|
+
const archiveDir = join26(archiveBase, changeId);
|
|
12142
|
+
const indexPath = join26(cwd, "specs", "archive", "INDEX.md");
|
|
12143
|
+
if (!existsSync25(changeDir)) {
|
|
10883
12144
|
log.error(`Change not found: specs/changes/${changeId}`);
|
|
10884
12145
|
process.exit(1);
|
|
10885
12146
|
}
|
|
10886
|
-
if (
|
|
12147
|
+
if (existsSync25(archiveDir)) {
|
|
10887
12148
|
log.error(`Already archived: specs/archive/${archiveYear}/${changeId}`);
|
|
10888
12149
|
process.exit(1);
|
|
10889
12150
|
}
|
|
10890
|
-
const tasksPath =
|
|
10891
|
-
if (
|
|
12151
|
+
const tasksPath = join26(changeDir, "tasks.yml");
|
|
12152
|
+
if (existsSync25(tasksPath)) {
|
|
10892
12153
|
try {
|
|
10893
|
-
const raw =
|
|
12154
|
+
const raw = readFileSync27(tasksPath, "utf8");
|
|
10894
12155
|
const data = yaml4.load(raw);
|
|
10895
12156
|
if (data?.status === "gate-blocked") {
|
|
10896
12157
|
log.warn("tasks.yml has status: gate-blocked \u2014 archiving anyway (change was paused).");
|
|
@@ -10903,7 +12164,7 @@ async function archive(changeId) {
|
|
|
10903
12164
|
log.warn("tasks.yml could not be parsed \u2014 archiving anyway.");
|
|
10904
12165
|
}
|
|
10905
12166
|
}
|
|
10906
|
-
if (!
|
|
12167
|
+
if (!existsSync25(archiveBase)) {
|
|
10907
12168
|
mkdirSync10(archiveBase, { recursive: true });
|
|
10908
12169
|
}
|
|
10909
12170
|
try {
|
|
@@ -10920,7 +12181,7 @@ async function archive(changeId) {
|
|
|
10920
12181
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10921
12182
|
const indexLine = `| ${changeId} | ${archiveYear} | ${today} | specs/archive/${archiveYear}/${changeId}/ |
|
|
10922
12183
|
`;
|
|
10923
|
-
if (!
|
|
12184
|
+
if (!existsSync25(indexPath)) {
|
|
10924
12185
|
writeFileSync13(indexPath, `# Archive Index
|
|
10925
12186
|
|
|
10926
12187
|
| change-id | year | archived-date | path |
|
|
@@ -10945,19 +12206,19 @@ var abandon_exports = {};
|
|
|
10945
12206
|
__export(abandon_exports, {
|
|
10946
12207
|
abandon: () => abandon
|
|
10947
12208
|
});
|
|
10948
|
-
import { join as
|
|
10949
|
-
import { existsSync as
|
|
12209
|
+
import { join as join27 } from "path";
|
|
12210
|
+
import { existsSync as existsSync26, readFileSync as readFileSync28, writeFileSync as writeFileSync14, appendFileSync as appendFileSync2, mkdirSync as mkdirSync11 } from "fs";
|
|
10950
12211
|
import yaml5 from "js-yaml";
|
|
10951
12212
|
async function abandon(changeId, opts) {
|
|
10952
12213
|
const cwd = process.cwd();
|
|
10953
|
-
const changeDir =
|
|
10954
|
-
const tasksPath =
|
|
10955
|
-
if (!
|
|
12214
|
+
const changeDir = join27(cwd, "specs", "changes", changeId);
|
|
12215
|
+
const tasksPath = join27(changeDir, "tasks.yml");
|
|
12216
|
+
if (!existsSync26(changeDir)) {
|
|
10956
12217
|
log.error(`Change not found: specs/changes/${changeId}`);
|
|
10957
12218
|
process.exit(1);
|
|
10958
12219
|
}
|
|
10959
|
-
if (
|
|
10960
|
-
const raw =
|
|
12220
|
+
if (existsSync26(tasksPath)) {
|
|
12221
|
+
const raw = readFileSync28(tasksPath, "utf8");
|
|
10961
12222
|
const data = yaml5.load(raw) ?? {};
|
|
10962
12223
|
data["status"] = "abandoned";
|
|
10963
12224
|
if (!data["change-id"]) {
|
|
@@ -10966,15 +12227,15 @@ async function abandon(changeId, opts) {
|
|
|
10966
12227
|
writeFileSync14(tasksPath, yaml5.dump(data, { lineWidth: -1, noRefs: true }), "utf8");
|
|
10967
12228
|
}
|
|
10968
12229
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10969
|
-
const archiveDir =
|
|
10970
|
-
const indexPath =
|
|
12230
|
+
const archiveDir = join27(cwd, "specs", "archive");
|
|
12231
|
+
const indexPath = join27(archiveDir, "INDEX.md");
|
|
10971
12232
|
const reason = opts.reason ?? "no reason given";
|
|
10972
12233
|
const indexLine = `| ${changeId} | abandoned | ${today} | ${reason} |
|
|
10973
12234
|
`;
|
|
10974
|
-
if (!
|
|
12235
|
+
if (!existsSync26(archiveDir)) {
|
|
10975
12236
|
mkdirSync11(archiveDir, { recursive: true });
|
|
10976
12237
|
}
|
|
10977
|
-
if (!
|
|
12238
|
+
if (!existsSync26(indexPath)) {
|
|
10978
12239
|
writeFileSync14(indexPath, `# Archive Index
|
|
10979
12240
|
|
|
10980
12241
|
| change-id | status | date | notes |
|
|
@@ -10999,15 +12260,15 @@ var list_changes_exports = {};
|
|
|
10999
12260
|
__export(list_changes_exports, {
|
|
11000
12261
|
listChanges: () => listChanges
|
|
11001
12262
|
});
|
|
11002
|
-
import { join as
|
|
11003
|
-
import { existsSync as
|
|
12263
|
+
import { join as join28 } from "path";
|
|
12264
|
+
import { existsSync as existsSync27, readdirSync as readdirSync13, readFileSync as readFileSync29 } from "fs";
|
|
11004
12265
|
import yaml6 from "js-yaml";
|
|
11005
12266
|
async function listChanges() {
|
|
11006
12267
|
const cwd = process.cwd();
|
|
11007
|
-
const changesDir =
|
|
12268
|
+
const changesDir = join28(cwd, "specs", "changes");
|
|
11008
12269
|
log.blank();
|
|
11009
12270
|
const active = [];
|
|
11010
|
-
if (
|
|
12271
|
+
if (existsSync27(changesDir)) {
|
|
11011
12272
|
active.push(...readdirSync13(changesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name));
|
|
11012
12273
|
}
|
|
11013
12274
|
if (active.length === 0) {
|
|
@@ -11015,12 +12276,12 @@ async function listChanges() {
|
|
|
11015
12276
|
} else {
|
|
11016
12277
|
log.info("Active changes:");
|
|
11017
12278
|
for (const id of active) {
|
|
11018
|
-
const tasksPath =
|
|
12279
|
+
const tasksPath = join28(changesDir, id, "tasks.yml");
|
|
11019
12280
|
let status = "in-progress";
|
|
11020
12281
|
let pending = 0;
|
|
11021
|
-
if (
|
|
12282
|
+
if (existsSync27(tasksPath)) {
|
|
11022
12283
|
try {
|
|
11023
|
-
const raw =
|
|
12284
|
+
const raw = readFileSync29(tasksPath, "utf8");
|
|
11024
12285
|
const data = yaml6.load(raw);
|
|
11025
12286
|
if (data?.status)
|
|
11026
12287
|
status = data.status;
|
|
@@ -11052,8 +12313,8 @@ __export(context_exports, {
|
|
|
11052
12313
|
rejectContextExpansion: () => rejectContextExpansion,
|
|
11053
12314
|
requestContextExpansion: () => requestContextExpansion
|
|
11054
12315
|
});
|
|
11055
|
-
import { existsSync as
|
|
11056
|
-
import { join as
|
|
12316
|
+
import { existsSync as existsSync28, readFileSync as readFileSync30, writeFileSync as writeFileSync15 } from "fs";
|
|
12317
|
+
import { join as join29 } from "path";
|
|
11057
12318
|
import picomatch2 from "picomatch";
|
|
11058
12319
|
function normalizePath(path) {
|
|
11059
12320
|
return path.replace(/\\/g, "/").replace(/^\.\//, "").trim();
|
|
@@ -11068,15 +12329,15 @@ function validateRepoRelativePath(path) {
|
|
|
11068
12329
|
return null;
|
|
11069
12330
|
}
|
|
11070
12331
|
function manifestPathFor(changeId) {
|
|
11071
|
-
return
|
|
12332
|
+
return join29(process.cwd(), "specs", "changes", changeId, "context-manifest.md");
|
|
11072
12333
|
}
|
|
11073
12334
|
function readManifest(changeId) {
|
|
11074
12335
|
const manifestPath = manifestPathFor(changeId);
|
|
11075
|
-
if (!
|
|
12336
|
+
if (!existsSync28(manifestPath)) {
|
|
11076
12337
|
log.error(`context manifest not found: specs/changes/${changeId}/context-manifest.md`);
|
|
11077
12338
|
process.exit(1);
|
|
11078
12339
|
}
|
|
11079
|
-
return
|
|
12340
|
+
return readFileSync30(manifestPath, "utf8");
|
|
11080
12341
|
}
|
|
11081
12342
|
function writeManifest(changeId, content) {
|
|
11082
12343
|
writeFileSync15(manifestPathFor(changeId), content.endsWith("\n") ? content : `${content}
|
|
@@ -11118,11 +12379,11 @@ function pathMatches(relPath, patterns, currentChangeId) {
|
|
|
11118
12379
|
});
|
|
11119
12380
|
}
|
|
11120
12381
|
function loadContextPolicy() {
|
|
11121
|
-
const policyPath =
|
|
11122
|
-
if (!
|
|
12382
|
+
const policyPath = join29(process.cwd(), ".cdd", "context-policy.json");
|
|
12383
|
+
if (!existsSync28(policyPath))
|
|
11123
12384
|
return { forbiddenPaths: DEFAULT_FORBIDDEN_PATHS };
|
|
11124
12385
|
try {
|
|
11125
|
-
const custom = JSON.parse(
|
|
12386
|
+
const custom = JSON.parse(readFileSync30(policyPath, "utf8"));
|
|
11126
12387
|
return {
|
|
11127
12388
|
forbiddenPaths: Array.from(/* @__PURE__ */ new Set([
|
|
11128
12389
|
...DEFAULT_FORBIDDEN_PATHS,
|
|
@@ -11404,10 +12665,10 @@ var init_context = __esm({
|
|
|
11404
12665
|
});
|
|
11405
12666
|
|
|
11406
12667
|
// src/cli/index.ts
|
|
11407
|
-
import { readFileSync as
|
|
12668
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
11408
12669
|
import os from "os";
|
|
11409
|
-
import { fileURLToPath as
|
|
11410
|
-
import { dirname as dirname7, join as
|
|
12670
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12671
|
+
import { dirname as dirname7, join as join30 } from "path";
|
|
11411
12672
|
import { Command } from "commander";
|
|
11412
12673
|
|
|
11413
12674
|
// src/commands/init.ts
|
|
@@ -12512,8 +13773,8 @@ async function installHooks() {
|
|
|
12512
13773
|
}
|
|
12513
13774
|
|
|
12514
13775
|
// src/cli/index.ts
|
|
12515
|
-
var __dirname2 = dirname7(
|
|
12516
|
-
var pkg = JSON.parse(
|
|
13776
|
+
var __dirname2 = dirname7(fileURLToPath4(import.meta.url));
|
|
13777
|
+
var pkg = JSON.parse(readFileSync31(join30(__dirname2, "..", "..", "package.json"), "utf8"));
|
|
12517
13778
|
var program = new Command();
|
|
12518
13779
|
program.name("cdd-kit").description("Contract-Driven Delivery Kit CLI").version(pkg.version);
|
|
12519
13780
|
program.command("init").description(
|
|
@@ -12625,6 +13886,55 @@ index.command("impact <path-or-symbol>").description("Show indexed local imports
|
|
|
12625
13886
|
});
|
|
12626
13887
|
process.exit(exit);
|
|
12627
13888
|
});
|
|
13889
|
+
var graph = program.command("graph").description("Query native cdd-kit code graph context with optional CodeGraph adapter and code-map fallback");
|
|
13890
|
+
graph.command("status [path]").description("Show active graph engine and index health").option("--engine <engine>", "Graph engine: auto, native, codegraph, or codemap", "auto").option("--map <path>", "Code-map YAML path for fallback status", ".cdd/code-map.yml").option("--json", "Print machine-readable JSON", false).action(async (path, opts) => {
|
|
13891
|
+
const { graphStatus: graphStatus2 } = await Promise.resolve().then(() => (init_graph(), graph_exports));
|
|
13892
|
+
const exit = await graphStatus2({ path, engine: opts.engine, map: opts.map, json: opts.json === true });
|
|
13893
|
+
process.exit(exit);
|
|
13894
|
+
});
|
|
13895
|
+
graph.command("sync [path]").description("Run CodeGraph incremental sync (requires CodeGraph)").option("--engine <engine>", "Graph engine: codegraph", "codegraph").option("--json", "Print machine-readable JSON on errors", false).action(async (path, opts) => {
|
|
13896
|
+
const { graphSync: graphSync2 } = await Promise.resolve().then(() => (init_graph(), graph_exports));
|
|
13897
|
+
const exit = await graphSync2({ path, engine: opts.engine, json: opts.json === true });
|
|
13898
|
+
process.exit(exit);
|
|
13899
|
+
});
|
|
13900
|
+
graph.command("query <term>").description("Search native graph symbols, optionally delegating to CodeGraph or code-map").option("--engine <engine>", "Graph engine: auto, native, codegraph, or codemap", "auto").option("--map <path>", "Code-map YAML path for fallback", ".cdd/code-map.yml").option("--limit <n>", "Maximum results to print", "10").option("--json", "Print machine-readable JSON", false).option("--no-refresh", "Do not auto-regenerate stale or missing fallback code-map").action(async (term, opts) => {
|
|
13901
|
+
const { graphQuery: graphQuery2 } = await Promise.resolve().then(() => (init_graph(), graph_exports));
|
|
13902
|
+
const exit = await graphQuery2(term, {
|
|
13903
|
+
engine: opts.engine,
|
|
13904
|
+
map: opts.map,
|
|
13905
|
+
limit: parseInt(opts.limit, 10),
|
|
13906
|
+
json: opts.json === true,
|
|
13907
|
+
refresh: opts.refresh !== false
|
|
13908
|
+
});
|
|
13909
|
+
process.exit(exit);
|
|
13910
|
+
});
|
|
13911
|
+
graph.command("impact <path-or-symbol>").description("Analyze impact radius with native graph calls/imports, CodeGraph, or code-map fallback").option("--engine <engine>", "Graph engine: auto, native, codegraph, or codemap", "auto").option("--map <path>", "Code-map YAML path for fallback", ".cdd/code-map.yml").option("--limit <n>", "Maximum fallback dependent files to print", "20").option("--depth <n>", "CodeGraph traversal depth (fallback is direct only)", "2").option("--json", "Print machine-readable JSON", false).option("--no-refresh", "Do not auto-regenerate stale or missing fallback code-map").action(async (term, opts) => {
|
|
13912
|
+
const { graphImpact: graphImpact3 } = await Promise.resolve().then(() => (init_graph(), graph_exports));
|
|
13913
|
+
const exit = await graphImpact3(term, {
|
|
13914
|
+
engine: opts.engine,
|
|
13915
|
+
map: opts.map,
|
|
13916
|
+
limit: parseInt(opts.limit, 10),
|
|
13917
|
+
depth: parseInt(opts.depth, 10),
|
|
13918
|
+
json: opts.json === true,
|
|
13919
|
+
refresh: opts.refresh !== false
|
|
13920
|
+
});
|
|
13921
|
+
process.exit(exit);
|
|
13922
|
+
});
|
|
13923
|
+
graph.command("context <task>").description("Build task context with native graph, CodeGraph, or code-map candidates").option("--engine <engine>", "Graph engine: auto, native, codegraph, or codemap", "auto").option("--map <path>", "Code-map YAML path for fallback", ".cdd/code-map.yml").option("--max-nodes <n>", "Maximum context candidates/nodes", "20").option("--json", "Print machine-readable JSON", false).option("--no-refresh", "Do not auto-regenerate stale or missing fallback code-map").action(async (task, opts) => {
|
|
13924
|
+
const { graphContext: graphContext3 } = await Promise.resolve().then(() => (init_graph(), graph_exports));
|
|
13925
|
+
const exit = await graphContext3(task, {
|
|
13926
|
+
engine: opts.engine,
|
|
13927
|
+
map: opts.map,
|
|
13928
|
+
maxNodes: parseInt(opts.maxNodes, 10),
|
|
13929
|
+
json: opts.json === true,
|
|
13930
|
+
refresh: opts.refresh !== false
|
|
13931
|
+
});
|
|
13932
|
+
process.exit(exit);
|
|
13933
|
+
});
|
|
13934
|
+
program.command("mcp").description("Run the cdd-kit MCP stdio server exposing graph and code-map tools").action(async () => {
|
|
13935
|
+
const { runMcpServer: runMcpServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
13936
|
+
await runMcpServer2({ version: pkg.version });
|
|
13937
|
+
});
|
|
12628
13938
|
program.command("gate <change-id>").description("Run delivery-quality gate for a change (required artifacts, tasks, tier, contracts)").option("--strict", "Treat pending tasks (except section 7) as errors", false).action(async (id, opts) => {
|
|
12629
13939
|
await gate(id, { strict: opts.strict });
|
|
12630
13940
|
});
|