@mcoda/core 0.1.8 → 0.1.11

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 (216) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +2 -2
  3. package/dist/api/AgentsApi.d.ts +9 -1
  4. package/dist/api/AgentsApi.d.ts.map +1 -1
  5. package/dist/api/AgentsApi.js +201 -6
  6. package/dist/api/QaTasksApi.d.ts.map +1 -1
  7. package/dist/api/QaTasksApi.js +6 -0
  8. package/dist/api/TasksApi.d.ts.map +1 -1
  9. package/dist/api/TasksApi.js +1 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -0
  13. package/dist/prompts/PdrPrompts.d.ts.map +1 -1
  14. package/dist/prompts/PdrPrompts.js +9 -1
  15. package/dist/prompts/SdsPrompts.d.ts.map +1 -1
  16. package/dist/prompts/SdsPrompts.js +9 -0
  17. package/dist/services/agents/AgentRatingFormula.d.ts +27 -0
  18. package/dist/services/agents/AgentRatingFormula.d.ts.map +1 -0
  19. package/dist/services/agents/AgentRatingFormula.js +45 -0
  20. package/dist/services/agents/AgentRatingService.d.ts +60 -0
  21. package/dist/services/agents/AgentRatingService.d.ts.map +1 -0
  22. package/dist/services/agents/AgentRatingService.js +363 -0
  23. package/dist/services/agents/GatewayAgentService.d.ts +11 -0
  24. package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
  25. package/dist/services/agents/GatewayAgentService.js +525 -84
  26. package/dist/services/agents/GatewayHandoff.d.ts +11 -0
  27. package/dist/services/agents/GatewayHandoff.d.ts.map +1 -0
  28. package/dist/services/agents/GatewayHandoff.js +141 -0
  29. package/dist/services/agents/RoutingService.d.ts +1 -0
  30. package/dist/services/agents/RoutingService.d.ts.map +1 -1
  31. package/dist/services/agents/RoutingService.js +4 -4
  32. package/dist/services/backlog/BacklogService.d.ts +23 -0
  33. package/dist/services/backlog/BacklogService.d.ts.map +1 -1
  34. package/dist/services/backlog/BacklogService.js +62 -7
  35. package/dist/services/backlog/TaskOrderingHeuristics.d.ts +12 -0
  36. package/dist/services/backlog/TaskOrderingHeuristics.d.ts.map +1 -0
  37. package/dist/services/backlog/TaskOrderingHeuristics.js +56 -0
  38. package/dist/services/backlog/TaskOrderingService.d.ts +17 -4
  39. package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
  40. package/dist/services/backlog/TaskOrderingService.js +538 -79
  41. package/dist/services/docs/DocInventory.d.ts +11 -0
  42. package/dist/services/docs/DocInventory.d.ts.map +1 -0
  43. package/dist/services/docs/DocInventory.js +230 -0
  44. package/dist/services/docs/DocgenRunContext.d.ts +59 -0
  45. package/dist/services/docs/DocgenRunContext.d.ts.map +1 -0
  46. package/dist/services/docs/DocgenRunContext.js +4 -0
  47. package/dist/services/docs/DocsService.d.ts +70 -3
  48. package/dist/services/docs/DocsService.d.ts.map +1 -1
  49. package/dist/services/docs/DocsService.js +1930 -89
  50. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts +23 -0
  51. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts.map +1 -0
  52. package/dist/services/docs/alignment/DocAlignmentGraph.js +78 -0
  53. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts +19 -0
  54. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts.map +1 -0
  55. package/dist/services/docs/alignment/DocAlignmentPatcher.js +222 -0
  56. package/dist/services/docs/patch/DocPatchEngine.d.ts +57 -0
  57. package/dist/services/docs/patch/DocPatchEngine.d.ts.map +1 -0
  58. package/dist/services/docs/patch/DocPatchEngine.js +331 -0
  59. package/dist/services/docs/review/Glossary.d.ts +16 -0
  60. package/dist/services/docs/review/Glossary.d.ts.map +1 -0
  61. package/dist/services/docs/review/Glossary.js +47 -0
  62. package/dist/services/docs/review/ReviewReportRenderer.d.ts +3 -0
  63. package/dist/services/docs/review/ReviewReportRenderer.d.ts.map +1 -0
  64. package/dist/services/docs/review/ReviewReportRenderer.js +133 -0
  65. package/dist/services/docs/review/ReviewReportSchema.d.ts +39 -0
  66. package/dist/services/docs/review/ReviewReportSchema.d.ts.map +1 -0
  67. package/dist/services/docs/review/ReviewReportSchema.js +47 -0
  68. package/dist/services/docs/review/ReviewTypes.d.ts +76 -0
  69. package/dist/services/docs/review/ReviewTypes.d.ts.map +1 -0
  70. package/dist/services/docs/review/ReviewTypes.js +94 -0
  71. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts +7 -0
  72. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts.map +1 -0
  73. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.js +93 -0
  74. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts +7 -0
  75. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts.map +1 -0
  76. package/dist/services/docs/review/gates/ApiPathConsistencyGate.js +308 -0
  77. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts +8 -0
  78. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts.map +1 -0
  79. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.js +278 -0
  80. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts +8 -0
  81. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts.map +1 -0
  82. package/dist/services/docs/review/gates/DeploymentBlueprintGate.js +487 -0
  83. package/dist/services/docs/review/gates/NoMaybesGate.d.ts +8 -0
  84. package/dist/services/docs/review/gates/NoMaybesGate.d.ts.map +1 -0
  85. package/dist/services/docs/review/gates/NoMaybesGate.js +145 -0
  86. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts +7 -0
  87. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts.map +1 -0
  88. package/dist/services/docs/review/gates/OpenApiCoverageGate.js +266 -0
  89. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts +7 -0
  90. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts.map +1 -0
  91. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.js +59 -0
  92. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts +7 -0
  93. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts.map +1 -0
  94. package/dist/services/docs/review/gates/OpenQuestionsGate.js +200 -0
  95. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts +7 -0
  96. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts.map +1 -0
  97. package/dist/services/docs/review/gates/PdrInterfacesGate.js +159 -0
  98. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts +8 -0
  99. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts.map +1 -0
  100. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.js +129 -0
  101. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts +7 -0
  102. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts.map +1 -0
  103. package/dist/services/docs/review/gates/PdrOwnershipGate.js +169 -0
  104. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts +10 -0
  105. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts.map +1 -0
  106. package/dist/services/docs/review/gates/PlaceholderArtifactGate.js +261 -0
  107. package/dist/services/docs/review/gates/RfpConsentGate.d.ts +6 -0
  108. package/dist/services/docs/review/gates/RfpConsentGate.d.ts.map +1 -0
  109. package/dist/services/docs/review/gates/RfpConsentGate.js +127 -0
  110. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts +7 -0
  111. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts.map +1 -0
  112. package/dist/services/docs/review/gates/RfpDefinitionGate.js +173 -0
  113. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts +7 -0
  114. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts.map +1 -0
  115. package/dist/services/docs/review/gates/SdsAdaptersGate.js +196 -0
  116. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts +7 -0
  117. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts.map +1 -0
  118. package/dist/services/docs/review/gates/SdsDecisionsGate.js +89 -0
  119. package/dist/services/docs/review/gates/SdsOpsGate.d.ts +7 -0
  120. package/dist/services/docs/review/gates/SdsOpsGate.d.ts.map +1 -0
  121. package/dist/services/docs/review/gates/SdsOpsGate.js +162 -0
  122. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts +7 -0
  123. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts.map +1 -0
  124. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.js +166 -0
  125. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts +7 -0
  126. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts.map +1 -0
  127. package/dist/services/docs/review/gates/SqlRequiredTablesGate.js +273 -0
  128. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts +7 -0
  129. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts.map +1 -0
  130. package/dist/services/docs/review/gates/SqlSyntaxGate.js +203 -0
  131. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts +9 -0
  132. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts.map +1 -0
  133. package/dist/services/docs/review/gates/TerminologyNormalizationGate.js +217 -0
  134. package/dist/services/docs/review/glossary.json +47 -0
  135. package/dist/services/estimate/EstimateService.d.ts +2 -0
  136. package/dist/services/estimate/EstimateService.d.ts.map +1 -1
  137. package/dist/services/estimate/EstimateService.js +66 -18
  138. package/dist/services/estimate/VelocityService.d.ts +4 -0
  139. package/dist/services/estimate/VelocityService.d.ts.map +1 -1
  140. package/dist/services/estimate/VelocityService.js +179 -36
  141. package/dist/services/estimate/types.d.ts +1 -0
  142. package/dist/services/estimate/types.d.ts.map +1 -1
  143. package/dist/services/execution/GatewayTrioService.d.ts +200 -0
  144. package/dist/services/execution/GatewayTrioService.d.ts.map +1 -0
  145. package/dist/services/execution/GatewayTrioService.js +2492 -0
  146. package/dist/services/execution/QaApiRunner.d.ts +30 -0
  147. package/dist/services/execution/QaApiRunner.d.ts.map +1 -0
  148. package/dist/services/execution/QaApiRunner.js +881 -0
  149. package/dist/services/execution/QaFollowupService.d.ts +2 -0
  150. package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
  151. package/dist/services/execution/QaFollowupService.js +9 -2
  152. package/dist/services/execution/QaPlanValidator.d.ts +10 -0
  153. package/dist/services/execution/QaPlanValidator.d.ts.map +1 -0
  154. package/dist/services/execution/QaPlanValidator.js +128 -0
  155. package/dist/services/execution/QaProfileService.d.ts +27 -1
  156. package/dist/services/execution/QaProfileService.d.ts.map +1 -1
  157. package/dist/services/execution/QaProfileService.js +354 -7
  158. package/dist/services/execution/QaTasksService.d.ts +59 -1
  159. package/dist/services/execution/QaTasksService.d.ts.map +1 -1
  160. package/dist/services/execution/QaTasksService.js +3347 -318
  161. package/dist/services/execution/QaTestCommandBuilder.d.ts +51 -0
  162. package/dist/services/execution/QaTestCommandBuilder.d.ts.map +1 -0
  163. package/dist/services/execution/QaTestCommandBuilder.js +495 -0
  164. package/dist/services/execution/TaskSelectionService.d.ts +4 -2
  165. package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
  166. package/dist/services/execution/TaskSelectionService.js +144 -28
  167. package/dist/services/execution/TaskStateService.d.ts +19 -6
  168. package/dist/services/execution/TaskStateService.d.ts.map +1 -1
  169. package/dist/services/execution/TaskStateService.js +128 -13
  170. package/dist/services/execution/WorkOnTasksService.d.ts +32 -1
  171. package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
  172. package/dist/services/execution/WorkOnTasksService.js +4667 -722
  173. package/dist/services/jobs/JobInsightsService.d.ts +4 -0
  174. package/dist/services/jobs/JobInsightsService.d.ts.map +1 -1
  175. package/dist/services/jobs/JobInsightsService.js +51 -5
  176. package/dist/services/jobs/JobResumeService.d.ts.map +1 -1
  177. package/dist/services/jobs/JobResumeService.js +23 -10
  178. package/dist/services/jobs/JobService.d.ts +56 -4
  179. package/dist/services/jobs/JobService.d.ts.map +1 -1
  180. package/dist/services/jobs/JobService.js +232 -1
  181. package/dist/services/openapi/OpenApiService.d.ts +51 -0
  182. package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
  183. package/dist/services/openapi/OpenApiService.js +953 -106
  184. package/dist/services/planning/CreateTasksService.d.ts +21 -0
  185. package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
  186. package/dist/services/planning/CreateTasksService.js +569 -31
  187. package/dist/services/planning/RefineTasksService.d.ts +9 -0
  188. package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
  189. package/dist/services/planning/RefineTasksService.js +409 -59
  190. package/dist/services/review/CodeReviewService.d.ts +18 -0
  191. package/dist/services/review/CodeReviewService.d.ts.map +1 -1
  192. package/dist/services/review/CodeReviewService.js +1309 -167
  193. package/dist/services/review/ReviewNormalizer.d.ts +9 -0
  194. package/dist/services/review/ReviewNormalizer.d.ts.map +1 -0
  195. package/dist/services/review/ReviewNormalizer.js +147 -0
  196. package/dist/services/shared/AuthErrors.d.ts +3 -0
  197. package/dist/services/shared/AuthErrors.d.ts.map +1 -0
  198. package/dist/services/shared/AuthErrors.js +17 -0
  199. package/dist/services/shared/DocdexGuidance.d.ts +7 -0
  200. package/dist/services/shared/DocdexGuidance.d.ts.map +1 -0
  201. package/dist/services/shared/DocdexGuidance.js +12 -0
  202. package/dist/services/shared/ProjectGuidance.d.ts +17 -0
  203. package/dist/services/shared/ProjectGuidance.d.ts.map +1 -0
  204. package/dist/services/shared/ProjectGuidance.js +78 -0
  205. package/dist/services/system/ToolDenylist.d.ts +13 -0
  206. package/dist/services/system/ToolDenylist.d.ts.map +1 -0
  207. package/dist/services/system/ToolDenylist.js +85 -0
  208. package/dist/services/tasks/TaskCommentFormatter.d.ts +20 -0
  209. package/dist/services/tasks/TaskCommentFormatter.d.ts.map +1 -0
  210. package/dist/services/tasks/TaskCommentFormatter.js +54 -0
  211. package/dist/services/telemetry/TelemetryService.d.ts.map +1 -1
  212. package/dist/services/telemetry/TelemetryService.js +39 -7
  213. package/dist/workspace/WorkspaceManager.d.ts +26 -0
  214. package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
  215. package/dist/workspace/WorkspaceManager.js +206 -32
  216. package/package.json +6 -5
