archtracker-mcp 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1709 -1473
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +101 -101
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +148 -134
- package/dist/mcp/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/arch-analyze/SKILL.md +2 -0
- package/skills/arch-check/SKILL.md +1 -0
- package/skills/arch-search/SKILL.md +4 -0
- package/skills/arch-snapshot/SKILL.md +1 -0
package/dist/index.js
CHANGED
|
@@ -2170,39 +2170,110 @@ function mergeLayerGraphs(projectRoot, layers) {
|
|
|
2170
2170
|
};
|
|
2171
2171
|
}
|
|
2172
2172
|
|
|
2173
|
-
// src/storage/
|
|
2174
|
-
import {
|
|
2173
|
+
// src/storage/layers.ts
|
|
2174
|
+
import { readFile as readFile2, writeFile, mkdir } from "fs/promises";
|
|
2175
2175
|
import { join as join5 } from "path";
|
|
2176
2176
|
import { z } from "zod";
|
|
2177
2177
|
var ARCHTRACKER_DIR = ".archtracker";
|
|
2178
|
+
var LAYERS_FILE = "layers.json";
|
|
2179
|
+
var LayerDefinitionSchema = z.object({
|
|
2180
|
+
name: z.string().min(1).regex(
|
|
2181
|
+
/^[a-zA-Z0-9_-]+$/,
|
|
2182
|
+
"Layer name must be alphanumeric (hyphens/underscores allowed)"
|
|
2183
|
+
),
|
|
2184
|
+
targetDir: z.string().min(1),
|
|
2185
|
+
language: z.enum(LANGUAGE_IDS).optional(),
|
|
2186
|
+
exclude: z.array(z.string()).optional(),
|
|
2187
|
+
color: z.string().optional(),
|
|
2188
|
+
description: z.string().optional()
|
|
2189
|
+
});
|
|
2190
|
+
var CrossLayerConnectionSchema = z.object({
|
|
2191
|
+
fromLayer: z.string(),
|
|
2192
|
+
fromFile: z.string(),
|
|
2193
|
+
toLayer: z.string(),
|
|
2194
|
+
toFile: z.string(),
|
|
2195
|
+
type: z.enum(["api-call", "event", "data-flow", "manual"]),
|
|
2196
|
+
label: z.string().optional()
|
|
2197
|
+
});
|
|
2198
|
+
var LayerConfigSchema = z.object({
|
|
2199
|
+
version: z.literal("1.0"),
|
|
2200
|
+
layers: z.array(LayerDefinitionSchema).min(1).refine(
|
|
2201
|
+
(layers) => {
|
|
2202
|
+
const names = layers.map((l) => l.name);
|
|
2203
|
+
return new Set(names).size === names.length;
|
|
2204
|
+
},
|
|
2205
|
+
{ message: "Layer names must be unique" }
|
|
2206
|
+
),
|
|
2207
|
+
connections: z.array(CrossLayerConnectionSchema).optional()
|
|
2208
|
+
});
|
|
2209
|
+
async function loadLayerConfig(projectRoot) {
|
|
2210
|
+
const filePath = join5(projectRoot, ARCHTRACKER_DIR, LAYERS_FILE);
|
|
2211
|
+
let raw;
|
|
2212
|
+
try {
|
|
2213
|
+
raw = await readFile2(filePath, "utf-8");
|
|
2214
|
+
} catch (error) {
|
|
2215
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
2216
|
+
return null;
|
|
2217
|
+
}
|
|
2218
|
+
throw new Error(`Failed to read ${filePath}`);
|
|
2219
|
+
}
|
|
2220
|
+
let parsed;
|
|
2221
|
+
try {
|
|
2222
|
+
parsed = JSON.parse(raw);
|
|
2223
|
+
} catch {
|
|
2224
|
+
throw new Error(`Invalid JSON in ${filePath}`);
|
|
2225
|
+
}
|
|
2226
|
+
const result = LayerConfigSchema.safeParse(parsed);
|
|
2227
|
+
if (!result.success) {
|
|
2228
|
+
const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).slice(0, 5).join("\n");
|
|
2229
|
+
throw new Error(`layers.json validation failed:
|
|
2230
|
+
${issues}`);
|
|
2231
|
+
}
|
|
2232
|
+
return result.data;
|
|
2233
|
+
}
|
|
2234
|
+
async function saveLayerConfig(projectRoot, config) {
|
|
2235
|
+
const dirPath = join5(projectRoot, ARCHTRACKER_DIR);
|
|
2236
|
+
const filePath = join5(dirPath, LAYERS_FILE);
|
|
2237
|
+
await mkdir(dirPath, { recursive: true });
|
|
2238
|
+
await writeFile(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
2239
|
+
}
|
|
2240
|
+
function isNodeError(error) {
|
|
2241
|
+
return error instanceof Error && "code" in error;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
// src/storage/snapshot.ts
|
|
2245
|
+
import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile3, access } from "fs/promises";
|
|
2246
|
+
import { join as join6 } from "path";
|
|
2247
|
+
import { z as z2 } from "zod";
|
|
2248
|
+
var ARCHTRACKER_DIR2 = ".archtracker";
|
|
2178
2249
|
var SNAPSHOT_FILE = "snapshot.json";
|
|
2179
|
-
var FileNodeSchema =
|
|
2180
|
-
path:
|
|
2181
|
-
exists:
|
|
2182
|
-
dependencies:
|
|
2183
|
-
dependents:
|
|
2250
|
+
var FileNodeSchema = z2.object({
|
|
2251
|
+
path: z2.string(),
|
|
2252
|
+
exists: z2.boolean(),
|
|
2253
|
+
dependencies: z2.array(z2.string()),
|
|
2254
|
+
dependents: z2.array(z2.string())
|
|
2184
2255
|
});
|
|
2185
|
-
var DependencyGraphSchema =
|
|
2186
|
-
rootDir:
|
|
2187
|
-
files:
|
|
2188
|
-
edges:
|
|
2189
|
-
source:
|
|
2190
|
-
target:
|
|
2191
|
-
type:
|
|
2256
|
+
var DependencyGraphSchema = z2.object({
|
|
2257
|
+
rootDir: z2.string(),
|
|
2258
|
+
files: z2.record(z2.string(), FileNodeSchema),
|
|
2259
|
+
edges: z2.array(z2.object({
|
|
2260
|
+
source: z2.string(),
|
|
2261
|
+
target: z2.string(),
|
|
2262
|
+
type: z2.enum(["static", "dynamic", "type-only"])
|
|
2192
2263
|
})),
|
|
2193
|
-
circularDependencies:
|
|
2194
|
-
totalFiles:
|
|
2195
|
-
totalEdges:
|
|
2264
|
+
circularDependencies: z2.array(z2.object({ cycle: z2.array(z2.string()) })),
|
|
2265
|
+
totalFiles: z2.number(),
|
|
2266
|
+
totalEdges: z2.number()
|
|
2196
2267
|
});
|
|
2197
|
-
var SnapshotSchema =
|
|
2198
|
-
version:
|
|
2199
|
-
timestamp:
|
|
2200
|
-
rootDir:
|
|
2268
|
+
var SnapshotSchema = z2.object({
|
|
2269
|
+
version: z2.enum([SCHEMA_VERSION, "1.0"]),
|
|
2270
|
+
timestamp: z2.string(),
|
|
2271
|
+
rootDir: z2.string(),
|
|
2201
2272
|
graph: DependencyGraphSchema
|
|
2202
2273
|
});
|
|
2203
2274
|
async function saveSnapshot(projectRoot, graph, multiLayer) {
|
|
2204
|
-
const dirPath =
|
|
2205
|
-
const filePath =
|
|
2275
|
+
const dirPath = join6(projectRoot, ARCHTRACKER_DIR2);
|
|
2276
|
+
const filePath = join6(dirPath, SNAPSHOT_FILE);
|
|
2206
2277
|
const snapshot = {
|
|
2207
2278
|
version: SCHEMA_VERSION,
|
|
2208
2279
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -2210,17 +2281,17 @@ async function saveSnapshot(projectRoot, graph, multiLayer) {
|
|
|
2210
2281
|
graph,
|
|
2211
2282
|
...multiLayer ? { multiLayer } : {}
|
|
2212
2283
|
};
|
|
2213
|
-
await
|
|
2214
|
-
await
|
|
2284
|
+
await mkdir2(dirPath, { recursive: true });
|
|
2285
|
+
await writeFile2(filePath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
2215
2286
|
return snapshot;
|
|
2216
2287
|
}
|
|
2217
2288
|
async function loadSnapshot(projectRoot) {
|
|
2218
|
-
const filePath =
|
|
2289
|
+
const filePath = join6(projectRoot, ARCHTRACKER_DIR2, SNAPSHOT_FILE);
|
|
2219
2290
|
let raw;
|
|
2220
2291
|
try {
|
|
2221
|
-
raw = await
|
|
2292
|
+
raw = await readFile3(filePath, "utf-8");
|
|
2222
2293
|
} catch (error) {
|
|
2223
|
-
if (
|
|
2294
|
+
if (isNodeError2(error) && error.code === "ENOENT") {
|
|
2224
2295
|
return null;
|
|
2225
2296
|
}
|
|
2226
2297
|
throw new StorageError(
|
|
@@ -2247,7 +2318,7 @@ async function loadSnapshot(projectRoot) {
|
|
|
2247
2318
|
}
|
|
2248
2319
|
async function hasArchtrackerDir(projectRoot) {
|
|
2249
2320
|
try {
|
|
2250
|
-
await access(
|
|
2321
|
+
await access(join6(projectRoot, ARCHTRACKER_DIR2));
|
|
2251
2322
|
return true;
|
|
2252
2323
|
} catch {
|
|
2253
2324
|
return false;
|
|
@@ -2259,7 +2330,7 @@ var StorageError = class extends Error {
|
|
|
2259
2330
|
this.name = "StorageError";
|
|
2260
2331
|
}
|
|
2261
2332
|
};
|
|
2262
|
-
function
|
|
2333
|
+
function isNodeError2(error) {
|
|
2263
2334
|
return error instanceof Error && "code" in error;
|
|
2264
2335
|
}
|
|
2265
2336
|
|
|
@@ -2359,77 +2430,6 @@ function arraysEqual(a, b) {
|
|
|
2359
2430
|
}
|
|
2360
2431
|
return true;
|
|
2361
2432
|
}
|
|
2362
|
-
|
|
2363
|
-
// src/storage/layers.ts
|
|
2364
|
-
import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
2365
|
-
import { join as join6 } from "path";
|
|
2366
|
-
import { z as z2 } from "zod";
|
|
2367
|
-
var ARCHTRACKER_DIR2 = ".archtracker";
|
|
2368
|
-
var LAYERS_FILE = "layers.json";
|
|
2369
|
-
var LayerDefinitionSchema = z2.object({
|
|
2370
|
-
name: z2.string().min(1).regex(
|
|
2371
|
-
/^[a-zA-Z0-9_-]+$/,
|
|
2372
|
-
"Layer name must be alphanumeric (hyphens/underscores allowed)"
|
|
2373
|
-
),
|
|
2374
|
-
targetDir: z2.string().min(1),
|
|
2375
|
-
language: z2.enum(LANGUAGE_IDS).optional(),
|
|
2376
|
-
exclude: z2.array(z2.string()).optional(),
|
|
2377
|
-
color: z2.string().optional(),
|
|
2378
|
-
description: z2.string().optional()
|
|
2379
|
-
});
|
|
2380
|
-
var CrossLayerConnectionSchema = z2.object({
|
|
2381
|
-
fromLayer: z2.string(),
|
|
2382
|
-
fromFile: z2.string(),
|
|
2383
|
-
toLayer: z2.string(),
|
|
2384
|
-
toFile: z2.string(),
|
|
2385
|
-
type: z2.enum(["api-call", "event", "data-flow", "manual"]),
|
|
2386
|
-
label: z2.string().optional()
|
|
2387
|
-
});
|
|
2388
|
-
var LayerConfigSchema = z2.object({
|
|
2389
|
-
version: z2.literal("1.0"),
|
|
2390
|
-
layers: z2.array(LayerDefinitionSchema).min(1).refine(
|
|
2391
|
-
(layers) => {
|
|
2392
|
-
const names = layers.map((l) => l.name);
|
|
2393
|
-
return new Set(names).size === names.length;
|
|
2394
|
-
},
|
|
2395
|
-
{ message: "Layer names must be unique" }
|
|
2396
|
-
),
|
|
2397
|
-
connections: z2.array(CrossLayerConnectionSchema).optional()
|
|
2398
|
-
});
|
|
2399
|
-
async function loadLayerConfig(projectRoot) {
|
|
2400
|
-
const filePath = join6(projectRoot, ARCHTRACKER_DIR2, LAYERS_FILE);
|
|
2401
|
-
let raw;
|
|
2402
|
-
try {
|
|
2403
|
-
raw = await readFile3(filePath, "utf-8");
|
|
2404
|
-
} catch (error) {
|
|
2405
|
-
if (isNodeError2(error) && error.code === "ENOENT") {
|
|
2406
|
-
return null;
|
|
2407
|
-
}
|
|
2408
|
-
throw new Error(`Failed to read ${filePath}`);
|
|
2409
|
-
}
|
|
2410
|
-
let parsed;
|
|
2411
|
-
try {
|
|
2412
|
-
parsed = JSON.parse(raw);
|
|
2413
|
-
} catch {
|
|
2414
|
-
throw new Error(`Invalid JSON in ${filePath}`);
|
|
2415
|
-
}
|
|
2416
|
-
const result = LayerConfigSchema.safeParse(parsed);
|
|
2417
|
-
if (!result.success) {
|
|
2418
|
-
const issues = result.error.issues.map((i) => ` ${i.path.join(".")}: ${i.message}`).slice(0, 5).join("\n");
|
|
2419
|
-
throw new Error(`layers.json validation failed:
|
|
2420
|
-
${issues}`);
|
|
2421
|
-
}
|
|
2422
|
-
return result.data;
|
|
2423
|
-
}
|
|
2424
|
-
async function saveLayerConfig(projectRoot, config) {
|
|
2425
|
-
const dirPath = join6(projectRoot, ARCHTRACKER_DIR2);
|
|
2426
|
-
const filePath = join6(dirPath, LAYERS_FILE);
|
|
2427
|
-
await mkdir2(dirPath, { recursive: true });
|
|
2428
|
-
await writeFile2(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
2429
|
-
}
|
|
2430
|
-
function isNodeError2(error) {
|
|
2431
|
-
return error instanceof Error && "code" in error;
|
|
2432
|
-
}
|
|
2433
2433
|
export {
|
|
2434
2434
|
AnalyzerError,
|
|
2435
2435
|
SCHEMA_VERSION,
|