engimcp 1.0.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +21 -0
  3. package/README.md +345 -0
  4. package/dist/audit/auditLog.d.ts +9 -0
  5. package/dist/audit/auditLog.js +20 -0
  6. package/dist/audit/auditLog.js.map +1 -0
  7. package/dist/bom/bomService.d.ts +23 -0
  8. package/dist/bom/bomService.js +44 -0
  9. package/dist/bom/bomService.js.map +1 -0
  10. package/dist/config/projectConfig.d.ts +16 -0
  11. package/dist/config/projectConfig.js +16 -0
  12. package/dist/config/projectConfig.js.map +1 -0
  13. package/dist/config/schema.d.ts +16 -0
  14. package/dist/config/schema.js +21 -0
  15. package/dist/config/schema.js.map +1 -0
  16. package/dist/context/contextPack.d.ts +31 -0
  17. package/dist/context/contextPack.js +142 -0
  18. package/dist/context/contextPack.js.map +1 -0
  19. package/dist/context/tokenBudget.d.ts +1 -0
  20. package/dist/context/tokenBudget.js +4 -0
  21. package/dist/context/tokenBudget.js.map +1 -0
  22. package/dist/decisions/decisionService.d.ts +21 -0
  23. package/dist/decisions/decisionService.js +62 -0
  24. package/dist/decisions/decisionService.js.map +1 -0
  25. package/dist/dev/smokeProjectStatus.d.ts +1 -0
  26. package/dist/dev/smokeProjectStatus.js +9 -0
  27. package/dist/dev/smokeProjectStatus.js.map +1 -0
  28. package/dist/documents/documentService.d.ts +83 -0
  29. package/dist/documents/documentService.js +371 -0
  30. package/dist/documents/documentService.js.map +1 -0
  31. package/dist/documents/frontmatter.d.ts +14 -0
  32. package/dist/documents/frontmatter.js +30 -0
  33. package/dist/documents/frontmatter.js.map +1 -0
  34. package/dist/documents/headings.d.ts +6 -0
  35. package/dist/documents/headings.js +15 -0
  36. package/dist/documents/headings.js.map +1 -0
  37. package/dist/documents/markdownParser.d.ts +2 -0
  38. package/dist/documents/markdownParser.js +3 -0
  39. package/dist/documents/markdownParser.js.map +1 -0
  40. package/dist/documents/sectionPatch.d.ts +7 -0
  41. package/dist/documents/sectionPatch.js +73 -0
  42. package/dist/documents/sectionPatch.js.map +1 -0
  43. package/dist/documents/templates.d.ts +1 -0
  44. package/dist/documents/templates.js +62 -0
  45. package/dist/documents/templates.js.map +1 -0
  46. package/dist/filesystem/filesystemService.d.ts +168 -0
  47. package/dist/filesystem/filesystemService.js +606 -0
  48. package/dist/filesystem/filesystemService.js.map +1 -0
  49. package/dist/git/gitAdapter.d.ts +25 -0
  50. package/dist/git/gitAdapter.js +99 -0
  51. package/dist/git/gitAdapter.js.map +1 -0
  52. package/dist/graph/graphBuilder.d.ts +27 -0
  53. package/dist/graph/graphBuilder.js +126 -0
  54. package/dist/graph/graphBuilder.js.map +1 -0
  55. package/dist/graph/impact.d.ts +18 -0
  56. package/dist/graph/impact.js +53 -0
  57. package/dist/graph/impact.js.map +1 -0
  58. package/dist/graph/relations.d.ts +7 -0
  59. package/dist/graph/relations.js +28 -0
  60. package/dist/graph/relations.js.map +1 -0
  61. package/dist/index.d.ts +2 -0
  62. package/dist/index.js +16 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/mcp/errors.d.ts +5 -0
  65. package/dist/mcp/errors.js +11 -0
  66. package/dist/mcp/errors.js.map +1 -0
  67. package/dist/mcp/prompts.d.ts +2 -0
  68. package/dist/mcp/prompts.js +39 -0
  69. package/dist/mcp/prompts.js.map +1 -0
  70. package/dist/mcp/resources.d.ts +2 -0
  71. package/dist/mcp/resources.js +36 -0
  72. package/dist/mcp/resources.js.map +1 -0
  73. package/dist/mcp/tools.d.ts +2 -0
  74. package/dist/mcp/tools.js +431 -0
  75. package/dist/mcp/tools.js.map +1 -0
  76. package/dist/project/pathSafety.d.ts +6 -0
  77. package/dist/project/pathSafety.js +137 -0
  78. package/dist/project/pathSafety.js.map +1 -0
  79. package/dist/project/projectInit.d.ts +11 -0
  80. package/dist/project/projectInit.js +81 -0
  81. package/dist/project/projectInit.js.map +1 -0
  82. package/dist/project/projectService.d.ts +36 -0
  83. package/dist/project/projectService.js +60 -0
  84. package/dist/project/projectService.js.map +1 -0
  85. package/dist/project/writeGuards.d.ts +3 -0
  86. package/dist/project/writeGuards.js +46 -0
  87. package/dist/project/writeGuards.js.map +1 -0
  88. package/dist/requirements/requirementService.d.ts +19 -0
  89. package/dist/requirements/requirementService.js +72 -0
  90. package/dist/requirements/requirementService.js.map +1 -0
  91. package/dist/runtime/options.d.ts +7 -0
  92. package/dist/runtime/options.js +34 -0
  93. package/dist/runtime/options.js.map +1 -0
  94. package/dist/search/ftsIndex.d.ts +29 -0
  95. package/dist/search/ftsIndex.js +96 -0
  96. package/dist/search/ftsIndex.js.map +1 -0
  97. package/dist/search/searchService.d.ts +20 -0
  98. package/dist/search/searchService.js +17 -0
  99. package/dist/search/searchService.js.map +1 -0
  100. package/dist/server.d.ts +2 -0
  101. package/dist/server.js +16 -0
  102. package/dist/server.js.map +1 -0
  103. package/dist/storage/sqlite.d.ts +15 -0
  104. package/dist/storage/sqlite.js +80 -0
  105. package/dist/storage/sqlite.js.map +1 -0
  106. package/dist/tasks/taskService.d.ts +17 -0
  107. package/dist/tasks/taskService.js +57 -0
  108. package/dist/tasks/taskService.js.map +1 -0
  109. package/dist/utils/atomicWrite.d.ts +1 -0
  110. package/dist/utils/atomicWrite.js +10 -0
  111. package/dist/utils/atomicWrite.js.map +1 -0
  112. package/dist/utils/errors.d.ts +1 -0
  113. package/dist/utils/errors.js +2 -0
  114. package/dist/utils/errors.js.map +1 -0
  115. package/dist/utils/ids.d.ts +3 -0
  116. package/dist/utils/ids.js +25 -0
  117. package/dist/utils/ids.js.map +1 -0
  118. package/dist/validation/checks.d.ts +1 -0
  119. package/dist/validation/checks.js +2 -0
  120. package/dist/validation/checks.js.map +1 -0
  121. package/dist/validation/validator.d.ts +18 -0
  122. package/dist/validation/validator.js +131 -0
  123. package/dist/validation/validator.js.map +1 -0
  124. package/dist/verification/testReportService.d.ts +19 -0
  125. package/dist/verification/testReportService.js +42 -0
  126. package/dist/verification/testReportService.js.map +1 -0
  127. package/dist/version.d.ts +1 -0
  128. package/dist/version.js +2 -0
  129. package/dist/version.js.map +1 -0
  130. package/package.json +49 -0
  131. package/templates/design_doc.md +24 -0
  132. package/templates/edr.md +58 -0
  133. package/templates/requirement.md +30 -0
  134. package/templates/task.md +22 -0
