@ctxo/cli 0.9.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/{atomic-write-AQNYJFAG.js → atomic-write-BAFH464Q.js} +3 -2
- package/dist/chunk-5DSKZJNN.js +38 -0
- package/dist/chunk-5DSKZJNN.js.map +1 -0
- package/dist/{chunk-2TVHKCCU.js → chunk-CDGQGCVN.js} +55 -5
- package/dist/chunk-CDGQGCVN.js.map +1 -0
- package/dist/{chunk-HXEPS2XY.js → chunk-HZ4UGA6J.js} +142 -11
- package/dist/chunk-HZ4UGA6J.js.map +1 -0
- package/dist/{chunk-6EKERTJ7.js → chunk-RFEXMBTG.js} +4 -36
- package/dist/chunk-RFEXMBTG.js.map +1 -0
- package/dist/{cli-router-CQJ7CN6E.js → cli-router-NFAGLJ46.js} +802 -198
- package/dist/cli-router-NFAGLJ46.js.map +1 -0
- package/dist/index.js +8 -94
- package/dist/index.js.map +1 -1
- package/dist/json-index-reader-UYS74USB.js +9 -0
- package/llms-full.txt +48 -1
- package/llms.txt +8 -0
- package/package.json +6 -5
- package/skills/ctxo-review-pr/SKILL.md +10 -0
- package/skills/ctxo-safe-edit/SKILL.md +15 -0
- package/skills/ctxo-understand/SKILL.md +14 -0
- package/dist/chunk-2TVHKCCU.js.map +0 -1
- package/dist/chunk-6EKERTJ7.js.map +0 -1
- package/dist/chunk-HXEPS2XY.js.map +0 -1
- package/dist/cli-router-CQJ7CN6E.js.map +0 -1
- package/dist/json-index-reader-XOEE6VMD.js +0 -8
- /package/dist/{atomic-write-AQNYJFAG.js.map → atomic-write-BAFH464Q.js.map} +0 -0
- /package/dist/{json-index-reader-XOEE6VMD.js.map → json-index-reader-UYS74USB.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ArchitecturalOverlay,
|
|
4
|
+
BlastRadiusCalculator,
|
|
4
5
|
BoundaryViolationDetector,
|
|
5
6
|
DeadCodeDetector,
|
|
6
7
|
DriftDetector,
|
|
@@ -16,14 +17,15 @@ import {
|
|
|
16
17
|
makeGlobMatcher,
|
|
17
18
|
maskingClusterLabelPatterns,
|
|
18
19
|
statsEnabled
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import
|
|
21
|
-
createLogger
|
|
22
|
-
} from "./chunk-6EKERTJ7.js";
|
|
20
|
+
} from "./chunk-HZ4UGA6J.js";
|
|
21
|
+
import "./chunk-RFEXMBTG.js";
|
|
23
22
|
import {
|
|
24
23
|
DetailLevelSchema,
|
|
25
24
|
JsonIndexReader
|
|
26
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-CDGQGCVN.js";
|
|
26
|
+
import {
|
|
27
|
+
createLogger
|
|
28
|
+
} from "./chunk-5DSKZJNN.js";
|
|
27
29
|
|
|
28
30
|
// src/index.ts
|
|
29
31
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -760,94 +762,6 @@ function handleGetChangeIntelligence(storage, git, masking, staleness, ctxoRoot
|
|
|
760
762
|
|
|
761
763
|
// src/adapters/mcp/get-blast-radius.ts
|
|
762
764
|
import { z as z4 } from "zod";
|
|
763
|
-
|
|
764
|
-
// src/core/blast-radius/blast-radius-calculator.ts
|
|
765
|
-
var CONFIRMED_KINDS = /* @__PURE__ */ new Set(["calls", "extends", "implements"]);
|
|
766
|
-
var LIKELY_KINDS = /* @__PURE__ */ new Set(["uses"]);
|
|
767
|
-
var CONFIDENCE_RANK = {
|
|
768
|
-
confirmed: 2,
|
|
769
|
-
likely: 1,
|
|
770
|
-
potential: 0
|
|
771
|
-
};
|
|
772
|
-
function edgeKindToConfidence(kind) {
|
|
773
|
-
if (CONFIRMED_KINDS.has(kind)) return "confirmed";
|
|
774
|
-
if (LIKELY_KINDS.has(kind)) return "likely";
|
|
775
|
-
return "potential";
|
|
776
|
-
}
|
|
777
|
-
var BlastRadiusCalculator = class {
|
|
778
|
-
calculate(graph, symbolId, coChangeMap) {
|
|
779
|
-
if (!graph.hasNode(symbolId)) {
|
|
780
|
-
return { impactedSymbols: [], directDependentsCount: 0, confirmedCount: 0, likelyCount: 0, potentialCount: 0, overallRiskScore: 0 };
|
|
781
|
-
}
|
|
782
|
-
const sourceFile = symbolId.split("::")[0];
|
|
783
|
-
const visited = /* @__PURE__ */ new Set([symbolId]);
|
|
784
|
-
const rawEntries = [];
|
|
785
|
-
const queue = [{ id: symbolId, depth: 0 }];
|
|
786
|
-
while (queue.length > 0) {
|
|
787
|
-
const current = queue.shift();
|
|
788
|
-
const reverseEdges = graph.getReverseEdges(current.id);
|
|
789
|
-
const bestByNode = /* @__PURE__ */ new Map();
|
|
790
|
-
for (const edge of reverseEdges) {
|
|
791
|
-
if (visited.has(edge.from)) continue;
|
|
792
|
-
const conf = edgeKindToConfidence(edge.kind);
|
|
793
|
-
const existing = bestByNode.get(edge.from);
|
|
794
|
-
if (!existing) {
|
|
795
|
-
bestByNode.set(edge.from, { confidence: conf, kinds: /* @__PURE__ */ new Set([edge.kind]) });
|
|
796
|
-
} else {
|
|
797
|
-
existing.kinds.add(edge.kind);
|
|
798
|
-
if (CONFIDENCE_RANK[conf] > CONFIDENCE_RANK[existing.confidence]) {
|
|
799
|
-
existing.confidence = conf;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
for (const [nodeId, info] of bestByNode) {
|
|
804
|
-
visited.add(nodeId);
|
|
805
|
-
const depth = current.depth + 1;
|
|
806
|
-
const riskScore = 1 / Math.pow(depth, 0.7);
|
|
807
|
-
let confidence = info.confidence;
|
|
808
|
-
let coChangeFrequency;
|
|
809
|
-
if (coChangeMap) {
|
|
810
|
-
const nodeFile = nodeId.split("::")[0];
|
|
811
|
-
const coEntries = coChangeMap.get(sourceFile);
|
|
812
|
-
if (coEntries) {
|
|
813
|
-
const match = coEntries.find((e) => e.file1 === nodeFile || e.file2 === nodeFile);
|
|
814
|
-
if (match) {
|
|
815
|
-
coChangeFrequency = match.frequency;
|
|
816
|
-
if (confidence === "potential" && match.frequency > 0.5) {
|
|
817
|
-
confidence = "likely";
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
rawEntries.push({
|
|
823
|
-
symbolId: nodeId,
|
|
824
|
-
depth,
|
|
825
|
-
riskScore: Math.round(riskScore * 1e3) / 1e3,
|
|
826
|
-
confidence,
|
|
827
|
-
edgeKinds: [...info.kinds],
|
|
828
|
-
coChangeFrequency
|
|
829
|
-
});
|
|
830
|
-
queue.push({ id: nodeId, depth });
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
const blastSet = new Set(rawEntries.map((e) => e.symbolId));
|
|
834
|
-
blastSet.add(symbolId);
|
|
835
|
-
const entries = rawEntries.map((e) => ({
|
|
836
|
-
...e,
|
|
837
|
-
dependentCount: graph.getReverseEdges(e.symbolId).filter((re) => blastSet.has(re.from)).length
|
|
838
|
-
}));
|
|
839
|
-
entries.sort((a, b) => a.depth - b.depth);
|
|
840
|
-
const directDependentsCount = entries.filter((e) => e.depth === 1).length;
|
|
841
|
-
const totalRisk = entries.reduce((sum, e) => sum + e.riskScore, 0);
|
|
842
|
-
const overallRiskScore = Math.round(Math.min(totalRisk / Math.max(directDependentsCount, 1), 1) * 1e3) / 1e3;
|
|
843
|
-
const confirmedCount = entries.filter((e) => e.confidence === "confirmed").length;
|
|
844
|
-
const likelyCount = entries.filter((e) => e.confidence === "likely").length;
|
|
845
|
-
const potentialCount = entries.filter((e) => e.confidence === "potential").length;
|
|
846
|
-
return { impactedSymbols: entries, directDependentsCount, confirmedCount, likelyCount, potentialCount, overallRiskScore };
|
|
847
|
-
}
|
|
848
|
-
};
|
|
849
|
-
|
|
850
|
-
// src/adapters/mcp/get-blast-radius.ts
|
|
851
765
|
function computeClusterBreakdown(snapshot, rootSymbolId, impactedSymbolIds) {
|
|
852
766
|
if (impactedSymbolIds.length === 0) return void 0;
|
|
853
767
|
const assignment = /* @__PURE__ */ new Map();
|
|
@@ -2747,7 +2661,7 @@ async function main() {
|
|
|
2747
2661
|
const args = process.argv.slice(2);
|
|
2748
2662
|
const httpPortStr = process.env.CTXO_HTTP_PORT || (args.includes("--http") ? args[args.indexOf("--port") + 1] || "3001" : null);
|
|
2749
2663
|
if (!httpPortStr && args.length > 0) {
|
|
2750
|
-
const { CliRouter } = await import("./cli-router-
|
|
2664
|
+
const { CliRouter } = await import("./cli-router-NFAGLJ46.js");
|
|
2751
2665
|
const router = new CliRouter(process.cwd());
|
|
2752
2666
|
await router.route(args);
|
|
2753
2667
|
return;
|