@herbertgao/pi-extensions 2026.9.6 → 2026.9.7
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 +3 -8
- package/THIRD_PARTY_NOTICES.md +0 -4
- package/node_modules/@narumitw/pi-btw/README.md +2 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +52 -53
- package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
- package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
- package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
- package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
- package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
- package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
- package/node_modules/pi-lens/CHANGELOG.md +239 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
- package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
- package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
- package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
- package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
- package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
- package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
- package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
- package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
- package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
- package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
- package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
- package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
- package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
- package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
- package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
- package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
- package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
- package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
- package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
- package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
- package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
- package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
- package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
- package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
- package/node_modules/pi-lens/dist/index.js +27416 -24153
- package/node_modules/pi-lens/dist/mcp/server.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
- package/node_modules/pi-lens/docs/audit1.md +5 -5
- package/node_modules/pi-lens/docs/dependencies.md +11 -0
- package/node_modules/pi-lens/docs/dispositions.md +52 -0
- package/node_modules/pi-lens/docs/environment-variables.md +2 -2
- package/node_modules/pi-lens/docs/features.md +4 -4
- package/node_modules/pi-lens/docs/globalconfig.md +3 -1
- package/node_modules/pi-lens/docs/language-coverage.md +1 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
- package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
- package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
- package/node_modules/pi-lens/docs/settings.md +7 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +2 -0
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
- package/package.json +5 -11
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
- package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
- 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 +0 -54
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
- package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { TERRAGRUNT_FILENAMES } from "./file-kinds.js";
|
|
4
|
+
import { recordDegradationOnce } from "./degradation-ledger.js";
|
|
4
5
|
import { logLatency } from "./latency-logger.js";
|
|
5
6
|
import { resolvePackagePath } from "./package-root.js";
|
|
6
7
|
import { findNearestContaining, normalizeMapKey, walkUpDirs, } from "./path-utils.js";
|
|
@@ -371,6 +372,24 @@ const FORMATTER_POLICY_BY_EXTENSION = new Map([
|
|
|
371
372
|
gate: "smart-default",
|
|
372
373
|
},
|
|
373
374
|
],
|
|
375
|
+
[
|
|
376
|
+
".typ",
|
|
377
|
+
{
|
|
378
|
+
formatterNames: ["typstyle"],
|
|
379
|
+
defaultFormatter: "typstyle",
|
|
380
|
+
defaultWhenUnconfigured: true,
|
|
381
|
+
gate: "smart-default",
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
[
|
|
385
|
+
".typc",
|
|
386
|
+
{
|
|
387
|
+
formatterNames: ["typstyle"],
|
|
388
|
+
defaultFormatter: "typstyle",
|
|
389
|
+
defaultWhenUnconfigured: true,
|
|
390
|
+
gate: "smart-default",
|
|
391
|
+
},
|
|
392
|
+
],
|
|
374
393
|
[
|
|
375
394
|
".c",
|
|
376
395
|
{
|
|
@@ -738,6 +757,7 @@ const AUTO_INSTALLABLE_DEFAULT_FORMATTERS = new Map([
|
|
|
738
757
|
["shfmt", "shfmt"],
|
|
739
758
|
["taplo", "taplo"],
|
|
740
759
|
["ktlint", "ktlint"],
|
|
760
|
+
["typstyle", "typstyle"],
|
|
741
761
|
]);
|
|
742
762
|
// `gate: "smart-default"` so a matched file is formatted only when nothing else
|
|
743
763
|
// claims it. Misdetection edge: `root.hcl` is filename-detected as terragrunt, so
|
|
@@ -1633,17 +1653,25 @@ export function getAutofixPolicyForFile(filePath, context = {}) {
|
|
|
1633
1653
|
export function getPreferredAutofixTools(filePath, context) {
|
|
1634
1654
|
return getAutofixPolicyForFile(filePath, context)?.preferredTools ?? [];
|
|
1635
1655
|
}
|
|
1636
|
-
|
|
1656
|
+
// Flat-config filenames resolve like ESLint itself: upward from cwd without
|
|
1657
|
+
// stopping at an intermediate package.json (#3017, shape 39). Legacy
|
|
1658
|
+
// `.eslintrc.*` names and the `package.json#eslintConfig` field keep the
|
|
1659
|
+
// historic per-package boundary below.
|
|
1660
|
+
const ESLINT_FLAT_CONFIGS = [
|
|
1661
|
+
"eslint.config.js",
|
|
1662
|
+
"eslint.config.mjs",
|
|
1663
|
+
"eslint.config.cjs",
|
|
1664
|
+
"eslint.config.ts",
|
|
1665
|
+
"eslint.config.mts",
|
|
1666
|
+
"eslint.config.cts",
|
|
1667
|
+
];
|
|
1668
|
+
const ESLINT_LEGACY_CONFIGS = [
|
|
1637
1669
|
".eslintrc",
|
|
1638
1670
|
".eslintrc.js",
|
|
1639
1671
|
".eslintrc.cjs",
|
|
1640
1672
|
".eslintrc.json",
|
|
1641
1673
|
".eslintrc.yaml",
|
|
1642
1674
|
".eslintrc.yml",
|
|
1643
|
-
"eslint.config.js",
|
|
1644
|
-
"eslint.config.mjs",
|
|
1645
|
-
"eslint.config.cjs",
|
|
1646
|
-
"eslint.config.ts",
|
|
1647
1675
|
];
|
|
1648
1676
|
function* walkUpDirsUntilPackageJson(cwd) {
|
|
1649
1677
|
for (const dir of walkUpDirs(cwd)) {
|
|
@@ -1692,8 +1720,19 @@ export function hasNearestPackageJsonField(cwd, fieldName) {
|
|
|
1692
1720
|
return false;
|
|
1693
1721
|
}
|
|
1694
1722
|
export function hasEslintConfig(cwd) {
|
|
1723
|
+
// Flat configs mirror ESLint's own discovery: every ancestor dir up to
|
|
1724
|
+
// the filesystem root, ignoring intermediate package.json boundaries, so
|
|
1725
|
+
// a monorepo root config stays visible from inside a nested package.
|
|
1726
|
+
for (const dir of walkUpDirs(cwd)) {
|
|
1727
|
+
for (const cfg of ESLINT_FLAT_CONFIGS) {
|
|
1728
|
+
if (fs.existsSync(path.join(dir, cfg)))
|
|
1729
|
+
return true;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
// Legacy `.eslintrc.*` and `package.json#eslintConfig` keep per-package
|
|
1733
|
+
// semantics: the walk stops at the nearest package.json.
|
|
1695
1734
|
for (const dir of walkUpDirsUntilPackageJson(cwd)) {
|
|
1696
|
-
for (const cfg of
|
|
1735
|
+
for (const cfg of ESLINT_LEGACY_CONFIGS) {
|
|
1697
1736
|
if (fs.existsSync(path.join(dir, cfg)))
|
|
1698
1737
|
return true;
|
|
1699
1738
|
}
|
|
@@ -2231,6 +2270,16 @@ const KOTLIN_GRADLE_FILES = [
|
|
|
2231
2270
|
"settings.gradle.kts",
|
|
2232
2271
|
"settings.gradle",
|
|
2233
2272
|
];
|
|
2273
|
+
const GRADLE_KTLINT_PLUGIN_PATTERN = /(?:id\s*\(\s*|id\s+|apply\s+plugin\s*:\s*)["']org\.jlleitschuh\.gradle\.ktlint["']/g;
|
|
2274
|
+
const GRADLE_BUILD_LOGIC_DIRS = ["buildSrc", "build-logic"];
|
|
2275
|
+
const GRADLE_BUILD_LOGIC_EXTENSIONS = [".gradle", ".gradle.kts", ".kt"];
|
|
2276
|
+
const GRADLE_INCLUDE_BUILD_PATTERN = /\bincludeBuild\s*\(\s*["']([^"']+)["']/g;
|
|
2277
|
+
/**
|
|
2278
|
+
* Bound the synchronous ownership probe so a large convention tree cannot
|
|
2279
|
+
* stall every autofix. Exceeding it is an unknown ownership result, not proof
|
|
2280
|
+
* of no owner, and callers must decline the write (#3004).
|
|
2281
|
+
*/
|
|
2282
|
+
export const GRADLE_BUILD_LOGIC_SCAN_MAX_ENTRIES = 10_000;
|
|
2234
2283
|
const spotlessKotlinConfigCache = new Map();
|
|
2235
2284
|
let spotlessGradleReadCount = 0;
|
|
2236
2285
|
/** Test-only observability for asserting the hot-path I/O bound. */
|
|
@@ -2429,6 +2478,110 @@ export function getSpotlessKotlinFormatter(cwd) {
|
|
|
2429
2478
|
export function hasKtlintConfig(cwd) {
|
|
2430
2479
|
return getSpotlessKotlinFormatter(cwd) === "ktlint";
|
|
2431
2480
|
}
|
|
2481
|
+
/**
|
|
2482
|
+
* Whether Gradle build logic applies the ktlint Gradle plugin. The plugin
|
|
2483
|
+
* establishes project ownership of ktlint, but its plugin version is not a
|
|
2484
|
+
* ktlint CLI version and must never be used as one (#3000).
|
|
2485
|
+
*/
|
|
2486
|
+
export function hasGradleKtlintPlugin(cwd) {
|
|
2487
|
+
const files = new Set();
|
|
2488
|
+
const scan = { entries: 0, exceeded: false, indeterminate: false };
|
|
2489
|
+
for (const dir of walkUpDirs(cwd)) {
|
|
2490
|
+
for (const gradle of KOTLIN_GRADLE_FILES) {
|
|
2491
|
+
const filePath = path.join(dir, gradle);
|
|
2492
|
+
if (fs.existsSync(filePath))
|
|
2493
|
+
files.add(filePath);
|
|
2494
|
+
}
|
|
2495
|
+
for (const buildLogicDir of GRADLE_BUILD_LOGIC_DIRS) {
|
|
2496
|
+
if (!addGradleBuildLogicFiles(path.join(dir, buildLogicDir), files, scan)) {
|
|
2497
|
+
scan.exceeded = true;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
for (const settings of ["settings.gradle.kts", "settings.gradle"]) {
|
|
2501
|
+
const settingsPath = path.join(dir, settings);
|
|
2502
|
+
if (!fs.existsSync(settingsPath))
|
|
2503
|
+
continue;
|
|
2504
|
+
try {
|
|
2505
|
+
const raw = fs.readFileSync(settingsPath, "utf-8");
|
|
2506
|
+
const stripped = stripGradleCommentsAndStrings(raw);
|
|
2507
|
+
GRADLE_INCLUDE_BUILD_PATTERN.lastIndex = 0;
|
|
2508
|
+
let match;
|
|
2509
|
+
while ((match = GRADLE_INCLUDE_BUILD_PATTERN.exec(raw)) !== null) {
|
|
2510
|
+
const code = stripped.slice(match.index, match.index + match[0].length);
|
|
2511
|
+
const includedBuild = match[1];
|
|
2512
|
+
if (includedBuild && /^\s*includeBuild\s*\(\s*/.test(code)) {
|
|
2513
|
+
if (!addGradleBuildLogicFiles(path.resolve(dir, includedBuild), files, scan)) {
|
|
2514
|
+
scan.exceeded = true;
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
catch {
|
|
2520
|
+
scan.indeterminate = true;
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
if (scan.exceeded) {
|
|
2525
|
+
recordDegradationOnce({
|
|
2526
|
+
kind: "gradle-ktlint-scan-budget-exceeded",
|
|
2527
|
+
subject: "ktlint:gradle-build-logic",
|
|
2528
|
+
reason: `Gradle build-logic ownership scan exceeded its ${GRADLE_BUILD_LOGIC_SCAN_MAX_ENTRIES}-entry budget; ` +
|
|
2529
|
+
"ownership cannot be established, so ktlint autofix is declined",
|
|
2530
|
+
});
|
|
2531
|
+
return { kind: "indeterminate" };
|
|
2532
|
+
}
|
|
2533
|
+
if (scan.indeterminate)
|
|
2534
|
+
return { kind: "indeterminate" };
|
|
2535
|
+
for (const filePath of files) {
|
|
2536
|
+
try {
|
|
2537
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
2538
|
+
const stripped = stripGradleCommentsAndStrings(raw);
|
|
2539
|
+
GRADLE_KTLINT_PLUGIN_PATTERN.lastIndex = 0;
|
|
2540
|
+
let match;
|
|
2541
|
+
while ((match = GRADLE_KTLINT_PLUGIN_PATTERN.exec(raw)) !== null) {
|
|
2542
|
+
const code = stripped.slice(match.index, match.index + match[0].length);
|
|
2543
|
+
if (!/^\s*$/.test(code))
|
|
2544
|
+
return { kind: "owned" };
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
catch {
|
|
2548
|
+
return { kind: "indeterminate" };
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
return { kind: "not-owned" };
|
|
2552
|
+
}
|
|
2553
|
+
function addGradleBuildLogicFiles(root, files, scan) {
|
|
2554
|
+
if (!fs.existsSync(root))
|
|
2555
|
+
return true;
|
|
2556
|
+
const pending = [root];
|
|
2557
|
+
while (pending.length > 0) {
|
|
2558
|
+
const dir = pending.pop();
|
|
2559
|
+
if (!dir)
|
|
2560
|
+
continue;
|
|
2561
|
+
let entries;
|
|
2562
|
+
try {
|
|
2563
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
2564
|
+
}
|
|
2565
|
+
catch {
|
|
2566
|
+
scan.indeterminate = true;
|
|
2567
|
+
continue;
|
|
2568
|
+
}
|
|
2569
|
+
for (const entry of entries) {
|
|
2570
|
+
scan.entries += 1;
|
|
2571
|
+
if (scan.entries > GRADLE_BUILD_LOGIC_SCAN_MAX_ENTRIES)
|
|
2572
|
+
return false;
|
|
2573
|
+
const entryPath = path.join(dir, entry.name);
|
|
2574
|
+
if (entry.isDirectory()) {
|
|
2575
|
+
pending.push(entryPath);
|
|
2576
|
+
}
|
|
2577
|
+
else if (entry.isFile() &&
|
|
2578
|
+
GRADLE_BUILD_LOGIC_EXTENSIONS.some((extension) => entry.name.endsWith(extension))) {
|
|
2579
|
+
files.add(entryPath);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
return true;
|
|
2584
|
+
}
|
|
2432
2585
|
export function hasKtfmtConfig(cwd) {
|
|
2433
2586
|
const spotlessFormatter = getSpotlessKotlinFormatter(cwd);
|
|
2434
2587
|
if (spotlessFormatter)
|
|
@@ -2557,7 +2710,10 @@ const OXLINT_CONFIGS = [
|
|
|
2557
2710
|
"oxlint.config.mts",
|
|
2558
2711
|
];
|
|
2559
2712
|
export function hasOxlintConfig(cwd) {
|
|
2560
|
-
|
|
2713
|
+
// Oxlint auto-discovers the nearest config by file location, so the walk
|
|
2714
|
+
// ignores intermediate package.json boundaries just like the flat
|
|
2715
|
+
// ESLint branch above (#3017).
|
|
2716
|
+
for (const dir of walkUpDirs(cwd)) {
|
|
2561
2717
|
for (const cfg of OXLINT_CONFIGS) {
|
|
2562
2718
|
if (fs.existsSync(path.join(dir, cfg)))
|
|
2563
2719
|
return true;
|
|
@@ -57,6 +57,14 @@ const PYTHON_SQL_SINK_METHODS = new Set([
|
|
|
57
57
|
"query",
|
|
58
58
|
"raw",
|
|
59
59
|
]);
|
|
60
|
+
const TYPESCRIPT_SQL_KNOWN_PACKAGES = new Set([
|
|
61
|
+
"pg",
|
|
62
|
+
"mysql2",
|
|
63
|
+
"better-sqlite3",
|
|
64
|
+
"knex",
|
|
65
|
+
"@prisma/client",
|
|
66
|
+
]);
|
|
67
|
+
const TYPESCRIPT_SQL_IMPORTS = new WeakMap();
|
|
60
68
|
const NOT_PARSED = { parsed: false };
|
|
61
69
|
function createParserCounters() {
|
|
62
70
|
return {
|
|
@@ -3408,6 +3416,118 @@ export class TreeSitterClient {
|
|
|
3408
3416
|
case "ts_command_injection_sink":
|
|
3409
3417
|
return (captures.MOD?.text === "child_process" &&
|
|
3410
3418
|
/^(exec|execSync)$/.test(captures.FN?.text ?? ""));
|
|
3419
|
+
case "ts_sql_injection_sink": {
|
|
3420
|
+
const template = captures.TEMPLATE?.text ?? "";
|
|
3421
|
+
// Inspect only the template's raw prefix. Leading SQL comments are
|
|
3422
|
+
// ignored; comments and unrelated strings elsewhere cannot satisfy it.
|
|
3423
|
+
const rawPrefix = template
|
|
3424
|
+
.replace(/^`/, "")
|
|
3425
|
+
.replace(/`$/, "")
|
|
3426
|
+
.replace(/^(?:\s|\/\*[\s\S]*?\*\/|--[^\n]*(?:\n|$))*/, "");
|
|
3427
|
+
if (/^(?:SELECT[\s\S]*(?:\bFROM\b|\$\{)|INSERT\s+INTO\b|UPDATE\s+[\s\S]*\bSET\b|DELETE\s+FROM\b|CREATE\s+(?:OR\s+REPLACE\s+|TEMP(?:ORARY)?\s+|UNIQUE\s+|MATERIALIZED\s+)*(?:TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|PROCEDURE|SEQUENCE|TYPE|EXTENSION)\b|DROP\s+(?:OR\s+REPLACE\s+|TEMP(?:ORARY)?\s+|UNIQUE\s+|MATERIALIZED\s+)*(?:TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|PROCEDURE|SEQUENCE|TYPE|EXTENSION)\b|ALTER\s+(?:OR\s+REPLACE\s+|TEMP(?:ORARY)?\s+|UNIQUE\s+|MATERIALIZED\s+)*(?:TABLE|INDEX|VIEW|SCHEMA|DATABASE|TRIGGER|FUNCTION|PROCEDURE|SEQUENCE|TYPE|EXTENSION)\b|GRANT\b|REVOKE\b|WITH[\s\S]*\bSELECT\b|MERGE\s+INTO\b|TRUNCATE\s+TABLE\b|REPLACE\s+INTO\b)/i.test(rawPrefix))
|
|
3428
|
+
return true;
|
|
3429
|
+
if (!rootNode || !captures.OBJ)
|
|
3430
|
+
return false;
|
|
3431
|
+
let imported = TYPESCRIPT_SQL_IMPORTS.get(rootNode);
|
|
3432
|
+
if (!imported) {
|
|
3433
|
+
const names = new Set();
|
|
3434
|
+
const stack = [rootNode];
|
|
3435
|
+
while (stack.length > 0) {
|
|
3436
|
+
const node = stack.pop();
|
|
3437
|
+
if (!node)
|
|
3438
|
+
continue;
|
|
3439
|
+
if (node.type === "import_statement") {
|
|
3440
|
+
const source = node.childForFieldName?.("source")?.text ?? "";
|
|
3441
|
+
const packageName = source.replace(/^['"]|['"]$/g, "");
|
|
3442
|
+
const isKnown = [...TYPESCRIPT_SQL_KNOWN_PACKAGES].some((pkg) => packageName === pkg || packageName.startsWith(`${pkg}/`));
|
|
3443
|
+
if (isKnown) {
|
|
3444
|
+
const importStack = [node];
|
|
3445
|
+
while (importStack.length > 0) {
|
|
3446
|
+
const importNode = importStack.pop();
|
|
3447
|
+
if (!importNode)
|
|
3448
|
+
continue;
|
|
3449
|
+
if (importNode.type === "identifier" ||
|
|
3450
|
+
importNode.type === "import_specifier") {
|
|
3451
|
+
names.add(importNode.text);
|
|
3452
|
+
}
|
|
3453
|
+
importStack.push(...importNode.children);
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
stack.push(...node.children);
|
|
3458
|
+
}
|
|
3459
|
+
const declarations = new Map();
|
|
3460
|
+
const declarationStack = [rootNode];
|
|
3461
|
+
while (declarationStack.length > 0) {
|
|
3462
|
+
const node = declarationStack.pop();
|
|
3463
|
+
if (!node)
|
|
3464
|
+
continue;
|
|
3465
|
+
if (node.type === "variable_declarator") {
|
|
3466
|
+
const name = node.childForFieldName?.("name")?.text;
|
|
3467
|
+
const value = node.childForFieldName?.("value");
|
|
3468
|
+
if (name && value)
|
|
3469
|
+
declarations.set(name, value);
|
|
3470
|
+
}
|
|
3471
|
+
declarationStack.push(...node.children);
|
|
3472
|
+
}
|
|
3473
|
+
const resolvesKnownValue = (node, seen = new Set()) => {
|
|
3474
|
+
if (node.type === "identifier") {
|
|
3475
|
+
if (names.has(node.text))
|
|
3476
|
+
return true;
|
|
3477
|
+
if (seen.has(node.text))
|
|
3478
|
+
return false;
|
|
3479
|
+
const value = declarations.get(node.text);
|
|
3480
|
+
if (!value)
|
|
3481
|
+
return false;
|
|
3482
|
+
seen.add(node.text);
|
|
3483
|
+
return resolvesKnownValue(value, seen);
|
|
3484
|
+
}
|
|
3485
|
+
if (node.type === "await_expression") {
|
|
3486
|
+
const value = node.children.find((child) => child.isNamed);
|
|
3487
|
+
return value ? resolvesKnownValue(value, seen) : false;
|
|
3488
|
+
}
|
|
3489
|
+
if (node.type === "new_expression") {
|
|
3490
|
+
const ctor = node.childForFieldName?.("constructor");
|
|
3491
|
+
return ctor ? resolvesKnownValue(ctor, seen) : false;
|
|
3492
|
+
}
|
|
3493
|
+
if (node.type === "call_expression") {
|
|
3494
|
+
const fn = node.childForFieldName?.("function");
|
|
3495
|
+
return fn ? resolvesKnownValue(fn, seen) : false;
|
|
3496
|
+
}
|
|
3497
|
+
return false;
|
|
3498
|
+
};
|
|
3499
|
+
let changed = true;
|
|
3500
|
+
while (changed) {
|
|
3501
|
+
changed = false;
|
|
3502
|
+
for (const [name, value] of declarations) {
|
|
3503
|
+
if (!names.has(name) && resolvesKnownValue(value)) {
|
|
3504
|
+
names.add(name);
|
|
3505
|
+
changed = true;
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
imported = names;
|
|
3510
|
+
TYPESCRIPT_SQL_IMPORTS.set(rootNode, imported);
|
|
3511
|
+
}
|
|
3512
|
+
const resolvesToKnownClient = (node) => {
|
|
3513
|
+
if (node.type === "identifier")
|
|
3514
|
+
return imported.has(node.text);
|
|
3515
|
+
if (node.type === "await_expression") {
|
|
3516
|
+
const value = node.children.find((child) => child.isNamed);
|
|
3517
|
+
return value ? resolvesToKnownClient(value) : false;
|
|
3518
|
+
}
|
|
3519
|
+
if (node.type === "new_expression") {
|
|
3520
|
+
const ctor = node.childForFieldName?.("constructor");
|
|
3521
|
+
return ctor ? resolvesToKnownClient(ctor) : false;
|
|
3522
|
+
}
|
|
3523
|
+
if (node.type === "call_expression") {
|
|
3524
|
+
const fn = node.childForFieldName?.("function");
|
|
3525
|
+
return fn ? resolvesToKnownClient(fn) : false;
|
|
3526
|
+
}
|
|
3527
|
+
return false;
|
|
3528
|
+
};
|
|
3529
|
+
return resolvesToKnownClient(captures.OBJ);
|
|
3530
|
+
}
|
|
3411
3531
|
case "ts_ssrf_sink": {
|
|
3412
3532
|
const fn = captures.FN?.text ?? "";
|
|
3413
3533
|
const obj = captures.OBJ?.text ?? "";
|