@herbertgao/pi-extensions 2026.9.14 → 2026.9.16
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 +8 -3
- package/THIRD_PARTY_NOTICES.md +28 -2
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/dist/index.ts +12 -6
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +4 -4
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +2 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +16 -4
- package/node_modules/pi-jev-auto-mode/CHANGELOG.md +8 -0
- package/node_modules/pi-jev-auto-mode/README.md +7 -0
- package/node_modules/pi-jev-auto-mode/package.json +1 -1
- package/node_modules/pi-jev-auto-mode/src/extension.ts +21 -2
- package/node_modules/pi-jev-auto-mode/src/records.ts +68 -2
- package/node_modules/pi-jev-auto-mode/src/settings.ts +22 -0
- package/node_modules/pi-jev-auto-mode/src/ui.ts +10 -0
- package/node_modules/pi-lens/CHANGELOG.md +498 -0
- package/node_modules/pi-lens/README.md +45 -2
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +23 -7
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +187 -51
- package/node_modules/pi-lens/dist/clients/cache-manager.js +64 -5
- package/node_modules/pi-lens/dist/clients/child-unref.js +17 -8
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +2 -0
- package/node_modules/pi-lens/dist/clients/config-locations.js +237 -9
- package/node_modules/pi-lens/dist/clients/config-resolve.js +7 -1
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +33 -3
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +87 -64
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -3
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +118 -1
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +8 -2
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +23 -4
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +14 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +26 -28
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +38 -25
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +32 -49
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +16 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +25 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +28 -47
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +11 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +27 -22
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +31 -46
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +29 -46
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +91 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +16 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +38 -23
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +27 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +31 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +34 -60
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +6 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +12 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +22 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +39 -16
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +27 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +18 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +6 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +11 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +10 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +11 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +12 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +30 -15
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +8 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +15 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +12 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +27 -39
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +13 -3
- package/node_modules/pi-lens/dist/clients/effective-config.js +3 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +42 -11
- package/node_modules/pi-lens/dist/clients/formatters.js +49 -11
- package/node_modules/pi-lens/dist/clients/git-guard.js +247 -34
- package/node_modules/pi-lens/dist/clients/gradle-ktfmt-style.js +121 -25
- package/node_modules/pi-lens/dist/clients/inline-blocker-dispositions.js +186 -0
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +19 -6
- package/node_modules/pi-lens/dist/clients/installer/index.js +281 -32
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +8 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +8 -0
- package/node_modules/pi-lens/dist/clients/lens-config.js +66 -8
- package/node_modules/pi-lens/dist/clients/lsp/client.js +139 -11
- package/node_modules/pi-lens/dist/clients/lsp/config.js +9 -7
- package/node_modules/pi-lens/dist/clients/lsp/content-limits.js +41 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +23 -2
- package/node_modules/pi-lens/dist/clients/lsp/server.js +106 -25
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +14 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +105 -16
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +232 -44
- package/node_modules/pi-lens/dist/clients/mcp/review.js +53 -7
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +11 -6
- package/node_modules/pi-lens/dist/clients/pipeline.js +121 -66
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +21 -3
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +11 -3
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +34 -26
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +16 -10
- package/node_modules/pi-lens/dist/clients/ruff-client.js +31 -4
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +38 -4
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +16 -5
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +27 -12
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +447 -280
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +256 -65
- package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +84 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +119 -58
- package/node_modules/pi-lens/dist/clients/turn-end/lane.js +51 -0
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/govulncheck.js +112 -0
- package/node_modules/pi-lens/dist/clients/turn-end/lanes/secrets.js +204 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +59 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +145 -14
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +57 -3
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -13
- package/node_modules/pi-lens/dist/index.js +5695 -3733
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +4 -0
- package/node_modules/pi-lens/dist/mcp/server.js +33 -21
- package/node_modules/pi-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +123 -0
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +43 -16
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +118 -7
- package/node_modules/pi-lens/docs/adr/0001-stale-advisory-live-arm.md +29 -0
- package/node_modules/pi-lens/docs/adr/0002-workspace-hash-rendezvous.md +30 -0
- package/node_modules/pi-lens/docs/adr/0003-git-guard-latch-writer.md +203 -0
- package/node_modules/pi-lens/docs/adr/0004-disposition-policy-seam.md +38 -0
- package/node_modules/pi-lens/docs/adr/0005-tool-availability-enforcement-seam.md +29 -0
- package/node_modules/pi-lens/docs/adr/0006-derived-state-benchmark-first.md +31 -0
- package/node_modules/pi-lens/docs/adr/0007-end-to-end-witness-per-seam-slice.md +38 -0
- package/node_modules/pi-lens/docs/adr/0008-turn-end-lane-interface.md +165 -0
- package/node_modules/pi-lens/docs/adr/0009-reported-path-attribution.md +114 -0
- package/node_modules/pi-lens/docs/adr/README.md +26 -0
- package/node_modules/pi-lens/docs/agent-tools.md +18 -1
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +4 -3
- package/node_modules/pi-lens/docs/configuration.md +55 -1
- package/node_modules/pi-lens/docs/engineering-principles.md +202 -0
- package/node_modules/pi-lens/docs/environment-variables.md +61 -4
- package/node_modules/pi-lens/docs/features.md +2 -2
- package/node_modules/pi-lens/docs/globalconfig.md +6 -1
- package/node_modules/pi-lens/docs/language-coverage.md +17 -0
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +98 -31
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +57 -3
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +9 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +16 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +9 -0
- package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +2 -0
- package/node_modules/pi-lens/docs/servercapabilities.md +21 -11
- package/node_modules/pi-lens/docs/settings.md +12 -3
- package/node_modules/pi-lens/docs/subagent-compat.md +1 -1
- package/node_modules/pi-lens/package.json +5 -3
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-assert-tuple-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-boolean-in-except-test.yml +26 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-http-headers-bracket-access-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/unchecked-numeric-parse-python-test.yml +18 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/unchecked-throwing-call-python-test.yml +4 -3
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +2 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-assert-tuple.yml +23 -13
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-boolean-in-except.yml +7 -3
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-console-except-error-js.yml +2 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-console-except-error.yml +2 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-http-headers-bracket-access.yml +12 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/unchecked-numeric-parse-python.yml +44 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/unchecked-throwing-call-python.yml +5 -3
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/console-statement.yml +2 -2
- package/node_modules/pi-lens/scripts/install-selftest.mjs +21 -17
- package/node_modules/pi-lens/scripts/lib/web-tree-sitter-dir.mjs +123 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +29 -0
- package/node_modules/pi-mcp-adapter/OAUTH.md +369 -0
- package/node_modules/pi-mcp-adapter/README.md +12 -5
- package/node_modules/pi-mcp-adapter/config.ts +31 -8
- package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +1 -1
- package/node_modules/pi-mcp-adapter/dist/config.js +33 -8
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +15 -2
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +27 -2
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +1 -1
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/server-manager.js +6 -4
- package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +1 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +2 -2
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +10 -3
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -1
- package/node_modules/pi-mcp-adapter/index.ts +37 -20
- package/node_modules/pi-mcp-adapter/init.ts +14 -15
- package/node_modules/pi-mcp-adapter/json-schema-validator.ts +16 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +27 -2
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +1 -1
- package/node_modules/pi-mcp-adapter/package.json +3 -2
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +1 -1
- package/node_modules/pi-mcp-adapter/server-manager.ts +6 -3
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +99 -6
- package/node_modules/pi-mcp-adapter/types.ts +2 -2
- package/node_modules/pi-mcp-adapter/ui-session.ts +60 -27
- package/node_modules/pi-mcp-adapter/utils.ts +11 -3
- package/node_modules/pi-multi-account/CHANGELOG.md +6 -0
- package/node_modules/pi-multi-account/README.md +15 -1
- package/node_modules/pi-multi-account/index.ts +295 -41
- package/node_modules/pi-multi-account/package.json +1 -1
- package/node_modules/pi-next-cue/.github/workflows/publish.yml +20 -0
- package/node_modules/pi-next-cue/LICENSE +21 -0
- package/node_modules/pi-next-cue/README.md +81 -0
- package/node_modules/pi-next-cue/index.ts +358 -0
- package/node_modules/pi-next-cue/package.json +28 -0
- package/package.json +10 -7
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
import * as fs from "node:fs";
|
|
105
105
|
import * as path from "node:path";
|
|
106
106
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
107
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
107
108
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
108
109
|
import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
|
|
109
110
|
import { spawnFailedWithNoOutput } from "./utils/spawn-outcome.js";
|
|
@@ -205,10 +206,24 @@ export function hasPackageClause(content) {
|
|
|
205
206
|
}
|
|
206
207
|
return false;
|
|
207
208
|
}
|
|
208
|
-
/**
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Is this reported location about the file we dispatched for? ONE seam answers
|
|
211
|
+
* that for every runner (#3278): resolve the tool's spelling against the cwd
|
|
212
|
+
* the tool RAN in and compare through `pathsEqual`.
|
|
213
|
+
*
|
|
214
|
+
* `cue` prints every position relative to its own cwd and prefixes a `./` when
|
|
215
|
+
* the result does not already start with a dot (`cue/errors/errors.go:586-596`
|
|
216
|
+
* at v0.11.0: `filepath.Rel(cfg.Cwd, s)`), which is why `.\bad.cue`,
|
|
217
|
+
* `./bad.cue` and `bad.cue` all name the vetted file — `pathsEqual` folds the
|
|
218
|
+
* separator and the `.` segment, so all three still match.
|
|
219
|
+
*
|
|
220
|
+
* What the basename compare this replaces could not do is tell those apart
|
|
221
|
+
* from `./sub/bad.cue` or `../lib/bad.cue`: an imported package's file that
|
|
222
|
+
* merely SHARES the touched file's basename was reported as the touched file's
|
|
223
|
+
* own failure (the over-merge direction, #3278 sub-shape C).
|
|
224
|
+
*/
|
|
225
|
+
function locationMatchesFile(location, absTarget, vetCwd) {
|
|
226
|
+
return pathsEqual(path.resolve(vetCwd, location.file), absTarget);
|
|
212
227
|
}
|
|
213
228
|
function toDiagnostic(id, message, fileName, line, column) {
|
|
214
229
|
return {
|
|
@@ -252,16 +267,19 @@ function toDiagnostic(id, message, fileName, line, column) {
|
|
|
252
267
|
* whole-output fallback message is used instead of one row per parsed
|
|
253
268
|
* header.
|
|
254
269
|
*/
|
|
255
|
-
export function filterToTouchedFile(errors, fileName) {
|
|
270
|
+
export function filterToTouchedFile(errors, fileName, vetCwd) {
|
|
256
271
|
if (errors.length === 0)
|
|
257
272
|
return undefined;
|
|
273
|
+
// `cue vet` always runs in the touched file's own directory, so the vet cwd
|
|
274
|
+
// joined with the bare file name IS the dispatched file.
|
|
275
|
+
const absTarget = path.resolve(vetCwd, fileName);
|
|
258
276
|
const withLocation = errors.filter((error) => error.locations.length > 0);
|
|
259
277
|
const unattributable = errors.filter((error) => error.locations.length === 0);
|
|
260
278
|
if (withLocation.length === 0)
|
|
261
279
|
return undefined;
|
|
262
280
|
const diagnostics = [];
|
|
263
281
|
for (const error of withLocation) {
|
|
264
|
-
const match = error.locations.find((location) => locationMatchesFile(location,
|
|
282
|
+
const match = error.locations.find((location) => locationMatchesFile(location, absTarget, vetCwd));
|
|
265
283
|
if (!match)
|
|
266
284
|
continue; // sibling-only finding — surfaces when that file is touched
|
|
267
285
|
diagnostics.push(toDiagnostic(`cue-vet-${diagnostics.length + 1}-${match.line}`, error.message, fileName, match.line, match.column));
|
|
@@ -364,7 +382,7 @@ const cueVetRunner = {
|
|
|
364
382
|
// the directory-scoped path — one code path, and a single-file run
|
|
365
383
|
// that somehow fails with no location at all still gets the same
|
|
366
384
|
// never-silently-clean `undefined` fallback as the directory path.
|
|
367
|
-
const filtered = filterToTouchedFile(errors, fileName);
|
|
385
|
+
const filtered = filterToTouchedFile(errors, fileName, fileDir);
|
|
368
386
|
if (filtered === undefined) {
|
|
369
387
|
// Nonzero exit, some output, but nothing in it could be attributed to
|
|
370
388
|
// ANY file — a real failure must not present as zero findings.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
3
4
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
4
5
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
6
|
+
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
5
7
|
import { PRIORITY } from "../priorities.js";
|
|
6
8
|
const dart = createAvailabilityChecker("dart", ".exe");
|
|
7
9
|
const flutter = createAvailabilityChecker("flutter", ".bat");
|
|
@@ -94,8 +96,9 @@ const DART_FIXABLE_RULES = new Set([
|
|
|
94
96
|
]);
|
|
95
97
|
// dart analyze --format=machine output:
|
|
96
98
|
// severity|type|code|file|line|col|length|message
|
|
97
|
-
function parseDartMachineOutput(raw, filePath) {
|
|
99
|
+
function parseDartMachineOutput(raw, filePath, cwd) {
|
|
98
100
|
const diagnostics = [];
|
|
101
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
99
102
|
for (const line of raw.split(/\r?\n/)) {
|
|
100
103
|
if (!line.trim())
|
|
101
104
|
continue;
|
|
@@ -106,14 +109,16 @@ function parseDartMachineOutput(raw, filePath) {
|
|
|
106
109
|
const message = messageParts.join("|").trim();
|
|
107
110
|
const lineNum = parseInt(lineStr, 10);
|
|
108
111
|
const colNum = parseInt(colStr, 10);
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
// #3278: one seam for reported-path attribution — see javac.ts.
|
|
113
|
+
// The `endsWith` outer arm this replaces was inert on the target (a
|
|
114
|
+
// string ends with itself) and an over-merge risk everywhere else: any
|
|
115
|
+
// reported path whose TAIL spelled the absolute target attached to it.
|
|
116
|
+
// `file` is `parts[3]`, which `tsconfig.strict-indexed.json`
|
|
117
|
+
// (`noUncheckedIndexedAccess`) types as `string | undefined` even behind the
|
|
118
|
+
// `parts.length < 8` guard above — the strictness ratchet pins that, so the
|
|
119
|
+
// optional chain stays.
|
|
120
|
+
if (!pathsEqual(path.resolve(cwd, file?.trim() ?? ""), absTarget))
|
|
121
|
+
continue;
|
|
117
122
|
const severity = severityStr?.trim().toLowerCase() === "error" ? "error" : "warning";
|
|
118
123
|
const ruleId = code?.trim() ?? "dart";
|
|
119
124
|
const fixable = DART_FIXABLE_RULES.has(ruleId);
|
|
@@ -136,12 +141,6 @@ function parseDartMachineOutput(raw, filePath) {
|
|
|
136
141
|
}
|
|
137
142
|
return diagnostics;
|
|
138
143
|
}
|
|
139
|
-
function firstOutputLine(result) {
|
|
140
|
-
return `${result.stderr || ""}\n${result.stdout || ""}`
|
|
141
|
-
.trim()
|
|
142
|
-
.split(/\r?\n/, 1)[0]
|
|
143
|
-
.slice(0, 200);
|
|
144
|
-
}
|
|
145
144
|
const dartAnalyzeRunner = {
|
|
146
145
|
id: "dart-analyze",
|
|
147
146
|
appliesTo: ["dart"],
|
|
@@ -162,40 +161,22 @@ const dartAnalyzeRunner = {
|
|
|
162
161
|
? ["analyze", "--format=machine", absPath]
|
|
163
162
|
: ["analyze", "--machine", absPath];
|
|
164
163
|
const result = await safeSpawnAsync(cmd, args, { cwd, timeout: 30000 });
|
|
165
|
-
if (result.error && !result.stdout && !result.stderr) {
|
|
166
|
-
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
167
|
-
}
|
|
168
164
|
// dart analyze writes diagnostics to stderr in machine format
|
|
169
165
|
const raw = (result.stderr || "") + (result.stdout || "");
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
rule: "dart-analyze",
|
|
185
|
-
fixable: false,
|
|
186
|
-
},
|
|
187
|
-
],
|
|
188
|
-
semantic: "warning",
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
192
|
-
}
|
|
193
|
-
const hasErrors = diagnostics.some((d) => d.severity === "error");
|
|
194
|
-
return {
|
|
195
|
-
status: hasErrors ? "failed" : "succeeded",
|
|
196
|
-
diagnostics,
|
|
197
|
-
semantic: hasErrors ? "blocking" : "warning",
|
|
198
|
-
};
|
|
166
|
+
const parsed = parseToolRun("dart-analyze", {
|
|
167
|
+
result,
|
|
168
|
+
output: raw,
|
|
169
|
+
// EXIT TABLE (Dart 3.5 measured fixture): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
170
|
+
exitCodes: { ran: [1, 2] },
|
|
171
|
+
}, (out) => parseDartMachineOutput(out, ctx.filePath, cwd));
|
|
172
|
+
if (parsed.skipped)
|
|
173
|
+
return parsed.skipped;
|
|
174
|
+
return finishParsedRun({
|
|
175
|
+
tool: "dart-analyze",
|
|
176
|
+
ctx,
|
|
177
|
+
result,
|
|
178
|
+
diagnostics: parsed.diagnostics,
|
|
179
|
+
});
|
|
199
180
|
},
|
|
200
181
|
};
|
|
201
182
|
export default dartAnalyzeRunner;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
4
5
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
5
6
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
6
7
|
import { PRIORITY } from "../priorities.js";
|
|
@@ -91,13 +92,14 @@ export function findDetektConfig(cwd) {
|
|
|
91
92
|
return undefined;
|
|
92
93
|
}
|
|
93
94
|
// detekt text output: /path/file.kt:10:5: error: Message [RuleId]
|
|
94
|
-
function parseDetektOutput(raw, filePath) {
|
|
95
|
+
function parseDetektOutput(raw, filePath, cwd) {
|
|
95
96
|
const diagnostics = [];
|
|
96
97
|
const pattern = /^(.+?):(\d+):(\d+): (error|warning): (.+?)(?:\s+\[([^\]]+)\])?$/gm;
|
|
97
|
-
const absTarget = path.resolve(filePath);
|
|
98
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
98
99
|
for (const match of raw.matchAll(pattern)) {
|
|
99
100
|
const [, file, lineStr, colStr, level, message, rule] = match;
|
|
100
|
-
|
|
101
|
+
// #3278: one seam for reported-path attribution — see javac.ts.
|
|
102
|
+
if (!pathsEqual(path.resolve(cwd, file.trim()), absTarget))
|
|
101
103
|
continue;
|
|
102
104
|
const severity = level === "error" ? "error" : "warning";
|
|
103
105
|
const lineNum = Number.parseInt(lineStr, 10);
|
|
@@ -150,7 +152,12 @@ const detektRunner = {
|
|
|
150
152
|
// read the same concatenated string. A nonzero exit that yields zero
|
|
151
153
|
// findings out of real output is a parser break, not clean Kotlin.
|
|
152
154
|
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
153
|
-
const run = parseToolRun("detekt", {
|
|
155
|
+
const run = parseToolRun("detekt", {
|
|
156
|
+
result,
|
|
157
|
+
output: raw,
|
|
158
|
+
// EXIT TABLE (detekt 1.23 measured fixture): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
159
|
+
exitCodes: { ran: [1, 2] },
|
|
160
|
+
}, (out) => parseDetektOutput(out, ctx.filePath, cwd));
|
|
154
161
|
if (run.skipped)
|
|
155
162
|
return run.skipped;
|
|
156
163
|
const diagnostics = run.diagnostics;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
4
5
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
6
7
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
8
|
+
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
7
9
|
const dotnet = createAvailabilityChecker("dotnet", ".exe");
|
|
8
10
|
function findProjectTarget(cwd) {
|
|
9
11
|
const entries = fs.readdirSync(cwd);
|
|
@@ -83,16 +85,16 @@ function parseDotnetDiagnosticLine(line) {
|
|
|
83
85
|
}
|
|
84
86
|
return { reportedFile, lineStr, colStr, severityLabel, rule, message };
|
|
85
87
|
}
|
|
86
|
-
function parseDotnetBuildOutput(raw, filePath) {
|
|
88
|
+
function parseDotnetBuildOutput(raw, filePath, cwd) {
|
|
87
89
|
const diagnostics = [];
|
|
90
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
88
91
|
for (const line of raw.split(/\r?\n/)) {
|
|
89
92
|
const parsed = parseDotnetDiagnosticLine(line);
|
|
90
93
|
if (!parsed)
|
|
91
94
|
continue;
|
|
92
95
|
const { reportedFile, lineStr, colStr, severityLabel, rule, message } = parsed;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (resolvedReported !== resolvedTarget)
|
|
96
|
+
// #3278: one seam for reported-path attribution — see javac.ts.
|
|
97
|
+
if (!pathsEqual(path.resolve(cwd, reportedFile), absTarget))
|
|
96
98
|
continue;
|
|
97
99
|
const severity = severityLabel.toLowerCase() === "error" ? "error" : "warning";
|
|
98
100
|
const lineNum = Number.parseInt(lineStr, 10) || 1;
|
|
@@ -136,24 +138,27 @@ const dotnetBuildRunner = {
|
|
|
136
138
|
timeout: 60000,
|
|
137
139
|
});
|
|
138
140
|
const raw = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim();
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
141
|
+
const parsed = parseToolRun("dotnet-build", {
|
|
142
|
+
result,
|
|
143
|
+
output: raw,
|
|
144
|
+
// EXIT TABLE (.NET SDK 8 measured fixture): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
145
|
+
exitCodes: { ran: [1, 2] },
|
|
146
|
+
}, (output) => parseDotnetBuildOutput(output, ctx.filePath, cwd));
|
|
147
|
+
if (parsed.skipped)
|
|
148
|
+
return parsed.skipped;
|
|
149
|
+
return finishParsedRun({
|
|
150
|
+
tool: "dotnet-build",
|
|
151
|
+
ctx,
|
|
152
|
+
result,
|
|
153
|
+
diagnostics: parsed.diagnostics,
|
|
154
|
+
classify: (diagnostics) => {
|
|
155
|
+
const hasErrors = diagnostics.some((d) => d.severity === "error");
|
|
156
|
+
return {
|
|
157
|
+
status: hasErrors ? "failed" : "succeeded",
|
|
158
|
+
semantic: hasErrors ? "blocking" : "warning",
|
|
159
|
+
};
|
|
160
|
+
},
|
|
161
|
+
});
|
|
157
162
|
},
|
|
158
163
|
};
|
|
159
164
|
export default dotnetBuildRunner;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { getProjectDataDir } from "../../file-utils.js";
|
|
4
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
4
5
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
5
6
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
6
7
|
import { PRIORITY } from "../priorities.js";
|
|
7
8
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
9
|
+
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
8
10
|
// Per-cwd cached `--version` probes (#120). Before this, each dispatch
|
|
9
11
|
// invocation fired a fresh `safeSpawnAsync` per command — once per Elixir
|
|
10
12
|
// file save.
|
|
@@ -34,15 +36,15 @@ function parseElixirOutput(raw, filePath, cwd = process.cwd()) {
|
|
|
34
36
|
const lines = raw.split(/\r?\n/);
|
|
35
37
|
// elixirc reports paths RELATIVE to its cwd (e.g. `bad.ex`, not the absolute
|
|
36
38
|
// path we passed), so resolve the reported path against the runner cwd — not
|
|
37
|
-
// process.cwd().
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
// process.cwd(). Two resolved spellings of ONE file still differ in ways
|
|
40
|
+
// only the filesystem can settle — Elixir 1.16+ normalizes to a lowercase
|
|
41
|
+
// drive letter and forward slashes (`c:/...`), which never string-equals
|
|
42
|
+
// `C:\...` on Windows — so ask `pathsEqual`, the repo's on-disk identity
|
|
43
|
+
// seam, instead of hand-rolling a win32 case fold here. It folds case
|
|
44
|
+
// exactly where the filesystem does and nowhere else, which a
|
|
45
|
+
// `process.platform` test cannot express; `terragrunt.ts:90` asks the same
|
|
46
|
+
// question the same way (#1193).
|
|
47
|
+
const matchesTarget = (sourcePath) => pathsEqual(path.resolve(cwd, sourcePath.trim()), resolvedTarget);
|
|
46
48
|
for (let index = 0; index < lines.length; index++) {
|
|
47
49
|
const line = lines[index];
|
|
48
50
|
// Defense-in-depth: cap line length before regex matching. The input is
|
|
@@ -130,12 +132,6 @@ function parseElixirOutput(raw, filePath, cwd = process.cwd()) {
|
|
|
130
132
|
}
|
|
131
133
|
return diagnostics;
|
|
132
134
|
}
|
|
133
|
-
function firstOutputLine(result) {
|
|
134
|
-
return `${result.stderr || ""}\n${result.stdout || ""}`
|
|
135
|
-
.trim()
|
|
136
|
-
.split(/\r?\n/, 1)[0]
|
|
137
|
-
.slice(0, 200);
|
|
138
|
-
}
|
|
139
135
|
const elixirCheckRunner = {
|
|
140
136
|
id: "elixir-check",
|
|
141
137
|
appliesTo: ["elixir"],
|
|
@@ -163,47 +159,36 @@ const elixirCheckRunner = {
|
|
|
163
159
|
cwd,
|
|
164
160
|
timeout: 30000,
|
|
165
161
|
});
|
|
166
|
-
if (result.error && !result.stdout && !result.stderr) {
|
|
167
|
-
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
168
|
-
}
|
|
169
162
|
const raw = `${result.stderr || ""}\n${result.stdout || ""}`;
|
|
170
163
|
const hasProjectContext = command === "mix";
|
|
171
|
-
const
|
|
164
|
+
const parsed = parseToolRun("elixir-check", {
|
|
165
|
+
result,
|
|
166
|
+
output: raw,
|
|
167
|
+
// EXIT TABLE (Elixir 1.16 measured fixture): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
168
|
+
exitCodes: { ran: [1, 2] },
|
|
169
|
+
}, (out) => parseElixirOutput(out, ctx.filePath, cwd).map((d) => hasProjectContext
|
|
172
170
|
? d
|
|
173
171
|
: {
|
|
174
172
|
...d,
|
|
175
173
|
// A direct elixirc invocation cannot resolve Mix dependencies.
|
|
176
174
|
// Standalone findings inform the agent, but cannot block it.
|
|
177
175
|
semantic: "warning",
|
|
178
|
-
});
|
|
179
|
-
if (
|
|
180
|
-
|
|
176
|
+
}));
|
|
177
|
+
if (parsed.skipped)
|
|
178
|
+
return parsed.skipped;
|
|
179
|
+
return finishParsedRun({
|
|
180
|
+
tool: "elixir-check",
|
|
181
|
+
ctx,
|
|
182
|
+
result,
|
|
183
|
+
diagnostics: parsed.diagnostics,
|
|
184
|
+
classify: (diagnostics) => {
|
|
185
|
+
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
|
|
181
186
|
return {
|
|
182
|
-
status: "failed",
|
|
183
|
-
|
|
184
|
-
{
|
|
185
|
-
id: "elixir-check-nonzero-no-diagnostics",
|
|
186
|
-
message: firstOutputLine(result) ||
|
|
187
|
-
`${command} exited non-zero without structured diagnostics`,
|
|
188
|
-
filePath: ctx.filePath,
|
|
189
|
-
severity: "error",
|
|
190
|
-
semantic: hasProjectContext ? "blocking" : "warning",
|
|
191
|
-
tool: "elixir-check",
|
|
192
|
-
rule: command,
|
|
193
|
-
fixable: false,
|
|
194
|
-
},
|
|
195
|
-
],
|
|
196
|
-
semantic: hasProjectContext ? "blocking" : "warning",
|
|
187
|
+
status: hasBlocking ? "failed" : "succeeded",
|
|
188
|
+
semantic: hasBlocking ? "blocking" : "warning",
|
|
197
189
|
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
const hasBlocking = diagnostics.some((d) => d.semantic === "blocking");
|
|
202
|
-
return {
|
|
203
|
-
status: hasBlocking ? "failed" : "succeeded",
|
|
204
|
-
diagnostics,
|
|
205
|
-
semantic: hasBlocking ? "blocking" : "warning",
|
|
206
|
-
};
|
|
190
|
+
},
|
|
191
|
+
});
|
|
207
192
|
},
|
|
208
193
|
};
|
|
209
194
|
export default elixirCheckRunner;
|
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Gate: skips when no ESLint config is detected (project uses Biome/OxLint instead).
|
|
8
8
|
*/
|
|
9
|
+
import * as path from "node:path";
|
|
10
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
9
11
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
10
12
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
11
13
|
import { getAutofixCapability, hasEslintConfig } from "../../tool-policy.js";
|
|
12
14
|
import { PRIORITY } from "../priorities.js";
|
|
13
15
|
import { createCwdCachedProbe, resolveToolCommand, } from "./utils/runner-helpers.js";
|
|
16
|
+
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
14
17
|
const ESLINT_PROBE_BUDGET_MS = 5000;
|
|
15
18
|
// Per-cwd cached eslint `--version` verification (#120). Before this, every
|
|
16
19
|
// dispatch invocation ran a fresh `safeSpawnAsync(cmd, ["--version"])` after
|
|
@@ -40,12 +43,18 @@ function getEslintProbe(cmd) {
|
|
|
40
43
|
eslintAvailabilityByCmd.set(cmd, created);
|
|
41
44
|
return created;
|
|
42
45
|
}
|
|
43
|
-
function parseEslintJson(raw, filePath) {
|
|
46
|
+
function parseEslintJson(raw, filePath, cwd) {
|
|
44
47
|
try {
|
|
45
48
|
const results = JSON.parse(raw);
|
|
46
49
|
const autofix = getAutofixCapability("eslint");
|
|
47
50
|
const diagnostics = [];
|
|
51
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
48
52
|
for (const fileResult of results) {
|
|
53
|
+
// #3295: flat config `files`/`ignores` and a directory argv both put a
|
|
54
|
+
// SECOND result in this array; each names its own `filePath`.
|
|
55
|
+
if (fileResult.filePath &&
|
|
56
|
+
!pathsEqual(path.resolve(cwd, fileResult.filePath), absTarget))
|
|
57
|
+
continue;
|
|
49
58
|
for (const msg of fileResult.messages) {
|
|
50
59
|
const severity = msg.severity === 2 ? "error" : "warning";
|
|
51
60
|
diagnostics.push({
|
|
@@ -92,11 +101,11 @@ const eslintRunner = {
|
|
|
92
101
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
93
102
|
}
|
|
94
103
|
const result = await safeSpawnAsync(cmd, ["--format", "json", "--no-error-on-unmatched-pattern", ctx.filePath], { timeout: 30000, cwd });
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
// Exit table: 0 is clean-or-findings, and 1/2 are ran outcomes whose
|
|
105
|
+
// JSON parser decides whether findings or a parse/config error reached the
|
|
106
|
+
// user. In particular, status 2 carries file-local fatal parse messages
|
|
107
|
+
// as JSON and must not be discarded before parsing.
|
|
108
|
+
//
|
|
100
109
|
// ESLint exits 0 whenever nothing reached ERROR severity — that
|
|
101
110
|
// includes a run that found only warnings (#1954), which also prints a
|
|
102
111
|
// full JSON report. So parse stdout unconditionally and branch on the
|
|
@@ -109,46 +118,20 @@ const eslintRunner = {
|
|
|
109
118
|
if (raw.length === 0 && result.status !== 0) {
|
|
110
119
|
raw = result.stderr || "";
|
|
111
120
|
}
|
|
112
|
-
const parsed =
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
severity: "warning",
|
|
127
|
-
semantic: "warning",
|
|
128
|
-
tool: "eslint",
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
semantic: "warning",
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
const diagnostics = parsed.diagnostics;
|
|
135
|
-
if (diagnostics.length === 0) {
|
|
136
|
-
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
137
|
-
}
|
|
138
|
-
const hasErrors = diagnostics.some((d) => d.semantic === "blocking");
|
|
139
|
-
// A warning-only result on exit 0 is ESLint's normal outcome, not a
|
|
140
|
-
// failure: exit 0 means nothing hit ERROR severity. Keying status off
|
|
141
|
-
// blocking severity plus exit code (the sibling convention from oxlint,
|
|
142
|
-
// biome-check, golangci-lint, rubocop) keeps plan.ts's fallback group
|
|
143
|
-
// ["eslint", "oxlint", "biome-check-json"] stopping at eslint instead
|
|
144
|
-
// of re-running oxlint and biome-check-json on every warning-only save.
|
|
145
|
-
// The findings reach delivery regardless of status — dispatcher.ts
|
|
146
|
-
// buckets by each diagnostic's own `semantic`.
|
|
147
|
-
return {
|
|
148
|
-
status: !hasErrors && result.status === 0 ? "succeeded" : "failed",
|
|
149
|
-
diagnostics,
|
|
150
|
-
semantic: hasErrors ? "blocking" : "warning",
|
|
151
|
-
};
|
|
121
|
+
const parsed = parseToolRun("eslint", {
|
|
122
|
+
result,
|
|
123
|
+
output: raw,
|
|
124
|
+
// EXIT TABLE (ESLint 9.10 docs https://eslint.org/docs/latest/use/command-line-interface): 0 clean; 1 findings; 2 fatal findings/error; other nonzero rejected.
|
|
125
|
+
exitCodes: { ran: [1, 2] },
|
|
126
|
+
}, (rawOutput) => parseEslintJson(rawOutput, ctx.filePath, cwd).diagnostics);
|
|
127
|
+
if (parsed.skipped)
|
|
128
|
+
return parsed.skipped;
|
|
129
|
+
return finishParsedRun({
|
|
130
|
+
tool: "eslint",
|
|
131
|
+
ctx,
|
|
132
|
+
result,
|
|
133
|
+
diagnostics: parsed.diagnostics,
|
|
134
|
+
});
|
|
152
135
|
},
|
|
153
136
|
};
|
|
154
137
|
export default eslintRunner;
|