@herbertgao/pi-extensions 2026.9.2 → 2026.9.4
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 +4 -2
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +3 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +16 -11
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +20 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +12 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +98 -0
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/sol-pi/LICENSE +19 -0
- package/node_modules/@herbertgao/sol-pi/README.md +159 -0
- package/node_modules/@herbertgao/sol-pi/SECURITY.md +26 -0
- package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +19 -0
- package/node_modules/@herbertgao/sol-pi/agents-install.md +150 -0
- package/node_modules/@herbertgao/sol-pi/assets/sol-pi-hero.png +0 -0
- package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +69 -0
- package/node_modules/@herbertgao/sol-pi/docs/configuration.md +75 -0
- package/node_modules/@herbertgao/sol-pi/package.json +76 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-pi-compat.mjs +32 -0
- package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +120 -0
- package/node_modules/@herbertgao/sol-pi/sol-pi.example.json +10 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +135 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +74 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +185 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +128 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/archive.ts +53 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/candidate.ts +101 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/config.ts +71 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +220 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +25 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +164 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/receipt.ts +177 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/index.ts +227 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/ledger.ts +20 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +252 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +237 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +455 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +49 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +79 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +208 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +100 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/index.ts +42 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +17 -0
- package/node_modules/@herbertgao/sol-pi/src/sol-pi/tui.ts +71 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +12 -2
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +2 -2
- package/node_modules/@narumitw/pi-btw/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +13 -2
- package/node_modules/pi-antigravity/LICENSE +21 -0
- package/node_modules/pi-antigravity/README.md +194 -0
- package/node_modules/pi-antigravity/package.json +67 -0
- package/node_modules/pi-antigravity/src/auth/index.ts +14 -0
- package/node_modules/pi-antigravity/src/auth/oauth.ts +442 -0
- package/node_modules/pi-antigravity/src/client/client.ts +561 -0
- package/node_modules/pi-antigravity/src/client/index.ts +1 -0
- package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
- package/node_modules/pi-antigravity/src/diagnostics/index.ts +1 -0
- package/node_modules/pi-antigravity/src/image/image.ts +336 -0
- package/node_modules/pi-antigravity/src/image/index.ts +1 -0
- package/node_modules/pi-antigravity/src/index.ts +280 -0
- package/node_modules/pi-antigravity/src/models/discovery.ts +154 -0
- package/node_modules/pi-antigravity/src/models/grouping.ts +424 -0
- package/node_modules/pi-antigravity/src/models/index.ts +3 -0
- package/node_modules/pi-antigravity/src/models/models.ts +500 -0
- package/node_modules/pi-antigravity/src/stream/index.ts +1 -0
- package/node_modules/pi-antigravity/src/stream/stream.ts +1460 -0
- package/node_modules/pi-antigravity/src/types/enums.ts +42 -0
- package/node_modules/pi-antigravity/src/types/index.ts +2 -0
- package/node_modules/pi-antigravity/src/types/types.ts +292 -0
- package/node_modules/pi-antigravity/src/usage/index.ts +1 -0
- package/node_modules/pi-antigravity/src/usage/usage.ts +371 -0
- package/node_modules/pi-antigravity/src/utils/http.ts +91 -0
- package/node_modules/pi-antigravity/src/utils/index.ts +3 -0
- package/node_modules/pi-antigravity/src/utils/security.ts +73 -0
- package/node_modules/pi-antigravity/src/utils/util.ts +132 -0
- package/node_modules/pi-antigravity/tsconfig.json +21 -0
- package/node_modules/pi-lens/CHANGELOG.md +176 -0
- package/node_modules/pi-lens/README.md +13 -8
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -1
- package/node_modules/pi-lens/dist/clients/analysed-root.js +1 -0
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +13 -2
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +2 -0
- package/node_modules/pi-lens/dist/clients/cache-observability.js +122 -1
- package/node_modules/pi-lens/dist/clients/complexity-client.js +5 -0
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +2 -0
- package/node_modules/pi-lens/dist/clients/config-resolve.js +6 -3
- package/node_modules/pi-lens/dist/clients/config-schema.js +17 -0
- package/node_modules/pi-lens/dist/clients/config-warn.js +2 -2
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +8 -1
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +38 -15
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +19 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +12 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +12 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +4 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +2 -1
- package/node_modules/pi-lens/dist/clients/effective-config.js +12 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +2 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +4 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +54 -188
- package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +42 -6
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +48 -7
- package/node_modules/pi-lens/dist/clients/installer/index.js +196 -52
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +9 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +12 -2
- package/node_modules/pi-lens/dist/clients/latency-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/lens-config.js +4 -0
- package/node_modules/pi-lens/dist/clients/lsp/config.js +36 -7
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +24 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +78 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +281 -45
- package/node_modules/pi-lens/dist/clients/lsp/server.js +62 -15
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +37 -4
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +3 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +2 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +2 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +8 -3
- package/node_modules/pi-lens/dist/clients/pipeline.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +38 -10
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +2 -0
- package/node_modules/pi-lens/dist/clients/ruff-client.js +18 -9
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +9 -0
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +5 -0
- package/node_modules/pi-lens/dist/clients/runtime-session.js +13 -4
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +4 -1
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +48 -1
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -2
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +69 -1
- package/node_modules/pi-lens/dist/clients/sg-runner.js +2 -1
- package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +108 -0
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +291 -76
- package/node_modules/pi-lens/dist/clients/tool-config.js +199 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +299 -0
- package/node_modules/pi-lens/dist/clients/tool-probe.js +53 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +42 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +9 -1
- package/node_modules/pi-lens/dist/clients/turn-context.js +52 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +4 -3
- package/node_modules/pi-lens/dist/index.js +21969 -20005
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -2
- package/node_modules/pi-lens/dist/mcp/server.js +135 -159
- package/node_modules/pi-lens/dist/tools/activate-tools.js +10 -7
- package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +2 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +8 -13
- package/node_modules/pi-lens/dist/tools/ast-grep-search.js +83 -39
- package/node_modules/pi-lens/dist/tools/effective-config.js +4 -3
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +1 -10
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +353 -85
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +21 -110
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +20 -44
- package/node_modules/pi-lens/dist/tools/module-report.js +5 -9
- package/node_modules/pi-lens/dist/tools/project-report.js +9 -17
- package/node_modules/pi-lens/dist/tools/render-compact.js +280 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +2 -2
- package/node_modules/pi-lens/docs/agent-guide.md +3 -4
- package/node_modules/pi-lens/docs/agent-tools.md +46 -22
- package/node_modules/pi-lens/docs/configuration.md +9 -0
- package/node_modules/pi-lens/docs/environment-variables.md +0 -5
- package/node_modules/pi-lens/docs/features.md +5 -5
- package/node_modules/pi-lens/docs/globalconfig.md +11 -1
- package/node_modules/pi-lens/docs/mcp.md +13 -1
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +71 -0
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +15 -0
- package/node_modules/pi-lens/docs/pi-lens-monitor.md +88 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +35 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +12 -4
- package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
- package/node_modules/pi-lens/docs/real-harness.md +46 -0
- package/node_modules/pi-lens/docs/release-qa-baseline.md +5 -1
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -6
- package/node_modules/pi-lens/docs/settings.md +37 -2
- package/node_modules/pi-lens/docs/tools_improvement2.md +4 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +13 -3
- package/node_modules/pi-lens/package.json +10 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +7 -3
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +8 -6
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +19 -9
- package/node_modules/pi-web-access/CHANGELOG.md +29 -0
- package/node_modules/pi-web-access/README.md +33 -22
- package/node_modules/pi-web-access/abortable.ts +17 -0
- package/node_modules/pi-web-access/crawl4ai.ts +204 -0
- package/node_modules/pi-web-access/credential-source.ts +1 -0
- package/node_modules/pi-web-access/curator-page.ts +20 -2
- package/node_modules/pi-web-access/curator-run.ts +44 -0
- package/node_modules/pi-web-access/curator-server.ts +3 -1
- package/node_modules/pi-web-access/duckduckgo.ts +1 -1
- package/node_modules/pi-web-access/extract.ts +57 -12
- package/node_modules/pi-web-access/fetch-params.ts +1 -1
- package/node_modules/pi-web-access/gemini-search.ts +9 -5
- package/node_modules/pi-web-access/index.ts +25 -18
- package/node_modules/pi-web-access/openai-search.ts +35 -13
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +5 -2
- package/node_modules/pi-web-access/query-rewrite.ts +5 -2
- package/node_modules/pi-web-access/serpapi.ts +220 -0
- package/node_modules/pi-web-access/ssrf-protection.ts +5 -1
- package/node_modules/pi-web-access/storage.ts +10 -0
- package/node_modules/pi-web-access/summary-review.ts +34 -21
- package/node_modules/pi-web-access/utils.ts +6 -4
- package/package.json +11 -5
- package/node_modules/pi-lens/dist/tools/ast-dump.js +0 -103
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
2
|
+
import { logRunnerAdvisoryOnce, resolveRunnerCwd } from "../../tool-cwd.js";
|
|
2
3
|
import { getLinterPolicyForCwd, hasSqlfluffConfig } from "../../tool-policy.js";
|
|
3
4
|
import { PRIORITY } from "../priorities.js";
|
|
4
5
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
@@ -117,14 +118,14 @@ const sqlfluffRunner = {
|
|
|
117
118
|
priority: PRIORITY.SQL_LINT,
|
|
118
119
|
skipTestFiles: false,
|
|
119
120
|
async run(ctx) {
|
|
120
|
-
const cwd = ctx
|
|
121
|
+
const cwd = resolveRunnerCwd(ctx, "sqlfluff");
|
|
121
122
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
122
123
|
if (policy && !policy.preferredRunners.includes("sqlfluff")) {
|
|
123
124
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
124
125
|
}
|
|
125
126
|
const hasConfig = hasSqlfluffConfig(cwd);
|
|
126
127
|
if (!hasConfig) {
|
|
127
|
-
ctx
|
|
128
|
+
logRunnerAdvisoryOnce(ctx, "sqlfluff", cwd, "sqlfluff: no config detected, using ANSI dialect defaults");
|
|
128
129
|
}
|
|
129
130
|
let cmd = null;
|
|
130
131
|
if (await sqlfluff.isAvailableAsync(cwd)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { logRunnerAdvisoryOnce, resolveRunnerCwd } from "../../tool-cwd.js";
|
|
3
4
|
import { getLinterPolicyForCwd, hasStylelintConfig, } from "../../tool-policy.js";
|
|
4
5
|
import { PRIORITY } from "../priorities.js";
|
|
5
6
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
@@ -116,7 +117,7 @@ const stylelintRunner = {
|
|
|
116
117
|
priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
|
|
117
118
|
skipTestFiles: false,
|
|
118
119
|
async run(ctx) {
|
|
119
|
-
const cwd = ctx
|
|
120
|
+
const cwd = resolveRunnerCwd(ctx, "stylelint");
|
|
120
121
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
121
122
|
if (policy && !policy.preferredRunners.includes("stylelint")) {
|
|
122
123
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -124,7 +125,7 @@ const stylelintRunner = {
|
|
|
124
125
|
const fileDir = path.dirname(path.resolve(cwd, ctx.filePath));
|
|
125
126
|
const hasConfig = hasStylelintConfig(fileDir) || hasStylelintConfig(cwd);
|
|
126
127
|
if (!hasConfig) {
|
|
127
|
-
ctx
|
|
128
|
+
logRunnerAdvisoryOnce(ctx, "stylelint", cwd, "stylelint: no config detected, running with default rules");
|
|
128
129
|
}
|
|
129
130
|
let cmd = null;
|
|
130
131
|
if (await stylelint.isAvailableAsync(cwd)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
3
4
|
import { PRIORITY } from "../priorities.js";
|
|
4
5
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
5
6
|
import { parseToolRun } from "./utils/tool-failure.js";
|
|
@@ -115,7 +116,7 @@ const swiftlintRunner = {
|
|
|
115
116
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
116
117
|
skipTestFiles: false,
|
|
117
118
|
async run(ctx) {
|
|
118
|
-
const cwd = ctx
|
|
119
|
+
const cwd = resolveRunnerCwd(ctx, "swiftlint");
|
|
119
120
|
let cmd = null;
|
|
120
121
|
if (await swiftlint.isAvailableAsync(cwd)) {
|
|
121
122
|
cmd = swiftlint.getCommand(cwd);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { findLocalBinUpwards } from "../../package-manager.js";
|
|
3
3
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
4
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
4
5
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
6
7
|
import { createAvailabilityChecker, lspPrimaryCoversFile, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
@@ -106,7 +107,7 @@ const taploRunner = {
|
|
|
106
107
|
priority: PRIORITY.FORMAT_AND_LINT_PRIMARY,
|
|
107
108
|
skipTestFiles: false,
|
|
108
109
|
async run(ctx) {
|
|
109
|
-
const cwd = ctx
|
|
110
|
+
const cwd = resolveRunnerCwd(ctx, "taplo");
|
|
110
111
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
111
112
|
if (policy && !policy.preferredRunners.includes("taplo")) {
|
|
112
113
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
3
4
|
import { pathsEqual } from "../../path-utils.js";
|
|
4
5
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
@@ -128,7 +129,7 @@ const terragruntRunner = {
|
|
|
128
129
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
129
130
|
skipTestFiles: false,
|
|
130
131
|
async run(ctx) {
|
|
131
|
-
const cwd = ctx
|
|
132
|
+
const cwd = resolveRunnerCwd(ctx, "terragrunt");
|
|
132
133
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
133
134
|
if (policy && !policy.preferredRunners.includes("terragrunt"))
|
|
134
135
|
return SKIPPED;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
3
4
|
import { getLinterPolicyForCwd } from "../../tool-policy.js";
|
|
4
5
|
import { findNearestDirWithAnyBasename } from "../../workspace-topology.js";
|
|
5
6
|
import { PRIORITY } from "../priorities.js";
|
|
@@ -52,7 +53,7 @@ const tflintRunner = {
|
|
|
52
53
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
53
54
|
skipTestFiles: false,
|
|
54
55
|
async run(ctx) {
|
|
55
|
-
const cwd = ctx
|
|
56
|
+
const cwd = resolveRunnerCwd(ctx, "tflint");
|
|
56
57
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
57
58
|
if (policy && !policy.preferredRunners.includes("tflint")) {
|
|
58
59
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -40,6 +40,7 @@ import * as fs from "node:fs";
|
|
|
40
40
|
import * as path from "node:path";
|
|
41
41
|
import { incrementDegradationCount } from "../../degradation-ledger.js";
|
|
42
42
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
43
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
43
44
|
import { isTrivyEnabled, resolveSeverityFloor, } from "../../trivy-client.js";
|
|
44
45
|
import { PRIORITY } from "../priorities.js";
|
|
45
46
|
import { createAvailabilityChecker, resolveAvailableOrInstall, } from "./utils/runner-helpers.js";
|
|
@@ -148,7 +149,7 @@ const trivyConfigRunner = {
|
|
|
148
149
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
149
150
|
skipTestFiles: false,
|
|
150
151
|
async run(ctx) {
|
|
151
|
-
const cwd = ctx
|
|
152
|
+
const cwd = resolveRunnerCwd(ctx, "trivy-config");
|
|
152
153
|
// Single opt-in switch — trivy is opt-in across all modes.
|
|
153
154
|
if (!isTrivyEnabled(cwd)) {
|
|
154
155
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -75,6 +75,11 @@ export function describeInstallAttempt(attempt, options = {}) {
|
|
|
75
75
|
return { install: "succeeded", ...(reason && { installReason: reason }) };
|
|
76
76
|
case "failed":
|
|
77
77
|
return { install: "failed", ...(reason && { installReason: reason }) };
|
|
78
|
+
case "unavailable":
|
|
79
|
+
return {
|
|
80
|
+
install: "unavailable",
|
|
81
|
+
...(reason && { installReason: reason }),
|
|
82
|
+
};
|
|
78
83
|
default:
|
|
79
84
|
return {
|
|
80
85
|
install: "not-attempted",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Complexity limit. This is that sweep, written once.
|
|
12
12
|
*/
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
|
-
import {
|
|
14
|
+
import { probeToolAsync } from "../../../tool-probe.js";
|
|
15
15
|
import { classifyProbeFailure, startHostStallSampler, } from "./availability-policy.js";
|
|
16
16
|
/**
|
|
17
17
|
* Walk `candidates` in order. A candidate containing a path separator is
|
|
@@ -45,7 +45,7 @@ export async function probeAvailabilityCandidates(candidates, probeArgs, timeout
|
|
|
45
45
|
let result;
|
|
46
46
|
let stallMs;
|
|
47
47
|
try {
|
|
48
|
-
result = await
|
|
48
|
+
result = await probeToolAsync(candidate, probeArgs, {
|
|
49
49
|
timeout: timeoutMs,
|
|
50
50
|
});
|
|
51
51
|
}
|
|
@@ -20,9 +20,11 @@ import { getServersForFileWithConfig, isServerDisabled, } from "../../../lsp/con
|
|
|
20
20
|
import { findGlobalBinary, findLocalBinAt, findLocalBinsUpwards, findLocalBinUpwards, VENDOR_BIN_DIRS, VENV_BIN_DIRS, } from "../../../package-manager.js";
|
|
21
21
|
import { logLatency } from "../../../latency-logger.js";
|
|
22
22
|
import { safeSpawnAsync } from "../../../safe-spawn.js";
|
|
23
|
+
import { probeToolAsync } from "../../../tool-probe.js";
|
|
23
24
|
import { compareOrdinal } from "../../../string-utils.js";
|
|
24
25
|
import { getToolCommandSpec, shouldAutoInstallTool, } from "../../../tool-policy.js";
|
|
25
26
|
import { isInSpawnTimeoutCooldown } from "../../../spawn-timeout-cooldown.js";
|
|
27
|
+
import { resolveToolCwd } from "../../../tool-cwd.js";
|
|
26
28
|
import { createAvailabilityProbeFlight } from "../../../availability-probe-flight.js";
|
|
27
29
|
import { classifyProbeFailure, createAvailabilityLatch, describeInstallAttempt, describeProbeEvidence, isLatchingOutcome, logAvailabilityDecision, startHostStallSampler, transientRetryDelayMs, } from "./availability-policy.js";
|
|
28
30
|
export { createAvailabilityLatch, classifyProbeFailure, describeProbeEvidence, describeUnavailability, isTransientDecision, logAvailabilityDecision, startHostStallSampler, } from "./availability-policy.js";
|
|
@@ -1390,7 +1392,7 @@ async function probeAstGrepCommandAsync(cmd, argsPrefix = []) {
|
|
|
1390
1392
|
let check;
|
|
1391
1393
|
let hostStallMs;
|
|
1392
1394
|
try {
|
|
1393
|
-
check = await
|
|
1395
|
+
check = await probeToolAsync(cmd, [...argsPrefix, "--version"], {
|
|
1394
1396
|
timeout: 5000,
|
|
1395
1397
|
});
|
|
1396
1398
|
}
|
|
@@ -1674,7 +1676,7 @@ export async function resolveLocalFirstAsync(toolName, cwd, windowsExt = ".cmd")
|
|
|
1674
1676
|
if (globalBin)
|
|
1675
1677
|
return { cmd: globalBin, args: [] };
|
|
1676
1678
|
// 3. Global PATH (already installed system-wide, on PATH)
|
|
1677
|
-
const globalCheck = await
|
|
1679
|
+
const globalCheck = await probeToolAsync(toolName, ["--version"], {
|
|
1678
1680
|
timeout: 3000,
|
|
1679
1681
|
});
|
|
1680
1682
|
if (!globalCheck.error && globalCheck.status === 0) {
|
|
@@ -1693,3 +1695,7 @@ export const sg = {
|
|
|
1693
1695
|
isAvailableAsync: isSgAvailableAsync,
|
|
1694
1696
|
getCommand: getSgCommand,
|
|
1695
1697
|
};
|
|
1698
|
+
/** Shared cwd seam for runner probes and analysis children (#2777). */
|
|
1699
|
+
export function resolveRunnerCwd(ctx, tool) {
|
|
1700
|
+
return resolveToolCwd("runner", tool, ctx.filePath, ctx);
|
|
1701
|
+
}
|
|
@@ -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 { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
4
5
|
import { PRIORITY } from "../priorities.js";
|
|
5
6
|
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
6
7
|
import { parseToolRun } from "./utils/tool-failure.js";
|
|
@@ -72,7 +73,7 @@ const valeRunner = {
|
|
|
72
73
|
priority: PRIORITY.DOC_QUALITY,
|
|
73
74
|
skipTestFiles: false,
|
|
74
75
|
async run(ctx) {
|
|
75
|
-
const cwd = ctx
|
|
76
|
+
const cwd = resolveRunnerCwd(ctx, "vale");
|
|
76
77
|
// Config-gated: skip unless a .vale.ini is found
|
|
77
78
|
if (!findValeConfig(cwd)) {
|
|
78
79
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
2
|
+
import { logRunnerAdvisoryOnce } from "../../tool-cwd.js";
|
|
2
3
|
import { getLinterPolicyForCwd, hasYamllintConfig } from "../../tool-policy.js";
|
|
3
4
|
import { PRIORITY } from "../priorities.js";
|
|
4
|
-
import { createAvailabilityChecker, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
5
|
+
import { createAvailabilityChecker, resolveRunnerCwd, resolveToolCommandWithInstallFallback, } from "./utils/runner-helpers.js";
|
|
5
6
|
import { parseToolRun } from "./utils/tool-failure.js";
|
|
6
7
|
import { finishParsedRun } from "./utils/tool-failure.js";
|
|
7
8
|
const yamllint = createAvailabilityChecker("yamllint", ".exe");
|
|
@@ -35,14 +36,14 @@ const yamllintRunner = {
|
|
|
35
36
|
priority: PRIORITY.YAML_LINT,
|
|
36
37
|
skipTestFiles: false,
|
|
37
38
|
async run(ctx) {
|
|
38
|
-
const cwd = ctx
|
|
39
|
+
const cwd = resolveRunnerCwd(ctx, "yamllint");
|
|
39
40
|
const policy = getLinterPolicyForCwd(ctx.filePath, cwd);
|
|
40
41
|
if (policy && !policy.preferredRunners.includes("yamllint")) {
|
|
41
42
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
42
43
|
}
|
|
43
44
|
const hasConfig = hasYamllintConfig(cwd);
|
|
44
45
|
if (!hasConfig) {
|
|
45
|
-
ctx
|
|
46
|
+
logRunnerAdvisoryOnce(ctx, "yamllint", cwd, "yamllint: no config detected, running with default rules");
|
|
46
47
|
}
|
|
47
48
|
let cmd = null;
|
|
48
49
|
if (await yamllint.isAvailableAsync(cwd)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { safeSpawnAsync } from "../../safe-spawn.js";
|
|
3
|
+
import { resolveRunnerCwd } from "../../tool-cwd.js";
|
|
3
4
|
import { createAvailabilityChecker } from "./utils/runner-helpers.js";
|
|
4
5
|
import { PRIORITY } from "../priorities.js";
|
|
5
6
|
// zig rejects `--version`; the version subcommand is `zig version`. Using the
|
|
@@ -46,7 +47,7 @@ const zigCheckRunner = {
|
|
|
46
47
|
priority: PRIORITY.GENERAL_ANALYSIS,
|
|
47
48
|
skipTestFiles: false,
|
|
48
49
|
async run(ctx) {
|
|
49
|
-
const cwd = ctx
|
|
50
|
+
const cwd = resolveRunnerCwd(ctx, "zig-check");
|
|
50
51
|
if (!(await zig.isAvailableAsync(cwd))) {
|
|
51
52
|
return { status: "skipped", diagnostics: [], semantic: "none" };
|
|
52
53
|
}
|
|
@@ -47,7 +47,9 @@ import { explainServersForFile, lspConfigOf, registerLSPConfig, } from "./lsp/co
|
|
|
47
47
|
// apart on a Windows-shaped path (AGENTS.md defect shape 2).
|
|
48
48
|
import { isSameOrWithin } from "./lsp/server.js";
|
|
49
49
|
import { homeRelativePath } from "./path-utils.js";
|
|
50
|
+
import { resolveToolCwd } from "./tool-cwd.js";
|
|
50
51
|
import { compareOrdinal } from "./string-utils.js";
|
|
52
|
+
import { LENS_TOOL_NAMES, resolveLensToolEnabled } from "./tool-config.js";
|
|
51
53
|
/** True when a `file` half is the rejection shape, not a resolved view. */
|
|
52
54
|
export function isEffectiveFileViewError(file) {
|
|
53
55
|
return "error" in file;
|
|
@@ -289,6 +291,10 @@ export async function effectiveConfig(options = {}) {
|
|
|
289
291
|
provenance: provenanceView(resolved, homeDir).entries,
|
|
290
292
|
provenanceCounts: summary.countsByTier,
|
|
291
293
|
recordCounts: countBy(resolution.records, (record) => record.code),
|
|
294
|
+
tools: LENS_TOOL_NAMES.map((name) => ({
|
|
295
|
+
name,
|
|
296
|
+
enabled: resolveLensToolEnabled(name, resolved.value, undefined, options.noTools),
|
|
297
|
+
})),
|
|
292
298
|
...(fileOutsideCwd
|
|
293
299
|
? {
|
|
294
300
|
file: {
|
|
@@ -299,7 +305,7 @@ export async function effectiveConfig(options = {}) {
|
|
|
299
305
|
: absolute === undefined
|
|
300
306
|
? {}
|
|
301
307
|
: {
|
|
302
|
-
file: await fileView(absolute, resolved, homeDir,
|
|
308
|
+
file: await fileView(absolute, resolved, homeDir, cwd,
|
|
303
309
|
// The gates read the LSP slice of that SAME resolution, through
|
|
304
310
|
// the same `registerLSPConfig` conversion `initLSPConfig` uses —
|
|
305
311
|
// no session-root registration, no per-root config-store write
|
|
@@ -325,7 +331,7 @@ function toolReason(selected, kind) {
|
|
|
325
331
|
return "selected";
|
|
326
332
|
return kind === undefined ? "no-dispatch-plan" : "not-registered-for-kind";
|
|
327
333
|
}
|
|
328
|
-
async function fileView(absolute, resolved, homeDir, lspConfig) {
|
|
334
|
+
async function fileView(absolute, resolved, homeDir, workspaceCwd, lspConfig) {
|
|
329
335
|
const language = resolveLanguage(absolute);
|
|
330
336
|
const kind = detectFileKind(absolute);
|
|
331
337
|
const section = lspSectionOf(resolved.value);
|
|
@@ -392,6 +398,10 @@ async function fileView(absolute, resolved, homeDir, lspConfig) {
|
|
|
392
398
|
id,
|
|
393
399
|
selected: available.has(id),
|
|
394
400
|
reason: toolReason(available.has(id), kind),
|
|
401
|
+
resolvedCwd: homeRelativePath(resolveToolCwd("runner", id, absolute, {
|
|
402
|
+
cwd: workspaceCwd,
|
|
403
|
+
suppressTelemetry: true,
|
|
404
|
+
}), homeDir),
|
|
395
405
|
}));
|
|
396
406
|
return {
|
|
397
407
|
path: homeRelativePath(absolute, homeDir),
|
|
@@ -26,6 +26,7 @@ import { isTestMode } from "./env-utils.js";
|
|
|
26
26
|
import { getGlobalPiLensLogDir } from "./probe-home-state.js";
|
|
27
27
|
import { getMaxLogSizeMB } from "./log-cleanup.js";
|
|
28
28
|
import { createNdjsonLogger } from "./ndjson-logger.js";
|
|
29
|
+
import { getTurnId } from "./turn-context.js";
|
|
29
30
|
export const EXTENSION_LOG_FILE = path.join(getGlobalPiLensLogDir(), "extension.log");
|
|
30
31
|
const writer = createNdjsonLogger({
|
|
31
32
|
filePath: EXTENSION_LOG_FILE,
|
|
@@ -37,6 +38,7 @@ export function logExtension(entry) {
|
|
|
37
38
|
writer.log({
|
|
38
39
|
ts: new Date().toISOString(),
|
|
39
40
|
pid: process.pid,
|
|
41
|
+
turnId: getTurnId(),
|
|
40
42
|
level: entry.level ?? "error",
|
|
41
43
|
subsystem: entry.subsystem,
|
|
42
44
|
message: entry.message,
|
|
@@ -51,15 +51,32 @@ function isTypeStub(content) {
|
|
|
51
51
|
*/
|
|
52
52
|
export function detectFileRole(filePath, content) {
|
|
53
53
|
const windowsShaped = isWindowsPath(filePath);
|
|
54
|
-
const
|
|
54
|
+
const rawBase = windowsShaped ? win32.basename(filePath) : basename(filePath);
|
|
55
|
+
const base = rawBase.toLowerCase();
|
|
55
56
|
const dir = (windowsShaped ? win32.dirname(filePath) : dirname(filePath))
|
|
56
57
|
.replace(/\\/g, "/")
|
|
57
58
|
.toLowerCase();
|
|
58
59
|
// --- Test ---
|
|
60
|
+
// Suffix conventions informed by the test-runner table
|
|
61
|
+
// (SOURCE_TO_TEST_PATTERNS + RUNNERS kinds in
|
|
62
|
+
// clients/test-runner-client.ts); hand-written, not iterated from it —
|
|
63
|
+
// see #2928 for the single-classifier fold:
|
|
64
|
+
// - `_test.` infix: Go (`*_test.go`), pytest (`*_test.py`), ExUnit
|
|
65
|
+
// (`*_test.exs`), Dart (`*_test.dart`). The underscore anchor keeps
|
|
66
|
+
// this precise: `contest.py` and `latest.ts` do not match.
|
|
67
|
+
// - `_spec.` infix: RSpec (`*_spec.rb`).
|
|
68
|
+
// - CamelCase `*Test(s).<ext>` suffix, matched case-SENSITIVELY on the
|
|
69
|
+
// raw basename: JUnit/Surefire (`*Test.java`, `*TestCase.java`),
|
|
70
|
+
// Kotlin (`*Test.kt`), dotnet (`*Test.cs`/`*Tests.cs`), PHPUnit
|
|
71
|
+
// (`*Test.php`). Case matters: Surefire's `*Test.java` does not match
|
|
72
|
+
// `contest.java`, so neither do we.
|
|
59
73
|
if (base.includes(".test.") ||
|
|
60
74
|
base.includes(".spec.") ||
|
|
75
|
+
base.includes("_test.") ||
|
|
76
|
+
base.includes("_spec.") ||
|
|
61
77
|
base.startsWith("test_") ||
|
|
62
78
|
base.startsWith("spec_") ||
|
|
79
|
+
/(Test|Tests|TestCase)\.(java|kt|kts|cs|fs|php)$/.test(rawBase) ||
|
|
63
80
|
dir.includes("/__tests__/") ||
|
|
64
81
|
dir.includes("/test/") ||
|
|
65
82
|
dir.includes("/tests/") ||
|
|
@@ -139,6 +139,10 @@
|
|
|
139
139
|
* agent-facing surface is EITHER gated OR explicitly labeled — never neither.
|
|
140
140
|
*/
|
|
141
141
|
const MS_PER_MINUTE = 60_000;
|
|
142
|
+
/** Mark retained findings whose replacement result could not be reconciled. */
|
|
143
|
+
export function markUnreconciledFindings(findings) {
|
|
144
|
+
return findings.map((finding) => ({ ...finding, stale: true }));
|
|
145
|
+
}
|
|
142
146
|
/**
|
|
143
147
|
* Render a short, honest age suffix for a store that cannot be freshness-
|
|
144
148
|
* gated per-path (see module doc). `undefined`/unparseable `scannedAt`
|