{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAGlG;;;;GAIG;AAEH,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,iBAAiB,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,iBAAiB,CAsBnF;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,SAAM,GACZ,mBAAmB,EAAE,CAoBvB;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAQ9E;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9C,MAAM,WAAW,oBAAoB;IACpC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,2BAA2B,EAAE,OAAO,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC;IAC7B,eAAe,CAAC,EAAE,gBAAgB,GAAG,WAAW,CAAC;CACjD;AAED,eAAO,MAAM,8BAA8B,EAAE,oBAK5C,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,qBAAqB,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,mBAAmB,EAAE,EAC7B,KAAK,EAAE,mBAAmB,EAAE,EAC5B,MAAM,GAAE,OAAO,CAAC,oBAAoB,CAAM,GACxC,oBAAoB,CAiCtB;AAED,YAAY,EAAE,aAAa,EAAE,CAAC","sourcesContent":["import type { LspDiagnostic, LspDiagnosticResult, LspPublishDiagnosticsParams } from \"./types.js\";\nimport { LspDiagnosticSeverity } from \"./types.js\";\n\n/**\n * Diagnostics as read-only code intelligence, a transaction validation gate,\n * and post-edit evidence. LSP diagnostics SUPPLEMENT builds/tests; they never\n * replace them and never become an execution authority.\n */\n\nexport interface DiagnosticsComparison {\n\tbefore: DiagnosticSummary;\n\tafter: DiagnosticSummary;\n\terrorsIntroduced: number;\n\terrorsResolved: number;\n\twarningsIntroduced: number;\n\twarningsResolved: number;\n}\n\nexport interface DiagnosticSummary {\n\ttotal: number;\n\terrors: number;\n\twarnings: number;\n\tinformations: number;\n\thints: number;\n}\n\nexport function summarizeDiagnostics(rows: LspDiagnosticResult[]): DiagnosticSummary {\n\tlet errors = 0;\n\tlet warnings = 0;\n\tlet informations = 0;\n\tlet hints = 0;\n\tfor (const d of rows) {\n\t\tswitch (d.severity) {\n\t\t\tcase LspDiagnosticSeverity.Error:\n\t\t\t\terrors++;\n\t\t\t\tbreak;\n\t\t\tcase LspDiagnosticSeverity.Warning:\n\t\t\t\twarnings++;\n\t\t\t\tbreak;\n\t\t\tcase LspDiagnosticSeverity.Information:\n\t\t\t\tinformations++;\n\t\t\t\tbreak;\n\t\t\tcase LspDiagnosticSeverity.Hint:\n\t\t\t\thints++;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn { total: rows.length, errors, warnings, informations, hints };\n}\n\n/** Converts published diagnostics into workspace-relative, deduped, capped rows. */\nexport function getDiagnosticRows(\n\tparams: LspPublishDiagnosticsParams | null,\n\tworkspaceRoot: string,\n\t_serverId: string,\n\tmaxCount = 500,\n): LspDiagnosticResult[] {\n\tif (!params) return [];\n\tconst seen = new Set<string>();\n\tconst rows: LspDiagnosticResult[] = [];\n\tfor (const d of params.diagnostics) {\n\t\tconst relPath = toWorkspaceRelative(params.uri, workspaceRoot);\n\t\tconst key = `${relPath}|${d.range.start.line}:${d.range.start.character}-${d.range.end.line}:${d.range.end.character}|${d.message}`;\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\trows.push({\n\t\t\tworkspaceRelativePath: relPath,\n\t\t\trange: d.range,\n\t\t\tseverity: d.severity,\n\t\t\tcode: d.code,\n\t\t\tsource: d.source,\n\t\t\tmessage: d.message,\n\t\t});\n\t\tif (rows.length >= maxCount) break;\n\t}\n\treturn rows;\n}\n\nexport function toWorkspaceRelative(uri: string, workspaceRoot: string): string {\n\tconst raw = decodeURIComponent(uri.startsWith(\"file://\") ? uri.slice(\"file://\".length) : uri);\n\tconst normRoot = workspaceRoot.replace(/[\\\\/]+/g, \"/\").replace(/\\/$/, \"\");\n\tconst normRaw = raw.replace(/[\\\\/]+/g, \"/\");\n\tif (normRaw.startsWith(`${normRoot}/`)) return normRaw.slice(normRoot.length + 1);\n\tif (normRaw.startsWith(normRoot)) return normRaw.slice(normRoot.length);\n\t// Outside workspace: classify as external, read-only reference.\n\treturn normRaw;\n}\n\nexport type WarningPolicy = \"allow\" | \"block\";\n\nexport interface DiagnosticGateConfig {\n\tfailOnNewLspErrors: boolean;\n\tallowExistingBaselineErrors: boolean;\n\twarningPolicy: WarningPolicy;\n\tdiagnosticScope?: \"affected_files\" | \"workspace\";\n}\n\nexport const DEFAULT_DIAGNOSTIC_GATE_CONFIG: DiagnosticGateConfig = {\n\tfailOnNewLspErrors: true,\n\tallowExistingBaselineErrors: true,\n\twarningPolicy: \"allow\",\n\tdiagnosticScope: \"affected_files\",\n};\n\nexport interface DiagnosticGateResult {\n\tpassed: boolean;\n\treason?: string;\n\tcomparison: DiagnosticsComparison;\n}\n\n/**\n * Compare before/after diagnostics for a transaction. The safe default is \"no\n * new errors in affected files\". Baseline errors may be allowed; new errors\n * fail the gate when `failOnNewLspErrors`.\n */\nexport function evaluateDiagnosticGate(\n\tbefore: LspDiagnosticResult[],\n\tafter: LspDiagnosticResult[],\n\tconfig: Partial<DiagnosticGateConfig> = {},\n): DiagnosticGateResult {\n\tconst cfg: DiagnosticGateConfig = { ...DEFAULT_DIAGNOSTIC_GATE_CONFIG, ...config };\n\tconst beforeSummary = summarizeDiagnostics(before);\n\tconst afterSummary = summarizeDiagnostics(after);\n\tconst errorsIntroduced = Math.max(0, afterSummary.errors - beforeSummary.errors);\n\tconst errorsResolved = Math.max(0, beforeSummary.errors - afterSummary.errors);\n\tconst warningsIntroduced = Math.max(0, afterSummary.warnings - beforeSummary.warnings);\n\tconst warningsResolved = Math.max(0, beforeSummary.warnings - afterSummary.warnings);\n\n\tconst comparison: DiagnosticsComparison = {\n\t\tbefore: beforeSummary,\n\t\tafter: afterSummary,\n\t\terrorsIntroduced,\n\t\terrorsResolved,\n\t\twarningsIntroduced,\n\t\twarningsResolved,\n\t};\n\n\tif (cfg.failOnNewLspErrors && errorsIntroduced > 0) {\n\t\treturn {\n\t\t\tpassed: false,\n\t\t\treason: `LSP diagnostics gate failed: ${errorsIntroduced} new error(s) introduced`,\n\t\t\tcomparison,\n\t\t};\n\t}\n\tif (cfg.warningPolicy === \"block\" && warningsIntroduced > 0) {\n\t\treturn {\n\t\t\tpassed: false,\n\t\t\treason: `LSP diagnostics gate failed (warnings): ${warningsIntroduced} new warning(s)`,\n\t\t\tcomparison,\n\t\t};\n\t}\n\treturn { passed: true, comparison };\n}\n\nexport type { LspDiagnostic };\n"]}