@@ -0,0 +1,80 @@
1
+ import { access, mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import initSqlJs from "sql.js";
4
+ import { buildDocumentRegistry } from "../documents/documentService.js";
5
+ import { buildGraph } from "../graph/graphBuilder.js";
6
+ import { validateProject } from "../validation/validator.js";
7
+ export async function ensureIndex(root) {
8
+ const indexPath = path.join(root, ".engimcp/index.sqlite");
9
+ try {
10
+ await access(indexPath);
11
+ return { ok: true, path: ".engimcp/index.sqlite", rebuilt: false };
12
+ }
13
+ catch {
14
+ const index = await rebuildIndex(root);
15
+ return { ok: true, path: index.path, rebuilt: true, index };
16
+ }
17
+ }
18
+ export async function rebuildIndex(root) {
19
+ const SQL = await initSqlJs({
20
+ locateFile: (file) => path.join(process.cwd(), "node_modules/sql.js/dist", file)
21
+ });
22
+ const registry = await buildDocumentRegistry(root);
23
+ const graph = await buildGraph(root);
24
+ const validation = await validateProject({ root });
25
+ const db = new SQL.Database();
26
+ db.run(`
27
+ create table documents(id text, path text, kind text, status text, version text, title text, summary text);
28
+ create table relations(source_id text, relation_type text, target_id text, source_path text);
29
+ create table validation_issues(severity text, code text, message text, path text, entity_id text);
30
+ `);
31
+ for (const document of registry.documents) {
32
+ db.run("insert into documents values (?, ?, ?, ?, ?, ?, ?)", [
33
+ document.id ?? null,
34
+ document.path,
35
+ document.kind ?? null,
36
+ document.status ?? null,
37
+ document.version ?? null,
38
+ document.title ?? null,
39
+ document.summary ?? null
40
+ ]);
41
+ }
42
+ for (const edge of graph.edges) {
43
+ db.run("insert into relations values (?, ?, ?, ?)", [
44
+ edge.source_id,
45
+ edge.relation_type,
46
+ edge.target_id,
47
+ edge.source_path
48
+ ]);
49
+ }
50
+ for (const issue of validation.errors) {
51
+ db.run("insert into validation_issues values (?, ?, ?, ?, ?)", [
52
+ "error",
53
+ issue.code,
54
+ issue.message,
55
+ issue.path ?? null,
56
+ issue.entity_id ?? null
57
+ ]);
58
+ }
59
+ for (const issue of validation.warnings) {
60
+ db.run("insert into validation_issues values (?, ?, ?, ?, ?)", [
61
+ "warning",
62
+ issue.code,
63
+ issue.message,
64
+ issue.path ?? null,
65
+ issue.entity_id ?? null
66
+ ]);
67
+ }
68
+ const indexPath = path.join(root, ".engimcp/index.sqlite");
69
+ await mkdir(path.dirname(indexPath), { recursive: true });
70
+ await writeFile(indexPath, Buffer.from(db.export()));
71
+ db.close();
72
+ return {
73
+ ok: true,
74
+ path: ".engimcp/index.sqlite",
75
+ documents: registry.documents.length,
76
+ relations: graph.edges.length,
77
+ validation_issues: validation.errors.length + validation.warnings.length
78
+ };
79
+ }
80
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface CreateTaskInput {
2
+ root: string;
3
+ title: string;
4
+ priority?: "low" | "medium" | "high";
5
+ related?: string[];
6
+ due?: string | null;
7
+ dry_run?: boolean;
8
+ }
9
+ export declare function createTask(input: CreateTaskInput): Promise<{
10
+ id: string;
11
+ path: string;
12
+ content: string;
13
+ } | {
14
+ id: string;
15
+ path: string;
16
+ content?: undefined;
17
+ }>;
@@ -0,0 +1,57 @@
1
+ import { writeAuditLog } from "../audit/auditLog.js";
2
+ import { buildDocumentRegistry } from "../documents/documentService.js";
3
+ import { serializeDocument } from "../documents/frontmatter.js";
4
+ import { assertAbsoluteRoot, resolveSafePath } from "../project/pathSafety.js";
5
+ import { assertProjectWritable } from "../project/writeGuards.js";
6
+ import { atomicWrite } from "../utils/atomicWrite.js";
7
+ import { nextSequentialId, slugify } from "../utils/ids.js";
8
+ export async function createTask(input) {
9
+ const root = assertAbsoluteRoot(input.root);
10
+ await assertProjectWritable(root);
11
+ const registry = await buildDocumentRegistry(root);
12
+ const id = nextSequentialId(registry.byId.keys(), "TASK", 4);
13
+ const relativePath = `docs/tasks/${id}-${slugify(input.title)}.md`;
14
+ const frontmatter = {
15
+ id,
16
+ kind: "task",
17
+ status: "todo",
18
+ priority: input.priority ?? "medium",
19
+ version: "0.1.0",
20
+ related: input.related ?? [],
21
+ blocked_by: [],
22
+ due: input.due ?? null
23
+ };
24
+ const body = `# ${id}: ${input.title}
25
+
26
+ ## Goal
27
+
28
+ ${input.title}
29
+
30
+ ## Context
31
+
32
+ Related: ${(input.related ?? []).join(", ")}
33
+
34
+ ## Work Items
35
+
36
+ - [ ] Define implementation steps.
37
+
38
+ ## Definition of Done
39
+
40
+ - [ ] Work is complete and validated.
41
+ `;
42
+ const content = serializeDocument(frontmatter, body);
43
+ if (input.dry_run) {
44
+ return { id, path: relativePath, content };
45
+ }
46
+ await atomicWrite(await resolveSafePath(root, relativePath), content);
47
+ await writeAuditLog({
48
+ root,
49
+ tool: "engi_task_create",
50
+ target: id,
51
+ operation: "create",
52
+ result: "ok",
53
+ diff_summary: "task created"
54
+ });
55
+ return { id, path: relativePath };
56
+ }
57
+ //# sourceMappingURL=taskService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskService.js","sourceRoot":"","sources":["../../src/tasks/taskService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAW5D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,EAAE,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,cAAc,EAAE,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IACnE,MAAM,WAAW,GAAG;QAClB,EAAE;QACF,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,QAAQ;QACpC,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;QAC5B,UAAU,EAAE,EAAE;QACd,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI;KACvB,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,EAAE,KAAK,KAAK,CAAC,KAAK;;;;EAIpC,KAAK,CAAC,KAAK;;;;WAIF,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;CAS1C,CAAC;IACA,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAErD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,WAAW,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,MAAM,aAAa,CAAC;QAClB,IAAI;QACJ,IAAI,EAAE,kBAAkB;QACxB,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,QAAQ;QACnB,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,cAAc;KAC7B,CAAC,CAAC;IAEH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function atomicWrite(filePath: string, content: string): Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { mkdir, rename, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ export async function atomicWrite(filePath, content) {
4
+ const directory = path.dirname(filePath);
5
+ const temporaryPath = path.join(directory, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
6
+ await mkdir(directory, { recursive: true });
7
+ await writeFile(temporaryPath, content, "utf8");
8
+ await rename(temporaryPath, filePath);
9
+ }
10
+ //# sourceMappingURL=atomicWrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomicWrite.js","sourceRoot":"","sources":["../../src/utils/atomicWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC7B,SAAS,EACT,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,CAC/D,CAAC;IAEF,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,SAAS,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1 @@
1
+ export { EngiMcpError } from "../mcp/errors.js";
@@ -0,0 +1,2 @@
1
+ export { EngiMcpError } from "../mcp/errors.js";
2
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function isEntityId(value: string): boolean;
2
+ export declare function nextSequentialId(existingIds: Iterable<string>, prefix: string, width?: number): string;
3
+ export declare function slugify(value: string): string;
@@ -0,0 +1,25 @@
1
+ export function isEntityId(value) {
2
+ return /^[A-Z][A-Z0-9-]*-\d+$/.test(value);
3
+ }
4
+ export function nextSequentialId(existingIds, prefix, width = 3) {
5
+ let max = 0;
6
+ const pattern = new RegExp(`^${escapeRegExp(prefix)}-(\\d+)$`);
7
+ for (const id of existingIds) {
8
+ const match = id.match(pattern);
9
+ if (match) {
10
+ max = Math.max(max, Number(match[1]));
11
+ }
12
+ }
13
+ return `${prefix}-${String(max + 1).padStart(width, "0")}`;
14
+ }
15
+ export function slugify(value) {
16
+ return (value
17
+ .toLowerCase()
18
+ .replace(/[^a-z0-9]+/g, "-")
19
+ .replace(/^-+|-+$/g, "")
20
+ .slice(0, 64) || "item");
21
+ }
22
+ function escapeRegExp(value) {
23
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24
+ }
25
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../../src/utils/ids.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAA6B,EAAE,MAAc,EAAE,KAAK,GAAG,CAAC;IACvF,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAE/D,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,CACL,KAAK;SACF,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAC1B,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const validationChecks: readonly ["ids", "frontmatter", "links", "requirements", "cycles"];
@@ -0,0 +1,2 @@
1
+ export const validationChecks = ["ids", "frontmatter", "links", "requirements", "cycles"];
2
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/validation/checks.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAU,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface ValidationIssue {
2
+ code: string;
3
+ message: string;
4
+ path?: string;
5
+ paths?: string[];
6
+ entity_id?: string;
7
+ }
8
+ export interface ValidateProjectInput {
9
+ root: string;
10
+ checks?: string[];
11
+ severity?: "error" | "warning";
12
+ }
13
+ export interface ValidateProjectResult {
14
+ ok: boolean;
15
+ errors: ValidationIssue[];
16
+ warnings: ValidationIssue[];
17
+ }
18
+ export declare function validateProject(input: ValidateProjectInput): Promise<ValidateProjectResult>;
@@ -0,0 +1,131 @@
1
+ import { buildDocumentRegistry, extractFrontmatterLinks } from "../documents/documentService.js";
2
+ import { buildGraph, findDependencyCycles } from "../graph/graphBuilder.js";
3
+ import { assertAbsoluteRoot } from "../project/pathSafety.js";
4
+ const requiredFrontmatterFields = ["id", "kind", "status", "version"];
5
+ const statusesByKind = {
6
+ requirement: new Set([
7
+ "draft",
8
+ "proposed",
9
+ "accepted",
10
+ "implemented",
11
+ "verified",
12
+ "rejected",
13
+ "superseded"
14
+ ]),
15
+ decision: new Set(["proposed", "accepted", "deprecated", "superseded"]),
16
+ task: new Set(["todo", "in_progress", "blocked", "done", "cancelled"])
17
+ };
18
+ export async function validateProject(input) {
19
+ const root = assertAbsoluteRoot(input.root);
20
+ const registry = await buildDocumentRegistry(root);
21
+ const errors = [];
22
+ const warnings = [];
23
+ const ids = new Map();
24
+ const requirementsVerifiedByReports = new Set();
25
+ for (const document of registry.documents) {
26
+ if (document.kind !== "test_report" && document.kind !== "test_plan") {
27
+ continue;
28
+ }
29
+ for (const requirementId of extractStringList(document.frontmatter.verifies)) {
30
+ requirementsVerifiedByReports.add(requirementId);
31
+ }
32
+ }
33
+ for (const document of registry.documents) {
34
+ if (document.id) {
35
+ ids.set(document.id, [...(ids.get(document.id) ?? []), document.path]);
36
+ }
37
+ if (document.frontmatterError) {
38
+ errors.push({
39
+ code: "BROKEN_FRONTMATTER",
40
+ message: document.frontmatterError,
41
+ path: document.path,
42
+ entity_id: document.id
43
+ });
44
+ continue;
45
+ }
46
+ for (const field of requiredFrontmatterFields) {
47
+ if (document.frontmatter[field] === undefined) {
48
+ errors.push({
49
+ code: "MISSING_FRONTMATTER_FIELD",
50
+ message: `Missing required frontmatter field: ${field}`,
51
+ path: document.path,
52
+ entity_id: document.id
53
+ });
54
+ }
55
+ }
56
+ const validStatuses = document.kind ? statusesByKind[document.kind] : undefined;
57
+ if (validStatuses && document.status && !validStatuses.has(document.status)) {
58
+ errors.push({
59
+ code: "INVALID_STATUS",
60
+ message: `Invalid status for ${document.kind}: ${document.status}`,
61
+ path: document.path,
62
+ entity_id: document.id
63
+ });
64
+ }
65
+ if (isRequirementKind(document.kind) &&
66
+ ["accepted", "implemented"].includes(document.status ?? "") &&
67
+ !hasRequirementVerification(document.id, document.frontmatter, requirementsVerifiedByReports)) {
68
+ warnings.push({
69
+ code: "REQUIREMENT_UNVERIFIED",
70
+ message: `Requirement ${document.id ?? document.path} has no verification links`,
71
+ path: document.path,
72
+ entity_id: document.id
73
+ });
74
+ }
75
+ if (isRequirementKind(document.kind) &&
76
+ !hasRequirementVerification(document.id, document.frontmatter, requirementsVerifiedByReports)) {
77
+ warnings.push({
78
+ code: "REQUIREMENT_WITHOUT_TESTS",
79
+ message: `Requirement ${document.id ?? document.path} has no tests`,
80
+ path: document.path,
81
+ entity_id: document.id
82
+ });
83
+ }
84
+ for (const targetId of extractFrontmatterLinks(document.frontmatter)) {
85
+ if (!registry.byId.has(targetId)) {
86
+ warnings.push({
87
+ code: "BROKEN_LINK",
88
+ message: `Target ID not found: ${targetId}`,
89
+ path: document.path,
90
+ entity_id: document.id
91
+ });
92
+ }
93
+ }
94
+ }
95
+ for (const [id, paths] of ids.entries()) {
96
+ if (paths.length > 1) {
97
+ errors.push({
98
+ code: "DUPLICATE_ID",
99
+ message: `ID ${id} is used by multiple documents`,
100
+ paths,
101
+ entity_id: id
102
+ });
103
+ }
104
+ }
105
+ const graph = await buildGraph(root);
106
+ for (const cycle of findDependencyCycles(graph)) {
107
+ warnings.push({
108
+ code: "DEPENDENCY_CYCLE",
109
+ message: `Dependency cycle detected: ${cycle.join(" -> ")}`
110
+ });
111
+ }
112
+ return {
113
+ ok: errors.length === 0,
114
+ errors,
115
+ warnings
116
+ };
117
+ }
118
+ function extractStringList(value) {
119
+ if (Array.isArray(value)) {
120
+ return value.filter((item) => typeof item === "string");
121
+ }
122
+ return typeof value === "string" ? [value] : [];
123
+ }
124
+ function isRequirementKind(kind) {
125
+ return kind === "requirement" || kind === "requirements";
126
+ }
127
+ function hasRequirementVerification(requirementId, frontmatter, verifiedByReports) {
128
+ return (extractStringList(frontmatter.verified_by).length > 0 ||
129
+ (requirementId !== undefined && verifiedByReports.has(requirementId)));
130
+ }
131
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validation/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface CreateTestReportInput {
2
+ root: string;
3
+ id: string;
4
+ title: string;
5
+ verifies: string[];
6
+ result: "pass" | "fail" | "blocked";
7
+ dry_run?: boolean;
8
+ }
9
+ export declare function createTestReport(input: CreateTestReportInput): Promise<{
10
+ id: string;
11
+ path: string;
12
+ content: string;
13
+ audit_id?: undefined;
14
+ } | {
15
+ id: string;
16
+ path: string;
17
+ audit_id: string;
18
+ content?: undefined;
19
+ }>;
@@ -0,0 +1,42 @@
1
+ import { writeAuditLog } from "../audit/auditLog.js";
2
+ import { serializeDocument } from "../documents/frontmatter.js";
3
+ import { assertAbsoluteRoot, resolveSafePath } from "../project/pathSafety.js";
4
+ import { assertProjectWritable } from "../project/writeGuards.js";
5
+ import { atomicWrite } from "../utils/atomicWrite.js";
6
+ import { slugify } from "../utils/ids.js";
7
+ export async function createTestReport(input) {
8
+ const root = assertAbsoluteRoot(input.root);
9
+ await assertProjectWritable(root);
10
+ const relativePath = `docs/tests/${input.id}-${slugify(input.title)}.md`;
11
+ const content = serializeDocument({
12
+ id: input.id,
13
+ kind: "test_report",
14
+ status: "completed",
15
+ version: "0.1.0",
16
+ verifies: input.verifies,
17
+ result: input.result
18
+ }, `# ${input.id}: ${input.title}
19
+
20
+ ## Result
21
+
22
+ ${input.result}
23
+
24
+ ## Verifies
25
+
26
+ ${input.verifies.map((id) => `- ${id}`).join("\n")}
27
+ `);
28
+ if (input.dry_run) {
29
+ return { id: input.id, path: relativePath, content };
30
+ }
31
+ await atomicWrite(await resolveSafePath(root, relativePath), content);
32
+ const auditId = await writeAuditLog({
33
+ root,
34
+ tool: "engi_test_report_create",
35
+ target: input.id,
36
+ operation: "create",
37
+ result: "ok",
38
+ diff_summary: "test report created"
39
+ });
40
+ return { id: input.id, path: relativePath, audit_id: auditId };
41
+ }
42
+ //# sourceMappingURL=testReportService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testReportService.js","sourceRoot":"","sources":["../../src/verification/testReportService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAW1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAA4B;IACjE,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,YAAY,GAAG,cAAc,KAAK,CAAC,EAAE,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IACzE,MAAM,OAAO,GAAG,iBAAiB,CAC/B;QACE,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,WAAW;QACnB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,EACD,KAAK,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,KAAK;;;;EAI/B,KAAK,CAAC,MAAM;;;;EAIZ,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;CACjD,CACE,CAAC;IAEF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IACvD,CAAC;IAED,MAAM,WAAW,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC;QAClC,IAAI;QACJ,IAAI,EAAE,yBAAyB;QAC/B,MAAM,EAAE,KAAK,CAAC,EAAE;QAChB,SAAS,EAAE,QAAQ;QACnB,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,qBAAqB;KACpC,CAAC,CAAC;IAEH,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACjE,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const ENGI_MCP_VERSION = "1.0.0";
@@ -0,0 +1,2 @@
1
+ export const ENGI_MCP_VERSION = "1.0.0";
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "engimcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for managing engineering projects in Markdown/Git.",
5
+ "type": "module",
6
+ "bin": {
7
+ "engimcp": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "templates",
12
+ "README.md",
13
+ "CHANGELOG.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.json",
18
+ "check": "npm run build && npm run lint && npm run format:check && npm test",
19
+ "dev": "tsx src/index.ts",
20
+ "format": "prettier --write --no-error-on-unmatched-pattern \"src/**/*.ts\" \"tests/**/*.ts\" \".github/**/*.yml\" \"*.json\" \"*.js\" \"*.yaml\" \"*.yml\"",
21
+ "format:check": "prettier --check --no-error-on-unmatched-pattern \"src/**/*.ts\" \"tests/**/*.ts\" \".github/**/*.yml\" \"*.json\" \"*.js\" \"*.yaml\" \"*.yml\"",
22
+ "lint": "eslint .",
23
+ "smoke": "npm run build && node dist/dev/smokeProjectStatus.js",
24
+ "start": "node dist/index.js",
25
+ "test": "vitest run",
26
+ "typecheck": "tsc -p tsconfig.json --noEmit"
27
+ },
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.29.0",
30
+ "sql.js": "^1.14.1",
31
+ "yaml": "^2.9.0",
32
+ "zod": "^4.4.3"
33
+ },
34
+ "devDependencies": {
35
+ "@eslint/js": "^10.0.1",
36
+ "@types/node": "^24.0.10",
37
+ "@types/sql.js": "^1.4.11",
38
+ "eslint": "^10.6.0",
39
+ "prettier": "^3.9.4",
40
+ "tsx": "^4.20.3",
41
+ "typescript": "^5.8.3",
42
+ "typescript-eslint": "^8.62.1",
43
+ "vitest": "^4.1.9"
44
+ },
45
+ "engines": {
46
+ "node": ">=20"
47
+ },
48
+ "license": "MIT"
49
+ }
@@ -0,0 +1,24 @@
1
+ ---
2
+ id: DOC-EXAMPLE
3
+ kind: design_doc
4
+ status: draft
5
+ version: 0.1.0
6
+ tags: []
7
+ depends_on: []
8
+ impacts: []
9
+ decided_by: []
10
+ ---
11
+
12
+ # Document Title
13
+
14
+ ## Purpose
15
+
16
+ ## Requirements
17
+
18
+ ## Current Solution
19
+
20
+ ## Calculations / Arguments
21
+
22
+ ## Risks
23
+
24
+ ## Related Documents
@@ -0,0 +1,58 @@
1
+ ---
2
+ id: EDR-0000
3
+ kind: decision
4
+ status: proposed
5
+ date: YYYY-MM-DD
6
+ title: Decision Title
7
+ related_requirements: []
8
+ impacts: []
9
+ supersedes: []
10
+ ---
11
+
12
+ # EDR-0000: Decision Title
13
+
14
+ ## Status
15
+
16
+ Proposed / Accepted / Deprecated / Superseded
17
+
18
+ ## Context
19
+
20
+ What problem is being solved? Which constraints matter?
21
+
22
+ ## Options
23
+
24
+ ### Option A
25
+
26
+ Pros:
27
+
28
+ Cons:
29
+
30
+ ### Option B
31
+
32
+ Pros:
33
+
34
+ Cons:
35
+
36
+ ## Decision
37
+
38
+ What was selected and why.
39
+
40
+ ## Consequences
41
+
42
+ Positive:
43
+
44
+ Negative:
45
+
46
+ Trade-offs:
47
+
48
+ ## Affected Documents
49
+
50
+ -
51
+
52
+ ## Affected Requirements
53
+
54
+ -
55
+
56
+ ## Open Questions
57
+
58
+ -
@@ -0,0 +1,30 @@
1
+ ---
2
+ id: FR-000
3
+ kind: requirement
4
+ requirement_type: functional
5
+ status: draft
6
+ priority: must
7
+ version: 0.1.0
8
+ verified_by: []
9
+ decided_by: []
10
+ ---
11
+
12
+ # FR-000: Requirement Title
13
+
14
+ ## Statement
15
+
16
+ The system must ...
17
+
18
+ ## Rationale
19
+
20
+ Why this requirement is needed.
21
+
22
+ ## Acceptance Criteria
23
+
24
+ - [ ] ...
25
+
26
+ ## Links
27
+
28
+ - Decisions:
29
+ - Tests:
30
+ - Documents: