@titan-design/style-checker 0.3.0 → 0.4.0
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/README.md +16 -5
- package/dist/index.d.ts +6 -2
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -36,11 +36,13 @@ const { diagnostics, failures, skippedRules, summary } = await orchestrate({
|
|
|
36
36
|
for naming, import order, function docs and function length that clear the profile's
|
|
37
37
|
`info` threshold, and carries `line-length`, isort section order, pydocstyle convention
|
|
38
38
|
and mccabe max complexity.
|
|
39
|
-
- `generateEslintConfig(profile)` returns
|
|
40
|
-
`**/*.ts` and `**/*.tsx` holding the rules
|
|
41
|
-
empty array when there are none. It is data:
|
|
42
|
-
objects and no parser. Style-profile's `info` tier
|
|
43
|
-
only `off`, `warn` and `error`.
|
|
39
|
+
- `generateEslintConfig(profile)` returns `{ entries, skippedRules }`. `entries` is an
|
|
40
|
+
`EslintFlatConfigEntry[]`: one entry for `**/*.ts` and `**/*.tsx` holding the rules
|
|
41
|
+
style-profile's rule builders produce, or an empty array when there are none. It is data:
|
|
42
|
+
rule names and options, with no plugin objects and no parser. Style-profile's `info` tier
|
|
43
|
+
becomes `warn`, because ESLint accepts only `off`, `warn` and `error`. `skippedRules` lists
|
|
44
|
+
a naming value style-profile's `buildNamingConvention` had no typescript-eslint format for
|
|
45
|
+
(same shape as `orchestrate`'s `skippedRules`).
|
|
44
46
|
- `orchestrate({ profile, files, fix?, language? })` picks the files by extension, runs
|
|
45
47
|
ESLint (through `npx --no -- eslint`) on `.ts`, `.tsx`, `.js`, `.jsx` and ruff on `.py`,
|
|
46
48
|
and returns `{ diagnostics, failures, skippedRules, summary }`. A tool is skipped when
|
|
@@ -52,6 +54,15 @@ const { diagnostics, failures, skippedRules, summary } = await orchestrate({
|
|
|
52
54
|
(`"code": "invalid-syntax"` in ruff 0.16.8, a null `code` in 0.9.10) are not
|
|
53
55
|
diagnostics; the runners report them as `file-not-checked` failures.
|
|
54
56
|
- `formatDiagnostic(d)` prints `file:line:column severity message [category.rule]`.
|
|
57
|
+
- Python audit runners, independent of any profile: `runRuffAudit` (the pinned
|
|
58
|
+
`AUDIT_RUFF_RULES` selection from `generateRuffAuditConfig()`), `runVultureAudit`
|
|
59
|
+
(dead code, rule `vulture/<kind>`), `runPydoclintAudit` (docstring drift, rule
|
|
60
|
+
`pydoclint/DOCnnn`), `runPyrightAudit` (four `reportUnnecessary*` checks under a
|
|
61
|
+
temporary config from `generatePyrightAuditConfig`), and `runImportLinter` (only when
|
|
62
|
+
the repo configures import-linter). `countSuppressions`, `findSuppressions` and
|
|
63
|
+
`suppressionTotals` count `# noqa` and `# type: ignore` markers by text scan. A runner
|
|
64
|
+
whose binary is absent returns an empty result with a warning naming its `pip install`
|
|
65
|
+
command, and never throws for it. The reference page lists each runner's options.
|
|
55
66
|
- `diffAgainstProfile(profile, observations)` compares each observation's value with the
|
|
56
67
|
profile's convention for its `type` and returns `{ deviations, summary }`. Observations
|
|
57
68
|
whose type has no profile rule count toward `total` but neither match nor deviate.
|
package/dist/index.d.ts
CHANGED
|
@@ -64,7 +64,11 @@ interface EslintFlatConfigEntry {
|
|
|
64
64
|
rules?: Record<string, unknown>;
|
|
65
65
|
files?: string[];
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
interface EslintConfigResult {
|
|
68
|
+
entries: EslintFlatConfigEntry[];
|
|
69
|
+
skippedRules: SkippedRule[];
|
|
70
|
+
}
|
|
71
|
+
declare function generateEslintConfig(profile: Profile): EslintConfigResult;
|
|
68
72
|
|
|
69
73
|
interface RuffConfig {
|
|
70
74
|
lint?: {
|
|
@@ -183,4 +187,4 @@ interface DiffResult {
|
|
|
183
187
|
}
|
|
184
188
|
declare function diffAgainstProfile(profile: Profile, observations: Observation[]): DiffResult;
|
|
185
189
|
|
|
186
|
-
export { AUDIT_PYRIGHT_RULES, AUDIT_RUFF_RULES, type AuditOptions, type CheckDiagnostic, type CheckResult, type Deviation, type DiffResult, type DocstringStyle, type EslintFlatConfigEntry, NOQA_RULE, NO_IMPORT_LINTER_CONFIG, type OrchestratorOptions, type OrchestratorResult, type PydoclintOptions, type PyrightConfig, type PyrightOptions, type RuffConfig, type RunnerOptions, type RunnerResult, type SkippedRule, type SuppressionCounts, type SuppressionTotals, TYPE_IGNORE_RULE, type ToolFailure, type ToolFailureKind, type ToolName, type VultureOptions, countSuppressions, diffAgainstProfile, findSuppressions, formatDiagnostic, generateEslintConfig, generatePyrightAuditConfig, generateRuffAuditConfig, generateRuffConfig, orchestrate, parseEslintJsonOutput, parseRuffJsonOutput, runImportLinter, runPydoclintAudit, runPyrightAudit, runRuffAudit, runVultureAudit, suppressionTotals };
|
|
190
|
+
export { AUDIT_PYRIGHT_RULES, AUDIT_RUFF_RULES, type AuditOptions, type CheckDiagnostic, type CheckResult, type Deviation, type DiffResult, type DocstringStyle, type EslintConfigResult, type EslintFlatConfigEntry, NOQA_RULE, NO_IMPORT_LINTER_CONFIG, type OrchestratorOptions, type OrchestratorResult, type PydoclintOptions, type PyrightConfig, type PyrightOptions, type RuffConfig, type RunnerOptions, type RunnerResult, type SkippedRule, type SuppressionCounts, type SuppressionTotals, TYPE_IGNORE_RULE, type ToolFailure, type ToolFailureKind, type ToolName, type VultureOptions, countSuppressions, diffAgainstProfile, findSuppressions, formatDiagnostic, generateEslintConfig, generatePyrightAuditConfig, generateRuffAuditConfig, generateRuffConfig, orchestrate, parseEslintJsonOutput, parseRuffJsonOutput, runImportLinter, runPydoclintAudit, runPyrightAudit, runRuffAudit, runVultureAudit, suppressionTotals };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/generators/eslint.ts
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
buildNamingConvention,
|
|
4
4
|
buildImportOrderRule,
|
|
5
5
|
buildFunctionLengthRule,
|
|
6
6
|
buildFileNamingRule,
|
|
@@ -10,10 +10,11 @@ function withEslintSeverity(value) {
|
|
|
10
10
|
if (Array.isArray(value) && value[0] === "info") return ["warn", ...value.slice(1)];
|
|
11
11
|
return value === "info" ? "warn" : value;
|
|
12
12
|
}
|
|
13
|
-
function collectRules(profile) {
|
|
13
|
+
function collectRules(profile, skippedRules) {
|
|
14
14
|
const rules = {};
|
|
15
|
-
const namingRule =
|
|
15
|
+
const { rule: namingRule, skippedRules: namingSkipped } = buildNamingConvention(profile);
|
|
16
16
|
if (namingRule) rules[namingRule[0]] = namingRule[1];
|
|
17
|
+
skippedRules.push(...namingSkipped);
|
|
17
18
|
const importRule = buildImportOrderRule(profile);
|
|
18
19
|
if (importRule) rules[importRule[0]] = importRule[1];
|
|
19
20
|
const fnLengthRule = buildFunctionLengthRule(profile);
|
|
@@ -29,14 +30,15 @@ function collectRules(profile) {
|
|
|
29
30
|
}
|
|
30
31
|
function generateEslintConfig(profile) {
|
|
31
32
|
const entries = [];
|
|
32
|
-
const
|
|
33
|
+
const skippedRules = [];
|
|
34
|
+
const rules = collectRules(profile, skippedRules);
|
|
33
35
|
if (Object.keys(rules).length > 0) {
|
|
34
36
|
entries.push({
|
|
35
37
|
files: ["**/*.ts", "**/*.tsx"],
|
|
36
38
|
rules
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
|
-
return entries;
|
|
41
|
+
return { entries, skippedRules };
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
// src/generators/ruff.ts
|
|
@@ -514,8 +516,13 @@ async function runTools(options) {
|
|
|
514
516
|
const pyFiles = files.filter((f) => /\.py$/.test(f));
|
|
515
517
|
const results = [];
|
|
516
518
|
if ((language === "typescript" || language === "mixed") && tsFiles.length > 0) {
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
+
const { entries, skippedRules: namingSkipped } = generateEslintConfig(profile);
|
|
520
|
+
if (entries.length > 0) {
|
|
521
|
+
const result = await runEslint(entries, tsFiles, { fix });
|
|
522
|
+
results.push({ ...result, skippedRules: [...namingSkipped, ...result.skippedRules] });
|
|
523
|
+
} else if (namingSkipped.length > 0) {
|
|
524
|
+
results.push({ diagnostics: [], exitCode: null, failures: [], skippedRules: namingSkipped });
|
|
525
|
+
}
|
|
519
526
|
}
|
|
520
527
|
if ((language === "python" || language === "mixed") && pyFiles.length > 0) {
|
|
521
528
|
const ruffConfig = generateRuffConfig(profile);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generators/eslint.ts","../src/generators/ruff.ts","../src/runners/eslint-runner.ts","../src/runners/tool-runner.ts","../src/runners/failures.ts","../src/runners/eslint-plugins.ts","../src/runners/eslint-config-module.ts","../src/formatters/unified.ts","../src/runners/ruff-runner.ts","../src/orchestrator/orchestrate.ts","../src/generators/ruff-audit.ts","../src/runners/paths.ts","../src/runners/ruff-audit.ts","../src/generators/pyright-audit.ts","../src/runners/python-tool.ts","../src/runners/vulture-audit.ts","../src/runners/pydoclint-audit.ts","../src/runners/pyright-audit.ts","../src/runners/import-linter.ts","../src/runners/import-linter-config.ts","../src/runners/import-linter-output.ts","../src/runners/suppressions.ts","../src/profile-diff/diff-against-profile.ts"],"sourcesContent":["import type { Profile } from \"@titan-design/style-profile\";\nimport {\n buildNamingConventionRule,\n buildImportOrderRule,\n buildFunctionLengthRule,\n buildFileNamingRule,\n buildJsdocRules,\n} from \"@titan-design/style-profile\";\n\nexport interface EslintFlatConfigEntry {\n plugins?: Record<string, unknown>;\n rules?: Record<string, unknown>;\n files?: string[];\n}\n\n// ESLint accepts only off, warn and error; style-profile's \"info\" tier becomes warn, as its own exporter does.\nfunction withEslintSeverity(value: unknown): unknown {\n if (Array.isArray(value) && value[0] === \"info\") return [\"warn\", ...value.slice(1)];\n return value === \"info\" ? \"warn\" : value;\n}\n\nfunction collectRules(profile: Profile): Record<string, unknown> {\n const rules: Record<string, unknown> = {};\n\n const namingRule = buildNamingConventionRule(profile);\n if (namingRule) rules[namingRule[0]] = namingRule[1];\n\n const importRule = buildImportOrderRule(profile);\n if (importRule) rules[importRule[0]] = importRule[1];\n\n const fnLengthRule = buildFunctionLengthRule(profile);\n if (fnLengthRule) rules[fnLengthRule[0]] = fnLengthRule[1];\n\n const fileNamingRule = buildFileNamingRule(profile);\n if (fileNamingRule) rules[fileNamingRule[0]] = fileNamingRule[1];\n\n const jsdocRules = buildJsdocRules(profile);\n for (const [name, value] of jsdocRules) {\n rules[name] = value;\n }\n\n for (const name of Object.keys(rules)) rules[name] = withEslintSeverity(rules[name]);\n return rules;\n}\n\nexport function generateEslintConfig(profile: Profile): EslintFlatConfigEntry[] {\n const entries: EslintFlatConfigEntry[] = [];\n const rules = collectRules(profile);\n\n if (Object.keys(rules).length > 0) {\n entries.push({\n files: [\"**/*.ts\", \"**/*.tsx\"],\n rules,\n });\n }\n\n return entries;\n}\n","import type { Profile } from \"@titan-design/style-profile\";\n\nexport interface RuffConfig {\n lint?: {\n select?: string[];\n ignore?: string[];\n fixable?: string[];\n \"per-file-ignores\"?: Record<string, string[]>;\n mccabe?: { \"max-complexity\"?: number };\n pydocstyle?: { convention?: string };\n isort?: {\n \"known-first-party\"?: string[];\n \"section-order\"?: string[];\n };\n };\n \"line-length\"?: number;\n preview?: boolean;\n}\n\ntype RuffLint = NonNullable<RuffConfig[\"lint\"]> & { select: string[] };\n\nfunction addNaming(profile: Profile, lint: RuffLint): void {\n if (profile.naming) {\n const hasNamingRules = Object.values(profile.naming).some(\n (rule) => rule.confidence >= profile.severityThresholds.info,\n );\n if (hasNamingRules) lint.select.push(\"N\");\n }\n}\n\nfunction addImportOrder(profile: Profile, lint: RuffLint): void {\n const importOrder = profile.structure?.importOrder;\n if (importOrder && importOrder.confidence >= profile.severityThresholds.info) {\n lint.select.push(\"I\");\n if (Array.isArray(importOrder.convention)) {\n lint.isort = {\n \"section-order\": importOrder.convention as string[],\n };\n }\n }\n}\n\nfunction addFunctionDocs(profile: Profile, lint: RuffLint): void {\n const functionDocs = profile.documentation?.functionDocs;\n if (functionDocs && functionDocs.confidence >= profile.severityThresholds.info) {\n lint.select.push(\"D\");\n const conv = functionDocs.convention;\n if (\n typeof conv === \"string\" &&\n conv !== \"jsdoc-selective\" &&\n conv !== \"jsdoc-all\"\n ) {\n lint.pydocstyle = { convention: conv };\n }\n }\n}\n\nfunction addComplexity(profile: Profile, lint: RuffLint): void {\n const maxLines = profile.structure?.functionMaxLines;\n if (\n maxLines &&\n maxLines.confidence >= profile.severityThresholds.info &&\n typeof maxLines.convention === \"number\"\n ) {\n lint.select.push(\"C90\");\n lint.mccabe = { \"max-complexity\": maxLines.convention };\n }\n}\n\nexport function generateRuffConfig(profile: Profile): RuffConfig {\n const lint: RuffLint = { select: [] };\n const config: RuffConfig = { lint };\n\n addNaming(profile, lint);\n addImportOrder(profile, lint);\n addFunctionDocs(profile, lint);\n addComplexity(profile, lint);\n\n const lineLength = profile.formatting?.lineLength;\n if (lineLength && typeof lineLength.convention === \"number\") {\n config[\"line-length\"] = lineLength.convention;\n }\n\n return config;\n}\n","import { writeFileSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { runAndClassify, parseOrFail } from \"./failures.js\";\nimport { buildEslintConfigModule } from \"./eslint-config-module.js\";\nimport { parseEslintJsonOutput } from \"../formatters/unified.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { EslintFlatConfigEntry } from \"../generators/eslint.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\ninterface EslintJsonMessage {\n ruleId: string | null;\n fatal?: boolean;\n message: string;\n}\n\n// ESLint reports a file it could not lint as a rule-less message: a fatal parse error, or \"File ignored ...\".\nfunction uncheckedFiles(stdout: string): ToolFailure[] {\n const entries = JSON.parse(stdout) as Array<{ filePath: string; messages: EslintJsonMessage[] }>;\n return entries.flatMap((entry) =>\n entry.messages\n .filter((m) => m.ruleId === null && (m.fatal === true || m.message.startsWith(\"File ignored\")))\n .map((m) => ({ tool: \"eslint\" as const, kind: \"file-not-checked\" as const, file: entry.filePath, message: m.message })),\n );\n}\n\nfunction readEslintOutput(stdout: string): { diagnostics: CheckDiagnostic[]; failures: ToolFailure[] } {\n const parsed = parseOrFail(\"eslint\", () => ({\n diagnostics: parseEslintJsonOutput(stdout),\n failures: uncheckedFiles(stdout),\n }));\n return parsed.ok ? parsed.value : { diagnostics: [], failures: [parsed.failure] };\n}\n\nfunction eslintArgs(configPath: string, files: string[], fix?: boolean): string[] {\n // --no stops npx from downloading an ESLint the project has not installed.\n return [\"--no\", \"--\", \"eslint\", \"--config\", configPath, \"--format\", \"json\", ...(fix ? [\"--fix\"] : []), ...files];\n}\n\nexport async function runEslint(\n config: EslintFlatConfigEntry[],\n files: string[],\n options?: RunnerOptions,\n): Promise<RunnerResult> {\n const cwd = options?.cwd ?? process.cwd();\n const built = buildEslintConfigModule(config, cwd);\n if (!built.ok) return { diagnostics: [], exitCode: null, failures: [built.failure], skippedRules: [] };\n const { skippedRules } = built;\n if (built.ruleCount === 0) return { diagnostics: [], exitCode: null, failures: [], skippedRules };\n\n const tempDir = mkdtempSync(join(tmpdir(), \"codewatch-eslint-\"));\n const configPath = join(tempDir, \"eslint.config.mjs\");\n try {\n writeFileSync(configPath, built.source, \"utf-8\");\n const run = await runAndClassify(\"eslint\", \"npx\", eslintArgs(configPath, files, options?.fix), {\n cwd,\n timeout: options?.timeout,\n });\n if (!run.ok) return { diagnostics: [], exitCode: run.exitCode, failures: [run.failure], skippedRules };\n return { ...readEslintOutput(run.stdout), exitCode: run.exitCode, skippedRules };\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { spawn } from \"node:child_process\";\n\nexport interface ToolRunResult {\n stdout: string;\n stderr: string;\n /** Null when the child was killed by a signal; see `signal`. */\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n timedOut: boolean;\n}\n\nexport function runTool(\n command: string,\n args: string[],\n options?: { cwd?: string; timeout?: number },\n): Promise<ToolRunResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd: options?.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const chunks: Buffer[] = [];\n const errChunks: Buffer[] = [];\n let timedOut = false;\n // Our own timer, because spawn's `timeout` option kills without telling us it did.\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, options?.timeout ?? 60_000);\n\n child.stdout.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n child.stderr.on(\"data\", (chunk: Buffer) => errChunks.push(chunk));\n\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n reject(new Error(`Failed to spawn ${command}: ${err.message}`));\n });\n\n child.on(\"close\", (code, signal) => {\n clearTimeout(timer);\n resolve({\n stdout: Buffer.concat(chunks).toString(\"utf-8\"),\n stderr: Buffer.concat(errChunks).toString(\"utf-8\"),\n exitCode: code,\n signal,\n timedOut,\n });\n });\n });\n}\n","import { runTool } from \"./tool-runner.js\";\nimport type { ToolRunResult } from \"./tool-runner.js\";\nimport type { ToolFailure, ToolName } from \"../orchestrator/types.js\";\n\n// ESLint and ruff both document 0 (clean) and 1 (problems found) as successful runs.\nconst SUCCESS_EXIT_CODES = new Set([0, 1]);\n\nexport type ToolRun =\n | { ok: true; stdout: string; stderr: string; exitCode: number }\n | { ok: false; failure: ToolFailure; exitCode: number | null };\n\nfunction excerpt(text: string): string {\n const trimmed = text.trim();\n return trimmed.length > 500 ? `${trimmed.slice(0, 500)}…` : trimmed;\n}\n\nfunction withStderr(message: string, stderr: string): string {\n const detail = excerpt(stderr);\n return detail ? `${message}: ${detail}` : message;\n}\n\n/** What counts as a successful run; vulture exits 3 on findings, and a clean vulture or pydoclint run prints nothing. */\nexport interface RunExpectations {\n successCodes?: ReadonlySet<number>;\n allowEmptyStdout?: boolean;\n}\n\nexport function classifyRun(tool: ToolName, run: ToolRunResult, expect: RunExpectations = {}): ToolRun {\n const fail = (kind: ToolFailure[\"kind\"], message: string): ToolRun => ({\n ok: false,\n failure: { tool, kind, message: withStderr(message, run.stderr) },\n exitCode: run.exitCode,\n });\n if (run.timedOut) return fail(\"timeout\", `${tool} timed out and was killed`);\n if (run.exitCode === null) {\n return fail(\"signal\", `${tool} was killed by ${run.signal ?? \"a signal\"}`);\n }\n if (!(expect.successCodes ?? SUCCESS_EXIT_CODES).has(run.exitCode)) {\n return fail(\"exit-code\", `${tool} exited with code ${run.exitCode}`);\n }\n if (!expect.allowEmptyStdout && !run.stdout.trim()) {\n return fail(\"unparseable-output\", `${tool} exited ${run.exitCode} with no output`);\n }\n return { ok: true, stdout: run.stdout, stderr: run.stderr, exitCode: run.exitCode };\n}\n\nexport async function runAndClassify(\n tool: ToolName,\n command: string,\n args: string[],\n options?: { cwd?: string; timeout?: number },\n expect?: RunExpectations,\n): Promise<ToolRun> {\n try {\n return classifyRun(tool, await runTool(command, args, options), expect);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, failure: { tool, kind: \"spawn-failed\", message }, exitCode: null };\n }\n}\n\nexport function parseOrFail<T>(\n tool: ToolName,\n parse: () => T,\n): { ok: true; value: T } | { ok: false; failure: ToolFailure } {\n try {\n return { ok: true, value: parse() };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, failure: { tool, kind: \"unparseable-output\", message } };\n }\n}\n","import { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nexport interface ModuleSource {\n specifier: string;\n member?: \"plugin\" | \"parser\";\n}\n\nexport interface ResolvedModule {\n url: string;\n member?: \"plugin\" | \"parser\";\n}\n\n// The typescript-eslint meta-package is the fallback because under pnpm it is often the only one a project can resolve.\nexport const PLUGIN_SOURCES: Record<string, ModuleSource[]> = {\n \"@typescript-eslint\": [\n { specifier: \"@typescript-eslint/eslint-plugin\" },\n { specifier: \"typescript-eslint\", member: \"plugin\" },\n ],\n perfectionist: [{ specifier: \"eslint-plugin-perfectionist\" }],\n unicorn: [{ specifier: \"eslint-plugin-unicorn\" }],\n jsdoc: [{ specifier: \"eslint-plugin-jsdoc\" }],\n};\n\nexport const PARSER_SOURCES: ModuleSource[] = [\n { specifier: \"@typescript-eslint/parser\" },\n { specifier: \"typescript-eslint\", member: \"parser\" },\n];\n\nexport function pluginNamespace(rule: string): string | null {\n const slash = rule.lastIndexOf(\"/\");\n return slash === -1 ? null : rule.slice(0, slash);\n}\n\nexport function describeSources(sources: ModuleSource[]): string {\n return sources.map((s) => s.specifier).join(\" or \");\n}\n\nexport function resolveModule(\n sources: ModuleSource[],\n fromDir: string,\n): ResolvedModule | null {\n // Resolve from the project, not from this package: ESLint runs there and loads plugins from there.\n const require = createRequire(join(fromDir, \"package.json\"));\n for (const source of sources) {\n try {\n const url = pathToFileURL(require.resolve(source.specifier)).href;\n return { url, member: source.member };\n } catch {\n continue;\n }\n }\n return null;\n}\n","import {\n PARSER_SOURCES,\n PLUGIN_SOURCES,\n describeSources,\n pluginNamespace,\n resolveModule,\n} from \"./eslint-plugins.js\";\nimport type { ResolvedModule } from \"./eslint-plugins.js\";\nimport type { EslintFlatConfigEntry } from \"../generators/eslint.js\";\nimport type { SkippedRule, ToolFailure } from \"../orchestrator/types.js\";\n\nexport type EslintConfigModule =\n | { ok: true; source: string; ruleCount: number; skippedRules: SkippedRule[] }\n | { ok: false; failure: ToolFailure };\n\ninterface ModuleContext {\n fromDir: string;\n imports: string[];\n ids: Map<string, string>;\n plugins: Map<string, ResolvedModule | null>;\n}\n\nfunction importExpr(ctx: ModuleContext, mod: ResolvedModule): string {\n let id = ctx.ids.get(mod.url);\n if (!id) {\n id = `m${ctx.ids.size}`;\n ctx.ids.set(mod.url, id);\n ctx.imports.push(`import ${id} from ${JSON.stringify(mod.url)};`);\n }\n return mod.member ? `${id}.${mod.member}` : id;\n}\n\nfunction resolvePlugin(ctx: ModuleContext, namespace: string): ResolvedModule | null {\n if (!ctx.plugins.has(namespace)) {\n const sources = PLUGIN_SOURCES[namespace];\n ctx.plugins.set(namespace, sources ? resolveModule(sources, ctx.fromDir) : null);\n }\n return ctx.plugins.get(namespace) ?? null;\n}\n\nfunction skipReason(ctx: ModuleContext, namespace: string): string {\n const sources = PLUGIN_SOURCES[namespace];\n if (!sources) return `no known package provides the ESLint plugin \"${namespace}\"`;\n return `${describeSources(sources)} is not installed in ${ctx.fromDir}`;\n}\n\nfunction renderEntry(\n ctx: ModuleContext,\n entry: EslintFlatConfigEntry,\n parserExpr: string,\n skipped: SkippedRule[],\n): { text: string; ruleCount: number } {\n const rules: Record<string, unknown> = {};\n const plugins: string[] = [];\n for (const [rule, value] of Object.entries(entry.rules ?? {})) {\n const namespace = pluginNamespace(rule);\n const plugin = namespace === null ? null : resolvePlugin(ctx, namespace);\n if (namespace !== null && !plugin) {\n skipped.push({ tool: \"eslint\", rule, plugin: namespace, reason: skipReason(ctx, namespace) });\n continue;\n }\n rules[rule] = value;\n if (namespace !== null && plugin) plugins.push(`${JSON.stringify(namespace)}: ${importExpr(ctx, plugin)}`);\n }\n const data = JSON.stringify({ files: entry.files, rules });\n const text = `{ ...${data}, languageOptions: { parser: ${parserExpr} }, plugins: { ${[...new Set(plugins)].join(\", \")} } }`;\n return { text, ruleCount: Object.keys(rules).length };\n}\n\nexport function buildEslintConfigModule(\n config: EslintFlatConfigEntry[],\n fromDir: string,\n): EslintConfigModule {\n const parser = resolveModule(PARSER_SOURCES, fromDir);\n if (!parser) {\n const message = `${describeSources(PARSER_SOURCES)} is not installed in ${fromDir}, so ESLint cannot parse TypeScript`;\n return { ok: false, failure: { tool: \"eslint\", kind: \"missing-dependency\", message } };\n }\n const ctx: ModuleContext = { fromDir, imports: [], ids: new Map(), plugins: new Map() };\n const parserExpr = importExpr(ctx, parser);\n const skippedRules: SkippedRule[] = [];\n const entries = config.map((entry) => renderEntry(ctx, entry, parserExpr, skippedRules));\n const ruleCount = entries.reduce((sum, e) => sum + e.ruleCount, 0);\n const body = entries.map((e) => e.text).join(\",\\n \");\n const source = `${ctx.imports.join(\"\\n\")}\\n\\nexport default [\\n ${body},\\n];\\n`;\n return { ok: true, source, ruleCount, skippedRules };\n}\n","import type { CheckDiagnostic } from \"../orchestrator/types.js\";\n\nconst RUFF_CODE_CATEGORY: Record<string, string> = {\n N: \"naming\",\n I: \"imports\",\n D: \"documentation\",\n C: \"complexity\",\n E: \"formatting\",\n W: \"formatting\",\n F: \"errors\",\n};\n\nconst ESLINT_RULE_CATEGORY: Record<string, string> = {\n \"@typescript-eslint/naming-convention\": \"naming\",\n \"unicorn/filename-case\": \"naming\",\n \"perfectionist/sort-imports\": \"imports\",\n \"import/order\": \"imports\",\n \"max-lines-per-function\": \"structure\",\n \"max-depth\": \"structure\",\n \"jsdoc/require-jsdoc\": \"documentation\",\n};\n\nfunction eslintSeverityToSeverity(eslintSeverity: number): \"error\" | \"warn\" {\n return eslintSeverity === 2 ? \"error\" : \"warn\";\n}\n\nfunction categorizeEslintRule(ruleId: string): string {\n if (ESLINT_RULE_CATEGORY[ruleId]) return ESLINT_RULE_CATEGORY[ruleId];\n if (ruleId.startsWith(\"@typescript-eslint/\")) return \"typescript\";\n if (ruleId.startsWith(\"jsdoc/\")) return \"documentation\";\n if (ruleId.startsWith(\"unicorn/\")) return \"style\";\n if (ruleId.startsWith(\"import/\")) return \"imports\";\n return \"other\";\n}\n\nfunction categorizeRuffCode(code: string): string {\n const prefix = code.replace(/[0-9]/g, \"\");\n return RUFF_CODE_CATEGORY[prefix] ?? \"other\";\n}\n\ninterface EslintJsonEntry {\n filePath: string;\n messages: Array<{\n ruleId: string | null;\n severity: number;\n message: string;\n line: number;\n column: number;\n fix?: { range: [number, number]; text: string } | null;\n }>;\n}\n\ninterface RuffJsonEntry {\n code: string | null;\n message: string;\n filename: string;\n location: { row: number; column: number };\n end_location: { row: number; column: number };\n fix?: {\n edits: Array<{\n content: string;\n location: { row: number; column: number };\n end_location: { row: number; column: number };\n }>;\n } | null;\n}\n\nexport function parseEslintJsonOutput(jsonStr: string): CheckDiagnostic[] {\n let entries: EslintJsonEntry[];\n try {\n entries = JSON.parse(jsonStr);\n } catch {\n throw new Error(\n `Failed to parse ESLint JSON output. Raw output:\\n${jsonStr.slice(0, 500)}`,\n );\n }\n const diagnostics: CheckDiagnostic[] = [];\n\n for (const entry of entries) {\n for (const msg of entry.messages) {\n if (!msg.ruleId) continue;\n diagnostics.push({\n file: entry.filePath,\n line: msg.line,\n column: msg.column,\n severity: eslintSeverityToSeverity(msg.severity),\n message: msg.message,\n category: categorizeEslintRule(msg.ruleId),\n rule: msg.ruleId,\n fixable: msg.fix != null,\n fix: msg.fix ?? undefined,\n });\n }\n }\n\n return diagnostics;\n}\n\n// ruff 0.16.8 reports a syntax error as code \"invalid-syntax\"; 0.9.10 used a null code.\nexport function isRuffSyntaxError(code: string | null): code is \"invalid-syntax\" | null {\n return code === null || code === \"invalid-syntax\";\n}\n\nexport function parseRuffJsonOutput(jsonStr: string): CheckDiagnostic[] {\n let entries: RuffJsonEntry[];\n try {\n entries = JSON.parse(jsonStr);\n } catch {\n throw new Error(\n `Failed to parse Ruff JSON output. Raw output:\\n${jsonStr.slice(0, 500)}`,\n );\n }\n return entries.flatMap((entry) => isRuffSyntaxError(entry.code) ? [] : [{\n file: entry.filename,\n line: entry.location.row,\n endLine: entry.end_location.row,\n column: entry.location.column,\n severity: \"warn\" as const,\n message: entry.message,\n category: categorizeRuffCode(entry.code),\n rule: entry.code,\n fixable: entry.fix != null,\n }]);\n}\n\nexport function formatDiagnostic(d: CheckDiagnostic): string {\n return `${d.file}:${d.line}:${d.column} ${d.severity} ${d.message} [${d.category}.${d.rule}]`;\n}\n","import { writeFileSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { runAndClassify, parseOrFail } from \"./failures.js\";\nimport { isRuffSyntaxError, parseRuffJsonOutput } from \"../formatters/unified.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\nimport type { RuffConfig } from \"../generators/ruff.js\";\n\ntype RuffLint = NonNullable<RuffConfig[\"lint\"]>;\n\nfunction quoteList(values: string[]): string {\n return `[${values.map((s) => `\"${s}\"`).join(\", \")}]`;\n}\n\nfunction lintSelectionLines(lint: RuffLint): string[] {\n const lines: string[] = [];\n if (lint.select) lines.push(`select = ${quoteList(lint.select)}`);\n if (lint.ignore) lines.push(`ignore = ${quoteList(lint.ignore)}`);\n return lines;\n}\n\nfunction lintSubsectionLines(lint: RuffLint): string[] {\n const lines: string[] = [];\n if (lint.mccabe) {\n lines.push(\"[lint.mccabe]\");\n if (lint.mccabe[\"max-complexity\"]) {\n lines.push(`max-complexity = ${lint.mccabe[\"max-complexity\"]}`);\n }\n }\n if (lint.pydocstyle) {\n lines.push(\"[lint.pydocstyle]\");\n if (lint.pydocstyle.convention) {\n lines.push(`convention = \"${lint.pydocstyle.convention}\"`);\n }\n }\n if (lint.isort) {\n lines.push(\"[lint.isort]\");\n if (lint.isort[\"section-order\"]) {\n lines.push(`section-order = ${quoteList(lint.isort[\"section-order\"])}`);\n }\n }\n return lines;\n}\n\nfunction toToml(config: RuffConfig): string {\n const lines: string[] = [];\n\n if (config[\"line-length\"]) {\n lines.push(`line-length = ${config[\"line-length\"]}`);\n }\n if (config.preview) lines.push(\"preview = true\");\n\n if (config.lint) {\n lines.push(\"[lint]\", ...lintSelectionLines(config.lint), ...lintSubsectionLines(config.lint));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\ninterface RuffJsonMessage {\n code: string | null;\n filename: string;\n message: string;\n}\n\nfunction notChecked(file: string, message: string): ToolFailure {\n return { tool: \"ruff\", kind: \"file-not-checked\", file, message };\n}\n\n// ruff emits one entry per syntax error; a file that fails to parse is reported once.\nfunction unparsedFiles(stdout: string): ToolFailure[] {\n const byFile = new Map<string, string[]>();\n for (const e of JSON.parse(stdout) as RuffJsonMessage[]) {\n if (!isRuffSyntaxError(e.code)) continue;\n byFile.set(e.filename, [...(byFile.get(e.filename) ?? []), e.message]);\n }\n return [...byFile].map(([file, messages]) => notChecked(file, messages.join(\"; \")));\n}\n\n// ruff 0.16.8 flags an unreadable path (exit 0, \"[]\") only in this stderr wording; if ruff rewords it, the case goes silent again.\nfunction unreadFiles(stderr: string): ToolFailure[] {\n return [...stderr.matchAll(/^warning: Failed to lint (.+?): (.+)$/gm)].map((m) => notChecked(m[1]!, m[2]!));\n}\n\nfunction readRuffOutput(stdout: string, stderr: string): { diagnostics: CheckDiagnostic[]; failures: ToolFailure[] } {\n const parsed = parseOrFail(\"ruff\", () => ({\n diagnostics: parseRuffJsonOutput(stdout),\n failures: [...unparsedFiles(stdout), ...unreadFiles(stderr)],\n }));\n return parsed.ok ? parsed.value : { diagnostics: [], failures: [parsed.failure] };\n}\n\nexport async function runRuff(\n config: RuffConfig,\n files: string[],\n options?: RunnerOptions,\n): Promise<RunnerResult> {\n const tempDir = mkdtempSync(join(tmpdir(), \"codewatch-ruff-\"));\n const configPath = join(tempDir, \"ruff.toml\");\n\n try {\n writeFileSync(configPath, toToml(config), \"utf-8\");\n\n const args = [\n \"check\",\n \"--config\",\n configPath,\n \"--output-format\",\n \"json\",\n ...(options?.fix ? [\"--fix\"] : []),\n ...files,\n ];\n\n const run = await runAndClassify(\"ruff\", \"ruff\", args, { cwd: options?.cwd, timeout: options?.timeout });\n if (!run.ok) return { diagnostics: [], exitCode: run.exitCode, failures: [run.failure], skippedRules: [] };\n return { ...readRuffOutput(run.stdout, run.stderr), exitCode: run.exitCode, skippedRules: [] };\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { generateEslintConfig } from \"../generators/eslint.js\";\nimport { generateRuffConfig } from \"../generators/ruff.js\";\nimport { runEslint } from \"../runners/eslint-runner.js\";\nimport { runRuff } from \"../runners/ruff-runner.js\";\nimport type { RunnerResult } from \"../runners/types.js\";\nimport type {\n OrchestratorOptions,\n OrchestratorResult,\n CheckDiagnostic,\n} from \"./types.js\";\n\nfunction detectLanguage(files: string[]): \"typescript\" | \"python\" | \"mixed\" {\n const tsFiles = files.filter((f) => /\\.[tj]sx?$/.test(f));\n const pyFiles = files.filter((f) => /\\.py$/.test(f));\n if (tsFiles.length > 0 && pyFiles.length === 0) return \"typescript\";\n if (pyFiles.length > 0 && tsFiles.length === 0) return \"python\";\n return \"mixed\";\n}\n\nfunction buildSummary(\n diagnostics: CheckDiagnostic[],\n): OrchestratorResult[\"summary\"] {\n return {\n total: diagnostics.length,\n errors: diagnostics.filter((d) => d.severity === \"error\").length,\n warnings: diagnostics.filter((d) => d.severity === \"warn\").length,\n infos: diagnostics.filter((d) => d.severity === \"info\").length,\n fixed: 0,\n };\n}\n\nasync function runTools(options: OrchestratorOptions): Promise<RunnerResult[]> {\n const { profile, files, fix } = options;\n const language = options.language ?? detectLanguage(files);\n const tsFiles = files.filter((f) => /\\.[tj]sx?$/.test(f));\n const pyFiles = files.filter((f) => /\\.py$/.test(f));\n const results: RunnerResult[] = [];\n\n if ((language === \"typescript\" || language === \"mixed\") && tsFiles.length > 0) {\n const eslintConfig = generateEslintConfig(profile);\n if (eslintConfig.length > 0) results.push(await runEslint(eslintConfig, tsFiles, { fix }));\n }\n\n if ((language === \"python\" || language === \"mixed\") && pyFiles.length > 0) {\n const ruffConfig = generateRuffConfig(profile);\n if (ruffConfig.lint?.select && ruffConfig.lint.select.length > 0) {\n results.push(await runRuff(ruffConfig, pyFiles, { fix }));\n }\n }\n return results;\n}\n\nexport async function orchestrate(\n options: OrchestratorOptions,\n): Promise<OrchestratorResult> {\n const results = await runTools(options);\n const diagnostics = results.flatMap((r) => r.diagnostics);\n return {\n diagnostics,\n failures: results.flatMap((r) => r.failures),\n skippedRules: results.flatMap((r) => r.skippedRules),\n summary: buildSummary(diagnostics),\n };\n}\n","import type { RuffConfig } from \"./ruff.js\";\n\n/** The audit's pinned ruff selection: complexity, size, dead code, and defensive-bloat signals. */\nexport const AUDIT_RUFF_RULES: readonly string[] = [\n \"C901\",\n \"PLR0904\",\n \"PLR0911\",\n \"PLR0912\",\n \"PLR0913\",\n \"PLR0914\",\n \"PLR0915\",\n \"PLR0916\",\n \"PLR0917\",\n \"PLR1702\",\n \"ARG\",\n \"FBT\",\n \"ERA001\",\n \"BLE001\",\n \"S110\",\n \"TRY203\",\n \"SIM105\",\n \"F401\",\n \"F841\",\n \"PIE790\",\n \"RUF100\",\n];\n\n/** Preview is on because ruff 0.16.8 silently skips PLR0904, PLR0914, PLR0916 and PLR1702 without it. */\nexport function generateRuffAuditConfig(): RuffConfig {\n return { preview: true, lint: { select: [...AUDIT_RUFF_RULES] } };\n}\n","import { realpathSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\n\n/** The directory diagnostics are reported relative to, resolved so it matches the real paths tools print. */\nexport function auditRoot(cwd?: string): string {\n return realpathSync(cwd ?? process.cwd());\n}\n\nexport function relativeTo(root: string, file: string): string {\n return isAbsolute(file) ? relative(root, file) : file;\n}\n","import { generateRuffAuditConfig } from \"../generators/ruff-audit.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport { runRuff } from \"./ruff-runner.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\n/** Runs the pinned audit rule set; diagnostics carry paths relative to `cwd`, since ruff reports absolute ones. */\nexport async function runRuffAudit(files: string[], options?: Omit<RunnerOptions, \"fix\">): Promise<RunnerResult> {\n const result = await runRuff(generateRuffAuditConfig(), files, options);\n const root = auditRoot(options?.cwd);\n const diagnostics = result.diagnostics.map((d) => ({ ...d, file: relativeTo(root, d.file) }));\n return { ...result, diagnostics };\n}\n","/** The audit's pinned pyright selection: checks whose finding is a guard or conversion the types already make redundant. */\nexport const AUDIT_PYRIGHT_RULES: readonly string[] = [\n \"reportUnnecessaryIsInstance\",\n \"reportUnnecessaryComparison\",\n \"reportUnnecessaryContains\",\n \"reportUnnecessaryCast\",\n];\n\n// typeCheckingMode \"off\" still leaves these on, and an audit that cannot see the project's dependencies would drown in them.\nconst STILL_ON_WHEN_OFF = [\"reportMissingImports\", \"reportMissingModuleSource\", \"reportUndefinedVariable\"];\n\nexport type PyrightConfig = Record<string, string | string[]>;\n\n/** Everything off except the audit rules, as warnings; `root` goes on extraPaths so the project's own imports resolve. */\nexport function generatePyrightAuditConfig(root: string): PyrightConfig {\n const config: PyrightConfig = { typeCheckingMode: \"off\", extraPaths: [root] };\n for (const rule of STILL_ON_WHEN_OFF) config[rule] = \"none\";\n for (const rule of AUDIT_PYRIGHT_RULES) config[rule] = \"warning\";\n return config;\n}\n","import { parseOrFail, runAndClassify } from \"./failures.js\";\nimport type { RunExpectations, ToolRun } from \"./failures.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport type { CheckDiagnostic, ToolFailure, ToolName } from \"../orchestrator/types.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\n/** How to invoke one audit tool and what to tell the user when it is not installed. */\nexport interface PythonToolSpec {\n tool: ToolName;\n command: string;\n install: string;\n installNote?: string;\n expect: RunExpectations;\n}\n\nexport interface ToolOutput {\n stdout: string;\n stderr: string;\n}\n\nexport interface ParsedOutput {\n diagnostics: CheckDiagnostic[];\n failures: ToolFailure[];\n}\n\nexport type AuditOptions = Omit<RunnerOptions, \"fix\">;\n\nexport function emptyResult(exitCode: number | null, extra: Partial<RunnerResult> = {}): RunnerResult {\n return { diagnostics: [], exitCode, failures: [], skippedRules: [], warnings: [], ...extra };\n}\n\nexport function missingToolWarning(spec: PythonToolSpec): string {\n const note = spec.installNote ? ` (${spec.installNote})` : \"\";\n return `${spec.tool} not found; install with \\`${spec.install}\\`${note}`;\n}\n\nfunction isMissingBinary(run: Extract<ToolRun, { ok: false }>): boolean {\n const { kind, message } = run.failure;\n if (kind === \"spawn-failed\" && message.includes(\"ENOENT\")) return true;\n return run.exitCode === 127 || /command not found/i.test(message);\n}\n\nfunction relativise(root: string, parsed: ParsedOutput): ParsedOutput {\n return {\n diagnostics: parsed.diagnostics.map((d) => ({ ...d, file: relativeTo(root, d.file) })),\n failures: parsed.failures.map((f) => (f.file ? { ...f, file: relativeTo(root, f.file) } : f)),\n };\n}\n\n/** Runs one tool, maps an absent binary to a warning, and reports paths relative to `cwd`. */\nexport async function runPythonTool(\n spec: PythonToolSpec,\n args: string[],\n options: AuditOptions | undefined,\n parse: (output: ToolOutput) => ParsedOutput,\n): Promise<RunnerResult> {\n const runOptions = { cwd: options?.cwd, timeout: options?.timeout };\n const run = await runAndClassify(spec.tool, spec.command, args, runOptions, spec.expect);\n if (!run.ok && isMissingBinary(run)) return emptyResult(null, { warnings: [missingToolWarning(spec)] });\n if (!run.ok) return emptyResult(run.exitCode, { failures: [run.failure] });\n const parsed = parseOrFail(spec.tool, () => parse(run));\n if (!parsed.ok) return emptyResult(run.exitCode, { failures: [parsed.failure] });\n return emptyResult(run.exitCode, relativise(auditRoot(options?.cwd), parsed.value));\n}\n\n/** Stderr lines a parser did not recognise, folded into one failure so a crash is never silent. */\nexport function unrecognisedStderr(tool: ToolName, lines: string[]): ToolFailure[] {\n if (lines.length === 0) return [];\n const message = lines.join(\"\\n\");\n return [{ tool, kind: \"unparseable-output\", message: message.length > 500 ? `${message.slice(0, 500)}…` : message }];\n}\n","import { runPythonTool, unrecognisedStderr } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// vulture exits 1 on invalid input (a syntax error) and 3 when it found dead code; both still carry findings.\nconst VULTURE: PythonToolSpec = {\n tool: \"vulture\",\n command: \"vulture\",\n install: \"pip install vulture\",\n expect: { successCodes: new Set([0, 1, 3]), allowEmptyStdout: true },\n};\n\nconst FINDING = /^(.+?):(\\d+): (.+) \\((\\d+)% confidence(?:, \\d+ lines?)?\\)$/;\nconst INVALID_INPUT = /^(.+?):(\\d+): (.+)$/;\nconst NOT_FOUND = /^Error: (.+) could not be found\\.$/;\n\nexport interface VultureOptions extends AuditOptions {\n /** vulture's --min-confidence; 60 keeps its uncertain unused-code guesses, 100 keeps only unreachable code. */\n minConfidence?: number;\n}\n\n/** Rule suffix from vulture's wording: \"unused function 'x'\" is unused-function; every other finding is unreachable code. */\nexport function vultureKind(text: string): string {\n const unused = /^unused (\\w+)/.exec(text);\n return unused ? `unused-${unused[1]}` : \"unreachable\";\n}\n\nfunction toDiagnostic(m: RegExpExecArray): CheckDiagnostic {\n const [, file, line, text, confidence] = m as unknown as [string, string, string, string, string];\n return {\n file,\n line: Number(line),\n column: 1,\n severity: \"warn\",\n message: `${text} (${confidence}% confidence)`,\n category: \"dead-code\",\n rule: `vulture/${vultureKind(text)}`,\n fixable: false,\n };\n}\n\nfunction parseStdout(stdout: string): CheckDiagnostic[] {\n return stdout.split(\"\\n\").filter((l) => l.trim()).map((line) => {\n const m = FINDING.exec(line);\n if (!m) throw new Error(`Unrecognised vulture line: ${line}`);\n return toDiagnostic(m);\n });\n}\n\nfunction parseStderr(stderr: string): ToolFailure[] {\n const failures: ToolFailure[] = [];\n const unknown: string[] = [];\n for (const line of stderr.split(\"\\n\").filter((l) => l.trim())) {\n const missing = NOT_FOUND.exec(line);\n const invalid = INVALID_INPUT.exec(line);\n if (missing) failures.push({ tool: \"vulture\", kind: \"file-not-checked\", file: missing[1]!, message: \"could not be found\" });\n else if (invalid) failures.push({ tool: \"vulture\", kind: \"file-not-checked\", file: invalid[1]!, message: invalid[3]! });\n else unknown.push(line);\n }\n return [...failures, ...unrecognisedStderr(\"vulture\", unknown)];\n}\n\nexport function parseVultureOutput({ stdout, stderr }: ToolOutput): ParsedOutput {\n return { diagnostics: parseStdout(stdout), failures: parseStderr(stderr) };\n}\n\n/** Dead-code candidates from vulture at `minConfidence` (default 60); rule ids are vulture/<kind>. */\nexport function runVultureAudit(files: string[], options?: VultureOptions): Promise<RunnerResult> {\n const args = [\"--min-confidence\", String(options?.minConfidence ?? 60), ...files];\n return runPythonTool(VULTURE, args, options, parseVultureOutput);\n}\n","import { runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\nconst PYDOCLINT: PythonToolSpec = {\n tool: \"pydoclint\",\n command: \"pydoclint\",\n install: \"pip install pydoclint\",\n expect: { successCodes: new Set([0, 1]), allowEmptyStdout: true },\n};\n\nconst VIOLATION = /^\\s+(\\d+): (DOC\\d+): (.*)$/;\n// pydoclint reports a file it cannot parse as a DOC002 violation at line 0.\nconst SYNTAX_ERROR = \"DOC002\";\n\nexport type DocstringStyle = \"numpy\" | \"google\" | \"sphinx\";\n\nexport interface PydoclintOptions extends AuditOptions {\n style?: DocstringStyle;\n}\n\nfunction toDiagnostic(file: string, m: RegExpExecArray): CheckDiagnostic {\n return {\n file,\n line: Math.max(1, Number(m[1])),\n column: 1,\n severity: \"warn\",\n message: m[3]!,\n category: \"documentation\",\n rule: `pydoclint/${m[2]}`,\n fixable: false,\n };\n}\n\n/** pydoclint prints each file's path unindented, then its violations indented beneath it, all on stderr. */\nexport function parsePydoclintOutput({ stdout, stderr }: ToolOutput): ParsedOutput {\n const parsed: ParsedOutput = { diagnostics: [], failures: [] };\n let file: string | undefined;\n for (const line of `${stdout}\\n${stderr}`.split(\"\\n\").filter((l) => l.trim())) {\n const m = VIOLATION.exec(line);\n if (!m && /^\\S/.test(line)) file = line.trim();\n else if (!m || !file) throw new Error(`Unrecognised pydoclint line: ${line}`);\n else if (m[2] === SYNTAX_ERROR) parsed.failures.push(notChecked(file, m[3]!));\n else parsed.diagnostics.push(toDiagnostic(file, m));\n }\n return parsed;\n}\n\nfunction notChecked(file: string, message: string): ToolFailure {\n return { tool: \"pydoclint\", kind: \"file-not-checked\", file, message };\n}\n\n/** Docstring-versus-signature drift from pydoclint in `style` (default numpy); rule ids are pydoclint/DOCnnn. */\nexport function runPydoclintAudit(files: string[], options?: PydoclintOptions): Promise<RunnerResult> {\n const args = [\"--style\", options?.style ?? \"numpy\", \"--quiet\", ...files];\n return runPythonTool(PYDOCLINT, args, options, parsePydoclintOutput);\n}\n","import { mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { AUDIT_PYRIGHT_RULES, generatePyrightAuditConfig } from \"../generators/pyright-audit.js\";\nimport { auditRoot } from \"./paths.js\";\nimport { runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\nconst PYRIGHT: PythonToolSpec = {\n tool: \"pyright\",\n command: \"pyright\",\n install: \"pip install pyright\",\n installNote: \"the pip wrapper fetches pyright's npm package on first run and needs Node on PATH; `npm install -g pyright` also works\",\n expect: { successCodes: new Set([0, 1]) },\n};\n\ninterface PyrightDiagnostic {\n file: string;\n severity: string;\n message: string;\n rule?: string;\n range: { start: { line: number; character: number }; end: { line: number } };\n}\n\nexport interface PyrightOptions extends AuditOptions {\n /** The interpreter whose site-packages pyright resolves third-party imports from. */\n pythonPath?: string;\n}\n\nfunction toDiagnostic(d: PyrightDiagnostic & { rule: string }): CheckDiagnostic {\n return {\n file: d.file,\n line: d.range.start.line + 1,\n endLine: d.range.end.line + 1,\n column: d.range.start.character + 1,\n severity: \"warn\",\n message: d.message,\n category: \"redundant-check\",\n rule: `pyright/${d.rule}`,\n fixable: false,\n };\n}\n\n// A diagnostic without a rule is a syntax error; the file is reported once, as ruff's runner does.\nfunction unparsedFiles(entries: PyrightDiagnostic[]): ToolFailure[] {\n const byFile = new Map<string, string[]>();\n for (const e of entries.filter((d) => !d.rule && d.severity === \"error\")) {\n byFile.set(e.file, [...(byFile.get(e.file) ?? []), e.message]);\n }\n return [...byFile].map(([file, messages]) => ({ tool: \"pyright\", kind: \"file-not-checked\", file, message: messages.join(\"; \") }));\n}\n\nexport function parsePyrightOutput({ stdout }: ToolOutput): ParsedOutput {\n const entries = (JSON.parse(stdout) as { generalDiagnostics: PyrightDiagnostic[] }).generalDiagnostics;\n const audited = entries.filter((d): d is PyrightDiagnostic & { rule: string } => AUDIT_PYRIGHT_RULES.includes(d.rule ?? \"\"));\n return { diagnostics: audited.map(toDiagnostic), failures: unparsedFiles(entries) };\n}\n\n/** Redundant isinstance, comparison, contains and cast findings from pyright; rule ids are pyright/<rule>. */\nexport async function runPyrightAudit(files: string[], options?: PyrightOptions): Promise<RunnerResult> {\n const tempDir = mkdtempSync(join(tmpdir(), \"style-checker-pyright-\"));\n try {\n const configPath = join(tempDir, \"pyrightconfig.json\");\n writeFileSync(configPath, JSON.stringify(generatePyrightAuditConfig(auditRoot(options?.cwd))), \"utf-8\");\n const python = options?.pythonPath ? [\"--pythonpath\", options.pythonPath] : [];\n return await runPythonTool(PYRIGHT, [\"--outputjson\", \"-p\", configPath, ...python, ...files], options, parsePyrightOutput);\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { findImportLinterConfig } from \"./import-linter-config.js\";\nimport type { ImportLinterConfig } from \"./import-linter-config.js\";\nimport { parseBrokenChains } from \"./import-linter-output.js\";\nimport type { BrokenChain } from \"./import-linter-output.js\";\nimport { auditRoot } from \"./paths.js\";\nimport { emptyResult, runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// lint-imports exits 1 when a contract is broken.\nconst IMPORT_LINTER: PythonToolSpec = {\n tool: \"import-linter\",\n command: \"lint-imports\",\n install: \"pip install import-linter\",\n expect: { successCodes: new Set([0, 1]) },\n};\n\nexport const NO_IMPORT_LINTER_CONFIG = \"no import-linter config\";\n\nfunction slug(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\");\n}\n\n/** The importing module's source file, tried at the root and under src/. */\nexport function moduleFile(root: string, module: string): string | undefined {\n const base = module.replace(/\\./g, \"/\");\n const candidates = [\"\", \"src/\"].flatMap((dir) => [`${dir}${base}.py`, `${dir}${base}/__init__.py`]);\n return candidates.find((c) => existsSync(join(root, c)));\n}\n\nfunction toDiagnostic(chain: BrokenChain, config: ImportLinterConfig, root: string): CheckDiagnostic {\n const first = chain.links[0]!;\n const file = moduleFile(root, first.importer);\n const path = [first.importer, ...chain.links.map((l) => l.imported)].join(\" -> \");\n return {\n file: file ?? chain.contract,\n line: file ? (first.lines[0] ?? 1) : 1,\n column: 1,\n severity: \"error\",\n message: `${chain.summary}: ${path}`,\n category: \"architecture\",\n rule: `import-linter/${config.contractIds.get(chain.contract) ?? slug(chain.contract)}`,\n fixable: false,\n };\n}\n\nfunction parser(config: ImportLinterConfig, root: string): (output: ToolOutput) => ParsedOutput {\n return ({ stdout }) => {\n const chains = parseBrokenChains(stdout);\n if (chains.length === 0 && /\\bBROKEN$/m.test(stdout)) throw new Error(\"lint-imports reported a broken contract but no import chain could be read\");\n return { diagnostics: chains.map((c) => toDiagnostic(c, config, root)), failures: [] };\n };\n}\n\n/** One diagnostic per broken import chain; runs only when the project configures import-linter. */\nexport function runImportLinter(options?: AuditOptions): Promise<RunnerResult> {\n const root = auditRoot(options?.cwd);\n const config = findImportLinterConfig(root);\n if (!config) return Promise.resolve(emptyResult(null, { warnings: [NO_IMPORT_LINTER_CONFIG] }));\n const args = [\"--config\", config.path, \"--no-logo\", \"--no-cache\"];\n return runPythonTool(IMPORT_LINTER, args, options, parser(config, root));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface ImportLinterConfig {\n path: string;\n /** Contract name to contract id; lint-imports prints names, the rule id wants the id. */\n contractIds: Map<string, string>;\n}\n\n// import-linter takes the id from the last colon-separated part of an importlinter: section name.\nconst INI_CONTRACT = /^\\[importlinter:(?:.*:)?([^:\\]]+)\\]$/;\n\nfunction iniContractIds(text: string): Map<string, string> {\n const ids = new Map<string, string>();\n let current: string | undefined;\n for (const line of text.split(\"\\n\").map((l) => l.trim())) {\n if (line.startsWith(\"[\")) current = INI_CONTRACT.exec(line)?.[1];\n const name = current && /^name\\s*[=:]\\s*(.+)$/.exec(line);\n if (current && name) ids.set(name[1]!.trim(), current);\n }\n return ids;\n}\n\nfunction tomlValue(block: string, key: string): string | undefined {\n return new RegExp(`^${key}\\\\s*=\\\\s*[\"'](.+?)[\"']\\\\s*$`, \"m\").exec(block)?.[1];\n}\n\nfunction tomlContractIds(text: string): Map<string, string> {\n const ids = new Map<string, string>();\n for (const chunk of text.split(/^\\[\\[tool\\.importlinter\\.contracts\\]\\]\\s*$/m).slice(1)) {\n const block = chunk.split(/^\\[/m)[0]!;\n const name = tomlValue(block, \"name\");\n const id = tomlValue(block, \"id\");\n if (name && id) ids.set(name, id);\n }\n return ids;\n}\n\nfunction readIfContains(path: string, marker: RegExp): string | undefined {\n if (!existsSync(path)) return undefined;\n const text = readFileSync(path, \"utf-8\");\n return marker.test(text) ? text : undefined;\n}\n\n/** The config lint-imports would use, in its own lookup order: setup.cfg, .importlinter, then pyproject.toml. */\nexport function findImportLinterConfig(cwd: string): ImportLinterConfig | undefined {\n for (const name of [\"setup.cfg\", \".importlinter\"]) {\n const ini = readIfContains(join(cwd, name), /^\\[importlinter\\]/m);\n if (ini !== undefined) return { path: join(cwd, name), contractIds: iniContractIds(ini) };\n }\n const toml = readIfContains(join(cwd, \"pyproject.toml\"), /^\\[tool\\.importlinter\\]/m);\n if (toml !== undefined) return { path: join(cwd, \"pyproject.toml\"), contractIds: tomlContractIds(toml) };\n return undefined;\n}\n","/** One import in a chain: `importer` imports `imported` on the given lines. */\nexport interface ImportLink {\n importer: string;\n imported: string;\n lines: number[];\n}\n\n/** One broken import chain, under the contract name and the sentence lint-imports prints above it. */\nexport interface BrokenChain {\n contract: string;\n summary: string;\n links: ImportLink[];\n}\n\nconst LINK = /^(-)?\\s+(\\S+) -> (\\S+) \\(l\\.([\\d, ?]+)\\)$/;\nconst SUMMARY = /^(\\S.* is not allowed to import \\S.*):$/;\n\nfunction isUnderline(line: string | undefined, heading: string): boolean {\n return line !== undefined && /^-+$/.test(line) && line.length === heading.length;\n}\n\nfunction toLink(m: RegExpExecArray): ImportLink {\n const lines = m[4]!.split(\",\").map((n) => Number(n.trim())).filter((n) => Number.isInteger(n) && n > 0);\n return { importer: m[2]!, imported: m[3]!, lines };\n}\n\n/** Reads the \"Broken contracts\" section; a chain starts at a \"-\" line and continues on indented lines. */\nexport function parseBrokenChains(stdout: string): BrokenChain[] {\n const lines = stdout.split(\"\\n\");\n const start = lines.findIndex((l, i) => l === \"Broken contracts\" && isUnderline(lines[i + 1], l));\n if (start < 0) return [];\n const chains: BrokenChain[] = [];\n let contract = \"\";\n let summary = \"\";\n for (let i = start + 2; i < lines.length; i++) {\n const line = lines[i]!;\n const link = LINK.exec(line);\n if (isUnderline(lines[i + 1], line) && line.trim()) contract = line;\n else if (SUMMARY.test(line)) summary = SUMMARY.exec(line)![1]!;\n else if (link?.[1]) chains.push({ contract, summary, links: [toLink(link)] });\n else if (link && chains.length > 0) chains.at(-1)!.links.push(toLink(link));\n }\n return chains;\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { emptyResult } from \"./python-tool.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// A text scan, not a tokenizer: a marker inside a string literal counts too.\nconst NOQA = /#\\s*noqa\\b(?::\\s*([A-Z]+\\d+(?:[\\s,]+[A-Z]+\\d+)*))?/gi;\nconst TYPE_IGNORE = /#\\s*type:\\s*ignore\\b(?:\\[([^\\]]*)\\])?/g;\n\nexport const NOQA_RULE = \"suppression/noqa\";\nexport const TYPE_IGNORE_RULE = \"suppression/type-ignore\";\n\nfunction codesOf(raw: string | undefined): string[] {\n return raw ? raw.split(/[\\s,]+/).filter(Boolean) : [];\n}\n\nfunction marker(file: string, line: number, m: RegExpMatchArray, rule: string, label: string): CheckDiagnostic {\n const codes = codesOf(m[1]);\n const message = codes.length ? `${label} suppresses ${codes.join(\", \")}` : `blanket ${label} suppresses every check on this line`;\n return { file, line, column: (m.index ?? 0) + 1, severity: \"warn\", message, category: \"suppression\", rule, fixable: false };\n}\n\n/** Every `# noqa` and `# type: ignore` marker in one file's text, one diagnostic per occurrence. */\nexport function findSuppressions(file: string, text: string): CheckDiagnostic[] {\n return text.split(\"\\n\").flatMap((content, i) => [\n ...[...content.matchAll(NOQA)].map((m) => marker(file, i + 1, m, NOQA_RULE, \"noqa\")),\n ...[...content.matchAll(TYPE_IGNORE)].map((m) => marker(file, i + 1, m, TYPE_IGNORE_RULE, \"type: ignore\")),\n ]);\n}\n\n/** Suppression markers across `files`, read from disk relative to `cwd`; no tool is run. */\nexport function countSuppressions(files: string[], options?: { cwd?: string }): RunnerResult {\n const root = auditRoot(options?.cwd);\n const diagnostics: CheckDiagnostic[] = [];\n const failures: ToolFailure[] = [];\n for (const file of files) {\n const shown = relativeTo(root, resolve(root, file));\n try {\n diagnostics.push(...findSuppressions(shown, readFileSync(resolve(root, file), \"utf-8\")));\n } catch (err) {\n failures.push({ tool: \"suppressions\", kind: \"file-not-checked\", file: shown, message: (err as Error).message });\n }\n }\n return emptyResult(0, { diagnostics, failures });\n}\n\nexport interface SuppressionCounts {\n noqa: number;\n typeIgnore: number;\n}\n\nexport interface SuppressionTotals extends SuppressionCounts {\n byFile: Record<string, SuppressionCounts>;\n}\n\n/** Totals of countSuppressions' diagnostics, overall and per file; other diagnostics are ignored. */\nexport function suppressionTotals(diagnostics: CheckDiagnostic[]): SuppressionTotals {\n const totals: SuppressionTotals = { noqa: 0, typeIgnore: 0, byFile: {} };\n for (const d of diagnostics) {\n const key = d.rule === NOQA_RULE ? \"noqa\" : d.rule === TYPE_IGNORE_RULE ? \"typeIgnore\" : undefined;\n if (!key) continue;\n const file = (totals.byFile[d.file] ??= { noqa: 0, typeIgnore: 0 });\n file[key] += 1;\n totals[key] += 1;\n }\n return totals;\n}\n","import { PROFILE_CATEGORIES } from \"@titan-design/style-profile\";\nimport type { Profile, ProfileCategory } from \"@titan-design/style-profile\";\nimport type { Observation } from \"@titan-design/style-analyzer\";\n\nexport interface Deviation {\n file: string;\n line: number;\n rule: string;\n expected: string;\n found: string;\n severity: \"error\" | \"warn\" | \"info\";\n}\n\nexport interface DiffResult {\n deviations: Deviation[];\n summary: {\n total: number;\n matching: number;\n deviating: number;\n };\n}\n\nfunction getSeverity(\n confidence: number,\n thresholds: Profile[\"severityThresholds\"],\n): \"error\" | \"warn\" | \"info\" {\n if (confidence >= thresholds.error) return \"error\";\n if (confidence >= thresholds.warn) return \"warn\";\n return \"info\";\n}\n\nfunction resolveProfileRule(\n profile: Profile,\n observationType: string,\n): { convention: unknown; confidence: number } | undefined {\n const [category, rule] = observationType.split(\".\");\n if (!PROFILE_CATEGORIES.includes(category as ProfileCategory)) return undefined;\n const section = profile[category as ProfileCategory];\n if (!section || typeof section !== \"object\") return undefined;\n const ruleObj = rule === undefined ? undefined : section[rule];\n if (!ruleObj || typeof ruleObj !== \"object\") return undefined;\n if (ruleObj.convention === undefined || ruleObj.confidence === undefined) {\n return undefined;\n }\n return { convention: ruleObj.convention, confidence: ruleObj.confidence };\n}\n\nexport function diffAgainstProfile(\n profile: Profile,\n observations: Observation[],\n): DiffResult {\n const deviations: Deviation[] = [];\n let matching = 0;\n\n for (const obs of observations) {\n const profileRule = resolveProfileRule(profile, obs.type);\n if (!profileRule) continue;\n\n const expected = String(profileRule.convention);\n const found = String(obs.value);\n\n if (found === expected) {\n matching++;\n } else {\n deviations.push({\n file: obs.file,\n line: obs.line,\n rule: obs.type,\n expected,\n found,\n severity: getSeverity(\n profileRule.confidence,\n profile.severityThresholds,\n ),\n });\n }\n }\n\n return {\n deviations,\n summary: {\n total: observations.length,\n matching,\n deviating: deviations.length,\n },\n };\n}\n"],"mappings":"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","names":["join","resolve","require","parser","join","writeFileSync","mkdtempSync","rmSync","join","tmpdir","mkdtempSync","join","tmpdir","writeFileSync","rmSync","toDiagnostic","notChecked","mkdtempSync","rmSync","writeFileSync","tmpdir","join","toDiagnostic","unparsedFiles","mkdtempSync","join","tmpdir","writeFileSync","rmSync","existsSync","join","join","marker","existsSync","join","toDiagnostic","readFileSync","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/generators/eslint.ts","../src/generators/ruff.ts","../src/runners/eslint-runner.ts","../src/runners/tool-runner.ts","../src/runners/failures.ts","../src/runners/eslint-plugins.ts","../src/runners/eslint-config-module.ts","../src/formatters/unified.ts","../src/runners/ruff-runner.ts","../src/orchestrator/orchestrate.ts","../src/generators/ruff-audit.ts","../src/runners/paths.ts","../src/runners/ruff-audit.ts","../src/generators/pyright-audit.ts","../src/runners/python-tool.ts","../src/runners/vulture-audit.ts","../src/runners/pydoclint-audit.ts","../src/runners/pyright-audit.ts","../src/runners/import-linter.ts","../src/runners/import-linter-config.ts","../src/runners/import-linter-output.ts","../src/runners/suppressions.ts","../src/profile-diff/diff-against-profile.ts"],"sourcesContent":["import type { Profile } from \"@titan-design/style-profile\";\nimport {\n buildNamingConvention,\n buildImportOrderRule,\n buildFunctionLengthRule,\n buildFileNamingRule,\n buildJsdocRules,\n} from \"@titan-design/style-profile\";\nimport type { SkippedRule } from \"../orchestrator/types.js\";\n\nexport interface EslintFlatConfigEntry {\n plugins?: Record<string, unknown>;\n rules?: Record<string, unknown>;\n files?: string[];\n}\n\nexport interface EslintConfigResult {\n entries: EslintFlatConfigEntry[];\n skippedRules: SkippedRule[];\n}\n\n// ESLint accepts only off, warn and error; style-profile's \"info\" tier becomes warn, as its own exporter does.\nfunction withEslintSeverity(value: unknown): unknown {\n if (Array.isArray(value) && value[0] === \"info\") return [\"warn\", ...value.slice(1)];\n return value === \"info\" ? \"warn\" : value;\n}\n\nfunction collectRules(profile: Profile, skippedRules: SkippedRule[]): Record<string, unknown> {\n const rules: Record<string, unknown> = {};\n\n const { rule: namingRule, skippedRules: namingSkipped } = buildNamingConvention(profile);\n if (namingRule) rules[namingRule[0]] = namingRule[1];\n skippedRules.push(...namingSkipped);\n\n const importRule = buildImportOrderRule(profile);\n if (importRule) rules[importRule[0]] = importRule[1];\n\n const fnLengthRule = buildFunctionLengthRule(profile);\n if (fnLengthRule) rules[fnLengthRule[0]] = fnLengthRule[1];\n\n const fileNamingRule = buildFileNamingRule(profile);\n if (fileNamingRule) rules[fileNamingRule[0]] = fileNamingRule[1];\n\n const jsdocRules = buildJsdocRules(profile);\n for (const [name, value] of jsdocRules) {\n rules[name] = value;\n }\n\n for (const name of Object.keys(rules)) rules[name] = withEslintSeverity(rules[name]);\n return rules;\n}\n\nexport function generateEslintConfig(profile: Profile): EslintConfigResult {\n const entries: EslintFlatConfigEntry[] = [];\n const skippedRules: SkippedRule[] = [];\n const rules = collectRules(profile, skippedRules);\n\n if (Object.keys(rules).length > 0) {\n entries.push({\n files: [\"**/*.ts\", \"**/*.tsx\"],\n rules,\n });\n }\n\n return { entries, skippedRules };\n}\n","import type { Profile } from \"@titan-design/style-profile\";\n\nexport interface RuffConfig {\n lint?: {\n select?: string[];\n ignore?: string[];\n fixable?: string[];\n \"per-file-ignores\"?: Record<string, string[]>;\n mccabe?: { \"max-complexity\"?: number };\n pydocstyle?: { convention?: string };\n isort?: {\n \"known-first-party\"?: string[];\n \"section-order\"?: string[];\n };\n };\n \"line-length\"?: number;\n preview?: boolean;\n}\n\ntype RuffLint = NonNullable<RuffConfig[\"lint\"]> & { select: string[] };\n\nfunction addNaming(profile: Profile, lint: RuffLint): void {\n if (profile.naming) {\n const hasNamingRules = Object.values(profile.naming).some(\n (rule) => rule.confidence >= profile.severityThresholds.info,\n );\n if (hasNamingRules) lint.select.push(\"N\");\n }\n}\n\nfunction addImportOrder(profile: Profile, lint: RuffLint): void {\n const importOrder = profile.structure?.importOrder;\n if (importOrder && importOrder.confidence >= profile.severityThresholds.info) {\n lint.select.push(\"I\");\n if (Array.isArray(importOrder.convention)) {\n lint.isort = {\n \"section-order\": importOrder.convention as string[],\n };\n }\n }\n}\n\nfunction addFunctionDocs(profile: Profile, lint: RuffLint): void {\n const functionDocs = profile.documentation?.functionDocs;\n if (functionDocs && functionDocs.confidence >= profile.severityThresholds.info) {\n lint.select.push(\"D\");\n const conv = functionDocs.convention;\n if (\n typeof conv === \"string\" &&\n conv !== \"jsdoc-selective\" &&\n conv !== \"jsdoc-all\"\n ) {\n lint.pydocstyle = { convention: conv };\n }\n }\n}\n\nfunction addComplexity(profile: Profile, lint: RuffLint): void {\n const maxLines = profile.structure?.functionMaxLines;\n if (\n maxLines &&\n maxLines.confidence >= profile.severityThresholds.info &&\n typeof maxLines.convention === \"number\"\n ) {\n lint.select.push(\"C90\");\n lint.mccabe = { \"max-complexity\": maxLines.convention };\n }\n}\n\nexport function generateRuffConfig(profile: Profile): RuffConfig {\n const lint: RuffLint = { select: [] };\n const config: RuffConfig = { lint };\n\n addNaming(profile, lint);\n addImportOrder(profile, lint);\n addFunctionDocs(profile, lint);\n addComplexity(profile, lint);\n\n const lineLength = profile.formatting?.lineLength;\n if (lineLength && typeof lineLength.convention === \"number\") {\n config[\"line-length\"] = lineLength.convention;\n }\n\n return config;\n}\n","import { writeFileSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { runAndClassify, parseOrFail } from \"./failures.js\";\nimport { buildEslintConfigModule } from \"./eslint-config-module.js\";\nimport { parseEslintJsonOutput } from \"../formatters/unified.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { EslintFlatConfigEntry } from \"../generators/eslint.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\ninterface EslintJsonMessage {\n ruleId: string | null;\n fatal?: boolean;\n message: string;\n}\n\n// ESLint reports a file it could not lint as a rule-less message: a fatal parse error, or \"File ignored ...\".\nfunction uncheckedFiles(stdout: string): ToolFailure[] {\n const entries = JSON.parse(stdout) as Array<{ filePath: string; messages: EslintJsonMessage[] }>;\n return entries.flatMap((entry) =>\n entry.messages\n .filter((m) => m.ruleId === null && (m.fatal === true || m.message.startsWith(\"File ignored\")))\n .map((m) => ({ tool: \"eslint\" as const, kind: \"file-not-checked\" as const, file: entry.filePath, message: m.message })),\n );\n}\n\nfunction readEslintOutput(stdout: string): { diagnostics: CheckDiagnostic[]; failures: ToolFailure[] } {\n const parsed = parseOrFail(\"eslint\", () => ({\n diagnostics: parseEslintJsonOutput(stdout),\n failures: uncheckedFiles(stdout),\n }));\n return parsed.ok ? parsed.value : { diagnostics: [], failures: [parsed.failure] };\n}\n\nfunction eslintArgs(configPath: string, files: string[], fix?: boolean): string[] {\n // --no stops npx from downloading an ESLint the project has not installed.\n return [\"--no\", \"--\", \"eslint\", \"--config\", configPath, \"--format\", \"json\", ...(fix ? [\"--fix\"] : []), ...files];\n}\n\nexport async function runEslint(\n config: EslintFlatConfigEntry[],\n files: string[],\n options?: RunnerOptions,\n): Promise<RunnerResult> {\n const cwd = options?.cwd ?? process.cwd();\n const built = buildEslintConfigModule(config, cwd);\n if (!built.ok) return { diagnostics: [], exitCode: null, failures: [built.failure], skippedRules: [] };\n const { skippedRules } = built;\n if (built.ruleCount === 0) return { diagnostics: [], exitCode: null, failures: [], skippedRules };\n\n const tempDir = mkdtempSync(join(tmpdir(), \"codewatch-eslint-\"));\n const configPath = join(tempDir, \"eslint.config.mjs\");\n try {\n writeFileSync(configPath, built.source, \"utf-8\");\n const run = await runAndClassify(\"eslint\", \"npx\", eslintArgs(configPath, files, options?.fix), {\n cwd,\n timeout: options?.timeout,\n });\n if (!run.ok) return { diagnostics: [], exitCode: run.exitCode, failures: [run.failure], skippedRules };\n return { ...readEslintOutput(run.stdout), exitCode: run.exitCode, skippedRules };\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { spawn } from \"node:child_process\";\n\nexport interface ToolRunResult {\n stdout: string;\n stderr: string;\n /** Null when the child was killed by a signal; see `signal`. */\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n timedOut: boolean;\n}\n\nexport function runTool(\n command: string,\n args: string[],\n options?: { cwd?: string; timeout?: number },\n): Promise<ToolRunResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd: options?.cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n const chunks: Buffer[] = [];\n const errChunks: Buffer[] = [];\n let timedOut = false;\n // Our own timer, because spawn's `timeout` option kills without telling us it did.\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, options?.timeout ?? 60_000);\n\n child.stdout.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n child.stderr.on(\"data\", (chunk: Buffer) => errChunks.push(chunk));\n\n child.on(\"error\", (err) => {\n clearTimeout(timer);\n reject(new Error(`Failed to spawn ${command}: ${err.message}`));\n });\n\n child.on(\"close\", (code, signal) => {\n clearTimeout(timer);\n resolve({\n stdout: Buffer.concat(chunks).toString(\"utf-8\"),\n stderr: Buffer.concat(errChunks).toString(\"utf-8\"),\n exitCode: code,\n signal,\n timedOut,\n });\n });\n });\n}\n","import { runTool } from \"./tool-runner.js\";\nimport type { ToolRunResult } from \"./tool-runner.js\";\nimport type { ToolFailure, ToolName } from \"../orchestrator/types.js\";\n\n// ESLint and ruff both document 0 (clean) and 1 (problems found) as successful runs.\nconst SUCCESS_EXIT_CODES = new Set([0, 1]);\n\nexport type ToolRun =\n | { ok: true; stdout: string; stderr: string; exitCode: number }\n | { ok: false; failure: ToolFailure; exitCode: number | null };\n\nfunction excerpt(text: string): string {\n const trimmed = text.trim();\n return trimmed.length > 500 ? `${trimmed.slice(0, 500)}…` : trimmed;\n}\n\nfunction withStderr(message: string, stderr: string): string {\n const detail = excerpt(stderr);\n return detail ? `${message}: ${detail}` : message;\n}\n\n/** What counts as a successful run; vulture exits 3 on findings, and a clean vulture or pydoclint run prints nothing. */\nexport interface RunExpectations {\n successCodes?: ReadonlySet<number>;\n allowEmptyStdout?: boolean;\n}\n\nexport function classifyRun(tool: ToolName, run: ToolRunResult, expect: RunExpectations = {}): ToolRun {\n const fail = (kind: ToolFailure[\"kind\"], message: string): ToolRun => ({\n ok: false,\n failure: { tool, kind, message: withStderr(message, run.stderr) },\n exitCode: run.exitCode,\n });\n if (run.timedOut) return fail(\"timeout\", `${tool} timed out and was killed`);\n if (run.exitCode === null) {\n return fail(\"signal\", `${tool} was killed by ${run.signal ?? \"a signal\"}`);\n }\n if (!(expect.successCodes ?? SUCCESS_EXIT_CODES).has(run.exitCode)) {\n return fail(\"exit-code\", `${tool} exited with code ${run.exitCode}`);\n }\n if (!expect.allowEmptyStdout && !run.stdout.trim()) {\n return fail(\"unparseable-output\", `${tool} exited ${run.exitCode} with no output`);\n }\n return { ok: true, stdout: run.stdout, stderr: run.stderr, exitCode: run.exitCode };\n}\n\nexport async function runAndClassify(\n tool: ToolName,\n command: string,\n args: string[],\n options?: { cwd?: string; timeout?: number },\n expect?: RunExpectations,\n): Promise<ToolRun> {\n try {\n return classifyRun(tool, await runTool(command, args, options), expect);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, failure: { tool, kind: \"spawn-failed\", message }, exitCode: null };\n }\n}\n\nexport function parseOrFail<T>(\n tool: ToolName,\n parse: () => T,\n): { ok: true; value: T } | { ok: false; failure: ToolFailure } {\n try {\n return { ok: true, value: parse() };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, failure: { tool, kind: \"unparseable-output\", message } };\n }\n}\n","import { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nexport interface ModuleSource {\n specifier: string;\n member?: \"plugin\" | \"parser\";\n}\n\nexport interface ResolvedModule {\n url: string;\n member?: \"plugin\" | \"parser\";\n}\n\n// The typescript-eslint meta-package is the fallback because under pnpm it is often the only one a project can resolve.\nexport const PLUGIN_SOURCES: Record<string, ModuleSource[]> = {\n \"@typescript-eslint\": [\n { specifier: \"@typescript-eslint/eslint-plugin\" },\n { specifier: \"typescript-eslint\", member: \"plugin\" },\n ],\n perfectionist: [{ specifier: \"eslint-plugin-perfectionist\" }],\n unicorn: [{ specifier: \"eslint-plugin-unicorn\" }],\n jsdoc: [{ specifier: \"eslint-plugin-jsdoc\" }],\n};\n\nexport const PARSER_SOURCES: ModuleSource[] = [\n { specifier: \"@typescript-eslint/parser\" },\n { specifier: \"typescript-eslint\", member: \"parser\" },\n];\n\nexport function pluginNamespace(rule: string): string | null {\n const slash = rule.lastIndexOf(\"/\");\n return slash === -1 ? null : rule.slice(0, slash);\n}\n\nexport function describeSources(sources: ModuleSource[]): string {\n return sources.map((s) => s.specifier).join(\" or \");\n}\n\nexport function resolveModule(\n sources: ModuleSource[],\n fromDir: string,\n): ResolvedModule | null {\n // Resolve from the project, not from this package: ESLint runs there and loads plugins from there.\n const require = createRequire(join(fromDir, \"package.json\"));\n for (const source of sources) {\n try {\n const url = pathToFileURL(require.resolve(source.specifier)).href;\n return { url, member: source.member };\n } catch {\n continue;\n }\n }\n return null;\n}\n","import {\n PARSER_SOURCES,\n PLUGIN_SOURCES,\n describeSources,\n pluginNamespace,\n resolveModule,\n} from \"./eslint-plugins.js\";\nimport type { ResolvedModule } from \"./eslint-plugins.js\";\nimport type { EslintFlatConfigEntry } from \"../generators/eslint.js\";\nimport type { SkippedRule, ToolFailure } from \"../orchestrator/types.js\";\n\nexport type EslintConfigModule =\n | { ok: true; source: string; ruleCount: number; skippedRules: SkippedRule[] }\n | { ok: false; failure: ToolFailure };\n\ninterface ModuleContext {\n fromDir: string;\n imports: string[];\n ids: Map<string, string>;\n plugins: Map<string, ResolvedModule | null>;\n}\n\nfunction importExpr(ctx: ModuleContext, mod: ResolvedModule): string {\n let id = ctx.ids.get(mod.url);\n if (!id) {\n id = `m${ctx.ids.size}`;\n ctx.ids.set(mod.url, id);\n ctx.imports.push(`import ${id} from ${JSON.stringify(mod.url)};`);\n }\n return mod.member ? `${id}.${mod.member}` : id;\n}\n\nfunction resolvePlugin(ctx: ModuleContext, namespace: string): ResolvedModule | null {\n if (!ctx.plugins.has(namespace)) {\n const sources = PLUGIN_SOURCES[namespace];\n ctx.plugins.set(namespace, sources ? resolveModule(sources, ctx.fromDir) : null);\n }\n return ctx.plugins.get(namespace) ?? null;\n}\n\nfunction skipReason(ctx: ModuleContext, namespace: string): string {\n const sources = PLUGIN_SOURCES[namespace];\n if (!sources) return `no known package provides the ESLint plugin \"${namespace}\"`;\n return `${describeSources(sources)} is not installed in ${ctx.fromDir}`;\n}\n\nfunction renderEntry(\n ctx: ModuleContext,\n entry: EslintFlatConfigEntry,\n parserExpr: string,\n skipped: SkippedRule[],\n): { text: string; ruleCount: number } {\n const rules: Record<string, unknown> = {};\n const plugins: string[] = [];\n for (const [rule, value] of Object.entries(entry.rules ?? {})) {\n const namespace = pluginNamespace(rule);\n const plugin = namespace === null ? null : resolvePlugin(ctx, namespace);\n if (namespace !== null && !plugin) {\n skipped.push({ tool: \"eslint\", rule, plugin: namespace, reason: skipReason(ctx, namespace) });\n continue;\n }\n rules[rule] = value;\n if (namespace !== null && plugin) plugins.push(`${JSON.stringify(namespace)}: ${importExpr(ctx, plugin)}`);\n }\n const data = JSON.stringify({ files: entry.files, rules });\n const text = `{ ...${data}, languageOptions: { parser: ${parserExpr} }, plugins: { ${[...new Set(plugins)].join(\", \")} } }`;\n return { text, ruleCount: Object.keys(rules).length };\n}\n\nexport function buildEslintConfigModule(\n config: EslintFlatConfigEntry[],\n fromDir: string,\n): EslintConfigModule {\n const parser = resolveModule(PARSER_SOURCES, fromDir);\n if (!parser) {\n const message = `${describeSources(PARSER_SOURCES)} is not installed in ${fromDir}, so ESLint cannot parse TypeScript`;\n return { ok: false, failure: { tool: \"eslint\", kind: \"missing-dependency\", message } };\n }\n const ctx: ModuleContext = { fromDir, imports: [], ids: new Map(), plugins: new Map() };\n const parserExpr = importExpr(ctx, parser);\n const skippedRules: SkippedRule[] = [];\n const entries = config.map((entry) => renderEntry(ctx, entry, parserExpr, skippedRules));\n const ruleCount = entries.reduce((sum, e) => sum + e.ruleCount, 0);\n const body = entries.map((e) => e.text).join(\",\\n \");\n const source = `${ctx.imports.join(\"\\n\")}\\n\\nexport default [\\n ${body},\\n];\\n`;\n return { ok: true, source, ruleCount, skippedRules };\n}\n","import type { CheckDiagnostic } from \"../orchestrator/types.js\";\n\nconst RUFF_CODE_CATEGORY: Record<string, string> = {\n N: \"naming\",\n I: \"imports\",\n D: \"documentation\",\n C: \"complexity\",\n E: \"formatting\",\n W: \"formatting\",\n F: \"errors\",\n};\n\nconst ESLINT_RULE_CATEGORY: Record<string, string> = {\n \"@typescript-eslint/naming-convention\": \"naming\",\n \"unicorn/filename-case\": \"naming\",\n \"perfectionist/sort-imports\": \"imports\",\n \"import/order\": \"imports\",\n \"max-lines-per-function\": \"structure\",\n \"max-depth\": \"structure\",\n \"jsdoc/require-jsdoc\": \"documentation\",\n};\n\nfunction eslintSeverityToSeverity(eslintSeverity: number): \"error\" | \"warn\" {\n return eslintSeverity === 2 ? \"error\" : \"warn\";\n}\n\nfunction categorizeEslintRule(ruleId: string): string {\n if (ESLINT_RULE_CATEGORY[ruleId]) return ESLINT_RULE_CATEGORY[ruleId];\n if (ruleId.startsWith(\"@typescript-eslint/\")) return \"typescript\";\n if (ruleId.startsWith(\"jsdoc/\")) return \"documentation\";\n if (ruleId.startsWith(\"unicorn/\")) return \"style\";\n if (ruleId.startsWith(\"import/\")) return \"imports\";\n return \"other\";\n}\n\nfunction categorizeRuffCode(code: string): string {\n const prefix = code.replace(/[0-9]/g, \"\");\n return RUFF_CODE_CATEGORY[prefix] ?? \"other\";\n}\n\ninterface EslintJsonEntry {\n filePath: string;\n messages: Array<{\n ruleId: string | null;\n severity: number;\n message: string;\n line: number;\n column: number;\n fix?: { range: [number, number]; text: string } | null;\n }>;\n}\n\ninterface RuffJsonEntry {\n code: string | null;\n message: string;\n filename: string;\n location: { row: number; column: number };\n end_location: { row: number; column: number };\n fix?: {\n edits: Array<{\n content: string;\n location: { row: number; column: number };\n end_location: { row: number; column: number };\n }>;\n } | null;\n}\n\nexport function parseEslintJsonOutput(jsonStr: string): CheckDiagnostic[] {\n let entries: EslintJsonEntry[];\n try {\n entries = JSON.parse(jsonStr);\n } catch {\n throw new Error(\n `Failed to parse ESLint JSON output. Raw output:\\n${jsonStr.slice(0, 500)}`,\n );\n }\n const diagnostics: CheckDiagnostic[] = [];\n\n for (const entry of entries) {\n for (const msg of entry.messages) {\n if (!msg.ruleId) continue;\n diagnostics.push({\n file: entry.filePath,\n line: msg.line,\n column: msg.column,\n severity: eslintSeverityToSeverity(msg.severity),\n message: msg.message,\n category: categorizeEslintRule(msg.ruleId),\n rule: msg.ruleId,\n fixable: msg.fix != null,\n fix: msg.fix ?? undefined,\n });\n }\n }\n\n return diagnostics;\n}\n\n// ruff 0.16.8 reports a syntax error as code \"invalid-syntax\"; 0.9.10 used a null code.\nexport function isRuffSyntaxError(code: string | null): code is \"invalid-syntax\" | null {\n return code === null || code === \"invalid-syntax\";\n}\n\nexport function parseRuffJsonOutput(jsonStr: string): CheckDiagnostic[] {\n let entries: RuffJsonEntry[];\n try {\n entries = JSON.parse(jsonStr);\n } catch {\n throw new Error(\n `Failed to parse Ruff JSON output. Raw output:\\n${jsonStr.slice(0, 500)}`,\n );\n }\n return entries.flatMap((entry) => isRuffSyntaxError(entry.code) ? [] : [{\n file: entry.filename,\n line: entry.location.row,\n endLine: entry.end_location.row,\n column: entry.location.column,\n severity: \"warn\" as const,\n message: entry.message,\n category: categorizeRuffCode(entry.code),\n rule: entry.code,\n fixable: entry.fix != null,\n }]);\n}\n\nexport function formatDiagnostic(d: CheckDiagnostic): string {\n return `${d.file}:${d.line}:${d.column} ${d.severity} ${d.message} [${d.category}.${d.rule}]`;\n}\n","import { writeFileSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { runAndClassify, parseOrFail } from \"./failures.js\";\nimport { isRuffSyntaxError, parseRuffJsonOutput } from \"../formatters/unified.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\nimport type { RuffConfig } from \"../generators/ruff.js\";\n\ntype RuffLint = NonNullable<RuffConfig[\"lint\"]>;\n\nfunction quoteList(values: string[]): string {\n return `[${values.map((s) => `\"${s}\"`).join(\", \")}]`;\n}\n\nfunction lintSelectionLines(lint: RuffLint): string[] {\n const lines: string[] = [];\n if (lint.select) lines.push(`select = ${quoteList(lint.select)}`);\n if (lint.ignore) lines.push(`ignore = ${quoteList(lint.ignore)}`);\n return lines;\n}\n\nfunction lintSubsectionLines(lint: RuffLint): string[] {\n const lines: string[] = [];\n if (lint.mccabe) {\n lines.push(\"[lint.mccabe]\");\n if (lint.mccabe[\"max-complexity\"]) {\n lines.push(`max-complexity = ${lint.mccabe[\"max-complexity\"]}`);\n }\n }\n if (lint.pydocstyle) {\n lines.push(\"[lint.pydocstyle]\");\n if (lint.pydocstyle.convention) {\n lines.push(`convention = \"${lint.pydocstyle.convention}\"`);\n }\n }\n if (lint.isort) {\n lines.push(\"[lint.isort]\");\n if (lint.isort[\"section-order\"]) {\n lines.push(`section-order = ${quoteList(lint.isort[\"section-order\"])}`);\n }\n }\n return lines;\n}\n\nfunction toToml(config: RuffConfig): string {\n const lines: string[] = [];\n\n if (config[\"line-length\"]) {\n lines.push(`line-length = ${config[\"line-length\"]}`);\n }\n if (config.preview) lines.push(\"preview = true\");\n\n if (config.lint) {\n lines.push(\"[lint]\", ...lintSelectionLines(config.lint), ...lintSubsectionLines(config.lint));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\ninterface RuffJsonMessage {\n code: string | null;\n filename: string;\n message: string;\n}\n\nfunction notChecked(file: string, message: string): ToolFailure {\n return { tool: \"ruff\", kind: \"file-not-checked\", file, message };\n}\n\n// ruff emits one entry per syntax error; a file that fails to parse is reported once.\nfunction unparsedFiles(stdout: string): ToolFailure[] {\n const byFile = new Map<string, string[]>();\n for (const e of JSON.parse(stdout) as RuffJsonMessage[]) {\n if (!isRuffSyntaxError(e.code)) continue;\n byFile.set(e.filename, [...(byFile.get(e.filename) ?? []), e.message]);\n }\n return [...byFile].map(([file, messages]) => notChecked(file, messages.join(\"; \")));\n}\n\n// ruff 0.16.8 flags an unreadable path (exit 0, \"[]\") only in this stderr wording; if ruff rewords it, the case goes silent again.\nfunction unreadFiles(stderr: string): ToolFailure[] {\n return [...stderr.matchAll(/^warning: Failed to lint (.+?): (.+)$/gm)].map((m) => notChecked(m[1]!, m[2]!));\n}\n\nfunction readRuffOutput(stdout: string, stderr: string): { diagnostics: CheckDiagnostic[]; failures: ToolFailure[] } {\n const parsed = parseOrFail(\"ruff\", () => ({\n diagnostics: parseRuffJsonOutput(stdout),\n failures: [...unparsedFiles(stdout), ...unreadFiles(stderr)],\n }));\n return parsed.ok ? parsed.value : { diagnostics: [], failures: [parsed.failure] };\n}\n\nexport async function runRuff(\n config: RuffConfig,\n files: string[],\n options?: RunnerOptions,\n): Promise<RunnerResult> {\n const tempDir = mkdtempSync(join(tmpdir(), \"codewatch-ruff-\"));\n const configPath = join(tempDir, \"ruff.toml\");\n\n try {\n writeFileSync(configPath, toToml(config), \"utf-8\");\n\n const args = [\n \"check\",\n \"--config\",\n configPath,\n \"--output-format\",\n \"json\",\n ...(options?.fix ? [\"--fix\"] : []),\n ...files,\n ];\n\n const run = await runAndClassify(\"ruff\", \"ruff\", args, { cwd: options?.cwd, timeout: options?.timeout });\n if (!run.ok) return { diagnostics: [], exitCode: run.exitCode, failures: [run.failure], skippedRules: [] };\n return { ...readRuffOutput(run.stdout, run.stderr), exitCode: run.exitCode, skippedRules: [] };\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { generateEslintConfig } from \"../generators/eslint.js\";\nimport { generateRuffConfig } from \"../generators/ruff.js\";\nimport { runEslint } from \"../runners/eslint-runner.js\";\nimport { runRuff } from \"../runners/ruff-runner.js\";\nimport type { RunnerResult } from \"../runners/types.js\";\nimport type {\n OrchestratorOptions,\n OrchestratorResult,\n CheckDiagnostic,\n} from \"./types.js\";\n\nfunction detectLanguage(files: string[]): \"typescript\" | \"python\" | \"mixed\" {\n const tsFiles = files.filter((f) => /\\.[tj]sx?$/.test(f));\n const pyFiles = files.filter((f) => /\\.py$/.test(f));\n if (tsFiles.length > 0 && pyFiles.length === 0) return \"typescript\";\n if (pyFiles.length > 0 && tsFiles.length === 0) return \"python\";\n return \"mixed\";\n}\n\nfunction buildSummary(\n diagnostics: CheckDiagnostic[],\n): OrchestratorResult[\"summary\"] {\n return {\n total: diagnostics.length,\n errors: diagnostics.filter((d) => d.severity === \"error\").length,\n warnings: diagnostics.filter((d) => d.severity === \"warn\").length,\n infos: diagnostics.filter((d) => d.severity === \"info\").length,\n fixed: 0,\n };\n}\n\nasync function runTools(options: OrchestratorOptions): Promise<RunnerResult[]> {\n const { profile, files, fix } = options;\n const language = options.language ?? detectLanguage(files);\n const tsFiles = files.filter((f) => /\\.[tj]sx?$/.test(f));\n const pyFiles = files.filter((f) => /\\.py$/.test(f));\n const results: RunnerResult[] = [];\n\n if ((language === \"typescript\" || language === \"mixed\") && tsFiles.length > 0) {\n const { entries, skippedRules: namingSkipped } = generateEslintConfig(profile);\n if (entries.length > 0) {\n const result = await runEslint(entries, tsFiles, { fix });\n results.push({ ...result, skippedRules: [...namingSkipped, ...result.skippedRules] });\n } else if (namingSkipped.length > 0) {\n results.push({ diagnostics: [], exitCode: null, failures: [], skippedRules: namingSkipped });\n }\n }\n\n if ((language === \"python\" || language === \"mixed\") && pyFiles.length > 0) {\n const ruffConfig = generateRuffConfig(profile);\n if (ruffConfig.lint?.select && ruffConfig.lint.select.length > 0) {\n results.push(await runRuff(ruffConfig, pyFiles, { fix }));\n }\n }\n return results;\n}\n\nexport async function orchestrate(\n options: OrchestratorOptions,\n): Promise<OrchestratorResult> {\n const results = await runTools(options);\n const diagnostics = results.flatMap((r) => r.diagnostics);\n return {\n diagnostics,\n failures: results.flatMap((r) => r.failures),\n skippedRules: results.flatMap((r) => r.skippedRules),\n summary: buildSummary(diagnostics),\n };\n}\n","import type { RuffConfig } from \"./ruff.js\";\n\n/** The audit's pinned ruff selection: complexity, size, dead code, and defensive-bloat signals. */\nexport const AUDIT_RUFF_RULES: readonly string[] = [\n \"C901\",\n \"PLR0904\",\n \"PLR0911\",\n \"PLR0912\",\n \"PLR0913\",\n \"PLR0914\",\n \"PLR0915\",\n \"PLR0916\",\n \"PLR0917\",\n \"PLR1702\",\n \"ARG\",\n \"FBT\",\n \"ERA001\",\n \"BLE001\",\n \"S110\",\n \"TRY203\",\n \"SIM105\",\n \"F401\",\n \"F841\",\n \"PIE790\",\n \"RUF100\",\n];\n\n/** Preview is on because ruff 0.16.8 silently skips PLR0904, PLR0914, PLR0916 and PLR1702 without it. */\nexport function generateRuffAuditConfig(): RuffConfig {\n return { preview: true, lint: { select: [...AUDIT_RUFF_RULES] } };\n}\n","import { realpathSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\n\n/** The directory diagnostics are reported relative to, resolved so it matches the real paths tools print. */\nexport function auditRoot(cwd?: string): string {\n return realpathSync(cwd ?? process.cwd());\n}\n\nexport function relativeTo(root: string, file: string): string {\n return isAbsolute(file) ? relative(root, file) : file;\n}\n","import { generateRuffAuditConfig } from \"../generators/ruff-audit.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport { runRuff } from \"./ruff-runner.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\n/** Runs the pinned audit rule set; diagnostics carry paths relative to `cwd`, since ruff reports absolute ones. */\nexport async function runRuffAudit(files: string[], options?: Omit<RunnerOptions, \"fix\">): Promise<RunnerResult> {\n const result = await runRuff(generateRuffAuditConfig(), files, options);\n const root = auditRoot(options?.cwd);\n const diagnostics = result.diagnostics.map((d) => ({ ...d, file: relativeTo(root, d.file) }));\n return { ...result, diagnostics };\n}\n","/** The audit's pinned pyright selection: checks whose finding is a guard or conversion the types already make redundant. */\nexport const AUDIT_PYRIGHT_RULES: readonly string[] = [\n \"reportUnnecessaryIsInstance\",\n \"reportUnnecessaryComparison\",\n \"reportUnnecessaryContains\",\n \"reportUnnecessaryCast\",\n];\n\n// typeCheckingMode \"off\" still leaves these on, and an audit that cannot see the project's dependencies would drown in them.\nconst STILL_ON_WHEN_OFF = [\"reportMissingImports\", \"reportMissingModuleSource\", \"reportUndefinedVariable\"];\n\nexport type PyrightConfig = Record<string, string | string[]>;\n\n/** Everything off except the audit rules, as warnings; `root` goes on extraPaths so the project's own imports resolve. */\nexport function generatePyrightAuditConfig(root: string): PyrightConfig {\n const config: PyrightConfig = { typeCheckingMode: \"off\", extraPaths: [root] };\n for (const rule of STILL_ON_WHEN_OFF) config[rule] = \"none\";\n for (const rule of AUDIT_PYRIGHT_RULES) config[rule] = \"warning\";\n return config;\n}\n","import { parseOrFail, runAndClassify } from \"./failures.js\";\nimport type { RunExpectations, ToolRun } from \"./failures.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport type { CheckDiagnostic, ToolFailure, ToolName } from \"../orchestrator/types.js\";\nimport type { RunnerOptions, RunnerResult } from \"./types.js\";\n\n/** How to invoke one audit tool and what to tell the user when it is not installed. */\nexport interface PythonToolSpec {\n tool: ToolName;\n command: string;\n install: string;\n installNote?: string;\n expect: RunExpectations;\n}\n\nexport interface ToolOutput {\n stdout: string;\n stderr: string;\n}\n\nexport interface ParsedOutput {\n diagnostics: CheckDiagnostic[];\n failures: ToolFailure[];\n}\n\nexport type AuditOptions = Omit<RunnerOptions, \"fix\">;\n\nexport function emptyResult(exitCode: number | null, extra: Partial<RunnerResult> = {}): RunnerResult {\n return { diagnostics: [], exitCode, failures: [], skippedRules: [], warnings: [], ...extra };\n}\n\nexport function missingToolWarning(spec: PythonToolSpec): string {\n const note = spec.installNote ? ` (${spec.installNote})` : \"\";\n return `${spec.tool} not found; install with \\`${spec.install}\\`${note}`;\n}\n\nfunction isMissingBinary(run: Extract<ToolRun, { ok: false }>): boolean {\n const { kind, message } = run.failure;\n if (kind === \"spawn-failed\" && message.includes(\"ENOENT\")) return true;\n return run.exitCode === 127 || /command not found/i.test(message);\n}\n\nfunction relativise(root: string, parsed: ParsedOutput): ParsedOutput {\n return {\n diagnostics: parsed.diagnostics.map((d) => ({ ...d, file: relativeTo(root, d.file) })),\n failures: parsed.failures.map((f) => (f.file ? { ...f, file: relativeTo(root, f.file) } : f)),\n };\n}\n\n/** Runs one tool, maps an absent binary to a warning, and reports paths relative to `cwd`. */\nexport async function runPythonTool(\n spec: PythonToolSpec,\n args: string[],\n options: AuditOptions | undefined,\n parse: (output: ToolOutput) => ParsedOutput,\n): Promise<RunnerResult> {\n const runOptions = { cwd: options?.cwd, timeout: options?.timeout };\n const run = await runAndClassify(spec.tool, spec.command, args, runOptions, spec.expect);\n if (!run.ok && isMissingBinary(run)) return emptyResult(null, { warnings: [missingToolWarning(spec)] });\n if (!run.ok) return emptyResult(run.exitCode, { failures: [run.failure] });\n const parsed = parseOrFail(spec.tool, () => parse(run));\n if (!parsed.ok) return emptyResult(run.exitCode, { failures: [parsed.failure] });\n return emptyResult(run.exitCode, relativise(auditRoot(options?.cwd), parsed.value));\n}\n\n/** Stderr lines a parser did not recognise, folded into one failure so a crash is never silent. */\nexport function unrecognisedStderr(tool: ToolName, lines: string[]): ToolFailure[] {\n if (lines.length === 0) return [];\n const message = lines.join(\"\\n\");\n return [{ tool, kind: \"unparseable-output\", message: message.length > 500 ? `${message.slice(0, 500)}…` : message }];\n}\n","import { runPythonTool, unrecognisedStderr } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// vulture exits 1 on invalid input (a syntax error) and 3 when it found dead code; both still carry findings.\nconst VULTURE: PythonToolSpec = {\n tool: \"vulture\",\n command: \"vulture\",\n install: \"pip install vulture\",\n expect: { successCodes: new Set([0, 1, 3]), allowEmptyStdout: true },\n};\n\nconst FINDING = /^(.+?):(\\d+): (.+) \\((\\d+)% confidence(?:, \\d+ lines?)?\\)$/;\nconst INVALID_INPUT = /^(.+?):(\\d+): (.+)$/;\nconst NOT_FOUND = /^Error: (.+) could not be found\\.$/;\n\nexport interface VultureOptions extends AuditOptions {\n /** vulture's --min-confidence; 60 keeps its uncertain unused-code guesses, 100 keeps only unreachable code. */\n minConfidence?: number;\n}\n\n/** Rule suffix from vulture's wording: \"unused function 'x'\" is unused-function; every other finding is unreachable code. */\nexport function vultureKind(text: string): string {\n const unused = /^unused (\\w+)/.exec(text);\n return unused ? `unused-${unused[1]}` : \"unreachable\";\n}\n\nfunction toDiagnostic(m: RegExpExecArray): CheckDiagnostic {\n const [, file, line, text, confidence] = m as unknown as [string, string, string, string, string];\n return {\n file,\n line: Number(line),\n column: 1,\n severity: \"warn\",\n message: `${text} (${confidence}% confidence)`,\n category: \"dead-code\",\n rule: `vulture/${vultureKind(text)}`,\n fixable: false,\n };\n}\n\nfunction parseStdout(stdout: string): CheckDiagnostic[] {\n return stdout.split(\"\\n\").filter((l) => l.trim()).map((line) => {\n const m = FINDING.exec(line);\n if (!m) throw new Error(`Unrecognised vulture line: ${line}`);\n return toDiagnostic(m);\n });\n}\n\nfunction parseStderr(stderr: string): ToolFailure[] {\n const failures: ToolFailure[] = [];\n const unknown: string[] = [];\n for (const line of stderr.split(\"\\n\").filter((l) => l.trim())) {\n const missing = NOT_FOUND.exec(line);\n const invalid = INVALID_INPUT.exec(line);\n if (missing) failures.push({ tool: \"vulture\", kind: \"file-not-checked\", file: missing[1]!, message: \"could not be found\" });\n else if (invalid) failures.push({ tool: \"vulture\", kind: \"file-not-checked\", file: invalid[1]!, message: invalid[3]! });\n else unknown.push(line);\n }\n return [...failures, ...unrecognisedStderr(\"vulture\", unknown)];\n}\n\nexport function parseVultureOutput({ stdout, stderr }: ToolOutput): ParsedOutput {\n return { diagnostics: parseStdout(stdout), failures: parseStderr(stderr) };\n}\n\n/** Dead-code candidates from vulture at `minConfidence` (default 60); rule ids are vulture/<kind>. */\nexport function runVultureAudit(files: string[], options?: VultureOptions): Promise<RunnerResult> {\n const args = [\"--min-confidence\", String(options?.minConfidence ?? 60), ...files];\n return runPythonTool(VULTURE, args, options, parseVultureOutput);\n}\n","import { runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\nconst PYDOCLINT: PythonToolSpec = {\n tool: \"pydoclint\",\n command: \"pydoclint\",\n install: \"pip install pydoclint\",\n expect: { successCodes: new Set([0, 1]), allowEmptyStdout: true },\n};\n\nconst VIOLATION = /^\\s+(\\d+): (DOC\\d+): (.*)$/;\n// pydoclint reports a file it cannot parse as a DOC002 violation at line 0.\nconst SYNTAX_ERROR = \"DOC002\";\n\nexport type DocstringStyle = \"numpy\" | \"google\" | \"sphinx\";\n\nexport interface PydoclintOptions extends AuditOptions {\n style?: DocstringStyle;\n}\n\nfunction toDiagnostic(file: string, m: RegExpExecArray): CheckDiagnostic {\n return {\n file,\n line: Math.max(1, Number(m[1])),\n column: 1,\n severity: \"warn\",\n message: m[3]!,\n category: \"documentation\",\n rule: `pydoclint/${m[2]}`,\n fixable: false,\n };\n}\n\n/** pydoclint prints each file's path unindented, then its violations indented beneath it, all on stderr. */\nexport function parsePydoclintOutput({ stdout, stderr }: ToolOutput): ParsedOutput {\n const parsed: ParsedOutput = { diagnostics: [], failures: [] };\n let file: string | undefined;\n for (const line of `${stdout}\\n${stderr}`.split(\"\\n\").filter((l) => l.trim())) {\n const m = VIOLATION.exec(line);\n if (!m && /^\\S/.test(line)) file = line.trim();\n else if (!m || !file) throw new Error(`Unrecognised pydoclint line: ${line}`);\n else if (m[2] === SYNTAX_ERROR) parsed.failures.push(notChecked(file, m[3]!));\n else parsed.diagnostics.push(toDiagnostic(file, m));\n }\n return parsed;\n}\n\nfunction notChecked(file: string, message: string): ToolFailure {\n return { tool: \"pydoclint\", kind: \"file-not-checked\", file, message };\n}\n\n/** Docstring-versus-signature drift from pydoclint in `style` (default numpy); rule ids are pydoclint/DOCnnn. */\nexport function runPydoclintAudit(files: string[], options?: PydoclintOptions): Promise<RunnerResult> {\n const args = [\"--style\", options?.style ?? \"numpy\", \"--quiet\", ...files];\n return runPythonTool(PYDOCLINT, args, options, parsePydoclintOutput);\n}\n","import { mkdtempSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { AUDIT_PYRIGHT_RULES, generatePyrightAuditConfig } from \"../generators/pyright-audit.js\";\nimport { auditRoot } from \"./paths.js\";\nimport { runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\nconst PYRIGHT: PythonToolSpec = {\n tool: \"pyright\",\n command: \"pyright\",\n install: \"pip install pyright\",\n installNote: \"the pip wrapper fetches pyright's npm package on first run and needs Node on PATH; `npm install -g pyright` also works\",\n expect: { successCodes: new Set([0, 1]) },\n};\n\ninterface PyrightDiagnostic {\n file: string;\n severity: string;\n message: string;\n rule?: string;\n range: { start: { line: number; character: number }; end: { line: number } };\n}\n\nexport interface PyrightOptions extends AuditOptions {\n /** The interpreter whose site-packages pyright resolves third-party imports from. */\n pythonPath?: string;\n}\n\nfunction toDiagnostic(d: PyrightDiagnostic & { rule: string }): CheckDiagnostic {\n return {\n file: d.file,\n line: d.range.start.line + 1,\n endLine: d.range.end.line + 1,\n column: d.range.start.character + 1,\n severity: \"warn\",\n message: d.message,\n category: \"redundant-check\",\n rule: `pyright/${d.rule}`,\n fixable: false,\n };\n}\n\n// A diagnostic without a rule is a syntax error; the file is reported once, as ruff's runner does.\nfunction unparsedFiles(entries: PyrightDiagnostic[]): ToolFailure[] {\n const byFile = new Map<string, string[]>();\n for (const e of entries.filter((d) => !d.rule && d.severity === \"error\")) {\n byFile.set(e.file, [...(byFile.get(e.file) ?? []), e.message]);\n }\n return [...byFile].map(([file, messages]) => ({ tool: \"pyright\", kind: \"file-not-checked\", file, message: messages.join(\"; \") }));\n}\n\nexport function parsePyrightOutput({ stdout }: ToolOutput): ParsedOutput {\n const entries = (JSON.parse(stdout) as { generalDiagnostics: PyrightDiagnostic[] }).generalDiagnostics;\n const audited = entries.filter((d): d is PyrightDiagnostic & { rule: string } => AUDIT_PYRIGHT_RULES.includes(d.rule ?? \"\"));\n return { diagnostics: audited.map(toDiagnostic), failures: unparsedFiles(entries) };\n}\n\n/** Redundant isinstance, comparison, contains and cast findings from pyright; rule ids are pyright/<rule>. */\nexport async function runPyrightAudit(files: string[], options?: PyrightOptions): Promise<RunnerResult> {\n const tempDir = mkdtempSync(join(tmpdir(), \"style-checker-pyright-\"));\n try {\n const configPath = join(tempDir, \"pyrightconfig.json\");\n writeFileSync(configPath, JSON.stringify(generatePyrightAuditConfig(auditRoot(options?.cwd))), \"utf-8\");\n const python = options?.pythonPath ? [\"--pythonpath\", options.pythonPath] : [];\n return await runPythonTool(PYRIGHT, [\"--outputjson\", \"-p\", configPath, ...python, ...files], options, parsePyrightOutput);\n } finally {\n rmSync(tempDir, { recursive: true, force: true });\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { findImportLinterConfig } from \"./import-linter-config.js\";\nimport type { ImportLinterConfig } from \"./import-linter-config.js\";\nimport { parseBrokenChains } from \"./import-linter-output.js\";\nimport type { BrokenChain } from \"./import-linter-output.js\";\nimport { auditRoot } from \"./paths.js\";\nimport { emptyResult, runPythonTool } from \"./python-tool.js\";\nimport type { AuditOptions, ParsedOutput, PythonToolSpec, ToolOutput } from \"./python-tool.js\";\nimport type { CheckDiagnostic } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// lint-imports exits 1 when a contract is broken.\nconst IMPORT_LINTER: PythonToolSpec = {\n tool: \"import-linter\",\n command: \"lint-imports\",\n install: \"pip install import-linter\",\n expect: { successCodes: new Set([0, 1]) },\n};\n\nexport const NO_IMPORT_LINTER_CONFIG = \"no import-linter config\";\n\nfunction slug(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-|-$/g, \"\");\n}\n\n/** The importing module's source file, tried at the root and under src/. */\nexport function moduleFile(root: string, module: string): string | undefined {\n const base = module.replace(/\\./g, \"/\");\n const candidates = [\"\", \"src/\"].flatMap((dir) => [`${dir}${base}.py`, `${dir}${base}/__init__.py`]);\n return candidates.find((c) => existsSync(join(root, c)));\n}\n\nfunction toDiagnostic(chain: BrokenChain, config: ImportLinterConfig, root: string): CheckDiagnostic {\n const first = chain.links[0]!;\n const file = moduleFile(root, first.importer);\n const path = [first.importer, ...chain.links.map((l) => l.imported)].join(\" -> \");\n return {\n file: file ?? chain.contract,\n line: file ? (first.lines[0] ?? 1) : 1,\n column: 1,\n severity: \"error\",\n message: `${chain.summary}: ${path}`,\n category: \"architecture\",\n rule: `import-linter/${config.contractIds.get(chain.contract) ?? slug(chain.contract)}`,\n fixable: false,\n };\n}\n\nfunction parser(config: ImportLinterConfig, root: string): (output: ToolOutput) => ParsedOutput {\n return ({ stdout }) => {\n const chains = parseBrokenChains(stdout);\n if (chains.length === 0 && /\\bBROKEN$/m.test(stdout)) throw new Error(\"lint-imports reported a broken contract but no import chain could be read\");\n return { diagnostics: chains.map((c) => toDiagnostic(c, config, root)), failures: [] };\n };\n}\n\n/** One diagnostic per broken import chain; runs only when the project configures import-linter. */\nexport function runImportLinter(options?: AuditOptions): Promise<RunnerResult> {\n const root = auditRoot(options?.cwd);\n const config = findImportLinterConfig(root);\n if (!config) return Promise.resolve(emptyResult(null, { warnings: [NO_IMPORT_LINTER_CONFIG] }));\n const args = [\"--config\", config.path, \"--no-logo\", \"--no-cache\"];\n return runPythonTool(IMPORT_LINTER, args, options, parser(config, root));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface ImportLinterConfig {\n path: string;\n /** Contract name to contract id; lint-imports prints names, the rule id wants the id. */\n contractIds: Map<string, string>;\n}\n\n// import-linter takes the id from the last colon-separated part of an importlinter: section name.\nconst INI_CONTRACT = /^\\[importlinter:(?:.*:)?([^:\\]]+)\\]$/;\n\nfunction iniContractIds(text: string): Map<string, string> {\n const ids = new Map<string, string>();\n let current: string | undefined;\n for (const line of text.split(\"\\n\").map((l) => l.trim())) {\n if (line.startsWith(\"[\")) current = INI_CONTRACT.exec(line)?.[1];\n const name = current && /^name\\s*[=:]\\s*(.+)$/.exec(line);\n if (current && name) ids.set(name[1]!.trim(), current);\n }\n return ids;\n}\n\nfunction tomlValue(block: string, key: string): string | undefined {\n return new RegExp(`^${key}\\\\s*=\\\\s*[\"'](.+?)[\"']\\\\s*$`, \"m\").exec(block)?.[1];\n}\n\nfunction tomlContractIds(text: string): Map<string, string> {\n const ids = new Map<string, string>();\n for (const chunk of text.split(/^\\[\\[tool\\.importlinter\\.contracts\\]\\]\\s*$/m).slice(1)) {\n const block = chunk.split(/^\\[/m)[0]!;\n const name = tomlValue(block, \"name\");\n const id = tomlValue(block, \"id\");\n if (name && id) ids.set(name, id);\n }\n return ids;\n}\n\nfunction readIfContains(path: string, marker: RegExp): string | undefined {\n if (!existsSync(path)) return undefined;\n const text = readFileSync(path, \"utf-8\");\n return marker.test(text) ? text : undefined;\n}\n\n/** The config lint-imports would use, in its own lookup order: setup.cfg, .importlinter, then pyproject.toml. */\nexport function findImportLinterConfig(cwd: string): ImportLinterConfig | undefined {\n for (const name of [\"setup.cfg\", \".importlinter\"]) {\n const ini = readIfContains(join(cwd, name), /^\\[importlinter\\]/m);\n if (ini !== undefined) return { path: join(cwd, name), contractIds: iniContractIds(ini) };\n }\n const toml = readIfContains(join(cwd, \"pyproject.toml\"), /^\\[tool\\.importlinter\\]/m);\n if (toml !== undefined) return { path: join(cwd, \"pyproject.toml\"), contractIds: tomlContractIds(toml) };\n return undefined;\n}\n","/** One import in a chain: `importer` imports `imported` on the given lines. */\nexport interface ImportLink {\n importer: string;\n imported: string;\n lines: number[];\n}\n\n/** One broken import chain, under the contract name and the sentence lint-imports prints above it. */\nexport interface BrokenChain {\n contract: string;\n summary: string;\n links: ImportLink[];\n}\n\nconst LINK = /^(-)?\\s+(\\S+) -> (\\S+) \\(l\\.([\\d, ?]+)\\)$/;\nconst SUMMARY = /^(\\S.* is not allowed to import \\S.*):$/;\n\nfunction isUnderline(line: string | undefined, heading: string): boolean {\n return line !== undefined && /^-+$/.test(line) && line.length === heading.length;\n}\n\nfunction toLink(m: RegExpExecArray): ImportLink {\n const lines = m[4]!.split(\",\").map((n) => Number(n.trim())).filter((n) => Number.isInteger(n) && n > 0);\n return { importer: m[2]!, imported: m[3]!, lines };\n}\n\n/** Reads the \"Broken contracts\" section; a chain starts at a \"-\" line and continues on indented lines. */\nexport function parseBrokenChains(stdout: string): BrokenChain[] {\n const lines = stdout.split(\"\\n\");\n const start = lines.findIndex((l, i) => l === \"Broken contracts\" && isUnderline(lines[i + 1], l));\n if (start < 0) return [];\n const chains: BrokenChain[] = [];\n let contract = \"\";\n let summary = \"\";\n for (let i = start + 2; i < lines.length; i++) {\n const line = lines[i]!;\n const link = LINK.exec(line);\n if (isUnderline(lines[i + 1], line) && line.trim()) contract = line;\n else if (SUMMARY.test(line)) summary = SUMMARY.exec(line)![1]!;\n else if (link?.[1]) chains.push({ contract, summary, links: [toLink(link)] });\n else if (link && chains.length > 0) chains.at(-1)!.links.push(toLink(link));\n }\n return chains;\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { emptyResult } from \"./python-tool.js\";\nimport { auditRoot, relativeTo } from \"./paths.js\";\nimport type { CheckDiagnostic, ToolFailure } from \"../orchestrator/types.js\";\nimport type { RunnerResult } from \"./types.js\";\n\n// A text scan, not a tokenizer: a marker inside a string literal counts too.\nconst NOQA = /#\\s*noqa\\b(?::\\s*([A-Z]+\\d+(?:[\\s,]+[A-Z]+\\d+)*))?/gi;\nconst TYPE_IGNORE = /#\\s*type:\\s*ignore\\b(?:\\[([^\\]]*)\\])?/g;\n\nexport const NOQA_RULE = \"suppression/noqa\";\nexport const TYPE_IGNORE_RULE = \"suppression/type-ignore\";\n\nfunction codesOf(raw: string | undefined): string[] {\n return raw ? raw.split(/[\\s,]+/).filter(Boolean) : [];\n}\n\nfunction marker(file: string, line: number, m: RegExpMatchArray, rule: string, label: string): CheckDiagnostic {\n const codes = codesOf(m[1]);\n const message = codes.length ? `${label} suppresses ${codes.join(\", \")}` : `blanket ${label} suppresses every check on this line`;\n return { file, line, column: (m.index ?? 0) + 1, severity: \"warn\", message, category: \"suppression\", rule, fixable: false };\n}\n\n/** Every `# noqa` and `# type: ignore` marker in one file's text, one diagnostic per occurrence. */\nexport function findSuppressions(file: string, text: string): CheckDiagnostic[] {\n return text.split(\"\\n\").flatMap((content, i) => [\n ...[...content.matchAll(NOQA)].map((m) => marker(file, i + 1, m, NOQA_RULE, \"noqa\")),\n ...[...content.matchAll(TYPE_IGNORE)].map((m) => marker(file, i + 1, m, TYPE_IGNORE_RULE, \"type: ignore\")),\n ]);\n}\n\n/** Suppression markers across `files`, read from disk relative to `cwd`; no tool is run. */\nexport function countSuppressions(files: string[], options?: { cwd?: string }): RunnerResult {\n const root = auditRoot(options?.cwd);\n const diagnostics: CheckDiagnostic[] = [];\n const failures: ToolFailure[] = [];\n for (const file of files) {\n const shown = relativeTo(root, resolve(root, file));\n try {\n diagnostics.push(...findSuppressions(shown, readFileSync(resolve(root, file), \"utf-8\")));\n } catch (err) {\n failures.push({ tool: \"suppressions\", kind: \"file-not-checked\", file: shown, message: (err as Error).message });\n }\n }\n return emptyResult(0, { diagnostics, failures });\n}\n\nexport interface SuppressionCounts {\n noqa: number;\n typeIgnore: number;\n}\n\nexport interface SuppressionTotals extends SuppressionCounts {\n byFile: Record<string, SuppressionCounts>;\n}\n\n/** Totals of countSuppressions' diagnostics, overall and per file; other diagnostics are ignored. */\nexport function suppressionTotals(diagnostics: CheckDiagnostic[]): SuppressionTotals {\n const totals: SuppressionTotals = { noqa: 0, typeIgnore: 0, byFile: {} };\n for (const d of diagnostics) {\n const key = d.rule === NOQA_RULE ? \"noqa\" : d.rule === TYPE_IGNORE_RULE ? \"typeIgnore\" : undefined;\n if (!key) continue;\n const file = (totals.byFile[d.file] ??= { noqa: 0, typeIgnore: 0 });\n file[key] += 1;\n totals[key] += 1;\n }\n return totals;\n}\n","import { PROFILE_CATEGORIES } from \"@titan-design/style-profile\";\nimport type { Profile, ProfileCategory } from \"@titan-design/style-profile\";\nimport type { Observation } from \"@titan-design/style-analyzer\";\n\nexport interface Deviation {\n file: string;\n line: number;\n rule: string;\n expected: string;\n found: string;\n severity: \"error\" | \"warn\" | \"info\";\n}\n\nexport interface DiffResult {\n deviations: Deviation[];\n summary: {\n total: number;\n matching: number;\n deviating: number;\n };\n}\n\nfunction getSeverity(\n confidence: number,\n thresholds: Profile[\"severityThresholds\"],\n): \"error\" | \"warn\" | \"info\" {\n if (confidence >= thresholds.error) return \"error\";\n if (confidence >= thresholds.warn) return \"warn\";\n return \"info\";\n}\n\nfunction resolveProfileRule(\n profile: Profile,\n observationType: string,\n): { convention: unknown; confidence: number } | undefined {\n const [category, rule] = observationType.split(\".\");\n if (!PROFILE_CATEGORIES.includes(category as ProfileCategory)) return undefined;\n const section = profile[category as ProfileCategory];\n if (!section || typeof section !== \"object\") return undefined;\n const ruleObj = rule === undefined ? undefined : section[rule];\n if (!ruleObj || typeof ruleObj !== \"object\") return undefined;\n if (ruleObj.convention === undefined || ruleObj.confidence === undefined) {\n return undefined;\n }\n return { convention: ruleObj.convention, confidence: ruleObj.confidence };\n}\n\nexport function diffAgainstProfile(\n profile: Profile,\n observations: Observation[],\n): DiffResult {\n const deviations: Deviation[] = [];\n let matching = 0;\n\n for (const obs of observations) {\n const profileRule = resolveProfileRule(profile, obs.type);\n if (!profileRule) continue;\n\n const expected = String(profileRule.convention);\n const found = String(obs.value);\n\n if (found === expected) {\n matching++;\n } else {\n deviations.push({\n file: obs.file,\n line: obs.line,\n rule: obs.type,\n expected,\n found,\n severity: getSeverity(\n profileRule.confidence,\n profile.severityThresholds,\n ),\n });\n }\n }\n\n return {\n deviations,\n summary: {\n total: observations.length,\n matching,\n deviating: deviations.length,\n },\n };\n}\n"],"mappings":"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","names":["join","resolve","require","parser","join","writeFileSync","mkdtempSync","rmSync","join","tmpdir","mkdtempSync","join","tmpdir","writeFileSync","rmSync","toDiagnostic","notChecked","mkdtempSync","rmSync","writeFileSync","tmpdir","join","toDiagnostic","unparsedFiles","mkdtempSync","join","tmpdir","writeFileSync","rmSync","existsSync","join","join","marker","existsSync","join","toDiagnostic","readFileSync","readFileSync"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@titan-design/style-checker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Run external lint tools (ruff, ESLint) against configs generated from a style profile, normalize their output into one diagnostic shape, and diff observations against a profile",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@titan-design/style-analyzer": "^0.1.
|
|
35
|
-
"@titan-design/style-profile": "^0.
|
|
34
|
+
"@titan-design/style-analyzer": "^0.1.2",
|
|
35
|
+
"@titan-design/style-profile": "^0.3.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"zod": "^4.0.0"
|