codeloop-mcp-server 0.1.57 → 0.1.61
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 +8 -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 +399 -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 +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"critical_floors.d.ts","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"critical_floors.d.ts","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAqE1C,CAAC"}
|
|
@@ -88,5 +88,13 @@ export const CRITICAL_FLOORS = [
|
|
|
88
88
|
min_version: "0.1.57",
|
|
89
89
|
reason: "Stuck external modal was never AUTO-closed — 0.1.54/0.1.55 only DETECTED stuck modals and DIRECTED the agent to close them; the close itself was always agent-driven. Photometry-DB E2E #12 ran on 0.1.55 and STILL left an external folder picker ('Select Folder') open and reopening, with zero cycle issues recorded, because three gaps remained: (a) detectWindowsModal required the app-name filter — but a file picker is a separate top-level window titled 'Select Folder' / 'Browse For Folder' / 'Save As' that never embeds the host app name, so detection silently missed it; (b) the F1 click-effect probe only ran after a SUCCESSFUL clicky/escape action — once the picker blocked the app, follow-up clicks failed (success=false) or the agent switched to wait / capture_screenshot / win_ui_automate, so the persistence counter never climbed past 1 and no cycle issue was written; (c) closing was entirely agent-driven and the agent rationalised the picker as a 'test artifact', so nothing closed it. 0.1.57 ships H1 (file-dialog detection matches on a strong title pattern — Select Folder / Browse For Folder / Save As / Open / Export / Choose … folder — WITHOUT the app-name filter, plus broadened dialog class names), H2 (codeloop_interact runs the modal probe on the wider modal-related action set REGARDLESS of success, throttled per recording so PowerShell cost stays bounded — a blocked/failed click is now itself the signal), H3 (when a file_dialog persists across 3+ consecutive detections, CodeLoop AUTOMATICALLY runs the multi-strategy close ladder in-flight instead of only nudging the agent; auto-closes are recorded as auto_resolved cycle issues that stay visible in the dev report but don't block the gate, while a failed ladder records an unresolved modal_close_failed + escalates the directive to codeloop_kill_modal_window; opt out with CODELOOP_AUTO_CLOSE_STUCK_MODALS=0), and H4 (codeloop_stop_recording sweeps for a lingering file dialog and auto-closes it so it does not sit open on the user's desktop after the cycle).",
|
|
90
90
|
},
|
|
91
|
+
{
|
|
92
|
+
min_version: "0.1.60",
|
|
93
|
+
reason: "Deep internal verification (code + backend + terminal) — pre-0.1.60 CodeLoop was almost entirely an EXTERNAL UI/UX checker: the only internal checks were build_passes, required_tests_pass, zero_critical_issues and (Flutter-only) `flutter analyze`; the Node runner literally just ran `npm test`. Type errors that the build tolerated, lint errors, untested changed lines, backend 500s, schema drift, broken API contracts, and runtime stack traces logged behind a 200 OK all reached ready_for_review unchallenged. 0.1.60 adds a deep INTERNAL verification layer as six applicable-or-n/a blocker gates that activate only when relevant to the stack (a missing analyzer / backend / ORM yields n/a, never a false-positive fail): static_analysis_passes (tsc / eslint / ruff / mypy / cargo clippy / dotnet format / flutter analyze — errors block, warnings don't), code_coverage_threshold (changed-LINE coverage scored against THIS cycle's git diff via lcov/cobertura, default 70%), backend_smoke_evidence (auto-detect + start the server as a managed subprocess with guaranteed teardown, wait for health 2xx / ready-log, probe routes, block on any 5xx), api_contract_evidence (validate probed routes against the OpenAPI/Swagger schema), db_schema_evidence (EF / Django / Alembic / Prisma / Rails migration-drift check), and runtime_log_clean_evidence (scan the backend/app/console logs for unhandled exceptions / fatal lines / 5xx even when the HTTP response was 2xx). codeloop_init_project now auto-detects + writes the `backend` config block (ASP.NET / Express / Nest / FastAPI / Django / Flask / Rails / Spring), codeloop_diagnose gains evidence-driven classifiers (typecheck_error / lint_error / coverage_gap / backend_5xx / runtime_exception / db_schema_drift / api_contract_violation), and codeloop_generate_dev_report documents the new evidence. Works across macOS / Windows / Linux and Cursor / Claude Code.",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
min_version: "0.1.61",
|
|
97
|
+
reason: "0.1.60 could CRASH THE ENTIRE MCP SERVER on a warm npx cache — backend_runtime.js (new in 0.1.60) statically imported @codelooptech/shared/init/detect-backend, a submodule first shipped in shared@0.1.30, but both codeloop-mcp-server and codeloop only pinned `@codelooptech/shared: ^0.1.22`. So npx could pair mcp-server 0.1.60 with an OLDER cached shared (0.1.22–0.1.29) that lacks detect-backend.js, and the static import threw ERR_MODULE_NOT_FOUND at module-load time, taking down index -> verify -> backend_runtime before any tool could run (the same class of stale-cache skew the 0.1.53 floor first patched for rules-version.js, reintroduced when the dep floor wasn't raised alongside the new submodule). 0.1.61 fixes it durably two ways: (1) raises the @codelooptech/shared dependency floor to ^0.1.30 in BOTH codeloop-mcp-server and codeloop so a fresh resolve can never pick a shared missing the file, and (2) makes detect-backend a LAZY, GUARDED dynamic import — if the submodule can't be loaded for any reason, backend auto-detection degrades to n/a (backend gates skip) instead of crashing the server, so no future shared-submodule addition can ever hard-crash CodeLoop again. Users on a broken 0.1.60 install must clear the npx cache (delete %LocalAppData%/npm-cache/_npx on Windows or ~/.npm/_npx on macOS/Linux, or run `npx clear-npx-cache`) and relaunch so npx fetches 0.1.61.",
|
|
98
|
+
},
|
|
91
99
|
];
|
|
92
100
|
//# sourceMappingURL=critical_floors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"critical_floors.js","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,ufAAuf;KAC1f;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,4hBAA4hB;KACriB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,yvBAAyvB;KAClwB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,kxBAAkxB;KACrxB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,0/BAA0/B;KAC7/B;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,0iCAA0iC;KAC7iC;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,gqDAAgqD;KACnqD;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,uqDAAuqD;KAC1qD;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,w+EAAw+E;KAC3+E;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,88EAA88E;KACj9E;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,uiEAAuiE;KAC1iE;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,u/DAAu/D;KAC1/D;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"critical_floors.js","sourceRoot":"","sources":["../../src/auth/critical_floors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,ufAAuf;KAC1f;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,4hBAA4hB;KACriB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EAAE,yvBAAyvB;KAClwB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,kxBAAkxB;KACrxB;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,0/BAA0/B;KAC7/B;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,0iCAA0iC;KAC7iC;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,gqDAAgqD;KACnqD;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,uqDAAuqD;KAC1qD;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,w+EAAw+E;KAC3+E;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,88EAA88E;KACj9E;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,uiEAAuiE;KAC1iE;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,u/DAAu/D;KAC1/D;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,k3DAAk3D;KACr3D;IACD;QACE,WAAW,EAAE,QAAQ;QACrB,MAAM,EACJ,g3CAAg3C;KACn3C;CACF,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.1.59-0.1.60 Phase 2/3 — backend_verification.json evidence + gate
|
|
3
|
+
* verdicts for `backend_smoke_evidence`, `api_contract_evidence`, and
|
|
4
|
+
* `db_schema_evidence`.
|
|
5
|
+
*
|
|
6
|
+
* Written by the backend_runtime runner during codeloop_verify (when a
|
|
7
|
+
* backend is detected/configured) and consumed by gate_check. All verdicts
|
|
8
|
+
* are pure functions over the evidence so they're unit-tested without a live
|
|
9
|
+
* server. Applicable-or-n/a: a missing file or `detected: false` yields a
|
|
10
|
+
* PASS — the gates only block when a backend actually ran and misbehaved.
|
|
11
|
+
*/
|
|
12
|
+
export interface BackendSmoke {
|
|
13
|
+
/** Health endpoint returned 2xx OR readiness confirmed via log pattern. */
|
|
14
|
+
healthy: boolean;
|
|
15
|
+
/** Each probed GET route and its HTTP status. */
|
|
16
|
+
probed: Array<{
|
|
17
|
+
route: string;
|
|
18
|
+
status: number;
|
|
19
|
+
}>;
|
|
20
|
+
/** Count of 5xx responses across probed routes. */
|
|
21
|
+
server_errors: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ApiContract {
|
|
24
|
+
applicable: boolean;
|
|
25
|
+
schema_source?: string;
|
|
26
|
+
checked: number;
|
|
27
|
+
violations: number;
|
|
28
|
+
details: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface DbSchema {
|
|
31
|
+
applicable: boolean;
|
|
32
|
+
tool?: string;
|
|
33
|
+
/** Migrations applied cleanly to the test/throwaway DB. */
|
|
34
|
+
applied: boolean;
|
|
35
|
+
/** Model-vs-migration drift detected (pending model changes). */
|
|
36
|
+
drift: boolean;
|
|
37
|
+
detail: string;
|
|
38
|
+
}
|
|
39
|
+
export interface BackendVerification {
|
|
40
|
+
generated_at: string;
|
|
41
|
+
/** A backend was detected or configured. */
|
|
42
|
+
detected: boolean;
|
|
43
|
+
start_command?: string;
|
|
44
|
+
base_url?: string;
|
|
45
|
+
/** Server process started. */
|
|
46
|
+
started: boolean;
|
|
47
|
+
/** Server became ready (health 2xx or ready_log_pattern matched). */
|
|
48
|
+
ready: boolean;
|
|
49
|
+
smoke?: BackendSmoke;
|
|
50
|
+
api_contract?: ApiContract;
|
|
51
|
+
db_schema?: DbSchema;
|
|
52
|
+
/** Human-readable note (skip reason or failure detail). */
|
|
53
|
+
reason?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function writeBackendVerification(runDir: string, ev: BackendVerification): void;
|
|
56
|
+
export declare function loadBackendVerification(runDir: string): BackendVerification | null;
|
|
57
|
+
export interface GateVerdict {
|
|
58
|
+
passed: boolean;
|
|
59
|
+
reason: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function evaluateBackendSmokeGate(b: BackendVerification | null): GateVerdict;
|
|
62
|
+
export declare function evaluateApiContractGate(b: BackendVerification | null): GateVerdict;
|
|
63
|
+
export declare function evaluateDbSchemaGate(b: BackendVerification | null): GateVerdict;
|
|
64
|
+
//# sourceMappingURL=backend_verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_verification.d.ts","sourceRoot":"","sources":["../../src/evidence/backend_verification.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,mBAAmB,GAAG,IAAI,CAOtF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAQlF;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,WAAW,CA4BnF;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,WAAW,CAYlF;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,WAAW,CAkB/E"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
const FILE = "backend_verification.json";
|
|
4
|
+
export function writeBackendVerification(runDir, ev) {
|
|
5
|
+
try {
|
|
6
|
+
mkdirSync(runDir, { recursive: true });
|
|
7
|
+
writeFileSync(join(runDir, FILE), JSON.stringify(ev, null, 2), "utf-8");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
/* best-effort */
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function loadBackendVerification(runDir) {
|
|
14
|
+
const p = join(runDir, FILE);
|
|
15
|
+
if (!existsSync(p))
|
|
16
|
+
return null;
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function evaluateBackendSmokeGate(b) {
|
|
25
|
+
if (!b)
|
|
26
|
+
return { passed: true, reason: "No backend_verification.json (no backend run this cycle)" };
|
|
27
|
+
if (!b.detected)
|
|
28
|
+
return { passed: true, reason: "n/a — no backend detected/configured" };
|
|
29
|
+
if (!b.started) {
|
|
30
|
+
return {
|
|
31
|
+
passed: false,
|
|
32
|
+
reason: `Backend failed to start (${b.reason ?? "start_command exited / never spawned"}). Fix the start command or set backend.start_command in .codeloop/config.json, then re-run codeloop_verify.`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (!b.ready) {
|
|
36
|
+
return {
|
|
37
|
+
passed: false,
|
|
38
|
+
reason: `Backend started but never became ready (${b.reason ?? "no health 2xx / ready_log_pattern within timeout"}). Verify backend.health_path / backend.ready_log_pattern, then re-run codeloop_verify.`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const smoke = b.smoke;
|
|
42
|
+
if (!smoke)
|
|
43
|
+
return { passed: true, reason: "n/a — backend ready but no routes probed" };
|
|
44
|
+
if (!smoke.healthy) {
|
|
45
|
+
return { passed: false, reason: "Backend health check did not return 2xx. Inspect the backend log under the run's logs/backend.log." };
|
|
46
|
+
}
|
|
47
|
+
if (smoke.server_errors > 0) {
|
|
48
|
+
const bad = smoke.probed.filter((p) => p.status >= 500).map((p) => `${p.route} -> ${p.status}`);
|
|
49
|
+
return {
|
|
50
|
+
passed: false,
|
|
51
|
+
reason: `${smoke.server_errors} route(s) returned 5xx: ${bad.join(", ")}. Read logs/backend.log for the stack trace, fix the handler, then re-run codeloop_verify.`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return { passed: true, reason: `Backend healthy; ${smoke.probed.length} route(s) probed, 0 server errors` };
|
|
55
|
+
}
|
|
56
|
+
export function evaluateApiContractGate(b) {
|
|
57
|
+
if (!b)
|
|
58
|
+
return { passed: true, reason: "No backend_verification.json (no backend run this cycle)" };
|
|
59
|
+
if (!b.detected)
|
|
60
|
+
return { passed: true, reason: "n/a — no backend detected/configured" };
|
|
61
|
+
const c = b.api_contract;
|
|
62
|
+
if (!c || !c.applicable)
|
|
63
|
+
return { passed: true, reason: "n/a — no OpenAPI schema / declared routes to validate" };
|
|
64
|
+
if (c.violations > 0) {
|
|
65
|
+
return {
|
|
66
|
+
passed: false,
|
|
67
|
+
reason: `${c.violations} API-contract violation(s) against ${c.schema_source ?? "schema"}: ${c.details.slice(0, 4).join("; ")}. Align the handlers with the schema (or update the schema), then re-run codeloop_verify.`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return { passed: true, reason: `API contract OK — ${c.checked} route(s) conform to ${c.schema_source ?? "schema"}` };
|
|
71
|
+
}
|
|
72
|
+
export function evaluateDbSchemaGate(b) {
|
|
73
|
+
if (!b)
|
|
74
|
+
return { passed: true, reason: "No backend_verification.json (no backend run this cycle)" };
|
|
75
|
+
if (!b.detected)
|
|
76
|
+
return { passed: true, reason: "n/a — no backend detected/configured" };
|
|
77
|
+
const d = b.db_schema;
|
|
78
|
+
if (!d || !d.applicable)
|
|
79
|
+
return { passed: true, reason: "n/a — no ORM / migration tool detected" };
|
|
80
|
+
if (d.drift) {
|
|
81
|
+
return {
|
|
82
|
+
passed: false,
|
|
83
|
+
reason: `Model-vs-migration drift detected via ${d.tool ?? "migration tool"}: ${d.detail}. Generate the pending migration (e.g. \`dotnet ef migrations add\`, \`makemigrations\`, \`alembic revision --autogenerate\`, \`prisma migrate dev\`), then re-run codeloop_verify.`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (!d.applied) {
|
|
87
|
+
return {
|
|
88
|
+
passed: false,
|
|
89
|
+
reason: `Migrations failed to apply via ${d.tool ?? "migration tool"}: ${d.detail}. Fix the failing migration, then re-run codeloop_verify.`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return { passed: true, reason: `DB schema OK via ${d.tool ?? "migration tool"} — migrations apply, no drift` };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=backend_verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend_verification.js","sourceRoot":"","sources":["../../src/evidence/backend_verification.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StaticAnalysisResult } from "../runners/static_analysis.js";
|
|
2
|
+
import type { CoverageResult } from "../runners/coverage.js";
|
|
3
|
+
/**
|
|
4
|
+
* 0.1.58 Phase 1 — code_quality.json evidence + gate verdicts.
|
|
5
|
+
*
|
|
6
|
+
* Written by codeloop_verify into <run>/code_quality.json and consumed by
|
|
7
|
+
* the `static_analysis_passes` and `code_coverage_threshold` blocker gates.
|
|
8
|
+
* Gate verdicts are pure functions over the evidence so they're unit-tested
|
|
9
|
+
* without needing the analyzers installed.
|
|
10
|
+
*
|
|
11
|
+
* Applicable-or-n/a contract: a missing file, or `applicable: false`
|
|
12
|
+
* evidence, yields a PASS with an "n/a" reason — the gate only blocks when
|
|
13
|
+
* its check actually ran and found errors / a coverage gap.
|
|
14
|
+
*/
|
|
15
|
+
export interface CodeQualityEvidence {
|
|
16
|
+
generated_at: string;
|
|
17
|
+
static_analysis: StaticAnalysisResult;
|
|
18
|
+
coverage: CoverageResult;
|
|
19
|
+
}
|
|
20
|
+
export declare function writeCodeQualityEvidence(runDir: string, evidence: CodeQualityEvidence): void;
|
|
21
|
+
export declare function loadCodeQualityEvidence(runDir: string): CodeQualityEvidence | null;
|
|
22
|
+
export interface GateVerdict {
|
|
23
|
+
passed: boolean;
|
|
24
|
+
reason: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* static_analysis_passes — typecheck/lint ERRORS must be zero.
|
|
28
|
+
* - No evidence file (legacy run / verify didn't write one) -> pass.
|
|
29
|
+
* - Not applicable (no analyzer ran) -> pass (n/a).
|
|
30
|
+
* - total_errors > 0 -> fail (blocker).
|
|
31
|
+
*/
|
|
32
|
+
export declare function evaluateStaticAnalysisGate(evidence: CodeQualityEvidence | null): GateVerdict;
|
|
33
|
+
/**
|
|
34
|
+
* code_coverage_threshold — changed-line coverage must meet the threshold.
|
|
35
|
+
* - No evidence / coverage not applicable -> pass (n/a).
|
|
36
|
+
* - changed_line_coverage not applicable (no changed source lines / no
|
|
37
|
+
* matching report) -> pass (n/a).
|
|
38
|
+
* - pct < threshold -> fail (blocker).
|
|
39
|
+
*/
|
|
40
|
+
export declare function evaluateCoverageGate(evidence: CodeQualityEvidence | null, threshold: number): GateVerdict;
|
|
41
|
+
/** Default changed-line coverage threshold when config does not override. */
|
|
42
|
+
export declare const DEFAULT_CHANGED_LINE_COVERAGE_MIN = 0.7;
|
|
43
|
+
/** Resolve the coverage threshold from config (clamped to [0,1]). */
|
|
44
|
+
export declare function resolveCoverageThreshold(config: unknown): number;
|
|
45
|
+
//# sourceMappingURL=deep_internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep_internal.d.ts","sourceRoot":"","sources":["../../src/evidence/deep_internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,oBAAoB,CAAC;IACtC,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAID,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAO5F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAQlF;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,GAAG,WAAW,CAqB5F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,EACpC,SAAS,EAAE,MAAM,GAChB,WAAW,CA8Bb;AAED,6EAA6E;AAC7E,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAErD,qEAAqE;AACrE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAKhE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
const CODE_QUALITY_FILE = "code_quality.json";
|
|
4
|
+
export function writeCodeQualityEvidence(runDir, evidence) {
|
|
5
|
+
try {
|
|
6
|
+
mkdirSync(runDir, { recursive: true });
|
|
7
|
+
writeFileSync(join(runDir, CODE_QUALITY_FILE), JSON.stringify(evidence, null, 2), "utf-8");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
/* best-effort — never throw out of verify */
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function loadCodeQualityEvidence(runDir) {
|
|
14
|
+
const p = join(runDir, CODE_QUALITY_FILE);
|
|
15
|
+
if (!existsSync(p))
|
|
16
|
+
return null;
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* static_analysis_passes — typecheck/lint ERRORS must be zero.
|
|
26
|
+
* - No evidence file (legacy run / verify didn't write one) -> pass.
|
|
27
|
+
* - Not applicable (no analyzer ran) -> pass (n/a).
|
|
28
|
+
* - total_errors > 0 -> fail (blocker).
|
|
29
|
+
*/
|
|
30
|
+
export function evaluateStaticAnalysisGate(evidence) {
|
|
31
|
+
if (!evidence) {
|
|
32
|
+
return { passed: true, reason: "No code_quality.json (run codeloop_verify to populate static analysis)" };
|
|
33
|
+
}
|
|
34
|
+
const sa = evidence.static_analysis;
|
|
35
|
+
if (!sa || !sa.applicable) {
|
|
36
|
+
return { passed: true, reason: "n/a — no static analyzer applies to this project (no tsconfig/eslint/ruff/mypy/clippy/dotnet/flutter)" };
|
|
37
|
+
}
|
|
38
|
+
const ran = sa.checks.filter((c) => c.available).map((c) => c.tool);
|
|
39
|
+
if (sa.total_errors === 0) {
|
|
40
|
+
const warn = sa.total_warnings > 0 ? ` (${sa.total_warnings} warning(s) — non-blocking)` : "";
|
|
41
|
+
return { passed: true, reason: `Static analysis clean across [${ran.join(", ")}]${warn}` };
|
|
42
|
+
}
|
|
43
|
+
const breakdown = sa.checks
|
|
44
|
+
.filter((c) => c.available && c.errors > 0)
|
|
45
|
+
.map((c) => `${c.tool}: ${c.errors} error(s)`)
|
|
46
|
+
.join(", ");
|
|
47
|
+
return {
|
|
48
|
+
passed: false,
|
|
49
|
+
reason: `${sa.total_errors} static-analysis error(s): ${breakdown}. Read the per-tool logs under the run's logs/ dir, fix the errors, then re-run codeloop_verify.`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* code_coverage_threshold — changed-line coverage must meet the threshold.
|
|
54
|
+
* - No evidence / coverage not applicable -> pass (n/a).
|
|
55
|
+
* - changed_line_coverage not applicable (no changed source lines / no
|
|
56
|
+
* matching report) -> pass (n/a).
|
|
57
|
+
* - pct < threshold -> fail (blocker).
|
|
58
|
+
*/
|
|
59
|
+
export function evaluateCoverageGate(evidence, threshold) {
|
|
60
|
+
if (!evidence) {
|
|
61
|
+
return { passed: true, reason: "No code_quality.json (run codeloop_verify to populate coverage)" };
|
|
62
|
+
}
|
|
63
|
+
const cov = evidence.coverage;
|
|
64
|
+
if (!cov || !cov.applicable) {
|
|
65
|
+
return { passed: true, reason: `n/a — ${cov?.reason ?? "no coverage report available"}` };
|
|
66
|
+
}
|
|
67
|
+
const cl = cov.changed_line_coverage;
|
|
68
|
+
if (!cl || !cl.applicable) {
|
|
69
|
+
return { passed: true, reason: `n/a — ${cl?.reason ?? "no changed source lines to score"}` };
|
|
70
|
+
}
|
|
71
|
+
const pct = cl.pct;
|
|
72
|
+
if (pct >= threshold) {
|
|
73
|
+
return {
|
|
74
|
+
passed: true,
|
|
75
|
+
reason: `Changed-line coverage ${(pct * 100).toFixed(1)}% (${cl.covered}/${cl.total}) >= ${(threshold * 100).toFixed(0)}% threshold`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const sample = cl.uncovered_files
|
|
79
|
+
.slice(0, 3)
|
|
80
|
+
.map((u) => `${u.file} (lines ${u.uncovered_lines.slice(0, 6).join(", ")}${u.uncovered_lines.length > 6 ? "…" : ""})`)
|
|
81
|
+
.join("; ");
|
|
82
|
+
return {
|
|
83
|
+
passed: false,
|
|
84
|
+
reason: `Changed-line coverage ${(pct * 100).toFixed(1)}% (${cl.covered}/${cl.total}) is BELOW the ${(threshold * 100).toFixed(0)}% threshold. ` +
|
|
85
|
+
`Add tests covering the changed lines you just wrote: ${sample}. ` +
|
|
86
|
+
`Then re-run codeloop_verify. (Lower the bar per-project via .codeloop/config.json code_quality.changed_line_coverage_min if intentional.)`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** Default changed-line coverage threshold when config does not override. */
|
|
90
|
+
export const DEFAULT_CHANGED_LINE_COVERAGE_MIN = 0.7;
|
|
91
|
+
/** Resolve the coverage threshold from config (clamped to [0,1]). */
|
|
92
|
+
export function resolveCoverageThreshold(config) {
|
|
93
|
+
const cq = config?.code_quality;
|
|
94
|
+
const raw = cq?.changed_line_coverage_min;
|
|
95
|
+
if (typeof raw === "number" && raw >= 0 && raw <= 1)
|
|
96
|
+
return raw;
|
|
97
|
+
return DEFAULT_CHANGED_LINE_COVERAGE_MIN;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=deep_internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep_internal.js","sourceRoot":"","sources":["../../src/evidence/deep_internal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.1.59 Phase 2 — runtime_log_scan.json evidence + the
|
|
3
|
+
* `runtime_log_clean_evidence` gate verdict.
|
|
4
|
+
*
|
|
5
|
+
* Unifies error-scanning across ALL captured logs of a cycle: the backend
|
|
6
|
+
* stdout/stderr, build/test logs, the app runtime log (app_logger), and the
|
|
7
|
+
* browser console. The previous design only surfaced 5xx via smoke; a
|
|
8
|
+
* handler that swallows an exception and returns 200 while logging a stack
|
|
9
|
+
* trace was invisible. This gate makes "the logs are clean" a hard blocker.
|
|
10
|
+
*
|
|
11
|
+
* Applicable-or-n/a: when no logs were captured the gate passes as n/a.
|
|
12
|
+
*/
|
|
13
|
+
export interface LogSourceScan {
|
|
14
|
+
source: string;
|
|
15
|
+
path: string;
|
|
16
|
+
error_count: number;
|
|
17
|
+
/** Up to a few sample offending lines for the agent. */
|
|
18
|
+
samples: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface RuntimeLogScan {
|
|
21
|
+
generated_at: string;
|
|
22
|
+
applicable: boolean;
|
|
23
|
+
sources: LogSourceScan[];
|
|
24
|
+
error_count: number;
|
|
25
|
+
}
|
|
26
|
+
/** Scan a blob of log text and return offending lines. */
|
|
27
|
+
export declare function scanLogText(text: string): string[];
|
|
28
|
+
export declare function writeRuntimeLogScan(runDir: string, ev: RuntimeLogScan): void;
|
|
29
|
+
export declare function loadRuntimeLogScan(runDir: string): RuntimeLogScan | null;
|
|
30
|
+
/**
|
|
31
|
+
* Build a RuntimeLogScan by scanning a set of log files. Each entry is
|
|
32
|
+
* { source, path }. Missing files are skipped silently.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildRuntimeLogScan(logs: Array<{
|
|
35
|
+
source: string;
|
|
36
|
+
path: string;
|
|
37
|
+
}>): RuntimeLogScan;
|
|
38
|
+
export interface GateVerdict {
|
|
39
|
+
passed: boolean;
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function evaluateRuntimeLogGate(s: RuntimeLogScan | null): GateVerdict;
|
|
43
|
+
//# sourceMappingURL=runtime_log_scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime_log_scan.d.ts","sourceRoot":"","sources":["../../src/evidence/runtime_log_scan.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAmCD,0DAA0D;AAC1D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CASlD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,CAO5E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAQxE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,cAAc,CAoBjG;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,cAAc,GAAG,IAAI,GAAG,WAAW,CAe5E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
const FILE = "runtime_log_scan.json";
|
|
4
|
+
/**
|
|
5
|
+
* Lines that indicate a real runtime fault. Deliberately conservative to
|
|
6
|
+
* avoid false positives on benign "error" substrings (e.g. "0 errors",
|
|
7
|
+
* "errorContainer", a logger named ErrorBoundary rendering normally).
|
|
8
|
+
*/
|
|
9
|
+
const ERROR_PATTERNS = [
|
|
10
|
+
/\bunhandled (?:exception|rejection|promise rejection)\b/i,
|
|
11
|
+
/\b(?:fatal|panic)\b[: ]/i,
|
|
12
|
+
/traceback \(most recent call last\)/i,
|
|
13
|
+
/\bexception in thread\b/i,
|
|
14
|
+
/^\s*at .+\(.+:\d+:\d+\)\s*$/m, // JS stack frame
|
|
15
|
+
/\b[A-Za-z.]*(?:Error|Exception)\b:.+/, // "TypeError: x", "System.NullReferenceException: ..."
|
|
16
|
+
/\bHTTP\/\d\.\d"?\s+5\d\d\b/, // access-log 5xx
|
|
17
|
+
/\b5\d\d\s+(?:Internal Server Error|Service Unavailable|Bad Gateway)\b/i,
|
|
18
|
+
/\[error\]/i,
|
|
19
|
+
/level"?\s*[:=]\s*"?(?:error|fatal|critical)\b/i,
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Lines that look like errors but are noise we must NOT count, to keep the
|
|
23
|
+
* gate from being a false-positive machine.
|
|
24
|
+
*/
|
|
25
|
+
const IGNORE_PATTERNS = [
|
|
26
|
+
/\b0 errors?\b/i,
|
|
27
|
+
/no errors?\b/i,
|
|
28
|
+
/error[_-]?(?:boundary|container|page|handler|middleware|message|code)\b/i,
|
|
29
|
+
/errors?:\s*\[\]/i,
|
|
30
|
+
/--- stderr ---/, // our own runCommand log delimiter
|
|
31
|
+
/\$ /, // command echo line in our logs
|
|
32
|
+
];
|
|
33
|
+
/** Scan a blob of log text and return offending lines. */
|
|
34
|
+
export function scanLogText(text) {
|
|
35
|
+
const offenders = [];
|
|
36
|
+
for (const raw of text.split("\n")) {
|
|
37
|
+
const line = raw.trim();
|
|
38
|
+
if (!line)
|
|
39
|
+
continue;
|
|
40
|
+
if (IGNORE_PATTERNS.some((re) => re.test(line)))
|
|
41
|
+
continue;
|
|
42
|
+
if (ERROR_PATTERNS.some((re) => re.test(line)))
|
|
43
|
+
offenders.push(line.slice(0, 500));
|
|
44
|
+
}
|
|
45
|
+
return offenders;
|
|
46
|
+
}
|
|
47
|
+
export function writeRuntimeLogScan(runDir, ev) {
|
|
48
|
+
try {
|
|
49
|
+
mkdirSync(runDir, { recursive: true });
|
|
50
|
+
writeFileSync(join(runDir, FILE), JSON.stringify(ev, null, 2), "utf-8");
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* best-effort */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function loadRuntimeLogScan(runDir) {
|
|
57
|
+
const p = join(runDir, FILE);
|
|
58
|
+
if (!existsSync(p))
|
|
59
|
+
return null;
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build a RuntimeLogScan by scanning a set of log files. Each entry is
|
|
69
|
+
* { source, path }. Missing files are skipped silently.
|
|
70
|
+
*/
|
|
71
|
+
export function buildRuntimeLogScan(logs) {
|
|
72
|
+
const sources = [];
|
|
73
|
+
for (const { source, path } of logs) {
|
|
74
|
+
if (!existsSync(path))
|
|
75
|
+
continue;
|
|
76
|
+
let text = "";
|
|
77
|
+
try {
|
|
78
|
+
text = readFileSync(path, "utf-8");
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const offenders = scanLogText(text);
|
|
84
|
+
sources.push({ source, path, error_count: offenders.length, samples: offenders.slice(0, 5) });
|
|
85
|
+
}
|
|
86
|
+
const error_count = sources.reduce((s, x) => s + x.error_count, 0);
|
|
87
|
+
return {
|
|
88
|
+
generated_at: new Date().toISOString(),
|
|
89
|
+
applicable: sources.length > 0,
|
|
90
|
+
sources,
|
|
91
|
+
error_count,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export function evaluateRuntimeLogGate(s) {
|
|
95
|
+
if (!s)
|
|
96
|
+
return { passed: true, reason: "No runtime_log_scan.json (no logs captured this cycle)" };
|
|
97
|
+
if (!s.applicable)
|
|
98
|
+
return { passed: true, reason: "n/a — no runtime logs captured" };
|
|
99
|
+
if (s.error_count === 0) {
|
|
100
|
+
return { passed: true, reason: `Runtime logs clean across ${s.sources.length} source(s)` };
|
|
101
|
+
}
|
|
102
|
+
const worst = s.sources
|
|
103
|
+
.filter((x) => x.error_count > 0)
|
|
104
|
+
.map((x) => `${x.source} (${x.error_count}): ${x.samples[0] ?? ""}`)
|
|
105
|
+
.slice(0, 3)
|
|
106
|
+
.join(" | ");
|
|
107
|
+
return {
|
|
108
|
+
passed: false,
|
|
109
|
+
reason: `${s.error_count} runtime error/exception line(s) found in logs: ${worst}. Read the offending log under the run's logs/ dir, fix the root cause, then re-run codeloop_verify.`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=runtime_log_scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime_log_scan.js","sourceRoot":"","sources":["../../src/evidence/runtime_log_scan.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2249,6 +2249,36 @@ The agent MUST then write the report to docs/DEVELOPMENT_LOG.md and present it t
|
|
|
2249
2249
|
.slice(0, 5)
|
|
2250
2250
|
.map((i) => `(${i.kind}) ${summariseCycleIssue(i)}`)
|
|
2251
2251
|
.join(" | ")}${ci.issues.length > 5 ? " | … (see logs/cycle_issues.jsonl for the full list)" : ""}`;
|
|
2252
|
+
// 0.1.58-0.1.60 — Deep Internal Verification aggregate. Pull the most
|
|
2253
|
+
// recent run that produced each evidence file so the dev report can
|
|
2254
|
+
// document static analysis, changed-line coverage, backend smoke,
|
|
2255
|
+
// API contract, DB schema, and runtime-log cleanliness.
|
|
2256
|
+
const { loadCodeQualityEvidence } = await import("./evidence/deep_internal.js");
|
|
2257
|
+
const { loadBackendVerification } = await import("./evidence/backend_verification.js");
|
|
2258
|
+
const { loadRuntimeLogScan } = await import("./evidence/runtime_log_scan.js");
|
|
2259
|
+
const deepInternal = { static_analysis: null, coverage: null, backend: null, runtime_log: null };
|
|
2260
|
+
for (const runId of [...runs].reverse()) {
|
|
2261
|
+
const runDir = getRunDir(runId, baseDir);
|
|
2262
|
+
if (deepInternal.static_analysis === null || deepInternal.coverage === null) {
|
|
2263
|
+
const cq = loadCodeQualityEvidence(runDir);
|
|
2264
|
+
if (cq) {
|
|
2265
|
+
if (deepInternal.static_analysis === null)
|
|
2266
|
+
deepInternal.static_analysis = cq.static_analysis;
|
|
2267
|
+
if (deepInternal.coverage === null)
|
|
2268
|
+
deepInternal.coverage = cq.coverage;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
if (deepInternal.backend === null) {
|
|
2272
|
+
const b = loadBackendVerification(runDir);
|
|
2273
|
+
if (b)
|
|
2274
|
+
deepInternal.backend = b;
|
|
2275
|
+
}
|
|
2276
|
+
if (deepInternal.runtime_log === null) {
|
|
2277
|
+
const s = loadRuntimeLogScan(runDir);
|
|
2278
|
+
if (s)
|
|
2279
|
+
deepInternal.runtime_log = s;
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2252
2282
|
const report = {
|
|
2253
2283
|
project_name: params.project_name,
|
|
2254
2284
|
project_description: params.project_description || "",
|
|
@@ -2273,6 +2303,7 @@ The agent MUST then write the report to docs/DEVELOPMENT_LOG.md and present it t
|
|
|
2273
2303
|
cycle_issues_summary: cycleSummary,
|
|
2274
2304
|
cycle_issues: cycleIssuesEntries,
|
|
2275
2305
|
cycle_issues_directive: cycleIssuesDirective,
|
|
2306
|
+
deep_internal_verification: deepInternal,
|
|
2276
2307
|
};
|
|
2277
2308
|
await trackUsage(apiKey, "verification_run");
|
|
2278
2309
|
return report;
|
|
@@ -2338,6 +2369,19 @@ For EACH video recording session, document:
|
|
|
2338
2369
|
Create a table with: | # | Bug Description | Severity | How Found | Fix Applied |
|
|
2339
2370
|
List every issue discovered by CodeLoop during the development process.
|
|
2340
2371
|
|
|
2372
|
+
**7b. Deep Internal Verification** (0.1.58+)
|
|
2373
|
+
Document the internal (code / backend / terminal) verification evidence from the
|
|
2374
|
+
\`deep_internal_verification\` block above. Include a table:
|
|
2375
|
+
| Layer | Check | Result | Gate |
|
|
2376
|
+
|-------|-------|--------|------|
|
|
2377
|
+
| Static analysis | tsc / eslint / ruff / mypy / clippy / dotnet-format / flutter analyze | errors found / clean / n/a | static_analysis_passes |
|
|
2378
|
+
| Coverage | changed-line coverage % (covered/total) | pass / below threshold / n/a | code_coverage_threshold |
|
|
2379
|
+
| Backend smoke | health + route probes, 5xx count | healthy / failed / n/a | backend_smoke_evidence |
|
|
2380
|
+
| API contract | OpenAPI route conformance (violations) | pass / violations / n/a | api_contract_evidence |
|
|
2381
|
+
| DB schema | migration apply + drift | clean / drift / n/a | db_schema_evidence |
|
|
2382
|
+
| Runtime logs | exceptions / 5xx / fatal lines in logs | clean / errors / n/a | runtime_log_clean_evidence |
|
|
2383
|
+
State clearly which checks were applicable for this project's stack and which were n/a.
|
|
2384
|
+
|
|
2341
2385
|
**8. Cross-Platform Coverage**
|
|
2342
2386
|
Document which OS and platform combinations CodeLoop supports:
|
|
2343
2387
|
| OS | App Type | Video Method | Interaction Method | Log Capture |
|