@herbertgao/pi-extensions 2026.8.11 → 2026.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -10
- package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
- package/node_modules/@czottmann/pi-automode/README.md +5 -3
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
- package/node_modules/@czottmann/pi-automode/package.json +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
- package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
- package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
- package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
- package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
- package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
- package/node_modules/@tifan/pi-handoff/package.json +43 -0
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
- package/node_modules/@tifan/pi-recap/package.json +42 -0
- package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
- package/node_modules/@tifan/pi-rename/package.json +47 -0
- package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
- package/node_modules/pi-lens/CHANGELOG.md +96 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
- package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
- package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
- package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
- package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
- package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
- package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
- package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
- package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
- package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
- package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
- package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
- package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
- package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
- package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
- package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
- package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
- package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
- package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
- package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
- package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
- package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
- package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
- package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
- package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
- package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
- package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
- package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
- package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
- package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
- package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
- package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
- package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
- package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
- package/node_modules/pi-lens/dist/i18n.js +13 -5
- package/node_modules/pi-lens/dist/index.js +10797 -8627
- package/node_modules/pi-lens/dist/mcp/server.js +3 -1
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
- package/node_modules/pi-lens/package.json +160 -156
- package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
- package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
- package/node_modules/pi-mcp-adapter/README.md +42 -13
- package/node_modules/pi-mcp-adapter/commands.ts +4 -2
- package/node_modules/pi-mcp-adapter/config.ts +45 -5
- package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
- package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
- package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
- package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
- package/node_modules/pi-mcp-adapter/index.ts +204 -82
- package/node_modules/pi-mcp-adapter/init.ts +41 -30
- package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
- package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
- package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
- package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
- package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
- package/node_modules/pi-mcp-adapter/package.json +24 -6
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
- package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
- package/node_modules/pi-mcp-adapter/state.ts +1 -3
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
- package/node_modules/pi-mcp-adapter/types.ts +48 -1
- package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
- package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
- package/node_modules/pi-mcp-adapter/utils.ts +21 -19
- package/node_modules/pi-web-access/CHANGELOG.md +26 -0
- package/node_modules/pi-web-access/README.md +71 -14
- package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
- package/node_modules/pi-web-access/credential-source.ts +6 -2
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +89 -9
- package/node_modules/pi-web-access/fetch-params.ts +13 -0
- package/node_modules/pi-web-access/gemini-adc.ts +298 -0
- package/node_modules/pi-web-access/gemini-api.ts +59 -15
- package/node_modules/pi-web-access/gemini-search.ts +58 -18
- package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
- package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
- package/node_modules/pi-web-access/gemini-web.ts +9 -3
- package/node_modules/pi-web-access/github-api.ts +5 -4
- package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
- package/node_modules/pi-web-access/index.ts +403 -297
- package/node_modules/pi-web-access/kimi-search.ts +234 -0
- package/node_modules/pi-web-access/openai-search.ts +118 -21
- package/node_modules/pi-web-access/package.json +3 -2
- package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
- package/node_modules/pi-web-access/utils.ts +307 -1
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +46 -37
- package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
- package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
- package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
- package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
- package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
- package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/package.json +0 -55
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-rename/package.json +0 -63
- package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
- package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
- /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/src/index.ts +0 -0
|
@@ -86,14 +86,14 @@ if (isSharedWriterState(existingGlobalState)) {
|
|
|
86
86
|
ndjsonGlobalState = existingGlobalState;
|
|
87
87
|
}
|
|
88
88
|
else if (existingGlobalState === undefined) {
|
|
89
|
-
ndjsonGlobalState =
|
|
89
|
+
ndjsonGlobalState = globalStateHost[NDJSON_GLOBAL_STATE_KEY] = {
|
|
90
90
|
schema: NDJSON_GLOBAL_STATE_SCHEMA,
|
|
91
91
|
version: NDJSON_GLOBAL_STATE_VERSION,
|
|
92
92
|
writers: new Map(),
|
|
93
93
|
exitFlushers: new Set(),
|
|
94
94
|
exitHandlerRegistered: false,
|
|
95
95
|
registeredLogFiles: new Set(),
|
|
96
|
-
}
|
|
96
|
+
};
|
|
97
97
|
}
|
|
98
98
|
else if (isLegacyGlobalState(existingGlobalState)) {
|
|
99
99
|
// Do not mutate or replace this state: its private queues and exit flusher
|
|
@@ -363,9 +363,7 @@ async function drainLoop(state) {
|
|
|
363
363
|
? state.queue.findIndex((queued) => queued.kind === "truncate")
|
|
364
364
|
: 0;
|
|
365
365
|
const pendingEnd = truncateIndex === -1 ? state.queue.length : truncateIndex;
|
|
366
|
-
const pending = item.kind === "truncate"
|
|
367
|
-
? [item]
|
|
368
|
-
: state.queue.slice(0, pendingEnd);
|
|
366
|
+
const pending = item.kind === "truncate" ? [item] : state.queue.slice(0, pendingEnd);
|
|
369
367
|
state.inFlightBatch = pending;
|
|
370
368
|
const writeBatch = async () => {
|
|
371
369
|
if (item.kind === "truncate") {
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque-mutation recovery (#2000 phase 2).
|
|
3
|
+
*
|
|
4
|
+
* A bash command whose writes are NOT recognized by
|
|
5
|
+
* `extractWrittenPathsFromCommand` (python/node/perl/PowerShell internal
|
|
6
|
+
* writes, restores) previously bypassed dispatch AND read-guard authorship.
|
|
7
|
+
* This module observes what such a command actually changed.
|
|
8
|
+
*
|
|
9
|
+
* GIT-FIRST STRATEGY: inside a git worktree the pre side records only a
|
|
10
|
+
* TIMESTAMP; the post side asks `git status --porcelain` which files are
|
|
11
|
+
* dirty and keeps those whose mtime falls inside the command's window.
|
|
12
|
+
* This has NO file-universe bound — it works identically on a 10-file site
|
|
13
|
+
* and a 5000-file monorepo, and content-identical rewrites are correctly
|
|
14
|
+
* NOT reported (a false positive the pure stat-diff design produced).
|
|
15
|
+
*
|
|
16
|
+
* NON-GIT FALLBACK: outside git the pre side takes a bounded stat snapshot
|
|
17
|
+
* (cap enforced, cooperative budget) and the post side diffs it — the
|
|
18
|
+
* original design, kept honestly scoped to small non-git trees.
|
|
19
|
+
*
|
|
20
|
+
* Every failure mode yields an explicit UNKNOWN verdict to the caller —
|
|
21
|
+
* never a clean claim (issue invariant 3). All path keys use
|
|
22
|
+
* normalizeMapKey+resolve, joining the mutation-seam's key form.
|
|
23
|
+
*
|
|
24
|
+
* KNOWN LIMITATIONS:
|
|
25
|
+
* - shape 6: stat-diff identity is size+mtimeMs PLUS a budgeted content-hash
|
|
26
|
+
* confirm (withHashes captures sha1 up to OPAQUE_HASH_BUDGET_BYTES); a
|
|
27
|
+
* same-tick/same-size rewrite is detected when both sides hashed the file,
|
|
28
|
+
* and degrades to mtime+size for files past the hash budget. The git path
|
|
29
|
+
* detects any content change regardless.
|
|
30
|
+
* - INVARIANT 4 (per issue): ignored/vendor paths are EXCLUDED. Under the
|
|
31
|
+
* git strategy this means writes landing ONLY in .gitignore'd locations
|
|
32
|
+
* are never reported - an all-ignored write set reads as an empty (clean)
|
|
33
|
+
* recovery BY SPEC, not by oversight. Codegen targeting dist/build-style
|
|
34
|
+
* outputs should use explicit redirect destinations so the extractor
|
|
35
|
+
* recognizes them.
|
|
36
|
+
*/
|
|
37
|
+
import * as fs from "node:fs";
|
|
38
|
+
import * as path from "node:path";
|
|
39
|
+
import { collectSourceFilesWithBudgetAsync } from "./source-filter.js";
|
|
40
|
+
import { createHash } from "node:crypto";
|
|
41
|
+
import { normalizeMapKey } from "./path-utils.js";
|
|
42
|
+
import { freshnessFromMtime } from "./freshness.js";
|
|
43
|
+
import { safeSpawnAsync } from "./safe-spawn.js";
|
|
44
|
+
/** Stop hashing once this many cumulative bytes were read (per capture). */
|
|
45
|
+
export const OPAQUE_HASH_BUDGET_BYTES = 8 * 1024 * 1024;
|
|
46
|
+
/** Hard cap on scanned files — beyond it the verdict is coverage-unknown. */
|
|
47
|
+
export const OPAQUE_SCAN_MAX_FILES = 2000;
|
|
48
|
+
/** How far before recorded start an earlier write may still be attributed. */
|
|
49
|
+
export const OPAQUE_MTIME_TOLERANCE_MS = 150;
|
|
50
|
+
export async function captureFileStats(root, options = {}) {
|
|
51
|
+
const budgetMs = options.budgetMs ?? 50;
|
|
52
|
+
try {
|
|
53
|
+
const walk = await collectSourceFilesWithBudgetAsync(root, {
|
|
54
|
+
maxFiles: OPAQUE_SCAN_MAX_FILES + 1,
|
|
55
|
+
budgetMs,
|
|
56
|
+
});
|
|
57
|
+
const files = walk.files;
|
|
58
|
+
if (walk.entryBudgetExceeded || files.length > OPAQUE_SCAN_MAX_FILES) {
|
|
59
|
+
// A PARTIAL universe must never read as a confident diff (invariant
|
|
60
|
+
// 3): writes in the unvisited tail would silently vanish.
|
|
61
|
+
return {
|
|
62
|
+
unknownReason: walk.entryBudgetExceeded
|
|
63
|
+
? "entry-budget-exceeded"
|
|
64
|
+
: "file-cap-exceeded",
|
|
65
|
+
scannedCount: files.length,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const snapshot = new Map();
|
|
69
|
+
let hashBytesSpent = 0;
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
try {
|
|
72
|
+
const stat = await fs.promises.stat(file);
|
|
73
|
+
const entry = {
|
|
74
|
+
mtimeMs: stat.mtimeMs,
|
|
75
|
+
size: stat.size,
|
|
76
|
+
};
|
|
77
|
+
if (options.withHashes &&
|
|
78
|
+
hashBytesSpent + stat.size <= OPAQUE_HASH_BUDGET_BYTES) {
|
|
79
|
+
entry.hash = createHash("sha256")
|
|
80
|
+
.update(await fs.promises.readFile(file))
|
|
81
|
+
.digest("hex");
|
|
82
|
+
hashBytesSpent += stat.size;
|
|
83
|
+
}
|
|
84
|
+
snapshot.set(normalizeMapKey(path.resolve(file)), entry);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Vanished mid-walk: absent from both snapshots = unchanged-by-absence.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { snapshot, scannedCount: snapshot.size };
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { unknownReason: "walk-failed", scannedCount: 0 };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Paths added or whose size/mtime changed. Deletions are NOT reported. */
|
|
97
|
+
export function diffFileStats(before, after) {
|
|
98
|
+
const changed = [];
|
|
99
|
+
for (const [key, stat] of after) {
|
|
100
|
+
const prev = before.get(key);
|
|
101
|
+
// Content confirm: same mtime tick + same size but different bytes.
|
|
102
|
+
const contentConfirm = prev?.hash !== undefined &&
|
|
103
|
+
stat.hash !== undefined &&
|
|
104
|
+
prev.hash !== stat.hash;
|
|
105
|
+
if (!prev ||
|
|
106
|
+
prev.mtimeMs !== stat.mtimeMs ||
|
|
107
|
+
prev.size !== stat.size ||
|
|
108
|
+
contentConfirm) {
|
|
109
|
+
changed.push(key);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return changed;
|
|
113
|
+
}
|
|
114
|
+
export class OpaqueBaselineStore {
|
|
115
|
+
byCwd = new Map();
|
|
116
|
+
evictions = 0;
|
|
117
|
+
record(cwdKey, baseline) {
|
|
118
|
+
if (this.byCwd.has(cwdKey))
|
|
119
|
+
this.evictions += 1;
|
|
120
|
+
this.byCwd.set(cwdKey, baseline);
|
|
121
|
+
}
|
|
122
|
+
take(cwdKey) {
|
|
123
|
+
const baseline = this.byCwd.get(cwdKey);
|
|
124
|
+
this.byCwd.delete(cwdKey);
|
|
125
|
+
return baseline;
|
|
126
|
+
}
|
|
127
|
+
get evictionCount() {
|
|
128
|
+
return this.evictions;
|
|
129
|
+
}
|
|
130
|
+
/** Session-boundary clear - unconsumed baselines are unreachable after reset. */
|
|
131
|
+
takeAllForTest() {
|
|
132
|
+
this.byCwd.clear();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const globalStoreSymbol = Symbol.for("pi-lens:opaque-snapshot-store");
|
|
136
|
+
const globalSlot = globalThis;
|
|
137
|
+
export function getOpaqueBaselineStore() {
|
|
138
|
+
const existing = globalSlot[globalStoreSymbol]?.store;
|
|
139
|
+
if (existing)
|
|
140
|
+
return existing;
|
|
141
|
+
const created = new OpaqueBaselineStore();
|
|
142
|
+
globalSlot[globalStoreSymbol] = { store: created };
|
|
143
|
+
return created;
|
|
144
|
+
}
|
|
145
|
+
const gitRepoMemo = new Map();
|
|
146
|
+
/**
|
|
147
|
+
* Session-boundary clear (#1635): unconsumed pending baselines are keyed by
|
|
148
|
+
* cwd:generation, so entries from a finished session are unreachable; and a
|
|
149
|
+
* directory that was not a worktree last session may be one now. Without this
|
|
150
|
+
* reset both leak and mis-answer forever.
|
|
151
|
+
*/
|
|
152
|
+
export function resetOpaqueMutationState() {
|
|
153
|
+
getOpaqueBaselineStore().takeAllForTest();
|
|
154
|
+
gitRepoMemo.clear();
|
|
155
|
+
}
|
|
156
|
+
/** Cached git-worktree probe (repos don't stop being git mid-session). */
|
|
157
|
+
export async function isGitWorktree(root) {
|
|
158
|
+
const key = normalizeMapKey(path.resolve(root));
|
|
159
|
+
const memo = gitRepoMemo.get(key);
|
|
160
|
+
if (memo !== undefined)
|
|
161
|
+
return memo;
|
|
162
|
+
const result = await safeSpawnAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: root, timeout: 3000 });
|
|
163
|
+
const isRepo = !result.error && result.status === 0 && result.stdout?.trim() === "true";
|
|
164
|
+
gitRepoMemo.set(key, isRepo === true);
|
|
165
|
+
return isRepo === true;
|
|
166
|
+
}
|
|
167
|
+
export function _resetGitWorktreeMemoForTests() {
|
|
168
|
+
gitRepoMemo.clear();
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Files dirty in the working tree whose mtime falls inside
|
|
172
|
+
* [startedAt - tolerance, now]. Porcelain -z parsing handles renames
|
|
173
|
+
* (the NEW path is reported; the old path token is skipped).
|
|
174
|
+
*/
|
|
175
|
+
export async function recoverOpaqueChangesViaGit(root, startedAt) {
|
|
176
|
+
const result = await safeSpawnAsync("git", ["status", "--porcelain", "-z", "--untracked-files=all"], { cwd: root, timeout: 5000 });
|
|
177
|
+
if (result.error || (result.status !== 0 && result.status !== null)) {
|
|
178
|
+
return {
|
|
179
|
+
verdict: "unknown",
|
|
180
|
+
paths: [],
|
|
181
|
+
unknownReason: "git-failed",
|
|
182
|
+
scannedCount: 0,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const floorMs = startedAt - OPAQUE_MTIME_TOLERANCE_MS;
|
|
186
|
+
const raw = result.stdout ?? "";
|
|
187
|
+
const tokens = raw.split("\0");
|
|
188
|
+
const paths = [];
|
|
189
|
+
let skipNext = false; // rename's OLD path follows its NEW path
|
|
190
|
+
for (const token of tokens) {
|
|
191
|
+
if (!token)
|
|
192
|
+
continue;
|
|
193
|
+
if (skipNext) {
|
|
194
|
+
skipNext = false;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
// Each entry: two status chars, one space, then the path.
|
|
198
|
+
if (token.length < 4 || token[2] !== " ")
|
|
199
|
+
continue;
|
|
200
|
+
const status = token.slice(0, 2);
|
|
201
|
+
const relPath = token.slice(3);
|
|
202
|
+
if (status.includes("R") || status.includes("C"))
|
|
203
|
+
skipNext = true;
|
|
204
|
+
const abs = path.resolve(root, relPath);
|
|
205
|
+
try {
|
|
206
|
+
const stat = await fs.promises.stat(abs);
|
|
207
|
+
if (stat.isFile() &&
|
|
208
|
+
freshnessFromMtime({ mtimeMs: stat.mtimeMs, referenceMs: floorMs })
|
|
209
|
+
.verdict === "stale") {
|
|
210
|
+
// Kernel "stale" = modified AFTER the window floor - exactly the
|
|
211
|
+
// writes this command may have authored.
|
|
212
|
+
paths.push(normalizeMapKey(abs));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Deleted or vanished: deletions are deliberately unreported.
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { verdict: "recovered", paths, scannedCount: paths.length };
|
|
220
|
+
}
|
|
@@ -23,7 +23,12 @@ import { safeSpawnAsync } from "./safe-spawn.js";
|
|
|
23
23
|
* missing). npm first for maximum compatibility; bun last. A project lockfile
|
|
24
24
|
* always overrides this order.
|
|
25
25
|
*/
|
|
26
|
-
const PREFERENCE = [
|
|
26
|
+
const PREFERENCE = [
|
|
27
|
+
"npm",
|
|
28
|
+
"pnpm",
|
|
29
|
+
"yarn",
|
|
30
|
+
"bun",
|
|
31
|
+
];
|
|
27
32
|
function onWindows() {
|
|
28
33
|
return process.platform === "win32";
|
|
29
34
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import * as nodeFs from "node:fs";
|
|
15
15
|
import * as path from "node:path";
|
|
16
|
-
import { findNearestContaining, normalizeEphemeralMapKey } from "./path-utils.js";
|
|
16
|
+
import { findNearestContaining, normalizeEphemeralMapKey, } from "./path-utils.js";
|
|
17
17
|
import { recordFromDispatchDiagnostic, } from "./actionable-warnings.js";
|
|
18
18
|
import { recordFromCodeQualityDiagnostic, } from "./code-quality-warnings.js";
|
|
19
19
|
import { recordDiagnostics } from "./widget-state.js";
|
|
@@ -25,6 +25,7 @@ import { classifyProbeFailure, createAvailabilityChecker, createAvailabilityLatc
|
|
|
25
25
|
import { findDetektConfig } from "./dispatch/runners/detekt.js";
|
|
26
26
|
import { detectFileKind, getFileKindLabel } from "./file-kinds.js";
|
|
27
27
|
import { detectFileChangedAfterCommand, getProjectIgnoreMatcher, isExcludedDirName, } from "./file-utils.js";
|
|
28
|
+
import { isInSpawnTimeoutCooldown } from "./spawn-timeout-cooldown.js";
|
|
28
29
|
import { logLatency } from "./latency-logger.js";
|
|
29
30
|
import { emitLensAnalysisComplete } from "./lens-events.js";
|
|
30
31
|
import { publishFilesTouched } from "./bus-publish.js";
|
|
@@ -36,6 +37,7 @@ import { RUNTIME_CONFIG } from "./runtime-config.js";
|
|
|
36
37
|
import { getAmbientAbortSignal, safeSpawnAsync } from "./safe-spawn.js";
|
|
37
38
|
import { combineAbortSignals } from "./deadline-utils.js";
|
|
38
39
|
import { recordDegradationOnce } from "./degradation-ledger.js";
|
|
40
|
+
import { dropFindingsForMissingPaths } from "./advisory-provenance.js";
|
|
39
41
|
import { getAutofixPolicyForFile, getPreferredAutofixTools, getRubocopCommand, hasBiomeConfig, hasDetektConfig, hasEslintConfig, hasGolangciConfig, hasKtfmtConfig, hasKtlintConfig, hasOxlintConfig, hasRubocopConfig, hasSqlfluffConfig, hasStylelintConfig, markdownlintConfigArgs, } from "./tool-policy.js";
|
|
40
42
|
const LSP_MAX_FILE_BYTES = RUNTIME_CONFIG.pipeline.lspMaxFileBytes;
|
|
41
43
|
const LSP_MAX_FILE_LINES = RUNTIME_CONFIG.pipeline.lspMaxFileLines;
|
|
@@ -336,10 +338,17 @@ async function tryDetektFix(filePath, cwd) {
|
|
|
336
338
|
const absPath = path.resolve(cwd, filePath);
|
|
337
339
|
return detectFileChangedAfterCommand(filePath, cmd, ["--auto-correct", "--input", absPath, "--config", configPath], cwd, [1, 2]);
|
|
338
340
|
}
|
|
339
|
-
|
|
341
|
+
// Exported for #1995 cooldown wiring tests: the guard on this lane is
|
|
342
|
+
// one of three mutation-proof surfaces.
|
|
343
|
+
export async function tryMarkdownlintFix(filePath, cwd) {
|
|
340
344
|
const cmd = await resolveToolCommandWithInstallFallback(cwd, "markdownlint");
|
|
341
345
|
if (!cmd)
|
|
342
346
|
return 0;
|
|
347
|
+
// #1995: skip the spawn entirely when the command is cooling down after a
|
|
348
|
+
// timeout — detectFileChangedAfterCommand also self-guards, but a wedged
|
|
349
|
+
// command should not even reach a second budget in the hot loop.
|
|
350
|
+
if (isInSpawnTimeoutCooldown(cmd))
|
|
351
|
+
return 0;
|
|
343
352
|
// Shared config-args seam (#1247): the lint runner consumes the same
|
|
344
353
|
// builder, so the bare --fix here can never fall back to markdownlint's
|
|
345
354
|
// default all-rules-on config again (the whole-file CHANGELOG/AGENTS
|
|
@@ -838,8 +847,10 @@ export async function runFormatPhase(filePath, getFormatService, dbg) {
|
|
|
838
847
|
* L4: 'randomInt' is declared but its value is never read.
|
|
839
848
|
* → const randomInt = Math.floor(result);
|
|
840
849
|
*/
|
|
841
|
-
function buildEnrichedBlockerOutput(blockers, fileContent) {
|
|
842
|
-
|
|
850
|
+
function buildEnrichedBlockerOutput(blockers, fileContent = "") {
|
|
851
|
+
// Empty fileContent (readback failed, e.g. deleted-file race) still
|
|
852
|
+
// renders the gated blocker list - just without per-line snippets.
|
|
853
|
+
const fileLines = fileContent ? fileContent.split("\n") : [];
|
|
843
854
|
const MAX_SNIPPET = 120; // chars — keep it tight in context
|
|
844
855
|
let out = `\n\n🔴 STOP — ${blockers.length} issue(s) must be fixed:\n`;
|
|
845
856
|
const shown = blockers.slice(0, 10);
|
|
@@ -1065,10 +1076,27 @@ export async function runPipeline(ctx, deps) {
|
|
|
1065
1076
|
if (dispatchResult.resolvedCount > 0)
|
|
1066
1077
|
getDiagnosticTracker().trackAgentFixed(dispatchResult.resolvedCount);
|
|
1067
1078
|
let output = "";
|
|
1079
|
+
// #2028: the 🔴 STOP block is an agent-facing delivery surface
|
|
1080
|
+
// (finding-delivery-gate.ts's `tool-call:stop-blocker`), so it routes through
|
|
1081
|
+
// the shared deleted-path gate before rendering: a blocker whose cited file
|
|
1082
|
+
// no longer exists has no remediation the agent can perform (the finding IS
|
|
1083
|
+
// the deleted file's content), so it is dropped here rather than re-asserted.
|
|
1084
|
+
// One bounded stat per unique cited path, only when blockers exist — zero
|
|
1085
|
+
// cost on the clean/fast paths.
|
|
1086
|
+
const deliverableBlockers = dispatchResult.hasBlockers
|
|
1087
|
+
? dropFindingsForMissingPaths({
|
|
1088
|
+
store: "stop-blocker",
|
|
1089
|
+
findings: dispatchResult.blockers,
|
|
1090
|
+
cwd,
|
|
1091
|
+
citedPath: (b) => b.filePath || undefined,
|
|
1092
|
+
})
|
|
1093
|
+
: dispatchResult.blockers;
|
|
1068
1094
|
if (dispatchResult.hasBlockers && fileContent) {
|
|
1069
1095
|
// Enrich blocker output with a code snippet so the agent can see the
|
|
1070
1096
|
// exact line it wrote that caused each violation — no re-read needed.
|
|
1071
|
-
|
|
1097
|
+
if (deliverableBlockers.length > 0) {
|
|
1098
|
+
output += buildEnrichedBlockerOutput(deliverableBlockers, fileContent);
|
|
1099
|
+
}
|
|
1072
1100
|
// Append fixed/coverage parts from the original output (slice off the
|
|
1073
1101
|
// blocker section we're replacing).
|
|
1074
1102
|
const rest = dispatchResult.output.slice(dispatchResult.blockerOutput.length);
|
|
@@ -1076,7 +1104,20 @@ export async function runPipeline(ctx, deps) {
|
|
|
1076
1104
|
output += rest;
|
|
1077
1105
|
}
|
|
1078
1106
|
else if (dispatchResult.output) {
|
|
1079
|
-
|
|
1107
|
+
// #2028 review P3: this path fires when readback FAILED - raw output
|
|
1108
|
+
// still cites possibly-deleted files. Re-render from the gated set
|
|
1109
|
+
// (no snippets without fileContent) and keep the post-blocker slice.
|
|
1110
|
+
if (dispatchResult.hasBlockers &&
|
|
1111
|
+
deliverableBlockers.length !== dispatchResult.blockers.length) {
|
|
1112
|
+
let gatedOut = buildEnrichedBlockerOutput(deliverableBlockers);
|
|
1113
|
+
const rest = dispatchResult.output.slice(dispatchResult.blockerOutput.length);
|
|
1114
|
+
if (rest)
|
|
1115
|
+
gatedOut += rest;
|
|
1116
|
+
output += `\n\n${gatedOut}`;
|
|
1117
|
+
}
|
|
1118
|
+
else {
|
|
1119
|
+
output += `\n\n${dispatchResult.output}`;
|
|
1120
|
+
}
|
|
1080
1121
|
}
|
|
1081
1122
|
if (fixedCount > 0) {
|
|
1082
1123
|
const detail = autofixTools.length > 0 ? ` (${autofixTools.join(", ")})` : "";
|
|
@@ -1126,7 +1167,8 @@ export async function runPipeline(ctx, deps) {
|
|
|
1126
1167
|
fileContent,
|
|
1127
1168
|
wordIndex: ctx.wordIndex,
|
|
1128
1169
|
onWordIndexUpdated: ctx.onWordIndexUpdated,
|
|
1129
|
-
})
|
|
1170
|
+
})
|
|
1171
|
+
.then((run) => ({ ...run, origin: cascadeOrigin }))
|
|
1130
1172
|
.catch((err) => {
|
|
1131
1173
|
dbg(`cascade compute failed for ${filePath}: ${err}`);
|
|
1132
1174
|
return {
|
|
@@ -1233,8 +1275,14 @@ export async function runPipeline(ctx, deps) {
|
|
|
1233
1275
|
fixedCount,
|
|
1234
1276
|
autofixTools,
|
|
1235
1277
|
postAutofixNotice,
|
|
1236
|
-
postMutation: ctx.autofixMode !== "deferred" &&
|
|
1237
|
-
|
|
1278
|
+
postMutation: ctx.autofixMode !== "deferred" &&
|
|
1279
|
+
autofixChangedFiles.some((f) => path.resolve(f) === path.resolve(filePath)) &&
|
|
1280
|
+
fileContent !== undefined
|
|
1281
|
+
? {
|
|
1282
|
+
filePath: path.resolve(filePath),
|
|
1283
|
+
content: fileContent,
|
|
1284
|
+
source: "autofix",
|
|
1285
|
+
}
|
|
1238
1286
|
: undefined,
|
|
1239
1287
|
};
|
|
1240
1288
|
}
|
|
@@ -72,8 +72,7 @@ function detectNext(cwd, pkg) {
|
|
|
72
72
|
signals.push("app/");
|
|
73
73
|
if (signals.length === 0)
|
|
74
74
|
return undefined;
|
|
75
|
-
const confidence = hasDep(pkg, "next") &&
|
|
76
|
-
signals.some((s) => s.startsWith("next.config."))
|
|
75
|
+
const confidence = hasDep(pkg, "next") && signals.some((s) => s.startsWith("next.config."))
|
|
77
76
|
? "high"
|
|
78
77
|
: hasDep(pkg, "next")
|
|
79
78
|
? "medium"
|
|
@@ -152,12 +151,7 @@ export function detectProjectConventions(cwd) {
|
|
|
152
151
|
return { frameworks: [], testRunners: [], buildTools: [], agentDocs: [] };
|
|
153
152
|
}
|
|
154
153
|
const pkg = readPackageJson(cwd);
|
|
155
|
-
const detectors = [
|
|
156
|
-
detectReact,
|
|
157
|
-
detectNext,
|
|
158
|
-
detectVite,
|
|
159
|
-
detectVitest,
|
|
160
|
-
];
|
|
154
|
+
const detectors = [detectReact, detectNext, detectVite, detectVitest];
|
|
161
155
|
const frameworks = [];
|
|
162
156
|
for (const detector of detectors) {
|
|
163
157
|
const detection = detector(cwd, pkg);
|
|
@@ -3,7 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { getProjectDataDir } from "../file-utils.js";
|
|
4
4
|
import { writeFileAtomic } from "../atomic-write.js";
|
|
5
5
|
import { readJsonCache } from "../json-cache-read.js";
|
|
6
|
-
import {
|
|
6
|
+
import { freshnessFromMtime } from "../freshness.js";
|
|
7
7
|
// v2: cheap-tier scan now also runs ast-grep-napi (#308); invalidate older
|
|
8
8
|
// snapshots so a pre-ast-grep cache isn't served as complete via refreshRunners=cached.
|
|
9
9
|
export const PROJECT_DIAGNOSTICS_CACHE_VERSION = 2;
|
|
@@ -80,16 +80,19 @@ export function reconcileProjectDiagnosticsSnapshot(snapshot) {
|
|
|
80
80
|
if (cached !== undefined)
|
|
81
81
|
return cached;
|
|
82
82
|
let stale;
|
|
83
|
+
let mtimeMs;
|
|
83
84
|
try {
|
|
84
|
-
|
|
85
|
-
// within the tolerance window of the scan timestamp being captured,
|
|
86
|
-
// has mtime <= scannedAt + MTIME_DRIFT_TOLERANCE_MS.
|
|
87
|
-
stale =
|
|
88
|
-
fs.statSync(filePath).mtimeMs > scannedAtMs + MTIME_DRIFT_TOLERANCE_MS;
|
|
85
|
+
mtimeMs = fs.statSync(filePath).mtimeMs;
|
|
89
86
|
}
|
|
90
87
|
catch {
|
|
91
|
-
|
|
88
|
+
mtimeMs = undefined; // deleted / unreadable -> indeterminate -> drop
|
|
92
89
|
}
|
|
90
|
+
const verdict = freshnessFromMtime({
|
|
91
|
+
mtimeMs,
|
|
92
|
+
referenceMs: scannedAtMs,
|
|
93
|
+
});
|
|
94
|
+
// Pre-kernel policy: an unreadable/missing file is stale (dropped).
|
|
95
|
+
stale = verdict.verdict !== "fresh";
|
|
93
96
|
staleByFile.set(filePath, stale);
|
|
94
97
|
return stale;
|
|
95
98
|
};
|
package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js
CHANGED
|
@@ -97,7 +97,8 @@ export function callGraphImpactToProjectDiagnostics(cwd, findings) {
|
|
|
97
97
|
continue;
|
|
98
98
|
const dedupeKey = `${resolvedFile}:${result.symbolKey}`;
|
|
99
99
|
const existing = byKey.get(dedupeKey);
|
|
100
|
-
if (existing &&
|
|
100
|
+
if (existing &&
|
|
101
|
+
SEVERITY_RANK[existing.severity] >= SEVERITY_RANK[mapped.severity]) {
|
|
101
102
|
continue;
|
|
102
103
|
}
|
|
103
104
|
const callerName = displayName(result.symbolKey);
|
|
@@ -14,7 +14,9 @@ export function gitleaksFindingToProjectDiagnostic(cwd, finding) {
|
|
|
14
14
|
// #1562 observability criterion: surface the git status right in the
|
|
15
15
|
// finding's message so a triage is a read, not a re-derivation. Omitted
|
|
16
16
|
// when git itself degraded (`pathStatus` undefined) rather than guessed.
|
|
17
|
-
const statusSuffix = finding.pathStatus
|
|
17
|
+
const statusSuffix = finding.pathStatus
|
|
18
|
+
? ` [git: ${finding.pathStatus}]`
|
|
19
|
+
: "";
|
|
18
20
|
const isScratch = finding.pathStatus === "scratch";
|
|
19
21
|
return {
|
|
20
22
|
filePath: path.isAbsolute(finding.file)
|
package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js
CHANGED
|
@@ -84,16 +84,20 @@ export function testRunnerFindingsToProjectDiagnostics(cache, cwd, runtime) {
|
|
|
84
84
|
const missingKeys = new Set((cache.provenance?.files ?? [])
|
|
85
85
|
.filter((file) => !fs.existsSync(path.resolve(root, file.path)))
|
|
86
86
|
.map((file) => advisoryPathKey(file.path, root)));
|
|
87
|
-
const historical = cache.superseded === true ||
|
|
87
|
+
const historical = cache.superseded === true ||
|
|
88
|
+
cache.stale === true ||
|
|
89
|
+
validation.status !== "current";
|
|
88
90
|
return cache.results
|
|
89
91
|
.filter((result) => !missingKeys.has(advisoryPathKey(result.file, root)))
|
|
90
92
|
.flatMap((result) => testResultToProjectDiagnostics(result, historical))
|
|
91
|
-
.map((diagnostic) => historical
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
.map((diagnostic) => historical
|
|
94
|
+
? {
|
|
95
|
+
...diagnostic,
|
|
96
|
+
severity: "info",
|
|
97
|
+
semantic: "none",
|
|
98
|
+
message: diagnostic.message.startsWith("[stale")
|
|
99
|
+
? diagnostic.message
|
|
100
|
+
: `[historical — re-run to confirm] ${diagnostic.message}`,
|
|
101
|
+
}
|
|
102
|
+
: diagnostic);
|
|
99
103
|
}
|
|
@@ -10,7 +10,9 @@ export function trivyFindingToProjectDiagnostic(cwd, finding) {
|
|
|
10
10
|
? finding.target
|
|
11
11
|
: path.resolve(cwd, finding.target)
|
|
12
12
|
: cwd;
|
|
13
|
-
const version = finding.installedVersion
|
|
13
|
+
const version = finding.installedVersion
|
|
14
|
+
? `@${finding.installedVersion}`
|
|
15
|
+
: "";
|
|
14
16
|
const fix = finding.fixedVersion ? ` (fixed in ${finding.fixedVersion})` : "";
|
|
15
17
|
return {
|
|
16
18
|
filePath,
|
|
@@ -38,7 +38,7 @@ const FACT_RULE_EXTENSIONS = new Set([
|
|
|
38
38
|
// The base is the shared per-edit resolver (EXT_TO_LANG — the single
|
|
39
39
|
// ext→grammar-id authority), so c/cpp/csharp/php/css and the .tsx→tsx /
|
|
40
40
|
// .jsx→javascript nuances can never drift from the per-edit path. `.tsx` resolves
|
|
41
|
-
// to the tsx grammar (not typescript: the typescript grammar ERRORs on JSX);
|
|
41
|
+
// to the tsx grammar (not typescript: the typescript grammar ERRORs on JSX); // spellchecker:disable-line
|
|
42
42
|
// typescript RULES still apply because `queriesForLanguage(...)` below merges the
|
|
43
43
|
// typescript rule set onto tsx.
|
|
44
44
|
//
|
|
@@ -295,7 +295,10 @@ async function scanFileMajorRules(cwd, files, signal) {
|
|
|
295
295
|
// so it stays visible SOMEWHERE instead of disappearing when the
|
|
296
296
|
// vacuous `project_diagnostics_ast_grep_scan` cache_stats record
|
|
297
297
|
// (below) was removed.
|
|
298
|
-
astGrep: {
|
|
298
|
+
astGrep: {
|
|
299
|
+
durationMs: astGrepDurationMs,
|
|
300
|
+
fileCount: astGrepFilesScanned,
|
|
301
|
+
},
|
|
299
302
|
});
|
|
300
303
|
});
|
|
301
304
|
// #1935: no `project_diagnostics_ast_grep_scan` cache_stats record here.
|
|
@@ -194,7 +194,11 @@ export function loadPiLensConfigInDir(dir) {
|
|
|
194
194
|
return cached.config;
|
|
195
195
|
}
|
|
196
196
|
const config = parseConfigFile(info.path);
|
|
197
|
-
configCache.set(info.path, {
|
|
197
|
+
configCache.set(info.path, {
|
|
198
|
+
mtimeMs: info.mtimeMs,
|
|
199
|
+
size: info.size,
|
|
200
|
+
config,
|
|
201
|
+
});
|
|
198
202
|
return config;
|
|
199
203
|
}
|
|
200
204
|
export function findPiLensProjectConfig(startDir) {
|
|
@@ -239,7 +243,12 @@ function discoverPiLensProjectConfig(startDir) {
|
|
|
239
243
|
const stat = safeFileStat(candidate);
|
|
240
244
|
if (stat?.isFile()) {
|
|
241
245
|
return {
|
|
242
|
-
info: {
|
|
246
|
+
info: {
|
|
247
|
+
path: candidate,
|
|
248
|
+
dir,
|
|
249
|
+
mtimeMs: stat.mtimeMs,
|
|
250
|
+
size: stat.size,
|
|
251
|
+
},
|
|
243
252
|
dirMtimes,
|
|
244
253
|
};
|
|
245
254
|
}
|
|
@@ -351,9 +360,7 @@ function parseConfigFile(configPath) {
|
|
|
351
360
|
if (entry.threshold !== undefined || entry.disable || entry.select) {
|
|
352
361
|
rules[ruleId] = entry;
|
|
353
362
|
}
|
|
354
|
-
else if (!("threshold" in r) &&
|
|
355
|
-
!("disable" in r) &&
|
|
356
|
-
!("select" in r)) {
|
|
363
|
+
else if (!("threshold" in r) && !("disable" in r) && !("select" in r)) {
|
|
357
364
|
warnInvalidConfigOnce(configPath, `rules.${ruleId} has no recognized setting (threshold, disable, select); ignored`);
|
|
358
365
|
}
|
|
359
366
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Hash serialized project-snapshot JSON while replacing only the top-level
|
|
4
|
+
* volatile `generatedAt` value with a stable sentinel. Production calls this
|
|
5
|
+
* on the persistence worker after stringify. The main-thread caller uses it
|
|
6
|
+
* only on the explicit synchronous fallback path, where serialization already
|
|
7
|
+
* happened and no second object walk is added.
|
|
8
|
+
*/
|
|
9
|
+
export function fingerprintProjectSnapshotJson(json, generatedAt) {
|
|
10
|
+
const marker = `"generatedAt":${JSON.stringify(generatedAt)}`;
|
|
11
|
+
let markerIndex = -1;
|
|
12
|
+
let depth = 0;
|
|
13
|
+
let inString = false;
|
|
14
|
+
let escaped = false;
|
|
15
|
+
for (let index = 0; index < json.length; index++) {
|
|
16
|
+
const char = json[index];
|
|
17
|
+
if (inString) {
|
|
18
|
+
if (escaped)
|
|
19
|
+
escaped = false;
|
|
20
|
+
else if (char === "\\")
|
|
21
|
+
escaped = true;
|
|
22
|
+
else if (char === '"')
|
|
23
|
+
inString = false;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (char === '"') {
|
|
27
|
+
if (depth === 1 && json.startsWith(marker, index)) {
|
|
28
|
+
markerIndex = index;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
inString = true;
|
|
32
|
+
}
|
|
33
|
+
else if (char === "{")
|
|
34
|
+
depth++;
|
|
35
|
+
else if (char === "}")
|
|
36
|
+
depth--;
|
|
37
|
+
}
|
|
38
|
+
const hash = createHash("sha256");
|
|
39
|
+
if (markerIndex < 0) {
|
|
40
|
+
hash.update(json);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
hash.update(json.slice(0, markerIndex));
|
|
44
|
+
hash.update('"generatedAt":""');
|
|
45
|
+
hash.update(json.slice(markerIndex + marker.length));
|
|
46
|
+
}
|
|
47
|
+
return hash.digest("hex");
|
|
48
|
+
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { serveGzipStageWorker, } from "./gzip-stage-write.js";
|
|
2
|
+
import { fingerprintProjectSnapshotJson } from "./project-snapshot-fingerprint.js";
|
|
3
|
+
/**
|
|
4
|
+
* Hash the serialized body while replacing only the top-level volatile
|
|
5
|
+
* `generatedAt` value with a stable sentinel. This runs after the worker has
|
|
6
|
+
* already paid the unavoidable stringify cost. It never walks the snapshot on
|
|
7
|
+
* the extension host's event loop.
|
|
8
|
+
*/
|
|
9
|
+
function semanticSnapshotFingerprint(request, json) {
|
|
10
|
+
const generatedAt = request.data.generatedAt;
|
|
11
|
+
return fingerprintProjectSnapshotJson(json, typeof generatedAt === "string" ? generatedAt : "");
|
|
12
|
+
}
|
|
2
13
|
serveGzipStageWorker((request) => ({
|
|
3
14
|
id: request.id,
|
|
4
15
|
generation: request.generation,
|
|
5
16
|
stagePath: request.stagePath,
|
|
6
|
-
})
|
|
17
|
+
}), {
|
|
18
|
+
semanticFingerprint: semanticSnapshotFingerprint,
|
|
19
|
+
skipIfFingerprints: (request) => request.priorFingerprints,
|
|
20
|
+
});
|