codeloop-mcp-server 0.1.57 → 0.1.60
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/dist/auth/critical_floors.d.ts.map +1 -1
- package/dist/auth/critical_floors.js +4 -0
- package/dist/auth/critical_floors.js.map +1 -1
- package/dist/evidence/backend_verification.d.ts +64 -0
- package/dist/evidence/backend_verification.d.ts.map +1 -0
- package/dist/evidence/backend_verification.js +94 -0
- package/dist/evidence/backend_verification.js.map +1 -0
- package/dist/evidence/deep_internal.d.ts +45 -0
- package/dist/evidence/deep_internal.d.ts.map +1 -0
- package/dist/evidence/deep_internal.js +99 -0
- package/dist/evidence/deep_internal.js.map +1 -0
- package/dist/evidence/runtime_log_scan.d.ts +43 -0
- package/dist/evidence/runtime_log_scan.d.ts.map +1 -0
- package/dist/evidence/runtime_log_scan.js +112 -0
- package/dist/evidence/runtime_log_scan.js.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -1
- package/dist/runners/backend_runtime.d.ts +40 -0
- package/dist/runners/backend_runtime.d.ts.map +1 -0
- package/dist/runners/backend_runtime.js +380 -0
- package/dist/runners/backend_runtime.js.map +1 -0
- package/dist/runners/coverage.d.ts +66 -0
- package/dist/runners/coverage.d.ts.map +1 -0
- package/dist/runners/coverage.js +380 -0
- package/dist/runners/coverage.js.map +1 -0
- package/dist/runners/static_analysis.d.ts +72 -0
- package/dist/runners/static_analysis.d.ts.map +1 -0
- package/dist/runners/static_analysis.js +248 -0
- package/dist/runners/static_analysis.js.map +1 -0
- package/dist/tools/diagnose.d.ts.map +1 -1
- package/dist/tools/diagnose.js +143 -0
- package/dist/tools/diagnose.js.map +1 -1
- package/dist/tools/gate_check.d.ts.map +1 -1
- package/dist/tools/gate_check.js +116 -0
- package/dist/tools/gate_check.js.map +1 -1
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +83 -0
- package/dist/tools/verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CodeLoopConfig } from "@codelooptech/shared";
|
|
2
|
+
import type { BackendVerification } from "../evidence/backend_verification.js";
|
|
3
|
+
/**
|
|
4
|
+
* 0.1.59-0.1.60 Phase 2/3 — backend lifecycle + smoke + contract + schema.
|
|
5
|
+
*
|
|
6
|
+
* Starts the detected/configured backend as a managed subprocess, waits for
|
|
7
|
+
* readiness (health 2xx or a ready_log_pattern), smoke-probes its routes,
|
|
8
|
+
* validates the OpenAPI contract, checks DB migration drift, then GUARANTEES
|
|
9
|
+
* teardown (process-tree kill on macOS/Windows/Linux) in a finally block.
|
|
10
|
+
*
|
|
11
|
+
* Safety policy that keeps this from being a false-positive blocker across
|
|
12
|
+
* "various apps": when the backend was AUTO-detected (not user-configured)
|
|
13
|
+
* and fails to start/ready, we downgrade to `detected: false` (gate n/a)
|
|
14
|
+
* with a note steering the user to set backend.start_command. When the user
|
|
15
|
+
* explicitly configured a start_command, a startup/readiness failure is a
|
|
16
|
+
* real, reportable blocker.
|
|
17
|
+
*/
|
|
18
|
+
interface ResolvedBackend {
|
|
19
|
+
start_command: string;
|
|
20
|
+
base_url: string;
|
|
21
|
+
health_path?: string;
|
|
22
|
+
ready_log_pattern?: string;
|
|
23
|
+
routes: string[];
|
|
24
|
+
env: Record<string, string>;
|
|
25
|
+
openapi_path?: string;
|
|
26
|
+
ready_timeout_ms: number;
|
|
27
|
+
source: "config" | "auto";
|
|
28
|
+
}
|
|
29
|
+
export declare function resolveBackend(cwd: string, config: CodeLoopConfig): ResolvedBackend | null;
|
|
30
|
+
/** Extract GET route paths from an OpenAPI/Swagger JSON document. */
|
|
31
|
+
export declare function extractGetRoutes(openapi: unknown): string[];
|
|
32
|
+
/** Declared status codes for GET on a path, per the OpenAPI doc. */
|
|
33
|
+
export declare function declaredStatusesForGet(openapi: unknown, path: string): number[];
|
|
34
|
+
/**
|
|
35
|
+
* Run the full backend verification. Returns null when no backend is
|
|
36
|
+
* detected/configured (caller writes no evidence -> gates n/a). Never throws.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runBackendVerification(cwd: string, config: CodeLoopConfig, logDir: string): Promise<BackendVerification | null>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=backend_runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_runtime.d.ts","sourceRoot":"","sources":["../../src/runners/backend_runtime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EAAE,mBAAmB,EAAuC,MAAM,qCAAqC,CAAC;AAEpH;;;;;;;;;;;;;;GAcG;AAEH,UAAU,eAAe;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,eAAe,GAAG,IAAI,CA+B1F;AAwGD,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAW3D;AAED,oEAAoE;AACpE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAO/E;AAwID;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAmErC"}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { appendFileSync, mkdirSync, existsSync, readdirSync } from "fs";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { detectBackendConfig } from "@codelooptech/shared/init/detect-backend";
|
|
5
|
+
import { runCommand, checkToolAvailable } from "./base.js";
|
|
6
|
+
export function resolveBackend(cwd, config) {
|
|
7
|
+
const cfg = config.backend;
|
|
8
|
+
if (cfg?.enabled === false)
|
|
9
|
+
return null;
|
|
10
|
+
if (cfg?.start_command) {
|
|
11
|
+
return {
|
|
12
|
+
start_command: cfg.start_command,
|
|
13
|
+
base_url: cfg.base_url ?? "http://localhost:3000",
|
|
14
|
+
health_path: cfg.health_path,
|
|
15
|
+
ready_log_pattern: cfg.ready_log_pattern,
|
|
16
|
+
routes: cfg.routes ?? [],
|
|
17
|
+
env: cfg.env ?? {},
|
|
18
|
+
openapi_path: cfg.openapi_path,
|
|
19
|
+
ready_timeout_ms: (cfg.ready_timeout_seconds ?? 60) * 1000,
|
|
20
|
+
source: "config",
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const detected = detectBackendConfig(cwd);
|
|
24
|
+
if (!detected)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
start_command: detected.start_command,
|
|
28
|
+
base_url: detected.base_url,
|
|
29
|
+
health_path: detected.health_path,
|
|
30
|
+
ready_log_pattern: detected.ready_log_pattern,
|
|
31
|
+
routes: [],
|
|
32
|
+
env: {},
|
|
33
|
+
openapi_path: cfg?.openapi_path,
|
|
34
|
+
ready_timeout_ms: (cfg?.ready_timeout_seconds ?? 60) * 1000,
|
|
35
|
+
source: "auto",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function startServer(rb, cwd, logPath) {
|
|
39
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
40
|
+
let buffer = "";
|
|
41
|
+
let exited = false;
|
|
42
|
+
const readyRe = rb.ready_log_pattern ? new RegExp(rb.ready_log_pattern, "i") : null;
|
|
43
|
+
let matched = false;
|
|
44
|
+
const isWindows = process.platform === "win32";
|
|
45
|
+
const child = spawn(rb.start_command, [], {
|
|
46
|
+
cwd,
|
|
47
|
+
shell: true,
|
|
48
|
+
detached: !isWindows, // posix: own process group so we can kill the tree
|
|
49
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
50
|
+
env: { ...process.env, ...rb.env },
|
|
51
|
+
});
|
|
52
|
+
const onData = (chunk) => {
|
|
53
|
+
const s = chunk.toString("utf-8");
|
|
54
|
+
buffer += s;
|
|
55
|
+
if (buffer.length > 1_000_000)
|
|
56
|
+
buffer = buffer.slice(-500_000);
|
|
57
|
+
try {
|
|
58
|
+
appendFileSync(logPath, s);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
/* best-effort */
|
|
62
|
+
}
|
|
63
|
+
if (readyRe && readyRe.test(buffer))
|
|
64
|
+
matched = true;
|
|
65
|
+
};
|
|
66
|
+
child.stdout?.on("data", onData);
|
|
67
|
+
child.stderr?.on("data", onData);
|
|
68
|
+
child.on("exit", () => {
|
|
69
|
+
exited = true;
|
|
70
|
+
});
|
|
71
|
+
const stop = async () => {
|
|
72
|
+
if (child.pid === undefined)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
if (isWindows) {
|
|
76
|
+
await runCommand("taskkill", ["/pid", String(child.pid), "/T", "/F"], cwd, undefined, undefined, 15000);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
try {
|
|
80
|
+
process.kill(-child.pid, "SIGTERM");
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* group may not exist */
|
|
84
|
+
}
|
|
85
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
86
|
+
try {
|
|
87
|
+
process.kill(-child.pid, "SIGKILL");
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
/* already dead */
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
/* best-effort */
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
return { pid: child.pid, readMatched: () => matched, exited: () => exited, stop };
|
|
99
|
+
}
|
|
100
|
+
async function httpGet(url, timeoutMs = 8000) {
|
|
101
|
+
const f = globalThis.fetch;
|
|
102
|
+
if (!f)
|
|
103
|
+
return null;
|
|
104
|
+
const ctrl = new AbortController();
|
|
105
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
106
|
+
try {
|
|
107
|
+
const res = await f(url, { signal: ctrl.signal, redirect: "manual" });
|
|
108
|
+
const body = await res.text().catch(() => "");
|
|
109
|
+
return { status: res.status, body };
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
clearTimeout(timer);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function waitForReady(rb, server) {
|
|
119
|
+
const deadline = Date.now() + rb.ready_timeout_ms;
|
|
120
|
+
const healthUrl = rb.health_path ? rb.base_url.replace(/\/$/, "") + rb.health_path : null;
|
|
121
|
+
while (Date.now() < deadline) {
|
|
122
|
+
if (server.exited())
|
|
123
|
+
return false;
|
|
124
|
+
if (server.readMatched())
|
|
125
|
+
return true;
|
|
126
|
+
if (healthUrl) {
|
|
127
|
+
const r = await httpGet(healthUrl, 4000);
|
|
128
|
+
if (r && r.status >= 200 && r.status < 300)
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
await new Promise((res) => setTimeout(res, 1000));
|
|
132
|
+
}
|
|
133
|
+
// One last health probe in case ready log never appears but server binds.
|
|
134
|
+
if (healthUrl) {
|
|
135
|
+
const r = await httpGet(healthUrl, 4000);
|
|
136
|
+
if (r && r.status >= 200 && r.status < 300)
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
/** Extract GET route paths from an OpenAPI/Swagger JSON document. */
|
|
142
|
+
export function extractGetRoutes(openapi) {
|
|
143
|
+
const doc = openapi;
|
|
144
|
+
if (!doc?.paths)
|
|
145
|
+
return [];
|
|
146
|
+
const routes = [];
|
|
147
|
+
for (const [path, methods] of Object.entries(doc.paths)) {
|
|
148
|
+
if (methods && typeof methods === "object" && "get" in methods) {
|
|
149
|
+
// Skip templated routes we can't fill (e.g. /users/{id}).
|
|
150
|
+
if (!/\{.*\}/.test(path))
|
|
151
|
+
routes.push(path);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return routes;
|
|
155
|
+
}
|
|
156
|
+
/** Declared status codes for GET on a path, per the OpenAPI doc. */
|
|
157
|
+
export function declaredStatusesForGet(openapi, path) {
|
|
158
|
+
const doc = openapi;
|
|
159
|
+
const responses = doc?.paths?.[path]?.get?.responses;
|
|
160
|
+
if (!responses)
|
|
161
|
+
return [];
|
|
162
|
+
return Object.keys(responses)
|
|
163
|
+
.map((k) => parseInt(k, 10))
|
|
164
|
+
.filter((n) => !Number.isNaN(n));
|
|
165
|
+
}
|
|
166
|
+
async function runSmoke(rb, openapiRoutes) {
|
|
167
|
+
const base = rb.base_url.replace(/\/$/, "");
|
|
168
|
+
const probed = [];
|
|
169
|
+
const seen = new Set();
|
|
170
|
+
const toProbe = [rb.health_path, ...rb.routes, ...openapiRoutes].filter((r) => !!r);
|
|
171
|
+
let healthy = false;
|
|
172
|
+
for (const route of toProbe) {
|
|
173
|
+
if (seen.has(route))
|
|
174
|
+
continue;
|
|
175
|
+
seen.add(route);
|
|
176
|
+
const r = await httpGet(base + (route.startsWith("/") ? route : "/" + route));
|
|
177
|
+
const status = r?.status ?? 0;
|
|
178
|
+
probed.push({ route, status });
|
|
179
|
+
if (route === rb.health_path && status >= 200 && status < 300)
|
|
180
|
+
healthy = true;
|
|
181
|
+
}
|
|
182
|
+
// If no explicit health path, treat readiness (server bound + any 2xx/4xx) as healthy.
|
|
183
|
+
if (!rb.health_path)
|
|
184
|
+
healthy = probed.some((p) => p.status >= 200 && p.status < 500);
|
|
185
|
+
const server_errors = probed.filter((p) => p.status >= 500).length;
|
|
186
|
+
return { healthy, probed, server_errors };
|
|
187
|
+
}
|
|
188
|
+
async function runApiContract(rb) {
|
|
189
|
+
const base = rb.base_url.replace(/\/$/, "");
|
|
190
|
+
const schemaPaths = [rb.openapi_path, "/swagger/v1/swagger.json", "/openapi.json", "/v3/api-docs"].filter((p) => !!p);
|
|
191
|
+
let schema = null;
|
|
192
|
+
let schemaSource = "";
|
|
193
|
+
for (const sp of schemaPaths) {
|
|
194
|
+
const url = sp.startsWith("http") ? sp : base + (sp.startsWith("/") ? sp : "/" + sp);
|
|
195
|
+
const r = await httpGet(url, 6000);
|
|
196
|
+
if (r && r.status >= 200 && r.status < 300 && r.body.trim().startsWith("{")) {
|
|
197
|
+
try {
|
|
198
|
+
schema = JSON.parse(r.body);
|
|
199
|
+
schemaSource = sp;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
/* keep looking */
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!schema) {
|
|
208
|
+
return { applicable: false, checked: 0, violations: 0, details: [] };
|
|
209
|
+
}
|
|
210
|
+
const routes = extractGetRoutes(schema);
|
|
211
|
+
const details = [];
|
|
212
|
+
let violations = 0;
|
|
213
|
+
let checked = 0;
|
|
214
|
+
for (const route of routes.slice(0, 25)) {
|
|
215
|
+
const r = await httpGet(base + route);
|
|
216
|
+
checked += 1;
|
|
217
|
+
const status = r?.status ?? 0;
|
|
218
|
+
const declared = declaredStatusesForGet(schema, route);
|
|
219
|
+
if (status >= 500) {
|
|
220
|
+
violations += 1;
|
|
221
|
+
details.push(`${route} -> ${status} (server error)`);
|
|
222
|
+
}
|
|
223
|
+
else if (declared.length > 0 && !declared.includes(status) && !(status >= 200 && status < 300 && declared.some((d) => d >= 200 && d < 300))) {
|
|
224
|
+
violations += 1;
|
|
225
|
+
details.push(`${route} -> ${status}, not in declared [${declared.join(", ")}]`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return { applicable: routes.length > 0, schema_source: schemaSource, checked, violations, details };
|
|
229
|
+
}
|
|
230
|
+
async function runDbSchema(rb, cwd, config) {
|
|
231
|
+
const dbCfg = config.backend?.db;
|
|
232
|
+
const tool = dbCfg?.tool ?? autoDetectOrm(cwd);
|
|
233
|
+
if (!tool || tool === "none") {
|
|
234
|
+
return { applicable: false, applied: true, drift: false, detail: "No ORM/migration tool detected" };
|
|
235
|
+
}
|
|
236
|
+
// Explicit override wins.
|
|
237
|
+
if (dbCfg?.drift_command) {
|
|
238
|
+
const r = await runCommand(dbCfg.drift_command.split(" ")[0], dbCfg.drift_command.split(" ").slice(1), cwd, undefined, rb.env, 120000);
|
|
239
|
+
const drift = r.exit_code !== 0;
|
|
240
|
+
return { applicable: true, tool, applied: !drift, drift, detail: drift ? r.stdout.slice(0, 400) + r.stderr.slice(0, 200) : "No drift" };
|
|
241
|
+
}
|
|
242
|
+
switch (tool) {
|
|
243
|
+
case "ef": {
|
|
244
|
+
if (!(await checkToolAvailable("dotnet")))
|
|
245
|
+
return { applicable: false, tool, applied: true, drift: false, detail: "dotnet not installed" };
|
|
246
|
+
const r = await runCommand("dotnet", ["ef", "migrations", "has-pending-model-changes"], cwd, undefined, rb.env, 180000);
|
|
247
|
+
// exit 0 => no pending changes; non-zero => drift (or ef not set up).
|
|
248
|
+
const drift = r.exit_code !== 0 && /pending|changes/i.test(r.stdout + r.stderr);
|
|
249
|
+
return { applicable: true, tool, applied: true, drift, detail: drift ? "Pending model changes — add a migration" : "No pending model changes" };
|
|
250
|
+
}
|
|
251
|
+
case "django": {
|
|
252
|
+
if (!(await checkToolAvailable("python")))
|
|
253
|
+
return { applicable: false, tool, applied: true, drift: false, detail: "python not installed" };
|
|
254
|
+
const r = await runCommand("python", ["manage.py", "makemigrations", "--check", "--dry-run"], cwd, undefined, rb.env, 120000);
|
|
255
|
+
const drift = r.exit_code !== 0;
|
|
256
|
+
return { applicable: true, tool, applied: true, drift, detail: drift ? "Missing migrations — run makemigrations" : "Migrations up to date" };
|
|
257
|
+
}
|
|
258
|
+
case "alembic": {
|
|
259
|
+
if (!(await checkToolAvailable("alembic")))
|
|
260
|
+
return { applicable: false, tool, applied: true, drift: false, detail: "alembic not installed" };
|
|
261
|
+
const r = await runCommand("alembic", ["check"], cwd, undefined, rb.env, 120000);
|
|
262
|
+
const drift = r.exit_code !== 0;
|
|
263
|
+
return { applicable: true, tool, applied: true, drift, detail: drift ? "Schema drift — autogenerate a revision" : "No drift" };
|
|
264
|
+
}
|
|
265
|
+
case "prisma": {
|
|
266
|
+
if (!(await checkToolAvailable("npx")))
|
|
267
|
+
return { applicable: false, tool, applied: true, drift: false, detail: "npx not installed" };
|
|
268
|
+
const r = await runCommand("npx", ["--no-install", "prisma", "migrate", "status"], cwd, undefined, rb.env, 120000);
|
|
269
|
+
const drift = /not yet been applied|drift|out of sync/i.test(r.stdout + r.stderr);
|
|
270
|
+
return { applicable: true, tool, applied: !drift, drift, detail: drift ? "Migrations pending / drift detected" : "Database schema up to date" };
|
|
271
|
+
}
|
|
272
|
+
case "rails": {
|
|
273
|
+
const r = await runCommand("bin/rails", ["db:migrate:status"], cwd, undefined, rb.env, 120000);
|
|
274
|
+
const drift = /\bdown\b/i.test(r.stdout);
|
|
275
|
+
return { applicable: true, tool, applied: !drift, drift, detail: drift ? "Pending migrations (status: down)" : "All migrations up" };
|
|
276
|
+
}
|
|
277
|
+
default:
|
|
278
|
+
return { applicable: false, tool, applied: true, drift: false, detail: "Unsupported ORM" };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function autoDetectOrm(cwd) {
|
|
282
|
+
if (existsSync(join(cwd, "manage.py")))
|
|
283
|
+
return "django";
|
|
284
|
+
if (existsSync(join(cwd, "alembic.ini")))
|
|
285
|
+
return "alembic";
|
|
286
|
+
if (existsSync(join(cwd, "prisma", "schema.prisma")) || existsSync(join(cwd, "schema.prisma")))
|
|
287
|
+
return "prisma";
|
|
288
|
+
if (existsSync(join(cwd, "bin", "rails")) || existsSync(join(cwd, "config", "database.yml")))
|
|
289
|
+
return "rails";
|
|
290
|
+
// EF: any .csproj referencing Microsoft.EntityFrameworkCore, or a Migrations/ dir.
|
|
291
|
+
try {
|
|
292
|
+
const hasMigrations = (dir) => {
|
|
293
|
+
try {
|
|
294
|
+
return readdirSync(dir).some((f) => f === "Migrations") || readdirSync(dir).some((f) => /DbContext\.cs$/i.test(f));
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
if (hasMigrations(cwd) || (existsSync(join(cwd, "src")) && hasMigrations(join(cwd, "src"))))
|
|
301
|
+
return "ef";
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
/* ignore */
|
|
305
|
+
}
|
|
306
|
+
return "none";
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Run the full backend verification. Returns null when no backend is
|
|
310
|
+
* detected/configured (caller writes no evidence -> gates n/a). Never throws.
|
|
311
|
+
*/
|
|
312
|
+
export async function runBackendVerification(cwd, config, logDir) {
|
|
313
|
+
const rb = resolveBackend(cwd, config);
|
|
314
|
+
if (!rb)
|
|
315
|
+
return null;
|
|
316
|
+
const backendLog = join(logDir, "backend.log");
|
|
317
|
+
const base = {
|
|
318
|
+
generated_at: new Date().toISOString(),
|
|
319
|
+
detected: true,
|
|
320
|
+
start_command: rb.start_command,
|
|
321
|
+
base_url: rb.base_url,
|
|
322
|
+
started: false,
|
|
323
|
+
ready: false,
|
|
324
|
+
};
|
|
325
|
+
let server = null;
|
|
326
|
+
try {
|
|
327
|
+
server = startServer(rb, cwd, backendLog);
|
|
328
|
+
base.started = server.pid !== undefined && !server.exited();
|
|
329
|
+
const ready = await waitForReady(rb, server);
|
|
330
|
+
base.ready = ready;
|
|
331
|
+
if (!ready) {
|
|
332
|
+
// Auto-detected start that never bound is most likely a wrong guess —
|
|
333
|
+
// downgrade to n/a so we don't false-block. Config-specified failures
|
|
334
|
+
// are real and stay as a blocker.
|
|
335
|
+
if (rb.source === "auto") {
|
|
336
|
+
base.detected = false;
|
|
337
|
+
base.reason =
|
|
338
|
+
"Auto-detected backend did not become ready — set backend.start_command / base_url / health_path in .codeloop/config.json to enable backend verification.";
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
base.reason = `Server did not become ready within ${Math.round(rb.ready_timeout_ms / 1000)}s (health_path=${rb.health_path ?? "none"}, ready_log_pattern=${rb.ready_log_pattern ?? "none"}).`;
|
|
342
|
+
}
|
|
343
|
+
return base;
|
|
344
|
+
}
|
|
345
|
+
// Fetch OpenAPI routes first so smoke can probe them too.
|
|
346
|
+
const contract = await runApiContract(rb);
|
|
347
|
+
let openapiRoutes = [];
|
|
348
|
+
if (contract.applicable) {
|
|
349
|
+
// Re-derive routes for smoke from the same schema fetch path.
|
|
350
|
+
const schemaUrl = (rb.openapi_path ?? "/swagger/v1/swagger.json").startsWith("http")
|
|
351
|
+
? rb.openapi_path
|
|
352
|
+
: rb.base_url.replace(/\/$/, "") + (contract.schema_source?.startsWith("/") ? contract.schema_source : "/" + (contract.schema_source ?? ""));
|
|
353
|
+
const r = await httpGet(schemaUrl, 6000);
|
|
354
|
+
if (r && r.body.trim().startsWith("{")) {
|
|
355
|
+
try {
|
|
356
|
+
openapiRoutes = extractGetRoutes(JSON.parse(r.body)).slice(0, 15);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
/* ignore */
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
base.smoke = await runSmoke(rb, openapiRoutes);
|
|
364
|
+
base.api_contract = contract;
|
|
365
|
+
base.db_schema = await runDbSchema(rb, cwd, config);
|
|
366
|
+
return base;
|
|
367
|
+
}
|
|
368
|
+
catch (e) {
|
|
369
|
+
base.reason = `Backend verification error: ${e.message}`;
|
|
370
|
+
// An internal error in our runner shouldn't false-block; downgrade.
|
|
371
|
+
if (rb.source === "auto")
|
|
372
|
+
base.detected = false;
|
|
373
|
+
return base;
|
|
374
|
+
}
|
|
375
|
+
finally {
|
|
376
|
+
if (server)
|
|
377
|
+
await server.stop();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
//# sourceMappingURL=backend_runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_runtime.js","sourceRoot":"","sources":["../../src/runners/backend_runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.1.58 Phase 1 — Deep internal verification: code coverage.
|
|
3
|
+
*
|
|
4
|
+
* Ties coverage to the DIFF rather than the whole repo: the
|
|
5
|
+
* `code_coverage_threshold` gate scores how many of THIS cycle's changed
|
|
6
|
+
* source lines are exercised by the test suite. A repo at 12% overall
|
|
7
|
+
* coverage can still ship a well-tested change; a repo at 95% overall can
|
|
8
|
+
* still ship an untested new function. Changed-line coverage is the honest
|
|
9
|
+
* signal for "did you test what you just wrote".
|
|
10
|
+
*
|
|
11
|
+
* Strategy:
|
|
12
|
+
* 1. Find an existing coverage report (lcov / cobertura / coverage-final.json)
|
|
13
|
+
* under the conventional locations; OR generate one with a per-stack
|
|
14
|
+
* command when the tool + config indicate support.
|
|
15
|
+
* 2. Determine the changed (added) source lines via `git diff` against the
|
|
16
|
+
* verified SHA (falls back to HEAD), scoped to the manifest's changed
|
|
17
|
+
* files.
|
|
18
|
+
* 3. Intersect: of the changed source lines, how many are covered.
|
|
19
|
+
*
|
|
20
|
+
* Applicable-or-n/a: if no coverage report can be found or generated, or if
|
|
21
|
+
* there are no changed source lines to score, the result is
|
|
22
|
+
* `applicable: false` and the gate passes as n/a.
|
|
23
|
+
*/
|
|
24
|
+
export interface ChangedLineCoverage {
|
|
25
|
+
applicable: boolean;
|
|
26
|
+
covered: number;
|
|
27
|
+
total: number;
|
|
28
|
+
pct: number;
|
|
29
|
+
uncovered_files: Array<{
|
|
30
|
+
file: string;
|
|
31
|
+
uncovered_lines: number[];
|
|
32
|
+
}>;
|
|
33
|
+
reason?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface CoverageResult {
|
|
36
|
+
applicable: boolean;
|
|
37
|
+
tool: string;
|
|
38
|
+
report_path?: string;
|
|
39
|
+
overall_pct?: number;
|
|
40
|
+
changed_line_coverage: ChangedLineCoverage;
|
|
41
|
+
reason?: string;
|
|
42
|
+
}
|
|
43
|
+
/** file path -> (line number -> hit count). */
|
|
44
|
+
export type CoverageMap = Record<string, Record<number, number>>;
|
|
45
|
+
/** Parse an lcov.info file into a CoverageMap. */
|
|
46
|
+
export declare function parseLcov(text: string): CoverageMap;
|
|
47
|
+
/** Parse a Cobertura XML coverage report into a CoverageMap. */
|
|
48
|
+
export declare function parseCobertura(xml: string): CoverageMap;
|
|
49
|
+
/**
|
|
50
|
+
* Parse a unified `git diff` into added line numbers per file (new-file
|
|
51
|
+
* line numbering). Only `+` lines that are not the `+++` header are counted.
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseGitDiffAddedLines(diff: string): Record<string, number[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Compute changed-line coverage by intersecting added source lines with the
|
|
56
|
+
* coverage map. Files with no coverage entry are counted as fully UNcovered
|
|
57
|
+
* (their added lines are all uncovered) ONLY when at least one changed file
|
|
58
|
+
* IS present in the coverage map — otherwise the report is for a different
|
|
59
|
+
* stack and we treat coverage as not-applicable.
|
|
60
|
+
*/
|
|
61
|
+
export declare function computeChangedLineCoverage(coverage: CoverageMap, addedLines: Record<string, number[]>, opts?: {
|
|
62
|
+
sourceExt?: RegExp;
|
|
63
|
+
exclude?: RegExp;
|
|
64
|
+
}): ChangedLineCoverage;
|
|
65
|
+
export declare function runCoverage(cwd: string, logDir: string, verifiedSha: string | null): Promise<CoverageResult>;
|
|
66
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/runners/coverage.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,mBAAmB,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAIjE,kDAAkD;AAClD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAqBnD;AAED,gEAAgE;AAChE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAkBvD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAkC7E;AAwBD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACpC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,mBAAmB,CA6DrB;AA8JD,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,cAAc,CAAC,CA2CzB"}
|