@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
|
@@ -2,6 +2,7 @@ import { randomBytes } from "node:crypto";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { logCascade } from "./cascade-logger.js";
|
|
5
|
+
import { appendProjectChange, } from "./project-changes.js";
|
|
5
6
|
import { normalizeMapKey, pathsEqual } from "./path-utils.js";
|
|
6
7
|
import { PathKeyedMap } from "./path-keyed-map.js";
|
|
7
8
|
import { BoundedLruCache } from "./bounded-cache.js";
|
|
@@ -9,6 +10,15 @@ import { ReadGuard } from "./read-guard.js";
|
|
|
9
10
|
import { RUNTIME_CONFIG } from "./runtime-config.js";
|
|
10
11
|
import { TurnSummaryCollector } from "./turn-summary.js";
|
|
11
12
|
import { deriveProviderFromModelId } from "./model-provider.js";
|
|
13
|
+
/**
|
|
14
|
+
* Bounded receipt ring capacity (defect shape 9: bound the axis that grows —
|
|
15
|
+
* per-mutation receipts are unbounded across a long session). Oldest receipts
|
|
16
|
+
* evict first; eviction is counted and surfaced via
|
|
17
|
+
* {@link RuntimeCoordinator.droppedMutationReceiptCount} so a consumer that
|
|
18
|
+
* needs a complete window knows the answer was truncated, never silently
|
|
19
|
+
* incomplete (#936 honesty rule).
|
|
20
|
+
*/
|
|
21
|
+
const MAX_MUTATION_RECEIPTS = 512;
|
|
12
22
|
/**
|
|
13
23
|
* Bound on in-flight tool_call → tool_result correlations. A tool_result
|
|
14
24
|
* follows its tool_call almost immediately, so this only needs to cover
|
|
@@ -49,6 +59,8 @@ export class RuntimeCoordinator {
|
|
|
49
59
|
_writtenThisTurn = new PathKeyedMap(normalizeMapKey);
|
|
50
60
|
_autofixDemotedThisTurn = new PathKeyedMap(normalizeMapKey);
|
|
51
61
|
_reportedThisTurn = new Set();
|
|
62
|
+
_mutationReceipts = [];
|
|
63
|
+
_droppedMutationReceipts = 0;
|
|
52
64
|
_projectRulesScan = {
|
|
53
65
|
rules: [],
|
|
54
66
|
hasCustomRules: false,
|
|
@@ -119,6 +131,8 @@ export class RuntimeCoordinator {
|
|
|
119
131
|
this._writtenThisTurn.clear();
|
|
120
132
|
this._autofixDemotedThisTurn.clear();
|
|
121
133
|
this._reportedThisTurn.clear();
|
|
134
|
+
this._mutationReceipts = [];
|
|
135
|
+
this._droppedMutationReceipts = 0;
|
|
122
136
|
this._telemetrySessionId = `lens-${Date.now().toString(36)}-${randomBytes(4).toString("hex")}`;
|
|
123
137
|
this._hasStableSessionId = false;
|
|
124
138
|
this._telemetryModel = "unknown";
|
|
@@ -174,7 +188,9 @@ export class RuntimeCoordinator {
|
|
|
174
188
|
const summaries = this.getInlineBlockersSnapshot()
|
|
175
189
|
.map((entry) => entry.summary.trim())
|
|
176
190
|
.filter(Boolean);
|
|
177
|
-
this._gitGuardSummary = (summaries[0] ??
|
|
191
|
+
this._gitGuardSummary = (summaries[0] ??
|
|
192
|
+
firstLine ??
|
|
193
|
+
"Unresolved blockers detected").slice(0, 160);
|
|
178
194
|
}
|
|
179
195
|
get gitGuardHasBlockers() {
|
|
180
196
|
return this._gitGuardHasBlockers;
|
|
@@ -239,6 +255,68 @@ export class RuntimeCoordinator {
|
|
|
239
255
|
this._writtenThisTurn.clear();
|
|
240
256
|
this._autofixDemotedThisTurn.clear();
|
|
241
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* THE one mutation seam. Every producer of an in-project file mutation —
|
|
260
|
+
* native write/edit, recognized bash writes, format/autofix, LSP workspace
|
|
261
|
+
* edits, and (phase 2) opaque script-write recovery — records through here,
|
|
262
|
+
* once: it bumps the seq store (`bumpFileSeq`), appends a bounded attributed
|
|
263
|
+
* receipt, and optionally appends the durable change-log entry. Consumers
|
|
264
|
+
* derive from `getFilesChangedSince` / `getMutationsSince`; no producer or
|
|
265
|
+
* consumer may hand-roll a parallel bump+log pairing (#2000 phase 1).
|
|
266
|
+
*
|
|
267
|
+
* Receipt recording never throws; change-log append failures route to
|
|
268
|
+
* `onAppendError` (default: swallowed) so telemetry cannot break dispatch.
|
|
269
|
+
*/
|
|
270
|
+
recordProjectMutation(args) {
|
|
271
|
+
const { projectSeq, fileSeq, key } = this.bumpFileSeq(args.filePath);
|
|
272
|
+
if (this._mutationReceipts.length >= MAX_MUTATION_RECEIPTS) {
|
|
273
|
+
this._mutationReceipts.shift();
|
|
274
|
+
this._droppedMutationReceipts += 1;
|
|
275
|
+
}
|
|
276
|
+
this._mutationReceipts.push({
|
|
277
|
+
seq: projectSeq,
|
|
278
|
+
// Reuse the bump's normalized key (~200us realpath on Windows) —
|
|
279
|
+
// never re-derive it here.
|
|
280
|
+
filePath: key,
|
|
281
|
+
source: args.source,
|
|
282
|
+
turnIndex: this._turnIndex,
|
|
283
|
+
ts: Date.now(),
|
|
284
|
+
});
|
|
285
|
+
if (args.cwd !== undefined) {
|
|
286
|
+
try {
|
|
287
|
+
appendProjectChange(args.cwd, {
|
|
288
|
+
seq: projectSeq,
|
|
289
|
+
timestamp: new Date().toISOString(),
|
|
290
|
+
sessionId: this.telemetrySessionId,
|
|
291
|
+
turnIndex: this.turnIndex,
|
|
292
|
+
source: args.source,
|
|
293
|
+
filePath: path.resolve(args.filePath),
|
|
294
|
+
fileSeq,
|
|
295
|
+
changedRange: args.changedRange,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
args.onAppendError?.(err);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return { projectSeq, fileSeq };
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Attributed mutations whose seq is strictly after `seq` — the receipt-level
|
|
306
|
+
* counterpart of {@link getFilesChangedSince}. Bounded: entries evicted by
|
|
307
|
+
* the ring cap are gone; compare `droppedMutationReceiptCount` against zero
|
|
308
|
+
* before treating the result as a complete window.
|
|
309
|
+
*/
|
|
310
|
+
getMutationsSince(seq) {
|
|
311
|
+
// Shallow copies: a consumer mutating a returned receipt must not
|
|
312
|
+
// corrupt the ring's internal state.
|
|
313
|
+
return this._mutationReceipts
|
|
314
|
+
.filter((r) => r.seq > seq)
|
|
315
|
+
.map((r) => ({ ...r }));
|
|
316
|
+
}
|
|
317
|
+
get droppedMutationReceiptCount() {
|
|
318
|
+
return this._droppedMutationReceipts;
|
|
319
|
+
}
|
|
242
320
|
/** Atomically records write/edit ordering before debounce can coalesce it. */
|
|
243
321
|
recordMutationToolReceipt(filePath, toolName) {
|
|
244
322
|
if (toolName === "write") {
|
|
@@ -359,12 +437,14 @@ export class RuntimeCoordinator {
|
|
|
359
437
|
}
|
|
360
438
|
}
|
|
361
439
|
bumpFileSeq(filePath) {
|
|
440
|
+
// normalizeMapKey costs ~200us/call on Windows (realpath); every caller
|
|
441
|
+
// that also needs the key must reuse this one instead of paying it twice.
|
|
362
442
|
const key = normalizeMapKey(path.resolve(filePath));
|
|
363
443
|
this._projectSeq += 1;
|
|
364
444
|
const fileSeq = (this._fileSeq.get(key) ?? 0) + 1;
|
|
365
445
|
this._fileSeq.set(key, fileSeq);
|
|
366
446
|
this._fileLastProjectSeq.set(key, this._projectSeq);
|
|
367
|
-
return { projectSeq: this._projectSeq, fileSeq };
|
|
447
|
+
return { projectSeq: this._projectSeq, fileSeq, key };
|
|
368
448
|
}
|
|
369
449
|
/**
|
|
370
450
|
* Files whose most recent bump happened AFTER `seq` — i.e. every file the
|
|
@@ -1036,8 +1116,7 @@ export class RuntimeCoordinator {
|
|
|
1036
1116
|
*/
|
|
1037
1117
|
export function readHostModelIdentity(ctx) {
|
|
1038
1118
|
try {
|
|
1039
|
-
const model = ctx
|
|
1040
|
-
?.model;
|
|
1119
|
+
const model = ctx?.model;
|
|
1041
1120
|
return {
|
|
1042
1121
|
model: typeof model?.id === "string" ? model.id : undefined,
|
|
1043
1122
|
provider: typeof model?.provider === "string" ? model.provider : undefined,
|
|
@@ -43,8 +43,11 @@ import { TrivyClient } from "./trivy-client.js";
|
|
|
43
43
|
import { isWarmAttached } from "./warm-attach.js";
|
|
44
44
|
import { setSessionLanguages } from "./widget-state.js";
|
|
45
45
|
import { logWordIndex } from "./word-index-logger.js";
|
|
46
|
+
import { resetOpaqueMutationState } from "./opaque-mutation-scan.js";
|
|
47
|
+
import { resetPendingAuxiliaryCoverage } from "./lsp/pending-aux-coverage.js";
|
|
46
48
|
import { resetWorkspaceTopology } from "./workspace-topology.js";
|
|
47
49
|
import { resetZizmorTokenAvailability } from "./zizmor-config.js";
|
|
50
|
+
import { resetSpawnTimeoutCooldowns } from "./spawn-timeout-cooldown.js";
|
|
48
51
|
const HOST_STALL_THRESHOLD_MS = 30_000;
|
|
49
52
|
function logHostReadyDelay(deps, cwd) {
|
|
50
53
|
if (!deps.emitHostReadyDelay ||
|
|
@@ -1608,6 +1611,12 @@ export async function handleSessionStart(deps) {
|
|
|
1608
1611
|
// previously session-lived with no reset hook at all).
|
|
1609
1612
|
resetWorkspaceTopology();
|
|
1610
1613
|
clearTsconfigPathsCache();
|
|
1614
|
+
// #2000: opaque-recovery baselines are keyed cwd:generation (unreachable
|
|
1615
|
+
// after reset) and the git-worktree memo must re-probe after a session
|
|
1616
|
+
// that may have seen a non-git dir become one.
|
|
1617
|
+
resetOpaqueMutationState();
|
|
1618
|
+
// #2026: pending auxiliary baselines are unreachable after generation bump.
|
|
1619
|
+
resetPendingAuxiliaryCoverage();
|
|
1611
1620
|
// #817/#1199: Windows command resolution is cached per (command, canonical
|
|
1612
1621
|
// effective child PATH/PATHEXT/cwd/per-drive provenance); drop it each
|
|
1613
1622
|
// session so environment changes (e.g.
|
|
@@ -1621,6 +1630,11 @@ export async function handleSessionStart(deps) {
|
|
|
1621
1630
|
// the tool for the rest of the process lifetime. Clear it here, same
|
|
1622
1631
|
// boundary as the other per-session caches on this line.
|
|
1623
1632
|
resetDispatchAvailabilityState();
|
|
1633
|
+
// #1995: a command that TIMED OUT (not merely failed a probe) cools down
|
|
1634
|
+
// for the rest of the session so a hot loop of edits cannot hand the same
|
|
1635
|
+
// wedged .cmd shim a second budget. A new session may retry: the executable
|
|
1636
|
+
// or its environment may have changed.
|
|
1637
|
+
resetSpawnTimeoutCooldowns();
|
|
1624
1638
|
// #1895: formatter PATH verdicts are session-scoped, but they live in
|
|
1625
1639
|
// formatters.ts and are not covered by the dispatch generation. Re-arm them
|
|
1626
1640
|
// here so a formatter installed or removed between sessions is observed by
|
|
@@ -4,7 +4,10 @@ import { loadBootstrapClients } from "./bootstrap.js";
|
|
|
4
4
|
import { recordDegradationOnce } from "./degradation-ledger.js";
|
|
5
5
|
import { detectFileKind } from "./file-kinds.js";
|
|
6
6
|
import { isPathIgnoredByProject } from "./file-utils.js";
|
|
7
|
-
import { evaluateGitGuard, isGitCommitOrPushAttempt
|
|
7
|
+
import { evaluateGitGuard, isGitCommitOrPushAttempt } from "./git-guard.js";
|
|
8
|
+
import { logLatency } from "./latency-logger.js";
|
|
9
|
+
import { normalizeMapKey } from "./path-utils.js";
|
|
10
|
+
import { captureFileStats, getOpaqueBaselineStore, isGitWorktree, } from "./opaque-mutation-scan.js";
|
|
8
11
|
import { normalizeForGuardMatch } from "./host-edit-normalize.js";
|
|
9
12
|
import { retargetReplacementIndentation } from "./indent-retarget.js";
|
|
10
13
|
import { LANGUAGE_POLICY } from "./language-policy.js";
|
|
@@ -17,7 +20,7 @@ import { EXPANSION_BUDGET_MS, EXPANSION_LIMIT_LINES, tryExpandRead, } from "./re
|
|
|
17
20
|
import { boundedIndexesForCount, createReadGuardEditBatchSummary, getReadGuardCorrelationId, logReadGuardEvent, } from "./read-guard-logger.js";
|
|
18
21
|
import { countFileLines, getTouchedLinesForGuard, relocateEditRange, tryCorrectIndentationMismatch, tryCorrectIndentationMismatchFromContent, } from "./read-guard-tool-lines.js";
|
|
19
22
|
import { handleToolResult } from "./runtime-tool-result.js";
|
|
20
|
-
import { isToolCallEventType, resolveToolCallCorrelationId } from "./tool-event.js";
|
|
23
|
+
import { isToolCallEventType, resolveToolCallCorrelationId, } from "./tool-event.js";
|
|
21
24
|
import { getSharedTreeSitterClient } from "./tree-sitter-shared.js";
|
|
22
25
|
const LSP_TOOLCALL_NAV_TOUCH_BUDGET_MS = Math.max(0, Number.parseInt(process.env.PI_LENS_TOOLCALL_NAV_TOUCH_MS ??
|
|
23
26
|
process.env.PI_LENS_LSP_NAV_CLIENT_WAIT_MS ??
|
|
@@ -317,6 +320,59 @@ async function handleToolCallImpl(deps) {
|
|
|
317
320
|
});
|
|
318
321
|
if (!lensEnabled)
|
|
319
322
|
return;
|
|
323
|
+
// #2000 phase 2: opaque-command pre-snapshot. A bash command whose writes
|
|
324
|
+
// the extractor will not recognize gets a bounded stat snapshot of the
|
|
325
|
+
// project source universe BEFORE it runs; the tool_result side diffs it.
|
|
326
|
+
// Fire-and-forget capture is WRONG here (the child may finish first), but
|
|
327
|
+
// the capture is stat-only and budgeted, so awaiting it is bounded work on
|
|
328
|
+
// an already-second-scale bash path.
|
|
329
|
+
if (toolName === "bash") {
|
|
330
|
+
const commandInput = event.input;
|
|
331
|
+
if (typeof commandInput?.command === "string" && commandInput.command) {
|
|
332
|
+
const scanRoot = ctx.cwd ?? runtime.projectRoot;
|
|
333
|
+
if (scanRoot) {
|
|
334
|
+
const started = Date.now();
|
|
335
|
+
const rootKey = `${normalizeMapKey(path.resolve(scanRoot))}:${runtime.sessionGeneration}`;
|
|
336
|
+
let baseline;
|
|
337
|
+
let resultNote;
|
|
338
|
+
if (await isGitWorktree(scanRoot)) {
|
|
339
|
+
// Git-first: the timestamp IS the baseline; git answers what
|
|
340
|
+
// changed, at any repo size, with no file-universe cap.
|
|
341
|
+
baseline = { startedAt: started, strategy: "git" };
|
|
342
|
+
resultNote = "git";
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
const outcome = await captureFileStats(scanRoot, {
|
|
346
|
+
withHashes: true,
|
|
347
|
+
});
|
|
348
|
+
baseline = outcome.snapshot
|
|
349
|
+
? {
|
|
350
|
+
startedAt: started,
|
|
351
|
+
strategy: "stat-diff",
|
|
352
|
+
stats: outcome.snapshot,
|
|
353
|
+
}
|
|
354
|
+
: {
|
|
355
|
+
startedAt: started,
|
|
356
|
+
strategy: "stat-diff",
|
|
357
|
+
statsUnknownReason: outcome.unknownReason ?? "walk-failed",
|
|
358
|
+
};
|
|
359
|
+
resultNote =
|
|
360
|
+
outcome.unknownReason ?? `scanned:${outcome.scannedCount}`;
|
|
361
|
+
}
|
|
362
|
+
// Session-stamped key: a concurrent-secondary session (#473)
|
|
363
|
+
// replacing this slot must yield a no-pending-snapshot UNKNOWN
|
|
364
|
+
// for us - never a diff against another session's baseline.
|
|
365
|
+
getOpaqueBaselineStore().record(rootKey, baseline);
|
|
366
|
+
logLatency({
|
|
367
|
+
type: "phase",
|
|
368
|
+
phase: "opaque_mutation_prescan",
|
|
369
|
+
filePath: commandInput.command.slice(0, 80),
|
|
370
|
+
durationMs: Date.now() - started,
|
|
371
|
+
result: resultNote,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
320
376
|
if (getFlag("lens-guard") &&
|
|
321
377
|
isGitCommitOrPushAttempt(toolName, event.input)) {
|
|
322
378
|
const guard = evaluateGitGuard(runtime, cacheManager, ctx.cwd ?? runtime.projectRoot);
|
|
@@ -456,7 +512,7 @@ async function handleToolCallImpl(deps) {
|
|
|
456
512
|
}
|
|
457
513
|
}
|
|
458
514
|
if (ctx.ui) {
|
|
459
|
-
|
|
515
|
+
updateLspStatus(ctx.ui.setStatus, ctx.ui.theme);
|
|
460
516
|
}
|
|
461
517
|
})
|
|
462
518
|
.catch((err) => {
|
|
@@ -2,13 +2,15 @@ import * as nodeCrypto from "node:crypto";
|
|
|
2
2
|
import * as nodeFs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { noteAuthoritativeContentAttachment } from "./agent-nudge.js";
|
|
5
|
+
import { captureFileStats, diffFileStats, getOpaqueBaselineStore, recoverOpaqueChangesViaGit, } from "./opaque-mutation-scan.js";
|
|
6
|
+
import { normalizeMapKey } from "./path-utils.js";
|
|
5
7
|
import { extractReadPathsFromCommand, extractDeletedPathsFromCommand, extractGrepSearchReadsFromOutput, extractWrittenPathsFromCommand, } from "./bash-file-access.js";
|
|
6
8
|
import { registerSearchReads, } from "./search-read-registration.js";
|
|
7
9
|
import { createFileTime } from "./file-time.js";
|
|
8
10
|
import { publishFormatQueued } from "./format-events-publish.js";
|
|
9
11
|
import { isPathIgnoredByProject } from "./file-utils.js";
|
|
10
12
|
import { getFormatService } from "./format-service.js";
|
|
11
|
-
import { isExternalOrVendorFile, normalizeEphemeralMapKey, pathsEqual } from "./path-utils.js";
|
|
13
|
+
import { isExternalOrVendorFile, normalizeEphemeralMapKey, pathsEqual, } from "./path-utils.js";
|
|
12
14
|
import { PathKeyedMap } from "./path-keyed-map.js";
|
|
13
15
|
import { resolveLanguageRootForFile } from "./language-profile.js";
|
|
14
16
|
import { logLatency } from "./latency-logger.js";
|
|
@@ -17,7 +19,6 @@ import { boundedIndexesForCount, createReadGuardEditBatchSummary, getReadGuardCo
|
|
|
17
19
|
import { notifyExternalFileChange } from "./lsp/index.js";
|
|
18
20
|
import { runPipeline } from "./pipeline.js";
|
|
19
21
|
import { renderPostAutofixNotice, } from "./post-autofix-notice.js";
|
|
20
|
-
import { appendProjectChange, } from "./project-changes.js";
|
|
21
22
|
import { syncGitGuardRecord } from "./git-guard.js";
|
|
22
23
|
import { scheduleWordIndexPersist } from "./word-index.js";
|
|
23
24
|
import { RUNTIME_CONFIG } from "./runtime-config.js";
|
|
@@ -111,7 +112,8 @@ function scheduleDebounced(filePath, debounceMs, deps) {
|
|
|
111
112
|
const existing = debouncedPipelines.get(filePath);
|
|
112
113
|
if (existing) {
|
|
113
114
|
clearTimeout(existing.timer);
|
|
114
|
-
const incomingId = deps._telemetryParticipantIds?.[0] ??
|
|
115
|
+
const incomingId = deps._telemetryParticipantIds?.[0] ??
|
|
116
|
+
getReadGuardCorrelationId(deps.event);
|
|
115
117
|
const priorIds = existing.latestDeps._telemetryParticipantIds ?? [];
|
|
116
118
|
existing.latestDeps = {
|
|
117
119
|
...deps,
|
|
@@ -133,7 +135,9 @@ function scheduleDebounced(filePath, debounceMs, deps) {
|
|
|
133
135
|
resolveFn = res;
|
|
134
136
|
rejectFn = rej;
|
|
135
137
|
});
|
|
136
|
-
const initialParticipantIds = deps._telemetryParticipantIds ?? [
|
|
138
|
+
const initialParticipantIds = deps._telemetryParticipantIds ?? [
|
|
139
|
+
getReadGuardCorrelationId(deps.event),
|
|
140
|
+
];
|
|
137
141
|
const entry = {
|
|
138
142
|
timer: setTimeout(() => {
|
|
139
143
|
debouncedPipelines.delete(filePath);
|
|
@@ -183,25 +187,16 @@ function singleRange(ranges) {
|
|
|
183
187
|
return ranges?.length === 1 ? ranges[0] : undefined;
|
|
184
188
|
}
|
|
185
189
|
function recordProjectChange(args) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
source: args.source,
|
|
197
|
-
filePath: path.resolve(args.filePath),
|
|
198
|
-
fileSeq,
|
|
199
|
-
changedRange: args.changedRange,
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
catch (err) {
|
|
203
|
-
args.dbg(`project change log append failed for ${args.filePath}: ${err}`);
|
|
204
|
-
}
|
|
190
|
+
// One mutation seam (#2000 phase 1): bump + receipt + change-log live in
|
|
191
|
+
// RuntimeCoordinator.recordProjectMutation; this wrapper only carries the
|
|
192
|
+
// legacy dbg shape.
|
|
193
|
+
args.runtime.recordProjectMutation?.({
|
|
194
|
+
filePath: args.filePath,
|
|
195
|
+
source: args.source,
|
|
196
|
+
cwd: args.cwd,
|
|
197
|
+
changedRange: args.changedRange,
|
|
198
|
+
onAppendError: (err) => args.dbg(`project change log append failed for ${args.filePath}: ${err}`),
|
|
199
|
+
});
|
|
205
200
|
}
|
|
206
201
|
export async function handleToolResult(deps) {
|
|
207
202
|
const { event, getFlag, getFlagSource, dbg, runtime, cacheManager, biomeClient, ruffClient, metricsClient, resetLSPService, agentBehaviorRecord, formatBehaviorWarnings, } = deps;
|
|
@@ -233,7 +228,9 @@ export async function handleToolResult(deps) {
|
|
|
233
228
|
if (attribution) {
|
|
234
229
|
resolutionBasis = attribution.originCwd;
|
|
235
230
|
}
|
|
236
|
-
else if (toolCallId !== undefined &&
|
|
231
|
+
else if (toolCallId !== undefined &&
|
|
232
|
+
rawFilePath &&
|
|
233
|
+
!path.isAbsolute(rawFilePath)) {
|
|
237
234
|
// A real correlation id existed (the host DOES support one) but no
|
|
238
235
|
// attribution was recorded under it — evicted, cleared because the
|
|
239
236
|
// call was blocked before it could execute, or simply never seen by
|
|
@@ -316,22 +313,128 @@ export async function handleToolResult(deps) {
|
|
|
316
313
|
if (event.toolName === "bash" &&
|
|
317
314
|
typeof event.input.command === "string") {
|
|
318
315
|
const command = event.input.command;
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
316
|
+
const recognized = extractWrittenPathsFromCommand(command, workspaceRoot);
|
|
317
|
+
// The SURVIVING recognized set: what will actually dispatch. Failure
|
|
318
|
+
// atomicity (#2000 invariant 5) means opaque recovery must subtract
|
|
319
|
+
// THIS set, not raw recognized - otherwise a redirect target dropped
|
|
320
|
+
// by the isError filter would be subtracted from recovery AND
|
|
321
|
+
// excluded here, attributed nowhere.
|
|
322
|
+
const recognizedWritten = event.isError !== true
|
|
323
|
+
? recognized.filter((wp) => !isExternalOrVendorFile(wp, workspaceRoot) &&
|
|
324
|
+
!isPathIgnoredByProject(wp, workspaceRoot, false))
|
|
325
|
+
: [];
|
|
326
|
+
// #2000 phase 2: when the extractor recognizes NOTHING, the command is
|
|
327
|
+
// opaque-candidate — recover its actual changed set by diffing the pre
|
|
328
|
+
// snapshot taken at tool_call. Partial writes that landed before a
|
|
329
|
+
// nonzero exit ARE attributed (the files changed and the agent authored
|
|
330
|
+
// them) — a deliberate divergence from the isError filter above, which
|
|
331
|
+
// exists for restore semantics where attribution would lie.
|
|
332
|
+
let opaquePaths = [];
|
|
333
|
+
// Recovery runs for EVERY bash command with a pending baseline - not
|
|
334
|
+
// only recognized-empty ones. A mixed command (`python x.py > out.ts`
|
|
335
|
+
// plus script-internal writes) previously skipped observation entirely
|
|
336
|
+
// with zero telemetry; git-first recovery is cheap enough (~60ms) to
|
|
337
|
+
// close that gap, subtracting already-recognized paths so nothing
|
|
338
|
+
// double-dispatches.
|
|
339
|
+
if (workspaceRoot && !getFlag("no-read-guard")) {
|
|
340
|
+
const scanRoot = workspaceRoot;
|
|
341
|
+
const started = Date.now();
|
|
342
|
+
const pending = getOpaqueBaselineStore().take(`${normalizeMapKey(path.resolve(scanRoot))}:${runtime.sessionGeneration}`);
|
|
343
|
+
let unknownReason;
|
|
344
|
+
if (!pending && recognized.length > 0) {
|
|
345
|
+
// Partial coverage without observation: the explicit verdict
|
|
346
|
+
// invariant 1 demands (never silently imply no change).
|
|
347
|
+
unknownReason = "partial-recognition-no-baseline";
|
|
348
|
+
}
|
|
349
|
+
else if (!pending) {
|
|
350
|
+
unknownReason = "no-pending-snapshot";
|
|
351
|
+
}
|
|
352
|
+
else if (pending.strategy === "git") {
|
|
353
|
+
// Git-first: no universe cap - works on any repo size.
|
|
354
|
+
const recovery = await recoverOpaqueChangesViaGit(scanRoot, pending.startedAt);
|
|
355
|
+
if (recovery.verdict === "recovered") {
|
|
356
|
+
opaquePaths = recovery.paths.filter((p) => !isExternalOrVendorFile(p, scanRoot) &&
|
|
357
|
+
!isPathIgnoredByProject(p, scanRoot, false));
|
|
358
|
+
}
|
|
359
|
+
else if (recovery.verdict === "unknown" && recognized.length > 0) {
|
|
360
|
+
// Git hiccup on a partially-recognized command: the
|
|
361
|
+
// remainder's coverage is unknown, never clean-by-default.
|
|
362
|
+
unknownReason = recovery.unknownReason;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (pending.stats) {
|
|
366
|
+
const outcome = await captureFileStats(scanRoot, {
|
|
367
|
+
withHashes: true,
|
|
368
|
+
});
|
|
369
|
+
if (outcome.snapshot && !outcome.unknownReason) {
|
|
370
|
+
opaquePaths = diffFileStats(pending.stats, outcome.snapshot);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
unknownReason =
|
|
374
|
+
outcome.unknownReason ??
|
|
375
|
+
pending.statsUnknownReason ??
|
|
376
|
+
"walk-failed";
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
unknownReason = pending.statsUnknownReason ?? "walk-failed";
|
|
381
|
+
}
|
|
382
|
+
if (opaquePaths.length > 0 && recognizedWritten.length > 0) {
|
|
383
|
+
const survivingKeys = new Set(recognizedWritten.map((p) => normalizeMapKey(path.resolve(p))));
|
|
384
|
+
opaquePaths = opaquePaths.filter((p) => !survivingKeys.has(p));
|
|
385
|
+
}
|
|
386
|
+
if (unknownReason) {
|
|
387
|
+
logLatency({
|
|
388
|
+
type: "phase",
|
|
389
|
+
phase: "opaque_mutation_coverage_unknown",
|
|
390
|
+
filePath: command.slice(0, 80),
|
|
391
|
+
durationMs: Date.now() - started,
|
|
392
|
+
result: unknownReason,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
if (opaquePaths.length > 0) {
|
|
396
|
+
logLatency({
|
|
397
|
+
type: "phase",
|
|
398
|
+
phase: "opaque_mutation_recovered",
|
|
399
|
+
filePath: opaquePaths.slice(0, 5).join(","),
|
|
400
|
+
durationMs: Date.now() - started,
|
|
401
|
+
result: `changed:${opaquePaths.length}`,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// wp iterates opaquePaths VERBATIM (already normalizeMapKey keys), so the
|
|
406
|
+
// set must hold those exact strings - no re-resolution.
|
|
407
|
+
const opaqueSet = new Set(opaquePaths);
|
|
408
|
+
const written = [...recognizedWritten, ...opaquePaths];
|
|
322
409
|
for (const wp of written) {
|
|
323
410
|
if (!getFlag("no-read-guard"))
|
|
324
411
|
deps.readGuard?.recordWritten(wp);
|
|
325
|
-
const receipt = runtime
|
|
412
|
+
const receipt = runtime
|
|
413
|
+
.recordMutationToolReceipt;
|
|
326
414
|
const autofixMode = receipt
|
|
327
415
|
? receipt.call(runtime, wp, "write").autofixMode
|
|
328
416
|
: "immediate";
|
|
417
|
+
// Recovered opaque writes carry their own source so the change log
|
|
418
|
+
// distinguishes them from parsed writes (auditable in production).
|
|
419
|
+
const isOpaque = opaqueSet.has(wp);
|
|
420
|
+
// Failure atomicity: an opaque-recovered file VERIFIABLY exists on
|
|
421
|
+
// disk, so its synthetic event must not inherit isError - the main
|
|
422
|
+
// path early-returns on failed host results before attribution,
|
|
423
|
+
// which would silently drop exactly the partial writes invariant 5
|
|
424
|
+
// says to attribute.
|
|
425
|
+
const syntheticEvent = {
|
|
426
|
+
...event,
|
|
427
|
+
toolName: "write",
|
|
428
|
+
input: { path: wp },
|
|
429
|
+
isError: false,
|
|
430
|
+
};
|
|
329
431
|
const syntheticResult = await handleToolResult({
|
|
330
432
|
...deps,
|
|
331
|
-
event:
|
|
433
|
+
event: syntheticEvent,
|
|
332
434
|
_bypassDebounce: true,
|
|
333
435
|
_autofixMode: autofixMode,
|
|
334
436
|
_attachmentBudget: syntheticAttachmentBudget,
|
|
437
|
+
_mutationSourceOverride: isOpaque ? "opaque-script" : undefined,
|
|
335
438
|
});
|
|
336
439
|
if (syntheticResult) {
|
|
337
440
|
// #1590: forward verbatim. The synthetic call already charged the
|
|
@@ -475,9 +578,11 @@ export async function handleToolResult(deps) {
|
|
|
475
578
|
}
|
|
476
579
|
// Must happen before debounce admission: latestDeps intentionally retains only
|
|
477
580
|
// the latest event, but write -> edit is a sticky turn transition.
|
|
478
|
-
const receipt = runtime
|
|
581
|
+
const receipt = runtime
|
|
582
|
+
.recordMutationToolReceipt;
|
|
479
583
|
const autofixMode = deps._bypassDebounce
|
|
480
|
-
? (deps._autofixMode ??
|
|
584
|
+
? (deps._autofixMode ??
|
|
585
|
+
(event.toolName === "edit" ? "deferred" : "immediate"))
|
|
481
586
|
: receipt
|
|
482
587
|
? receipt.call(runtime, filePath, event.toolName).autofixMode
|
|
483
588
|
: event.toolName === "edit"
|
|
@@ -612,7 +717,8 @@ export async function handleToolResult(deps) {
|
|
|
612
717
|
runtime,
|
|
613
718
|
cwd: turnStateCwd,
|
|
614
719
|
filePath,
|
|
615
|
-
source:
|
|
720
|
+
source: deps._mutationSourceOverride ??
|
|
721
|
+
sourceForToolName(event.toolName, event.details),
|
|
616
722
|
changedRange: singleRange(modifiedRanges),
|
|
617
723
|
dbg,
|
|
618
724
|
});
|
|
@@ -807,7 +913,9 @@ export async function handleToolResult(deps) {
|
|
|
807
913
|
}
|
|
808
914
|
}
|
|
809
915
|
let autofixNewlyQueued = false;
|
|
810
|
-
if (!result.isError &&
|
|
916
|
+
if (!result.isError &&
|
|
917
|
+
autofixMode === "deferred" &&
|
|
918
|
+
nodeFs.existsSync(filePath)) {
|
|
811
919
|
autofixNewlyQueued =
|
|
812
920
|
runtime.deferMutation?.call(runtime, filePath, dispatchCwd, event.toolName, turnStateCwd, "autofix", deps.sessionId, resolutionBasis) ?? false;
|
|
813
921
|
dbg(`tool_result: queued deferred autofix for ${filePath}`);
|
|
@@ -841,7 +949,13 @@ export async function handleToolResult(deps) {
|
|
|
841
949
|
}
|
|
842
950
|
}
|
|
843
951
|
if (autofixNewlyQueued && !formatQueued) {
|
|
844
|
-
publishFormatQueued({
|
|
952
|
+
publishFormatQueued({
|
|
953
|
+
filePath,
|
|
954
|
+
cwd: dispatchCwd,
|
|
955
|
+
tool: event.toolName,
|
|
956
|
+
kinds: ["autofix"],
|
|
957
|
+
dbg,
|
|
958
|
+
});
|
|
845
959
|
}
|
|
846
960
|
for (const changedFile of result.changedFiles ?? []) {
|
|
847
961
|
const resolvedChanged = path.resolve(changedFile);
|