@genvidtech/c3-domain-manager 0.0.1 → 0.6.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.
Files changed (70) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +195 -29
  3. package/dist/adapters/locations.d.ts +22 -0
  4. package/dist/adapters/locations.d.ts.map +1 -0
  5. package/dist/adapters/locations.js +42 -0
  6. package/dist/adapters/locations.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +99 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/domain/classification.d.ts +8 -0
  12. package/dist/domain/classification.d.ts.map +1 -0
  13. package/dist/domain/classification.js +66 -0
  14. package/dist/domain/classification.js.map +1 -0
  15. package/dist/domain/contextMap.d.ts +8 -0
  16. package/dist/domain/contextMap.d.ts.map +1 -0
  17. package/dist/domain/contextMap.js +168 -0
  18. package/dist/domain/contextMap.js.map +1 -0
  19. package/dist/domain/domainAnalysis.d.ts +25 -0
  20. package/dist/domain/domainAnalysis.d.ts.map +1 -0
  21. package/dist/domain/domainAnalysis.js +136 -0
  22. package/dist/domain/domainAnalysis.js.map +1 -0
  23. package/dist/domain/domainGenerator.d.ts +33 -0
  24. package/dist/domain/domainGenerator.d.ts.map +1 -0
  25. package/dist/domain/domainGenerator.js +307 -0
  26. package/dist/domain/domainGenerator.js.map +1 -0
  27. package/dist/domain/editorValidation.d.ts +19 -0
  28. package/dist/domain/editorValidation.d.ts.map +1 -0
  29. package/dist/domain/editorValidation.js +40 -0
  30. package/dist/domain/editorValidation.js.map +1 -0
  31. package/dist/domain/formatting.d.ts +16 -0
  32. package/dist/domain/formatting.d.ts.map +1 -0
  33. package/dist/domain/formatting.js +414 -0
  34. package/dist/domain/formatting.js.map +1 -0
  35. package/dist/domain/glossary.d.ts +20 -0
  36. package/dist/domain/glossary.d.ts.map +1 -0
  37. package/dist/domain/glossary.js +62 -0
  38. package/dist/domain/glossary.js.map +1 -0
  39. package/dist/domain/health.d.ts +14 -0
  40. package/dist/domain/health.d.ts.map +1 -0
  41. package/dist/domain/health.js +21 -0
  42. package/dist/domain/health.js.map +1 -0
  43. package/dist/domain/relationships.d.ts +13 -0
  44. package/dist/domain/relationships.d.ts.map +1 -0
  45. package/dist/domain/relationships.js +74 -0
  46. package/dist/domain/relationships.js.map +1 -0
  47. package/dist/domain/types.d.ts +290 -0
  48. package/dist/domain/types.d.ts.map +1 -0
  49. package/dist/domain/types.js +29 -0
  50. package/dist/domain/types.js.map +1 -0
  51. package/dist/index.d.ts +11 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +12 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/mcp/server.d.ts +3 -0
  56. package/dist/mcp/server.d.ts.map +1 -0
  57. package/dist/mcp/server.js +519 -0
  58. package/dist/mcp/server.js.map +1 -0
  59. package/docs/TOC.md +27 -0
  60. package/docs/decisions/0001-adopt-c3source-extractors.md +67 -0
  61. package/docs/decisions/0002-configurable-locations-adapters-seam.md +72 -0
  62. package/docs/decisions/0003-adopt-loadprojectconfig-schema-first.md +73 -0
  63. package/docs/decisions/0004-adopt-mcp-utils-0.4.0-helpers.md +74 -0
  64. package/docs/decisions/0005-validateforeditor-read-side-diagnostic.md +65 -0
  65. package/docs/decisions/0006-event-variable-reference-coupling.md +77 -0
  66. package/docs/decisions/0007-project-dir-resolverootfolder.md +72 -0
  67. package/docs/decisions/0008-adopt-openproject-option-a.md +74 -0
  68. package/docs/domain-architecture.md +242 -0
  69. package/docs/releasing.md +122 -0
  70. package/package.json +79 -8
