@ctxo/cli 0.13.0 → 0.14.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 +20 -4
- package/dist/chunk-2Q76LH2H.js +186 -0
- package/dist/chunk-2Q76LH2H.js.map +1 -0
- package/dist/chunk-72CEQEQD.js +53 -0
- package/dist/chunk-72CEQEQD.js.map +1 -0
- package/dist/chunk-7HSA5JVP.js +1049 -0
- package/dist/chunk-7HSA5JVP.js.map +1 -0
- package/dist/chunk-G4BMKCKG.js +76 -0
- package/dist/chunk-G4BMKCKG.js.map +1 -0
- package/dist/chunk-L2CAUER6.js +508 -0
- package/dist/chunk-L2CAUER6.js.map +1 -0
- package/dist/chunk-LAX6VVBU.js +98 -0
- package/dist/chunk-LAX6VVBU.js.map +1 -0
- package/dist/chunk-SRQZDGFZ.js +128 -0
- package/dist/chunk-SRQZDGFZ.js.map +1 -0
- package/dist/{chunk-DT3ZH4AU.js → chunk-X4TVFJ4C.js} +6 -1
- package/dist/chunk-X4TVFJ4C.js.map +1 -0
- package/dist/{chunk-BYX3UFBJ.js → chunk-ZL36YS2V.js} +785 -1624
- package/dist/chunk-ZL36YS2V.js.map +1 -0
- package/dist/{cli-router-RR4CM62C.js → cli-router-AZCDNX5R.js} +982 -506
- package/dist/cli-router-AZCDNX5R.js.map +1 -0
- package/dist/index.js +13 -2874
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +747 -0
- package/dist/internal.js +13 -0
- package/dist/{json-index-reader-OXTRTGE6.js → json-index-reader-DBW32TCN.js} +6 -4
- package/dist/json-index-reader-DBW32TCN.js.map +1 -0
- package/dist/mcp-server-6YG2QE6E.js +2604 -0
- package/dist/mcp-server-6YG2QE6E.js.map +1 -0
- package/dist/module-host-KNMKS62R.js +13 -0
- package/dist/module-host-KNMKS62R.js.map +1 -0
- package/dist/module-loader-B3LYF3W7.js +14 -0
- package/dist/module-loader-B3LYF3W7.js.map +1 -0
- package/dist/plugin-discovery-XRXI3IJF.js +13 -0
- package/dist/plugin-discovery-XRXI3IJF.js.map +1 -0
- package/llms-full.txt +105 -1
- package/llms.txt +21 -1
- package/package.json +15 -4
- package/dist/chunk-BYX3UFBJ.js.map +0 -1
- package/dist/chunk-DT3ZH4AU.js.map +0 -1
- package/dist/cli-router-RR4CM62C.js.map +0 -1
- /package/dist/{json-index-reader-OXTRTGE6.js.map → internal.js.map} +0 -0
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
import { z, ZodRawShape } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const SymbolKindSchema: z.ZodEnum<{
|
|
4
|
+
function: "function";
|
|
5
|
+
class: "class";
|
|
6
|
+
interface: "interface";
|
|
7
|
+
method: "method";
|
|
8
|
+
variable: "variable";
|
|
9
|
+
type: "type";
|
|
10
|
+
table: "table";
|
|
11
|
+
view: "view";
|
|
12
|
+
procedure: "procedure";
|
|
13
|
+
}>;
|
|
14
|
+
type SymbolKind = z.infer<typeof SymbolKindSchema>;
|
|
15
|
+
|
|
16
|
+
declare const EdgeKindSchema: z.ZodEnum<{
|
|
17
|
+
imports: "imports";
|
|
18
|
+
calls: "calls";
|
|
19
|
+
extends: "extends";
|
|
20
|
+
implements: "implements";
|
|
21
|
+
uses: "uses";
|
|
22
|
+
reads: "reads";
|
|
23
|
+
writes: "writes";
|
|
24
|
+
executes: "executes";
|
|
25
|
+
}>;
|
|
26
|
+
type EdgeKind = z.infer<typeof EdgeKindSchema>;
|
|
27
|
+
declare const SymbolNodeSchema: z.ZodObject<{
|
|
28
|
+
symbolId: z.ZodString;
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
kind: z.ZodEnum<{
|
|
31
|
+
function: "function";
|
|
32
|
+
class: "class";
|
|
33
|
+
interface: "interface";
|
|
34
|
+
method: "method";
|
|
35
|
+
variable: "variable";
|
|
36
|
+
type: "type";
|
|
37
|
+
table: "table";
|
|
38
|
+
view: "view";
|
|
39
|
+
procedure: "procedure";
|
|
40
|
+
}>;
|
|
41
|
+
startLine: z.ZodNumber;
|
|
42
|
+
endLine: z.ZodNumber;
|
|
43
|
+
startOffset: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
endOffset: z.ZodOptional<z.ZodNumber>;
|
|
45
|
+
annotations: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
46
|
+
name: z.ZodString;
|
|
47
|
+
args: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
48
|
+
named: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
49
|
+
}, z.core.$strip>>>>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
type SymbolNode = z.infer<typeof SymbolNodeSchema>;
|
|
52
|
+
declare const GraphEdgeSchema: z.ZodObject<{
|
|
53
|
+
from: z.ZodString;
|
|
54
|
+
to: z.ZodString;
|
|
55
|
+
kind: z.ZodEnum<{
|
|
56
|
+
imports: "imports";
|
|
57
|
+
calls: "calls";
|
|
58
|
+
extends: "extends";
|
|
59
|
+
implements: "implements";
|
|
60
|
+
uses: "uses";
|
|
61
|
+
reads: "reads";
|
|
62
|
+
writes: "writes";
|
|
63
|
+
executes: "executes";
|
|
64
|
+
}>;
|
|
65
|
+
typeOnly: z.ZodOptional<z.ZodBoolean>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
type GraphEdge = z.infer<typeof GraphEdgeSchema>;
|
|
68
|
+
declare const FileIndexSchema: z.ZodObject<{
|
|
69
|
+
file: z.ZodString;
|
|
70
|
+
lastModified: z.ZodNumber;
|
|
71
|
+
contentHash: z.ZodOptional<z.ZodString>;
|
|
72
|
+
symbols: z.ZodArray<z.ZodObject<{
|
|
73
|
+
symbolId: z.ZodString;
|
|
74
|
+
name: z.ZodString;
|
|
75
|
+
kind: z.ZodEnum<{
|
|
76
|
+
function: "function";
|
|
77
|
+
class: "class";
|
|
78
|
+
interface: "interface";
|
|
79
|
+
method: "method";
|
|
80
|
+
variable: "variable";
|
|
81
|
+
type: "type";
|
|
82
|
+
table: "table";
|
|
83
|
+
view: "view";
|
|
84
|
+
procedure: "procedure";
|
|
85
|
+
}>;
|
|
86
|
+
startLine: z.ZodNumber;
|
|
87
|
+
endLine: z.ZodNumber;
|
|
88
|
+
startOffset: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
endOffset: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
annotations: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
91
|
+
name: z.ZodString;
|
|
92
|
+
args: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
93
|
+
named: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
94
|
+
}, z.core.$strip>>>>;
|
|
95
|
+
}, z.core.$strip>>;
|
|
96
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
97
|
+
from: z.ZodString;
|
|
98
|
+
to: z.ZodString;
|
|
99
|
+
kind: z.ZodEnum<{
|
|
100
|
+
imports: "imports";
|
|
101
|
+
calls: "calls";
|
|
102
|
+
extends: "extends";
|
|
103
|
+
implements: "implements";
|
|
104
|
+
uses: "uses";
|
|
105
|
+
reads: "reads";
|
|
106
|
+
writes: "writes";
|
|
107
|
+
executes: "executes";
|
|
108
|
+
}>;
|
|
109
|
+
typeOnly: z.ZodOptional<z.ZodBoolean>;
|
|
110
|
+
}, z.core.$strip>>;
|
|
111
|
+
complexity: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
112
|
+
symbolId: z.ZodString;
|
|
113
|
+
cyclomatic: z.ZodNumber;
|
|
114
|
+
}, z.core.$strip>>>;
|
|
115
|
+
intent: z.ZodArray<z.ZodObject<{
|
|
116
|
+
hash: z.ZodString;
|
|
117
|
+
message: z.ZodString;
|
|
118
|
+
date: z.ZodString;
|
|
119
|
+
kind: z.ZodLiteral<"commit">;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
antiPatterns: z.ZodArray<z.ZodObject<{
|
|
122
|
+
hash: z.ZodString;
|
|
123
|
+
message: z.ZodString;
|
|
124
|
+
date: z.ZodString;
|
|
125
|
+
}, z.core.$strip>>;
|
|
126
|
+
facts: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
127
|
+
kind: z.ZodEnum<{
|
|
128
|
+
"literal-comparison": "literal-comparison";
|
|
129
|
+
normalization: "normalization";
|
|
130
|
+
"retry-timeout": "retry-timeout";
|
|
131
|
+
endpoint: "endpoint";
|
|
132
|
+
}>;
|
|
133
|
+
symbolId: z.ZodString;
|
|
134
|
+
line: z.ZodNumber;
|
|
135
|
+
text: z.ZodString;
|
|
136
|
+
detail: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
137
|
+
}, z.core.$strip>>>>;
|
|
138
|
+
}, z.core.$strip>;
|
|
139
|
+
type FileIndex = z.infer<typeof FileIndexSchema>;
|
|
140
|
+
interface ChurnData {
|
|
141
|
+
readonly filePath: string;
|
|
142
|
+
readonly commitCount: number;
|
|
143
|
+
}
|
|
144
|
+
interface CoChangeEntry {
|
|
145
|
+
readonly file1: string;
|
|
146
|
+
readonly file2: string;
|
|
147
|
+
readonly sharedCommits: number;
|
|
148
|
+
readonly frequency: number;
|
|
149
|
+
}
|
|
150
|
+
interface CommitRecord {
|
|
151
|
+
readonly hash: string;
|
|
152
|
+
readonly message: string;
|
|
153
|
+
readonly date: string;
|
|
154
|
+
readonly author: string;
|
|
155
|
+
}
|
|
156
|
+
/** git name-status letters Ctxo keeps; A added, M modified, D deleted, R renamed, C copied, T type changed. */
|
|
157
|
+
type FileChangeStatus = 'A' | 'M' | 'D' | 'R' | 'C' | 'T';
|
|
158
|
+
interface FileChange {
|
|
159
|
+
readonly status: FileChangeStatus;
|
|
160
|
+
/** Path after the change: repo-relative, forward slashes. */
|
|
161
|
+
readonly path: string;
|
|
162
|
+
/** Path before the change; set only for renames (R) and copies (C). */
|
|
163
|
+
readonly oldPath?: string;
|
|
164
|
+
}
|
|
165
|
+
/** One non-merge commit and the files it changed. */
|
|
166
|
+
interface CommitChangeSet {
|
|
167
|
+
/** Full commit SHA (git %H). */
|
|
168
|
+
readonly hash: string;
|
|
169
|
+
/** Subject line (git %s). */
|
|
170
|
+
readonly message: string;
|
|
171
|
+
/** Author date, strict ISO 8601 (git %aI). */
|
|
172
|
+
readonly date: string;
|
|
173
|
+
/** Author name (git %an). */
|
|
174
|
+
readonly author: string;
|
|
175
|
+
/** Committer date in unix seconds (git %ct). */
|
|
176
|
+
readonly committedAt: number;
|
|
177
|
+
readonly changes: readonly FileChange[];
|
|
178
|
+
}
|
|
179
|
+
interface ChangeLog {
|
|
180
|
+
/** Short SHA of HEAD (git %h), which may itself be a merge commit. */
|
|
181
|
+
readonly head: string;
|
|
182
|
+
/** Committer date of HEAD in unix seconds (git %ct). */
|
|
183
|
+
readonly headCommittedAt: number;
|
|
184
|
+
/** Non-merge commits reachable from HEAD, newest first. */
|
|
185
|
+
readonly commits: readonly CommitChangeSet[];
|
|
186
|
+
}
|
|
187
|
+
/** A revision range: commits reachable from `head` and from none of `exclude`. */
|
|
188
|
+
interface GitRange {
|
|
189
|
+
readonly head: string;
|
|
190
|
+
readonly exclude: readonly string[];
|
|
191
|
+
}
|
|
192
|
+
/** One commit of a range log. */
|
|
193
|
+
interface RangeCommit {
|
|
194
|
+
/** Full commit SHA (git %H). */
|
|
195
|
+
readonly hash: string;
|
|
196
|
+
readonly subject: string;
|
|
197
|
+
/** More than one parent. */
|
|
198
|
+
readonly isMerge: boolean;
|
|
199
|
+
/** Values of the requested trailer key, in message order, trimmed, no empties. */
|
|
200
|
+
readonly trailers: readonly string[];
|
|
201
|
+
/** Files the commit changed; empty for merge commits. */
|
|
202
|
+
readonly changes: readonly FileChange[];
|
|
203
|
+
}
|
|
204
|
+
/** Branch facts of a repository; every field but `branches` is absent when git cannot say. */
|
|
205
|
+
interface GitRefs {
|
|
206
|
+
/** Undefined on a detached HEAD. */
|
|
207
|
+
readonly currentBranch?: string;
|
|
208
|
+
/** For example 'origin/feat'. */
|
|
209
|
+
readonly upstream?: string;
|
|
210
|
+
/** For example 'origin/main'. */
|
|
211
|
+
readonly originHead?: string;
|
|
212
|
+
/** Local and remote-tracking short names without the remote HEAD aliases, in codepoint order. */
|
|
213
|
+
readonly branches: readonly string[];
|
|
214
|
+
/** Local branches only (refs/heads), in codepoint order. */
|
|
215
|
+
readonly localBranches?: readonly string[];
|
|
216
|
+
/** Remote-tracking branches as `<remote>/<name>` (refs/remotes, no HEAD aliases), in codepoint order. */
|
|
217
|
+
readonly remoteBranches?: readonly string[];
|
|
218
|
+
}
|
|
219
|
+
interface CommunityEntry {
|
|
220
|
+
readonly symbolId: string;
|
|
221
|
+
readonly communityId: number;
|
|
222
|
+
readonly communityLabel: string;
|
|
223
|
+
}
|
|
224
|
+
interface GodNode {
|
|
225
|
+
readonly symbolId: string;
|
|
226
|
+
readonly bridgedCommunities: readonly number[];
|
|
227
|
+
readonly centralityScore: number;
|
|
228
|
+
}
|
|
229
|
+
declare const EDGE_QUALITY: readonly ["full", "syntax-only", "mixed"];
|
|
230
|
+
type EdgeQuality = (typeof EDGE_QUALITY)[number];
|
|
231
|
+
interface CommunitySnapshot {
|
|
232
|
+
readonly version: 1;
|
|
233
|
+
readonly computedAt: string;
|
|
234
|
+
readonly commitSha: string;
|
|
235
|
+
readonly modularity: number;
|
|
236
|
+
readonly communities: readonly CommunityEntry[];
|
|
237
|
+
readonly godNodes: readonly GodNode[];
|
|
238
|
+
readonly edgeQuality: EdgeQuality;
|
|
239
|
+
readonly crossClusterEdges: number;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** A table, view or procedure as one resource across every definition of its canonical name. */
|
|
243
|
+
interface DataResourceIdentity {
|
|
244
|
+
/** `<name>::<kind>` with the winner's kind, for example `dbo.loans::table`. */
|
|
245
|
+
readonly canonicalId: string;
|
|
246
|
+
/** The definition every data reference to the name resolves to (the `definitionRank` tie-break). */
|
|
247
|
+
readonly winner: SymbolNode;
|
|
248
|
+
/** Every definition of the name, once each, in tie-break order: the winner comes first. */
|
|
249
|
+
readonly definitions: readonly SymbolNode[];
|
|
250
|
+
/**
|
|
251
|
+
* The definitions in neither a test file nor a documentation folder (the best `definitionRank`), in
|
|
252
|
+
* tie-break order. Empty when every definition is a docs or test copy.
|
|
253
|
+
*/
|
|
254
|
+
readonly production: readonly SymbolNode[];
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* The symbol graph of an index.
|
|
258
|
+
*
|
|
259
|
+
* Add all nodes before any edge: `addEdge` resolves each endpoint against the nodes present at that moment,
|
|
260
|
+
* and an endpoint it cannot resolve keeps its raw id for good.
|
|
261
|
+
*
|
|
262
|
+
* A table, view or procedure is one resource per canonical name, whatever the number of files that define
|
|
263
|
+
* it (`dataResourceIdentity`). Every data reference resolves to the same definition, the winner, so only the
|
|
264
|
+
* winner has incoming edges. The impact tools read dependents through `getDependentEdges`, which gives every
|
|
265
|
+
* definition those edges, and forward edges stay on each definition: a procedure body in a later migration
|
|
266
|
+
* keeps its own accesses.
|
|
267
|
+
*/
|
|
268
|
+
declare class SymbolGraph$1 {
|
|
269
|
+
private readonly nodes;
|
|
270
|
+
private readonly nodesByFileAndName;
|
|
271
|
+
private readonly nodesByNameAndKind;
|
|
272
|
+
private readonly forwardEdges;
|
|
273
|
+
private readonly reverseEdges;
|
|
274
|
+
private readonly definitionRanks;
|
|
275
|
+
private edgeSet;
|
|
276
|
+
addNode(node: SymbolNode): void;
|
|
277
|
+
addEdge(edge: GraphEdge): void;
|
|
278
|
+
getNode(symbolId: string): SymbolNode | undefined;
|
|
279
|
+
private resolveNodeId;
|
|
280
|
+
private resolveNodeFuzzy;
|
|
281
|
+
/**
|
|
282
|
+
* Resolves a 2-part data reference (`dbo.loans::table`). A table or view reference is kind-agnostic
|
|
283
|
+
* across data resource kinds, a procedure reference matches procedures only. Several definitions
|
|
284
|
+
* resolve by `definitionRank` (a production copy before a documentation copy before a test copy), then
|
|
285
|
+
* to the codepoint-smallest symbolId, which is the first file in sorted path order. The result does
|
|
286
|
+
* not depend on insertion order.
|
|
287
|
+
*/
|
|
288
|
+
private resolveDataReference;
|
|
289
|
+
/** The tie-break order of same-name definitions: `definitionRank`, then the codepoint-smaller symbolId. */
|
|
290
|
+
private readonly compareDefinitions;
|
|
291
|
+
/**
|
|
292
|
+
* The identity of the table, view or procedure that `id` names: a full id of any of its definitions, or a
|
|
293
|
+
* 2-part reference such as `dbo.loans::table`. Undefined when `id` names no node, or a node of another
|
|
294
|
+
* kind. A table or view identity spans both kinds, as a 2-part `::table` reference does.
|
|
295
|
+
*/
|
|
296
|
+
dataResourceIdentity(id: string): DataResourceIdentity | undefined;
|
|
297
|
+
private identityOf;
|
|
298
|
+
/** `definitionRank`, cached per symbolId (the glob match runs once per definition). */
|
|
299
|
+
private definitionRankOf;
|
|
300
|
+
/**
|
|
301
|
+
* Extracts a `name::kind` key from the segments of a reference ID, supporting:
|
|
302
|
+
* - 2-part: `Bar::class` → `Bar::class`
|
|
303
|
+
* - 3-part: `pkg.Bar::helper::method` → `helper::method`
|
|
304
|
+
* Returns undefined for 1-part IDs (no kind information available).
|
|
305
|
+
*/
|
|
306
|
+
private extractNameKind;
|
|
307
|
+
getForwardEdges(symbolId: string): GraphEdge[];
|
|
308
|
+
getReverseEdges(symbolId: string): GraphEdge[];
|
|
309
|
+
/**
|
|
310
|
+
* The dependents of a resolved symbolId, as the impact tools read them. For a definition of a table, view
|
|
311
|
+
* or procedure these are the incoming edges of every same-name definition, which in practice are the
|
|
312
|
+
* winner's: any copy then reports the dependents of the resource. For every other id they are its own
|
|
313
|
+
* incoming edges, as `getReverseEdges` gives them.
|
|
314
|
+
*/
|
|
315
|
+
getDependentEdges(symbolId: string): GraphEdge[];
|
|
316
|
+
hasNode(symbolId: string): boolean;
|
|
317
|
+
get nodeCount(): number;
|
|
318
|
+
get edgeCount(): number;
|
|
319
|
+
allNodes(): SymbolNode[];
|
|
320
|
+
allEdges(): GraphEdge[];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
type ImpactConfidence = 'confirmed' | 'likely' | 'potential';
|
|
324
|
+
interface BlastRadiusEntry {
|
|
325
|
+
readonly symbolId: string;
|
|
326
|
+
readonly depth: number;
|
|
327
|
+
readonly dependentCount: number;
|
|
328
|
+
readonly riskScore: number;
|
|
329
|
+
readonly confidence: ImpactConfidence;
|
|
330
|
+
readonly edgeKinds: string[];
|
|
331
|
+
readonly coChangeFrequency?: number;
|
|
332
|
+
}
|
|
333
|
+
interface BlastRadiusResult {
|
|
334
|
+
readonly impactedSymbols: BlastRadiusEntry[];
|
|
335
|
+
readonly directDependentsCount: number;
|
|
336
|
+
readonly confirmedCount: number;
|
|
337
|
+
readonly likelyCount: number;
|
|
338
|
+
readonly potentialCount: number;
|
|
339
|
+
readonly overallRiskScore: number;
|
|
340
|
+
}
|
|
341
|
+
declare class BlastRadiusCalculator$1 {
|
|
342
|
+
/**
|
|
343
|
+
* `symbolId` may be any id `SymbolGraph.getNode` resolves, a 2-part data id included. The root is the
|
|
344
|
+
* node it names, and the root's own file is the one co-change is matched against. Dependents come from
|
|
345
|
+
* `getDependentEdges`, so every copy of a table, view or procedure, and its 2-part id, has the dependents
|
|
346
|
+
* of the resource, and no definition of the resource counts as a dependent of another.
|
|
347
|
+
*/
|
|
348
|
+
calculate(graph: SymbolGraph$1, symbolId: string, coChangeMap?: Map<string, CoChangeEntry[]>): BlastRadiusResult;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
declare const CtxoConfigSchema: z.ZodObject<{
|
|
352
|
+
version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
353
|
+
stats: z.ZodOptional<z.ZodObject<{
|
|
354
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
355
|
+
}, z.core.$strict>>;
|
|
356
|
+
index: z.ZodOptional<z.ZodObject<{
|
|
357
|
+
ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
358
|
+
ignoreProjects: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
359
|
+
facts: z.ZodOptional<z.ZodBoolean>;
|
|
360
|
+
tests: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
361
|
+
}, z.core.$strict>>;
|
|
362
|
+
masking: z.ZodOptional<z.ZodObject<{
|
|
363
|
+
clusterLabels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
364
|
+
}, z.core.$strict>>;
|
|
365
|
+
watch: z.ZodOptional<z.ZodObject<{
|
|
366
|
+
snapshotMinFileChanges: z.ZodOptional<z.ZodNumber>;
|
|
367
|
+
}, z.core.$strict>>;
|
|
368
|
+
gate: z.ZodOptional<z.ZodObject<{
|
|
369
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
370
|
+
sensitivity: z.ZodOptional<z.ZodEnum<{
|
|
371
|
+
strict: "strict";
|
|
372
|
+
balanced: "balanced";
|
|
373
|
+
lenient: "lenient";
|
|
374
|
+
}>>;
|
|
375
|
+
minDependents: z.ZodOptional<z.ZodNumber>;
|
|
376
|
+
percentile: z.ZodOptional<z.ZodNumber>;
|
|
377
|
+
}, z.core.$strict>>;
|
|
378
|
+
cochange: z.ZodOptional<z.ZodObject<{
|
|
379
|
+
maxCommits: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<"all">]>>;
|
|
380
|
+
since: z.ZodOptional<z.ZodString>;
|
|
381
|
+
maxFilesPerCommit: z.ZodOptional<z.ZodNumber>;
|
|
382
|
+
minShared: z.ZodOptional<z.ZodNumber>;
|
|
383
|
+
include: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
384
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
385
|
+
}, z.core.$strict>>;
|
|
386
|
+
communities: z.ZodOptional<z.ZodObject<{
|
|
387
|
+
resolution: z.ZodOptional<z.ZodNumber>;
|
|
388
|
+
godNodeMinBridged: z.ZodOptional<z.ZodNumber>;
|
|
389
|
+
godNodeMaxResults: z.ZodOptional<z.ZodNumber>;
|
|
390
|
+
}, z.core.$strict>>;
|
|
391
|
+
contextsView: z.ZodOptional<z.ZodObject<{
|
|
392
|
+
weights: z.ZodOptional<z.ZodObject<{
|
|
393
|
+
dependency: z.ZodOptional<z.ZodNumber>;
|
|
394
|
+
coChange: z.ZodOptional<z.ZodNumber>;
|
|
395
|
+
data: z.ZodOptional<z.ZodNumber>;
|
|
396
|
+
}, z.core.$strict>>;
|
|
397
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
398
|
+
hubs: z.ZodOptional<z.ZodObject<{
|
|
399
|
+
auto: z.ZodOptional<z.ZodBoolean>;
|
|
400
|
+
topPercent: z.ZodOptional<z.ZodNumber>;
|
|
401
|
+
minDependents: z.ZodOptional<z.ZodNumber>;
|
|
402
|
+
paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
403
|
+
}, z.core.$strict>>;
|
|
404
|
+
resolution: z.ZodOptional<z.ZodNumber>;
|
|
405
|
+
minCandidateFiles: z.ZodOptional<z.ZodNumber>;
|
|
406
|
+
technicalTerms: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
407
|
+
}, z.core.$strict>>;
|
|
408
|
+
}, z.core.$loose>;
|
|
409
|
+
type CtxoConfig = z.infer<typeof CtxoConfigSchema>;
|
|
410
|
+
|
|
411
|
+
interface LoadedConfig {
|
|
412
|
+
readonly config: CtxoConfig;
|
|
413
|
+
readonly errors: readonly string[];
|
|
414
|
+
readonly invalidGlobs: readonly string[];
|
|
415
|
+
readonly path: string;
|
|
416
|
+
readonly exists: boolean;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Structured logger for Ctxo — all output goes to stderr (stdout reserved for MCP JSON-RPC).
|
|
421
|
+
*
|
|
422
|
+
* Supports debug mode via DEBUG environment variable:
|
|
423
|
+
* DEBUG=ctxo:* — all debug output
|
|
424
|
+
* DEBUG=ctxo:git — only git adapter debug
|
|
425
|
+
* DEBUG=ctxo:index — only indexing debug
|
|
426
|
+
* DEBUG=ctxo:mcp — only MCP handler debug
|
|
427
|
+
* DEBUG=ctxo:storage — only storage adapter debug
|
|
428
|
+
* DEBUG=ctxo:masking — only masking pipeline debug
|
|
429
|
+
*
|
|
430
|
+
* Always outputs: info, warn, error (regardless of DEBUG).
|
|
431
|
+
* Only outputs debug when matching namespace is enabled.
|
|
432
|
+
*/
|
|
433
|
+
interface Logger {
|
|
434
|
+
debug(message: string, ...args: unknown[]): void;
|
|
435
|
+
info(message: string, ...args: unknown[]): void;
|
|
436
|
+
warn(message: string, ...args: unknown[]): void;
|
|
437
|
+
error(message: string, ...args: unknown[]): void;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
type CheckStatus = 'pass' | 'warn' | 'fail';
|
|
441
|
+
interface CheckResult {
|
|
442
|
+
readonly id: string;
|
|
443
|
+
readonly title: string;
|
|
444
|
+
readonly status: CheckStatus;
|
|
445
|
+
readonly message: string;
|
|
446
|
+
readonly fix?: string;
|
|
447
|
+
readonly value?: string;
|
|
448
|
+
}
|
|
449
|
+
interface CheckContext {
|
|
450
|
+
readonly projectRoot: string;
|
|
451
|
+
readonly ctxoRoot: string;
|
|
452
|
+
readonly indices?: readonly FileIndex[];
|
|
453
|
+
}
|
|
454
|
+
interface IHealthCheck {
|
|
455
|
+
readonly id: string;
|
|
456
|
+
readonly title: string;
|
|
457
|
+
run(ctx: CheckContext): Promise<CheckResult>;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
interface IGitPort {
|
|
461
|
+
getCommitHistory(filePath: string, maxCount?: number): Promise<CommitRecord[]>;
|
|
462
|
+
getFileChurn(filePath: string): Promise<ChurnData>;
|
|
463
|
+
getChangedFiles(since: string): Promise<string[]>;
|
|
464
|
+
isAvailable(): Promise<boolean>;
|
|
465
|
+
/** Short (8-char) SHA of current HEAD, or undefined if git is unavailable. */
|
|
466
|
+
getHeadSha?(): Promise<string | undefined>;
|
|
467
|
+
/**
|
|
468
|
+
* Number of commits in `base..HEAD` (reachable from HEAD but not from base).
|
|
469
|
+
* Returns undefined when either ref cannot be resolved. Zero means HEAD has
|
|
470
|
+
* not advanced past `base`.
|
|
471
|
+
*/
|
|
472
|
+
countCommitsBetween?(base: string): Promise<number | undefined>;
|
|
473
|
+
/**
|
|
474
|
+
* Non-merge commits reachable from HEAD, newest first, each with the files it
|
|
475
|
+
* changed (renames carry `oldPath`). `maxCommits` caps the number of non-merge
|
|
476
|
+
* commits; 'all' reads the whole history. `head` and `headCommittedAt` describe
|
|
477
|
+
* HEAD itself, even when HEAD is a merge commit. Returns undefined when git
|
|
478
|
+
* fails or the repository has no commits.
|
|
479
|
+
*/
|
|
480
|
+
getChangeLog?(maxCommits: number | 'all'): Promise<ChangeLog | undefined>;
|
|
481
|
+
/**
|
|
482
|
+
* Files changed by a single commit, root commits included. A merge commit
|
|
483
|
+
* yields an empty list. Returns undefined when `rev` cannot be resolved or git
|
|
484
|
+
* fails.
|
|
485
|
+
*/
|
|
486
|
+
getCommitFileChanges?(rev: string): Promise<FileChange[] | undefined>;
|
|
487
|
+
/**
|
|
488
|
+
* Tracked paths that git marks skip-worktree (a sparse checkout, or
|
|
489
|
+
* `git update-index --skip-worktree`): git still tracks them, but they are
|
|
490
|
+
* deliberately absent from the working tree. Repo-relative, forward slashes.
|
|
491
|
+
* Returns undefined when git fails, so a caller can fail safe.
|
|
492
|
+
*/
|
|
493
|
+
getSkipWorktreePaths?(): Promise<ReadonlySet<string> | undefined>;
|
|
494
|
+
/**
|
|
495
|
+
* Of the given repo-relative paths, those that git ignores (.gitignore, .git/info/exclude, the global
|
|
496
|
+
* excludes). A tracked file is never ignored in this sense, however a pattern matches it. Returns
|
|
497
|
+
* undefined when git fails.
|
|
498
|
+
*/
|
|
499
|
+
getIgnoredPaths?(paths: readonly string[]): Promise<ReadonlySet<string> | undefined>;
|
|
500
|
+
/**
|
|
501
|
+
* The methods below return undefined when git fails, and refuse any ref that starts with `-`.
|
|
502
|
+
*/
|
|
503
|
+
/** Full SHA of `<ref>^{commit}`. */
|
|
504
|
+
resolveCommit?(ref: string): Promise<string | undefined>;
|
|
505
|
+
/** Full SHA of the merge base of two refs. */
|
|
506
|
+
mergeBase?(a: string, b: string): Promise<string | undefined>;
|
|
507
|
+
/** Whether `ancestor` is reachable from `descendant`. */
|
|
508
|
+
isAncestor?(ancestor: string, descendant: string): Promise<boolean | undefined>;
|
|
509
|
+
/**
|
|
510
|
+
* Commits reachable from `range.head` and from none of `range.exclude`, newest first. Merge commits
|
|
511
|
+
* carry no changes. `trailerKey` collects that trailer's values per commit.
|
|
512
|
+
*/
|
|
513
|
+
getRangeLog?(range: GitRange, options?: {
|
|
514
|
+
readonly trailerKey?: string;
|
|
515
|
+
}): Promise<RangeCommit[] | undefined>;
|
|
516
|
+
/**
|
|
517
|
+
* 'all': staged, unstaged and untracked (not ignored) changes against HEAD; 'staged': only the index.
|
|
518
|
+
*/
|
|
519
|
+
getWorkingTreeChanges?(scope: 'all' | 'staged'): Promise<FileChange[] | undefined>;
|
|
520
|
+
/** Current branch, upstream, origin/HEAD and the branch list. */
|
|
521
|
+
getRefs?(): Promise<GitRefs | undefined>;
|
|
522
|
+
/** Tracked paths (git ls-files -z), repo-relative, forward slashes. */
|
|
523
|
+
listTrackedFiles?(): Promise<string[] | undefined>;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* The module API: what an opt-in module such as `@ctxo/domain` registers with the CLI, and the host
|
|
528
|
+
* services it receives in return (ADR-018). Types only. A module imports these from `@ctxo/cli/internal`
|
|
529
|
+
* with `import type`; every runtime service arrives through `CtxoHost.services`. The API changes only in
|
|
530
|
+
* minor releases, and a module runs only when its `major.minor` equals the running CLI's.
|
|
531
|
+
*/
|
|
532
|
+
/** The 14 core MCP tools a module may enrich. */
|
|
533
|
+
type CoreToolName = 'get_logic_slice' | 'get_why_context' | 'get_change_intelligence' | 'get_blast_radius' | 'get_architectural_overlay' | 'find_dead_code' | 'get_context_for_task' | 'get_ranked_context' | 'search_symbols' | 'get_changed_symbols' | 'find_importers' | 'get_class_hierarchy' | 'get_symbol_importance' | 'get_pr_impact';
|
|
534
|
+
/**
|
|
535
|
+
* Adds fields to a core tool's payload before the envelope, truncation and masking see it. Additive only:
|
|
536
|
+
* it returns the payload with its fields added and never removes or rewrites the core's fields.
|
|
537
|
+
*/
|
|
538
|
+
type ResponseEnricher = (payload: Record<string, unknown>, args: Readonly<Record<string, unknown>>) => Record<string, unknown>;
|
|
539
|
+
/** An MCP tool a module contributes. The CLI wraps the handler with the envelope, masking and recording. */
|
|
540
|
+
interface ModuleToolDefinition {
|
|
541
|
+
readonly name: string;
|
|
542
|
+
readonly description: string;
|
|
543
|
+
/** A factory that receives the host's `zod`, so the module needs no zod dependency of its own. */
|
|
544
|
+
readonly inputSchema: (zod: typeof z) => ZodRawShape;
|
|
545
|
+
handler(args: Record<string, unknown>): Promise<Record<string, unknown>> | Record<string, unknown>;
|
|
546
|
+
}
|
|
547
|
+
interface ToolRegistrar {
|
|
548
|
+
registerTool(tool: ModuleToolDefinition): void;
|
|
549
|
+
}
|
|
550
|
+
interface ModuleCommandContext {
|
|
551
|
+
readonly projectRoot: string;
|
|
552
|
+
readonly ctxoRoot: string;
|
|
553
|
+
readStdin(): Promise<string>;
|
|
554
|
+
}
|
|
555
|
+
/** A `ctxo <name>` command a module contributes. */
|
|
556
|
+
interface ModuleCommand {
|
|
557
|
+
readonly name: string;
|
|
558
|
+
/** Usage lines for `ctxo <name> --help` and `ctxo --help`. */
|
|
559
|
+
readonly help: readonly string[];
|
|
560
|
+
/** The full usage for `ctxo <name> --help` (flags, exit codes); `help` is printed when absent. */
|
|
561
|
+
readonly usage?: readonly string[];
|
|
562
|
+
/** Left out of `ctxo --help` (hook commands). */
|
|
563
|
+
readonly hidden?: boolean;
|
|
564
|
+
/** Resolves to the exit code. */
|
|
565
|
+
run(args: readonly string[], ctx: ModuleCommandContext): Promise<number>;
|
|
566
|
+
}
|
|
567
|
+
interface CommandRegistrar {
|
|
568
|
+
registerCommand(command: ModuleCommand): void;
|
|
569
|
+
}
|
|
570
|
+
/** Whether a repo-relative path (either separator) is a test file. It already holds the annotated files. */
|
|
571
|
+
type TestFileCheck = (path: string) => boolean;
|
|
572
|
+
/** The raw commits of the configured co-change window, newest first, renames intact. */
|
|
573
|
+
interface CoChangeWindowCommits {
|
|
574
|
+
/** Short SHA of HEAD. */
|
|
575
|
+
readonly head: string;
|
|
576
|
+
/** HEAD's committer date in unix seconds. */
|
|
577
|
+
readonly headCommittedAt: number;
|
|
578
|
+
readonly commits: readonly CommitChangeSet[];
|
|
579
|
+
}
|
|
580
|
+
/** What a module's index pass receives at the end of `ctxo index`. */
|
|
581
|
+
interface IndexPassContext {
|
|
582
|
+
readonly projectRoot: string;
|
|
583
|
+
readonly ctxoRoot: string;
|
|
584
|
+
readonly config: CtxoConfig;
|
|
585
|
+
/** The merged full index. */
|
|
586
|
+
readonly indices: readonly FileIndex[];
|
|
587
|
+
/** Built on first call, then reused. */
|
|
588
|
+
graph(): SymbolGraph$1;
|
|
589
|
+
readonly isTestFile: TestFileCheck;
|
|
590
|
+
/** Raw window commits, renames intact; absent with --skip-history or without git. */
|
|
591
|
+
readonly history?: CoChangeWindowCommits;
|
|
592
|
+
}
|
|
593
|
+
interface InitFileResult {
|
|
594
|
+
readonly file: string;
|
|
595
|
+
readonly action: 'created' | 'updated' | 'skipped';
|
|
596
|
+
readonly warning?: string;
|
|
597
|
+
}
|
|
598
|
+
interface ClaudeHookEntry {
|
|
599
|
+
readonly event: string;
|
|
600
|
+
readonly matcher?: string;
|
|
601
|
+
readonly command: string;
|
|
602
|
+
}
|
|
603
|
+
interface InitPrompter {
|
|
604
|
+
confirm(message: string, initial: boolean): Promise<boolean>;
|
|
605
|
+
select<T extends string>(message: string, options: readonly {
|
|
606
|
+
readonly value: T;
|
|
607
|
+
readonly label: string;
|
|
608
|
+
}[], initial: T): Promise<T>;
|
|
609
|
+
}
|
|
610
|
+
interface InitPartContext {
|
|
611
|
+
readonly projectRoot: string;
|
|
612
|
+
readonly toolIds: readonly string[];
|
|
613
|
+
readonly dryRun: boolean;
|
|
614
|
+
readonly yes: boolean;
|
|
615
|
+
readonly boundaries?: 'by-rung' | 'report';
|
|
616
|
+
/** Returns `initial` when not interactive or with --yes. */
|
|
617
|
+
readonly prompt: InitPrompter;
|
|
618
|
+
ensureConfigFile(): InitFileResult;
|
|
619
|
+
ensureClaudeHookEntry(entry: ClaudeHookEntry): InitFileResult;
|
|
620
|
+
installSkill(platformId: string, name: string, content: string): InitFileResult | undefined;
|
|
621
|
+
}
|
|
622
|
+
/** The part a module adds to `ctxo init`. */
|
|
623
|
+
interface InitContribution {
|
|
624
|
+
readonly part: 'domain';
|
|
625
|
+
apply(ctx: InitPartContext): Promise<readonly InitFileResult[]>;
|
|
626
|
+
}
|
|
627
|
+
/** What a module contributes. Every member is optional; the CLI uses the ones present. */
|
|
628
|
+
interface CtxoModuleRegistration {
|
|
629
|
+
readonly id: 'domain';
|
|
630
|
+
/** Capabilities `ctxo index` requests from the plugins on the module's behalf. */
|
|
631
|
+
readonly indexCapabilities?: {
|
|
632
|
+
readonly facts?: boolean;
|
|
633
|
+
};
|
|
634
|
+
indexPass?(ctx: IndexPassContext): Promise<void>;
|
|
635
|
+
registerTools?(registrar: ToolRegistrar): void;
|
|
636
|
+
readonly enrich?: Partial<Record<CoreToolName, ResponseEnricher>>;
|
|
637
|
+
registerCommands?(registrar: CommandRegistrar): void;
|
|
638
|
+
readonly init?: InitContribution;
|
|
639
|
+
readonly doctorChecks?: readonly IHealthCheck[];
|
|
640
|
+
}
|
|
641
|
+
/** The runtime services a module gets from the CLI instead of importing them. */
|
|
642
|
+
interface CtxoHostServices {
|
|
643
|
+
createLogger(namespace: string): Logger;
|
|
644
|
+
loadConfig(ctxoRoot: string): LoadedConfig;
|
|
645
|
+
/** The CLI's glob matcher: forward-slash normalised, dotfiles included. */
|
|
646
|
+
makeGlobMatcher(patterns: readonly string[]): (path: string) => boolean;
|
|
647
|
+
/** The classifier the contexts view uses: test globs, `index.tests`, test-framework annotations. */
|
|
648
|
+
createTestFileCheck(config: CtxoConfig, indices: readonly FileIndex[]): TestFileCheck;
|
|
649
|
+
createGit(projectRoot: string): IGitPort;
|
|
650
|
+
readIndex(ctxoRoot: string): FileIndex[];
|
|
651
|
+
buildGraph(indices: readonly FileIndex[]): SymbolGraph$1;
|
|
652
|
+
/** The configured co-change window (`cochange.maxCommits`, `cochange.since`); undefined without git history. */
|
|
653
|
+
readCoChangeWindow(projectRoot: string, config: CtxoConfig): Promise<CoChangeWindowCommits | undefined>;
|
|
654
|
+
/** The nearest directory at or above `dir` that holds `.git`. */
|
|
655
|
+
findGitRoot(dir: string): string | undefined;
|
|
656
|
+
/** Short names of the attributes that mark a test (`Fact`, `Test`, `TestMethod`, ...): the classifier's own list. */
|
|
657
|
+
readonly testFrameworkAnnotations: readonly string[];
|
|
658
|
+
}
|
|
659
|
+
interface CtxoHost {
|
|
660
|
+
readonly cliVersion: string;
|
|
661
|
+
readonly mode: 'mcp' | 'cli' | 'hook';
|
|
662
|
+
readonly projectRoot: string;
|
|
663
|
+
readonly ctxoRoot: string;
|
|
664
|
+
readonly services: CtxoHostServices;
|
|
665
|
+
}
|
|
666
|
+
/** The `register` export of a module package. Resolves to undefined when the module declines to run. */
|
|
667
|
+
type CtxoModuleRegister = (host: CtxoHost) => Promise<CtxoModuleRegistration | undefined>;
|
|
668
|
+
|
|
669
|
+
interface IStoragePort {
|
|
670
|
+
writeSymbolFile(fileIndex: FileIndex): void;
|
|
671
|
+
readSymbolFile(relativePath: string): FileIndex | undefined;
|
|
672
|
+
listIndexedFiles(): string[];
|
|
673
|
+
deleteSymbolFile(relativePath: string): void;
|
|
674
|
+
getSymbolById(symbolId: string): SymbolNode | undefined;
|
|
675
|
+
getEdgesFrom(symbolId: string): GraphEdge[];
|
|
676
|
+
getEdgesTo(symbolId: string): GraphEdge[];
|
|
677
|
+
getAllSymbols(): SymbolNode[];
|
|
678
|
+
getAllEdges(): GraphEdge[];
|
|
679
|
+
bulkWrite(indices: FileIndex[]): void;
|
|
680
|
+
readCommunities(): CommunitySnapshot | undefined;
|
|
681
|
+
writeCommunities(snapshot: CommunitySnapshot): void;
|
|
682
|
+
listCommunityHistory(limit?: number): CommunitySnapshot[];
|
|
683
|
+
close(): void;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
interface IMaskingPort {
|
|
687
|
+
mask(text: string): string;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Response envelope — adds _meta field and truncates large payloads.
|
|
692
|
+
*
|
|
693
|
+
* Applied between payload construction and masking in every MCP handler.
|
|
694
|
+
* Threshold default: 8192 bytes (~8KB). Configurable via CTXO_RESPONSE_LIMIT env.
|
|
695
|
+
*/
|
|
696
|
+
interface ResponseMeta {
|
|
697
|
+
totalItems: number;
|
|
698
|
+
returnedItems: number;
|
|
699
|
+
truncated: boolean;
|
|
700
|
+
totalBytes: number;
|
|
701
|
+
hint?: string;
|
|
702
|
+
/**
|
|
703
|
+
* Workspace descriptor (forward-compat for Monorepo Workspace PRD).
|
|
704
|
+
* v0.7: `root` is set at startup; `package` is always undefined.
|
|
705
|
+
*/
|
|
706
|
+
workspace?: {
|
|
707
|
+
root: string;
|
|
708
|
+
package?: string;
|
|
709
|
+
};
|
|
710
|
+
/**
|
|
711
|
+
* How far the community snapshot has drifted from current git HEAD.
|
|
712
|
+
* Only populated on cluster-aware MCP tools (overlay, blast-radius,
|
|
713
|
+
* why-context, pr-impact). Tells AI agents whether the cluster / drift /
|
|
714
|
+
* boundary data they are about to act on is fresh or N commits stale.
|
|
715
|
+
*/
|
|
716
|
+
snapshotStaleness?: {
|
|
717
|
+
snapshotCommit: string;
|
|
718
|
+
currentHeadCommit?: string;
|
|
719
|
+
commitsBehind?: number;
|
|
720
|
+
hint?: string;
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
interface CreateModuleHostOptions {
|
|
725
|
+
readonly projectRoot: string;
|
|
726
|
+
readonly mode: CtxoHost['mode'];
|
|
727
|
+
/** Defaults to the running CLI's version. */
|
|
728
|
+
readonly cliVersion?: string;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* The host a module's `register(host)` receives: the CLI version, the run mode, the project paths and the
|
|
732
|
+
* shared services. Imports neither the CLI router nor the MCP server, so the hook route can build one.
|
|
733
|
+
*/
|
|
734
|
+
declare function createModuleHost(options: CreateModuleHostOptions): CtxoHost;
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* `@ctxo/cli/internal`: the API an opt-in module such as `@ctxo/domain` builds against (ADR-018).
|
|
738
|
+
*
|
|
739
|
+
* Types only, plus one runtime function, `createModuleHost`. Modules import the types with `import type`;
|
|
740
|
+
* every runtime service reaches them through `host.services`. No adapter is exported. The API changes only
|
|
741
|
+
* in minor releases. This file is a package entry and the one exception to the no-barrel rule.
|
|
742
|
+
*/
|
|
743
|
+
|
|
744
|
+
type SymbolGraph = SymbolGraph$1;
|
|
745
|
+
type BlastRadiusCalculator = BlastRadiusCalculator$1;
|
|
746
|
+
|
|
747
|
+
export { type BlastRadiusCalculator, type ChangeLog, type CheckContext, type CheckResult, type CheckStatus, type ClaudeHookEntry, type CoChangeEntry, type CoChangeWindowCommits, type CommandRegistrar, type CommitChangeSet, type CoreToolName, type CtxoConfig, type CtxoHost, type CtxoHostServices, type CtxoModuleRegister, type CtxoModuleRegistration, type EdgeKind, type FileChange, type FileChangeStatus, type FileIndex, type GitRange, type GitRefs, type GraphEdge, type IGitPort, type IHealthCheck, type IMaskingPort, type IStoragePort, type IndexPassContext, type InitContribution, type InitFileResult, type InitPartContext, type InitPrompter, type LoadedConfig, type Logger, type ModuleCommand, type ModuleCommandContext, type ModuleToolDefinition, type RangeCommit, type ResponseEnricher, type ResponseMeta, type SymbolGraph, type SymbolKind, type SymbolNode, type TestFileCheck, type ToolRegistrar, createModuleHost };
|