@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.
- package/CHANGELOG.md +3 -0
- package/README.md +2 -2
- package/dist/api/AgentsApi.d.ts +9 -1
- package/dist/api/AgentsApi.d.ts.map +1 -1
- package/dist/api/AgentsApi.js +201 -6
- package/dist/api/QaTasksApi.d.ts.map +1 -1
- package/dist/api/QaTasksApi.js +6 -0
- package/dist/api/TasksApi.d.ts.map +1 -1
- package/dist/api/TasksApi.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/prompts/PdrPrompts.d.ts.map +1 -1
- package/dist/prompts/PdrPrompts.js +9 -1
- package/dist/prompts/SdsPrompts.d.ts.map +1 -1
- package/dist/prompts/SdsPrompts.js +9 -0
- package/dist/services/agents/AgentRatingFormula.d.ts +27 -0
- package/dist/services/agents/AgentRatingFormula.d.ts.map +1 -0
- package/dist/services/agents/AgentRatingFormula.js +45 -0
- package/dist/services/agents/AgentRatingService.d.ts +60 -0
- package/dist/services/agents/AgentRatingService.d.ts.map +1 -0
- package/dist/services/agents/AgentRatingService.js +363 -0
- package/dist/services/agents/GatewayAgentService.d.ts +11 -0
- package/dist/services/agents/GatewayAgentService.d.ts.map +1 -1
- package/dist/services/agents/GatewayAgentService.js +525 -84
- package/dist/services/agents/GatewayHandoff.d.ts +11 -0
- package/dist/services/agents/GatewayHandoff.d.ts.map +1 -0
- package/dist/services/agents/GatewayHandoff.js +141 -0
- package/dist/services/agents/RoutingService.d.ts +1 -0
- package/dist/services/agents/RoutingService.d.ts.map +1 -1
- package/dist/services/agents/RoutingService.js +4 -4
- package/dist/services/backlog/BacklogService.d.ts +23 -0
- package/dist/services/backlog/BacklogService.d.ts.map +1 -1
- package/dist/services/backlog/BacklogService.js +62 -7
- package/dist/services/backlog/TaskOrderingHeuristics.d.ts +12 -0
- package/dist/services/backlog/TaskOrderingHeuristics.d.ts.map +1 -0
- package/dist/services/backlog/TaskOrderingHeuristics.js +56 -0
- package/dist/services/backlog/TaskOrderingService.d.ts +17 -4
- package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
- package/dist/services/backlog/TaskOrderingService.js +538 -79
- package/dist/services/docs/DocInventory.d.ts +11 -0
- package/dist/services/docs/DocInventory.d.ts.map +1 -0
- package/dist/services/docs/DocInventory.js +230 -0
- package/dist/services/docs/DocgenRunContext.d.ts +59 -0
- package/dist/services/docs/DocgenRunContext.d.ts.map +1 -0
- package/dist/services/docs/DocgenRunContext.js +4 -0
- package/dist/services/docs/DocsService.d.ts +70 -3
- package/dist/services/docs/DocsService.d.ts.map +1 -1
- package/dist/services/docs/DocsService.js +1930 -89
- package/dist/services/docs/alignment/DocAlignmentGraph.d.ts +23 -0
- package/dist/services/docs/alignment/DocAlignmentGraph.d.ts.map +1 -0
- package/dist/services/docs/alignment/DocAlignmentGraph.js +78 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts +19 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.d.ts.map +1 -0
- package/dist/services/docs/alignment/DocAlignmentPatcher.js +222 -0
- package/dist/services/docs/patch/DocPatchEngine.d.ts +57 -0
- package/dist/services/docs/patch/DocPatchEngine.d.ts.map +1 -0
- package/dist/services/docs/patch/DocPatchEngine.js +331 -0
- package/dist/services/docs/review/Glossary.d.ts +16 -0
- package/dist/services/docs/review/Glossary.d.ts.map +1 -0
- package/dist/services/docs/review/Glossary.js +47 -0
- package/dist/services/docs/review/ReviewReportRenderer.d.ts +3 -0
- package/dist/services/docs/review/ReviewReportRenderer.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewReportRenderer.js +133 -0
- package/dist/services/docs/review/ReviewReportSchema.d.ts +39 -0
- package/dist/services/docs/review/ReviewReportSchema.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewReportSchema.js +47 -0
- package/dist/services/docs/review/ReviewTypes.d.ts +76 -0
- package/dist/services/docs/review/ReviewTypes.d.ts.map +1 -0
- package/dist/services/docs/review/ReviewTypes.js +94 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts +7 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/AdminOpenApiSpecGate.js +93 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts +7 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/ApiPathConsistencyGate.js +308 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts +8 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/BuildReadyCompletenessGate.js +278 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts +8 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/DeploymentBlueprintGate.js +487 -0
- package/dist/services/docs/review/gates/NoMaybesGate.d.ts +8 -0
- package/dist/services/docs/review/gates/NoMaybesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/NoMaybesGate.js +145 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenApiCoverageGate.js +266 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenApiSchemaSanityGate.js +59 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/OpenQuestionsGate.js +200 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts +7 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrInterfacesGate.js +159 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts +8 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrOpenQuestionsGate.js +129 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts +7 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PdrOwnershipGate.js +169 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts +10 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/PlaceholderArtifactGate.js +261 -0
- package/dist/services/docs/review/gates/RfpConsentGate.d.ts +6 -0
- package/dist/services/docs/review/gates/RfpConsentGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/RfpConsentGate.js +127 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts +7 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/RfpDefinitionGate.js +173 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsAdaptersGate.js +196 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsDecisionsGate.js +89 -0
- package/dist/services/docs/review/gates/SdsOpsGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsOpsGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsOpsGate.js +162 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SdsPolicyTelemetryGate.js +166 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SqlRequiredTablesGate.js +273 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts +7 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/SqlSyntaxGate.js +203 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts +9 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.d.ts.map +1 -0
- package/dist/services/docs/review/gates/TerminologyNormalizationGate.js +217 -0
- package/dist/services/docs/review/glossary.json +47 -0
- package/dist/services/estimate/EstimateService.d.ts +2 -0
- package/dist/services/estimate/EstimateService.d.ts.map +1 -1
- package/dist/services/estimate/EstimateService.js +66 -18
- package/dist/services/estimate/VelocityService.d.ts +4 -0
- package/dist/services/estimate/VelocityService.d.ts.map +1 -1
- package/dist/services/estimate/VelocityService.js +179 -36
- package/dist/services/estimate/types.d.ts +1 -0
- package/dist/services/estimate/types.d.ts.map +1 -1
- package/dist/services/execution/GatewayTrioService.d.ts +200 -0
- package/dist/services/execution/GatewayTrioService.d.ts.map +1 -0
- package/dist/services/execution/GatewayTrioService.js +2492 -0
- package/dist/services/execution/QaApiRunner.d.ts +30 -0
- package/dist/services/execution/QaApiRunner.d.ts.map +1 -0
- package/dist/services/execution/QaApiRunner.js +881 -0
- package/dist/services/execution/QaFollowupService.d.ts +2 -0
- package/dist/services/execution/QaFollowupService.d.ts.map +1 -1
- package/dist/services/execution/QaFollowupService.js +9 -2
- package/dist/services/execution/QaPlanValidator.d.ts +10 -0
- package/dist/services/execution/QaPlanValidator.d.ts.map +1 -0
- package/dist/services/execution/QaPlanValidator.js +128 -0
- package/dist/services/execution/QaProfileService.d.ts +27 -1
- package/dist/services/execution/QaProfileService.d.ts.map +1 -1
- package/dist/services/execution/QaProfileService.js +354 -7
- package/dist/services/execution/QaTasksService.d.ts +59 -1
- package/dist/services/execution/QaTasksService.d.ts.map +1 -1
- package/dist/services/execution/QaTasksService.js +3347 -318
- package/dist/services/execution/QaTestCommandBuilder.d.ts +51 -0
- package/dist/services/execution/QaTestCommandBuilder.d.ts.map +1 -0
- package/dist/services/execution/QaTestCommandBuilder.js +495 -0
- package/dist/services/execution/TaskSelectionService.d.ts +4 -2
- package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
- package/dist/services/execution/TaskSelectionService.js +144 -28
- package/dist/services/execution/TaskStateService.d.ts +19 -6
- package/dist/services/execution/TaskStateService.d.ts.map +1 -1
- package/dist/services/execution/TaskStateService.js +128 -13
- package/dist/services/execution/WorkOnTasksService.d.ts +32 -1
- package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
- package/dist/services/execution/WorkOnTasksService.js +4667 -722
- package/dist/services/jobs/JobInsightsService.d.ts +4 -0
- package/dist/services/jobs/JobInsightsService.d.ts.map +1 -1
- package/dist/services/jobs/JobInsightsService.js +51 -5
- package/dist/services/jobs/JobResumeService.d.ts.map +1 -1
- package/dist/services/jobs/JobResumeService.js +23 -10
- package/dist/services/jobs/JobService.d.ts +56 -4
- package/dist/services/jobs/JobService.d.ts.map +1 -1
- package/dist/services/jobs/JobService.js +232 -1
- package/dist/services/openapi/OpenApiService.d.ts +51 -0
- package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
- package/dist/services/openapi/OpenApiService.js +953 -106
- package/dist/services/planning/CreateTasksService.d.ts +21 -0
- package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
- package/dist/services/planning/CreateTasksService.js +569 -31
- package/dist/services/planning/RefineTasksService.d.ts +9 -0
- package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
- package/dist/services/planning/RefineTasksService.js +409 -59
- package/dist/services/review/CodeReviewService.d.ts +18 -0
- package/dist/services/review/CodeReviewService.d.ts.map +1 -1
- package/dist/services/review/CodeReviewService.js +1309 -167
- package/dist/services/review/ReviewNormalizer.d.ts +9 -0
- package/dist/services/review/ReviewNormalizer.d.ts.map +1 -0
- package/dist/services/review/ReviewNormalizer.js +147 -0
- package/dist/services/shared/AuthErrors.d.ts +3 -0
- package/dist/services/shared/AuthErrors.d.ts.map +1 -0
- package/dist/services/shared/AuthErrors.js +17 -0
- package/dist/services/shared/DocdexGuidance.d.ts +7 -0
- package/dist/services/shared/DocdexGuidance.d.ts.map +1 -0
- package/dist/services/shared/DocdexGuidance.js +12 -0
- package/dist/services/shared/ProjectGuidance.d.ts +17 -0
- package/dist/services/shared/ProjectGuidance.d.ts.map +1 -0
- package/dist/services/shared/ProjectGuidance.js +78 -0
- package/dist/services/system/ToolDenylist.d.ts +13 -0
- package/dist/services/system/ToolDenylist.d.ts.map +1 -0
- package/dist/services/system/ToolDenylist.js +85 -0
- package/dist/services/tasks/TaskCommentFormatter.d.ts +20 -0
- package/dist/services/tasks/TaskCommentFormatter.d.ts.map +1 -0
- package/dist/services/tasks/TaskCommentFormatter.js +54 -0
- package/dist/services/telemetry/TelemetryService.d.ts.map +1 -1
- package/dist/services/telemetry/TelemetryService.js +39 -7
- package/dist/workspace/WorkspaceManager.d.ts +26 -0
- package/dist/workspace/WorkspaceManager.d.ts.map +1 -1
- package/dist/workspace/WorkspaceManager.js +206 -32
- package/package.json +6 -5
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
|
|
3
|
+
const extractSection = (lines, headingMatch) => {
|
|
4
|
+
let inFence = false;
|
|
5
|
+
let capture = false;
|
|
6
|
+
let startLine = 0;
|
|
7
|
+
const collected = [];
|
|
8
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
9
|
+
const line = lines[i] ?? "";
|
|
10
|
+
const trimmed = line.trim();
|
|
11
|
+
if (isFenceLine(trimmed)) {
|
|
12
|
+
inFence = !inFence;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (inFence)
|
|
16
|
+
continue;
|
|
17
|
+
const heading = trimmed.match(/^#{1,6}\s+(.*)$/);
|
|
18
|
+
if (heading) {
|
|
19
|
+
const title = heading[1]?.trim() ?? "";
|
|
20
|
+
if (headingMatch.test(title)) {
|
|
21
|
+
capture = true;
|
|
22
|
+
startLine = i + 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (capture)
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (capture && trimmed)
|
|
29
|
+
collected.push(trimmed);
|
|
30
|
+
}
|
|
31
|
+
if (!capture)
|
|
32
|
+
return undefined;
|
|
33
|
+
return { content: collected, line: startLine };
|
|
34
|
+
};
|
|
35
|
+
const containsAny = (lines, patterns) => lines.some((line) => patterns.some((pattern) => pattern.test(line)));
|
|
36
|
+
const buildIssue = (input) => ({
|
|
37
|
+
id: input.id,
|
|
38
|
+
gateId: "gate-sds-external-adapters",
|
|
39
|
+
severity: "high",
|
|
40
|
+
category: "completeness",
|
|
41
|
+
artifact: "sds",
|
|
42
|
+
message: input.message,
|
|
43
|
+
remediation: input.remediation,
|
|
44
|
+
location: {
|
|
45
|
+
kind: "line_range",
|
|
46
|
+
path: input.record.path,
|
|
47
|
+
lineStart: input.line ?? 1,
|
|
48
|
+
lineEnd: input.line ?? 1,
|
|
49
|
+
excerpt: input.message,
|
|
50
|
+
},
|
|
51
|
+
metadata: input.metadata,
|
|
52
|
+
});
|
|
53
|
+
const EXTERNAL_SERVICE_PATTERNS = [
|
|
54
|
+
{ name: "Brave", pattern: /\bBrave(?:\s+Search)?\b/i },
|
|
55
|
+
{ name: "OpenRouter", pattern: /\bOpenRouter\b/i },
|
|
56
|
+
{ name: "OpenAI", pattern: /\bOpenAI\b/i },
|
|
57
|
+
{ name: "Anthropic", pattern: /\bAnthropic\b/i },
|
|
58
|
+
{ name: "Cohere", pattern: /\bCohere\b/i },
|
|
59
|
+
{ name: "Mistral", pattern: /\bMistral\b/i },
|
|
60
|
+
{ name: "Stripe", pattern: /\bStripe\b/i },
|
|
61
|
+
{ name: "Twilio", pattern: /\bTwilio\b/i },
|
|
62
|
+
{ name: "SendGrid", pattern: /\bSendGrid\b/i },
|
|
63
|
+
{ name: "Sentry", pattern: /\bSentry\b/i },
|
|
64
|
+
{ name: "Datadog", pattern: /\bDatadog\b/i },
|
|
65
|
+
{ name: "PostHog", pattern: /\bPostHog\b/i },
|
|
66
|
+
{ name: "Algolia", pattern: /\bAlgolia\b/i },
|
|
67
|
+
];
|
|
68
|
+
const ADAPTER_SECTION = /adapter|integration|external|third[- ]?party|provider|vendor|connector|dependency|contract/i;
|
|
69
|
+
const CONSTRAINT_PATTERNS = [
|
|
70
|
+
/rate limit/i,
|
|
71
|
+
/quota/i,
|
|
72
|
+
/sla/i,
|
|
73
|
+
/contract/i,
|
|
74
|
+
/auth/i,
|
|
75
|
+
/api key/i,
|
|
76
|
+
/token/i,
|
|
77
|
+
/timeout/i,
|
|
78
|
+
/latency/i,
|
|
79
|
+
/limit/i,
|
|
80
|
+
/pricing/i,
|
|
81
|
+
];
|
|
82
|
+
const ERROR_HANDLING_PATTERNS = [
|
|
83
|
+
/error/i,
|
|
84
|
+
/retry/i,
|
|
85
|
+
/backoff/i,
|
|
86
|
+
/circuit/i,
|
|
87
|
+
/failover/i,
|
|
88
|
+
/dead[- ]?letter/i,
|
|
89
|
+
];
|
|
90
|
+
const FALLBACK_PATTERNS = [/fallback/i, /degrade/i, /alternate/i, /secondary/i, /backup/i, /switch/i];
|
|
91
|
+
export const runSdsAdaptersGate = async (input) => {
|
|
92
|
+
const sds = input.artifacts.sds;
|
|
93
|
+
if (!sds) {
|
|
94
|
+
return {
|
|
95
|
+
gateId: "gate-sds-external-adapters",
|
|
96
|
+
gateName: "SDS External Adapters",
|
|
97
|
+
status: "skipped",
|
|
98
|
+
issues: [],
|
|
99
|
+
notes: ["No SDS artifact available for external adapter validation."],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const issues = [];
|
|
103
|
+
const notes = [];
|
|
104
|
+
try {
|
|
105
|
+
const content = await fs.readFile(sds.path, "utf8");
|
|
106
|
+
const lines = content.split(/\r?\n/);
|
|
107
|
+
const references = new Map();
|
|
108
|
+
let inFence = false;
|
|
109
|
+
lines.forEach((line, index) => {
|
|
110
|
+
const trimmed = line.trim();
|
|
111
|
+
if (isFenceLine(trimmed)) {
|
|
112
|
+
inFence = !inFence;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (inFence)
|
|
116
|
+
return;
|
|
117
|
+
for (const entry of EXTERNAL_SERVICE_PATTERNS) {
|
|
118
|
+
if (entry.pattern.test(line)) {
|
|
119
|
+
if (!references.has(entry.name)) {
|
|
120
|
+
references.set(entry.name, index + 1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
if (references.size === 0) {
|
|
126
|
+
return {
|
|
127
|
+
gateId: "gate-sds-external-adapters",
|
|
128
|
+
gateName: "SDS External Adapters",
|
|
129
|
+
status: "pass",
|
|
130
|
+
issues: [],
|
|
131
|
+
metadata: { issueCount: 0 },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const adapterSection = extractSection(lines, ADAPTER_SECTION);
|
|
135
|
+
if (!adapterSection) {
|
|
136
|
+
for (const [service, line] of references.entries()) {
|
|
137
|
+
issues.push(buildIssue({
|
|
138
|
+
id: `gate-sds-external-adapters-missing-section-${service.toLowerCase()}`,
|
|
139
|
+
message: `SDS references ${service} but lacks an external adapter section.`,
|
|
140
|
+
remediation: `Add an External Integrations/Adapters section describing constraints, error handling, and fallback for ${service}.`,
|
|
141
|
+
record: sds,
|
|
142
|
+
line,
|
|
143
|
+
metadata: { issueType: "missing_adapter_section", service },
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const adapterText = adapterSection.content.join(" ");
|
|
149
|
+
for (const [service, line] of references.entries()) {
|
|
150
|
+
const pattern = EXTERNAL_SERVICE_PATTERNS.find((entry) => entry.name === service)?.pattern;
|
|
151
|
+
if (pattern && !pattern.test(adapterText)) {
|
|
152
|
+
issues.push(buildIssue({
|
|
153
|
+
id: `gate-sds-external-adapters-missing-${service.toLowerCase()}`,
|
|
154
|
+
message: `SDS references ${service} but the adapter details are missing.`,
|
|
155
|
+
remediation: `Describe the ${service} adapter/contract, including constraints, error handling, and fallback behavior.`,
|
|
156
|
+
record: sds,
|
|
157
|
+
line,
|
|
158
|
+
metadata: { issueType: "missing_adapter_description", service },
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const missing = [];
|
|
163
|
+
if (!containsAny(adapterSection.content, CONSTRAINT_PATTERNS)) {
|
|
164
|
+
missing.push("constraints");
|
|
165
|
+
}
|
|
166
|
+
if (!containsAny(adapterSection.content, ERROR_HANDLING_PATTERNS)) {
|
|
167
|
+
missing.push("error_handling");
|
|
168
|
+
}
|
|
169
|
+
if (!containsAny(adapterSection.content, FALLBACK_PATTERNS)) {
|
|
170
|
+
missing.push("fallback");
|
|
171
|
+
}
|
|
172
|
+
if (missing.length > 0) {
|
|
173
|
+
issues.push(buildIssue({
|
|
174
|
+
id: "gate-sds-external-adapters-missing-details",
|
|
175
|
+
message: `External adapter section is missing ${missing.join(", ")} details.`,
|
|
176
|
+
remediation: "Expand the adapter section to document integration constraints, error handling, and fallback behavior.",
|
|
177
|
+
record: sds,
|
|
178
|
+
line: adapterSection.line,
|
|
179
|
+
metadata: { issueType: "missing_adapter_details", missing },
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
notes.push(`Unable to read SDS ${sds.path}: ${error.message ?? String(error)}`);
|
|
186
|
+
}
|
|
187
|
+
const status = issues.length === 0 ? "pass" : "fail";
|
|
188
|
+
return {
|
|
189
|
+
gateId: "gate-sds-external-adapters",
|
|
190
|
+
gateName: "SDS External Adapters",
|
|
191
|
+
status,
|
|
192
|
+
issues,
|
|
193
|
+
notes: notes.length ? notes : undefined,
|
|
194
|
+
metadata: { issueCount: issues.length },
|
|
195
|
+
};
|
|
196
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
|
|
2
|
+
import { ReviewGateResult } from "../ReviewTypes.js";
|
|
3
|
+
export interface SdsDecisionsGateInput {
|
|
4
|
+
artifacts: DocgenArtifactInventory;
|
|
5
|
+
}
|
|
6
|
+
export declare const runSdsDecisionsGate: (input: SdsDecisionsGateInput) => Promise<ReviewGateResult>;
|
|
7
|
+
//# sourceMappingURL=SdsDecisionsGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SdsDecisionsGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SdsDecisionsGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAqCD,eAAO,MAAM,mBAAmB,GAC9B,OAAO,qBAAqB,KAC3B,OAAO,CAAC,gBAAgB,CAiE1B,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
const DECISION_HEADINGS = /architecture|tech stack|technology|database|storage|runtime|language|framework|deployment/i;
|
|
3
|
+
const OPTIONS_HEADING = /options considered|alternatives/i;
|
|
4
|
+
const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
|
|
5
|
+
const isAmbiguousDecision = (line) => {
|
|
6
|
+
const trimmed = line.toLowerCase();
|
|
7
|
+
if (trimmed.includes("either ") || trimmed.includes(" or ") || trimmed.includes("/")) {
|
|
8
|
+
return /\b\w+\s+(or|\/)+\s+\w+/.test(trimmed) || /either\s+\w+\s+or\s+\w+/.test(trimmed);
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
};
|
|
12
|
+
const buildIssue = (input) => ({
|
|
13
|
+
id: `gate-sds-explicit-decisions-${input.line}`,
|
|
14
|
+
gateId: "gate-sds-explicit-decisions",
|
|
15
|
+
severity: "high",
|
|
16
|
+
category: "decision",
|
|
17
|
+
artifact: "sds",
|
|
18
|
+
message: "SDS decision section contains ambiguous technology choice.",
|
|
19
|
+
remediation: "Replace ambiguous choices with a single explicit decision.",
|
|
20
|
+
location: {
|
|
21
|
+
kind: "line_range",
|
|
22
|
+
path: input.record.path,
|
|
23
|
+
lineStart: input.line,
|
|
24
|
+
lineEnd: input.line,
|
|
25
|
+
excerpt: input.excerpt,
|
|
26
|
+
},
|
|
27
|
+
metadata: { issueType: "ambiguous_decision" },
|
|
28
|
+
});
|
|
29
|
+
export const runSdsDecisionsGate = async (input) => {
|
|
30
|
+
const sds = input.artifacts.sds;
|
|
31
|
+
if (!sds) {
|
|
32
|
+
return {
|
|
33
|
+
gateId: "gate-sds-explicit-decisions",
|
|
34
|
+
gateName: "SDS Explicit Decisions",
|
|
35
|
+
status: "skipped",
|
|
36
|
+
issues: [],
|
|
37
|
+
notes: ["No SDS artifact available for explicit decision validation."],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const issues = [];
|
|
41
|
+
const notes = [];
|
|
42
|
+
try {
|
|
43
|
+
const content = await fs.readFile(sds.path, "utf8");
|
|
44
|
+
const lines = content.split(/\r?\n/);
|
|
45
|
+
let inFence = false;
|
|
46
|
+
let inDecisionSection = false;
|
|
47
|
+
let inOptionsSection = false;
|
|
48
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
49
|
+
const line = lines[i] ?? "";
|
|
50
|
+
const trimmed = line.trim();
|
|
51
|
+
if (!trimmed)
|
|
52
|
+
continue;
|
|
53
|
+
if (isFenceLine(trimmed)) {
|
|
54
|
+
inFence = !inFence;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (inFence)
|
|
58
|
+
continue;
|
|
59
|
+
const heading = trimmed.match(/^#{1,6}\s+(.*)$/);
|
|
60
|
+
if (heading) {
|
|
61
|
+
const title = heading[1]?.trim() ?? "";
|
|
62
|
+
inOptionsSection = OPTIONS_HEADING.test(title);
|
|
63
|
+
inDecisionSection = DECISION_HEADINGS.test(title) && !inOptionsSection;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!inDecisionSection || inOptionsSection)
|
|
67
|
+
continue;
|
|
68
|
+
if (!isAmbiguousDecision(trimmed))
|
|
69
|
+
continue;
|
|
70
|
+
issues.push(buildIssue({
|
|
71
|
+
record: sds,
|
|
72
|
+
line: i + 1,
|
|
73
|
+
excerpt: trimmed,
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
notes.push(`Unable to read SDS ${sds.path}: ${error.message ?? String(error)}`);
|
|
79
|
+
}
|
|
80
|
+
const status = issues.length === 0 ? "pass" : "fail";
|
|
81
|
+
return {
|
|
82
|
+
gateId: "gate-sds-explicit-decisions",
|
|
83
|
+
gateName: "SDS Explicit Decisions",
|
|
84
|
+
status,
|
|
85
|
+
issues,
|
|
86
|
+
notes: notes.length ? notes : undefined,
|
|
87
|
+
metadata: { issueCount: issues.length },
|
|
88
|
+
};
|
|
89
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
|
|
2
|
+
import { ReviewGateResult } from "../ReviewTypes.js";
|
|
3
|
+
export interface SdsOpsGateInput {
|
|
4
|
+
artifacts: DocgenArtifactInventory;
|
|
5
|
+
}
|
|
6
|
+
export declare const runSdsOpsGate: (input: SdsOpsGateInput) => Promise<ReviewGateResult>;
|
|
7
|
+
//# sourceMappingURL=SdsOpsGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SdsOpsGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SdsOpsGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAgED,eAAO,MAAM,aAAa,GAAU,OAAO,eAAe,KAAG,OAAO,CAAC,gBAAgB,CAgIpF,CAAC"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
|
|
3
|
+
const extractSection = (lines, headingMatch) => {
|
|
4
|
+
let inFence = false;
|
|
5
|
+
let capture = false;
|
|
6
|
+
let startLine = 0;
|
|
7
|
+
const collected = [];
|
|
8
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
9
|
+
const line = lines[i] ?? "";
|
|
10
|
+
const trimmed = line.trim();
|
|
11
|
+
if (isFenceLine(trimmed)) {
|
|
12
|
+
inFence = !inFence;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (inFence)
|
|
16
|
+
continue;
|
|
17
|
+
const heading = trimmed.match(/^#{1,6}\s+(.*)$/);
|
|
18
|
+
if (heading) {
|
|
19
|
+
const title = heading[1]?.trim() ?? "";
|
|
20
|
+
if (headingMatch.test(title)) {
|
|
21
|
+
capture = true;
|
|
22
|
+
startLine = i + 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (capture)
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (capture && trimmed)
|
|
29
|
+
collected.push(trimmed);
|
|
30
|
+
}
|
|
31
|
+
if (!capture)
|
|
32
|
+
return undefined;
|
|
33
|
+
return { content: collected, line: startLine };
|
|
34
|
+
};
|
|
35
|
+
const containsAny = (lines, patterns) => lines.some((line) => patterns.some((pattern) => pattern.test(line)));
|
|
36
|
+
const buildIssue = (input) => ({
|
|
37
|
+
id: input.id,
|
|
38
|
+
gateId: "gate-sds-ops-observability-testing",
|
|
39
|
+
severity: "high",
|
|
40
|
+
category: "completeness",
|
|
41
|
+
artifact: "sds",
|
|
42
|
+
message: input.message,
|
|
43
|
+
remediation: input.remediation,
|
|
44
|
+
location: {
|
|
45
|
+
kind: "line_range",
|
|
46
|
+
path: input.record.path,
|
|
47
|
+
lineStart: input.line ?? 1,
|
|
48
|
+
lineEnd: input.line ?? 1,
|
|
49
|
+
excerpt: input.message,
|
|
50
|
+
},
|
|
51
|
+
metadata: input.metadata,
|
|
52
|
+
});
|
|
53
|
+
export const runSdsOpsGate = async (input) => {
|
|
54
|
+
const sds = input.artifacts.sds;
|
|
55
|
+
if (!sds) {
|
|
56
|
+
return {
|
|
57
|
+
gateId: "gate-sds-ops-observability-testing",
|
|
58
|
+
gateName: "SDS Ops & Observability",
|
|
59
|
+
status: "skipped",
|
|
60
|
+
issues: [],
|
|
61
|
+
notes: ["No SDS artifact available for ops/observability validation."],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const issues = [];
|
|
65
|
+
const notes = [];
|
|
66
|
+
try {
|
|
67
|
+
const content = await fs.readFile(sds.path, "utf8");
|
|
68
|
+
const lines = content.split(/\r?\n/);
|
|
69
|
+
const opsSection = extractSection(lines, /operations|deployment|environment/i);
|
|
70
|
+
const observabilitySection = extractSection(lines, /observability|monitoring|slo|alert/i);
|
|
71
|
+
const testingSection = extractSection(lines, /testing|quality|test gates?/i);
|
|
72
|
+
const failureSection = extractSection(lines, /failure|recovery|rollback|incident/i);
|
|
73
|
+
if (!opsSection) {
|
|
74
|
+
issues.push(buildIssue({
|
|
75
|
+
id: "gate-sds-ops-observability-testing-missing-ops",
|
|
76
|
+
message: "SDS is missing an operations/deployment section.",
|
|
77
|
+
remediation: "Add environment, secrets strategy, and deployment details.",
|
|
78
|
+
record: sds,
|
|
79
|
+
metadata: { issueType: "missing_ops" },
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
else if (!containsAny(opsSection.content, [/environment/i, /secrets?/i, /deploy/i])) {
|
|
83
|
+
issues.push(buildIssue({
|
|
84
|
+
id: "gate-sds-ops-observability-testing-incomplete-ops",
|
|
85
|
+
message: "Operations section lacks environment/secrets details.",
|
|
86
|
+
remediation: "Describe deployment environments and secrets handling.",
|
|
87
|
+
record: sds,
|
|
88
|
+
line: opsSection.line,
|
|
89
|
+
metadata: { issueType: "incomplete_ops" },
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
if (!observabilitySection) {
|
|
93
|
+
issues.push(buildIssue({
|
|
94
|
+
id: "gate-sds-ops-observability-testing-missing-observability",
|
|
95
|
+
message: "SDS is missing an observability section.",
|
|
96
|
+
remediation: "Add SLOs, alerting thresholds, and monitoring targets.",
|
|
97
|
+
record: sds,
|
|
98
|
+
metadata: { issueType: "missing_observability" },
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
else if (!containsAny(observabilitySection.content, [/slo/i, /alert/i, /threshold/i])) {
|
|
102
|
+
issues.push(buildIssue({
|
|
103
|
+
id: "gate-sds-ops-observability-testing-incomplete-observability",
|
|
104
|
+
message: "Observability section lacks SLOs or alert thresholds.",
|
|
105
|
+
remediation: "Define SLOs and alert thresholds for critical metrics.",
|
|
106
|
+
record: sds,
|
|
107
|
+
line: observabilitySection.line,
|
|
108
|
+
metadata: { issueType: "incomplete_observability" },
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
if (!testingSection) {
|
|
112
|
+
issues.push(buildIssue({
|
|
113
|
+
id: "gate-sds-ops-observability-testing-missing-testing",
|
|
114
|
+
message: "SDS is missing a testing gates section.",
|
|
115
|
+
remediation: "Describe test gates and release validation steps.",
|
|
116
|
+
record: sds,
|
|
117
|
+
metadata: { issueType: "missing_testing" },
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
else if (!containsAny(testingSection.content, [/test/i, /gate/i, /validation/i])) {
|
|
121
|
+
issues.push(buildIssue({
|
|
122
|
+
id: "gate-sds-ops-observability-testing-incomplete-testing",
|
|
123
|
+
message: "Testing section lacks explicit test gates or validation criteria.",
|
|
124
|
+
remediation: "List required test gates for deployment readiness.",
|
|
125
|
+
record: sds,
|
|
126
|
+
line: testingSection.line,
|
|
127
|
+
metadata: { issueType: "incomplete_testing" },
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
if (!failureSection) {
|
|
131
|
+
issues.push(buildIssue({
|
|
132
|
+
id: "gate-sds-ops-observability-testing-missing-failure",
|
|
133
|
+
message: "SDS is missing failure modes and recovery procedures.",
|
|
134
|
+
remediation: "Document failure modes and recovery/runbook steps.",
|
|
135
|
+
record: sds,
|
|
136
|
+
metadata: { issueType: "missing_failure" },
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
else if (!containsAny(failureSection.content, [/failure/i, /recovery/i, /rollback/i])) {
|
|
140
|
+
issues.push(buildIssue({
|
|
141
|
+
id: "gate-sds-ops-observability-testing-incomplete-failure",
|
|
142
|
+
message: "Failure section lacks recovery or rollback details.",
|
|
143
|
+
remediation: "Include recovery procedures and rollback steps.",
|
|
144
|
+
record: sds,
|
|
145
|
+
line: failureSection.line,
|
|
146
|
+
metadata: { issueType: "incomplete_failure" },
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
notes.push(`Unable to read SDS ${sds.path}: ${error.message ?? String(error)}`);
|
|
152
|
+
}
|
|
153
|
+
const status = issues.length === 0 ? "pass" : "fail";
|
|
154
|
+
return {
|
|
155
|
+
gateId: "gate-sds-ops-observability-testing",
|
|
156
|
+
gateName: "SDS Ops & Observability",
|
|
157
|
+
status,
|
|
158
|
+
issues,
|
|
159
|
+
notes: notes.length ? notes : undefined,
|
|
160
|
+
metadata: { issueCount: issues.length },
|
|
161
|
+
};
|
|
162
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
|
|
2
|
+
import { ReviewGateResult } from "../ReviewTypes.js";
|
|
3
|
+
export interface SdsPolicyTelemetryGateInput {
|
|
4
|
+
artifacts: DocgenArtifactInventory;
|
|
5
|
+
}
|
|
6
|
+
export declare const runSdsPolicyTelemetryGate: (input: SdsPolicyTelemetryGateInput) => Promise<ReviewGateResult>;
|
|
7
|
+
//# sourceMappingURL=SdsPolicyTelemetryGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SdsPolicyTelemetryGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SdsPolicyTelemetryGate.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAgED,eAAO,MAAM,yBAAyB,GACpC,OAAO,2BAA2B,KACjC,OAAO,CAAC,gBAAgB,CAgI1B,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
const isFenceLine = (line) => /^```|^~~~/.test(line.trim());
|
|
3
|
+
const extractSection = (lines, headingMatch) => {
|
|
4
|
+
let inFence = false;
|
|
5
|
+
let capture = false;
|
|
6
|
+
let startLine = 0;
|
|
7
|
+
const collected = [];
|
|
8
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
9
|
+
const line = lines[i] ?? "";
|
|
10
|
+
const trimmed = line.trim();
|
|
11
|
+
if (isFenceLine(trimmed)) {
|
|
12
|
+
inFence = !inFence;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (inFence)
|
|
16
|
+
continue;
|
|
17
|
+
const heading = trimmed.match(/^#{1,6}\s+(.*)$/);
|
|
18
|
+
if (heading) {
|
|
19
|
+
const title = heading[1]?.trim() ?? "";
|
|
20
|
+
if (headingMatch.test(title)) {
|
|
21
|
+
capture = true;
|
|
22
|
+
startLine = i + 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (capture)
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (capture && trimmed)
|
|
29
|
+
collected.push(trimmed);
|
|
30
|
+
}
|
|
31
|
+
if (!capture)
|
|
32
|
+
return undefined;
|
|
33
|
+
return { content: collected, line: startLine };
|
|
34
|
+
};
|
|
35
|
+
const containsAny = (lines, patterns) => lines.some((line) => patterns.some((pattern) => pattern.test(line)));
|
|
36
|
+
const buildIssue = (input) => ({
|
|
37
|
+
id: input.id,
|
|
38
|
+
gateId: "gate-sds-policy-telemetry-metering",
|
|
39
|
+
severity: "high",
|
|
40
|
+
category: "completeness",
|
|
41
|
+
artifact: "sds",
|
|
42
|
+
message: input.message,
|
|
43
|
+
remediation: input.remediation,
|
|
44
|
+
location: {
|
|
45
|
+
kind: "line_range",
|
|
46
|
+
path: input.record.path,
|
|
47
|
+
lineStart: input.line ?? 1,
|
|
48
|
+
lineEnd: input.line ?? 1,
|
|
49
|
+
excerpt: input.message,
|
|
50
|
+
},
|
|
51
|
+
metadata: input.metadata,
|
|
52
|
+
});
|
|
53
|
+
export const runSdsPolicyTelemetryGate = async (input) => {
|
|
54
|
+
const sds = input.artifacts.sds;
|
|
55
|
+
if (!sds) {
|
|
56
|
+
return {
|
|
57
|
+
gateId: "gate-sds-policy-telemetry-metering",
|
|
58
|
+
gateName: "SDS Policy, Telemetry & Metering",
|
|
59
|
+
status: "skipped",
|
|
60
|
+
issues: [],
|
|
61
|
+
notes: ["No SDS artifact available for policy/telemetry validation."],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const issues = [];
|
|
65
|
+
const notes = [];
|
|
66
|
+
try {
|
|
67
|
+
const content = await fs.readFile(sds.path, "utf8");
|
|
68
|
+
const lines = content.split(/\r?\n/);
|
|
69
|
+
const policySection = extractSection(lines, /policy|cache|consent/i);
|
|
70
|
+
const telemetrySection = extractSection(lines, /telemetry|metrics|logging|events?/i);
|
|
71
|
+
const meteringSection = extractSection(lines, /metering|usage|billing|rate limits?/i);
|
|
72
|
+
if (!policySection) {
|
|
73
|
+
issues.push(buildIssue({
|
|
74
|
+
id: "gate-sds-policy-telemetry-metering-missing-policy",
|
|
75
|
+
message: "SDS is missing a policy/cache section.",
|
|
76
|
+
remediation: "Add cache key policy, TTL tiers, and consent matrix details.",
|
|
77
|
+
record: sds,
|
|
78
|
+
metadata: { issueType: "missing_policy" },
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const policyOk = containsAny(policySection.content, [
|
|
83
|
+
/cache key/i,
|
|
84
|
+
/ttl/i,
|
|
85
|
+
/consent matrix/i,
|
|
86
|
+
/consent/i,
|
|
87
|
+
]);
|
|
88
|
+
if (!policyOk) {
|
|
89
|
+
issues.push(buildIssue({
|
|
90
|
+
id: "gate-sds-policy-telemetry-metering-incomplete-policy",
|
|
91
|
+
message: "Policy section lacks cache key/TTL/consent matrix details.",
|
|
92
|
+
remediation: "Include cache key rules, TTL tiers, and a consent matrix.",
|
|
93
|
+
record: sds,
|
|
94
|
+
line: policySection.line,
|
|
95
|
+
metadata: { issueType: "incomplete_policy" },
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!telemetrySection) {
|
|
100
|
+
issues.push(buildIssue({
|
|
101
|
+
id: "gate-sds-policy-telemetry-metering-missing-telemetry",
|
|
102
|
+
message: "SDS is missing a telemetry schema section.",
|
|
103
|
+
remediation: "Add telemetry schema definitions for anonymous and identified data.",
|
|
104
|
+
record: sds,
|
|
105
|
+
metadata: { issueType: "missing_telemetry" },
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const telemetryOk = containsAny(telemetrySection.content, [
|
|
110
|
+
/schema/i,
|
|
111
|
+
/anonymous/i,
|
|
112
|
+
/identified/i,
|
|
113
|
+
]);
|
|
114
|
+
if (!telemetryOk) {
|
|
115
|
+
issues.push(buildIssue({
|
|
116
|
+
id: "gate-sds-policy-telemetry-metering-incomplete-telemetry",
|
|
117
|
+
message: "Telemetry section lacks schema details for anonymous/identified data.",
|
|
118
|
+
remediation: "Describe telemetry schemas and how anonymous vs identified data are captured.",
|
|
119
|
+
record: sds,
|
|
120
|
+
line: telemetrySection.line,
|
|
121
|
+
metadata: { issueType: "incomplete_telemetry" },
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (!meteringSection) {
|
|
126
|
+
issues.push(buildIssue({
|
|
127
|
+
id: "gate-sds-policy-telemetry-metering-missing-metering",
|
|
128
|
+
message: "SDS is missing a metering/usage section.",
|
|
129
|
+
remediation: "Add metering rules and enforcement details.",
|
|
130
|
+
record: sds,
|
|
131
|
+
metadata: { issueType: "missing_metering" },
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const meteringOk = containsAny(meteringSection.content, [
|
|
136
|
+
/meter/i,
|
|
137
|
+
/usage/i,
|
|
138
|
+
/rate/i,
|
|
139
|
+
/limit/i,
|
|
140
|
+
/enforce/i,
|
|
141
|
+
]);
|
|
142
|
+
if (!meteringOk) {
|
|
143
|
+
issues.push(buildIssue({
|
|
144
|
+
id: "gate-sds-policy-telemetry-metering-incomplete-metering",
|
|
145
|
+
message: "Metering section lacks usage tracking or enforcement rules.",
|
|
146
|
+
remediation: "Describe usage tracking, rate limits, and enforcement actions.",
|
|
147
|
+
record: sds,
|
|
148
|
+
line: meteringSection.line,
|
|
149
|
+
metadata: { issueType: "incomplete_metering" },
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
notes.push(`Unable to read SDS ${sds.path}: ${error.message ?? String(error)}`);
|
|
156
|
+
}
|
|
157
|
+
const status = issues.length === 0 ? "pass" : "fail";
|
|
158
|
+
return {
|
|
159
|
+
gateId: "gate-sds-policy-telemetry-metering",
|
|
160
|
+
gateName: "SDS Policy, Telemetry & Metering",
|
|
161
|
+
status,
|
|
162
|
+
issues,
|
|
163
|
+
notes: notes.length ? notes : undefined,
|
|
164
|
+
metadata: { issueCount: issues.length },
|
|
165
|
+
};
|
|
166
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DocgenArtifactInventory } from "../../DocgenRunContext.js";
|
|
2
|
+
import { ReviewGateResult } from "../ReviewTypes.js";
|
|
3
|
+
export interface SqlRequiredTablesGateInput {
|
|
4
|
+
artifacts: DocgenArtifactInventory;
|
|
5
|
+
}
|
|
6
|
+
export declare const runSqlRequiredTablesGate: (input: SqlRequiredTablesGateInput) => Promise<ReviewGateResult>;
|
|
7
|
+
//# sourceMappingURL=SqlRequiredTablesGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlRequiredTablesGate.d.ts","sourceRoot":"","sources":["../../../../../src/services/docs/review/gates/SqlRequiredTablesGate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAe,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,uBAAuB,CAAC;CACpC;AA8MD,eAAO,MAAM,wBAAwB,GACnC,OAAO,0BAA0B,KAChC,OAAO,CAAC,gBAAgB,CA4H1B,CAAC"}
|