@@ -0,0 +1,273 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ const FEATURE_DEFINITIONS = [
4
+ {
5
+ key: "data_exports",
6
+ label: "data exports",
7
+ matchers: ["data export", "export job", "export artifact", "dataset export"],
8
+ requiredTables: ["data_export_jobs", "data_export_artifacts"],
9
+ },
10
+ {
11
+ key: "rights_policies",
12
+ label: "rights policies",
13
+ matchers: ["rights policy", "rights policies"],
14
+ requiredTables: ["rights_policies"],
15
+ },
16
+ {
17
+ key: "admin_audit",
18
+ label: "admin audit logs",
19
+ matchers: ["admin audit", "audit admin", "admin audit log"],
20
+ requiredTables: ["admin_audit_log"],
21
+ },
22
+ {
23
+ key: "event_outbox",
24
+ label: "event outbox",
25
+ matchers: ["event outbox", "outbox", "event bus", "message bus", "pub sub"],
26
+ requiredTables: ["event_outbox"],
27
+ },
28
+ ];
29
+ const CREATE_TABLE_PATTERN = /\\bcreate\\s+table\\s+(?:if\\s+not\\s+exists\\s+)?([`\"\\[]?[A-Za-z0-9_]+[`\"\\]]?)/i;
30
+ const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
31
+ const normalizeDocLine = (line) => line
32
+ .toLowerCase()
33
+ .replace(/[^a-z0-9]+/g, " ")
34
+ .trim();
35
+ const stripSqlComments = (line, state) => {
36
+ let working = line;
37
+ if (state.inBlockComment) {
38
+ const end = working.indexOf("*/");
39
+ if (end === -1)
40
+ return "";
41
+ working = working.slice(end + 2);
42
+ state.inBlockComment = false;
43
+ }
44
+ let blockStart = working.indexOf("/*");
45
+ while (blockStart !== -1) {
46
+ const blockEnd = working.indexOf("*/", blockStart + 2);
47
+ if (blockEnd === -1) {
48
+ working = working.slice(0, blockStart);
49
+ state.inBlockComment = true;
50
+ break;
51
+ }
52
+ working = `${working.slice(0, blockStart)} ${working.slice(blockEnd + 2)}`;
53
+ blockStart = working.indexOf("/*", blockStart);
54
+ }
55
+ const lineComment = working.indexOf("--");
56
+ if (lineComment !== -1) {
57
+ working = working.slice(0, lineComment);
58
+ }
59
+ return working.trim();
60
+ };
61
+ const collectFeatureMatches = async (records) => {
62
+ const matches = {
63
+ data_exports: [],
64
+ rights_policies: [],
65
+ admin_audit: [],
66
+ event_outbox: [],
67
+ };
68
+ for (const record of records) {
69
+ try {
70
+ const content = await fs.readFile(record.path, "utf8");
71
+ const lines = content.split(/\\r?\\n/);
72
+ let inFence = false;
73
+ lines.forEach((line, index) => {
74
+ const trimmed = line.trim();
75
+ if (isFenceLine(trimmed)) {
76
+ inFence = !inFence;
77
+ return;
78
+ }
79
+ if (inFence)
80
+ return;
81
+ const normalized = normalizeDocLine(line);
82
+ if (!normalized)
83
+ return;
84
+ for (const feature of FEATURE_DEFINITIONS) {
85
+ if (feature.matchers.some((matcher) => normalized.includes(matcher))) {
86
+ matches[feature.key].push({
87
+ record,
88
+ line: index + 1,
89
+ excerpt: trimmed.slice(0, 140),
90
+ });
91
+ }
92
+ }
93
+ });
94
+ }
95
+ catch {
96
+ // ignore missing doc reads; handled by gate notes
97
+ }
98
+ }
99
+ return matches;
100
+ };
101
+ const normalizeTableName = (value) => value.replace(/[`\"\\[]|\\]$/g, "").toLowerCase();
102
+ const stripSqlCommentsFromRaw = (raw) => raw.replace(/--.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, " ");
103
+ const collectTableNamesFromRaw = (raw) => {
104
+ const tables = new Set();
105
+ const sanitized = stripSqlCommentsFromRaw(raw);
106
+ const pattern = /\bcreate\s+table\s+(?:if\s+not\s+exists\s+)?([`"\[]?[A-Za-z0-9_]+[`"\]]?)/gi;
107
+ let match;
108
+ while ((match = pattern.exec(sanitized)) !== null) {
109
+ if (match[1])
110
+ tables.add(normalizeTableName(match[1]));
111
+ }
112
+ return tables;
113
+ };
114
+ const collectBadRightsPolicyFk = (lines) => {
115
+ const results = [];
116
+ const state = { inBlockComment: false };
117
+ lines.forEach((line, index) => {
118
+ const code = stripSqlComments(line, state);
119
+ if (!code)
120
+ return;
121
+ if (/\\brights_policies_id\\b/i.test(code)) {
122
+ results.push({ line: index + 1, excerpt: code.trim().slice(0, 140) });
123
+ }
124
+ });
125
+ return results;
126
+ };
127
+ const collectBadRightsPolicyFkFromRaw = (raw) => {
128
+ const results = [];
129
+ const pattern = /\brights_policies_id\b/gi;
130
+ let match;
131
+ while ((match = pattern.exec(raw)) !== null) {
132
+ const prefix = raw.slice(0, match.index);
133
+ const line = prefix.split(/\r?\n/).length;
134
+ const lineText = raw.split(/\r?\n/)[line - 1] ?? raw.slice(match.index);
135
+ results.push({ line, excerpt: lineText.trim().slice(0, 140) });
136
+ }
137
+ return results;
138
+ };
139
+ const formatEvidence = (matches) => {
140
+ if (matches.length === 0)
141
+ return undefined;
142
+ const preview = matches
143
+ .slice(0, 2)
144
+ .map((match) => `${path.basename(match.record.path)}:${match.line}`)
145
+ .join(", ");
146
+ const suffix = matches.length > 2 ? ` (+${matches.length - 2} more)` : "";
147
+ return `${preview}${suffix}`;
148
+ };
149
+ const buildIssue = (input) => ({
150
+ id: input.id,
151
+ gateId: "gate-sql-required-tables",
152
+ severity: "high",
153
+ category: "sql",
154
+ artifact: "sql",
155
+ message: input.message,
156
+ remediation: input.remediation,
157
+ location: {
158
+ kind: "line_range",
159
+ path: input.record.path,
160
+ lineStart: input.line ?? 1,
161
+ lineEnd: input.line ?? 1,
162
+ excerpt: input.message,
163
+ },
164
+ metadata: input.metadata,
165
+ });
166
+ export const runSqlRequiredTablesGate = async (input) => {
167
+ const sql = input.artifacts.sql;
168
+ if (!sql) {
169
+ return {
170
+ gateId: "gate-sql-required-tables",
171
+ gateName: "SQL Required Tables",
172
+ status: "skipped",
173
+ issues: [],
174
+ notes: ["No SQL artifact available for required table validation."],
175
+ };
176
+ }
177
+ const docRecords = [input.artifacts.sds, input.artifacts.pdr].filter((record) => Boolean(record));
178
+ if (docRecords.length === 0) {
179
+ return {
180
+ gateId: "gate-sql-required-tables",
181
+ gateName: "SQL Required Tables",
182
+ status: "skipped",
183
+ issues: [],
184
+ notes: ["No SDS/PDR artifacts available for SQL requirement detection."],
185
+ };
186
+ }
187
+ const notes = [];
188
+ const issues = [];
189
+ const featureMatches = await collectFeatureMatches(docRecords);
190
+ const activeFeatures = FEATURE_DEFINITIONS.filter((feature) => featureMatches[feature.key].length > 0);
191
+ if (activeFeatures.length === 0) {
192
+ return {
193
+ gateId: "gate-sql-required-tables",
194
+ gateName: "SQL Required Tables",
195
+ status: "pass",
196
+ issues: [],
197
+ notes: ["No feature-driven SQL requirements detected in docs."],
198
+ };
199
+ }
200
+ let raw;
201
+ try {
202
+ raw = await fs.readFile(sql.path, "utf8");
203
+ }
204
+ catch (error) {
205
+ return {
206
+ gateId: "gate-sql-required-tables",
207
+ gateName: "SQL Required Tables",
208
+ status: "pass",
209
+ issues: [],
210
+ notes: [`Unable to read SQL schema ${sql.path}: ${error.message ?? String(error)}`],
211
+ };
212
+ }
213
+ const lines = raw.split(/\\r?\\n/);
214
+ const tables = collectTableNamesFromRaw(raw);
215
+ const hasOutbox = Array.from(tables).some((name) => name.includes("outbox"));
216
+ const hasAdminAudit = tables.has("admin_audit_log") || tables.has("admin_audit_logs");
217
+ for (const feature of activeFeatures) {
218
+ const evidence = formatEvidence(featureMatches[feature.key]);
219
+ for (const table of feature.requiredTables) {
220
+ if (feature.key === "event_outbox") {
221
+ if (hasOutbox)
222
+ continue;
223
+ }
224
+ else if (feature.key === "admin_audit") {
225
+ if (hasAdminAudit)
226
+ continue;
227
+ }
228
+ else if (tables.has(table)) {
229
+ continue;
230
+ }
231
+ const message = evidence
232
+ ? `SQL schema is missing required table \"${table}\" for ${feature.label} (referenced at ${evidence}).`
233
+ : `SQL schema is missing required table \"${table}\" for ${feature.label}.`;
234
+ issues.push(buildIssue({
235
+ id: `gate-sql-required-tables-${feature.key}-${table}`,
236
+ message,
237
+ remediation: `Add the ${table} table to the SQL schema.`,
238
+ record: sql,
239
+ metadata: { issueType: "missing_table", feature: feature.key, table, evidence },
240
+ }));
241
+ }
242
+ }
243
+ const shouldCheckRightsFk = featureMatches.rights_policies.length > 0 || tables.has("rights_policies");
244
+ if (shouldCheckRightsFk) {
245
+ const badFks = collectBadRightsPolicyFk(lines);
246
+ const fkHits = badFks.length > 0 ? badFks : collectBadRightsPolicyFkFromRaw(raw);
247
+ for (const bad of fkHits) {
248
+ issues.push(buildIssue({
249
+ id: `gate-sql-required-tables-rights-policy-fk-${bad.line}`,
250
+ message: "SQL schema uses \"rights_policies_id\"; use \"rights_policy_id\" for FK columns.",
251
+ remediation: "Rename FK columns to rights_policy_id and update references.",
252
+ record: sql,
253
+ line: bad.line,
254
+ metadata: { issueType: "fk_naming", expected: "rights_policy_id", found: "rights_policies_id" },
255
+ }));
256
+ }
257
+ }
258
+ if (issues.length === 0) {
259
+ const features = activeFeatures.map((feature) => feature.label).join(", ");
260
+ notes.push(`SQL requirement checks passed for: ${features}.`);
261
+ }
262
+ return {
263
+ gateId: "gate-sql-required-tables",
264
+ gateName: "SQL Required Tables",
265
+ status: issues.length > 0 ? "fail" : "pass",
266
+ issues,
267
+ notes: notes.length > 0 ? notes : undefined,
268
+ metadata: {
269
+ featureCount: activeFeatures.length,
270
+ tableCount: tables.size,
271
+ },
272
+ };
273
+ };
@@ -0,0 +1,7 @@
1
+ import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
2
+ import { ReviewGateResult } from "../ReviewTypes.js";
3
+ export interface SqlSyntaxGateInput {
4
+ artifacts: DocgenArtifactInventory;
5
+ }
6
+ export declare const runSqlSyntaxGate: (input: SqlSyntaxGateInput) => Promise<ReviewGateResult>;
7
+ //# sourceMappingURL=SqlSyntaxGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlSyntaxGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SqlSyntaxGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAA+B,MAAM,mBAAmB,CAAC;AAElF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAkMD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,kBAAkB,KACxB,OAAO,CAAC,gBAAgB,CAgC1B,CAAC"}
@@ -0,0 +1,203 @@
1
+ import { promises as fs } from "node:fs";
2
+ const STATEMENT_START = /^(create|alter|drop|insert|update|delete|select|with|pragma|begin|commit|rollback|end|vacuum|analyze|attach|detach)\b/i;
3
+ const CLAUSE_START = /^(from|where|join|left|right|inner|outer|on|group|order|limit|offset|union|values|set|returning)\b/i;
4
+ const CONTINUATION_START = /^(,|\)|constraint\b|primary\b|foreign\b|unique\b|check\b|references\b|index\b|key\b|generated\b|as\b|collate\b|not\b|null\b)/i;
5
+ const COLUMN_DEF = /^(?:`[^`]+`|"[^"]+"|\[[^\]]+]|[A-Za-z_][\w$]*)(?:\s+[A-Za-z_][\w$]*)(?:\s*\([^)]*\))?/i;
6
+ const TYPE_KEYWORDS = /\b(bigint|int|integer|smallint|tinyint|serial|bigserial|uuid|text|varchar|char|character|boolean|bool|date|timestamp|timestamptz|datetime|time|json|jsonb|blob|real|double|float|numeric|decimal|money|bytea)\b/i;
7
+ const CONSTRAINT_KEYWORDS = /\b(primary|foreign|references|unique|check|default|collate|generated|identity)\b/i;
8
+ const NULL_KEYWORDS = /\bnot\s+null\b|\bnull\b/i;
9
+ const ISSUE_SEVERITY = {
10
+ empty: "high",
11
+ prose: "medium",
12
+ syntax: "high",
13
+ unterminated: "high",
14
+ };
15
+ const stripComments = (line, state) => {
16
+ let working = line;
17
+ if (state.inBlockComment) {
18
+ const end = working.indexOf("*/");
19
+ if (end === -1)
20
+ return "";
21
+ working = working.slice(end + 2);
22
+ state.inBlockComment = false;
23
+ }
24
+ let blockStart = working.indexOf("/*");
25
+ while (blockStart !== -1) {
26
+ const blockEnd = working.indexOf("*/", blockStart + 2);
27
+ if (blockEnd === -1) {
28
+ working = working.slice(0, blockStart);
29
+ state.inBlockComment = true;
30
+ break;
31
+ }
32
+ working = `${working.slice(0, blockStart)} ${working.slice(blockEnd + 2)}`;
33
+ blockStart = working.indexOf("/*", blockStart);
34
+ }
35
+ const lineComment = working.indexOf("--");
36
+ if (lineComment !== -1) {
37
+ working = working.slice(0, lineComment);
38
+ }
39
+ return working.trim();
40
+ };
41
+ const countParens = (line) => {
42
+ const stripped = line
43
+ .replace(/'[^']*'/g, "")
44
+ .replace(/"[^"]*"/g, "")
45
+ .replace(/\[[^\]]*]/g, "");
46
+ return {
47
+ open: (stripped.match(/\(/g) ?? []).length,
48
+ close: (stripped.match(/\)/g) ?? []).length,
49
+ };
50
+ };
51
+ const isSqlLine = (line, inStatement) => {
52
+ const trimmed = line.trim();
53
+ if (!trimmed)
54
+ return true;
55
+ if (STATEMENT_START.test(trimmed))
56
+ return true;
57
+ if (!inStatement)
58
+ return false;
59
+ if (CLAUSE_START.test(trimmed))
60
+ return true;
61
+ if (CONTINUATION_START.test(trimmed))
62
+ return true;
63
+ if (trimmed === ");" || trimmed === ")" || trimmed === "," || trimmed === ";")
64
+ return true;
65
+ const normalized = trimmed.replace(/[;,)]\s*$/, "").trim();
66
+ if (COLUMN_DEF.test(normalized)) {
67
+ return TYPE_KEYWORDS.test(normalized) || CONSTRAINT_KEYWORDS.test(normalized) || NULL_KEYWORDS.test(normalized);
68
+ }
69
+ return false;
70
+ };
71
+ const validateSqlContent = (raw) => {
72
+ const errors = [];
73
+ if (!raw || !raw.trim()) {
74
+ return [{ line: 1, type: "empty", message: "SQL schema is empty." }];
75
+ }
76
+ const lines = raw.split(/\r?\n/);
77
+ const state = { inBlockComment: false, inStatement: false, statementStart: 0, parenDepth: 0 };
78
+ for (let index = 0; index < lines.length; index += 1) {
79
+ const lineNumber = index + 1;
80
+ const rawLine = lines[index] ?? "";
81
+ const code = stripComments(rawLine, state);
82
+ if (!code)
83
+ continue;
84
+ const trimmed = code.trim();
85
+ const isStart = STATEMENT_START.test(trimmed);
86
+ if (!state.inStatement && !isStart) {
87
+ errors.push({
88
+ line: lineNumber,
89
+ type: "prose",
90
+ message: "Non-SQL content detected.",
91
+ excerpt: trimmed.slice(0, 140),
92
+ });
93
+ continue;
94
+ }
95
+ if (state.inStatement && !isSqlLine(trimmed, true)) {
96
+ errors.push({
97
+ line: lineNumber,
98
+ type: "prose",
99
+ message: "Non-SQL content detected inside a statement.",
100
+ excerpt: trimmed.slice(0, 140),
101
+ });
102
+ }
103
+ if (!state.inStatement && isStart) {
104
+ state.inStatement = true;
105
+ state.statementStart = lineNumber;
106
+ }
107
+ const parenCount = countParens(code);
108
+ state.parenDepth += parenCount.open - parenCount.close;
109
+ if (state.parenDepth < 0) {
110
+ errors.push({
111
+ line: lineNumber,
112
+ type: "syntax",
113
+ message: "Unexpected closing parenthesis in SQL statement.",
114
+ excerpt: trimmed.slice(0, 140),
115
+ });
116
+ state.parenDepth = 0;
117
+ }
118
+ if (code.includes(";") && state.parenDepth > 0) {
119
+ errors.push({
120
+ line: lineNumber,
121
+ type: "syntax",
122
+ message: "Statement terminates before closing all parentheses.",
123
+ excerpt: trimmed.slice(0, 140),
124
+ });
125
+ }
126
+ if (code.includes(";") && state.parenDepth <= 0) {
127
+ state.inStatement = false;
128
+ state.statementStart = 0;
129
+ state.parenDepth = 0;
130
+ }
131
+ }
132
+ if (state.inStatement) {
133
+ errors.push({
134
+ line: state.statementStart || lines.length,
135
+ type: "unterminated",
136
+ message: `SQL statement starting at line ${state.statementStart} is missing a terminating semicolon.`,
137
+ });
138
+ }
139
+ if (state.parenDepth > 0) {
140
+ errors.push({
141
+ line: lines.length,
142
+ type: "syntax",
143
+ message: "SQL statement has unbalanced parentheses.",
144
+ });
145
+ }
146
+ return errors;
147
+ };
148
+ const buildIssue = (issue, record) => {
149
+ const remediation = issue.type === "prose"
150
+ ? "Remove prose and keep only SQL statements or comments."
151
+ : "Fix the SQL syntax and ensure statements terminate with semicolons.";
152
+ return {
153
+ id: `gate-sql-syntax-prose-${issue.type}-${issue.line}`,
154
+ gateId: "gate-sql-syntax-prose",
155
+ severity: ISSUE_SEVERITY[issue.type],
156
+ category: "sql",
157
+ artifact: record.kind,
158
+ message: issue.message,
159
+ remediation,
160
+ location: {
161
+ kind: "line_range",
162
+ path: record.path,
163
+ lineStart: issue.line,
164
+ lineEnd: issue.line,
165
+ excerpt: issue.excerpt ?? issue.message,
166
+ },
167
+ metadata: {
168
+ issueType: issue.type,
169
+ },
170
+ };
171
+ };
172
+ export const runSqlSyntaxGate = async (input) => {
173
+ const record = input.artifacts.sql;
174
+ if (!record) {
175
+ return {
176
+ gateId: "gate-sql-syntax-prose",
177
+ gateName: "SQL Syntax & Prose",
178
+ status: "skipped",
179
+ issues: [],
180
+ notes: ["No SQL artifacts available for syntax validation."],
181
+ };
182
+ }
183
+ let raw;
184
+ try {
185
+ raw = await fs.readFile(record.path, "utf8");
186
+ }
187
+ catch (error) {
188
+ return {
189
+ gateId: "gate-sql-syntax-prose",
190
+ gateName: "SQL Syntax & Prose",
191
+ status: "pass",
192
+ issues: [],
193
+ notes: [`Unable to read SQL schema ${record.path}: ${error.message ?? String(error)}`],
194
+ };
195
+ }
196
+ const issues = validateSqlContent(raw).map((issue) => buildIssue(issue, record));
197
+ return {
198
+ gateId: "gate-sql-syntax-prose",
199
+ gateName: "SQL Syntax & Prose",
200
+ status: issues.length > 0 ? "fail" : "pass",
201
+ issues,
202
+ };
203
+ };
@@ -0,0 +1,9 @@
1
+ import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
2
+ import { GlossaryData } from "../Glossary.js";
3
+ import { ReviewGateResult } from "../ReviewTypes.js";
4
+ export interface TerminologyNormalizationGateInput {
5
+ artifacts: DocgenArtifactInventory;
6
+ glossary?: GlossaryData;
7
+ }
8
+ export declare const runTerminologyNormalizationGate: (input: TerminologyNormalizationGateInput) => Promise<ReviewGateResult>;
9
+ //# sourceMappingURL=TerminologyNormalizationGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerminologyNormalizationGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/TerminologyNormalizationGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAA+B,MAAM,mBAAmB,CAAC;AAElF,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,uBAAuB,CAAC;IACnC,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AA2MD,eAAO,MAAM,+BAA+B,GAC1C,OAAO,iCAAiC,KACvC,OAAO,CAAC,gBAAgB,CA0E1B,CAAC"}