@herbertgao/pi-extensions 2026.9.15 โ 2026.9.17
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 +5 -0
- package/THIRD_PARTY_NOTICES.md +26 -0
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +1 -1
- package/node_modules/@herbertgao/sol-pi/package.json +1 -1
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +11 -53
- 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-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-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 +9 -6
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
2
3
|
import { findLocalBinUpwards } from "../../package-manager.js";
|
|
4
|
+
import { stripAnsi } from "../../sanitize.js";
|
|
3
5
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
6
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
5
7
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
@@ -12,6 +14,7 @@ const taplo = createAvailabilityChecker("taplo", ".exe");
|
|
|
12
14
|
//
|
|
13
15
|
// #1937 round 2: the parser fix alone turned the old silent-clean into a false
|
|
14
16
|
// BLOCKING diagnostic. clap prints `error: unexpected argument '--output'
|
|
17
|
+
// EXIT TABLE (taplo 0.9 measured fixture): 0 clean; 1 findings; other nonzero rejected/error.
|
|
15
18
|
// found`, which starts with the same lowercase `error:` a real taplo
|
|
16
19
|
// diagnostic does, so a mistyped flag would have reddened every valid TOML
|
|
17
20
|
// file. Both readings are wrong; the exit code is what separates them.
|
|
@@ -21,7 +24,7 @@ const HEADER_PATTERN = /^\s*(error|warning):(.*)$/;
|
|
|
21
24
|
/** The box-drawing lead taplo puts on a codespan location line. */
|
|
22
25
|
const LOCATION_LEAD = "โโ";
|
|
23
26
|
/** The `:line:column` tail of a codespan location line. */
|
|
24
|
-
const LOCATION_PATTERN =
|
|
27
|
+
const LOCATION_PATTERN = /^\s*โโ\s+(.+?):(\d+):(\d+)$/;
|
|
25
28
|
/**
|
|
26
29
|
* Parse `taplo lint` output (#1937).
|
|
27
30
|
*
|
|
@@ -48,9 +51,10 @@ const LOCATION_PATTERN = /:(\d+):(\d+)$/;
|
|
|
48
51
|
* (#1937 round 2). The exit-code table in the runner is the primary guard;
|
|
49
52
|
* this is the structural one, and each covers a case the other does not.
|
|
50
53
|
*/
|
|
51
|
-
export function parseTaploOutput(raw, filePath) {
|
|
54
|
+
export function parseTaploOutput(raw, filePath, cwd) {
|
|
52
55
|
const diagnostics = [];
|
|
53
|
-
const
|
|
56
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
57
|
+
const lines = stripAnsi(raw ?? "").split(/\r?\n/);
|
|
54
58
|
for (let i = 0; i < lines.length; i++) {
|
|
55
59
|
// Lowercase `error:`/`warning:` starts a diagnostic. taplo's tracing
|
|
56
60
|
// lines are uppercase (`ERROR taplo:lint_files: ...`), so a
|
|
@@ -79,8 +83,10 @@ export function parseTaploOutput(raw, filePath) {
|
|
|
79
83
|
const location = LOCATION_PATTERN.exec(lines[j].trimEnd());
|
|
80
84
|
if (!location)
|
|
81
85
|
continue;
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
if (!pathsEqual(path.resolve(cwd, location[1].trim()), absTarget))
|
|
87
|
+
continue;
|
|
88
|
+
line = Number.parseInt(location[2], 10) || 1;
|
|
89
|
+
column = Number.parseInt(location[3], 10) || 1;
|
|
84
90
|
break;
|
|
85
91
|
}
|
|
86
92
|
if (line === null)
|
|
@@ -155,7 +161,7 @@ const taploRunner = {
|
|
|
155
161
|
// outright lie, so taplo opts into `skipWhenParsedNothing` (#1948). This
|
|
156
162
|
// replaces a hand-rolled per-runner copy of the same rule, which wrote
|
|
157
163
|
// its own `runner-empty-result` row with its own wording.
|
|
158
|
-
const run = parseToolRun("taplo", { result, output: raw, exitCodes: TAPLO_EXIT_CODES }, (out) => parseTaploOutput(out, ctx.filePath), { skipWhenParsedNothing: true });
|
|
164
|
+
const run = parseToolRun("taplo", { result, output: raw, exitCodes: TAPLO_EXIT_CODES }, (out) => parseTaploOutput(out, ctx.filePath, cwd), { skipWhenParsedNothing: true });
|
|
159
165
|
if (run.skipped)
|
|
160
166
|
return run.skipped;
|
|
161
167
|
const diagnostics = run.diagnostics;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
2
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
4
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
4
5
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
@@ -23,24 +24,34 @@ function findTflintConfig(fileDir) {
|
|
|
23
24
|
const dir = findNearestDirWithAnyBasename(fileDir, [TFLINT_CONFIG]);
|
|
24
25
|
return dir ? path.join(dir, TFLINT_CONFIG) : null;
|
|
25
26
|
}
|
|
26
|
-
function parseTflintOutput(raw, filePath) {
|
|
27
|
+
function parseTflintOutput(raw, filePath, toolCwd) {
|
|
27
28
|
try {
|
|
28
29
|
const parsed = JSON.parse(raw);
|
|
29
30
|
const issues = parsed.issues ?? [];
|
|
30
|
-
|
|
31
|
+
// #3295: tflint loads EVERY `*.tf` in its working directory โ `--filter` is
|
|
32
|
+
// best-effort โ and names each issue's own `range.filename`, relative to
|
|
33
|
+
// the directory it ran in (`toolCwd`, which is the file's dir, not the
|
|
34
|
+
// runner cwd).
|
|
35
|
+
const absTarget = path.resolve(toolCwd, filePath);
|
|
36
|
+
return issues.flatMap((issue) => {
|
|
37
|
+
if (issue.range?.filename &&
|
|
38
|
+
!pathsEqual(path.resolve(toolCwd, issue.range.filename), absTarget))
|
|
39
|
+
return [];
|
|
31
40
|
const severity = issue.rule.severity === "error" ? "error" : "warning";
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
id: `tflint-${issue.rule.name}-${issue.range.start.line}`,
|
|
44
|
+
message: `[${issue.rule.name}] ${issue.message}`,
|
|
45
|
+
filePath,
|
|
46
|
+
line: issue.range.start.line,
|
|
47
|
+
column: issue.range.start.column,
|
|
48
|
+
severity,
|
|
49
|
+
semantic: severity === "error" ? "blocking" : "warning",
|
|
50
|
+
tool: "tflint",
|
|
51
|
+
rule: issue.rule.name,
|
|
52
|
+
fixable: false,
|
|
53
|
+
},
|
|
54
|
+
];
|
|
44
55
|
});
|
|
45
56
|
}
|
|
46
57
|
catch {
|
|
@@ -88,7 +99,11 @@ const tflintRunner = {
|
|
|
88
99
|
// not a clean file. No exit-code table: tflint's nonzero codes are not
|
|
89
100
|
// verified against a real binary here, so the conservative
|
|
90
101
|
// nothing-to-parse rule stays the only discriminator.
|
|
91
|
-
const run = parseToolRun("tflint", {
|
|
102
|
+
const run = parseToolRun("tflint", {
|
|
103
|
+
result,
|
|
104
|
+
// EXIT TABLE (TFLint 0.52 measured fixture): 0 clean; 1 error; 2 findings; other nonzero rejected.
|
|
105
|
+
exitCodes: { ran: [1, 2] },
|
|
106
|
+
}, (out) => parseTflintOutput(out, absPath, fileDir));
|
|
92
107
|
if (run.skipped)
|
|
93
108
|
return run.skipped;
|
|
94
109
|
const diagnostics = run.diagnostics;
|
|
@@ -585,6 +585,29 @@ const treeSitterRunner = {
|
|
|
585
585
|
}
|
|
586
586
|
}
|
|
587
587
|
if (diagnostics.length === 0) {
|
|
588
|
+
// #3409: zero diagnostics because the language's GRAMMAR never loaded is
|
|
589
|
+
// not a clean file, and `runQueriesOnFile` returns [] for both. The
|
|
590
|
+
// honest discriminator, once the run has already demanded the language,
|
|
591
|
+
// is the client's own loaded-language map: a grammar that could not be
|
|
592
|
+
// resolved, fetched, or decoded is absent from it. Reported through this
|
|
593
|
+
// runner's existing "the analysis did not run" arm (the same
|
|
594
|
+
// `runner_skip` + `status: "skipped"` shape as client-unavailable,
|
|
595
|
+
// init-failed and unsupported-extension) instead of as a pass with
|
|
596
|
+
// nothing found โ which is what made a degraded language on a compiled
|
|
597
|
+
// host indistinguishable from a clean file in `runner_complete`.
|
|
598
|
+
//
|
|
599
|
+
// The abort term keeps a mid-run WASM abort (#402, its own
|
|
600
|
+
// `runtime_abort` record) from being misreported as a missing grammar.
|
|
601
|
+
if (!isTreeSitterWasmAborted() && !client.getLanguage(languageId)) {
|
|
602
|
+
logTreeSitter({
|
|
603
|
+
phase: "runner_skip",
|
|
604
|
+
filePath,
|
|
605
|
+
languageId,
|
|
606
|
+
reason: "grammar_unavailable",
|
|
607
|
+
status: "skipped",
|
|
608
|
+
});
|
|
609
|
+
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
610
|
+
}
|
|
588
611
|
logTreeSitter({
|
|
589
612
|
phase: "runner_complete",
|
|
590
613
|
filePath,
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
import { formatToolFailure } from "./utils/tool-failure.js";
|
|
39
39
|
import * as fs from "node:fs";
|
|
40
40
|
import * as path from "node:path";
|
|
41
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
41
42
|
import { incrementDegradationCount } from "../../degradation-ledger.js";
|
|
42
43
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
43
44
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
@@ -89,7 +90,7 @@ function normalizeSeverity(raw) {
|
|
|
89
90
|
* CauseMetadata: { StartLine } }] }] }`. CRITICAL โ blocking, the rest advisory.
|
|
90
91
|
* Defensive: malformed input returns `[]`. Exported for unit tests.
|
|
91
92
|
*/
|
|
92
|
-
export function parseTrivyConfigOutput(raw, filePath) {
|
|
93
|
+
export function parseTrivyConfigOutput(raw, filePath, cwd = process.cwd()) {
|
|
93
94
|
if (!raw.trim())
|
|
94
95
|
return [];
|
|
95
96
|
let parsed;
|
|
@@ -103,9 +104,14 @@ export function parseTrivyConfigOutput(raw, filePath) {
|
|
|
103
104
|
if (!Array.isArray(results))
|
|
104
105
|
return [];
|
|
105
106
|
const diagnostics = [];
|
|
107
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
106
108
|
for (const resultEntry of results) {
|
|
107
109
|
if (!resultEntry || typeof resultEntry !== "object")
|
|
108
110
|
continue;
|
|
111
|
+
const target = resultEntry.Target;
|
|
112
|
+
if (typeof target !== "string" ||
|
|
113
|
+
!pathsEqual(path.resolve(cwd, target), absTarget))
|
|
114
|
+
continue;
|
|
109
115
|
const rows = resultEntry
|
|
110
116
|
.Misconfigurations;
|
|
111
117
|
if (!Array.isArray(rows))
|
|
@@ -232,7 +238,7 @@ const trivyConfigRunner = {
|
|
|
232
238
|
});
|
|
233
239
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
234
240
|
}
|
|
235
|
-
const diagnostics = parseTrivyConfigOutput(result.stdout || "", ctx.filePath);
|
|
241
|
+
const diagnostics = parseTrivyConfigOutput(result.stdout || "", ctx.filePath, cwd);
|
|
236
242
|
if (diagnostics.length === 0) {
|
|
237
243
|
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
238
244
|
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Common patterns for parsing tool output into standardized diagnostics.
|
|
5
5
|
* Supports the common `file:line:col: message` format used by most linters.
|
|
6
6
|
*/
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { pathsEqual } from "../../../path-utils.js";
|
|
7
9
|
import { stripAnsi } from "../../../sanitize.js";
|
|
8
10
|
import { getAutofixCapability } from "../../../tool-policy.js";
|
|
9
11
|
/**
|
|
@@ -11,8 +13,13 @@ import { getAutofixCapability } from "../../../tool-policy.js";
|
|
|
11
13
|
* Common format: file:line:col: message (with variations)
|
|
12
14
|
*/
|
|
13
15
|
function createLineParser(config) {
|
|
14
|
-
return (raw, filePath) => {
|
|
16
|
+
return (raw, filePath, cwd) => {
|
|
15
17
|
const diagnostics = [];
|
|
18
|
+
// #3295: `config.regex` is documented above as capturing the FILE in group
|
|
19
|
+
// 1, and every parser built here then dropped it and stamped the dispatched
|
|
20
|
+
// path on every line. This is the shared factory, so the predicate lives
|
|
21
|
+
// here once rather than in each `createLineParser` caller.
|
|
22
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
16
23
|
// Optionally strip ANSI codes (for tools that output colored text)
|
|
17
24
|
const clean = config.stripAnsi !== false ? stripAnsi(raw) : raw;
|
|
18
25
|
const lines = clean.split("\n").filter((l) => l.trim());
|
|
@@ -20,6 +27,9 @@ function createLineParser(config) {
|
|
|
20
27
|
const match = line.match(config.regex);
|
|
21
28
|
if (!match)
|
|
22
29
|
continue;
|
|
30
|
+
const reported = match[1];
|
|
31
|
+
if (reported && !pathsEqual(path.resolve(cwd, reported), absTarget))
|
|
32
|
+
continue;
|
|
23
33
|
const lineNum = parseInt(match[2], 10);
|
|
24
34
|
const colNum = parseInt(match[3], 10);
|
|
25
35
|
const severity = config.getSeverity
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
3
4
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
5
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
@@ -25,17 +26,24 @@ function findValeConfig(cwd) {
|
|
|
25
26
|
}
|
|
26
27
|
return undefined;
|
|
27
28
|
}
|
|
28
|
-
export function parseValeOutput(raw, filePath) {
|
|
29
|
+
export function parseValeOutput(raw, filePath, cwd) {
|
|
29
30
|
const diagnostics = [];
|
|
30
31
|
if (!raw.trim())
|
|
31
32
|
return diagnostics;
|
|
33
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
32
34
|
try {
|
|
33
35
|
const parsed = JSON.parse(raw);
|
|
34
36
|
if (!parsed || typeof parsed !== "object")
|
|
35
37
|
return diagnostics;
|
|
36
|
-
|
|
38
|
+
// #3295: vale's top level is keyed BY the linted file's path โ the only
|
|
39
|
+
// place the reported path appears. `Object.values` dropped it, so a
|
|
40
|
+
// `.vale.ini` glob or a directory argv charged a second file's alerts to
|
|
41
|
+
// the dispatched one.
|
|
42
|
+
for (const [reported, alerts] of Object.entries(parsed)) {
|
|
37
43
|
if (!Array.isArray(alerts))
|
|
38
44
|
continue;
|
|
45
|
+
if (reported && !pathsEqual(path.resolve(cwd, reported), absTarget))
|
|
46
|
+
continue;
|
|
39
47
|
for (const alert of alerts) {
|
|
40
48
|
if (!alert.Message)
|
|
41
49
|
continue;
|
|
@@ -98,7 +106,11 @@ const valeRunner = {
|
|
|
98
106
|
// #1948: `parseToolRun` adds the second gate. Vale's `Data.Files`
|
|
99
107
|
// envelope bug produced exactly this shape โ exit 1, a full JSON
|
|
100
108
|
// report on stdout, zero alerts parsed โ and left no record.
|
|
101
|
-
const run = parseToolRun("vale", {
|
|
109
|
+
const run = parseToolRun("vale", {
|
|
110
|
+
result,
|
|
111
|
+
// EXIT TABLE (Vale 3.9.6 docs https://vale.sh/docs/topics/metrics/): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
112
|
+
exitCodes: { ran: [1, 2] },
|
|
113
|
+
}, (raw) => parseValeOutput(raw, ctx.filePath, cwd));
|
|
102
114
|
if (run.skipped)
|
|
103
115
|
return run.skipped;
|
|
104
116
|
const diagnostics = run.diagnostics;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
1
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
2
4
|
import { logRunnerAdvisoryOnce } from "../../tool-cwd.js";
|
|
3
5
|
import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
|
|
@@ -7,14 +9,17 @@ import { parseToolRun } from "./utils/tool-failure.js";
|
|
|
7
9
|
import { finishParsedRun } from "./utils/tool-failure.js";
|
|
8
10
|
const yamllint = createAvailabilityChecker("yamllint", ".exe");
|
|
9
11
|
export { hasYamllintConfig };
|
|
10
|
-
function parseYamllintParsable(raw, filePath) {
|
|
12
|
+
function parseYamllintParsable(raw, filePath, cwd) {
|
|
11
13
|
const diagnostics = [];
|
|
14
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
12
15
|
for (const line of raw.split(/\r?\n/)) {
|
|
13
16
|
if (!line.trim())
|
|
14
17
|
continue;
|
|
15
18
|
const match = line.match(/^(.*?):(\d+):(\d+):\s*\[(error|warning)\]\s*(.*?)\s*\(([^)]+)\)\s*$/i);
|
|
16
19
|
if (!match)
|
|
17
20
|
continue;
|
|
21
|
+
if (!pathsEqual(path.resolve(cwd, match[1]), absTarget))
|
|
22
|
+
continue;
|
|
18
23
|
const severity = match[4].toLowerCase() === "error" ? "error" : "warning";
|
|
19
24
|
diagnostics.push({
|
|
20
25
|
id: `yamllint-${match[2]}-${match[3]}-${match[6]}`,
|
|
@@ -70,7 +75,12 @@ const yamllintRunner = {
|
|
|
70
75
|
const raw = `${result.stdout ?? ""}${result.stderr ?? ""}`;
|
|
71
76
|
// #1948: classify on stdout as before, parse both streams as before, and
|
|
72
77
|
// record when a failing run yields nothing.
|
|
73
|
-
const run = parseToolRun("yamllint", {
|
|
78
|
+
const run = parseToolRun("yamllint", {
|
|
79
|
+
result,
|
|
80
|
+
output: result.stdout,
|
|
81
|
+
// EXIT TABLE (yamllint 1.35 docs https://yamllint.readthedocs.io/en/stable/): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
82
|
+
exitCodes: { ran: [1, 2] },
|
|
83
|
+
}, (out) => parseYamllintParsable(out, ctx.filePath, cwd), { parseOutput: raw });
|
|
74
84
|
if (run.skipped)
|
|
75
85
|
return run.skipped;
|
|
76
86
|
const diagnostics = run.diagnostics;
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
+
import { pathsEqual } from "../../path-utils.js";
|
|
2
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
4
|
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
4
5
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
7
|
+
import { finishParsedRun, parseToolRun } from "./utils/tool-failure.js";
|
|
6
8
|
// zig rejects `--version`; the version subcommand is `zig version`. Using the
|
|
7
9
|
// default probe would make this runner skip on every machine.
|
|
8
10
|
const zig = createAvailabilityChecker("zig", ".exe", ["version"]);
|
|
9
|
-
function parseZigOutput(raw, filePath) {
|
|
11
|
+
function parseZigOutput(raw, filePath, cwd) {
|
|
10
12
|
const diagnostics = [];
|
|
13
|
+
const absTarget = path.resolve(cwd, filePath);
|
|
11
14
|
for (const line of raw.split(/\r?\n/)) {
|
|
12
15
|
const match = line.match(/^(.*?):(\d+):(\d+):\s*(error|warning|note):\s*(.+)$/);
|
|
13
16
|
if (!match)
|
|
14
17
|
continue;
|
|
15
18
|
const [, rawFile, lineStr, colStr, level, message] = match;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (resolvedSource !== resolvedTarget)
|
|
19
|
+
// #3278: one seam for reported-path attribution โ see javac.ts.
|
|
20
|
+
if (!pathsEqual(path.resolve(cwd, rawFile.trim()), absTarget))
|
|
19
21
|
continue;
|
|
20
22
|
const severity = level === "error" ? "error" : "warning";
|
|
21
23
|
diagnostics.push({
|
|
@@ -35,12 +37,6 @@ function parseZigOutput(raw, filePath) {
|
|
|
35
37
|
}
|
|
36
38
|
return diagnostics;
|
|
37
39
|
}
|
|
38
|
-
function firstOutputLine(result) {
|
|
39
|
-
return `${result.stderr || ""}\n${result.stdout || ""}`
|
|
40
|
-
.trim()
|
|
41
|
-
.split(/\r?\n/, 1)[0]
|
|
42
|
-
.slice(0, 200);
|
|
43
|
-
}
|
|
44
40
|
const zigCheckRunner = {
|
|
45
41
|
id: "zig-check",
|
|
46
42
|
appliesTo: ["zig"],
|
|
@@ -57,35 +53,27 @@ const zigCheckRunner = {
|
|
|
57
53
|
if (result.error && !result.stdout && !result.stderr) {
|
|
58
54
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
59
55
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return { status: "succeeded", diagnostics: [], semantic: "none" };
|
|
82
|
-
}
|
|
83
|
-
const hasErrors = diagnostics.some((d) => d.severity === "error");
|
|
84
|
-
return {
|
|
85
|
-
status: hasErrors ? "failed" : "succeeded",
|
|
86
|
-
diagnostics,
|
|
87
|
-
semantic: "warning",
|
|
88
|
-
};
|
|
56
|
+
const raw = `${result.stdout || ""}\n${result.stderr || ""}`;
|
|
57
|
+
const parsed = parseToolRun("zig-check", {
|
|
58
|
+
result,
|
|
59
|
+
output: raw,
|
|
60
|
+
// EXIT TABLE (Zig 0.13 measured fixture): 0 clean; 1 findings; 2 error; other nonzero rejected.
|
|
61
|
+
exitCodes: { ran: [1, 2] },
|
|
62
|
+
}, (output) => parseZigOutput(output, ctx.filePath, cwd));
|
|
63
|
+
if (parsed.skipped)
|
|
64
|
+
return parsed.skipped;
|
|
65
|
+
return finishParsedRun({
|
|
66
|
+
tool: "zig-check",
|
|
67
|
+
ctx,
|
|
68
|
+
result,
|
|
69
|
+
diagnostics: parsed.diagnostics,
|
|
70
|
+
classify: (diagnostics) => ({
|
|
71
|
+
status: diagnostics.some((d) => d.severity === "error")
|
|
72
|
+
? "failed"
|
|
73
|
+
: "succeeded",
|
|
74
|
+
semantic: "warning",
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
89
77
|
},
|
|
90
78
|
};
|
|
91
79
|
export default zigCheckRunner;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* vice versa.
|
|
8
8
|
*/
|
|
9
9
|
import * as path from "node:path";
|
|
10
|
+
import { parseInlineSuppressionRuleIds, splitInlineSuppressionPayload, } from "./inline-suppressions.js";
|
|
10
11
|
const HASH_COMMENT_EXTENSIONS = new Set([
|
|
11
12
|
".py",
|
|
12
13
|
".rb",
|
|
@@ -50,14 +51,23 @@ export function insertSuppressComment(content, filePath, line, rule) {
|
|
|
50
51
|
const suppressRe = /((?:\/\/|#)\s*pi-lens-ignore:\s*)(.+)$/;
|
|
51
52
|
const match = existingAbove !== undefined ? suppressRe.exec(existingAbove) : null;
|
|
52
53
|
if (match && existingAbove !== undefined) {
|
|
53
|
-
const
|
|
54
|
+
const prefix = match[1];
|
|
55
|
+
const payload = match[2];
|
|
56
|
+
if (prefix === undefined || payload === undefined)
|
|
57
|
+
return content;
|
|
58
|
+
const { ruleList, trailingReason } = splitInlineSuppressionPayload(payload);
|
|
59
|
+
const rules = ruleList
|
|
54
60
|
.split(",")
|
|
55
61
|
.map((r) => r.trim())
|
|
56
62
|
.filter(Boolean);
|
|
57
|
-
|
|
63
|
+
const ruleIds = parseInlineSuppressionRuleIds(ruleList);
|
|
64
|
+
if (!ruleIds.includes(rule))
|
|
58
65
|
rules.push(rule);
|
|
59
66
|
lines[aboveIdx] =
|
|
60
|
-
existingAbove.slice(0, match.index) +
|
|
67
|
+
existingAbove.slice(0, match.index) +
|
|
68
|
+
prefix +
|
|
69
|
+
rules.join(", ") +
|
|
70
|
+
trailingReason;
|
|
61
71
|
return lines.join("\n");
|
|
62
72
|
}
|
|
63
73
|
// Match the indentation of the flagged line so the inserted comment lines
|
|
@@ -229,7 +229,9 @@ export async function effectiveConfig(options = {}) {
|
|
|
229
229
|
const resolveAt = (dir) => resolvePiLensConfig({
|
|
230
230
|
cwd: dir,
|
|
231
231
|
globalDir: getGlobalPiLensDir(),
|
|
232
|
-
|
|
232
|
+
// Production resolution for the global tier โ see loadLSPConfig's
|
|
233
|
+
// comment (global-config-location PR, refs #2457).
|
|
234
|
+
globalConfigPath: getPiLensGlobalConfigPath(),
|
|
233
235
|
homeDir,
|
|
234
236
|
});
|
|
235
237
|
// The queried path resolves HERE, beside the resolution root it selects, so
|
|
@@ -30,7 +30,11 @@
|
|
|
30
30
|
* deliver unchanged. A missed demotion is noise; a wrong drop can hide a
|
|
31
31
|
* live credential or CVE.
|
|
32
32
|
* The turn-end secrets (gitleaks/trivy-secrets) and govulncheck advisory both
|
|
33
|
-
* route through this gate in `clients/runtime-turn.ts
|
|
33
|
+
* route through this gate in `clients/runtime-turn.ts`, in ONE shared call
|
|
34
|
+
* (#3264) whose arms the secrets LANE (`clients/turn-end/lanes/secrets.ts`,
|
|
35
|
+
* #1892) renders. A lane declares its sources and never gates itself: the
|
|
36
|
+
* pass, its stat budget and its bounded records are per DELIVERY, not per
|
|
37
|
+
* lane.
|
|
34
38
|
*
|
|
35
39
|
* The SAME freshness family, one level up, covers cross-file drift: a cached
|
|
36
40
|
* inline blocker is a verdict about its file *and everything that file
|
|
@@ -222,9 +226,25 @@ function labeled(file, description, reason, ageSource, evidence = [], extra = {}
|
|
|
222
226
|
const RUNTIME_TURN_FILE = "clients/runtime-turn.ts";
|
|
223
227
|
const LENS_DIAGNOSTICS_FILE = "tools/lens-diagnostics.ts";
|
|
224
228
|
export const DELIVERY_SURFACES = {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
229
|
+
// #1892 (lane extraction): both secrets tiers are rendered by the secrets
|
|
230
|
+
// LANE (`clients/turn-end/lanes/secrets.ts`), so `clients/runtime-turn.ts`
|
|
231
|
+
// no longer reads `.live`/`.stale` itself โ the arm it can still be pinned
|
|
232
|
+
// to is the whole gated store object it hands the lane. That is WEAKER than
|
|
233
|
+
// the previous `gitleaksGate.live,` pin (it no longer says which partition
|
|
234
|
+
// feeds which tier) and the loss is deliberate: the live/stale split is a
|
|
235
|
+
// lane rule now, pinned behaviourally instead, by
|
|
236
|
+
// `tests/clients/runtime-turn-finding-freshness.test.ts` ("keeps an
|
|
237
|
+
// unmodified file's finding as a full-severity blocker" / "DEMOTES a
|
|
238
|
+
// finding whose file was edited after the scan โ kept, no line") and the
|
|
239
|
+
// committed witness goldens under `tests/fixtures/witness/`. What the pin
|
|
240
|
+
// still proves is what this registry exists for: the rows the tier renders
|
|
241
|
+
// came out of a real `gateFindingsByPathFreshness` call and not out of a
|
|
242
|
+
// hand-built object (the R2 binding chain in
|
|
243
|
+
// `tests/clients/finding-delivery-gate.test.ts` walks
|
|
244
|
+
// `gitleaksGate` โ `scannerGates` โ the call).
|
|
245
|
+
"runtime-turn:secrets-gitleaks": gated(RUNTIME_TURN_FILE, "Turn-end ๐ด secrets blocker, gitleaks cache.", ["gateFindingsByPathFreshness"], ["gitleaksGate,"]),
|
|
246
|
+
"runtime-turn:secrets-trivy": gated(RUNTIME_TURN_FILE, "Turn-end ๐ด secrets blocker, trivy secrets cache.", ["gateFindingsByPathFreshness"], ["trivySecretsGate,"]),
|
|
247
|
+
"runtime-turn:govulncheck-advisory": gated(RUNTIME_TURN_FILE, "Turn-end ๐ก๏ธ Go CVE advisory (call-site line only).", ["gateFindingsByPathFreshness"], ["scannerGates.govulncheck"]),
|
|
228
248
|
// Two tagged seams (the stale and live render branches below the same
|
|
229
249
|
// `sweepInlineBlockerFreshness` call) legitimately share one evidence
|
|
230
250
|
// occurrence โ evidenceMin: 2 tells the exclusive-assignment check both
|
|
@@ -234,9 +254,11 @@ export const DELIVERY_SURFACES = {
|
|
|
234
254
|
// third argument, so the literal is the call's opening rather than the
|
|
235
255
|
// whole single-line invocation.
|
|
236
256
|
["sweepInlineBlockerFreshness(runtime, cwd, {"], { evidenceMin: 2 }),
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
|
|
257
|
+
// The same shared gate call and the same two stores as the live secrets
|
|
258
|
+
// tier โ one lane renders both tiers, so this surface has no gate call and
|
|
259
|
+
// no arm read of its own; see the note above the live tier for what the pin
|
|
260
|
+
// does and does not prove.
|
|
261
|
+
"runtime-turn:stale-secrets-tier": gated(RUNTIME_TURN_FILE, "Turn-end ๐ demoted-secrets tier (drifted since scan).", ["gateFindingsByPathFreshness"], ["gitleaksGate,", "trivySecretsGate,"]),
|
|
240
262
|
// The evidence below is the literal header FRAGMENT including the
|
|
241
263
|
// interpolation โ proves the label is actually rendered, not merely
|
|
242
264
|
// computed and discarded (review round F1's "deleted the age
|
|
@@ -280,8 +302,17 @@ export const DELIVERY_SURFACES = {
|
|
|
280
302
|
// nowhere else in this file: a bare `applyFindingPolicy` would also be
|
|
281
303
|
// satisfied by an import line or an unrelated caller.
|
|
282
304
|
"runtime-turn:late-auxiliary-findings": gated(RUNTIME_TURN_FILE, "Turn-end late-auxiliary LSP findings (collect-later probe of aux " +
|
|
283
|
-
"client caches whose grace window expired).",
|
|
284
|
-
|
|
305
|
+
"client caches whose grace window expired).",
|
|
306
|
+
// #3248: the open-coded `applyFindingPolicy(...)` here and the identical
|
|
307
|
+
// one the late-RUNNER lane needed are now one `applyPushedFindingPolicy`
|
|
308
|
+
// call, so the gate and the evidence name that call. Same stack, same
|
|
309
|
+
// identities โ only the spelling moved.
|
|
310
|
+
["gateFindingsByPathFreshness", "applyPushedFindingPolicy"], ['"late-auxiliary-findings": {', "applyPushedFindingPolicy(gate.live, {"]),
|
|
311
|
+
"runtime-turn:late-runner-findings": gated(RUNTIME_TURN_FILE, "Turn-end CLI runner findings collected after the post-write path.",
|
|
312
|
+
// #3248: this lane was the last push surface with no disposition stage;
|
|
313
|
+
// it now routes through the same shared policy call as its
|
|
314
|
+
// late-auxiliary twin, which is what this gate pins.
|
|
315
|
+
["gateFindingsByPathFreshness", "applyPushedFindingPolicy"], ['"late-runner-findings"'], { evidenceMin: 2 }),
|
|
285
316
|
"runtime-turn:cascade-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end ๐งช cascade neighbor blocker.", "Cascade results settle synchronously this turn where possible " +
|
|
286
317
|
"(`settleCascadeRuns`), but an unsettled compute can carry over to a " +
|
|
287
318
|
"later turn (bounded by a carry cap) โ a carried-over result renders " +
|
|
@@ -359,9 +390,9 @@ export const DELIVERY_SURFACES = {
|
|
|
359
390
|
"lens-diagnostics:mode-delta": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=delta` report (the tool's DEFAULT mode) โ " +
|
|
360
391
|
"re-serves the actionable-warnings/code-quality-warnings caches AND " +
|
|
361
392
|
"the persisted project-diagnostics delta report.", ["gateFindingsByPathFreshness"], [
|
|
362
|
-
'
|
|
393
|
+
'"lens-diagnostics-delta": {',
|
|
363
394
|
"applyDeltaFreshnessGate(",
|
|
364
|
-
'
|
|
395
|
+
'"lens-diagnostics-delta-project": {',
|
|
365
396
|
]),
|
|
366
397
|
"widget-state:footer": gated("clients/widget-state.ts", "TUI footer blocking/error/warning tally.", ["reconcileStaleWidgetFiles", "isBlocking"], ["isBlocking(diagnostic)", "reconcileStaleWidgetFiles()"]),
|
|
367
398
|
"agent-nudge:context-message": labeled("clients/agent-nudge.ts", "Post-edit file-touch nudge injected via `context`.", "Not a scanner finding store: no severity, no cited line, no cache โ the " +
|