@duckmind/dm-linux-x64 0.66.0 → 0.66.2
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/dm +2 -2
- package/extensions/.dm-extensions.json +12 -546
- package/extensions/dm-lens/clients/dispatch/runners/utils/runner-helpers.js +1 -1
- package/extensions/dm-mcp-adapter/mcp-keyring-helper.cjs +1 -1
- package/extensions/dm-ponytail/hooks/ponytail-activate.js +1 -1
- package/extensions/dm-ponytail/hooks/ponytail-instructions.js +1 -1
- package/extensions/dm-subagents/src/runs/background/runner-aliases.js +2 -2
- package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +4 -1
- package/extensions/dm-subagents/src/runs/shared/child-session.js +8 -6
- package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +9 -1
- package/extensions/dm-subagents/src/watchdog/review.js +4 -1
- package/package.json +1 -1
- package/extensions/dm-lens/dist/clients/actionable-warnings-logger.js +0 -24
- package/extensions/dm-lens/dist/clients/actionable-warnings.js +0 -1014
- package/extensions/dm-lens/dist/clients/advisory-provenance.js +0 -385
- package/extensions/dm-lens/dist/clients/agent-behavior-client.js +0 -94
- package/extensions/dm-lens/dist/clients/agent-nudge.js +0 -151
- package/extensions/dm-lens/dist/clients/analysed-root.js +0 -1
- package/extensions/dm-lens/dist/clients/ast-grep-client.js +0 -576
- package/extensions/dm-lens/dist/clients/ast-grep-rule-manager.js +0 -114
- package/extensions/dm-lens/dist/clients/ast-grep-tool-logger.js +0 -85
- package/extensions/dm-lens/dist/clients/ast-grep-types.js +0 -1
- package/extensions/dm-lens/dist/clients/ast-grep-yaml-synth.js +0 -109
- package/extensions/dm-lens/dist/clients/atomic-write-staging.js +0 -66
- package/extensions/dm-lens/dist/clients/atomic-write.js +0 -37
- package/extensions/dm-lens/dist/clients/availability-probe-flight.js +0 -11
- package/extensions/dm-lens/dist/clients/bash-file-access.js +0 -830
- package/extensions/dm-lens/dist/clients/biome-client.js +0 -221
- package/extensions/dm-lens/dist/clients/blocker-freshness.js +0 -385
- package/extensions/dm-lens/dist/clients/blocker-past-eof.js +0 -49
- package/extensions/dm-lens/dist/clients/bootstrap.js +0 -246
- package/extensions/dm-lens/dist/clients/bounded-cache.js +0 -105
- package/extensions/dm-lens/dist/clients/bounded-pid-file-lock.js +0 -173
- package/extensions/dm-lens/dist/clients/bounded-telemetry.js +0 -104
- package/extensions/dm-lens/dist/clients/build-identity.js +0 -45
- package/extensions/dm-lens/dist/clients/bundled-resource-health.js +0 -41
- package/extensions/dm-lens/dist/clients/bus-events-logger.js +0 -48
- package/extensions/dm-lens/dist/clients/bus-publish.js +0 -117
- package/extensions/dm-lens/dist/clients/cache/rule-cache.js +0 -103
- package/extensions/dm-lens/dist/clients/cache-manager.js +0 -340
- package/extensions/dm-lens/dist/clients/cache-observability.js +0 -847
- package/extensions/dm-lens/dist/clients/call-graph.js +0 -628
- package/extensions/dm-lens/dist/clients/cargo-manifest.js +0 -151
- package/extensions/dm-lens/dist/clients/cascade-budget.js +0 -52
- package/extensions/dm-lens/dist/clients/cascade-format.js +0 -160
- package/extensions/dm-lens/dist/clients/cascade-logger.js +0 -22
- package/extensions/dm-lens/dist/clients/cascade-types.js +0 -1
- package/extensions/dm-lens/dist/clients/child-unref.js +0 -59
- package/extensions/dm-lens/dist/clients/code-quality-warnings.js +0 -192
- package/extensions/dm-lens/dist/clients/codebase-model.js +0 -110
- package/extensions/dm-lens/dist/clients/collateral-test-role.js +0 -8
- package/extensions/dm-lens/dist/clients/complexity-client.js +0 -398
- package/extensions/dm-lens/dist/clients/config-core/deny.js +0 -117
- package/extensions/dm-lens/dist/clients/config-core/index.js +0 -2
- package/extensions/dm-lens/dist/clients/config-core/merge.js +0 -228
- package/extensions/dm-lens/dist/clients/config-core/normalize.js +0 -217
- package/extensions/dm-lens/dist/clients/config-core/process-spec.js +0 -147
- package/extensions/dm-lens/dist/clients/config-core/provenance.js +0 -54
- package/extensions/dm-lens/dist/clients/config-core/records.js +0 -79
- package/extensions/dm-lens/dist/clients/config-core/resolve.js +0 -48
- package/extensions/dm-lens/dist/clients/config-core/safe-object.js +0 -22
- package/extensions/dm-lens/dist/clients/config-core/schema.js +0 -90
- package/extensions/dm-lens/dist/clients/config-diagnostic-codes.js +0 -90
- package/extensions/dm-lens/dist/clients/config-locations.js +0 -175
- package/extensions/dm-lens/dist/clients/config-resolve.js +0 -359
- package/extensions/dm-lens/dist/clients/config-schema.js +0 -128
- package/extensions/dm-lens/dist/clients/config-warn.js +0 -146
- package/extensions/dm-lens/dist/clients/console-guard-install.js +0 -4
- package/extensions/dm-lens/dist/clients/cooperative-budget.js +0 -36
- package/extensions/dm-lens/dist/clients/dead-code-client.js +0 -342
- package/extensions/dm-lens/dist/clients/dead-code-logger.js +0 -18
- package/extensions/dm-lens/dist/clients/deadline-utils.js +0 -117
- package/extensions/dm-lens/dist/clients/debug-handles.js +0 -121
- package/extensions/dm-lens/dist/clients/debug-heap.js +0 -80
- package/extensions/dm-lens/dist/clients/deferred-lsp-work.js +0 -33
- package/extensions/dm-lens/dist/clients/degradation-ledger.js +0 -272
- package/extensions/dm-lens/dist/clients/demoted-finding-render.js +0 -61
- package/extensions/dm-lens/dist/clients/dependency-checker.js +0 -525
- package/extensions/dm-lens/dist/clients/deps/ast-grep-napi.js +0 -17
- package/extensions/dm-lens/dist/clients/deps/dm-host-deps.js +0 -10
- package/extensions/dm-lens/dist/clients/deps/dm-tui-compat.js +0 -58
- package/extensions/dm-lens/dist/clients/deps/js-yaml.js +0 -7
- package/extensions/dm-lens/dist/clients/deps/minimatch.js +0 -6
- package/extensions/dm-lens/dist/clients/deps/pidusage.js +0 -5
- package/extensions/dm-lens/dist/clients/deps/typebox.js +0 -5
- package/extensions/dm-lens/dist/clients/deps/vscode-jsonrpc.js +0 -8
- package/extensions/dm-lens/dist/clients/deps/web-tree-sitter.js +0 -11
- package/extensions/dm-lens/dist/clients/diagnostic-dispositions.js +0 -318
- package/extensions/dm-lens/dist/clients/diagnostic-line-freshness.js +0 -144
- package/extensions/dm-lens/dist/clients/diagnostic-logger.js +0 -60
- package/extensions/dm-lens/dist/clients/diagnostic-tracker.js +0 -89
- package/extensions/dm-lens/dist/clients/diagnostics-publish.js +0 -134
- package/extensions/dm-lens/dist/clients/dispatch/ast-grep-catalog.js +0 -16
- package/extensions/dm-lens/dist/clients/dispatch/auxiliary-lsp.js +0 -158
- package/extensions/dm-lens/dist/clients/dispatch/collect-later-tier.js +0 -25
- package/extensions/dm-lens/dist/clients/dispatch/diagnostic-taxonomy.js +0 -58
- package/extensions/dm-lens/dist/clients/dispatch/dispatcher.js +0 -953
- package/extensions/dm-lens/dist/clients/dispatch/fact-provider-types.js +0 -1
- package/extensions/dm-lens/dist/clients/dispatch/fact-rule-runner.js +0 -17
- package/extensions/dm-lens/dist/clients/dispatch/fact-runner.js +0 -18
- package/extensions/dm-lens/dist/clients/dispatch/fact-scheduler.js +0 -52
- package/extensions/dm-lens/dist/clients/dispatch/fact-store.js +0 -199
- package/extensions/dm-lens/dist/clients/dispatch/facts/comment-facts.js +0 -20
- package/extensions/dm-lens/dist/clients/dispatch/facts/file-content.js +0 -18
- package/extensions/dm-lens/dist/clients/dispatch/facts/function-facts.js +0 -281
- package/extensions/dm-lens/dist/clients/dispatch/facts/import-facts.js +0 -169
- package/extensions/dm-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +0 -19
- package/extensions/dm-lens/dist/clients/dispatch/facts/try-catch-facts.js +0 -95
- package/extensions/dm-lens/dist/clients/dispatch/finding-policy.js +0 -159
- package/extensions/dm-lens/dist/clients/dispatch/indent-detect.js +0 -227
- package/extensions/dm-lens/dist/clients/dispatch/inline-suppressions.js +0 -52
- package/extensions/dm-lens/dist/clients/dispatch/integration.js +0 -1463
- package/extensions/dm-lens/dist/clients/dispatch/lazy.js +0 -8
- package/extensions/dm-lens/dist/clients/dispatch/pending-runner-findings.js +0 -75
- package/extensions/dm-lens/dist/clients/dispatch/plan.js +0 -278
- package/extensions/dm-lens/dist/clients/dispatch/priorities.js +0 -14
- package/extensions/dm-lens/dist/clients/dispatch/rule-id-normalize.js +0 -42
- package/extensions/dm-lens/dist/clients/dispatch/rule-ignores.js +0 -21
- package/extensions/dm-lens/dist/clients/dispatch/rule-policy.js +0 -73
- package/extensions/dm-lens/dist/clients/dispatch/rules/async-noise.js +0 -31
- package/extensions/dm-lens/dist/clients/dispatch/rules/async-unnecessary-wrapper.js +0 -27
- package/extensions/dm-lens/dist/clients/dispatch/rules/cors-wildcard.js +0 -35
- package/extensions/dm-lens/dist/clients/dispatch/rules/error-obscuring.js +0 -29
- package/extensions/dm-lens/dist/clients/dispatch/rules/error-swallowing.js +0 -29
- package/extensions/dm-lens/dist/clients/dispatch/rules/framework-call-noise.js +0 -31
- package/extensions/dm-lens/dist/clients/dispatch/rules/high-complexity.js +0 -56
- package/extensions/dm-lens/dist/clients/dispatch/rules/high-fan-out.js +0 -45
- package/extensions/dm-lens/dist/clients/dispatch/rules/high-import-coupling.js +0 -31
- package/extensions/dm-lens/dist/clients/dispatch/rules/missing-error-propagation.js +0 -45
- package/extensions/dm-lens/dist/clients/dispatch/rules/no-commented-credentials.js +0 -46
- package/extensions/dm-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +0 -38
- package/extensions/dm-lens/dist/clients/dispatch/rules/placeholder-comments.js +0 -40
- package/extensions/dm-lens/dist/clients/dispatch/rules/unsafe-boundary.js +0 -101
- package/extensions/dm-lens/dist/clients/dispatch/runner-context.js +0 -46
- package/extensions/dm-lens/dist/clients/dispatch/runners/actionlint.js +0 -98
- package/extensions/dm-lens/dist/clients/dispatch/runners/ast-grep-napi.js +0 -690
- package/extensions/dm-lens/dist/clients/dispatch/runners/biome-check.js +0 -202
- package/extensions/dm-lens/dist/clients/dispatch/runners/cpp-check.js +0 -190
- package/extensions/dm-lens/dist/clients/dispatch/runners/credo.js +0 -66
- package/extensions/dm-lens/dist/clients/dispatch/runners/cue-vet.js +0 -167
- package/extensions/dm-lens/dist/clients/dispatch/runners/dart-analyze.js +0 -151
- package/extensions/dm-lens/dist/clients/dispatch/runners/detekt.js +0 -157
- package/extensions/dm-lens/dist/clients/dispatch/runners/dotnet-build.js +0 -157
- package/extensions/dm-lens/dist/clients/dispatch/runners/elixir-check.js +0 -153
- package/extensions/dm-lens/dist/clients/dispatch/runners/eslint.js +0 -99
- package/extensions/dm-lens/dist/clients/dispatch/runners/fact-rules.js +0 -20
- package/extensions/dm-lens/dist/clients/dispatch/runners/fish-indent.js +0 -65
- package/extensions/dm-lens/dist/clients/dispatch/runners/gleam-check.js +0 -107
- package/extensions/dm-lens/dist/clients/dispatch/runners/go-vet.js +0 -51
- package/extensions/dm-lens/dist/clients/dispatch/runners/golangci-lint.js +0 -89
- package/extensions/dm-lens/dist/clients/dispatch/runners/hadolint.js +0 -83
- package/extensions/dm-lens/dist/clients/dispatch/runners/helm-lint.js +0 -144
- package/extensions/dm-lens/dist/clients/dispatch/runners/helm-render.js +0 -593
- package/extensions/dm-lens/dist/clients/dispatch/runners/htmlhint.js +0 -103
- package/extensions/dm-lens/dist/clients/dispatch/runners/index.js +0 -100
- package/extensions/dm-lens/dist/clients/dispatch/runners/javac.js +0 -82
- package/extensions/dm-lens/dist/clients/dispatch/runners/ktlint.js +0 -93
- package/extensions/dm-lens/dist/clients/dispatch/runners/lsp.js +0 -206
- package/extensions/dm-lens/dist/clients/dispatch/runners/markdownlint.js +0 -129
- package/extensions/dm-lens/dist/clients/dispatch/runners/mypy.js +0 -70
- package/extensions/dm-lens/dist/clients/dispatch/runners/oxlint.js +0 -305
- package/extensions/dm-lens/dist/clients/dispatch/runners/php-lint.js +0 -70
- package/extensions/dm-lens/dist/clients/dispatch/runners/phpstan.js +0 -90
- package/extensions/dm-lens/dist/clients/dispatch/runners/prisma-validate.js +0 -56
- package/extensions/dm-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +0 -307
- package/extensions/dm-lens/dist/clients/dispatch/runners/pyright.js +0 -118
- package/extensions/dm-lens/dist/clients/dispatch/runners/rubocop.js +0 -79
- package/extensions/dm-lens/dist/clients/dispatch/runners/ruff.js +0 -69
- package/extensions/dm-lens/dist/clients/dispatch/runners/rust-clippy.js +0 -147
- package/extensions/dm-lens/dist/clients/dispatch/runners/shellcheck.js +0 -111
- package/extensions/dm-lens/dist/clients/dispatch/runners/shfmt.js +0 -81
- package/extensions/dm-lens/dist/clients/dispatch/runners/spellcheck.js +0 -74
- package/extensions/dm-lens/dist/clients/dispatch/runners/spotbugs.js +0 -208
- package/extensions/dm-lens/dist/clients/dispatch/runners/sqlfluff.js +0 -136
- package/extensions/dm-lens/dist/clients/dispatch/runners/stylelint.js +0 -118
- package/extensions/dm-lens/dist/clients/dispatch/runners/swiftlint.js +0 -143
- package/extensions/dm-lens/dist/clients/dispatch/runners/taplo.js +0 -97
- package/extensions/dm-lens/dist/clients/dispatch/runners/terragrunt.js +0 -110
- package/extensions/dm-lens/dist/clients/dispatch/runners/tflint.js +0 -104
- package/extensions/dm-lens/dist/clients/dispatch/runners/tree-sitter.js +0 -516
- package/extensions/dm-lens/dist/clients/dispatch/runners/trivy-config.js +0 -155
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/availability-policy.js +0 -285
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +0 -61
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -61
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +0 -130
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +0 -1067
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +0 -40
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/tool-failure.js +0 -117
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +0 -88
- package/extensions/dm-lens/dist/clients/dispatch/runners/utils.js +0 -8
- package/extensions/dm-lens/dist/clients/dispatch/runners/vale.js +0 -106
- package/extensions/dm-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +0 -163
- package/extensions/dm-lens/dist/clients/dispatch/runners/yamllint.js +0 -83
- package/extensions/dm-lens/dist/clients/dispatch/runners/zig-check.js +0 -72
- package/extensions/dm-lens/dist/clients/dispatch/suppress-writer.js +0 -57
- package/extensions/dm-lens/dist/clients/dispatch/tool-profile.js +0 -30
- package/extensions/dm-lens/dist/clients/dispatch/types.js +0 -7
- package/extensions/dm-lens/dist/clients/dispatch/utils/format-utils.js +0 -45
- package/extensions/dm-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +0 -31
- package/extensions/dm-lens/dist/clients/disposition-logger.js +0 -19
- package/extensions/dm-lens/dist/clients/disposition-publish.js +0 -88
- package/extensions/dm-lens/dist/clients/durable-store.js +0 -77
- package/extensions/dm-lens/dist/clients/effective-config.js +0 -160
- package/extensions/dm-lens/dist/clients/env-utils.js +0 -26
- package/extensions/dm-lens/dist/clients/error-class.js +0 -3
- package/extensions/dm-lens/dist/clients/eval-timestamp.js +0 -2
- package/extensions/dm-lens/dist/clients/event-loop-hold.js +0 -119
- package/extensions/dm-lens/dist/clients/event-loop-monitor.js +0 -84
- package/extensions/dm-lens/dist/clients/extension-log.js +0 -230
- package/extensions/dm-lens/dist/clients/extension-mode.js +0 -20
- package/extensions/dm-lens/dist/clients/feature-hints.js +0 -88
- package/extensions/dm-lens/dist/clients/file-kinds.js +0 -304
- package/extensions/dm-lens/dist/clients/file-role.js +0 -50
- package/extensions/dm-lens/dist/clients/file-time.js +0 -112
- package/extensions/dm-lens/dist/clients/file-utils.js +0 -630
- package/extensions/dm-lens/dist/clients/finding-delivery-gate.js +0 -129
- package/extensions/dm-lens/dist/clients/finding-identity.js +0 -23
- package/extensions/dm-lens/dist/clients/fix-worklog.js +0 -75
- package/extensions/dm-lens/dist/clients/format-events-publish.js +0 -230
- package/extensions/dm-lens/dist/clients/format-service.js +0 -154
- package/extensions/dm-lens/dist/clients/formatters-lazy.js +0 -8
- package/extensions/dm-lens/dist/clients/formatters.js +0 -1351
- package/extensions/dm-lens/dist/clients/freshness-cadence.js +0 -1
- package/extensions/dm-lens/dist/clients/freshness.js +0 -8
- package/extensions/dm-lens/dist/clients/generated-artifacts.js +0 -209
- package/extensions/dm-lens/dist/clients/generation-guard.js +0 -105
- package/extensions/dm-lens/dist/clients/git-guard.js +0 -770
- package/extensions/dm-lens/dist/clients/git-tracked-ignore.js +0 -120
- package/extensions/dm-lens/dist/clients/gitleaks-client.js +0 -282
- package/extensions/dm-lens/dist/clients/go-client.js +0 -47
- package/extensions/dm-lens/dist/clients/govulncheck-client.js +0 -411
- package/extensions/dm-lens/dist/clients/gradle-ktfmt-style.js +0 -177
- package/extensions/dm-lens/dist/clients/grammar-source.js +0 -224
- package/extensions/dm-lens/dist/clients/gzip-stage-write.js +0 -85
- package/extensions/dm-lens/dist/clients/hashline-anchor.js +0 -222
- package/extensions/dm-lens/dist/clients/hook-budgets.js +0 -16
- package/extensions/dm-lens/dist/clients/host-edit-normalize.js +0 -87
- package/extensions/dm-lens/dist/clients/host-ports.js +0 -35
- package/extensions/dm-lens/dist/clients/indent-retarget.js +0 -102
- package/extensions/dm-lens/dist/clients/inline-blocker-dispositions.js +0 -103
- package/extensions/dm-lens/dist/clients/install-diagnostics.js +0 -123
- package/extensions/dm-lens/dist/clients/installer/index.js +0 -3770
- package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh-session.js +0 -17
- package/extensions/dm-lens/dist/clients/installer/managed-tool-refresh.js +0 -522
- package/extensions/dm-lens/dist/clients/instance-reaper-state.js +0 -3
- package/extensions/dm-lens/dist/clients/instance-reaper.js +0 -577
- package/extensions/dm-lens/dist/clients/instance-registry-lock.js +0 -131
- package/extensions/dm-lens/dist/clients/instance-registry.js +0 -452
- package/extensions/dm-lens/dist/clients/jscpd-client.js +0 -252
- package/extensions/dm-lens/dist/clients/json-cache-read.js +0 -25
- package/extensions/dm-lens/dist/clients/knip-client.js +0 -472
- package/extensions/dm-lens/dist/clients/language-policy.js +0 -242
- package/extensions/dm-lens/dist/clients/language-profile.js +0 -261
- package/extensions/dm-lens/dist/clients/language-registry.js +0 -424
- package/extensions/dm-lens/dist/clients/latency-logger.js +0 -192
- package/extensions/dm-lens/dist/clients/lazy-import.js +0 -14
- package/extensions/dm-lens/dist/clients/ledger-bounds.js +0 -21
- package/extensions/dm-lens/dist/clients/lens-config.js +0 -237
- package/extensions/dm-lens/dist/clients/lens-engine.js +0 -181
- package/extensions/dm-lens/dist/clients/lens-events.js +0 -105
- package/extensions/dm-lens/dist/clients/lens-flag-registry.js +0 -302
- package/extensions/dm-lens/dist/clients/lens-map.js +0 -980
- package/extensions/dm-lens/dist/clients/live-bus-emitter.js +0 -53
- package/extensions/dm-lens/dist/clients/log-cleanup.js +0 -138
- package/extensions/dm-lens/dist/clients/lsp/aggregation.js +0 -88
- package/extensions/dm-lens/dist/clients/lsp/cascade-tier.js +0 -203
- package/extensions/dm-lens/dist/clients/lsp/client.js +0 -2709
- package/extensions/dm-lens/dist/clients/lsp/config.js +0 -252
- package/extensions/dm-lens/dist/clients/lsp/content-limits.js +0 -21
- package/extensions/dm-lens/dist/clients/lsp/diagnostic-binding.js +0 -79
- package/extensions/dm-lens/dist/clients/lsp/document-drift.js +0 -312
- package/extensions/dm-lens/dist/clients/lsp/edits.js +0 -930
- package/extensions/dm-lens/dist/clients/lsp/index.js +0 -4448
- package/extensions/dm-lens/dist/clients/lsp/inferred-project.js +0 -121
- package/extensions/dm-lens/dist/clients/lsp/jvm-runtime.js +0 -194
- package/extensions/dm-lens/dist/clients/lsp/language.js +0 -23
- package/extensions/dm-lens/dist/clients/lsp/launch.js +0 -468
- package/extensions/dm-lens/dist/clients/lsp/lombok.js +0 -146
- package/extensions/dm-lens/dist/clients/lsp/path-utils.js +0 -1
- package/extensions/dm-lens/dist/clients/lsp/pending-aux-coverage.js +0 -90
- package/extensions/dm-lens/dist/clients/lsp/position-encoding.js +0 -28
- package/extensions/dm-lens/dist/clients/lsp/ruby-drive-dirs.js +0 -42
- package/extensions/dm-lens/dist/clients/lsp/server.js +0 -2422
- package/extensions/dm-lens/dist/clients/lsp/session-roots.js +0 -52
- package/extensions/dm-lens/dist/clients/lsp/spawn-history.js +0 -15
- package/extensions/dm-lens/dist/clients/lsp/sync-kind.js +0 -30
- package/extensions/dm-lens/dist/clients/lsp/tsserver-sync.js +0 -156
- package/extensions/dm-lens/dist/clients/lsp/wait-policy/capability-snapshot.js +0 -1
- package/extensions/dm-lens/dist/clients/lsp/wait-policy/classification.js +0 -36
- package/extensions/dm-lens/dist/clients/lsp/wait-policy/index.js +0 -3
- package/extensions/dm-lens/dist/clients/lsp/wait-policy/strategies.js +0 -175
- package/extensions/dm-lens/dist/clients/lsp/watch-queue.js +0 -40
- package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-cache.js +0 -267
- package/extensions/dm-lens/dist/clients/lsp/workspace-diagnostics-session.js +0 -7
- package/extensions/dm-lens/dist/clients/lsp/workspace-sweep-hold.js +0 -93
- package/extensions/dm-lens/dist/clients/lsp-budget.js +0 -83
- package/extensions/dm-lens/dist/clients/lsp-document-symbols.js +0 -93
- package/extensions/dm-lens/dist/clients/lsp-lazy.js +0 -8
- package/extensions/dm-lens/dist/clients/lsp-mutation.js +0 -273
- package/extensions/dm-lens/dist/clients/lsp-status.js +0 -37
- package/extensions/dm-lens/dist/clients/map-with-concurrency.js +0 -20
- package/extensions/dm-lens/dist/clients/mcp/analyze.js +0 -251
- package/extensions/dm-lens/dist/clients/mcp/host-shim.js +0 -14
- package/extensions/dm-lens/dist/clients/mcp/ipc.js +0 -302
- package/extensions/dm-lens/dist/clients/mcp/review.js +0 -137
- package/extensions/dm-lens/dist/clients/mcp/session.js +0 -305
- package/extensions/dm-lens/dist/clients/memory-sampler.js +0 -107
- package/extensions/dm-lens/dist/clients/message-end-attribution.js +0 -18
- package/extensions/dm-lens/dist/clients/metrics-client.js +0 -80
- package/extensions/dm-lens/dist/clients/metrics-history.js +0 -255
- package/extensions/dm-lens/dist/clients/middle-man-analysis.js +0 -161
- package/extensions/dm-lens/dist/clients/model-provider.js +0 -31
- package/extensions/dm-lens/dist/clients/module-report-lsp.js +0 -140
- package/extensions/dm-lens/dist/clients/module-report.js +0 -1642
- package/extensions/dm-lens/dist/clients/mutating-tool.js +0 -377
- package/extensions/dm-lens/dist/clients/mutation-attribution.js +0 -168
- package/extensions/dm-lens/dist/clients/mutation-bridge.js +0 -102
- package/extensions/dm-lens/dist/clients/ndjson-logger.js +0 -471
- package/extensions/dm-lens/dist/clients/observed-mutation-sources.js +0 -43
- package/extensions/dm-lens/dist/clients/observed-mutation.js +0 -709
- package/extensions/dm-lens/dist/clients/oldtext-autopatch.js +0 -100
- package/extensions/dm-lens/dist/clients/opaque-mutation-scan.js +0 -313
- package/extensions/dm-lens/dist/clients/opengrep-client.js +0 -216
- package/extensions/dm-lens/dist/clients/opengrep-config.js +0 -52
- package/extensions/dm-lens/dist/clients/package-manager.js +0 -303
- package/extensions/dm-lens/dist/clients/package-root.js +0 -25
- package/extensions/dm-lens/dist/clients/partial-edit-apply.js +0 -337
- package/extensions/dm-lens/dist/clients/path-attribution-telemetry.js +0 -31
- package/extensions/dm-lens/dist/clients/path-keyed-map.js +0 -57
- package/extensions/dm-lens/dist/clients/path-utils.js +0 -476
- package/extensions/dm-lens/dist/clients/performance-report.js +0 -291
- package/extensions/dm-lens/dist/clients/persist-debounce.js +0 -37
- package/extensions/dm-lens/dist/clients/persistent-reverify.js +0 -165
- package/extensions/dm-lens/dist/clients/php-cs-fixer-config.js +0 -15
- package/extensions/dm-lens/dist/clients/pipeline.js +0 -1091
- package/extensions/dm-lens/dist/clients/post-autofix-notice.js +0 -19
- package/extensions/dm-lens/dist/clients/print-mode.js +0 -3
- package/extensions/dm-lens/dist/clients/probe-home-state.js +0 -62
- package/extensions/dm-lens/dist/clients/process-bridge.js +0 -20
- package/extensions/dm-lens/dist/clients/process-singletons.js +0 -69
- package/extensions/dm-lens/dist/clients/process-snapshot.js +0 -22
- package/extensions/dm-lens/dist/clients/project-changes.js +0 -112
- package/extensions/dm-lens/dist/clients/project-conventions.js +0 -152
- package/extensions/dm-lens/dist/clients/project-diagnostics/cache.js +0 -91
- package/extensions/dm-lens/dist/clients/project-diagnostics/extractors.js +0 -53
- package/extensions/dm-lens/dist/clients/project-diagnostics/fresh-fetch.js +0 -408
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +0 -64
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +0 -38
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +0 -21
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/govulncheck.js +0 -23
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +0 -28
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +0 -45
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +0 -34
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +0 -32
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +0 -79
- package/extensions/dm-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +0 -41
- package/extensions/dm-lens/dist/clients/project-diagnostics/scanner.js +0 -349
- package/extensions/dm-lens/dist/clients/project-diagnostics/types.js +0 -1
- package/extensions/dm-lens/dist/clients/project-lens-config.js +0 -437
- package/extensions/dm-lens/dist/clients/project-report.js +0 -527
- package/extensions/dm-lens/dist/clients/project-scale.js +0 -60
- package/extensions/dm-lens/dist/clients/project-scan-policy.js +0 -4
- package/extensions/dm-lens/dist/clients/project-snapshot-fingerprint.js +0 -39
- package/extensions/dm-lens/dist/clients/project-snapshot-persist-worker.js +0 -14
- package/extensions/dm-lens/dist/clients/project-snapshot.js +0 -1178
- package/extensions/dm-lens/dist/clients/project-trust.js +0 -104
- package/extensions/dm-lens/dist/clients/python-environment.js +0 -120
- package/extensions/dm-lens/dist/clients/python-provenance.js +0 -551
- package/extensions/dm-lens/dist/clients/quiet-window-config.js +0 -16
- package/extensions/dm-lens/dist/clients/quiet-window.js +0 -126
- package/extensions/dm-lens/dist/clients/read-bridge.js +0 -46
- package/extensions/dm-lens/dist/clients/read-expansion.js +0 -218
- package/extensions/dm-lens/dist/clients/read-guard-logger.js +0 -178
- package/extensions/dm-lens/dist/clients/read-guard-tool-lines.js +0 -1042
- package/extensions/dm-lens/dist/clients/read-guard.js +0 -1096
- package/extensions/dm-lens/dist/clients/recent-touches.js +0 -126
- package/extensions/dm-lens/dist/clients/redact/secrets.js +0 -386
- package/extensions/dm-lens/dist/clients/resource-sampler.js +0 -344
- package/extensions/dm-lens/dist/clients/reverse-deps.js +0 -227
- package/extensions/dm-lens/dist/clients/review-graph/builder.js +0 -3635
- package/extensions/dm-lens/dist/clients/review-graph/format.js +0 -30
- package/extensions/dm-lens/dist/clients/review-graph/git-identity.js +0 -115
- package/extensions/dm-lens/dist/clients/review-graph/import-resolvers.js +0 -325
- package/extensions/dm-lens/dist/clients/review-graph/persist-worker.js +0 -8
- package/extensions/dm-lens/dist/clients/review-graph/query.js +0 -195
- package/extensions/dm-lens/dist/clients/review-graph/revision-drift.js +0 -3
- package/extensions/dm-lens/dist/clients/review-graph/service.js +0 -60
- package/extensions/dm-lens/dist/clients/review-graph/shared-extraction-ir.js +0 -54
- package/extensions/dm-lens/dist/clients/review-graph/symbol-id.js +0 -29
- package/extensions/dm-lens/dist/clients/review-graph/tsconfig-paths.js +0 -253
- package/extensions/dm-lens/dist/clients/review-graph/types.js +0 -1
- package/extensions/dm-lens/dist/clients/review-graph/workspace-modules.js +0 -374
- package/extensions/dm-lens/dist/clients/review-graph-logger.js +0 -51
- package/extensions/dm-lens/dist/clients/ruff-client.js +0 -109
- package/extensions/dm-lens/dist/clients/rules-scanner.js +0 -113
- package/extensions/dm-lens/dist/clients/run-duration.js +0 -9
- package/extensions/dm-lens/dist/clients/runtime-agent-end.js +0 -608
- package/extensions/dm-lens/dist/clients/runtime-config.js +0 -39
- package/extensions/dm-lens/dist/clients/runtime-context.js +0 -155
- package/extensions/dm-lens/dist/clients/runtime-coordinator.js +0 -817
- package/extensions/dm-lens/dist/clients/runtime-session.js +0 -1625
- package/extensions/dm-lens/dist/clients/runtime-tool-call.js +0 -868
- package/extensions/dm-lens/dist/clients/runtime-tool-result.js +0 -1317
- package/extensions/dm-lens/dist/clients/runtime-turn.js +0 -2333
- package/extensions/dm-lens/dist/clients/rust-client.js +0 -48
- package/extensions/dm-lens/dist/clients/safe-spawn.js +0 -1267
- package/extensions/dm-lens/dist/clients/sanitize.js +0 -174
- package/extensions/dm-lens/dist/clients/scan-utils.js +0 -7
- package/extensions/dm-lens/dist/clients/scratch-tree-policy.js +0 -57
- package/extensions/dm-lens/dist/clients/search-read-registration.js +0 -59
- package/extensions/dm-lens/dist/clients/secret-findings.js +0 -69
- package/extensions/dm-lens/dist/clients/security-scan-client.js +0 -208
- package/extensions/dm-lens/dist/clients/session-event-guard.js +0 -111
- package/extensions/dm-lens/dist/clients/session-lifecycle.js +0 -173
- package/extensions/dm-lens/dist/clients/session-start-observability.js +0 -47
- package/extensions/dm-lens/dist/clients/session-state-store.js +0 -63
- package/extensions/dm-lens/dist/clients/session-summary.js +0 -8
- package/extensions/dm-lens/dist/clients/sessionstart-logger.js +0 -22
- package/extensions/dm-lens/dist/clients/sg-runner.js +0 -627
- package/extensions/dm-lens/dist/clients/sgconfig.js +0 -280
- package/extensions/dm-lens/dist/clients/shared-checkout-guard.js +0 -177
- package/extensions/dm-lens/dist/clients/single-flight.js +0 -52
- package/extensions/dm-lens/dist/clients/situational-tool-telemetry.js +0 -85
- package/extensions/dm-lens/dist/clients/skills-resolver.js +0 -38
- package/extensions/dm-lens/dist/clients/slow-fs.js +0 -77
- package/extensions/dm-lens/dist/clients/smells-rollup.js +0 -118
- package/extensions/dm-lens/dist/clients/source-filter.js +0 -320
- package/extensions/dm-lens/dist/clients/source-walker.js +0 -96
- package/extensions/dm-lens/dist/clients/spawn-output-cap.js +0 -35
- package/extensions/dm-lens/dist/clients/spawn-timeout-cooldown.js +0 -51
- package/extensions/dm-lens/dist/clients/stale-marker.js +0 -1
- package/extensions/dm-lens/dist/clients/startup-scan.js +0 -222
- package/extensions/dm-lens/dist/clients/startup-timing.js +0 -67
- package/extensions/dm-lens/dist/clients/string-utils.js +0 -6
- package/extensions/dm-lens/dist/clients/subagent-mode.js +0 -40
- package/extensions/dm-lens/dist/clients/symbol-containment.js +0 -16
- package/extensions/dm-lens/dist/clients/symbol-types.js +0 -1
- package/extensions/dm-lens/dist/clients/test-runner-client.js +0 -1504
- package/extensions/dm-lens/dist/clients/test-runner-delivery.js +0 -260
- package/extensions/dm-lens/dist/clients/todo-scanner.js +0 -164
- package/extensions/dm-lens/dist/clients/tool-agreement.js +0 -377
- package/extensions/dm-lens/dist/clients/tool-config.js +0 -218
- package/extensions/dm-lens/dist/clients/tool-cwd.js +0 -235
- package/extensions/dm-lens/dist/clients/tool-definition.js +0 -22
- package/extensions/dm-lens/dist/clients/tool-event.js +0 -18
- package/extensions/dm-lens/dist/clients/tool-policy.js +0 -2393
- package/extensions/dm-lens/dist/clients/tool-probe.js +0 -5
- package/extensions/dm-lens/dist/clients/tool-render.js +0 -79
- package/extensions/dm-lens/dist/clients/tool-set-policy.js +0 -70
- package/extensions/dm-lens/dist/clients/tree-sitter-cache.js +0 -206
- package/extensions/dm-lens/dist/clients/tree-sitter-client.js +0 -2787
- package/extensions/dm-lens/dist/clients/tree-sitter-logger.js +0 -77
- package/extensions/dm-lens/dist/clients/tree-sitter-navigator.js +0 -198
- package/extensions/dm-lens/dist/clients/tree-sitter-query-loader.js +0 -318
- package/extensions/dm-lens/dist/clients/tree-sitter-shared.js +0 -87
- package/extensions/dm-lens/dist/clients/tree-sitter-symbol-extractor.js +0 -957
- package/extensions/dm-lens/dist/clients/trivy-client.js +0 -305
- package/extensions/dm-lens/dist/clients/tui-fit.js +0 -26
- package/extensions/dm-lens/dist/clients/turn-context.js +0 -48
- package/extensions/dm-lens/dist/clients/turn-end/lane.js +0 -1
- package/extensions/dm-lens/dist/clients/turn-end/lanes/govulncheck.js +0 -54
- package/extensions/dm-lens/dist/clients/turn-end/lanes/secrets.js +0 -131
- package/extensions/dm-lens/dist/clients/turn-summary-render.js +0 -56
- package/extensions/dm-lens/dist/clients/turn-summary.js +0 -84
- package/extensions/dm-lens/dist/clients/typos-config.js +0 -9
- package/extensions/dm-lens/dist/clients/user-notify.js +0 -15
- package/extensions/dm-lens/dist/clients/vanished-instance-marker.js +0 -18
- package/extensions/dm-lens/dist/clients/warm-attach.js +0 -210
- package/extensions/dm-lens/dist/clients/widget-state.js +0 -963
- package/extensions/dm-lens/dist/clients/word-index-logger.js +0 -21
- package/extensions/dm-lens/dist/clients/word-index-store.js +0 -222
- package/extensions/dm-lens/dist/clients/word-index.js +0 -1426
- package/extensions/dm-lens/dist/clients/workspace-topology.js +0 -261
- package/extensions/dm-lens/dist/clients/write-ordering-guard.js +0 -24
- package/extensions/dm-lens/dist/clients/zizmor-config.js +0 -160
- package/extensions/dm-lens/dist/i18n.js +0 -67
- package/extensions/dm-lens/dist/index.js +0 -1782
- package/extensions/dm-lens/dist/mcp/analyze-cli.js +0 -178
- package/extensions/dm-lens/dist/mcp/build-staleness.js +0 -55
- package/extensions/dm-lens/dist/mcp/cli.js +0 -78
- package/extensions/dm-lens/dist/mcp/server.js +0 -1208
- package/extensions/dm-lens/dist/mcp/worker.js +0 -33
- package/extensions/dm-lens/dist/scripts/lib/process-scan.mjs +0 -256
- package/extensions/dm-lens/dist/scripts/lib/skills-predicate.mjs +0 -53
- package/extensions/dm-lens/dist/scripts/lib/web-tree-sitter-dir.mjs +0 -45
- package/extensions/dm-lens/dist/tools/activate-tools.js +0 -61
- package/extensions/dm-lens/dist/tools/ast-grep-outline.js +0 -127
- package/extensions/dm-lens/dist/tools/ast-grep-replace.js +0 -226
- package/extensions/dm-lens/dist/tools/ast-grep-search.js +0 -687
- package/extensions/dm-lens/dist/tools/effective-config.js +0 -59
- package/extensions/dm-lens/dist/tools/lens-diagnostic-mark.js +0 -240
- package/extensions/dm-lens/dist/tools/lens-diagnostics.js +0 -1484
- package/extensions/dm-lens/dist/tools/lsp-diagnostics.js +0 -1088
- package/extensions/dm-lens/dist/tools/lsp-navigation.js +0 -1194
- package/extensions/dm-lens/dist/tools/lsp-structured-output.js +0 -277
- package/extensions/dm-lens/dist/tools/module-report.js +0 -332
- package/extensions/dm-lens/dist/tools/project-report.js +0 -72
- package/extensions/dm-lens/dist/tools/render-compact.js +0 -272
- package/extensions/dm-lens/dist/tools/scan-progress.js +0 -31
- package/extensions/dm-lens/dist/tools/shared.js +0 -26
- package/extensions/dm-lens/dist/tools/symbol-search.js +0 -133
- package/extensions/dm-mcp-adapter/dist/abort.js +0 -35
- package/extensions/dm-mcp-adapter/dist/agent-dir.js +0 -45
- package/extensions/dm-mcp-adapter/dist/agent-plugin-loader.js +0 -392
- package/extensions/dm-mcp-adapter/dist/agent-plugin-provenance.js +0 -26
- package/extensions/dm-mcp-adapter/dist/bearer-command-resolver.js +0 -182
- package/extensions/dm-mcp-adapter/dist/claude-plugin-loader.js +0 -350
- package/extensions/dm-mcp-adapter/dist/config.js +0 -1310
- package/extensions/dm-mcp-adapter/dist/consent-manager.js +0 -84
- package/extensions/dm-mcp-adapter/dist/elicitation-handler.js +0 -308
- package/extensions/dm-mcp-adapter/dist/errors.js +0 -225
- package/extensions/dm-mcp-adapter/dist/http-ca.js +0 -71
- package/extensions/dm-mcp-adapter/dist/jev-client.js +0 -359
- package/extensions/dm-mcp-adapter/dist/jev-contracts.js +0 -1
- package/extensions/dm-mcp-adapter/dist/jev-key-store.js +0 -176
- package/extensions/dm-mcp-adapter/dist/json-schema-validator.js +0 -70
- package/extensions/dm-mcp-adapter/dist/lifecycle.js +0 -387
- package/extensions/dm-mcp-adapter/dist/logger.js +0 -115
- package/extensions/dm-mcp-adapter/dist/mcp-auth-fetch.js +0 -86
- package/extensions/dm-mcp-adapter/dist/mcp-auth-flow.js +0 -949
- package/extensions/dm-mcp-adapter/dist/mcp-auth.js +0 -997
- package/extensions/dm-mcp-adapter/dist/mcp-bearer-store.js +0 -182
- package/extensions/dm-mcp-adapter/dist/mcp-callback-server.js +0 -381
- package/extensions/dm-mcp-adapter/dist/mcp-oauth-provider.js +0 -524
- package/extensions/dm-mcp-adapter/dist/mcp-probe.js +0 -151
- package/extensions/dm-mcp-adapter/dist/mcp-tasks.js +0 -300
- package/extensions/dm-mcp-adapter/dist/mcp-trace.js +0 -215
- package/extensions/dm-mcp-adapter/dist/metadata-cache.js +0 -267
- package/extensions/dm-mcp-adapter/dist/npx-resolver.js +0 -465
- package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +0 -135
- package/extensions/dm-mcp-adapter/dist/request-headers-command.js +0 -294
- package/extensions/dm-mcp-adapter/dist/resource-tools.js +0 -7
- package/extensions/dm-mcp-adapter/dist/runtime-owner.js +0 -94
- package/extensions/dm-mcp-adapter/dist/sampling-handler.js +0 -213
- package/extensions/dm-mcp-adapter/dist/secure-keyring.js +0 -191
- package/extensions/dm-mcp-adapter/dist/server-manager.js +0 -1514
- package/extensions/dm-mcp-adapter/dist/session-approvals.js +0 -127
- package/extensions/dm-mcp-adapter/dist/session-recovery.js +0 -82
- package/extensions/dm-mcp-adapter/dist/state.js +0 -1
- package/extensions/dm-mcp-adapter/dist/types.js +0 -286
- package/extensions/dm-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -36
- package/extensions/dm-mcp-adapter/dist/ui-resource-handler.js +0 -204
- package/extensions/dm-mcp-adapter/dist/ui-stream-types.js +0 -58
- package/extensions/dm-mcp-adapter/dist/ui-tool-visibility.js +0 -26
- package/extensions/dm-mcp-adapter/dist/unix-socket-transport.js +0 -83
- package/extensions/dm-mcp-adapter/dist/utils.js +0 -382
|
@@ -1,1484 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import * as fsSync from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { BoundedLruCache } from "../clients/bounded-cache.js";
|
|
5
|
-
import { Type } from "../clients/deps/typebox.js";
|
|
6
|
-
import { anchorsForDiagnostic, applyDispositions, applyWeakDispositions, hasAnyDispositionMarks, hasStrictDispositionMarks, getDisposition } from "../clients/diagnostic-dispositions.js";
|
|
7
|
-
import { DEPENDENCY_DRIFT_MAX_DELIVERIES } from "../clients/blocker-freshness.js";
|
|
8
|
-
import { freshnessFromMtime } from "../clients/freshness.js";
|
|
9
|
-
import { applyFindingPolicy, loadProjectRulePolicyMap } from "../clients/dispatch/finding-policy.js";
|
|
10
|
-
import { gateFindingsByPathFreshness } from "../clients/advisory-provenance.js";
|
|
11
|
-
import { formatCacheAgeLabel, markUnreconciledFindings } from "../clients/finding-delivery-gate.js";
|
|
12
|
-
import { normalizeRuleId } from "../clients/dispatch/rule-id-normalize.js";
|
|
13
|
-
import { applyRulePolicy } from "../clients/dispatch/rule-policy.js";
|
|
14
|
-
import { compactRenderResult } from "./render-compact.js";
|
|
15
|
-
import { combineAbortSignals } from "../clients/deadline-utils.js";
|
|
16
|
-
import { getProjectIgnoreMatcher } from "../clients/file-utils.js";
|
|
17
|
-
import { isAtOrAboveHomeDir, normalizeEphemeralMapKey, normalizeFilePath, normalizeMapKey, realpathOrResolve } from "../clients/path-utils.js";
|
|
18
|
-
import { getLSPService } from "../clients/lsp/index.js";
|
|
19
|
-
import { retireInlineBlockerAndResyncGuard } from "../clients/git-guard.js";
|
|
20
|
-
import { primaryServerId, resolveLspCwdForFile } from "../clients/lsp/config.js";
|
|
21
|
-
import { getFullScanWallClockMs } from "../clients/lsp/workspace-sweep-hold.js";
|
|
22
|
-
import { demoteInferredProjectSweepResults } from "../clients/lsp/inferred-project.js";
|
|
23
|
-
import { hashDiagnosticContent } from "../clients/lsp/diagnostic-binding.js";
|
|
24
|
-
import { loadProjectDiagnosticsDeltaReport, loadProjectDiagnosticsSnapshot, PROJECT_DIAGNOSTICS_CACHE_VERSION, reconcileProjectDiagnosticsSnapshot } from "../clients/project-diagnostics/cache.js";
|
|
25
|
-
import { formatCacheAgeOld, formatNotRunEntry } from "../clients/project-diagnostics/extractors.js";
|
|
26
|
-
import { ANALYZER_IDS, fetchFreshProjectDiagnostics } from "../clients/project-diagnostics/fresh-fetch.js";
|
|
27
|
-
import { loadBootstrapClients } from "../clients/bootstrap.js";
|
|
28
|
-
import { resolveLensToolName } from "../clients/tool-config.js";
|
|
29
|
-
import { generatedSkipNotice, scanTruncationNotice } from "../clients/lens-engine.js";
|
|
30
|
-
import { scanProjectDiagnostics } from "../clients/project-diagnostics/scanner.js";
|
|
31
|
-
import { classifyDiagnosticTier, getFileDiagnosticSummaries, reconcileCorrelatedScanDiagnostics, reconcileScanDiagnostics, reconcileStaleWidgetDependencyBlockers, reconcileStaleWidgetFiles, widgetDiagnosticUri } from "../clients/widget-state.js";
|
|
32
|
-
import { claimPhaseOncePerSession, logLatency } from "../clients/latency-logger.js";
|
|
33
|
-
import { logExtension } from "../clients/extension-log.js";
|
|
34
|
-
import { recordDegradationOnce } from "../clients/degradation-ledger.js";
|
|
35
|
-
import { convertLspDiagnostics } from "../clients/dispatch/utils/lsp-diagnostics.js";
|
|
36
|
-
import { findAuxiliaryProfileForSource, retagAuxiliaryDiagnostics } from "../clients/dispatch/auxiliary-lsp.js";
|
|
37
|
-
import { detectFileRole } from "../clients/file-role.js";
|
|
38
|
-
import { STALE_LINE_MARKER } from "../clients/stale-marker.js";
|
|
39
|
-
import { makeProgressReporter, scanningSummaryLine } from "./scan-progress.js";
|
|
40
|
-
import { createLspDiagnosticsTool, LSP_SEVERITY_FILTERS, MAX_BATCH_FILES, renderBatchOutcomeLines } from "./lsp-diagnostics.js";
|
|
41
|
-
import { demotePastEofDiagnostics, PAST_EOF_STALE_MARKER, resyncDocumentOnPastEof } from "../clients/diagnostic-line-freshness.js";
|
|
42
|
-
const MAX_DIAGNOSTICS_PER_FILE = 50;
|
|
43
|
-
const MAX_PATHS_ENTRIES = MAX_BATCH_FILES;
|
|
44
|
-
function notRequestedReason(host) {
|
|
45
|
-
return "refreshRunners not requested this call (quick mode) — pass " + `refreshRunners=cheap/all/cached to ${resolveLensToolName("lens_diagnostics", host) ?? "diagnostics"} mode=full to run it`;
|
|
46
|
-
}
|
|
47
|
-
const FULL_SCAN_WALL_CLOCK_MS = getFullScanWallClockMs();
|
|
48
|
-
const FULL_SCAN_BINDING_YIELD_EVERY = 16;
|
|
49
|
-
async function findFullScanBindingMismatches(results) {
|
|
50
|
-
const mismatched = new WeakSet;
|
|
51
|
-
let sinceYield = 0;
|
|
52
|
-
for (const result of results) {
|
|
53
|
-
if (result.boundToCurrentDisk === false) {
|
|
54
|
-
mismatched.add(result);
|
|
55
|
-
} else if (result.boundToCurrentDisk !== true && result.contentHash !== undefined) {
|
|
56
|
-
try {
|
|
57
|
-
const content = await fs.readFile(result.filePath, "utf-8");
|
|
58
|
-
if (hashDiagnosticContent(content) !== result.contentHash) {
|
|
59
|
-
mismatched.add(result);
|
|
60
|
-
}
|
|
61
|
-
} catch {}
|
|
62
|
-
}
|
|
63
|
-
sinceYield += 1;
|
|
64
|
-
if (sinceYield >= FULL_SCAN_BINDING_YIELD_EVERY) {
|
|
65
|
-
sinceYield = 0;
|
|
66
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return mismatched;
|
|
70
|
-
}
|
|
71
|
-
export function createLensDiagnosticsTool(cacheManager, getCwd, getLspService = getLSPService, flushPending = async () => {}, nextWriteIndex, captureLspStatusRepaint, getRuntime, isLensGuardEnabled = () => true) {
|
|
72
|
-
const lspProbe = createLspDiagnosticsTool(nextWriteIndex, (info) => {
|
|
73
|
-
const runtime = getRuntime?.();
|
|
74
|
-
if (!runtime)
|
|
75
|
-
return;
|
|
76
|
-
const retired = retireInlineBlockerAndResyncGuard({
|
|
77
|
-
runtime,
|
|
78
|
-
cacheManager,
|
|
79
|
-
cwd: info.cwd,
|
|
80
|
-
filePath: info.filePath,
|
|
81
|
-
...info.writeIndex === undefined ? {} : { writeIndex: info.writeIndex },
|
|
82
|
-
coveredSources: info.coveredSources,
|
|
83
|
-
lensGuardEnabled: isLensGuardEnabled()
|
|
84
|
-
});
|
|
85
|
-
if (retired) {
|
|
86
|
-
logExtension({
|
|
87
|
-
subsystem: "git-guard",
|
|
88
|
-
level: "debug",
|
|
89
|
-
message: `inline_blocker: retired for ${info.filePath}`
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}, getLspService);
|
|
93
|
-
return {
|
|
94
|
-
name: "lens_diagnostics",
|
|
95
|
-
label: "Project Diagnostics",
|
|
96
|
-
description: 'Query dm-lens diagnostics from the session cache or an active LSP probe, at paths or workspace scope. Empty cache is not proof of clean; probe changed paths when findings are absent or stale. Example: `{source: "lsp", scope: "paths", paths: ["src/app.ts"]}`.',
|
|
97
|
-
promptSnippet: "lens_diagnostics source=session reads the session cache and an empty cache is not proof of a clean file; use source=lsp scope=paths for changed files when cached findings are absent or stale",
|
|
98
|
-
renderResult: compactRenderResult(({ details, args, isError, text }) => {
|
|
99
|
-
if (details?.source === "lsp") {
|
|
100
|
-
const count = details.totalDiagnostics ?? 0;
|
|
101
|
-
const files = details.filesChecked ?? details.filesScanned ?? 0;
|
|
102
|
-
const noun = count === 1 ? "diagnostic" : "diagnostics";
|
|
103
|
-
const filePath = typeof details?.filePath === "string" ? details.filePath : Array.isArray(args?.paths) && args.paths.length === 1 && typeof args.paths[0] === "string" ? args.paths[0] : undefined;
|
|
104
|
-
const singleFile = (details?.mode === "file" || files === 1) && typeof filePath === "string" ? ` ${path.basename(filePath)}` : "";
|
|
105
|
-
const scope = files > 1 ? ` across ${files} files` : singleFile;
|
|
106
|
-
if (isError)
|
|
107
|
-
return `lens_diagnostics lsp — ${text.split(`
|
|
108
|
-
`)[0] ?? "error"}`;
|
|
109
|
-
if ((details.navigationOnlyFiles ?? 0) > 0)
|
|
110
|
-
return `lens_diagnostics${scope} — ${count} ${noun} · ${details.cleanFiles ?? 0} clean · ${details.navigationOnlyFiles} navigation-only`;
|
|
111
|
-
if ((details.unconfirmedFiles ?? 0) > 0)
|
|
112
|
-
return `lens_diagnostics${scope} — ${count} ${noun} · ${details.cleanFiles ?? 0} clean · ${details.unconfirmedFiles} unconfirmed${details.timedOutFiles ? ` (${details.timedOutFiles} timed out)` : ""}`;
|
|
113
|
-
const outcomeCounts = details.outcomeCounts;
|
|
114
|
-
const tooLargeLines = renderBatchOutcomeLines(details.outcomes ?? []);
|
|
115
|
-
if (tooLargeLines.length > 0)
|
|
116
|
-
return `lens_diagnostics${scope} — too large: ${tooLargeLines.join("; ")}`;
|
|
117
|
-
const notConfirmed = outcomeCounts ? (outcomeCounts.inconclusive ?? 0) + (outcomeCounts.unavailable ?? 0) + (outcomeCounts.unsupported ?? 0) + (outcomeCounts.failed ?? 0) + (outcomeCounts.too_large ?? 0) : 0;
|
|
118
|
-
if (notConfirmed > 0)
|
|
119
|
-
return `lens_diagnostics${scope} — ${count} ${noun} · ${notConfirmed} checks not confirmed`;
|
|
120
|
-
if ((details.incompleteFiles ?? 0) > 0)
|
|
121
|
-
return `lens_diagnostics${scope} — incomplete (${details.incompleteFiles} files not confirmed)`;
|
|
122
|
-
if (count === 0 && details.unconfirmed)
|
|
123
|
-
return details.timedOut ? `lens_diagnostics${scope} — timed out (result may be incomplete)` : `lens_diagnostics${scope} — unconfirmed (server cannot confirm clean)`;
|
|
124
|
-
return `lens_diagnostics${scope} — ${count} ${noun}`;
|
|
125
|
-
}
|
|
126
|
-
const scanning = scanningSummaryLine(details, text);
|
|
127
|
-
if (scanning)
|
|
128
|
-
return scanning;
|
|
129
|
-
const mode = details?.mode ?? (typeof args.mode === "string" ? args.mode : "delta");
|
|
130
|
-
if (isError) {
|
|
131
|
-
return `lens_diagnostics ${mode} — ${text.split(`
|
|
132
|
-
`)[0] ?? "error"}`;
|
|
133
|
-
}
|
|
134
|
-
const coldSuffix = details?.coldRunners && details.coldRunners.length > 0 ? ` (${details.coldRunners.length} cold: ${details.coldRunners.join(", ")})` : "";
|
|
135
|
-
const failedSuffix = details?.failedAnalyzers && details.failedAnalyzers.length > 0 ? ` (${details.failedAnalyzers.length} failed: ${details.failedAnalyzers.map((item) => item.id).join(", ")})` : "";
|
|
136
|
-
if (mode === "delta") {
|
|
137
|
-
const aw = details?.actionableWarnings ?? 0;
|
|
138
|
-
const cq = details?.qualityIssues ?? 0;
|
|
139
|
-
const pd = details?.projectDiagnostics ?? 0;
|
|
140
|
-
if (aw + cq + pd === 0)
|
|
141
|
-
return `lens_diagnostics delta — clean${coldSuffix}${failedSuffix}`;
|
|
142
|
-
return `lens_diagnostics delta — ${aw} actionable · ${cq} quality · ${pd} project${coldSuffix}${failedSuffix}`;
|
|
143
|
-
}
|
|
144
|
-
const b = details?.totalBlocking ?? 0;
|
|
145
|
-
const e = details?.totalErrors ?? 0;
|
|
146
|
-
const w = details?.totalWarnings ?? 0;
|
|
147
|
-
const adv = details?.totalAdvisories ?? 0;
|
|
148
|
-
const files = details?.filesWithIssues ?? details?.filesChecked ?? 0;
|
|
149
|
-
if (b + e + w === 0) {
|
|
150
|
-
const advisorySuffix = adv > 0 ? `, ${adv} hint${adv === 1 ? "" : "s"}` : "";
|
|
151
|
-
return `lens_diagnostics ${mode} — clean${advisorySuffix} (${files} files)${coldSuffix}${failedSuffix}`;
|
|
152
|
-
}
|
|
153
|
-
const parts = [`${b} blocking`];
|
|
154
|
-
if (b === 0 && e > 0)
|
|
155
|
-
parts.push(`${e} errors`);
|
|
156
|
-
parts.push(`${w} warnings`);
|
|
157
|
-
return `lens_diagnostics ${mode} — ${parts.join(" · ")} (${files} files)${coldSuffix}${failedSuffix}`;
|
|
158
|
-
}),
|
|
159
|
-
parameters: Type.Object({
|
|
160
|
-
source: Type.Optional(Type.String({
|
|
161
|
-
enum: ["session", "lsp"],
|
|
162
|
-
description: "Evidence source: session cache (empty cache is not proof of a " + "clean file — use source=lsp for changed files) or an active LSP probe."
|
|
163
|
-
})),
|
|
164
|
-
scope: Type.Optional(Type.String({
|
|
165
|
-
enum: ["paths", "workspace"],
|
|
166
|
-
description: "Coverage scope: explicit paths, or workspace (default: current turn's delta for source=session)."
|
|
167
|
-
})),
|
|
168
|
-
mode: Type.Optional(Type.String({
|
|
169
|
-
enum: ["delta", "all", "full"],
|
|
170
|
-
description: "delta = current turn; all = cache-only; full = active LSP scan of paths. Empty cache is not proof of clean."
|
|
171
|
-
})),
|
|
172
|
-
path: Type.Optional(Type.String({
|
|
173
|
-
description: "One file or directory for source=lsp checks."
|
|
174
|
-
})),
|
|
175
|
-
concurrency: Type.Optional(Type.Number({
|
|
176
|
-
description: "Source=lsp batch concurrency (maximum 16)."
|
|
177
|
-
})),
|
|
178
|
-
waitMs: Type.Optional(Type.Number({
|
|
179
|
-
description: "Source=lsp per-file wait budget in milliseconds."
|
|
180
|
-
})),
|
|
181
|
-
serverScope: Type.Optional(Type.String({
|
|
182
|
-
enum: ["primary", "all"],
|
|
183
|
-
description: "Source=lsp server coverage: primary or all."
|
|
184
|
-
})),
|
|
185
|
-
refreshRunners: Type.Optional(Type.Union([
|
|
186
|
-
Type.Boolean(),
|
|
187
|
-
Type.String({ enum: ["cached", "cheap", "all", "none"] })
|
|
188
|
-
], {
|
|
189
|
-
description: "Analyzer refresh mode for full view."
|
|
190
|
-
})),
|
|
191
|
-
maxProjectFiles: Type.Optional(Type.Number({
|
|
192
|
-
description: "Project-file limit for cheap runners."
|
|
193
|
-
})),
|
|
194
|
-
maxLspFiles: Type.Optional(Type.Number({
|
|
195
|
-
description: "File limit for the LSP sweep."
|
|
196
|
-
})),
|
|
197
|
-
includeGenerated: Type.Optional(Type.Boolean({
|
|
198
|
-
description: "Include generated-name paths in full scans."
|
|
199
|
-
})),
|
|
200
|
-
analysisRoot: Type.Optional(Type.String({
|
|
201
|
-
description: "Explicit project directory for heavyweight analyzers; it must exist and resolve strictly below the home directory."
|
|
202
|
-
})),
|
|
203
|
-
severity: Type.Optional(Type.String({
|
|
204
|
-
enum: [...LSP_SEVERITY_FILTERS],
|
|
205
|
-
description: "Filter by severity threshold (default: all): error shows errors; warning includes errors and warnings; information includes errors, warnings, and information; hint and all show every known tier."
|
|
206
|
-
})),
|
|
207
|
-
paths: Type.Optional(Type.Array(Type.String(), {
|
|
208
|
-
maxItems: MAX_PATHS_ENTRIES,
|
|
209
|
-
description: "Files or directories to filter."
|
|
210
|
-
}))
|
|
211
|
-
}),
|
|
212
|
-
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
213
|
-
const requestedSource = params.source;
|
|
214
|
-
const requestedScope = params.scope;
|
|
215
|
-
const legacyMode = params.mode;
|
|
216
|
-
const source = requestedSource ?? "session";
|
|
217
|
-
const scope = requestedScope ?? (legacyMode === "delta" || legacyMode === undefined ? source === "lsp" ? "paths" : "delta" : "workspace");
|
|
218
|
-
const cwd = ctx.cwd ?? getCwd();
|
|
219
|
-
if (source === "lsp") {
|
|
220
|
-
const lspParams = { ...params };
|
|
221
|
-
delete lspParams.source;
|
|
222
|
-
delete lspParams.scope;
|
|
223
|
-
const hasExplicitPath = typeof lspParams.path === "string" && lspParams.path.length > 0;
|
|
224
|
-
const hasExplicitPaths = Array.isArray(lspParams.paths) && lspParams.paths.length > 0;
|
|
225
|
-
if (scope === "workspace" && !hasExplicitPath && !hasExplicitPaths) {
|
|
226
|
-
lspParams.path = cwd;
|
|
227
|
-
}
|
|
228
|
-
const lspStart = Date.now();
|
|
229
|
-
const result = await lspProbe.execute(_toolCallId, lspParams, signal, onUpdate, ctx.signal ? { cwd, signal: ctx.signal } : { cwd });
|
|
230
|
-
logLatency({
|
|
231
|
-
type: "phase",
|
|
232
|
-
toolName: "lens_diagnostics",
|
|
233
|
-
filePath: cwd,
|
|
234
|
-
phase: "lens_diagnostics_lsp_route",
|
|
235
|
-
durationMs: Date.now() - lspStart,
|
|
236
|
-
metadata: {
|
|
237
|
-
scope,
|
|
238
|
-
isError: result.isError === true,
|
|
239
|
-
totalDiagnostics: result.details?.totalDiagnostics ?? 0,
|
|
240
|
-
cleanFiles: result.details?.cleanFiles ?? 0,
|
|
241
|
-
unconfirmedFiles: result.details?.unconfirmedFiles ?? 0,
|
|
242
|
-
timedOutFiles: result.details?.timedOutFiles ?? 0
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
return {
|
|
246
|
-
...result,
|
|
247
|
-
isError: result.isError === true,
|
|
248
|
-
details: { ...result.details, source, scope }
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
if (requestedSource !== undefined) {
|
|
252
|
-
const effectiveMode = legacyMode ?? (scope === "workspace" ? "all" : scope === "paths" ? "all" : "delta");
|
|
253
|
-
params = { ...params, mode: effectiveMode };
|
|
254
|
-
}
|
|
255
|
-
const repaintLspStatus = captureLspStatusRepaint?.(ctx);
|
|
256
|
-
const mode = params.mode ?? "delta";
|
|
257
|
-
const severity = params.severity ?? "all";
|
|
258
|
-
const refreshRunners = params.refreshRunners;
|
|
259
|
-
const parsePositiveInt = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : undefined;
|
|
260
|
-
const maxProjectFiles = parsePositiveInt(params.maxProjectFiles);
|
|
261
|
-
const maxLspFiles = parsePositiveInt(params.maxLspFiles);
|
|
262
|
-
const includeGenerated = params.includeGenerated === true;
|
|
263
|
-
let pathsScope;
|
|
264
|
-
try {
|
|
265
|
-
pathsScope = resolvePathsScope(cwd, params.paths);
|
|
266
|
-
} catch (err) {
|
|
267
|
-
return {
|
|
268
|
-
content: [
|
|
269
|
-
{
|
|
270
|
-
type: "text",
|
|
271
|
-
text: err instanceof Error ? err.message : String(err)
|
|
272
|
-
}
|
|
273
|
-
],
|
|
274
|
-
isError: true,
|
|
275
|
-
details: { mode, pathsError: true }
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
const abortSignal = combineAbortSignals(signal, ctx.signal);
|
|
279
|
-
await flushPending();
|
|
280
|
-
const staleDropped = await reconcileStaleWidgetFiles();
|
|
281
|
-
if (mode === "all") {
|
|
282
|
-
const dependencyGateStart = Date.now();
|
|
283
|
-
const { demoted: dependencyDemoted, truncatedImports } = await reconcileStaleWidgetDependencyBlockers(cwd, getRuntime?.()?.turnIndex);
|
|
284
|
-
logLatency({
|
|
285
|
-
type: "phase",
|
|
286
|
-
toolName: "lens_diagnostics",
|
|
287
|
-
filePath: cwd,
|
|
288
|
-
phase: "blocker_freshness_widget_gate",
|
|
289
|
-
durationMs: Date.now() - dependencyGateStart,
|
|
290
|
-
metadata: {
|
|
291
|
-
demoted: dependencyDemoted,
|
|
292
|
-
truncatedImports,
|
|
293
|
-
surface: "mode=all"
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
return formatAllMode(cwd, severity, undefined, undefined, staleDropped, pathsScope, dependencyDemoted);
|
|
297
|
-
}
|
|
298
|
-
if (mode === "full") {
|
|
299
|
-
const ceiling = AbortSignal.timeout(FULL_SCAN_WALL_CLOCK_MS);
|
|
300
|
-
const fullSignal = combineAbortSignals(abortSignal, ceiling);
|
|
301
|
-
const onProgress = makeProgressReporter(onUpdate);
|
|
302
|
-
return formatFullMode(cwd, severity, getLspService(), cacheManager, {
|
|
303
|
-
refreshRunners,
|
|
304
|
-
maxProjectFiles,
|
|
305
|
-
maxLspFiles,
|
|
306
|
-
includeGenerated,
|
|
307
|
-
signal: fullSignal,
|
|
308
|
-
wallClockMs: FULL_SCAN_WALL_CLOCK_MS,
|
|
309
|
-
onProgress,
|
|
310
|
-
onServerReady: repaintLspStatus,
|
|
311
|
-
pathsScope,
|
|
312
|
-
nextWriteIndex,
|
|
313
|
-
runtime: getRuntime?.(),
|
|
314
|
-
analysisRoot: typeof params.analysisRoot === "string" ? params.analysisRoot : undefined,
|
|
315
|
-
host: ctx.host ?? "pi"
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
return formatDeltaMode(cacheManager, cwd, severity, pathsScope);
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
function formatProjectDeltaDiagnostic(diagnostic, stale) {
|
|
323
|
-
const marker = stale ? "○" : diagnostic.semantic === "blocking" || diagnostic.severity === "error" ? "\uD83D\uDD34" : "ℹ";
|
|
324
|
-
const rule = diagnostic.rule ?? diagnostic.code ?? diagnostic.runner;
|
|
325
|
-
const where = stale ? STALE_LINE_MARKER : `L${diagnostic.line ?? "?"}`;
|
|
326
|
-
return ` ${marker} ${where} ${rule} ${diagnostic.message}`;
|
|
327
|
-
}
|
|
328
|
-
function appendProjectDiagnosticsDeltaLines(groups, cwd, report, severity, includeFile) {
|
|
329
|
-
const scoped = (report?.diagnostics ?? []).filter((diagnostic) => includeFile(diagnostic.filePath) && matchesSeverity(projectDiagnosticToWidget(diagnostic, diagnostic.filePath), severity));
|
|
330
|
-
const { "lens-diagnostics-delta-project": gated } = gateFindingsByPathFreshness({
|
|
331
|
-
cwd,
|
|
332
|
-
sources: {
|
|
333
|
-
"lens-diagnostics-delta-project": {
|
|
334
|
-
findings: scoped,
|
|
335
|
-
scannedAt: report?.generatedAt,
|
|
336
|
-
citedPath: (d) => d.filePath,
|
|
337
|
-
onMissing: "drop"
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
const staleSet = new Set(gated.stale);
|
|
342
|
-
const diagnostics = [...gated.live, ...gated.stale];
|
|
343
|
-
const byFile = new Map;
|
|
344
|
-
for (const diagnostic of diagnostics) {
|
|
345
|
-
const filePath = path.resolve(diagnostic.filePath);
|
|
346
|
-
const bucket = byFile.get(filePath) ?? [];
|
|
347
|
-
bucket.push(diagnostic);
|
|
348
|
-
byFile.set(filePath, bucket);
|
|
349
|
-
}
|
|
350
|
-
for (const [filePath, fileDiagnostics] of byFile) {
|
|
351
|
-
const group = getDeltaFileGroup(groups, cwd, filePath);
|
|
352
|
-
for (const diagnostic of fileDiagnostics) {
|
|
353
|
-
group.projectLines.push(formatProjectDeltaDiagnostic(diagnostic, staleSet.has(diagnostic)));
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
return diagnostics.length;
|
|
357
|
-
}
|
|
358
|
-
export const CACHED_CONTENT_MEMO_CAP = 64;
|
|
359
|
-
const cachedContentMemo = new BoundedLruCache(CACHED_CONTENT_MEMO_CAP);
|
|
360
|
-
function readContentForAnchors(filePath, stat) {
|
|
361
|
-
const key = normalizeEphemeralMapKey(filePath);
|
|
362
|
-
const hit = cachedContentMemo.get(key);
|
|
363
|
-
if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size) {
|
|
364
|
-
return hit.content;
|
|
365
|
-
}
|
|
366
|
-
let content;
|
|
367
|
-
try {
|
|
368
|
-
content = fsSync.readFileSync(filePath, "utf-8");
|
|
369
|
-
} catch {
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
cachedContentMemo.set(key, {
|
|
373
|
-
mtimeMs: stat.mtimeMs,
|
|
374
|
-
size: stat.size,
|
|
375
|
-
content
|
|
376
|
-
});
|
|
377
|
-
return content;
|
|
378
|
-
}
|
|
379
|
-
export function _readContentForAnchorsForTests(filePath, stat) {
|
|
380
|
-
return readContentForAnchors(filePath, stat);
|
|
381
|
-
}
|
|
382
|
-
function applyCachedDispositions(cachedDiagnostics, cwd, filePath) {
|
|
383
|
-
if (!hasAnyDispositionMarks(cwd))
|
|
384
|
-
return cachedDiagnostics;
|
|
385
|
-
if (!hasStrictDispositionMarks(cwd)) {
|
|
386
|
-
return applyWeakDispositions(cachedDiagnostics, cwd, filePath);
|
|
387
|
-
}
|
|
388
|
-
let stat;
|
|
389
|
-
try {
|
|
390
|
-
stat = fsSync.statSync(filePath);
|
|
391
|
-
} catch {
|
|
392
|
-
return applyWeakDispositions(cachedDiagnostics, cwd, filePath);
|
|
393
|
-
}
|
|
394
|
-
const referenceMs = cachedDiagnostics.reduce((latest, d) => Math.max(latest, d.observedAt ?? 0), 0);
|
|
395
|
-
if (referenceMs > 0 && freshnessFromMtime({ mtimeMs: stat.mtimeMs, referenceMs }).verdict === "stale") {
|
|
396
|
-
return applyWeakDispositions(cachedDiagnostics, cwd, filePath);
|
|
397
|
-
}
|
|
398
|
-
const content = readContentForAnchors(filePath, stat);
|
|
399
|
-
if (content === undefined) {
|
|
400
|
-
return applyWeakDispositions(cachedDiagnostics, cwd, filePath);
|
|
401
|
-
}
|
|
402
|
-
return applyDispositions(cachedDiagnostics, cwd, filePath, content);
|
|
403
|
-
}
|
|
404
|
-
function filterDeltaReportDispositions(report, cwd, policyMap) {
|
|
405
|
-
if (!report?.diagnostics.length)
|
|
406
|
-
return report;
|
|
407
|
-
const kept = report.diagnostics.filter((d) => applyCachedDispositions([projectDiagnosticToWidget(d, d.filePath)], cwd, d.filePath).length === 1);
|
|
408
|
-
const policyKept = applyRulePolicy(kept, policyMap);
|
|
409
|
-
if (policyKept.length === report.diagnostics.length)
|
|
410
|
-
return report;
|
|
411
|
-
return { ...report, diagnostics: policyKept };
|
|
412
|
-
}
|
|
413
|
-
function applyDeltaFreshnessGate(files, cwd, generatedAt) {
|
|
414
|
-
const stamps = new Set(files.map((file) => file.generatedAt ?? generatedAt ?? ""));
|
|
415
|
-
if (stamps.size > 1) {
|
|
416
|
-
const gatedByPath = new Map;
|
|
417
|
-
for (const stamp of stamps) {
|
|
418
|
-
const group = files.filter((file) => (file.generatedAt ?? generatedAt ?? "") === stamp);
|
|
419
|
-
for (const gated of applyDeltaFreshnessGate(group.map((file) => ({
|
|
420
|
-
filePath: file.filePath,
|
|
421
|
-
warnings: file.warnings
|
|
422
|
-
})), cwd, stamp === "" ? undefined : stamp)) {
|
|
423
|
-
gatedByPath.set(gated.filePath, gated);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
return files.map((file) => gatedByPath.get(file.filePath)).filter((entry) => entry !== undefined);
|
|
427
|
-
}
|
|
428
|
-
const stampedAt = [...stamps][0];
|
|
429
|
-
const effectiveAt = stampedAt !== undefined && stampedAt !== "" ? stampedAt : generatedAt;
|
|
430
|
-
if (!effectiveAt)
|
|
431
|
-
return files;
|
|
432
|
-
const flat = [];
|
|
433
|
-
for (const file of files) {
|
|
434
|
-
for (const warning of file.warnings)
|
|
435
|
-
flat.push({ filePath: file.filePath, warning });
|
|
436
|
-
}
|
|
437
|
-
if (flat.length === 0)
|
|
438
|
-
return files;
|
|
439
|
-
const { "lens-diagnostics-delta": gated } = gateFindingsByPathFreshness({
|
|
440
|
-
cwd,
|
|
441
|
-
sources: {
|
|
442
|
-
"lens-diagnostics-delta": {
|
|
443
|
-
findings: flat,
|
|
444
|
-
scannedAt: effectiveAt,
|
|
445
|
-
citedPath: (f) => f.filePath,
|
|
446
|
-
onMissing: "drop"
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
const byFile = new Map;
|
|
451
|
-
for (const f of gated.live) {
|
|
452
|
-
const arr = byFile.get(f.filePath) ?? [];
|
|
453
|
-
arr.push(f.warning);
|
|
454
|
-
byFile.set(f.filePath, arr);
|
|
455
|
-
}
|
|
456
|
-
for (const f of gated.stale) {
|
|
457
|
-
const arr = byFile.get(f.filePath) ?? [];
|
|
458
|
-
arr.push({
|
|
459
|
-
...f.warning,
|
|
460
|
-
stale: true,
|
|
461
|
-
line: undefined,
|
|
462
|
-
staleAsOf: effectiveAt
|
|
463
|
-
});
|
|
464
|
-
byFile.set(f.filePath, arr);
|
|
465
|
-
}
|
|
466
|
-
return files.map((file) => ({
|
|
467
|
-
filePath: file.filePath,
|
|
468
|
-
warnings: byFile.get(file.filePath) ?? []
|
|
469
|
-
})).filter((file) => file.warnings.length > 0);
|
|
470
|
-
}
|
|
471
|
-
function getDeltaFileGroup(groups, cwd, filePath) {
|
|
472
|
-
const rel = path.relative(cwd, filePath);
|
|
473
|
-
let group = groups.get(rel);
|
|
474
|
-
if (!group) {
|
|
475
|
-
group = {
|
|
476
|
-
rel,
|
|
477
|
-
actionableLines: [],
|
|
478
|
-
qualityLines: [],
|
|
479
|
-
projectLines: [],
|
|
480
|
-
incomplete: false
|
|
481
|
-
};
|
|
482
|
-
groups.set(rel, group);
|
|
483
|
-
}
|
|
484
|
-
return group;
|
|
485
|
-
}
|
|
486
|
-
function formatDeltaMode(cacheManager, cwd, severity, pathsScope) {
|
|
487
|
-
const actionableEntry = cacheManager.readCache("actionable-warnings", cwd);
|
|
488
|
-
const qualityEntry = cacheManager.readCache("code-quality-warnings", cwd);
|
|
489
|
-
const reverifyIncompletePaths = new Set((actionableEntry?.data?.files ?? []).filter((file) => file.reVerifyIncomplete).map((file) => normalizeMapKey(file.filePath)));
|
|
490
|
-
const actionable = actionableEntry?.data;
|
|
491
|
-
const quality = qualityEntry?.data;
|
|
492
|
-
const policyMap = loadProjectRulePolicyMap(cwd);
|
|
493
|
-
const projectDelta = filterDeltaReportDispositions(loadProjectDiagnosticsDeltaReport(cwd), cwd, policyMap);
|
|
494
|
-
const includeFile = createScopedFileFilter(cwd, pathsScope);
|
|
495
|
-
const visibleWarningFiles = (files) => (files ?? []).filter((file) => includeFile(file.filePath)).map((file) => ({
|
|
496
|
-
filePath: file.filePath,
|
|
497
|
-
generatedAt: file.generatedAt,
|
|
498
|
-
warnings: applyRulePolicy(applyCachedDispositions(file.warnings ?? [], cwd, file.filePath), policyMap)
|
|
499
|
-
})).filter((file) => file.warnings.length > 0);
|
|
500
|
-
const actionableFiles = applyDeltaFreshnessGate(visibleWarningFiles(actionable?.files), cwd, actionable?.generatedAt);
|
|
501
|
-
const qualityFiles = applyDeltaFreshnessGate(visibleWarningFiles(quality?.files), cwd, quality?.generatedAt);
|
|
502
|
-
const matchingWarnings = (warnings) => warnings.filter((warning) => matchesRecordSeverity(warning.severity, severity));
|
|
503
|
-
const filteredActionableFiles = actionableFiles.map((file) => ({
|
|
504
|
-
...file,
|
|
505
|
-
warnings: matchingWarnings(file.warnings)
|
|
506
|
-
})).filter((file) => file.warnings.length > 0);
|
|
507
|
-
const filteredQualityFiles = qualityFiles.map((file) => ({
|
|
508
|
-
...file,
|
|
509
|
-
warnings: matchingWarnings(file.warnings)
|
|
510
|
-
})).filter((file) => file.warnings.length > 0);
|
|
511
|
-
const groups = new Map;
|
|
512
|
-
if (filteredActionableFiles.length > 0) {
|
|
513
|
-
for (const file of filteredActionableFiles) {
|
|
514
|
-
const group = getDeltaFileGroup(groups, cwd, file.filePath);
|
|
515
|
-
for (const w of file.warnings) {
|
|
516
|
-
const where = w.stale ? STALE_LINE_MARKER : `L${w.line ?? "?"}`;
|
|
517
|
-
group.actionableLines.push(` ⚠ ${where} ${w.rule ?? w.code ?? w.tool} ${w.message}`);
|
|
518
|
-
}
|
|
519
|
-
const key = normalizeMapKey(file.filePath);
|
|
520
|
-
if (reverifyIncompletePaths.has(key))
|
|
521
|
-
group.incomplete = true;
|
|
522
|
-
if (!group.staleRow) {
|
|
523
|
-
const staleWarning = file.warnings.find((w) => w.stale);
|
|
524
|
-
if (staleWarning)
|
|
525
|
-
group.staleRow = { staleAsOf: staleWarning.staleAsOf };
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (filteredQualityFiles.length > 0) {
|
|
530
|
-
for (const file of filteredQualityFiles) {
|
|
531
|
-
const group = getDeltaFileGroup(groups, cwd, file.filePath);
|
|
532
|
-
for (const w of file.warnings) {
|
|
533
|
-
const where = w.stale ? STALE_LINE_MARKER : `L${w.line ?? "?"}`;
|
|
534
|
-
group.qualityLines.push(` ℹ ${where} ${w.rule ?? w.code ?? w.tool} ${w.message}`);
|
|
535
|
-
}
|
|
536
|
-
const key = normalizeMapKey(file.filePath);
|
|
537
|
-
if (reverifyIncompletePaths.has(key))
|
|
538
|
-
group.incomplete = true;
|
|
539
|
-
if (!group.staleRow) {
|
|
540
|
-
const staleWarning = file.warnings.find((w) => w.stale);
|
|
541
|
-
if (staleWarning)
|
|
542
|
-
group.staleRow = { staleAsOf: staleWarning.staleAsOf };
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
const projectDeltaCount = appendProjectDiagnosticsDeltaLines(groups, cwd, projectDelta, severity, includeFile);
|
|
547
|
-
const lines = [];
|
|
548
|
-
for (const group of groups.values()) {
|
|
549
|
-
lines.push(group.rel);
|
|
550
|
-
lines.push(...group.actionableLines);
|
|
551
|
-
lines.push(...group.qualityLines);
|
|
552
|
-
lines.push(...group.projectLines);
|
|
553
|
-
if (group.staleRow) {
|
|
554
|
-
lines.push(` (${formatCacheAgeLabel(group.staleRow.staleAsOf)})`);
|
|
555
|
-
}
|
|
556
|
-
if (group.incomplete)
|
|
557
|
-
lines.push(" (re-verify incomplete)");
|
|
558
|
-
}
|
|
559
|
-
const selectedActionableFiles = filteredActionableFiles;
|
|
560
|
-
const selectedQualityFiles = filteredQualityFiles;
|
|
561
|
-
const aw = selectedActionableFiles.reduce((count, file) => count + file.warnings.length, 0);
|
|
562
|
-
const cq = selectedQualityFiles.reduce((count, file) => count + file.warnings.length, 0);
|
|
563
|
-
if (lines.length === 0) {
|
|
564
|
-
let text = `No ${severity === "all" ? "" : severity + " "}issues in the current turn delta.`;
|
|
565
|
-
const carried = getFileDiagnosticSummaries().filter((f) => includeFile(f.filePath)).map((f) => ({
|
|
566
|
-
...f,
|
|
567
|
-
diagnostics: applyRulePolicy(applyCachedDispositions(f.diagnostics, cwd, f.filePath), policyMap)
|
|
568
|
-
})).filter((f) => f.diagnostics.length > 0);
|
|
569
|
-
const carriedIssues = carried.reduce((n, f) => n + f.diagnostics.length, 0);
|
|
570
|
-
if (carried.length > 0) {
|
|
571
|
-
text += ` ${carriedIssues} finding${carriedIssues === 1 ? "" : "s"} across ${carried.length} file${carried.length === 1 ? "" : "s"} carried over from earlier this session — use mode=all to see them.`;
|
|
572
|
-
}
|
|
573
|
-
text += pathsScopeCacheOnlyNote(pathsScope);
|
|
574
|
-
return {
|
|
575
|
-
content: [{ type: "text", text }],
|
|
576
|
-
details: { mode: "delta", warnings: 0, carriedOverFiles: carried.length }
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
const summary = `
|
|
580
|
-
Summary (turn delta): ${aw} actionable warning${aw === 1 ? "" : "s"} · ${cq} quality issue${cq === 1 ? "" : "s"} · ${projectDeltaCount} project diagnostic${projectDeltaCount === 1 ? "" : "s"}`;
|
|
581
|
-
return {
|
|
582
|
-
content: [{ type: "text", text: lines.join(`
|
|
583
|
-
`) + summary }],
|
|
584
|
-
details: {
|
|
585
|
-
mode: "delta",
|
|
586
|
-
actionableWarnings: aw,
|
|
587
|
-
qualityIssues: cq,
|
|
588
|
-
projectDiagnostics: projectDeltaCount
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
function createCurrentIgnoreFilter(cwd) {
|
|
593
|
-
try {
|
|
594
|
-
const matcher = getProjectIgnoreMatcher(cwd);
|
|
595
|
-
return (filePath) => !matcher.isIgnored(path.resolve(filePath), false);
|
|
596
|
-
} catch {
|
|
597
|
-
return () => true;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
function resolvePathsScope(cwd, rawPaths) {
|
|
601
|
-
if (!Array.isArray(rawPaths) || rawPaths.length === 0)
|
|
602
|
-
return;
|
|
603
|
-
if (rawPaths.length > MAX_PATHS_ENTRIES) {
|
|
604
|
-
throw new Error(`paths has ${rawPaths.length} entries, over the ${MAX_PATHS_ENTRIES} cap. ` + "Narrow the list or omit paths to scan without a restriction.");
|
|
605
|
-
}
|
|
606
|
-
const entries = rawPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0).map((entry) => path.resolve(path.isAbsolute(entry) ? entry : path.resolve(cwd, entry)));
|
|
607
|
-
const missing = [];
|
|
608
|
-
const fileEntries = [];
|
|
609
|
-
const existingEntries = [];
|
|
610
|
-
const dirEntries = [];
|
|
611
|
-
for (const entry of entries) {
|
|
612
|
-
let stat;
|
|
613
|
-
try {
|
|
614
|
-
stat = fsSync.statSync(entry);
|
|
615
|
-
} catch {
|
|
616
|
-
missing.push(entry);
|
|
617
|
-
fileEntries.push(entry);
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
|
-
if (stat.isDirectory()) {
|
|
621
|
-
dirEntries.push(entry);
|
|
622
|
-
} else {
|
|
623
|
-
fileEntries.push(entry);
|
|
624
|
-
existingEntries.push(entry);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
const fileKeys = new Set(fileEntries.map((f) => normalizeFilePath(f)));
|
|
628
|
-
const dirPrefixes = dirEntries.map((d) => normalizeFilePath(d));
|
|
629
|
-
const includeExplicitFile = (filePath) => fileKeys.has(normalizeFilePath(path.resolve(filePath)));
|
|
630
|
-
const includeFile = (filePath) => {
|
|
631
|
-
const key = normalizeFilePath(path.resolve(filePath));
|
|
632
|
-
if (fileKeys.has(key))
|
|
633
|
-
return true;
|
|
634
|
-
return dirPrefixes.some((prefix) => key === prefix || key.startsWith(`${prefix}/`));
|
|
635
|
-
};
|
|
636
|
-
return {
|
|
637
|
-
includeFile,
|
|
638
|
-
includeExplicitFile,
|
|
639
|
-
missing,
|
|
640
|
-
existingEntries,
|
|
641
|
-
hasDirectoryEntries: dirEntries.length > 0
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
function pathsScopeCacheOnlyNote(scope) {
|
|
645
|
-
if (!scope)
|
|
646
|
-
return "";
|
|
647
|
-
return `
|
|
648
|
-
|
|
649
|
-
Note: paths restricts this to cached findings for files dm-lens has ` + "already dispatched this session — mode=delta/all can't see files it " + "hasn't touched. Use mode=full to actively scan exactly these paths.";
|
|
650
|
-
}
|
|
651
|
-
function pathsScopeMissingNote(scope) {
|
|
652
|
-
if (!scope || scope.missing.length === 0)
|
|
653
|
-
return "";
|
|
654
|
-
const shown = scope.missing.slice(0, 10).map((p) => path.basename(p));
|
|
655
|
-
const more = scope.missing.length > shown.length ? ` (+${scope.missing.length - shown.length} more)` : "";
|
|
656
|
-
return `
|
|
657
|
-
|
|
658
|
-
⚠ Skipped ${scope.missing.length} path(s) not found on disk: ${shown.join(", ")}${more}`;
|
|
659
|
-
}
|
|
660
|
-
function createScopedFileFilter(cwd, pathsScope) {
|
|
661
|
-
const ignoreFile = createCurrentIgnoreFilter(cwd);
|
|
662
|
-
return (filePath) => {
|
|
663
|
-
if (!pathsScope)
|
|
664
|
-
return ignoreFile(filePath);
|
|
665
|
-
if (!pathsScope.includeFile(filePath))
|
|
666
|
-
return false;
|
|
667
|
-
return pathsScope.includeExplicitFile(filePath) || ignoreFile(filePath);
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
function filterProjectDiagnosticsSnapshot(snapshot, includeFile) {
|
|
671
|
-
if (!snapshot)
|
|
672
|
-
return;
|
|
673
|
-
return {
|
|
674
|
-
...snapshot,
|
|
675
|
-
diagnostics: snapshot.diagnostics.filter((d) => includeFile(d.filePath))
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
function filterProjectDiagnosticsDeltaReport(report, includeFile) {
|
|
679
|
-
if (!report)
|
|
680
|
-
return;
|
|
681
|
-
return {
|
|
682
|
-
...report,
|
|
683
|
-
diagnostics: report.diagnostics.filter((d) => includeFile(d.filePath))
|
|
684
|
-
};
|
|
685
|
-
}
|
|
686
|
-
function applyProjectRulePolicy(value, policyMap) {
|
|
687
|
-
if (!value)
|
|
688
|
-
return;
|
|
689
|
-
return {
|
|
690
|
-
...value,
|
|
691
|
-
diagnostics: applyRulePolicy(value.diagnostics, policyMap)
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
function isErrorLike(d) {
|
|
695
|
-
if (d.stale)
|
|
696
|
-
return false;
|
|
697
|
-
return d.semantic === "blocking" || d.severity === "error";
|
|
698
|
-
}
|
|
699
|
-
function matchesSeverity(d, severity) {
|
|
700
|
-
return matchesRecordSeverity(isErrorLike(d) ? "error" : d.severity, severity);
|
|
701
|
-
}
|
|
702
|
-
function matchesRecordSeverity(recordSeverity, requested) {
|
|
703
|
-
if (requested === "all")
|
|
704
|
-
return true;
|
|
705
|
-
if (requested === "error")
|
|
706
|
-
return recordSeverity === "error";
|
|
707
|
-
if (requested === "warning")
|
|
708
|
-
return recordSeverity === "error" || recordSeverity === "warning";
|
|
709
|
-
if (requested === "information")
|
|
710
|
-
return recordSeverity === "error" || recordSeverity === "warning" || recordSeverity === "info" || recordSeverity === "note" || recordSeverity === "help";
|
|
711
|
-
if (requested === "hint")
|
|
712
|
-
return recordSeverity === "error" || recordSeverity === "warning" || recordSeverity === "info" || recordSeverity === "note" || recordSeverity === "help" || recordSeverity === "hint";
|
|
713
|
-
return true;
|
|
714
|
-
}
|
|
715
|
-
function severityRank(d) {
|
|
716
|
-
if (d.semantic === "blocking")
|
|
717
|
-
return 0;
|
|
718
|
-
if (d.severity === "error")
|
|
719
|
-
return 1;
|
|
720
|
-
if (d.severity === "warning")
|
|
721
|
-
return 2;
|
|
722
|
-
return 3;
|
|
723
|
-
}
|
|
724
|
-
function bySeverityThenLine(a, b) {
|
|
725
|
-
return severityRank(a) - severityRank(b) || (a.line ?? 0) - (b.line ?? 0);
|
|
726
|
-
}
|
|
727
|
-
function lspSeverityName(severity) {
|
|
728
|
-
if (severity === 1)
|
|
729
|
-
return "error";
|
|
730
|
-
if (severity === 2)
|
|
731
|
-
return "warning";
|
|
732
|
-
if (severity === 3)
|
|
733
|
-
return "info";
|
|
734
|
-
return "hint";
|
|
735
|
-
}
|
|
736
|
-
function lspRuleId(diagnostic) {
|
|
737
|
-
const code = diagnostic.code === undefined ? undefined : String(diagnostic.code);
|
|
738
|
-
if (diagnostic.source && code)
|
|
739
|
-
return `${diagnostic.source}:${code}`;
|
|
740
|
-
return diagnostic.source ?? code ?? "lsp";
|
|
741
|
-
}
|
|
742
|
-
function lspDiagnosticToWidget(diagnostic) {
|
|
743
|
-
const severity = lspSeverityName(diagnostic.severity);
|
|
744
|
-
const rule = lspRuleId(diagnostic);
|
|
745
|
-
return {
|
|
746
|
-
severity,
|
|
747
|
-
semantic: diagnostic.severity === 1 ? "blocking" : "warning",
|
|
748
|
-
message: diagnostic.message,
|
|
749
|
-
line: diagnostic.range.start.line + 1,
|
|
750
|
-
col: diagnostic.range.start.character + 1,
|
|
751
|
-
rule,
|
|
752
|
-
tool: findAuxiliaryProfileForSource(diagnostic.source)?.tool ?? "lsp"
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
function projectDiagnosticToWidget(diagnostic, filePath) {
|
|
756
|
-
return {
|
|
757
|
-
severity: diagnostic.severity,
|
|
758
|
-
semantic: diagnostic.semantic,
|
|
759
|
-
message: diagnostic.message,
|
|
760
|
-
line: diagnostic.line,
|
|
761
|
-
col: diagnostic.column,
|
|
762
|
-
rule: diagnostic.rule ?? diagnostic.code,
|
|
763
|
-
tool: diagnostic.runner || diagnostic.tool,
|
|
764
|
-
uri: widgetDiagnosticUri(filePath, diagnostic.line, diagnostic.column)
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
function diagnosticDedupKey(filePath, diagnostic) {
|
|
768
|
-
const ruleId = normalizeRuleId(diagnostic.rule ?? diagnostic.tool ?? "");
|
|
769
|
-
return [path.resolve(filePath), diagnostic.line ?? "?", ruleId].join(":");
|
|
770
|
-
}
|
|
771
|
-
function runnerIdOf(diagnostic) {
|
|
772
|
-
return diagnostic.tool ?? diagnostic.rule?.split(":", 1)[0] ?? "";
|
|
773
|
-
}
|
|
774
|
-
export function runnerRetirementDecision(diagnostic, filePath, authoritativeRunnerIds, authoritativeCoverage) {
|
|
775
|
-
const runnerId = runnerIdOf(diagnostic);
|
|
776
|
-
const coverage = (authoritativeCoverage ?? []).filter((entry) => entry.runnerId === runnerId);
|
|
777
|
-
if (coverage.length === 0) {
|
|
778
|
-
return authoritativeRunnerIds?.has(runnerId) ? "retire" : "keep";
|
|
779
|
-
}
|
|
780
|
-
const realFilePath = realpathOrResolve(filePath);
|
|
781
|
-
for (const entry of coverage) {
|
|
782
|
-
const root = entry.root;
|
|
783
|
-
const relative = path.relative(root, realFilePath);
|
|
784
|
-
const underRoot = relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
785
|
-
if (!underRoot)
|
|
786
|
-
continue;
|
|
787
|
-
if (entry.files.has(realFilePath)) {
|
|
788
|
-
return "retire";
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
return "keep";
|
|
792
|
-
}
|
|
793
|
-
function summarizeDiagnostics(filePath, diagnostics, hasFinalSnapshot) {
|
|
794
|
-
let blocking = 0;
|
|
795
|
-
let errors = 0;
|
|
796
|
-
let warnings = 0;
|
|
797
|
-
let advisories = 0;
|
|
798
|
-
for (const diagnostic of diagnostics) {
|
|
799
|
-
if (diagnostic.stale)
|
|
800
|
-
continue;
|
|
801
|
-
if (diagnostic.semantic === "blocking")
|
|
802
|
-
blocking++;
|
|
803
|
-
const tier = classifyDiagnosticTier(diagnostic);
|
|
804
|
-
if (tier === "error")
|
|
805
|
-
errors++;
|
|
806
|
-
else if (tier === "warning")
|
|
807
|
-
warnings++;
|
|
808
|
-
else if (tier === "advisory")
|
|
809
|
-
advisories++;
|
|
810
|
-
}
|
|
811
|
-
return {
|
|
812
|
-
filePath,
|
|
813
|
-
blocking,
|
|
814
|
-
errors,
|
|
815
|
-
warnings,
|
|
816
|
-
advisories,
|
|
817
|
-
hasFinalSnapshot,
|
|
818
|
-
diagnostics
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
const UNCONFIRMED_REASON_SENTENCE = {
|
|
822
|
-
budget: "check didn't complete within budget",
|
|
823
|
-
inconclusive: "check was inconclusive (notify-write or diagnostics wait timed out)",
|
|
824
|
-
coverage_gap: "an auxiliary scanner coverage gap",
|
|
825
|
-
service_destroyed: "the LSP service was reset mid-sweep",
|
|
826
|
-
error: "check errored",
|
|
827
|
-
binding_mismatch: "the file changed on disk since this result was computed",
|
|
828
|
-
outside_project_root: "the file is outside every initialized session project root, so no language server was asked"
|
|
829
|
-
};
|
|
830
|
-
const UNCONFIRMED_REASON_COUNT_LABEL = {
|
|
831
|
-
budget: "timed out",
|
|
832
|
-
inconclusive: "inconclusive",
|
|
833
|
-
coverage_gap: "coverage gap",
|
|
834
|
-
service_destroyed: "service reset mid-sweep",
|
|
835
|
-
error: "errored",
|
|
836
|
-
binding_mismatch: "stale binding",
|
|
837
|
-
outside_project_root: "outside project root"
|
|
838
|
-
};
|
|
839
|
-
function classifyUnconfirmedReason(result, mismatched) {
|
|
840
|
-
if (mismatched.has(result))
|
|
841
|
-
return "binding_mismatch";
|
|
842
|
-
return result.unconfirmedReason ?? (result.error ? "error" : "budget");
|
|
843
|
-
}
|
|
844
|
-
function tallyUnconfirmedReasons(results, mismatched) {
|
|
845
|
-
const tally = new Map;
|
|
846
|
-
for (const result of results) {
|
|
847
|
-
const reason = classifyUnconfirmedReason(result, mismatched);
|
|
848
|
-
tally.set(reason, (tally.get(reason) ?? 0) + 1);
|
|
849
|
-
}
|
|
850
|
-
return tally;
|
|
851
|
-
}
|
|
852
|
-
function formatUnconfirmedReasonClause(tally) {
|
|
853
|
-
const entries = [...tally.entries()].filter(([, count]) => count > 0);
|
|
854
|
-
if (entries.length === 0)
|
|
855
|
-
return "";
|
|
856
|
-
if (entries.length === 1) {
|
|
857
|
-
return UNCONFIRMED_REASON_SENTENCE[entries[0][0]];
|
|
858
|
-
}
|
|
859
|
-
return entries.map(([reason, count]) => `${count} ${UNCONFIRMED_REASON_COUNT_LABEL[reason]}`).join(", ");
|
|
860
|
-
}
|
|
861
|
-
function tallyLspByPrimaryServer(confirmed, unconfirmed) {
|
|
862
|
-
const byServer = new Map;
|
|
863
|
-
const bump = (filePath, wasConfirmed) => {
|
|
864
|
-
const id = primaryServerId(filePath) ?? "unknown";
|
|
865
|
-
const entry = byServer.get(id) ?? { confirmed: 0, total: 0 };
|
|
866
|
-
entry.total += 1;
|
|
867
|
-
if (wasConfirmed)
|
|
868
|
-
entry.confirmed += 1;
|
|
869
|
-
byServer.set(id, entry);
|
|
870
|
-
};
|
|
871
|
-
for (const result of confirmed)
|
|
872
|
-
bump(result.filePath, true);
|
|
873
|
-
for (const result of unconfirmed)
|
|
874
|
-
bump(result.filePath, false);
|
|
875
|
-
return byServer;
|
|
876
|
-
}
|
|
877
|
-
function formatLspServerBreakdown(byServer) {
|
|
878
|
-
return [...byServer.entries()].sort((a, b) => {
|
|
879
|
-
const rateA = a[1].confirmed / a[1].total;
|
|
880
|
-
const rateB = b[1].confirmed / b[1].total;
|
|
881
|
-
return rateA - rateB;
|
|
882
|
-
}).map(([id, { confirmed, total }]) => `${id}: ${confirmed}/${total}`).join(", ");
|
|
883
|
-
}
|
|
884
|
-
function tallyLspPrimaryVsAuxiliary(results) {
|
|
885
|
-
let primary = 0;
|
|
886
|
-
let auxiliary = 0;
|
|
887
|
-
for (const result of results) {
|
|
888
|
-
const primaryId = primaryServerId(result.filePath);
|
|
889
|
-
for (const diagnostic of result.diagnostics ?? []) {
|
|
890
|
-
if (diagnostic.serverId === primaryId)
|
|
891
|
-
primary += 1;
|
|
892
|
-
else
|
|
893
|
-
auxiliary += 1;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
return { primary, auxiliary };
|
|
897
|
-
}
|
|
898
|
-
function mergeDiagnosticsWithWidgetSummaries(widgetSummaries, lspResults, projectSnapshot, projectDelta, authoritativeLspFiles, authoritativeRunnerIds, authoritativeRunnerCoverage) {
|
|
899
|
-
const byFile = new Map;
|
|
900
|
-
const seen = new Set;
|
|
901
|
-
for (const summary of widgetSummaries) {
|
|
902
|
-
const filePath = path.resolve(summary.filePath);
|
|
903
|
-
if (authoritativeLspFiles?.has(filePath))
|
|
904
|
-
continue;
|
|
905
|
-
const retained = summary.diagnostics ?? [];
|
|
906
|
-
const diagnostics = retained.filter((diagnostic) => runnerRetirementDecision(diagnostic, filePath, authoritativeRunnerIds, authoritativeRunnerCoverage) !== "retire").map((d) => ({ ...d }));
|
|
907
|
-
byFile.set(filePath, diagnostics.length === retained.length ? { ...summary, filePath, diagnostics } : summarizeDiagnostics(filePath, diagnostics, summary.hasFinalSnapshot ?? true));
|
|
908
|
-
for (const diagnostic of diagnostics) {
|
|
909
|
-
seen.add(diagnosticDedupKey(filePath, diagnostic));
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
const addDiagnostic = (filePath, widgetDiagnostic) => {
|
|
913
|
-
const existing = byFile.get(filePath);
|
|
914
|
-
const diagnostics = existing ? [...existing.diagnostics] : [];
|
|
915
|
-
const key = diagnosticDedupKey(filePath, widgetDiagnostic);
|
|
916
|
-
if (seen.has(key))
|
|
917
|
-
return;
|
|
918
|
-
seen.add(key);
|
|
919
|
-
diagnostics.push(widgetDiagnostic);
|
|
920
|
-
byFile.set(filePath, summarizeDiagnostics(filePath, diagnostics, existing?.hasFinalSnapshot ?? true));
|
|
921
|
-
};
|
|
922
|
-
for (const result of lspResults) {
|
|
923
|
-
const filePath = path.resolve(result.filePath);
|
|
924
|
-
for (const diagnostic of result.diagnostics ?? []) {
|
|
925
|
-
addDiagnostic(filePath, lspDiagnosticToWidget(diagnostic));
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
for (const diagnostic of projectSnapshot?.diagnostics ?? []) {
|
|
929
|
-
addDiagnostic(path.resolve(diagnostic.filePath), projectDiagnosticToWidget(diagnostic, diagnostic.filePath));
|
|
930
|
-
}
|
|
931
|
-
for (const diagnostic of projectDelta?.diagnostics ?? []) {
|
|
932
|
-
addDiagnostic(path.resolve(diagnostic.filePath), projectDiagnosticToWidget(diagnostic, diagnostic.filePath));
|
|
933
|
-
}
|
|
934
|
-
return [...byFile.values()];
|
|
935
|
-
}
|
|
936
|
-
async function applyInlineSuppressionsToSummaries(summaries, cwd, policyMap) {
|
|
937
|
-
return Promise.all(summaries.map(async (summary) => {
|
|
938
|
-
if (!summary.diagnostics.length)
|
|
939
|
-
return summary;
|
|
940
|
-
let content;
|
|
941
|
-
try {
|
|
942
|
-
content = await fs.readFile(summary.filePath, "utf8");
|
|
943
|
-
} catch {
|
|
944
|
-
const policyKept = applyRulePolicy(summary.diagnostics, policyMap);
|
|
945
|
-
return policyKept.length === summary.diagnostics.length ? summary : summarizeDiagnostics(summary.filePath, policyKept, summary.hasFinalSnapshot);
|
|
946
|
-
}
|
|
947
|
-
const { kept: policyKept } = applyFindingPolicy(summary.diagnostics, {
|
|
948
|
-
cwd,
|
|
949
|
-
filePath: summary.filePath,
|
|
950
|
-
content,
|
|
951
|
-
policyMap
|
|
952
|
-
});
|
|
953
|
-
for (const d of policyKept) {
|
|
954
|
-
const { weak } = anchorsForDiagnostic(cwd, summary.filePath, d, content);
|
|
955
|
-
if (getDisposition(cwd, weak)?.disposition === "flagged") {
|
|
956
|
-
d.flagged = true;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
if (policyKept.length === summary.diagnostics.length)
|
|
960
|
-
return summary;
|
|
961
|
-
return summarizeDiagnostics(summary.filePath, policyKept, summary.hasFinalSnapshot);
|
|
962
|
-
}));
|
|
963
|
-
}
|
|
964
|
-
function shouldUseCachedProjectDiagnostics(value) {
|
|
965
|
-
return value === "cached";
|
|
966
|
-
}
|
|
967
|
-
function shouldRefreshProjectDiagnostics(value) {
|
|
968
|
-
return value === "cheap" || value === "all";
|
|
969
|
-
}
|
|
970
|
-
function shouldIncludeProjectRunners(value) {
|
|
971
|
-
return shouldRefreshProjectDiagnostics(value) || value === "cached";
|
|
972
|
-
}
|
|
973
|
-
function foldExtraDiagnosticsIntoSnapshot(snapshot, extra, runners, cwd) {
|
|
974
|
-
if (extra.length === 0)
|
|
975
|
-
return snapshot;
|
|
976
|
-
if (snapshot) {
|
|
977
|
-
const merged = new Set([...snapshot.runners, ...runners]);
|
|
978
|
-
return {
|
|
979
|
-
...snapshot,
|
|
980
|
-
diagnostics: [...snapshot.diagnostics, ...extra],
|
|
981
|
-
runners: [...merged]
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
return {
|
|
985
|
-
version: PROJECT_DIAGNOSTICS_CACHE_VERSION,
|
|
986
|
-
cwd,
|
|
987
|
-
tier: "all",
|
|
988
|
-
scannedAt: new Date().toISOString(),
|
|
989
|
-
diagnostics: extra,
|
|
990
|
-
filesScanned: 0,
|
|
991
|
-
runners
|
|
992
|
-
};
|
|
993
|
-
}
|
|
994
|
-
async function getProjectDiagnosticsSnapshotForFullMode(cwd, options) {
|
|
995
|
-
if (shouldRefreshProjectDiagnostics(options.refreshRunners)) {
|
|
996
|
-
return scanProjectDiagnostics({
|
|
997
|
-
cwd,
|
|
998
|
-
tier: "cheap",
|
|
999
|
-
maxFiles: options.maxProjectFiles,
|
|
1000
|
-
signal: options.signal,
|
|
1001
|
-
files: options.files,
|
|
1002
|
-
includeGenerated: options.includeGenerated
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
if (shouldUseCachedProjectDiagnostics(options.refreshRunners)) {
|
|
1006
|
-
const cached = loadProjectDiagnosticsSnapshot(cwd);
|
|
1007
|
-
if (!cached)
|
|
1008
|
-
return;
|
|
1009
|
-
const reconciled = reconcileProjectDiagnosticsSnapshot(cached);
|
|
1010
|
-
if (reconciled.staleDropped > 0) {
|
|
1011
|
-
logLatency({
|
|
1012
|
-
type: "phase",
|
|
1013
|
-
toolName: "lens_diagnostics",
|
|
1014
|
-
filePath: cwd,
|
|
1015
|
-
phase: "project_snapshot_rows_retired",
|
|
1016
|
-
durationMs: 0,
|
|
1017
|
-
metadata: {
|
|
1018
|
-
files: reconciled.staleDropped,
|
|
1019
|
-
rows: cached.diagnostics.length - reconciled.snapshot.diagnostics.length,
|
|
1020
|
-
scannedAt: cached.scannedAt
|
|
1021
|
-
}
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
return reconciled.snapshot;
|
|
1025
|
-
}
|
|
1026
|
-
return;
|
|
1027
|
-
}
|
|
1028
|
-
async function formatFullMode(cwd, severity, lspService, cacheManager, options = {}) {
|
|
1029
|
-
const runWorkspaceDiagnostics = lspService.runWorkspaceDiagnostics;
|
|
1030
|
-
if (typeof runWorkspaceDiagnostics !== "function") {
|
|
1031
|
-
return {
|
|
1032
|
-
content: [
|
|
1033
|
-
{
|
|
1034
|
-
type: "text",
|
|
1035
|
-
text: "LSP service does not support project-wide workspace diagnostics."
|
|
1036
|
-
}
|
|
1037
|
-
],
|
|
1038
|
-
details: { mode: "full", filesChecked: 0, lspUnavailable: true }
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
const { signal, pathsScope, nextWriteIndex } = options;
|
|
1042
|
-
const host = options.host ?? "pi";
|
|
1043
|
-
const includeFile = createScopedFileFilter(cwd, pathsScope);
|
|
1044
|
-
const explicitFiles = pathsScope && !pathsScope.hasDirectoryEntries ? pathsScope.existingEntries : undefined;
|
|
1045
|
-
const projectRunnersRequested = shouldIncludeProjectRunners(options.refreshRunners);
|
|
1046
|
-
const analyzersPromise = projectRunnersRequested ? loadBootstrapClients().then((clients) => fetchFreshProjectDiagnostics(cacheManager, cwd, clients, signal, {
|
|
1047
|
-
runtime: options.runtime,
|
|
1048
|
-
analysisRoot: options.analysisRoot
|
|
1049
|
-
})) : Promise.resolve({
|
|
1050
|
-
diagnostics: [],
|
|
1051
|
-
runners: [],
|
|
1052
|
-
analyzed: [],
|
|
1053
|
-
authoritativeCoverage: [],
|
|
1054
|
-
cold: [...ANALYZER_IDS],
|
|
1055
|
-
coldReasons: Object.fromEntries(ANALYZER_IDS.map((id) => [id, notRequestedReason(host)])),
|
|
1056
|
-
failed: [],
|
|
1057
|
-
timings: {}
|
|
1058
|
-
});
|
|
1059
|
-
const [rawLspResults, rawProjectSnapshot, extracted] = await Promise.all([
|
|
1060
|
-
runWorkspaceDiagnostics.call(lspService, cwd, {
|
|
1061
|
-
maxFiles: options.maxLspFiles,
|
|
1062
|
-
signal,
|
|
1063
|
-
onProgress: options.onProgress,
|
|
1064
|
-
onServerReady: options.onServerReady,
|
|
1065
|
-
nextWriteIndex: options.nextWriteIndex,
|
|
1066
|
-
files: explicitFiles
|
|
1067
|
-
}),
|
|
1068
|
-
getProjectDiagnosticsSnapshotForFullMode(cwd, {
|
|
1069
|
-
...options,
|
|
1070
|
-
files: explicitFiles
|
|
1071
|
-
}),
|
|
1072
|
-
analyzersPromise
|
|
1073
|
-
]);
|
|
1074
|
-
if (extracted.analysisRootError) {
|
|
1075
|
-
return {
|
|
1076
|
-
content: [{ type: "text", text: extracted.analysisRootError }],
|
|
1077
|
-
isError: true,
|
|
1078
|
-
details: {
|
|
1079
|
-
mode: "full",
|
|
1080
|
-
analysisRootError: extracted.analysisRootError,
|
|
1081
|
-
analysisRootValidation: extracted.analysisRootValidation
|
|
1082
|
-
}
|
|
1083
|
-
};
|
|
1084
|
-
}
|
|
1085
|
-
const aborted = signal?.aborted ?? false;
|
|
1086
|
-
const lspResults = await demoteInferredProjectSweepResults(rawLspResults.filter((result) => includeFile(result.filePath)), cwd, lspService, signal);
|
|
1087
|
-
const mismatchedLspResults = await findFullScanBindingMismatches(lspResults);
|
|
1088
|
-
const confirmedLspResults = lspResults.filter((result) => !result.timedOut && !result.error && !mismatchedLspResults.has(result));
|
|
1089
|
-
const fullyCoveredLspResults = confirmedLspResults.filter((result) => (result.unconfirmedServerIds?.length ?? 0) === 0);
|
|
1090
|
-
const partiallyCoveredLspResults = confirmedLspResults.filter((result) => (result.unconfirmedServerIds?.length ?? 0) > 0);
|
|
1091
|
-
const unconfirmedLspResults = lspResults.filter((result) => result.timedOut || result.error || mismatchedLspResults.has(result));
|
|
1092
|
-
const authoritativeLspFiles = new Set;
|
|
1093
|
-
const unreconciledFiles = new Set;
|
|
1094
|
-
for (const result of fullyCoveredLspResults) {
|
|
1095
|
-
try {
|
|
1096
|
-
const diagnostics = convertLspDiagnostics(result.diagnostics, result.filePath, { scanOrigin: "lens_diagnostics_full" });
|
|
1097
|
-
const retagged = retagAuxiliaryDiagnostics(diagnostics, result.diagnostics, "", { cwd, fileRole: detectFileRole(result.filePath) });
|
|
1098
|
-
const retired = reconcileScanDiagnostics(result.filePath, retagged, true, result.writeIndex ?? nextWriteIndex?.(), result.observedAt);
|
|
1099
|
-
if (retired === true) {
|
|
1100
|
-
authoritativeLspFiles.add(path.resolve(result.filePath));
|
|
1101
|
-
} else {
|
|
1102
|
-
unreconciledFiles.add(path.resolve(result.filePath));
|
|
1103
|
-
recordDegradationOnce({
|
|
1104
|
-
kind: "diagnostic-retained-unreconciled",
|
|
1105
|
-
subject: `${path.resolve(result.filePath)}:lsp`,
|
|
1106
|
-
reason: "confirmed diagnostic result could not replace retained widget state"
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
} catch {
|
|
1110
|
-
unreconciledFiles.add(path.resolve(result.filePath));
|
|
1111
|
-
recordDegradationOnce({
|
|
1112
|
-
kind: "diagnostic-retained-unreconciled",
|
|
1113
|
-
subject: `${path.resolve(result.filePath)}:lsp`,
|
|
1114
|
-
reason: "confirmed diagnostic result failed during widget reconciliation"
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
const policyMap = loadProjectRulePolicyMap(cwd);
|
|
1119
|
-
const scannedSnapshot = filterProjectDiagnosticsSnapshot(rawProjectSnapshot, includeFile);
|
|
1120
|
-
const authoritativeRunnerIds = new Set(extracted.analyzed ?? []);
|
|
1121
|
-
const authoritativeRunnerCoverage = extracted.authoritativeCoverage ?? [];
|
|
1122
|
-
const foldedProjectSnapshot = foldExtraDiagnosticsIntoSnapshot(scannedSnapshot, extracted.diagnostics.filter((d) => includeFile(d.filePath)), extracted.runners, cwd);
|
|
1123
|
-
const projectSnapshot = applyProjectRulePolicy(foldedProjectSnapshot, policyMap);
|
|
1124
|
-
const projectDelta = applyProjectRulePolicy(filterProjectDiagnosticsDeltaReport(loadProjectDiagnosticsDeltaReport(cwd), includeFile), policyMap);
|
|
1125
|
-
const authoritativeRetiredCount = getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath) && authoritativeLspFiles.has(path.resolve(summary.filePath)) && (summary.diagnostics?.length ?? 0) > 0).length;
|
|
1126
|
-
if (authoritativeRetiredCount > 0) {
|
|
1127
|
-
logLatency({
|
|
1128
|
-
type: "phase",
|
|
1129
|
-
phase: "lsp_authoritative_widget_retire",
|
|
1130
|
-
filePath: "",
|
|
1131
|
-
durationMs: 0,
|
|
1132
|
-
metadata: { files: authoritativeRetiredCount }
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
const retiredRunnerCounts = new Map;
|
|
1136
|
-
const runnerRetiredRows = getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)).reduce((total, summary) => total + (summary.diagnostics ?? []).filter((diagnostic) => {
|
|
1137
|
-
const retired = runnerRetirementDecision(diagnostic, summary.filePath, authoritativeRunnerIds, authoritativeRunnerCoverage) === "retire";
|
|
1138
|
-
if (retired) {
|
|
1139
|
-
const runnerId = runnerIdOf(diagnostic);
|
|
1140
|
-
retiredRunnerCounts.set(runnerId, (retiredRunnerCounts.get(runnerId) ?? 0) + 1);
|
|
1141
|
-
}
|
|
1142
|
-
return retired;
|
|
1143
|
-
}).length, 0);
|
|
1144
|
-
if (runnerRetiredRows > 0) {
|
|
1145
|
-
logLatency({
|
|
1146
|
-
type: "phase",
|
|
1147
|
-
phase: "runner_authoritative_widget_retire",
|
|
1148
|
-
filePath: "",
|
|
1149
|
-
durationMs: 0,
|
|
1150
|
-
metadata: {
|
|
1151
|
-
rows: runnerRetiredRows,
|
|
1152
|
-
runners: [...retiredRunnerCounts.keys()].join(","),
|
|
1153
|
-
coverage: authoritativeRunnerCoverage.map((entry) => ({
|
|
1154
|
-
runnerId: entry.runnerId,
|
|
1155
|
-
root: entry.root,
|
|
1156
|
-
files: entry.files.size
|
|
1157
|
-
}))
|
|
1158
|
-
}
|
|
1159
|
-
});
|
|
1160
|
-
}
|
|
1161
|
-
for (const entry of authoritativeRunnerCoverage) {
|
|
1162
|
-
if (entry.files.size === 0)
|
|
1163
|
-
continue;
|
|
1164
|
-
if (!claimPhaseOncePerSession("runner_coverage_retired", entry.runnerId)) {
|
|
1165
|
-
continue;
|
|
1166
|
-
}
|
|
1167
|
-
logLatency({
|
|
1168
|
-
type: "phase",
|
|
1169
|
-
phase: "runner_coverage_retired",
|
|
1170
|
-
filePath: "",
|
|
1171
|
-
durationMs: 0,
|
|
1172
|
-
metadata: {
|
|
1173
|
-
runnerId: entry.runnerId,
|
|
1174
|
-
count: retiredRunnerCounts.get(entry.runnerId) ?? 0
|
|
1175
|
-
}
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
let summaries = await applyInlineSuppressionsToSummaries(mergeDiagnosticsWithWidgetSummaries(getFileDiagnosticSummaries().filter((summary) => includeFile(summary.filePath)), confirmedLspResults, projectSnapshot, projectDelta, authoritativeLspFiles, authoritativeRunnerIds, authoritativeRunnerCoverage), cwd, policyMap);
|
|
1179
|
-
if (unreconciledFiles.size > 0) {
|
|
1180
|
-
summaries = summaries.map((summary) => unreconciledFiles.has(path.resolve(summary.filePath)) ? summarizeDiagnostics(summary.filePath, markUnreconciledFindings(summary.diagnostics), summary.hasFinalSnapshot) : summary);
|
|
1181
|
-
}
|
|
1182
|
-
const parsedProjectScanObservedAt = projectSnapshot?.scannedAt ? Date.parse(projectSnapshot.scannedAt) : undefined;
|
|
1183
|
-
const projectScanObservedAt = parsedProjectScanObservedAt !== undefined && Number.isFinite(parsedProjectScanObservedAt) ? parsedProjectScanObservedAt : undefined;
|
|
1184
|
-
for (const summary of summaries) {
|
|
1185
|
-
reconcileCorrelatedScanDiagnostics(summary.filePath, summary.diagnostics, nextWriteIndex?.(), projectScanObservedAt);
|
|
1186
|
-
}
|
|
1187
|
-
const result = await formatAllMode(cwd, severity, summaries, {
|
|
1188
|
-
mode: "full",
|
|
1189
|
-
lspFilesChecked: rawLspResults.length,
|
|
1190
|
-
partial: aborted,
|
|
1191
|
-
projectDiagnostics: projectSnapshot === undefined ? undefined : {
|
|
1192
|
-
tier: projectSnapshot.tier,
|
|
1193
|
-
filesScanned: projectSnapshot.filesScanned,
|
|
1194
|
-
diagnostics: projectSnapshot.diagnostics.length,
|
|
1195
|
-
runners: projectSnapshot.runners
|
|
1196
|
-
},
|
|
1197
|
-
projectDiagnosticsDelta: projectDelta === undefined ? undefined : {
|
|
1198
|
-
diagnostics: projectDelta.diagnostics.length,
|
|
1199
|
-
sources: projectDelta.sources,
|
|
1200
|
-
turnIndex: projectDelta.turnIndex
|
|
1201
|
-
}
|
|
1202
|
-
}, 0, pathsScope);
|
|
1203
|
-
const missingNote = pathsScopeMissingNote(pathsScope);
|
|
1204
|
-
const unconfirmedByReason = tallyUnconfirmedReasons(unconfirmedLspResults, mismatchedLspResults);
|
|
1205
|
-
const lspServerBreakdown = tallyLspByPrimaryServer(confirmedLspResults, unconfirmedLspResults);
|
|
1206
|
-
const serverBreakdownClause = lspServerBreakdown.size > 1 ? ` — by server: ${formatLspServerBreakdown(lspServerBreakdown)}.` : "";
|
|
1207
|
-
const unconfirmedLspNote = unconfirmedLspResults.length > 0 ? `
|
|
1208
|
-
|
|
1209
|
-
⚠ LSP sweep: ${confirmedLspResults.length} file(s) confirmed via LSP, ` + `${unconfirmedLspResults.length} unconfirmed (${formatUnconfirmedReasonClause(unconfirmedByReason)})${serverBreakdownClause} — NOT the same as 0 diagnostics for: ${unconfirmedLspResults.slice(0, 20).map((result) => result.filePath).join(", ")}${unconfirmedLspResults.length > 20 ? ", …" : ""}. These files' LSP contribution is excluded from this result; re-run mode=full to retry them (they may still show findings above from cached/project-runner state).` : "";
|
|
1210
|
-
const uncoveredScannerIds = [
|
|
1211
|
-
...new Set(partiallyCoveredLspResults.flatMap((result) => result.unconfirmedServerIds ?? []))
|
|
1212
|
-
].sort((a, b) => Number(a > b) - Number(a < b));
|
|
1213
|
-
const auxiliaryCoverageNote = uncoveredScannerIds.length > 0 ? `
|
|
1214
|
-
|
|
1215
|
-
⚠ Auxiliary coverage incomplete: ${uncoveredScannerIds.join(", ")} did not answer for ${partiallyCoveredLspResults.length} file(s). Findings from answering servers are included; this is not a clean verdict for the named scanner lane(s).` : "";
|
|
1216
|
-
const lspPrimaryVsAuxiliary = tallyLspPrimaryVsAuxiliary(confirmedLspResults);
|
|
1217
|
-
logExtension({
|
|
1218
|
-
subsystem: "lsp-diagnostics",
|
|
1219
|
-
message: "lens_diagnostics verdict",
|
|
1220
|
-
metadata: {
|
|
1221
|
-
server: [
|
|
1222
|
-
...new Set(confirmedLspResults.map((result) => primaryServerId(result.filePath) ?? "unknown"))
|
|
1223
|
-
].join(","),
|
|
1224
|
-
primary: lspPrimaryVsAuxiliary.primary,
|
|
1225
|
-
auxiliary: lspPrimaryVsAuxiliary.auxiliary,
|
|
1226
|
-
total: lspPrimaryVsAuxiliary.primary + lspPrimaryVsAuxiliary.auxiliary,
|
|
1227
|
-
sources: [
|
|
1228
|
-
...new Set(confirmedLspResults.flatMap((result) => (result.diagnostics ?? []).map((diagnostic) => diagnostic.source ?? "unknown")))
|
|
1229
|
-
].slice(0, 5)
|
|
1230
|
-
}
|
|
1231
|
-
});
|
|
1232
|
-
const lspPrimaryVsAuxiliaryNote = lspPrimaryVsAuxiliary.primary + lspPrimaryVsAuxiliary.auxiliary > 0 ? `
|
|
1233
|
-
|
|
1234
|
-
LSP sweep findings: ${lspPrimaryVsAuxiliary.primary} primary (language server), ` + `${lspPrimaryVsAuxiliary.auxiliary} auxiliary (ast-grep/opengrep/zizmor/typos/marksman/...).` : "";
|
|
1235
|
-
const abortedIds = new Set(extracted.abortedIds ?? []);
|
|
1236
|
-
const genuinelyColdIds = extracted.cold.filter((id) => !abortedIds.has(id));
|
|
1237
|
-
const partialIds = extracted.partial ?? [];
|
|
1238
|
-
const coldNote = extracted.unsafeRoot ? `
|
|
1239
|
-
|
|
1240
|
-
heavyweight analyzers skipped: the analysis root resolves at or above the home directory, so a fresh knip/jscpd/madge/gitleaks/govulncheck/trivy/dead-code scan would walk every unrelated tree under it. Supply a project directory below the home ceiling. Absence of their findings is NOT a clean verdict.` : extracted.analysisRootError ? `
|
|
1241
|
-
|
|
1242
|
-
heavyweight analyzers skipped: ${extracted.analysisRootError}. Supply an existing project directory below the home ceiling. Absence of their findings is NOT a clean verdict.` : !projectRunnersRequested && genuinelyColdIds.length > 0 ? `
|
|
1243
|
-
|
|
1244
|
-
not run this call (quick mode): ${genuinelyColdIds.join(", ")}. ${notRequestedReason(host)}. Absence of their findings is NOT a clean verdict.` : genuinelyColdIds.length > 0 ? `
|
|
1245
|
-
|
|
1246
|
-
cold (not applicable / unavailable this run): ${genuinelyColdIds.map((id) => formatNotRunEntry(id, extracted.coldReasons)).join(", ")}. These analyzers have not contributed to this result — absence of their findings is NOT a clean verdict.` : "";
|
|
1247
|
-
const partialNote = partialIds.length > 0 ? `
|
|
1248
|
-
|
|
1249
|
-
⚠ partial coverage (findings included): ${partialIds.map((id) => `${id} — ${extracted.partialReasons?.[id] ?? "coverage is incomplete"}`).join(", ")}. Coverage is incomplete, so absence of findings is NOT a clean verdict.` : "";
|
|
1250
|
-
const testRunnerEditScopedNote = extracted.runners.includes("test-runner") ? `
|
|
1251
|
-
|
|
1252
|
-
test-runner coverage is edit-scoped, NOT a full-project run: its findings only reflect the test file(s) touched by the most recent edit's turn_end fire, not a fresh whole-project test suite run (mode=full never re-runs the suite — see fresh-fetch.ts). Absence of test-runner findings elsewhere in the project is NOT a clean verdict, and presence here does not mean "just checked" — it may be from several turns ago.` : "";
|
|
1253
|
-
const failedAnalyzers = extracted.failed ?? [];
|
|
1254
|
-
const failedNote = failedAnalyzers.length > 0 ? `
|
|
1255
|
-
|
|
1256
|
-
failed (ran, but no trustworthy result): ${failedAnalyzers.map(({ id, summary }) => `${id} — ${summary}`).join(", ")}. These analyzers were not cached and will be retried; absence of their findings is NOT a clean verdict.` : "";
|
|
1257
|
-
const dispositionSuppressedByLaneText = Object.entries(extracted.dispositionSuppressedByLane ?? {}).map(([id, count]) => `${id} ${count}`).join(", ");
|
|
1258
|
-
const dispositionSuppressedNote = (extracted.dispositionSuppressed ?? 0) > 0 ? `
|
|
1259
|
-
|
|
1260
|
-
suppressed by disposition: ${extracted.dispositionSuppressed} finding(s) dropped from this result because they're marked false-positive or won't-fix (${dispositionSuppressedByLaneText}). Not a clean verdict for those locations — they were found, then intentionally hidden.` : "";
|
|
1261
|
-
const walkUnsafeRoot = explicitFiles === undefined && isAtOrAboveHomeDir(cwd);
|
|
1262
|
-
const walkUnsafeRootNote = walkUnsafeRoot ? `
|
|
1263
|
-
|
|
1264
|
-
project file walk skipped: the working directory resolves at or above the home directory, so the cheap project scan and the LSP workspace sweep would each enumerate every unrelated tree under it. Re-run from inside a project directory. Absence of their findings is NOT a clean verdict.` : "";
|
|
1265
|
-
const scanTruncatedNoticeText = projectSnapshot ? scanTruncationNotice(projectSnapshot) : undefined;
|
|
1266
|
-
const scanTruncatedNote = scanTruncatedNoticeText ? `
|
|
1267
|
-
|
|
1268
|
-
${scanTruncatedNoticeText}` : "";
|
|
1269
|
-
const generatedSkipNoticeText = projectSnapshot ? generatedSkipNotice(projectSnapshot, host) : undefined;
|
|
1270
|
-
const generatedSkipNote = generatedSkipNoticeText ? `
|
|
1271
|
-
|
|
1272
|
-
${generatedSkipNoticeText}` : "";
|
|
1273
|
-
const cheapScanScannedAtMs = rawProjectSnapshot?.scannedAt ? Date.parse(rawProjectSnapshot.scannedAt) : undefined;
|
|
1274
|
-
const cheapScanStatusNote = !projectRunnersRequested ? `
|
|
1275
|
-
|
|
1276
|
-
cheap project scan (tree-sitter/fact-rules/ast-grep): not run this call (${notRequestedReason(host)}).` : options.refreshRunners === "cached" ? cheapScanScannedAtMs !== undefined && Number.isFinite(cheapScanScannedAtMs) ? `
|
|
1277
|
-
|
|
1278
|
-
cheap project scan (tree-sitter/fact-rules/ast-grep): served from cache, ${formatCacheAgeOld(Date.now() - cheapScanScannedAtMs)} — not re-run this call.` : `
|
|
1279
|
-
|
|
1280
|
-
cheap project scan (tree-sitter/fact-rules/ast-grep): not run (no cached scan; refresh with refreshRunners=cheap/all to populate).` : "";
|
|
1281
|
-
const abortedNote = abortedIds.size > 0 ? `
|
|
1282
|
-
|
|
1283
|
-
stopped mid-scan (still running in the background, not reflected in this result): ${[
|
|
1284
|
-
...abortedIds
|
|
1285
|
-
].join(", ")}. Not a clean verdict for these — re-run mode=full to pick up their result once it's cached.` : "";
|
|
1286
|
-
const cachedAgeMs = extracted.cachedAgeMs ?? {};
|
|
1287
|
-
const timingEntries = Object.entries(extracted.timings ?? {}).filter(([id]) => !(id in cachedAgeMs));
|
|
1288
|
-
const freshNote = timingEntries.length > 0 ? `
|
|
1289
|
-
|
|
1290
|
-
fetched fresh this call: ${timingEntries.map(([id, ms]) => `${id} (${Math.round(ms)}ms)`).join(", ")}.` : "";
|
|
1291
|
-
const cachedAgeEntries = Object.entries(cachedAgeMs);
|
|
1292
|
-
const cachedAgeNote = cachedAgeEntries.length > 0 ? `
|
|
1293
|
-
|
|
1294
|
-
served from cache this call (not re-run): ${cachedAgeEntries.map(([id, ms]) => `${id} (${formatCacheAgeOld(ms)})`).join(", ")}.` : "";
|
|
1295
|
-
const resultWithCold = {
|
|
1296
|
-
...result,
|
|
1297
|
-
details: {
|
|
1298
|
-
...result.details,
|
|
1299
|
-
coldRunners: extracted.cold,
|
|
1300
|
-
partialRunners: partialIds,
|
|
1301
|
-
coldReasons: extracted.coldReasons ?? {},
|
|
1302
|
-
failedAnalyzers,
|
|
1303
|
-
analyzerTimingsMs: extracted.timings,
|
|
1304
|
-
dispositionSuppressed: extracted.dispositionSuppressed ?? 0,
|
|
1305
|
-
dispositionSuppressedByLane: extracted.dispositionSuppressedByLane ?? {},
|
|
1306
|
-
analyzersCachedAgeMs: cachedAgeMs,
|
|
1307
|
-
analyzersAborted: extracted.aborted ?? false,
|
|
1308
|
-
analyzersAbortedIds: extracted.abortedIds ?? [],
|
|
1309
|
-
analyzersUnsafeRoot: extracted.analysisRootValidation?.state === "unsafe" || extracted.unsafeRoot === true,
|
|
1310
|
-
analysisRootValidation: extracted.analysisRootValidation,
|
|
1311
|
-
projectWalkUnsafeRoot: walkUnsafeRoot,
|
|
1312
|
-
lspFilesConfirmed: confirmedLspResults.length,
|
|
1313
|
-
lspFilesUnconfirmed: unconfirmedLspResults.length,
|
|
1314
|
-
lspFilesPartiallyCovered: partiallyCoveredLspResults.length,
|
|
1315
|
-
unconfirmedLspServerIds: uncoveredScannerIds,
|
|
1316
|
-
unconfirmedLspFiles: unconfirmedLspResults.map((result) => result.filePath),
|
|
1317
|
-
lspServerBreakdown: Object.fromEntries(lspServerBreakdown),
|
|
1318
|
-
lspPrimaryDiagnosticsCount: lspPrimaryVsAuxiliary.primary,
|
|
1319
|
-
lspAuxiliaryDiagnosticsCount: lspPrimaryVsAuxiliary.auxiliary,
|
|
1320
|
-
projectScanTruncated: projectSnapshot?.scanTruncated ?? false,
|
|
1321
|
-
...projectSnapshot?.generatedFileSkips ? { projectGeneratedFileSkips: projectSnapshot.generatedFileSkips } : {},
|
|
1322
|
-
...projectSnapshot?.generatedNameOnlySkips ? {
|
|
1323
|
-
projectGeneratedNameOnlySkips: projectSnapshot.generatedNameOnlySkips
|
|
1324
|
-
} : {},
|
|
1325
|
-
...projectSnapshot?.generatedDirSkips ? { projectGeneratedDirSkips: projectSnapshot.generatedDirSkips } : {}
|
|
1326
|
-
}
|
|
1327
|
-
};
|
|
1328
|
-
if (aborted) {
|
|
1329
|
-
const timedOut = signal?.reason?.name === "TimeoutError";
|
|
1330
|
-
const note = timedOut ? `
|
|
1331
|
-
|
|
1332
|
-
⚠ Scan exceeded its ${Math.round((options.wallClockMs ?? 0) / 1000)}s time budget and was stopped — results are partial. ` + "Narrow it with maxLspFiles, or raise DM_LENS_LENS_DIAGNOSTICS_FULL_TIMEOUT_MS." : `
|
|
1333
|
-
|
|
1334
|
-
⚠ Scan cancelled before completion — results are partial. ` + "Re-run with a smaller maxLspFiles to finish within budget.";
|
|
1335
|
-
return {
|
|
1336
|
-
content: [
|
|
1337
|
-
{
|
|
1338
|
-
type: "text",
|
|
1339
|
-
text: result.content[0].text + note + unconfirmedLspNote + auxiliaryCoverageNote + lspPrimaryVsAuxiliaryNote + partialNote + coldNote + testRunnerEditScopedNote + failedNote + dispositionSuppressedNote + walkUnsafeRootNote + scanTruncatedNote + generatedSkipNote + abortedNote + freshNote + cachedAgeNote + cheapScanStatusNote + missingNote
|
|
1340
|
-
}
|
|
1341
|
-
],
|
|
1342
|
-
details: { ...resultWithCold.details, timedOut }
|
|
1343
|
-
};
|
|
1344
|
-
}
|
|
1345
|
-
if (missingNote || coldNote || partialNote || testRunnerEditScopedNote || failedNote || dispositionSuppressedNote || walkUnsafeRootNote || scanTruncatedNote || generatedSkipNote || abortedNote || freshNote || cachedAgeNote || cheapScanStatusNote || unconfirmedLspNote || auxiliaryCoverageNote || lspPrimaryVsAuxiliaryNote) {
|
|
1346
|
-
return {
|
|
1347
|
-
content: [
|
|
1348
|
-
{
|
|
1349
|
-
type: "text",
|
|
1350
|
-
text: result.content[0].text + unconfirmedLspNote + auxiliaryCoverageNote + lspPrimaryVsAuxiliaryNote + partialNote + coldNote + testRunnerEditScopedNote + failedNote + dispositionSuppressedNote + walkUnsafeRootNote + scanTruncatedNote + generatedSkipNote + abortedNote + freshNote + cachedAgeNote + cheapScanStatusNote + missingNote
|
|
1351
|
-
}
|
|
1352
|
-
],
|
|
1353
|
-
details: resultWithCold.details
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
return resultWithCold;
|
|
1357
|
-
}
|
|
1358
|
-
async function projectResolvedCwd(summary, cwd) {
|
|
1359
|
-
const resolvedCwd = await resolveLspCwdForFile(summary.filePath, cwd);
|
|
1360
|
-
return {
|
|
1361
|
-
...summary,
|
|
1362
|
-
...resolvedCwd === undefined ? {} : { resolvedCwd },
|
|
1363
|
-
diagnostics: summary.diagnostics ?? []
|
|
1364
|
-
};
|
|
1365
|
-
}
|
|
1366
|
-
async function formatAllMode(cwd, severity, summaries = getFileDiagnosticSummaries(), detailOverrides = { mode: "all" }, staleDropped = 0, pathsScope, dependencyDemoted = 0) {
|
|
1367
|
-
const footerCapped = summaries.reduce((n, s) => n + (s.diagnostics ?? []).filter((d) => d.footerRetired === true).length, 0);
|
|
1368
|
-
const staleNote = (staleDropped > 0 ? ` (${staleDropped} changed file${staleDropped === 1 ? "" : "s"} omitted as stale — use mode=full to rescan)` : "") + (dependencyDemoted > 0 ? ` (${dependencyDemoted} blocking finding${dependencyDemoted === 1 ? "" : "s"} demoted to [stale] — an imported file changed since; re-run to confirm)` : "") + (footerCapped > 0 ? ` (${footerCapped} demoted finding${footerCapped === 1 ? "" : "s"} capped after ${DEPENDENCY_DRIFT_MAX_DELIVERIES} unconfirmed deliveries — no longer shown in the dm-lens footer, still listed here; re-run to confirm)` : "");
|
|
1369
|
-
const isFullMode = detailOverrides.mode === "full";
|
|
1370
|
-
const includeFile = createScopedFileFilter(cwd, pathsScope);
|
|
1371
|
-
const policyMap = loadProjectRulePolicyMap(cwd);
|
|
1372
|
-
const dispositioned = isFullMode ? summaries : summaries.map((s) => {
|
|
1373
|
-
const diagnostics = s.diagnostics ?? [];
|
|
1374
|
-
const kept = applyCachedDispositions(diagnostics, cwd, s.filePath);
|
|
1375
|
-
const policyKept = applyRulePolicy(kept, policyMap);
|
|
1376
|
-
if (policyKept.length === kept.length && kept.length === diagnostics.length)
|
|
1377
|
-
return s;
|
|
1378
|
-
return summarizeDiagnostics(s.filePath, policyKept, s.hasFinalSnapshot);
|
|
1379
|
-
});
|
|
1380
|
-
const eofGated = dispositioned.map((s) => {
|
|
1381
|
-
const { diagnostics, demotedCount } = demotePastEofDiagnostics({
|
|
1382
|
-
store: "lens_diagnostics",
|
|
1383
|
-
cwd,
|
|
1384
|
-
filePath: s.filePath,
|
|
1385
|
-
diagnostics: s.diagnostics ?? [],
|
|
1386
|
-
resync: resyncDocumentOnPastEof
|
|
1387
|
-
});
|
|
1388
|
-
if (demotedCount === 0)
|
|
1389
|
-
return s;
|
|
1390
|
-
return summarizeDiagnostics(s.filePath, diagnostics, s.hasFinalSnapshot);
|
|
1391
|
-
});
|
|
1392
|
-
const visibleSummaries = eofGated.filter((s) => includeFile(s.filePath));
|
|
1393
|
-
const withIssues = visibleSummaries.filter((s) => {
|
|
1394
|
-
if (severity === "error")
|
|
1395
|
-
return s.blocking > 0 || s.errors > 0;
|
|
1396
|
-
if (severity === "warning")
|
|
1397
|
-
return s.blocking > 0 || s.errors > 0 || s.warnings > 0;
|
|
1398
|
-
return s.blocking > 0 || s.errors > 0 || s.warnings > 0 || s.advisories > 0 || (s.diagnostics ?? []).some((d) => d.stale);
|
|
1399
|
-
});
|
|
1400
|
-
const pathsNote = isFullMode ? "" : pathsScopeCacheOnlyNote(pathsScope);
|
|
1401
|
-
if (withIssues.length === 0) {
|
|
1402
|
-
const text = (visibleSummaries.length === 0 ? "No files diagnosed yet this session." : `No ${severity === "all" ? "" : severity + " "}issues across ${visibleSummaries.length} file${visibleSummaries.length === 1 ? "" : "s"} diagnosed this session. ✓`) + staleNote + pathsNote;
|
|
1403
|
-
return {
|
|
1404
|
-
content: [{ type: "text", text }],
|
|
1405
|
-
details: {
|
|
1406
|
-
...detailOverrides,
|
|
1407
|
-
filesChecked: visibleSummaries.length,
|
|
1408
|
-
staleDropped
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
}
|
|
1412
|
-
const sorted = withIssues.sort((a, b) => b.blocking - a.blocking || b.errors - a.errors || b.warnings - a.warnings);
|
|
1413
|
-
const rendered = await Promise.all(sorted.map((summary) => projectResolvedCwd(summary, cwd)));
|
|
1414
|
-
const lines = [];
|
|
1415
|
-
let totalBlocking = 0;
|
|
1416
|
-
let totalErrors = 0;
|
|
1417
|
-
let totalWarnings = 0;
|
|
1418
|
-
let totalAdvisories = 0;
|
|
1419
|
-
for (const s of rendered) {
|
|
1420
|
-
const rel = path.relative(cwd, s.filePath);
|
|
1421
|
-
const parts = [];
|
|
1422
|
-
if (s.blocking > 0)
|
|
1423
|
-
parts.push(`\uD83D\uDD34 ${s.blocking} blocking`);
|
|
1424
|
-
if (s.errors > 0 && s.blocking === 0)
|
|
1425
|
-
parts.push(`${s.errors}E`);
|
|
1426
|
-
if (s.warnings > 0)
|
|
1427
|
-
parts.push(`${s.warnings}W`);
|
|
1428
|
-
if (s.advisories > 0)
|
|
1429
|
-
parts.push(`${s.advisories} hint${s.advisories === 1 ? "" : "s"}`);
|
|
1430
|
-
if (!s.hasFinalSnapshot)
|
|
1431
|
-
parts.push(`(pending)`);
|
|
1432
|
-
const staleCount = (s.diagnostics ?? []).filter((d) => d.stale).length;
|
|
1433
|
-
if (staleCount > 0) {
|
|
1434
|
-
parts.push(`${staleCount} stale — re-run to confirm`);
|
|
1435
|
-
}
|
|
1436
|
-
if (s.resolvedCwd !== undefined)
|
|
1437
|
-
parts.push(`cwd=${s.resolvedCwd}`);
|
|
1438
|
-
lines.push(`${rel} ${parts.join(" ")}`);
|
|
1439
|
-
const matching = (s.diagnostics ?? []).filter((d) => matchesSeverity(d, severity)).sort(bySeverityThenLine);
|
|
1440
|
-
const shown = matching.slice(0, MAX_DIAGNOSTICS_PER_FILE);
|
|
1441
|
-
for (const d of shown) {
|
|
1442
|
-
const marker = d.stale ? "" : isErrorLike(d) ? d.semantic === "blocking" ? "\uD83D\uDD34 " : "" : "";
|
|
1443
|
-
const label = d.rule ?? d.tool;
|
|
1444
|
-
const tag = label ? ` [${label}]` : "";
|
|
1445
|
-
const flaggedTag = d.flagged ? " \uD83D\uDCCC flagged-to-fix" : "";
|
|
1446
|
-
const msg = d.message.replace(/\s+/g, " ").trim();
|
|
1447
|
-
const pastEof = d.stale && (d.staleReason ?? "past-eof") === "past-eof";
|
|
1448
|
-
const loc = pastEof ? PAST_EOF_STALE_MARKER : `L${d.line ?? "?"}`;
|
|
1449
|
-
const staleTag = d.stale && !pastEof ? ` ${STALE_LINE_MARKER}` : "";
|
|
1450
|
-
lines.push(` ${marker}${loc}: ${msg}${tag}${flaggedTag}${staleTag}`);
|
|
1451
|
-
}
|
|
1452
|
-
if (matching.length > shown.length) {
|
|
1453
|
-
lines.push(` … ${matching.length - shown.length} more in this file (showing ${shown.length} of ${matching.length})`);
|
|
1454
|
-
}
|
|
1455
|
-
totalBlocking += s.blocking;
|
|
1456
|
-
totalErrors += s.errors;
|
|
1457
|
-
totalWarnings += s.warnings;
|
|
1458
|
-
totalAdvisories += s.advisories;
|
|
1459
|
-
}
|
|
1460
|
-
const summary = [
|
|
1461
|
-
`
|
|
1462
|
-
Summary (${visibleSummaries.length} files diagnosed this session):`,
|
|
1463
|
-
totalBlocking > 0 ? ` \uD83D\uDD34 ${totalBlocking} blocking error${totalBlocking === 1 ? "" : "s"}` : null,
|
|
1464
|
-
totalBlocking === 0 && totalErrors > 0 ? ` ${totalErrors} error${totalErrors === 1 ? "" : "s"}` : null,
|
|
1465
|
-
totalWarnings > 0 ? ` ${totalWarnings} warning${totalWarnings === 1 ? "" : "s"}` : null,
|
|
1466
|
-
totalAdvisories > 0 ? ` ${totalAdvisories} hint/info (style — not counted as warnings)` : null
|
|
1467
|
-
].filter(Boolean).join(`
|
|
1468
|
-
`);
|
|
1469
|
-
return {
|
|
1470
|
-
content: [
|
|
1471
|
-
{ type: "text", text: lines.join(`
|
|
1472
|
-
`) + summary + staleNote }
|
|
1473
|
-
],
|
|
1474
|
-
details: {
|
|
1475
|
-
...detailOverrides,
|
|
1476
|
-
filesWithIssues: withIssues.length,
|
|
1477
|
-
totalBlocking,
|
|
1478
|
-
totalErrors,
|
|
1479
|
-
totalWarnings,
|
|
1480
|
-
totalAdvisories,
|
|
1481
|
-
staleDropped
|
|
1482
|
-
}
|
|
1483
|
-
};
|
|
1484
|
-
}
|