@danielblomma/cortex-mcp 2.4.1 → 2.4.2

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +5 -0
  3. package/bin/cli/arguments.mjs +60 -0
  4. package/bin/cli/context-passthrough.mjs +129 -0
  5. package/bin/cli/daemon.mjs +157 -0
  6. package/bin/cli/enterprise.mjs +516 -0
  7. package/bin/cli/help.mjs +88 -0
  8. package/bin/cli/hooks.mjs +199 -0
  9. package/bin/cli/mcp-command.mjs +87 -0
  10. package/bin/cli/paths.mjs +14 -0
  11. package/bin/cli/process.mjs +49 -0
  12. package/bin/cli/project-commands.mjs +237 -0
  13. package/bin/cli/project-runtime.mjs +34 -0
  14. package/bin/cli/query-command.mjs +18 -0
  15. package/bin/cli/router.mjs +66 -0
  16. package/bin/cli/run-command.mjs +44 -0
  17. package/bin/cli/scaffold-ownership.mjs +936 -0
  18. package/bin/cli/scaffold.mjs +687 -0
  19. package/bin/cli/stage-command.mjs +9 -0
  20. package/bin/cli/telemetry-command.mjs +18 -0
  21. package/bin/cli/trusted-runtime.mjs +18 -0
  22. package/bin/cortex.mjs +6 -1834
  23. package/mcp-registry-submission.json +1 -1
  24. package/package.json +3 -2
  25. package/scaffold/ownership/baseline-v2.4.1.json +22 -0
  26. package/scaffold/ownership/current.json +4 -0
  27. package/scaffold/ownership/v1.json +456 -0
  28. package/scaffold/scripts/ingest-parsers.mjs +1 -387
  29. package/scaffold/scripts/ingest-worker.mjs +4 -1
  30. package/scaffold/scripts/ingest.mjs +5 -3899
  31. package/scaffold/scripts/lib/ingest/arguments.mjs +78 -0
  32. package/scaffold/scripts/lib/ingest/chunks.mjs +212 -0
  33. package/scaffold/scripts/lib/ingest/config.mjs +120 -0
  34. package/scaffold/scripts/lib/ingest/constants.mjs +222 -0
  35. package/scaffold/scripts/lib/ingest/files.mjs +387 -0
  36. package/scaffold/scripts/lib/ingest/incremental-state.mjs +131 -0
  37. package/scaffold/scripts/lib/ingest/io.mjs +78 -0
  38. package/scaffold/scripts/lib/ingest/main.mjs +76 -0
  39. package/scaffold/scripts/lib/ingest/parser-composition.mjs +140 -0
  40. package/scaffold/scripts/lib/ingest/parser-registry.mjs +387 -0
  41. package/scaffold/scripts/lib/ingest/pipeline-stages.mjs +1625 -0
  42. package/scaffold/scripts/lib/ingest/projects.mjs +272 -0
  43. package/scaffold/scripts/lib/ingest/relations.mjs +860 -0
  44. package/scaffold/scripts/lib/ingest/runtime-paths.mjs +11 -0
  45. package/scaffold/scripts/lib/ingest/workers.mjs +264 -0