@@ -0,0 +1,519 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { ReadWriteLock, ExpectedChanges, exposeDocs, loadProjectConfig, isMcpError, mcpContent, paginatedContent, withMcpErrors, READ_ONLY, REGENERATE, MUTATE } from "@genvidtech/mcp-utils";
8
+ import { formatDomainConfig } from "../domain/formatting.js";
9
+ import { DomainConfigSchema } from "../domain/types.js";
10
+ import { collectGlossary, findCollisions, formatGlossaryReport } from "../domain/glossary.js";
11
+ import { validateBoundaries, formatBoundaryReport } from "../domain/relationships.js";
12
+ import { validateEditorStrictness, formatEditorStrictnessReport } from "../domain/editorValidation.js";
13
+ import { computeHealth, formatHealthReport } from "../domain/health.js";
14
+ import { generateContextMap } from "../domain/contextMap.js";
15
+ import { listUncategorized, listStaleOverrides, collectValidDomainNames, validateOverrideKeys, validateOverrideValues, } from "../domain/domainAnalysis.js";
16
+ import { generateDomainIndex, computeDomainData } from "../domain/domainGenerator.js";
17
+ import { resolveLocations } from "../adapters/locations.js";
18
+ let PROJECT_ROOT = process.cwd();
19
+ let EXTRACTED_DIR = path.join(PROJECT_ROOT, "extracted");
20
+ let CONFIG_PATH = path.join(PROJECT_ROOT, "domain-config.json");
21
+ let CONFIG_DIR = path.dirname(CONFIG_PATH);
22
+ let CONFIG_FILENAME = path.basename(CONFIG_PATH);
23
+ let CONFIG_WATCH_KEY = CONFIG_PATH.replace(/\\/g, "/");
24
+ let EXTRACTED_EPHEMERAL = false;
25
+ const server = new McpServer({ name: "c3-domain-manager", version: "1.0.0" }, { capabilities: { logging: {}, resources: {} } });
26
+ const __pkgDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
27
+ exposeDocs(server, __pkgDir);
28
+ // ── Server State ─────────────────────────────────────────────────────────────
29
+ let txId = 0;
30
+ let domainDirty = false;
31
+ let suppressWatcherDepth = 0;
32
+ const rwlock = new ReadWriteLock();
33
+ const expectedChanges = new ExpectedChanges();
34
+ let domainConfigCache = null;
35
+ let domainDataCache = null;
36
+ // ── Helpers ──────────────────────────────────────────────────────────────────
37
+ function emitLog(level, message) {
38
+ server.sendLoggingMessage({ level, logger: "c3-domain-manager", data: message }).catch(() => { });
39
+ }
40
+ function isWithinDir(fullPath, dir) {
41
+ return fullPath.startsWith(dir + path.sep) || fullPath === dir;
42
+ }
43
+ function readExtracted(relPath) {
44
+ const fullPath = path.resolve(path.join(EXTRACTED_DIR, relPath));
45
+ if (!isWithinDir(fullPath, EXTRACTED_DIR))
46
+ return null;
47
+ if (!fs.existsSync(fullPath))
48
+ return null;
49
+ return fs.readFileSync(fullPath, "utf-8");
50
+ }
51
+ function notFound(tool, hint) {
52
+ return {
53
+ content: [{ type: "text", text: `${tool}: ${hint}` }],
54
+ isError: true,
55
+ };
56
+ }
57
+ const STALE_WARNING_LINE = "[Warning: domain index may be stale — run regenerate to refresh]";
58
+ const STALE_WARNING = "\n\n" + STALE_WARNING_LINE;
59
+ function appendStaleWarning(text) {
60
+ return domainDirty ? text + STALE_WARNING : text;
61
+ }
62
+ // Footer for paginatedContent on index reads: the stale warning rides as a
63
+ // trailing footer line (omitted entirely when the index is fresh).
64
+ function staleFooter() {
65
+ return domainDirty ? () => STALE_WARNING_LINE : undefined;
66
+ }
67
+ const PAGINATION_PARAMS = {
68
+ offset: z.number().int().min(1).optional().describe("Start line (1-based). Omit to start from beginning."),
69
+ limit: z.number().int().min(1).optional().describe("Max lines to return. Omit to return all."),
70
+ };
71
+ // ── Domain Config Cache ───────────────────────────────────────────────────────
72
+ async function loadDomainConfig() {
73
+ if (!domainConfigCache) {
74
+ const cfg = await loadProjectConfig(CONFIG_DIR, CONFIG_FILENAME, DomainConfigSchema);
75
+ if (isMcpError(cfg))
76
+ return cfg; // do NOT cache transient errors
77
+ domainConfigCache = cfg;
78
+ }
79
+ return domainConfigCache;
80
+ }
81
+ async function getDomainData() {
82
+ if (!domainDataCache) {
83
+ const config = await loadDomainConfig();
84
+ if (isMcpError(config))
85
+ return config;
86
+ domainDataCache = computeDomainData(PROJECT_ROOT, config);
87
+ }
88
+ return domainDataCache;
89
+ }
90
+ function writeDomainConfig(config) {
91
+ suppressWatcherDepth++;
92
+ try {
93
+ expectedChanges.add(CONFIG_WATCH_KEY);
94
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, "\t") + "\n", "utf-8");
95
+ }
96
+ finally {
97
+ suppressWatcherDepth--;
98
+ }
99
+ // Caching the mutated object without re-validation is safe: the lenient
100
+ // .passthrough() schema still accepts it, and we own the mutation.
101
+ domainConfigCache = config;
102
+ txId++;
103
+ domainDirty = true;
104
+ emitLog("info", `domain-config.json updated (txId → ${txId})`);
105
+ }
106
+ // onError hook for the mutate tools: a write that throws (e.g. a failed
107
+ // fs.writeFileSync) leaves txId un-bumped while the on-disk file may have
108
+ // changed — and the watcher swallows its own event via expectedChanges — so the
109
+ // client would never learn to reconcile. Bumping txId here forces a re-read.
110
+ function onWriteError(err) {
111
+ txId++;
112
+ emitLog("error", `domain-config.json write failed (txId → ${txId}): ${err instanceof Error ? err.message : String(err)}`);
113
+ }
114
+ // ── Tools ─────────────────────────────────────────────────────────────────────
115
+ server.registerTool("read-domain-index", {
116
+ title: "Read Domain Index",
117
+ description: "Read the domain index for a feature area. Without a domain, returns the master index listing all domains. With a domain name (e.g. 'Authentication'), returns that domain's detail page with functions, cross-domain dependencies, and include graphs.",
118
+ annotations: READ_ONLY,
119
+ inputSchema: {
120
+ domain: z.string().optional().describe("Domain name (e.g. 'Authentication'). Omit for master index."),
121
+ ...PAGINATION_PARAMS,
122
+ },
123
+ }, async ({ domain, offset, limit }) => rwlock.read(async () => {
124
+ const relPath = domain
125
+ ? `domain-index/${domain}.md`
126
+ : "domain-index/index.md";
127
+ const text = readExtracted(relPath);
128
+ if (text === null) {
129
+ const indexText = readExtracted("domain-index/index.md");
130
+ const hint = domain
131
+ ? `No domain index found for '${domain}'. Available domains:\n${indexText ?? "(index not found)"}`
132
+ : "domain-index/index.md not found. Run 'npm run generate-domain' to generate it.";
133
+ return notFound("read-domain-index", hint);
134
+ }
135
+ return paginatedContent(text, { offset, limit }, staleFooter());
136
+ }));
137
+ server.registerTool("read-domain-config", {
138
+ title: "Read Domain Config",
139
+ description: "Read the raw domain-config.json structure. Returns domains, shared subdomains, and overrides " +
140
+ "in a formatted text view. Use 'section' to filter to a specific part.",
141
+ annotations: READ_ONLY,
142
+ inputSchema: {
143
+ section: z.enum(["domains", "sharedSubdomains", "overrides", "all"]).default("all")
144
+ .describe("Which section to return (default: all)"),
145
+ },
146
+ }, async ({ section }) => rwlock.read(async () => {
147
+ try {
148
+ const config = await loadDomainConfig();
149
+ if (isMcpError(config))
150
+ return config;
151
+ const text = formatDomainConfig(config, section);
152
+ return { content: [{ type: "text", text }] };
153
+ }
154
+ catch (e) {
155
+ return notFound("read-domain-config", `Error: ${e instanceof Error ? e.message : String(e)}`);
156
+ }
157
+ }));
158
+ server.registerTool("list-uncategorized", {
159
+ title: "List Uncategorized Files",
160
+ description: "List project files (eventSheets, layouts, scripts) not covered by any domain mapping or override in domain-config.json. Useful for maintaining domain coverage.",
161
+ annotations: READ_ONLY,
162
+ inputSchema: {},
163
+ }, async () => rwlock.read(async () => {
164
+ try {
165
+ const config = await loadDomainConfig();
166
+ if (isMcpError(config))
167
+ return config;
168
+ const uncategorized = listUncategorized(PROJECT_ROOT, config);
169
+ if (uncategorized.length === 0) {
170
+ return { content: [{ type: "text", text: "All files are categorized." }] };
171
+ }
172
+ return {
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: `${uncategorized.length} uncategorized files:\n${uncategorized.join("\n")}`,
177
+ },
178
+ ],
179
+ };
180
+ }
181
+ catch (e) {
182
+ return notFound("list-uncategorized", `Error: ${e instanceof Error ? e.message : String(e)}`);
183
+ }
184
+ }));
185
+ server.registerTool("list-stale-overrides", {
186
+ title: "List Stale Overrides",
187
+ description: "List override entries in domain-config.json that point to files that no longer exist on disk. These should be removed to keep the domain config clean.",
188
+ annotations: READ_ONLY,
189
+ inputSchema: {},
190
+ }, async () => rwlock.read(async () => {
191
+ try {
192
+ const config = await loadDomainConfig();
193
+ if (isMcpError(config))
194
+ return config;
195
+ const stale = listStaleOverrides(PROJECT_ROOT, config);
196
+ if (stale.length === 0) {
197
+ return { content: [{ type: "text", text: "No stale overrides found." }] };
198
+ }
199
+ return {
200
+ content: [
201
+ {
202
+ type: "text",
203
+ text: `${stale.length} stale overrides:\n${stale.join("\n")}`,
204
+ },
205
+ ],
206
+ };
207
+ }
208
+ catch (e) {
209
+ return notFound("list-stale-overrides", `Error: ${e instanceof Error ? e.message : String(e)}`);
210
+ }
211
+ }));
212
+ server.registerTool("set-overrides", {
213
+ title: "Set Domain Overrides",
214
+ description: "Add or update overrides in domain-config.json. Each override maps a file path " +
215
+ "(e.g. 'eventSheets/Foo.json') to a domain or subdomain name. The domain must exist in the config.",
216
+ annotations: MUTATE,
217
+ inputSchema: {
218
+ overrides: z.record(z.string(), z.string())
219
+ .describe("File path → domain/subdomain name"),
220
+ txId: z.number().optional()
221
+ .describe("Expected txId for optimistic concurrency — rejected if stale"),
222
+ },
223
+ }, async ({ overrides: newOverrides, txId: expectedTxId }) => rwlock.write(withMcpErrors(async () => {
224
+ if (expectedTxId !== undefined && expectedTxId !== txId) {
225
+ return {
226
+ content: [{ type: "text", text: `State changed: expected txId ${expectedTxId}, got ${txId}. Re-read state and retry.` }],
227
+ isError: true,
228
+ };
229
+ }
230
+ const config = await loadDomainConfig();
231
+ if (isMcpError(config))
232
+ return config;
233
+ const validNames = collectValidDomainNames(config);
234
+ const keyErrors = validateOverrideKeys(Object.keys(newOverrides));
235
+ const valueErrors = validateOverrideValues(newOverrides, validNames);
236
+ const errors = [...keyErrors, ...valueErrors];
237
+ if (errors.length > 0) {
238
+ return {
239
+ content: [{ type: "text", text: `Validation failed:\n${errors.join("\n")}` }],
240
+ isError: true,
241
+ };
242
+ }
243
+ if (!config.overrides)
244
+ config.overrides = {};
245
+ const added = [];
246
+ const updated = [];
247
+ for (const [filePath, domain] of Object.entries(newOverrides)) {
248
+ if (filePath in config.overrides) {
249
+ updated.push(`${filePath}: ${config.overrides[filePath]} → ${domain}`);
250
+ }
251
+ else {
252
+ added.push(`${filePath} → ${domain}`);
253
+ }
254
+ config.overrides[filePath] = domain;
255
+ }
256
+ writeDomainConfig(config);
257
+ const parts = [];
258
+ if (added.length > 0)
259
+ parts.push(`Added ${added.length}:\n${added.join("\n")}`);
260
+ if (updated.length > 0)
261
+ parts.push(`Updated ${updated.length}:\n${updated.join("\n")}`);
262
+ return mcpContent(parts.join("\n\n"), `txId: ${txId}`);
263
+ }, { onError: onWriteError })));
264
+ server.registerTool("remove-overrides", {
265
+ title: "Remove Domain Overrides",
266
+ description: "Remove overrides from domain-config.json by file path. " +
267
+ "Non-existent keys are silently ignored. Use after list-stale-overrides to clean up.",
268
+ annotations: MUTATE,
269
+ inputSchema: {
270
+ paths: z.array(z.string())
271
+ .describe("File paths to remove from overrides"),
272
+ txId: z.number().optional()
273
+ .describe("Expected txId for optimistic concurrency — rejected if stale"),
274
+ },
275
+ }, async ({ paths, txId: expectedTxId }) => rwlock.write(withMcpErrors(async () => {
276
+ if (expectedTxId !== undefined && expectedTxId !== txId) {
277
+ return {
278
+ content: [{ type: "text", text: `State changed: expected txId ${expectedTxId}, got ${txId}. Re-read state and retry.` }],
279
+ isError: true,
280
+ };
281
+ }
282
+ const config = await loadDomainConfig();
283
+ if (isMcpError(config))
284
+ return config;
285
+ if (!config.overrides || Object.keys(config.overrides).length === 0) {
286
+ return { content: [{ type: "text", text: "No overrides to remove." }] };
287
+ }
288
+ const removed = [];
289
+ for (const p of paths) {
290
+ if (p in config.overrides) {
291
+ removed.push(`${p} (was: ${config.overrides[p]})`);
292
+ delete config.overrides[p];
293
+ }
294
+ }
295
+ if (removed.length === 0) {
296
+ return { content: [{ type: "text", text: "None of the specified paths were in overrides." }] };
297
+ }
298
+ writeDomainConfig(config);
299
+ return mcpContent(`Removed ${removed.length}:\n${removed.join("\n")}`, `txId: ${txId}`);
300
+ }, { onError: onWriteError })));
301
+ server.registerTool("regenerate", {
302
+ title: "Regenerate Domain Index",
303
+ description: "Run the domain index generator and update extracted/domain-index/. Clears the domainDirty flag. Use after external edits to domain-config.json or source files, or when domainDirty is true.",
304
+ annotations: REGENERATE,
305
+ inputSchema: {},
306
+ }, async () => rwlock.write(async () => {
307
+ const lines = [];
308
+ const log = (...args) => lines.push(args.map(String).join(" "));
309
+ try {
310
+ suppressWatcherDepth++;
311
+ try {
312
+ await generateDomainIndex(PROJECT_ROOT, EXTRACTED_DIR, CONFIG_DIR, CONFIG_FILENAME, log);
313
+ }
314
+ finally {
315
+ suppressWatcherDepth--;
316
+ }
317
+ // Populate domain data cache
318
+ const config = await loadDomainConfig();
319
+ if (isMcpError(config))
320
+ return config;
321
+ domainDataCache = computeDomainData(PROJECT_ROOT, config);
322
+ domainDirty = false;
323
+ return {
324
+ content: [{ type: "text", text: lines.join("\n") }],
325
+ };
326
+ }
327
+ catch (e) {
328
+ return {
329
+ content: [{ type: "text", text: `Error: ${e instanceof Error ? e.message : String(e)}` }],
330
+ isError: true,
331
+ };
332
+ }
333
+ }));
334
+ server.registerTool("get-state", {
335
+ title: "Get Server State",
336
+ description: "Returns the current server state: txId (incremented on domain-config.json changes) and domainDirty (true if domain-config.json or source files changed since last regeneration).",
337
+ annotations: READ_ONLY,
338
+ inputSchema: {},
339
+ }, async () => rwlock.read(async () => {
340
+ return {
341
+ content: [{ type: "text", text: `txId: ${txId}\ndomainDirty: ${domainDirty}` }],
342
+ };
343
+ }));
344
+ server.registerTool("glossary-check", {
345
+ title: "Check Glossary Collisions",
346
+ description: "Check for glossary term collisions across domains. Reports terms that appear in multiple domains with different definitions.",
347
+ annotations: READ_ONLY,
348
+ inputSchema: {},
349
+ }, async () => rwlock.read(async () => {
350
+ try {
351
+ const config = await loadDomainConfig();
352
+ if (isMcpError(config))
353
+ return config;
354
+ const entries = collectGlossary(config);
355
+ const collisions = findCollisions(entries);
356
+ const report = formatGlossaryReport(collisions);
357
+ return { content: [{ type: "text", text: report }] };
358
+ }
359
+ catch (e) {
360
+ return notFound("glossary-check", `Error: ${e instanceof Error ? e.message : String(e)}`);
361
+ }
362
+ }));
363
+ server.registerTool("validate-boundaries", {
364
+ title: "Validate Domain Boundaries",
365
+ description: "Validate domain boundaries by checking for undeclared cross-domain dependencies, stale relationship declarations, and forbidden dependency patterns (e.g., supporting domains depending on core domains).",
366
+ annotations: READ_ONLY,
367
+ inputSchema: {
368
+ domain: z.string().optional().describe("Filter violations to a specific domain"),
369
+ },
370
+ }, async ({ domain }) => rwlock.read(async () => {
371
+ try {
372
+ const config = await loadDomainConfig();
373
+ if (isMcpError(config))
374
+ return config;
375
+ const data = await getDomainData();
376
+ if (isMcpError(data))
377
+ return data;
378
+ const { domains } = data;
379
+ const report = validateBoundaries(domains, config, domain);
380
+ const text = formatBoundaryReport(report);
381
+ return { content: [{ type: "text", text: appendStaleWarning(text) }] };
382
+ }
383
+ catch (e) {
384
+ return notFound("validate-boundaries", `Error: ${e instanceof Error ? e.message : String(e)}`);
385
+ }
386
+ }));
387
+ server.registerTool("validate-editor", {
388
+ title: "Validate Editor Strictness",
389
+ description: "Report event sheets the C3 editor would reject on import (editor-strictness validation). Flags variable events missing a comment and group events missing a description — fields the C3 editor loader requires but the lenient parse types allow to be absent. Validates sheets fresh from disk, so its result is independent of domain-index staleness.",
390
+ annotations: READ_ONLY,
391
+ inputSchema: {},
392
+ }, async () => rwlock.read(async () => {
393
+ try {
394
+ const config = await loadDomainConfig();
395
+ if (isMcpError(config))
396
+ return config;
397
+ const report = validateEditorStrictness(PROJECT_ROOT, config);
398
+ // No appendStaleWarning: this diagnostic re-walks sheets fresh and never
399
+ // reads the cached domain index, so the index-staleness warning would mislead.
400
+ return { content: [{ type: "text", text: formatEditorStrictnessReport(report) }] };
401
+ }
402
+ catch (e) {
403
+ return notFound("validate-editor", `Error: ${e instanceof Error ? e.message : String(e)}`);
404
+ }
405
+ }));
406
+ server.registerTool("domain-health", {
407
+ title: "Domain Health Metrics",
408
+ description: "Compute coupling and instability metrics for domains. Ca = afferent coupling (incoming dependencies), Ce = efferent coupling (outgoing dependencies), Instability = Ce/(Ca+Ce).",
409
+ annotations: READ_ONLY,
410
+ inputSchema: {
411
+ domain: z.string().optional().describe("Compute metrics for a specific domain only"),
412
+ },
413
+ }, async ({ domain: domainFilter }) => rwlock.read(async () => {
414
+ try {
415
+ const data = await getDomainData();
416
+ if (isMcpError(data))
417
+ return data;
418
+ const { domains } = data;
419
+ let targetDomains = domains;
420
+ if (domainFilter) {
421
+ targetDomains = domains.filter(d => d.name === domainFilter);
422
+ if (targetDomains.length === 0) {
423
+ return notFound("domain-health", `Domain '${domainFilter}' not found`);
424
+ }
425
+ }
426
+ const results = targetDomains.map(d => ({ name: d.name, ...computeHealth(d) }));
427
+ const text = formatHealthReport(results);
428
+ return { content: [{ type: "text", text: appendStaleWarning(text) }] };
429
+ }
430
+ catch (e) {
431
+ return notFound("domain-health", `Error: ${e instanceof Error ? e.message : String(e)}`);
432
+ }
433
+ }));
434
+ server.registerTool("context-map", {
435
+ title: "Generate Context Map",
436
+ description: "Generate a context map showing relationships between domains. Supports text and mermaid output formats. Use 'domain' parameter to focus on a single domain's neighborhood.",
437
+ annotations: READ_ONLY,
438
+ inputSchema: {
439
+ format: z.enum(["text", "mermaid"]).describe("Output format"),
440
+ domain: z.string().optional().describe("Focus on this domain's 1-hop neighborhood"),
441
+ includeObserved: z.boolean().optional().default(true).describe("Include observed (undeclared) dependencies"),
442
+ },
443
+ }, async ({ format, domain, includeObserved }) => rwlock.read(async () => {
444
+ try {
445
+ const config = await loadDomainConfig();
446
+ if (isMcpError(config))
447
+ return config;
448
+ const data = await getDomainData();
449
+ if (isMcpError(data))
450
+ return data;
451
+ const { domains } = data;
452
+ const text = generateContextMap(domains, config, { format, domain, includeObserved });
453
+ return { content: [{ type: "text", text: appendStaleWarning(text) }] };
454
+ }
455
+ catch (e) {
456
+ return notFound("context-map", `Error: ${e instanceof Error ? e.message : String(e)}`);
457
+ }
458
+ }));
459
+ // ── File Watcher ─────────────────────────────────────────────────────────────
460
+ function setupWatcher() {
461
+ if (!fs.existsSync(CONFIG_PATH))
462
+ return;
463
+ fs.watch(CONFIG_PATH, () => {
464
+ if (suppressWatcherDepth > 0)
465
+ return;
466
+ if (expectedChanges.consume(CONFIG_WATCH_KEY))
467
+ return;
468
+ txId++;
469
+ domainDirty = true;
470
+ domainConfigCache = null;
471
+ domainDataCache = null;
472
+ emitLog("warning", `External change detected: domain-config.json (txId → ${txId})`);
473
+ });
474
+ // Periodically purge expired entries from expectedChanges
475
+ setInterval(() => expectedChanges.purgeExpired(), 30_000).unref();
476
+ }
477
+ // ── Start ─────────────────────────────────────────────────────────────────────
478
+ export async function startServer(loc = resolveLocations({}, process.cwd())) {
479
+ PROJECT_ROOT = loc.projectRoot;
480
+ EXTRACTED_DIR = loc.extractedDir;
481
+ CONFIG_PATH = loc.configPath;
482
+ CONFIG_DIR = loc.configDir;
483
+ CONFIG_FILENAME = loc.configFileName;
484
+ CONFIG_WATCH_KEY = loc.configWatchKey;
485
+ EXTRACTED_EPHEMERAL = loc.extractedEphemeral;
486
+ const domainIndexPath = path.join(EXTRACTED_DIR, "domain-index");
487
+ if (!fs.existsSync(domainIndexPath)) {
488
+ console.error(`[c3-domain-manager] domain-index not found — auto-generating...`);
489
+ try {
490
+ const log = (...args) => console.error(`[c3-domain-manager] ${args.map(String).join(" ")}`);
491
+ await generateDomainIndex(PROJECT_ROOT, EXTRACTED_DIR, CONFIG_DIR, CONFIG_FILENAME, log);
492
+ console.error(`[c3-domain-manager] Auto-generation complete`);
493
+ }
494
+ catch (e) {
495
+ console.error(`[c3-domain-manager] Warning: auto-generation failed — ${e instanceof Error ? e.message : String(e)}`);
496
+ console.error(`[c3-domain-manager] Run 'npx c3-domain-manager generate' manually to generate domain index`);
497
+ }
498
+ }
499
+ console.error(`[c3-domain-manager] Starting server in ${PROJECT_ROOT}`);
500
+ console.error(`[c3-domain-manager] config: ${CONFIG_PATH}${EXTRACTED_EPHEMERAL ? " | extracted: ephemeral" : ""}`);
501
+ // Graceful shutdown
502
+ function shutdown() {
503
+ console.error("[c3-domain-manager] Shutting down...");
504
+ server.close().catch(() => { });
505
+ if (EXTRACTED_EPHEMERAL) {
506
+ try {
507
+ fs.rmSync(EXTRACTED_DIR, { recursive: true, force: true });
508
+ }
509
+ catch { /* best-effort */ }
510
+ }
511
+ process.exit(0);
512
+ }
513
+ process.on("SIGINT", shutdown);
514
+ process.on("SIGTERM", shutdown);
515
+ setupWatcher();
516
+ const transport = new StdioServerTransport();
517
+ await server.connect(transport);
518
+ }
519
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
package/docs/TOC.md ADDED
@@ -0,0 +1,27 @@
1
+ # Documentation Index
2
+
3
+ <!--
4
+ Genvid plugin skills consult this index to find your project's docs.
5
+ Each entry should be a one-line description.
6
+ -->
7
+
8
+ ## Project context
9
+
10
+ - `domain-architecture.md` — the domain model concepts and the full `domain-config.json` schema
11
+
12
+ ## Operations
13
+
14
+ - `releasing.md` — how to cut a new release (version bump, tag convention, OIDC publish via `publish.yml`)
15
+
16
+ ## Decision Records
17
+
18
+ Architecture Decision Records, numbered chronologically by when the decision was made.
19
+
20
+ - `decisions/0001-adopt-c3source-extractors.md` — retire local `extraction.ts`; consume c3source 1.1.0 `extractFunctions`/`extractIncludes` (issue #5)
21
+ - `decisions/0002-configurable-locations-adapters-seam.md` — make the config path and extracted-output dir overridable via a pure `src/adapters/locations.ts` resolution seam (issue #7)
22
+ - `decisions/0003-adopt-loadprojectconfig-schema-first.md` — adopt mcp-utils 0.3.0 `loadProjectConfig`; make `DomainConfig` schema-first via `DomainConfigSchema` (issue #9)
23
+ - `decisions/0004-adopt-mcp-utils-0.4.0-helpers.md` — adopt mcp-utils 0.4.0 `mcpContent`/`paginatedContent`/`withMcpErrors` + annotation constants; harden mutate writes (issue #11)
24
+ - `decisions/0005-validateforeditor-read-side-diagnostic.md` — adopt c3source 1.4.0 `validateForEditor` as a read-side diagnostic, reframing #12's "before write-out" premise (issue #13)
25
+ - `decisions/0006-event-variable-reference-coupling.md` — add event-variable references as a second cross-domain coupling source aggregated under union semantics (issue #14)
26
+ - `decisions/0007-project-dir-resolverootfolder.md` — add `--project-dir` via mcp-utils 0.5.0 `resolveRootFolder` instead of hand-rolling root discovery (issue #16)
27
+ - `decisions/0008-adopt-openproject-option-a.md` — adopt `C3Project`/`openProject` for C3 file discovery in place of hardcoded section-folder joins (Option A: local-open in pure functions; issue #19)
@@ -0,0 +1,67 @@
1
+ # ADR 0001: Adopt `@genvid/c3source` 1.1.0 event-tree extractors; retire local `extraction.ts`
2
+
3
+ **Status:** Accepted
4
+ **Date:** 2026-06-02
5
+ **Issue:** #5 — adopt upstream extractors once c3source 1.1.0 ships them
6
+
7
+ > Recovered retroactively (2026-06-30) from commit `1fe2638` and the
8
+ > CLAUDE.md "When bumping `@genvidtech/c3source`" guidance. Numbered first
9
+ > because it is the earliest architectural decision in the project's history.
10
+
11
+ ---
12
+
13
+ ## Context
14
+
15
+ `c3-domain-manager` needs the exported function signatures and the include
16
+ edges out of each parsed event sheet. Originally this lived in a local
17
+ `src/domain/extraction.ts` that walked the C3 event tree by hand — stringly-typed
18
+ `eventType` checks and `as` casts over the raw event JSON — because the upstream
19
+ `@genvid/c3source` package did not yet expose typed extractors.
20
+
21
+ c3source 1.1.0 landed both upstream requests this had been waiting on: a typed
22
+ `extractFunctions(sheet)` over the `EventSheetEvent` union (upstream #23) and
23
+ `extractIncludes(sheet)` (upstream #24). c3source owns the Construct 3 platform
24
+ facts, so its typed extractors are authoritative where our hand-rolled walk was a
25
+ fragile re-derivation. Per the standing CLAUDE.md guidance ("when bumping
26
+ c3source, check whether new exports supersede local C3-parsing logic"), the bump
27
+ triggered an evaluation of whether to retire the local walk.
28
+
29
+ ## Decision
30
+
31
+ **Delete `src/domain/extraction.ts` and consume c3source's typed extractors
32
+ directly.** `domainGenerator.ts` calls `extractFunctions` / `extractIncludes`
33
+ and maps the typed output onto our local types:
34
+
35
+ - `extractFunctionDefs(sheet, sheetName)` is retained as one small exported
36
+ seam that maps c3source's `ExtractedFunction` → our `FunctionDef`
37
+ (param-string formatting, `sourceSheet`, and the custom-ACE
38
+ `objectClass`/`aceName` fields).
39
+ - Includes become `extractIncludes(sheet).map(r => r.includeSheet)`.
40
+ - `types.ts` re-exports c3source's `FunctionParameter` instead of defining a
41
+ byte-identical local copy.
42
+
43
+ ## Alternatives Considered
44
+
45
+ **Keep the hand-rolled walk.** Rejected: it duplicates platform knowledge that
46
+ c3source now owns and maintains, and the stringly-typed checks would silently rot
47
+ as the C3 event schema evolves. The typed extractors eliminate the `as` casts.
48
+
49
+ **Wrap c3source's extractors behind a local abstraction layer.** Rejected as
50
+ premature — only the thin `extractFunctionDefs` mapping seam is needed to bridge
51
+ to our `FunctionDef`; a broader abstraction would add indirection without a
52
+ second consumer to justify it.
53
+
54
+ ## Consequences
55
+
56
+ - The local event-tree walk is gone; c3source is now the single source of truth
57
+ for function and include extraction. This is the pattern later decisions follow
58
+ (see [[0005-validateforeditor-read-side-diagnostic]] and
59
+ [[0008-adopt-openproject-option-a]]): a c3source release ships a primitive that
60
+ retires a hand-rolled equivalent here.
61
+ - Behaviour-preserving: the full suite (130 tests at the time) stayed green and
62
+ generated output was unchanged.
63
+ - Removing the exported `extraction.ts` symbols is a public-API change. At 0.x a
64
+ breaking removal takes a **minor** bump, so this shipped as 0.1.3 → 0.2.0
65
+ (clarified in the release docs at the same time).
66
+ - `extractFunctionDefs` remains the one seam to maintain when c3source's
67
+ `ExtractedFunction` shape changes.