@mcoda/core 0.1.9 → 0.1.12

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 (204) hide show
  1. package/README.md +2 -2
  2. package/dist/api/AgentsApi.d.ts +1 -0
  3. package/dist/api/AgentsApi.d.ts.map +1 -1
  4. package/dist/api/AgentsApi.js +136 -11
  5. package/dist/api/QaTasksApi.d.ts.map +1 -1
  6. package/dist/api/QaTasksApi.js +4 -0
  7. package/dist/prompts/PdrPrompts.d.ts.map +1 -1
  8. package/dist/prompts/PdrPrompts.js +6 -0
  9. package/dist/prompts/SdsPrompts.d.ts.map +1 -1
  10. package/dist/prompts/SdsPrompts.js +7 -0
  11. package/dist/services/agents/AgentRatingService.d.ts +19 -0
  12. package/dist/services/agents/AgentRatingService.d.ts.map +1 -1
  13. package/dist/services/agents/AgentRatingService.js +66 -2
  14. package/dist/services/agents/GatewayAgentService.d.ts +8 -0
  15. package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
  16. package/dist/services/agents/GatewayAgentService.js +462 -65
  17. package/dist/services/agents/GatewayHandoff.d.ts +5 -1
  18. package/dist/services/agents/GatewayHandoff.d.ts.map +1 -1
  19. package/dist/services/agents/GatewayHandoff.js +65 -32
  20. package/dist/services/agents/RoutingService.d.ts +1 -0
  21. package/dist/services/agents/RoutingService.d.ts.map +1 -1
  22. package/dist/services/agents/RoutingService.js +4 -4
  23. package/dist/services/backlog/BacklogService.d.ts +23 -0
  24. package/dist/services/backlog/BacklogService.d.ts.map +1 -1
  25. package/dist/services/backlog/BacklogService.js +62 -7
  26. package/dist/services/backlog/TaskOrderingHeuristics.d.ts +12 -0
  27. package/dist/services/backlog/TaskOrderingHeuristics.d.ts.map +1 -0
  28. package/dist/services/backlog/TaskOrderingHeuristics.js +56 -0
  29. package/dist/services/backlog/TaskOrderingService.d.ts +16 -4
  30. package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
  31. package/dist/services/backlog/TaskOrderingService.js +529 -73
  32. package/dist/services/docs/DocInventory.d.ts +11 -0
  33. package/dist/services/docs/DocInventory.d.ts.map +1 -0
  34. package/dist/services/docs/DocInventory.js +230 -0
  35. package/dist/services/docs/DocgenRunContext.d.ts +59 -0
  36. package/dist/services/docs/DocgenRunContext.d.ts.map +1 -0
  37. package/dist/services/docs/DocgenRunContext.js +4 -0
  38. package/dist/services/docs/DocsService.d.ts +59 -2
  39. package/dist/services/docs/DocsService.d.ts.map +1 -1
  40. package/dist/services/docs/DocsService.js +1701 -48
  41. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts +23 -0
  42. package/dist/services/docs/alignment/DocAlignmentGraph.d.ts.map +1 -0
  43. package/dist/services/docs/alignment/DocAlignmentGraph.js +78 -0
  44. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts +19 -0
  45. package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts.map +1 -0
  46. package/dist/services/docs/alignment/DocAlignmentPatcher.js +222 -0
  47. package/dist/services/docs/patch/DocPatchEngine.d.ts +57 -0
  48. package/dist/services/docs/patch/DocPatchEngine.d.ts.map +1 -0
  49. package/dist/services/docs/patch/DocPatchEngine.js +331 -0
  50. package/dist/services/docs/review/Glossary.d.ts +16 -0
  51. package/dist/services/docs/review/Glossary.d.ts.map +1 -0
  52. package/dist/services/docs/review/Glossary.js +47 -0
  53. package/dist/services/docs/review/ReviewReportRenderer.d.ts +3 -0
  54. package/dist/services/docs/review/ReviewReportRenderer.d.ts.map +1 -0
  55. package/dist/services/docs/review/ReviewReportRenderer.js +133 -0
  56. package/dist/services/docs/review/ReviewReportSchema.d.ts +39 -0
  57. package/dist/services/docs/review/ReviewReportSchema.d.ts.map +1 -0
  58. package/dist/services/docs/review/ReviewReportSchema.js +47 -0
  59. package/dist/services/docs/review/ReviewTypes.d.ts +76 -0
  60. package/dist/services/docs/review/ReviewTypes.d.ts.map +1 -0
  61. package/dist/services/docs/review/ReviewTypes.js +94 -0
  62. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts +7 -0
  63. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts.map +1 -0
  64. package/dist/services/docs/review/gates/AdminOpenApiSpecGate.js +93 -0
  65. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts +7 -0
  66. package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts.map +1 -0
  67. package/dist/services/docs/review/gates/ApiPathConsistencyGate.js +308 -0
  68. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts +8 -0
  69. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts.map +1 -0
  70. package/dist/services/docs/review/gates/BuildReadyCompletenessGate.js +278 -0
  71. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts +8 -0
  72. package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts.map +1 -0
  73. package/dist/services/docs/review/gates/DeploymentBlueprintGate.js +487 -0
  74. package/dist/services/docs/review/gates/NoMaybesGate.d.ts +8 -0
  75. package/dist/services/docs/review/gates/NoMaybesGate.d.ts.map +1 -0
  76. package/dist/services/docs/review/gates/NoMaybesGate.js +145 -0
  77. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts +7 -0
  78. package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts.map +1 -0
  79. package/dist/services/docs/review/gates/OpenApiCoverageGate.js +266 -0
  80. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts +7 -0
  81. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts.map +1 -0
  82. package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.js +59 -0
  83. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts +7 -0
  84. package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts.map +1 -0
  85. package/dist/services/docs/review/gates/OpenQuestionsGate.js +200 -0
  86. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts +7 -0
  87. package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts.map +1 -0
  88. package/dist/services/docs/review/gates/PdrInterfacesGate.js +159 -0
  89. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts +8 -0
  90. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts.map +1 -0
  91. package/dist/services/docs/review/gates/PdrOpenQuestionsGate.js +129 -0
  92. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts +7 -0
  93. package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts.map +1 -0
  94. package/dist/services/docs/review/gates/PdrOwnershipGate.js +169 -0
  95. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts +10 -0
  96. package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts.map +1 -0
  97. package/dist/services/docs/review/gates/PlaceholderArtifactGate.js +261 -0
  98. package/dist/services/docs/review/gates/RfpConsentGate.d.ts +6 -0
  99. package/dist/services/docs/review/gates/RfpConsentGate.d.ts.map +1 -0
  100. package/dist/services/docs/review/gates/RfpConsentGate.js +127 -0
  101. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts +7 -0
  102. package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts.map +1 -0
  103. package/dist/services/docs/review/gates/RfpDefinitionGate.js +173 -0
  104. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts +7 -0
  105. package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts.map +1 -0
  106. package/dist/services/docs/review/gates/SdsAdaptersGate.js +196 -0
  107. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts +7 -0
  108. package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts.map +1 -0
  109. package/dist/services/docs/review/gates/SdsDecisionsGate.js +89 -0
  110. package/dist/services/docs/review/gates/SdsOpsGate.d.ts +7 -0
  111. package/dist/services/docs/review/gates/SdsOpsGate.d.ts.map +1 -0
  112. package/dist/services/docs/review/gates/SdsOpsGate.js +162 -0
  113. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts +7 -0
  114. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts.map +1 -0
  115. package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.js +166 -0
  116. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts +7 -0
  117. package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts.map +1 -0
  118. package/dist/services/docs/review/gates/SqlRequiredTablesGate.js +273 -0
  119. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts +7 -0
  120. package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts.map +1 -0
  121. package/dist/services/docs/review/gates/SqlSyntaxGate.js +203 -0
  122. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts +9 -0
  123. package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts.map +1 -0
  124. package/dist/services/docs/review/gates/TerminologyNormalizationGate.js +217 -0
  125. package/dist/services/docs/review/glossary.json +47 -0
  126. package/dist/services/estimate/EstimateService.d.ts +2 -0
  127. package/dist/services/estimate/EstimateService.d.ts.map +1 -1
  128. package/dist/services/estimate/EstimateService.js +66 -18
  129. package/dist/services/estimate/VelocityService.d.ts +4 -0
  130. package/dist/services/estimate/VelocityService.d.ts.map +1 -1
  131. package/dist/services/estimate/VelocityService.js +179 -36
  132. package/dist/services/estimate/types.d.ts +1 -0
  133. package/dist/services/estimate/types.d.ts.map +1 -1
  134. package/dist/services/execution/GatewayTrioService.d.ts +71 -4
  135. package/dist/services/execution/GatewayTrioService.d.ts.map +1 -1
  136. package/dist/services/execution/GatewayTrioService.js +1695 -328
  137. package/dist/services/execution/QaApiRunner.d.ts +30 -0
  138. package/dist/services/execution/QaApiRunner.d.ts.map +1 -0
  139. package/dist/services/execution/QaApiRunner.js +881 -0
  140. package/dist/services/execution/QaFollowupService.d.ts +1 -0
  141. package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
  142. package/dist/services/execution/QaFollowupService.js +8 -2
  143. package/dist/services/execution/QaPlanValidator.d.ts +10 -0
  144. package/dist/services/execution/QaPlanValidator.d.ts.map +1 -0
  145. package/dist/services/execution/QaPlanValidator.js +128 -0
  146. package/dist/services/execution/QaProfileService.d.ts +21 -1
  147. package/dist/services/execution/QaProfileService.d.ts.map +1 -1
  148. package/dist/services/execution/QaProfileService.js +214 -29
  149. package/dist/services/execution/QaTasksService.d.ts +41 -1
  150. package/dist/services/execution/QaTasksService.d.ts.map +1 -1
  151. package/dist/services/execution/QaTasksService.js +2851 -500
  152. package/dist/services/execution/QaTestCommandBuilder.d.ts +51 -0
  153. package/dist/services/execution/QaTestCommandBuilder.d.ts.map +1 -0
  154. package/dist/services/execution/QaTestCommandBuilder.js +495 -0
  155. package/dist/services/execution/TaskSelectionService.d.ts +4 -2
  156. package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
  157. package/dist/services/execution/TaskSelectionService.js +144 -28
  158. package/dist/services/execution/TaskStateService.d.ts +19 -6
  159. package/dist/services/execution/TaskStateService.d.ts.map +1 -1
  160. package/dist/services/execution/TaskStateService.js +128 -13
  161. package/dist/services/execution/WorkOnTasksService.d.ts +19 -2
  162. package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
  163. package/dist/services/execution/WorkOnTasksService.js +3913 -1225
  164. package/dist/services/jobs/JobInsightsService.d.ts +4 -0
  165. package/dist/services/jobs/JobInsightsService.d.ts.map +1 -1
  166. package/dist/services/jobs/JobInsightsService.js +51 -5
  167. package/dist/services/jobs/JobResumeService.d.ts.map +1 -1
  168. package/dist/services/jobs/JobResumeService.js +23 -10
  169. package/dist/services/jobs/JobService.d.ts +56 -4
  170. package/dist/services/jobs/JobService.d.ts.map +1 -1
  171. package/dist/services/jobs/JobService.js +232 -1
  172. package/dist/services/openapi/OpenApiService.d.ts +41 -0
  173. package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
  174. package/dist/services/openapi/OpenApiService.js +889 -98
  175. package/dist/services/planning/CreateTasksService.d.ts +15 -0
  176. package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
  177. package/dist/services/planning/CreateTasksService.js +311 -6
  178. package/dist/services/planning/RefineTasksService.d.ts +4 -0
  179. package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
  180. package/dist/services/planning/RefineTasksService.js +225 -24
  181. package/dist/services/review/CodeReviewService.d.ts +4 -0
  182. package/dist/services/review/CodeReviewService.d.ts.map +1 -1
  183. package/dist/services/review/CodeReviewService.js +778 -232
  184. package/dist/services/review/ReviewNormalizer.d.ts +9 -0
  185. package/dist/services/review/ReviewNormalizer.d.ts.map +1 -0
  186. package/dist/services/review/ReviewNormalizer.js +147 -0
  187. package/dist/services/shared/AuthErrors.d.ts +3 -0
  188. package/dist/services/shared/AuthErrors.d.ts.map +1 -0
  189. package/dist/services/shared/AuthErrors.js +17 -0
  190. package/dist/services/shared/DocdexGuidance.d.ts +7 -0
  191. package/dist/services/shared/DocdexGuidance.d.ts.map +1 -0
  192. package/dist/services/shared/DocdexGuidance.js +12 -0
  193. package/dist/services/shared/ProjectGuidance.d.ts +12 -1
  194. package/dist/services/shared/ProjectGuidance.d.ts.map +1 -1
  195. package/dist/services/shared/ProjectGuidance.js +64 -7
  196. package/dist/services/system/ToolDenylist.d.ts +13 -0
  197. package/dist/services/system/ToolDenylist.d.ts.map +1 -0
  198. package/dist/services/system/ToolDenylist.js +85 -0
  199. package/dist/services/telemetry/TelemetryService.d.ts.map +1 -1
  200. package/dist/services/telemetry/TelemetryService.js +39 -7
  201. package/dist/workspace/WorkspaceManager.d.ts +22 -0
  202. package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
  203. package/dist/workspace/WorkspaceManager.js +203 -32
  204. package/package.json +6 -5