@@ -0,0 +1,272 @@
1
+ import path from "node:path";
2
+ import { PROJECT_DEFINITION_EXTENSIONS } from "./constants.mjs";
3
+ import { toPosixPath } from "./files.mjs";
4
+ import {
5
+ decodeXmlEntities,
6
+ extractXmlTagValue,
7
+ relationKey
8
+ } from "./relations.mjs";
9
+ import { REPO_ROOT } from "./runtime-paths.mjs";
10
+
11
+ export function projectIdFor(filePath) {
12
+ return `project:${filePath}`;
13
+ }
14
+
15
+ export function isProjectDefinitionFile(filePath) {
16
+ return PROJECT_DEFINITION_EXTENSIONS.has(path.extname(filePath).toLowerCase());
17
+ }
18
+
19
+ export function resolveProjectRelativePath(baseFilePath, includePath) {
20
+ if (!includePath) {
21
+ return null;
22
+ }
23
+
24
+ const normalizedInclude = toPosixPath(decodeXmlEntities(includePath).trim().replace(/\\/g, "/"));
25
+ if (!normalizedInclude) {
26
+ return null;
27
+ }
28
+
29
+ const resolved = path.resolve(REPO_ROOT, path.dirname(baseFilePath), normalizedInclude);
30
+ const relPath = toPosixPath(path.relative(REPO_ROOT, resolved));
31
+ if (!relPath || relPath.startsWith("../")) {
32
+ return null;
33
+ }
34
+
35
+ return relPath;
36
+ }
37
+
38
+ export function projectLanguageForExtension(ext) {
39
+ switch (ext) {
40
+ case ".vbproj":
41
+ return "vbnet";
42
+ case ".csproj":
43
+ return "csharp";
44
+ case ".fsproj":
45
+ return "fsharp";
46
+ case ".vcxproj":
47
+ return "cpp";
48
+ case ".sln":
49
+ return "solution";
50
+ default:
51
+ return "dotnet";
52
+ }
53
+ }
54
+
55
+ export function collectXmlIncludeValues(content, elementNames) {
56
+ const values = [];
57
+ const pattern = new RegExp(
58
+ `<(?:${elementNames.join("|")})\\b[^>]*\\bInclude="([^"]+)"[^>]*\\/?>`,
59
+ "gi"
60
+ );
61
+ let match;
62
+ while ((match = pattern.exec(content)) !== null) {
63
+ values.push(decodeXmlEntities(match[1]).trim());
64
+ }
65
+ return values;
66
+ }
67
+
68
+ export function parseSolutionProject(fileRecord, indexedFileIds) {
69
+ const declaredMembers = [];
70
+ const referencesProjectRelations = [];
71
+ const includesFileRelations = [];
72
+ const fileRelationKeys = new Set();
73
+ const ext = path.extname(fileRecord.path).toLowerCase();
74
+ const fallbackName = path.basename(fileRecord.path, ext);
75
+ const projectPattern =
76
+ /^Project\([^)]*\)\s*=\s*"([^"]+)",\s*"([^"]+\.(?:vbproj|csproj|fsproj|vcxproj))",\s*"\{[^"]+\}"$/gim;
77
+
78
+ let match;
79
+ while ((match = projectPattern.exec(fileRecord.content)) !== null) {
80
+ const memberName = match[1].trim();
81
+ const memberPath = resolveProjectRelativePath(fileRecord.path, match[2]);
82
+ if (!memberPath) {
83
+ continue;
84
+ }
85
+ declaredMembers.push({ name: memberName, path: memberPath });
86
+ const targetId = projectIdFor(memberPath);
87
+ if (indexedFileIds.has(`file:${memberPath}`)) {
88
+ referencesProjectRelations.push({
89
+ from: projectIdFor(fileRecord.path),
90
+ to: targetId,
91
+ note: `solution_member:${memberName}`
92
+ });
93
+ }
94
+ }
95
+
96
+ for (const fileId of [`file:${fileRecord.path}`]) {
97
+ if (indexedFileIds.has(fileId) && !fileRelationKeys.has(fileId)) {
98
+ fileRelationKeys.add(fileId);
99
+ includesFileRelations.push({ from: projectIdFor(fileRecord.path), to: fileId });
100
+ }
101
+ }
102
+
103
+ const summaryParts = [`Solution ${fallbackName}`];
104
+ if (declaredMembers.length > 0) {
105
+ summaryParts.push(`Contains ${declaredMembers.length} project references`);
106
+ }
107
+
108
+ return {
109
+ project: {
110
+ id: projectIdFor(fileRecord.path),
111
+ path: fileRecord.path,
112
+ name: fallbackName,
113
+ kind: "solution",
114
+ language: projectLanguageForExtension(ext),
115
+ target_framework: "",
116
+ summary: `${summaryParts.join(". ")}.`,
117
+ file_count: includesFileRelations.length,
118
+ updated_at: fileRecord.updated_at,
119
+ source_of_truth: false,
120
+ trust_level: 78,
121
+ status: "active"
122
+ },
123
+ includesFileRelations,
124
+ referencesProjectRelations
125
+ };
126
+ }
127
+ export function parseDotNetProject(fileRecord, indexedFileIds) {
128
+ const ext = path.extname(fileRecord.path).toLowerCase();
129
+ const fallbackName = path.basename(fileRecord.path, ext);
130
+ const assemblyName = extractXmlTagValue(fileRecord.content, "AssemblyName");
131
+ const rootNamespace = extractXmlTagValue(fileRecord.content, "RootNamespace");
132
+ const targetFrameworkRaw =
133
+ extractXmlTagValue(fileRecord.content, "TargetFramework") ||
134
+ extractXmlTagValue(fileRecord.content, "TargetFrameworkVersion") ||
135
+ extractXmlTagValue(fileRecord.content, "TargetFrameworks");
136
+ const targetFramework = targetFrameworkRaw.split(";")[0].trim();
137
+ const includeCandidates = collectXmlIncludeValues(fileRecord.content, [
138
+ "Compile",
139
+ "Content",
140
+ "EmbeddedResource",
141
+ "None",
142
+ "Page",
143
+ "ApplicationDefinition"
144
+ ]);
145
+ const projectReferenceCandidates = collectXmlIncludeValues(fileRecord.content, ["ProjectReference"]);
146
+ const includesFileRelations = [];
147
+ const referencesProjectRelations = [];
148
+ const fileRelationKeys = new Set();
149
+
150
+ const addFileRelation = (relPath) => {
151
+ const fileId = `file:${relPath}`;
152
+ if (!indexedFileIds.has(fileId) || fileRelationKeys.has(fileId)) {
153
+ return;
154
+ }
155
+ fileRelationKeys.add(fileId);
156
+ includesFileRelations.push({
157
+ from: projectIdFor(fileRecord.path),
158
+ to: fileId
159
+ });
160
+ };
161
+
162
+ addFileRelation(fileRecord.path);
163
+
164
+ for (const includePath of includeCandidates) {
165
+ const relPath = resolveProjectRelativePath(fileRecord.path, includePath);
166
+ if (!relPath) {
167
+ continue;
168
+ }
169
+ addFileRelation(relPath);
170
+ }
171
+
172
+ for (const includePath of projectReferenceCandidates) {
173
+ const relPath = resolveProjectRelativePath(fileRecord.path, includePath);
174
+ if (!relPath) {
175
+ continue;
176
+ }
177
+ const targetFileId = `file:${relPath}`;
178
+ if (!indexedFileIds.has(targetFileId)) {
179
+ continue;
180
+ }
181
+ referencesProjectRelations.push({
182
+ from: projectIdFor(fileRecord.path),
183
+ to: projectIdFor(relPath),
184
+ note: includePath
185
+ });
186
+ }
187
+
188
+ const summaryParts = [
189
+ `${projectLanguageForExtension(ext).toUpperCase()} project ${assemblyName || rootNamespace || fallbackName}`
190
+ ];
191
+ if (targetFramework) {
192
+ summaryParts.push(`Target framework ${targetFramework}`);
193
+ }
194
+ if (includesFileRelations.length > 1) {
195
+ summaryParts.push(`Includes ${includesFileRelations.length - 1} indexed project files`);
196
+ }
197
+ if (referencesProjectRelations.length > 0) {
198
+ summaryParts.push(`References ${referencesProjectRelations.length} projects`);
199
+ }
200
+
201
+ return {
202
+ project: {
203
+ id: projectIdFor(fileRecord.path),
204
+ path: fileRecord.path,
205
+ name: assemblyName || rootNamespace || fallbackName,
206
+ kind: "project",
207
+ language: projectLanguageForExtension(ext),
208
+ target_framework: targetFramework,
209
+ summary: `${summaryParts.join(". ")}.`,
210
+ file_count: includesFileRelations.length,
211
+ updated_at: fileRecord.updated_at,
212
+ source_of_truth: false,
213
+ trust_level: 80,
214
+ status: "active"
215
+ },
216
+ includesFileRelations,
217
+ referencesProjectRelations
218
+ };
219
+ }
220
+
221
+ export function generateProjects(fileRecords) {
222
+ const indexedFileIds = new Set(fileRecords.map((record) => record.id));
223
+ const projectRecords = [];
224
+ const includesFileRelations = [];
225
+ const referencesProjectRelations = [];
226
+ const includeKeys = new Set();
227
+ const referenceKeys = new Set();
228
+
229
+ for (const fileRecord of fileRecords) {
230
+ if (!isProjectDefinitionFile(fileRecord.path)) {
231
+ continue;
232
+ }
233
+
234
+ const ext = path.extname(fileRecord.path).toLowerCase();
235
+ const parsed =
236
+ ext === ".sln"
237
+ ? parseSolutionProject(fileRecord, indexedFileIds)
238
+ : parseDotNetProject(fileRecord, indexedFileIds);
239
+
240
+ projectRecords.push(parsed.project);
241
+
242
+ for (const relation of parsed.includesFileRelations) {
243
+ const key = relationKey(relation.from, relation.to);
244
+ if (includeKeys.has(key)) {
245
+ continue;
246
+ }
247
+ includeKeys.add(key);
248
+ includesFileRelations.push(relation);
249
+ }
250
+
251
+ for (const relation of parsed.referencesProjectRelations) {
252
+ const key = relationKey(relation.from, relation.to, relation.note);
253
+ if (referenceKeys.has(key)) {
254
+ continue;
255
+ }
256
+ referenceKeys.add(key);
257
+ referencesProjectRelations.push(relation);
258
+ }
259
+ }
260
+
261
+ projectRecords.sort((a, b) => a.path.localeCompare(b.path));
262
+ includesFileRelations.sort((a, b) => relationKey(a.from, a.to).localeCompare(relationKey(b.from, b.to)));
263
+ referencesProjectRelations.sort((a, b) =>
264
+ relationKey(a.from, a.to, a.note).localeCompare(relationKey(b.from, b.to, b.note))
265
+ );
266
+
267
+ return {
268
+ projects: projectRecords,
269
+ includesFileRelations,
270
+ referencesProjectRelations
271
+ };
272
+ }