@@ -0,0 +1,261 @@
1
+ import { promises as fs } from "node:fs";
2
+ const DEFAULT_ALLOWLIST = ["for example", "example only", "sample data", "sample payload"];
3
+ const SEVERITY_RANK = {
4
+ blocker: 4,
5
+ high: 3,
6
+ medium: 2,
7
+ low: 1,
8
+ info: 0,
9
+ };
10
+ const DEFAULT_PATTERNS = [
11
+ {
12
+ id: "placeholder.tbd",
13
+ label: "TBD placeholder",
14
+ type: "placeholder",
15
+ pattern: /\bTBD\b/i,
16
+ severity: "blocker",
17
+ },
18
+ {
19
+ id: "placeholder.tbc",
20
+ label: "TBC placeholder",
21
+ type: "placeholder",
22
+ pattern: /\bTBC\b/i,
23
+ severity: "blocker",
24
+ },
25
+ {
26
+ id: "placeholder.fixme",
27
+ label: "FIXME placeholder",
28
+ type: "placeholder",
29
+ pattern: /\bFIXME\b/i,
30
+ severity: "high",
31
+ },
32
+ {
33
+ id: "placeholder.todo",
34
+ label: "TODO placeholder",
35
+ type: "placeholder",
36
+ pattern: /\bTODO\b/,
37
+ severity: "high",
38
+ },
39
+ {
40
+ id: "placeholder.lorem",
41
+ label: "Lorem ipsum placeholder",
42
+ type: "placeholder",
43
+ pattern: /\blorem ipsum\b/i,
44
+ severity: "high",
45
+ },
46
+ {
47
+ id: "placeholder.placeholder",
48
+ label: "Placeholder text",
49
+ type: "placeholder",
50
+ pattern: /\bplaceholder\b/i,
51
+ severity: "medium",
52
+ },
53
+ {
54
+ id: "placeholder.tobe",
55
+ label: "To be decided placeholder",
56
+ type: "placeholder",
57
+ pattern: /\bto be (decided|determined|filled)\b/i,
58
+ severity: "high",
59
+ },
60
+ {
61
+ id: "template.restaurant",
62
+ label: "Restaurant template artifact",
63
+ type: "template_artifact",
64
+ pattern: /\brestaurant\b/i,
65
+ severity: "high",
66
+ },
67
+ {
68
+ id: "template.menu_items",
69
+ label: "Menu items template artifact",
70
+ type: "template_artifact",
71
+ pattern: /\bmenu items?\b/i,
72
+ severity: "medium",
73
+ },
74
+ {
75
+ id: "template.reservation",
76
+ label: "Reservation template artifact",
77
+ type: "template_artifact",
78
+ pattern: /\btable reservation(s)?\b/i,
79
+ severity: "medium",
80
+ },
81
+ {
82
+ id: "template.voting",
83
+ label: "Voting template artifact",
84
+ type: "template_artifact",
85
+ pattern: /\b(voting|election|ballot)\b/i,
86
+ severity: "high",
87
+ },
88
+ {
89
+ id: "template.food_delivery",
90
+ label: "Food delivery template artifact",
91
+ type: "template_artifact",
92
+ pattern: /\bfood delivery\b/i,
93
+ severity: "medium",
94
+ },
95
+ ];
96
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
97
+ const buildAllowlist = (allowlist) => {
98
+ const combined = [...DEFAULT_ALLOWLIST, ...(allowlist ?? [])];
99
+ return combined.map((entry) => new RegExp(escapeRegExp(entry), "i"));
100
+ };
101
+ const buildCustomPatterns = (denylist) => {
102
+ if (!denylist || denylist.length === 0)
103
+ return [];
104
+ return denylist.map((entry, index) => ({
105
+ id: `custom.placeholder.${index + 1}`,
106
+ label: `Custom placeholder: ${entry}`,
107
+ type: "placeholder",
108
+ pattern: new RegExp(escapeRegExp(entry), "i"),
109
+ severity: "high",
110
+ }));
111
+ };
112
+ const collectRecords = (artifacts) => {
113
+ const records = [];
114
+ if (artifacts.pdr)
115
+ records.push(artifacts.pdr);
116
+ if (artifacts.sds)
117
+ records.push(artifacts.sds);
118
+ if (artifacts.sql)
119
+ records.push(artifacts.sql);
120
+ if (artifacts.openapi?.length)
121
+ records.push(...artifacts.openapi);
122
+ if (artifacts.blueprints?.length)
123
+ records.push(...artifacts.blueprints);
124
+ return records;
125
+ };
126
+ const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
127
+ const isExampleHeading = (heading) => /example|sample/i.test(heading);
128
+ const selectHighestSeverity = (candidates) => {
129
+ let chosen = candidates[0];
130
+ for (const candidate of candidates.slice(1)) {
131
+ if (SEVERITY_RANK[candidate.severity] > SEVERITY_RANK[chosen.severity]) {
132
+ chosen = candidate;
133
+ }
134
+ }
135
+ return chosen;
136
+ };
137
+ const buildIssue = (input) => {
138
+ const match = input.line.match(input.pattern.pattern);
139
+ const excerpt = input.line.trim();
140
+ const message = `${input.pattern.label} detected${match ? ` (${match[0]})` : ""}.`;
141
+ const remediation = input.pattern.type === "placeholder"
142
+ ? "Replace placeholders with concrete content."
143
+ : "Replace unrelated template artifacts with project-specific content.";
144
+ return {
145
+ id: `gate-placeholder-artifacts-${input.record.kind}-${input.pattern.id}-${input.lineNumber}`,
146
+ gateId: "gate-placeholder-artifacts",
147
+ severity: input.pattern.severity,
148
+ category: "content",
149
+ artifact: input.record.kind,
150
+ message,
151
+ remediation,
152
+ location: {
153
+ kind: "line_range",
154
+ path: input.record.path,
155
+ lineStart: input.lineNumber,
156
+ lineEnd: input.lineNumber,
157
+ excerpt,
158
+ },
159
+ metadata: {
160
+ placeholderType: input.pattern.type,
161
+ patternId: input.pattern.id,
162
+ patternLabel: input.pattern.label,
163
+ matchedText: match ? match[0] : undefined,
164
+ heading: input.heading,
165
+ },
166
+ };
167
+ };
168
+ export const runPlaceholderArtifactGate = async (input) => {
169
+ const allowlist = buildAllowlist(input.allowlist);
170
+ const patterns = [...DEFAULT_PATTERNS, ...buildCustomPatterns(input.denylist)];
171
+ const records = collectRecords(input.artifacts);
172
+ const issues = [];
173
+ const notes = [];
174
+ if (records.length === 0) {
175
+ return {
176
+ gateId: "gate-placeholder-artifacts",
177
+ gateName: "Placeholder Artifacts",
178
+ status: "skipped",
179
+ issues,
180
+ notes: ["No artifacts available for placeholder scanning."],
181
+ };
182
+ }
183
+ for (const record of records) {
184
+ let content;
185
+ try {
186
+ content = await fs.readFile(record.path, "utf8");
187
+ }
188
+ catch (error) {
189
+ notes.push(`Placeholder scan skipped for ${record.path}: ${error.message}`);
190
+ continue;
191
+ }
192
+ const lines = content.split(/\r?\n/);
193
+ let inFence = false;
194
+ let allowSection = false;
195
+ let currentHeading;
196
+ for (let i = 0; i < lines.length; i += 1) {
197
+ const line = lines[i] ?? "";
198
+ const trimmed = line.trim();
199
+ if (!trimmed)
200
+ continue;
201
+ if (isFenceLine(trimmed)) {
202
+ inFence = !inFence;
203
+ continue;
204
+ }
205
+ const headingMatch = trimmed.match(/^#{1,6}\s+(.*)$/);
206
+ if (headingMatch) {
207
+ currentHeading = headingMatch[1]?.trim() || undefined;
208
+ allowSection = currentHeading ? isExampleHeading(currentHeading) : false;
209
+ }
210
+ if (inFence || allowSection)
211
+ continue;
212
+ if (allowlist.some((pattern) => pattern.test(line)))
213
+ continue;
214
+ const matches = [];
215
+ for (const pattern of patterns) {
216
+ if (!pattern.pattern.test(line))
217
+ continue;
218
+ matches.push(pattern);
219
+ }
220
+ if (matches.length === 0)
221
+ continue;
222
+ const grouped = new Map();
223
+ for (const match of matches) {
224
+ const existing = grouped.get(match.type);
225
+ if (existing) {
226
+ existing.push(match);
227
+ }
228
+ else {
229
+ grouped.set(match.type, [match]);
230
+ }
231
+ }
232
+ const typeOrder = ["placeholder", "template_artifact"];
233
+ for (const type of typeOrder) {
234
+ const candidates = grouped.get(type);
235
+ if (!candidates || candidates.length === 0)
236
+ continue;
237
+ const selected = selectHighestSeverity(candidates);
238
+ issues.push(buildIssue({
239
+ record,
240
+ pattern: selected,
241
+ line,
242
+ lineNumber: i + 1,
243
+ heading: currentHeading,
244
+ }));
245
+ }
246
+ }
247
+ }
248
+ const status = issues.length > 0 ? "fail" : "pass";
249
+ return {
250
+ gateId: "gate-placeholder-artifacts",
251
+ gateName: "Placeholder Artifacts",
252
+ status,
253
+ issues,
254
+ notes: notes.length > 0 ? notes : undefined,
255
+ metadata: {
256
+ scannedArtifacts: records.length,
257
+ patternCount: patterns.length,
258
+ allowlistCount: allowlist.length,
259
+ },
260
+ };
261
+ };
@@ -0,0 +1,6 @@
1
+ import { ReviewGateResult } from "../ReviewTypes.js";
2
+ export interface RfpConsentGateInput {
3
+ rfpPath?: string;
4
+ }
5
+ export declare const runRfpConsentGate: (input: RfpConsentGateInput) => Promise<ReviewGateResult>;
6
+ //# sourceMappingURL=RfpConsentGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RfpConsentGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/RfpConsentGate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAA+B,MAAM,mBAAmB,CAAC;AAElF,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoDD,eAAO,MAAM,iBAAiB,GAC5B,OAAO,mBAAmB,KACzB,OAAO,CAAC,gBAAgB,CAmG1B,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { loadGlossary } from "../Glossary.js";
3
+ const OVERBROAD_PATTERNS = [
4
+ /\bstore all interactions\b/i,
5
+ /\bcollect everything\b/i,
6
+ /\bretain everything\b/i,
7
+ /\bstore all data\b/i,
8
+ /\blog everything\b/i,
9
+ /\bkeep all records\b/i,
10
+ /\bfull data retention\b/i,
11
+ ];
12
+ const MINIMIZATION_HINTS = [
13
+ /\bdata minimization\b/i,
14
+ /\bminimi[sz]e data\b/i,
15
+ /\blimit retention\b/i,
16
+ /\bcollect only\b/i,
17
+ /\bminimum necessary\b/i,
18
+ ];
19
+ const ANON_HINTS = [/\banonymous\b/i, /\banon token\b/i, /\bno identifiers\b/i];
20
+ const IDENT_HINTS = [/\bidentified\b/i, /\buser id\b/i, /\baccount id\b/i, /\bnon-anonymous\b/i];
21
+ const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
22
+ const buildIssue = (input) => ({
23
+ id: input.id,
24
+ gateId: "gate-rfp-consent-contradictions",
25
+ severity: input.severity,
26
+ category: "compliance",
27
+ artifact: "pdr",
28
+ message: input.message,
29
+ remediation: input.remediation,
30
+ location: {
31
+ kind: "line_range",
32
+ path: input.path,
33
+ lineStart: input.line,
34
+ lineEnd: input.line,
35
+ excerpt: input.excerpt,
36
+ },
37
+ metadata: input.metadata,
38
+ });
39
+ export const runRfpConsentGate = async (input) => {
40
+ if (!input.rfpPath) {
41
+ return {
42
+ gateId: "gate-rfp-consent-contradictions",
43
+ gateName: "RFP Consent & Minimization",
44
+ status: "skipped",
45
+ issues: [],
46
+ notes: ["No RFP path provided for consent/minimization validation."],
47
+ };
48
+ }
49
+ const issues = [];
50
+ const notes = [];
51
+ const glossary = loadGlossary();
52
+ const consentPhrase = glossary.canonicalPhrases?.consent_flow ?? "consent flow";
53
+ const anonymityPhrase = glossary.canonicalPhrases?.anonymity ?? "anonymous vs identified handling";
54
+ try {
55
+ const content = await fs.readFile(input.rfpPath, "utf8");
56
+ const lines = content.split(/\r?\n/);
57
+ let inFence = false;
58
+ let anonLine;
59
+ let identLine;
60
+ const minimizationDeclared = lines.some((line) => MINIMIZATION_HINTS.some((pattern) => pattern.test(line)));
61
+ for (let i = 0; i < lines.length; i += 1) {
62
+ const rawLine = lines[i] ?? "";
63
+ const trimmed = rawLine.trim();
64
+ if (!trimmed)
65
+ continue;
66
+ if (isFenceLine(trimmed)) {
67
+ inFence = !inFence;
68
+ continue;
69
+ }
70
+ if (inFence)
71
+ continue;
72
+ if (anonLine === undefined && ANON_HINTS.some((pattern) => pattern.test(trimmed))) {
73
+ anonLine = i + 1;
74
+ }
75
+ if (identLine === undefined && IDENT_HINTS.some((pattern) => pattern.test(trimmed))) {
76
+ identLine = i + 1;
77
+ }
78
+ const overbroadMatch = OVERBROAD_PATTERNS.find((pattern) => pattern.test(trimmed));
79
+ if (overbroadMatch) {
80
+ const severity = minimizationDeclared ? "high" : "medium";
81
+ issues.push(buildIssue({
82
+ id: `gate-rfp-consent-contradictions-overbroad-${i + 1}`,
83
+ message: "Over-broad data retention statement conflicts with minimization goals.",
84
+ remediation: `Align retention language with ${consentPhrase} and explicit minimization scope.`,
85
+ severity,
86
+ path: input.rfpPath,
87
+ line: i + 1,
88
+ excerpt: trimmed,
89
+ metadata: {
90
+ issueType: "overbroad_statement",
91
+ minimizationDeclared,
92
+ pattern: overbroadMatch.source,
93
+ },
94
+ }));
95
+ }
96
+ }
97
+ if (anonLine !== undefined && identLine !== undefined) {
98
+ const line = Math.min(anonLine, identLine);
99
+ issues.push(buildIssue({
100
+ id: "gate-rfp-consent-contradictions-anon-ident",
101
+ message: "RFP mentions both anonymous and identified handling without clarifying boundaries.",
102
+ remediation: `Clarify ${anonymityPhrase} and reconcile consent requirements with minimization constraints.`,
103
+ severity: "high",
104
+ path: input.rfpPath,
105
+ line,
106
+ excerpt: lines[line - 1] ?? "",
107
+ metadata: {
108
+ issueType: "anon_ident_contradiction",
109
+ anonymousLine: anonLine,
110
+ identifiedLine: identLine,
111
+ },
112
+ }));
113
+ }
114
+ }
115
+ catch (error) {
116
+ notes.push(`Unable to read RFP at ${input.rfpPath}: ${error.message ?? String(error)}`);
117
+ }
118
+ const status = issues.length === 0 ? "pass" : "fail";
119
+ return {
120
+ gateId: "gate-rfp-consent-contradictions",
121
+ gateName: "RFP Consent & Minimization",
122
+ status,
123
+ issues,
124
+ notes: notes.length ? notes : undefined,
125
+ metadata: { issueCount: issues.length },
126
+ };
127
+ };
@@ -0,0 +1,7 @@
1
+ import { ReviewGateResult } from "../ReviewTypes.js";
2
+ export interface RfpDefinitionGateInput {
3
+ rfpPath?: string;
4
+ allowlist?: string[];
5
+ }
6
+ export declare const runRfpDefinitionGate: (input: RfpDefinitionGateInput) => Promise<ReviewGateResult>;
7
+ //# sourceMappingURL=RfpDefinitionGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RfpDefinitionGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/RfpDefinitionGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAkFD,eAAO,MAAM,oBAAoB,GAC/B,OAAO,sBAAsB,KAC5B,OAAO,CAAC,gBAAgB,CA8G1B,CAAC"}
@@ -0,0 +1,173 @@
1
+ import { promises as fs } from "node:fs";
2
+ const DEFAULT_ALLOWLIST = [
3
+ "api",
4
+ "http",
5
+ "https",
6
+ "tls",
7
+ "oauth",
8
+ "sso",
9
+ "jwt",
10
+ "cli",
11
+ "ui",
12
+ "sdk",
13
+ "db",
14
+ "sql",
15
+ "rest",
16
+ "graphql",
17
+ ];
18
+ const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
19
+ const normalizeTerm = (term) => term
20
+ .replace(/[`*_]/g, "")
21
+ .replace(/\(.*\)/g, "")
22
+ .replace(/[^a-zA-Z0-9\s-]/g, " ")
23
+ .toLowerCase()
24
+ .trim();
25
+ const extractDefinitionTerm = (line) => {
26
+ const trimmed = line.trim();
27
+ const bullet = trimmed.replace(/^[-*+]\s+/, "");
28
+ const boldMatch = bullet.match(/\*\*([^*]+)\*\*/);
29
+ if (boldMatch)
30
+ return boldMatch[1]?.trim();
31
+ const backtickMatch = bullet.match(/`([^`]+)`/);
32
+ if (backtickMatch)
33
+ return backtickMatch[1]?.trim();
34
+ const colonMatch = bullet.match(/^([A-Za-z][A-Za-z0-9 _-]{1,40})\s*:/);
35
+ if (colonMatch)
36
+ return colonMatch[1]?.trim();
37
+ return undefined;
38
+ };
39
+ const extractReferencedTerms = (line) => {
40
+ const terms = [];
41
+ const boldMatches = line.matchAll(/\*\*([^*]+)\*\*/g);
42
+ for (const match of boldMatches) {
43
+ if (match[1])
44
+ terms.push(match[1]);
45
+ }
46
+ const codeMatches = line.matchAll(/`([^`]+)`/g);
47
+ for (const match of codeMatches) {
48
+ if (match[1])
49
+ terms.push(match[1]);
50
+ }
51
+ return terms;
52
+ };
53
+ const buildIssue = (input) => ({
54
+ id: input.id,
55
+ gateId: "gate-rfp-definition-coverage",
56
+ severity: "medium",
57
+ category: "compliance",
58
+ artifact: "pdr",
59
+ message: `Undefined term referenced in RFP: ${input.term}.`,
60
+ remediation: `Add a definition for \"${input.term}\" in the RFP Definitions section.`,
61
+ location: {
62
+ kind: "line_range",
63
+ path: input.path,
64
+ lineStart: input.line,
65
+ lineEnd: input.line,
66
+ excerpt: input.excerpt,
67
+ },
68
+ metadata: {
69
+ issueType: input.issueType,
70
+ term: input.term,
71
+ },
72
+ });
73
+ export const runRfpDefinitionGate = async (input) => {
74
+ if (!input.rfpPath) {
75
+ return {
76
+ gateId: "gate-rfp-definition-coverage",
77
+ gateName: "RFP Definition Coverage",
78
+ status: "skipped",
79
+ issues: [],
80
+ notes: ["No RFP path provided for definition coverage validation."],
81
+ };
82
+ }
83
+ const allowlist = new Set([...DEFAULT_ALLOWLIST, ...(input.allowlist ?? [])].map((item) => normalizeTerm(item)));
84
+ const issues = [];
85
+ const notes = [];
86
+ try {
87
+ const content = await fs.readFile(input.rfpPath, "utf8");
88
+ const lines = content.split(/\r?\n/);
89
+ let inFence = false;
90
+ let inDefinitions = false;
91
+ let definitionsHeadingLevel = 0;
92
+ const definedTerms = new Set();
93
+ const referencedTerms = [];
94
+ for (let i = 0; i < lines.length; i += 1) {
95
+ const line = lines[i] ?? "";
96
+ const trimmed = line.trim();
97
+ if (!trimmed)
98
+ continue;
99
+ if (isFenceLine(trimmed)) {
100
+ inFence = !inFence;
101
+ continue;
102
+ }
103
+ if (inFence)
104
+ continue;
105
+ const headingMatch = trimmed.match(/^(#{1,6})\s+(.*)$/);
106
+ if (headingMatch) {
107
+ const level = headingMatch[1]?.length ?? 0;
108
+ const heading = headingMatch[2]?.trim() ?? "";
109
+ if (/definitions|glossary/i.test(heading)) {
110
+ inDefinitions = true;
111
+ definitionsHeadingLevel = level;
112
+ }
113
+ else if (inDefinitions && level <= definitionsHeadingLevel) {
114
+ inDefinitions = false;
115
+ }
116
+ continue;
117
+ }
118
+ if (inDefinitions) {
119
+ const term = extractDefinitionTerm(trimmed);
120
+ if (term) {
121
+ definedTerms.add(normalizeTerm(term));
122
+ }
123
+ continue;
124
+ }
125
+ const refs = extractReferencedTerms(trimmed);
126
+ if (refs.length > 0) {
127
+ for (const ref of refs) {
128
+ const normalized = normalizeTerm(ref);
129
+ if (!normalized || allowlist.has(normalized))
130
+ continue;
131
+ referencedTerms.push({ term: ref, line: i + 1, excerpt: trimmed });
132
+ }
133
+ }
134
+ }
135
+ const reported = new Set();
136
+ for (const ref of referencedTerms) {
137
+ const normalized = normalizeTerm(ref.term);
138
+ if (!normalized || definedTerms.has(normalized) || reported.has(normalized))
139
+ continue;
140
+ reported.add(normalized);
141
+ issues.push(buildIssue({
142
+ id: `gate-rfp-definition-coverage-${normalized}`,
143
+ term: ref.term,
144
+ path: input.rfpPath,
145
+ line: ref.line,
146
+ excerpt: ref.excerpt,
147
+ issueType: "undefined_term",
148
+ }));
149
+ }
150
+ if (definedTerms.size === 0 && referencedTerms.length > 0) {
151
+ issues.push(buildIssue({
152
+ id: "gate-rfp-definition-coverage-missing-section",
153
+ term: "Definitions section",
154
+ path: input.rfpPath,
155
+ line: referencedTerms[0]?.line ?? 1,
156
+ excerpt: referencedTerms[0]?.excerpt ?? "",
157
+ issueType: "missing_definitions_section",
158
+ }));
159
+ }
160
+ }
161
+ catch (error) {
162
+ notes.push(`Unable to read RFP at ${input.rfpPath}: ${error.message ?? String(error)}`);
163
+ }
164
+ const status = issues.length === 0 ? "pass" : "fail";
165
+ return {
166
+ gateId: "gate-rfp-definition-coverage",
167
+ gateName: "RFP Definition Coverage",
168
+ status,
169
+ issues,
170
+ notes: notes.length ? notes : undefined,
171
+ metadata: { issueCount: issues.length },
172
+ };
173
+ };
@@ -0,0 +1,7 @@
1
+ import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
2
+ import { ReviewGateResult } from "../ReviewTypes.js";
3
+ export interface SdsAdaptersGateInput {
4
+ artifacts: DocgenArtifactInventory;
5
+ }
6
+ export declare const runSdsAdaptersGate: (input: SdsAdaptersGateInput) => Promise<ReviewGateResult>;
7
+ //# sourceMappingURL=SdsAdaptersGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SdsAdaptersGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SdsAdaptersGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,uBAAuB,CAAC;CACpC;AA2GD,eAAO,MAAM,kBAAkB,GAC7B,OAAO,oBAAoB,KAC1B,OAAO,CAAC,gBAAgB,CAoH1B,CAAC"}