@herbertgao/pi-extensions 2026.9.1 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@narumitw/pi-btw/README.md +57 -141
- package/node_modules/@narumitw/pi-btw/dist/index.ts +466 -41
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/docs/workflows.md +74 -0
- package/node_modules/@narumitw/pi-btw/package.json +2 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +15 -1
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +32 -2
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +330 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +136 -19
- package/node_modules/@narumitw/pi-btw/src/settings.ts +32 -0
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +57 -5
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +52 -30
- package/node_modules/pi-lens/CHANGELOG.md +84 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +133 -1
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +0 -6
- package/node_modules/pi-lens/dist/clients/bootstrap.js +4 -4
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +1 -1
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +0 -5
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +1 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +1 -6
- package/node_modules/pi-lens/dist/clients/cargo-manifest.js +2 -2
- package/node_modules/pi-lens/dist/clients/cascade-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/child-unref.js +1 -19
- package/node_modules/pi-lens/dist/clients/config-core/index.js +11 -8
- package/node_modules/pi-lens/dist/clients/config-core/process-spec.js +1 -1
- package/node_modules/pi-lens/dist/clients/config-core/provenance.js +2 -9
- package/node_modules/pi-lens/dist/clients/config-core/records.js +1 -1
- package/node_modules/pi-lens/dist/clients/config-core/schema.js +3 -5
- package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +1 -1
- package/node_modules/pi-lens/dist/clients/config-resolve.js +4 -4
- package/node_modules/pi-lens/dist/clients/config-schema.js +39 -2
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +0 -4
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +1 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +0 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +0 -26
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +0 -6
- package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +0 -3
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-complexity.js +2 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/high-fan-out.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +1 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +6 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +4 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/diagnostic-parsers.js +1 -64
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils.js +0 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +2 -20
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +1 -0
- package/node_modules/pi-lens/dist/clients/dispatch/utils/format-utils.js +2 -2
- package/node_modules/pi-lens/dist/clients/disposition-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +2 -2
- package/node_modules/pi-lens/dist/clients/file-kinds.js +1 -38
- package/node_modules/pi-lens/dist/clients/file-time.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-utils.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-service.js +0 -1
- package/node_modules/pi-lens/dist/clients/formatters.js +110 -3
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +3 -4
- package/node_modules/pi-lens/dist/clients/git-guard.js +5 -0
- package/node_modules/pi-lens/dist/clients/grammar-source.js +3 -3
- package/node_modules/pi-lens/dist/clients/installer/index.js +220 -9
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +84 -18
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +6 -6
- package/node_modules/pi-lens/dist/clients/language-profile.js +0 -9
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +5 -7
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +19 -0
- package/node_modules/pi-lens/dist/clients/lens-engine.js +3 -4
- package/node_modules/pi-lens/dist/clients/lens-events.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +18 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +1 -1
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +0 -36
- package/node_modules/pi-lens/dist/clients/lsp/client.js +4 -3
- package/node_modules/pi-lens/dist/clients/lsp/config.js +1 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +3 -3
- package/node_modules/pi-lens/dist/clients/lsp/index.js +216 -25
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/language.js +0 -8
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +0 -2
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +0 -1
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +5 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +6 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +28 -107
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +1 -1
- package/node_modules/pi-lens/dist/clients/module-report.js +1 -1
- package/node_modules/pi-lens/dist/clients/mutating-tool.js +3 -3
- package/node_modules/pi-lens/dist/clients/mutation-attribution.js +3 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +0 -4
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +9 -9
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +2 -6
- package/node_modules/pi-lens/dist/clients/opengrep-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/path-utils.js +23 -2
- package/node_modules/pi-lens/dist/clients/performance-report.js +2 -2
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +2 -2
- package/node_modules/pi-lens/dist/clients/project-changes.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/jscpd.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/knip.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/opengrep.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +46 -1
- package/node_modules/pi-lens/dist/clients/project-scan-policy.js +3 -51
- package/node_modules/pi-lens/dist/clients/python-provenance.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +5 -2
- package/node_modules/pi-lens/dist/clients/recent-touches.js +2 -2
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +3 -5
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-session.js +45 -10
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +11 -1
- package/node_modules/pi-lens/dist/clients/sanitize.js +0 -11
- package/node_modules/pi-lens/dist/clients/scan-utils.js +1 -56
- package/node_modules/pi-lens/dist/clients/session-summary.js +0 -24
- package/node_modules/pi-lens/dist/clients/sgconfig.js +1 -5
- package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +2 -2
- package/node_modules/pi-lens/dist/clients/startup-scan.js +2 -10
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +77 -72
- package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +1 -52
- package/node_modules/pi-lens/dist/clients/tui-fit.js +0 -4
- package/node_modules/pi-lens/dist/clients/user-notify.js +0 -4
- package/node_modules/pi-lens/dist/clients/word-index-logger.js +0 -7
- package/node_modules/pi-lens/dist/clients/word-index-store.js +3 -7
- package/node_modules/pi-lens/dist/clients/word-index.js +9 -16
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +1 -1
- package/node_modules/pi-lens/dist/index.js +1062 -538
- package/node_modules/pi-lens/dist/mcp/build-staleness.js +1 -1
- package/node_modules/pi-lens/dist/scripts/lib/process-scan.mjs +1 -1
- package/node_modules/pi-lens/dist/scripts/lib/skills-predicate.mjs +1 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +1 -1
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +37 -6
- package/node_modules/pi-lens/dist/tools/lsp-structured-output.js +3 -3
- package/node_modules/pi-lens/dist/tools/render-compact.js +1 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -2
- package/node_modules/pi-lens/docs/globalconfig.md +20 -0
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +9 -1
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +6 -0
- package/node_modules/pi-lens/docs/pi-lens-subagent.md +12 -1
- package/node_modules/pi-lens/docs/release-qa-baseline.md +12 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +7 -3
- package/node_modules/pi-lens/docs/word-index.md +1 -1
- package/node_modules/pi-lens/package.json +6 -15
- package/node_modules/pi-lens/rules/typos/_typos.toml +4 -2
- package/node_modules/pi-lens/scripts/lib/skills-predicate.mjs +1 -1
- package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +1 -1
- package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +4 -2
- package/package.json +3 -3
|
@@ -2,17 +2,14 @@
|
|
|
2
2
|
* Automatic test-runner delivery for the post-agent idle window (#2366).
|
|
3
3
|
*
|
|
4
4
|
* Test results remain in `test-runner-findings` for pull diagnostics and the
|
|
5
|
-
* commit guard. This module
|
|
6
|
-
*
|
|
5
|
+
* commit guard. This module stages an owner-qualified pointer and marks it
|
|
6
|
+
* eligible for the next context build after the host proves that the agent is
|
|
7
7
|
* idle. Provenance validation stays in `peekTestFindings`, the one shared
|
|
8
8
|
* delivery gate for this cache.
|
|
9
9
|
*/
|
|
10
10
|
import { emitBounded } from "./bounded-telemetry.js";
|
|
11
|
-
import { peekTestFindings } from "./runtime-context.js";
|
|
12
|
-
import { fitLines } from "./tui-fit.js";
|
|
13
|
-
export const TEST_RUNNER_ENTRY_TYPE = "pilens:test-runner-findings";
|
|
11
|
+
import { consumeTestFindings, peekTestFindings } from "./runtime-context.js";
|
|
14
12
|
const MAX_PENDING_DELIVERIES = 32;
|
|
15
|
-
const MAX_ENTRY_CONTENT = 12_000;
|
|
16
13
|
const pending = new Map();
|
|
17
14
|
function key(cwd, sessionId, ownerId) {
|
|
18
15
|
// `cwd` comes from the same host session field at turn_end and settle. Keep
|
|
@@ -20,14 +17,6 @@ function key(cwd, sessionId, ownerId) {
|
|
|
20
17
|
// identity; dispatch contexts already normalize their own path fields.
|
|
21
18
|
return `${ownerId ?? "direct"}\u0000${cwd}\u0000${sessionId}`;
|
|
22
19
|
}
|
|
23
|
-
function boundedContent(content) {
|
|
24
|
-
if (content.length <= MAX_ENTRY_CONTENT)
|
|
25
|
-
return { content, droppedDetailCount: 0 };
|
|
26
|
-
return {
|
|
27
|
-
content: `${content.slice(0, MAX_ENTRY_CONTENT)}\n[…details truncated]`,
|
|
28
|
-
droppedDetailCount: content.length - MAX_ENTRY_CONTENT,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
20
|
function record(identity, outcome, delivery, metadata = {}) {
|
|
32
21
|
emitBounded("test_runner_delivery", identity, {
|
|
33
22
|
filePath: delivery.cwd,
|
|
@@ -44,9 +33,7 @@ function record(identity, outcome, delivery, metadata = {}) {
|
|
|
44
33
|
},
|
|
45
34
|
}, {
|
|
46
35
|
capPerTurn: { limit: 8, turnIndex: delivery.generation },
|
|
47
|
-
ledgerKind: outcome === "delivery-failed"
|
|
48
|
-
? "test-runner-delivery"
|
|
49
|
-
: undefined,
|
|
36
|
+
ledgerKind: outcome === "delivery-failed" ? "test-runner-delivery" : undefined,
|
|
50
37
|
reason: `test runner delivery ${outcome}`,
|
|
51
38
|
});
|
|
52
39
|
}
|
|
@@ -70,6 +57,7 @@ export function stageTestRunnerDelivery(args) {
|
|
|
70
57
|
generation: args.generation,
|
|
71
58
|
targetCount: args.targetCount,
|
|
72
59
|
createdAt: Date.now(),
|
|
60
|
+
eligible: false,
|
|
73
61
|
owner: args.owner,
|
|
74
62
|
};
|
|
75
63
|
record(deliveryKey, "superseded", superseded, {
|
|
@@ -95,13 +83,14 @@ export function stageTestRunnerDelivery(args) {
|
|
|
95
83
|
generation: args.generation,
|
|
96
84
|
targetCount: args.targetCount,
|
|
97
85
|
createdAt: Date.now(),
|
|
86
|
+
eligible: false,
|
|
98
87
|
owner: args.owner,
|
|
99
88
|
};
|
|
100
89
|
pending.set(deliveryKey, delivery);
|
|
101
90
|
prunePending();
|
|
102
91
|
record(deliveryKey, "staged", delivery);
|
|
103
92
|
}
|
|
104
|
-
/**
|
|
93
|
+
/** Mark the latest staged result eligible during a host-confirmed idle window. */
|
|
105
94
|
export function deliverTestRunnerFindings(args) {
|
|
106
95
|
const cwd = args.ctx.cwd ?? process.cwd();
|
|
107
96
|
const deliveryKey = key(cwd, args.sessionId, args.ownerId);
|
|
@@ -112,16 +101,11 @@ export function deliverTestRunnerFindings(args) {
|
|
|
112
101
|
if (currentGeneration !== undefined &&
|
|
113
102
|
currentGeneration > delivery.generation) {
|
|
114
103
|
pending.delete(deliveryKey);
|
|
115
|
-
record(deliveryKey, "superseded", delivery, {
|
|
116
|
-
currentGeneration,
|
|
117
|
-
});
|
|
104
|
+
record(deliveryKey, "superseded", delivery, { currentGeneration });
|
|
118
105
|
return;
|
|
119
106
|
}
|
|
120
107
|
if (typeof args.ctx.isIdle !== "function") {
|
|
121
108
|
pending.delete(deliveryKey);
|
|
122
|
-
record(deliveryKey, "capability-unavailable", delivery, {
|
|
123
|
-
reason: "host does not expose ctx.isIdle",
|
|
124
|
-
});
|
|
125
109
|
return;
|
|
126
110
|
}
|
|
127
111
|
try {
|
|
@@ -136,14 +120,13 @@ export function deliverTestRunnerFindings(args) {
|
|
|
136
120
|
});
|
|
137
121
|
return;
|
|
138
122
|
}
|
|
139
|
-
|
|
140
|
-
if (!findings) {
|
|
123
|
+
if (!peekTestFindings(args.cacheManager, cwd, args.runtime, true)) {
|
|
141
124
|
pending.delete(deliveryKey);
|
|
142
125
|
record(deliveryKey, "superseded", delivery);
|
|
143
126
|
return;
|
|
144
127
|
}
|
|
145
|
-
// Recheck immediately before
|
|
146
|
-
// the first check and this synchronous call.
|
|
128
|
+
// Recheck immediately before marking eligible. The host may accept a prompt
|
|
129
|
+
// between the first check and this synchronous call.
|
|
147
130
|
try {
|
|
148
131
|
if (!args.ctx.isIdle()) {
|
|
149
132
|
record(deliveryKey, "carried", delivery);
|
|
@@ -156,32 +139,23 @@ export function deliverTestRunnerFindings(args) {
|
|
|
156
139
|
});
|
|
157
140
|
return;
|
|
158
141
|
}
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
142
|
+
delivery.eligible = true;
|
|
143
|
+
const current = args.cacheManager.readCache("test-runner-findings", cwd)?.data;
|
|
144
|
+
if (!current?.content || current.testRunGeneration !== delivery.generation) {
|
|
162
145
|
pending.delete(deliveryKey);
|
|
163
|
-
record(deliveryKey, "capability-unavailable", delivery);
|
|
164
146
|
return;
|
|
165
147
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
...bounded,
|
|
148
|
+
args.cacheManager.writeCache("test-runner-findings", {
|
|
149
|
+
...current,
|
|
150
|
+
deliveryEligible: {
|
|
170
151
|
sessionId: delivery.sessionId,
|
|
171
152
|
generation: delivery.generation,
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
catch (error) {
|
|
181
|
-
record(deliveryKey, "delivery-failed", delivery, {
|
|
182
|
-
error: String(error).slice(0, 500),
|
|
183
|
-
});
|
|
184
|
-
}
|
|
153
|
+
eligibleAt: Date.now(),
|
|
154
|
+
},
|
|
155
|
+
}, cwd);
|
|
156
|
+
record(deliveryKey, "eligible", delivery, {
|
|
157
|
+
ageMs: Math.max(0, Date.now() - delivery.createdAt),
|
|
158
|
+
});
|
|
185
159
|
}
|
|
186
160
|
/** Deliver only the result staged by this activation and settled session. */
|
|
187
161
|
export function deliverStagedTestRunnerFindings(args) {
|
|
@@ -195,7 +169,6 @@ export function deliverStagedTestRunnerFindings(args) {
|
|
|
195
169
|
if (!delivery?.owner)
|
|
196
170
|
return;
|
|
197
171
|
deliverTestRunnerFindings({
|
|
198
|
-
pi: delivery.owner.pi,
|
|
199
172
|
ctx: delivery.owner.getCtx(),
|
|
200
173
|
cacheManager: delivery.owner.cacheManager,
|
|
201
174
|
runtime: delivery.owner.runtime,
|
|
@@ -203,31 +176,63 @@ export function deliverStagedTestRunnerFindings(args) {
|
|
|
203
176
|
ownerId: delivery.ownerId,
|
|
204
177
|
});
|
|
205
178
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
179
|
+
/** Consume the result made eligible by the settled idle boundary. */
|
|
180
|
+
export function consumeStagedTestRunnerFindings(args) {
|
|
181
|
+
const deliveryKey = key(args.cwd, args.sessionId, args.ownerId);
|
|
182
|
+
let delivery = pending.get(deliveryKey);
|
|
183
|
+
const persisted = args.cacheManager.readCache("test-runner-findings", args.cwd)?.data;
|
|
184
|
+
const eligible = persisted?.deliveryEligible;
|
|
185
|
+
if (!delivery && persisted?.content && eligible) {
|
|
186
|
+
const sameSession = eligible.sessionId === args.sessionId;
|
|
187
|
+
if (!sameSession) {
|
|
188
|
+
const foreignDelivery = {
|
|
189
|
+
cwd: args.cwd,
|
|
190
|
+
sessionId: eligible.sessionId,
|
|
191
|
+
generation: eligible.generation,
|
|
192
|
+
targetCount: 0,
|
|
193
|
+
createdAt: eligible.eligibleAt,
|
|
194
|
+
eligible: true,
|
|
195
|
+
rehydrated: true,
|
|
196
|
+
};
|
|
197
|
+
record(deliveryKey, "foreign-session", foreignDelivery, {
|
|
198
|
+
currentSessionId: args.sessionId,
|
|
199
|
+
currentOwnerId: args.ownerId,
|
|
200
|
+
reason: "session-mismatch",
|
|
201
|
+
});
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
delivery = {
|
|
205
|
+
cwd: args.cwd,
|
|
206
|
+
sessionId: args.sessionId,
|
|
207
|
+
ownerId: args.ownerId,
|
|
208
|
+
generation: eligible.generation,
|
|
209
|
+
targetCount: 0,
|
|
210
|
+
createdAt: eligible.eligibleAt,
|
|
211
|
+
eligible: true,
|
|
212
|
+
rehydrated: true,
|
|
213
|
+
};
|
|
214
|
+
pending.set(deliveryKey, delivery);
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
-
return
|
|
216
|
+
if (!delivery?.eligible)
|
|
217
|
+
return undefined;
|
|
218
|
+
const currentGeneration = persisted?.testRunGeneration;
|
|
219
|
+
if (currentGeneration !== delivery.generation) {
|
|
220
|
+
pending.delete(deliveryKey);
|
|
221
|
+
record(deliveryKey, "superseded", delivery, { currentGeneration });
|
|
222
|
+
return undefined;
|
|
217
223
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
224
|
+
const findings = consumeTestFindings(args.cacheManager, args.cwd, args.runtime);
|
|
225
|
+
if (!findings) {
|
|
226
|
+
pending.delete(deliveryKey);
|
|
227
|
+
record(deliveryKey, "superseded", delivery);
|
|
222
228
|
return undefined;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
};
|
|
229
|
+
}
|
|
230
|
+
pending.delete(deliveryKey);
|
|
231
|
+
record(deliveryKey, "delivered", delivery, {
|
|
232
|
+
ageMs: Math.max(0, Date.now() - delivery.createdAt),
|
|
233
|
+
rehydrated: delivery.rehydrated === true,
|
|
234
|
+
});
|
|
235
|
+
return findings;
|
|
231
236
|
}
|
|
232
237
|
/** Test-only reset; session ownership prevents cross-session consumption. */
|
|
233
238
|
export function _resetTestRunnerDeliveryForTests() {
|
|
@@ -756,7 +756,7 @@ const FORMATTER_POLICY_BY_FILENAME = new Map(TERRAGRUNT_FILENAMES.map((name) =>
|
|
|
756
756
|
// lines don't fall at the head of the pre-existing lookup-table duplication and
|
|
757
757
|
// get counted as new duplicated code. Bindings are live, so position is safe.
|
|
758
758
|
export { AUTO_INSTALLABLE_DEFAULT_FORMATTERS, FORMATTER_POLICY_BY_EXTENSION, FORMATTER_POLICY_BY_FILENAME, };
|
|
759
|
-
|
|
759
|
+
function getFormatterPolicyForExtension(ext) {
|
|
760
760
|
return FORMATTER_POLICY_BY_EXTENSION.get(ext.toLowerCase());
|
|
761
761
|
}
|
|
762
762
|
export function getFormatterPolicyForFile(filePath) {
|
|
@@ -80,7 +80,7 @@ function grammarFileStamp(filePath) {
|
|
|
80
80
|
return undefined;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
function isTreeSitterWasmAbortError(error) {
|
|
84
84
|
const message = error instanceof Error ? error.message : String(error);
|
|
85
85
|
return message.includes("Aborted") || message.includes("abort()");
|
|
86
86
|
}
|
|
@@ -4012,54 +4012,3 @@ export class TreeSitterClient {
|
|
|
4012
4012
|
}
|
|
4013
4013
|
}
|
|
4014
4014
|
// --- Simplified Pattern Search (regex fallback) ---
|
|
4015
|
-
/**
|
|
4016
|
-
* Fallback structural search using regex when tree-sitter unavailable
|
|
4017
|
-
* Less accurate but works without WASM dependencies
|
|
4018
|
-
*/
|
|
4019
|
-
export function regexStructuralSearch(pattern, files, options = {}) {
|
|
4020
|
-
const matches = [];
|
|
4021
|
-
const maxResults = options.maxResults ?? 50;
|
|
4022
|
-
// Extract pattern structure for regex
|
|
4023
|
-
// "console.log($MSG)" -> /console\.log\(([^)]+)\)/
|
|
4024
|
-
const regexPattern = pattern
|
|
4025
|
-
.replace(/\\/g, "\\\\")
|
|
4026
|
-
.replace(/\./g, "\\.")
|
|
4027
|
-
.replace(/\$\$\$[A-Z_][A-Z0-9_]*/g, "(.*?)") // variadic - non-greedy
|
|
4028
|
-
.replace(/\$[A-Z_][A-Z0-9_]*/g, "([^,)]+)"); // single - capture group
|
|
4029
|
-
try {
|
|
4030
|
-
const regex = new RegExp(regexPattern, "g");
|
|
4031
|
-
for (const file of files) {
|
|
4032
|
-
if (matches.length >= maxResults)
|
|
4033
|
-
break;
|
|
4034
|
-
try {
|
|
4035
|
-
const content = fs.readFileSync(file, "utf-8");
|
|
4036
|
-
const lines = content.split("\n");
|
|
4037
|
-
for (let i = 0; i < lines.length; i++) {
|
|
4038
|
-
regex.lastIndex = 0;
|
|
4039
|
-
const match = regex.exec(lines[i]);
|
|
4040
|
-
if (match) {
|
|
4041
|
-
const captures = {};
|
|
4042
|
-
// Extract captures
|
|
4043
|
-
for (let j = 1; j < match.length; j++) {
|
|
4044
|
-
captures[`$${j}`] = match[j];
|
|
4045
|
-
}
|
|
4046
|
-
matches.push({
|
|
4047
|
-
file,
|
|
4048
|
-
line: i + 1,
|
|
4049
|
-
column: match.index + 1,
|
|
4050
|
-
matchedText: match[0],
|
|
4051
|
-
captures,
|
|
4052
|
-
});
|
|
4053
|
-
if (matches.length >= maxResults)
|
|
4054
|
-
break;
|
|
4055
|
-
}
|
|
4056
|
-
}
|
|
4057
|
-
}
|
|
4058
|
-
catch { }
|
|
4059
|
-
}
|
|
4060
|
-
}
|
|
4061
|
-
catch {
|
|
4062
|
-
// Invalid regex
|
|
4063
|
-
}
|
|
4064
|
-
return matches;
|
|
4065
|
-
}
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
import { truncateToWidth } from "./deps/pi-tui.js";
|
|
19
19
|
const ELLIPSIS_KIND = { "…": 0, "...": 1, "": 2 };
|
|
20
20
|
let truncateIsNative = null;
|
|
21
|
-
/** Test-only: reset the signature probe between test cases. */
|
|
22
|
-
export function _resetTruncateProbeForTests() {
|
|
23
|
-
truncateIsNative = null;
|
|
24
|
-
}
|
|
25
21
|
export function fitLine(s, maxWidth, ellipsis = "...") {
|
|
26
22
|
const w = Math.max(0, maxWidth);
|
|
27
23
|
const fn = truncateToWidth;
|
|
@@ -32,10 +32,6 @@ export function wireUserNotifier(portsOrGetter) {
|
|
|
32
32
|
export function resetUserNotifier() {
|
|
33
33
|
notifierGetter = undefined;
|
|
34
34
|
}
|
|
35
|
-
/** True when a host render path is available (for callers that want to branch). */
|
|
36
|
-
export function hasUserNotifier() {
|
|
37
|
-
return notifierGetter !== undefined;
|
|
38
|
-
}
|
|
39
35
|
/**
|
|
40
36
|
* Best-effort delivery of a user-facing degradation. Never throws — a stale
|
|
41
37
|
* `ctx` after a session replacement must degrade to a no-op, not break the
|
|
@@ -47,10 +47,3 @@ export function logWordIndex(entry) {
|
|
|
47
47
|
cwd: normalizeFilePath(entry.cwd),
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
export function getWordIndexLogPath() {
|
|
51
|
-
return WORD_INDEX_LOG_FILE;
|
|
52
|
-
}
|
|
53
|
-
/** Resolve once all enqueued word-index writes are on disk (tests/shutdown). */
|
|
54
|
-
export function flushWordIndexLog() {
|
|
55
|
-
return writer.flush();
|
|
56
|
-
}
|
|
@@ -30,8 +30,8 @@ import { createDeadline, yieldIfOverBudget, } from "./cooperative-budget.js";
|
|
|
30
30
|
/**
|
|
31
31
|
* Bytes of backing store per posting entry: one `fileId` lane and one `line`
|
|
32
32
|
* lane, both `Int32`. This is the constant #2069's acceptance criterion is
|
|
33
|
-
* written against, and
|
|
34
|
-
*
|
|
33
|
+
* written against, and the arithmetic the memory-sample record and the
|
|
34
|
+
* regression test both read.
|
|
35
35
|
*/
|
|
36
36
|
export const WORD_POSTING_ENTRY_BYTES = 8;
|
|
37
37
|
/**
|
|
@@ -189,10 +189,6 @@ export class WordPostingList {
|
|
|
189
189
|
return list;
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
-
/** Estimated bytes one posting list holds, backing store plus fixed headers. */
|
|
193
|
-
export function estimatePostingListBytes(list) {
|
|
194
|
-
return list.byteLength + WORD_POSTING_LIST_OVERHEAD_BYTES;
|
|
195
|
-
}
|
|
196
192
|
/**
|
|
197
193
|
* Re-home every posting list into ONE shared `ArrayBuffer`, exactly sized.
|
|
198
194
|
*
|
|
@@ -405,7 +401,7 @@ export class WordForwardEntry {
|
|
|
405
401
|
* Bytes per forward entry: one pointer-compressed slot for the shared token
|
|
406
402
|
* string and one `Int32` count lane.
|
|
407
403
|
*/
|
|
408
|
-
|
|
404
|
+
const WORD_FORWARD_ENTRY_BYTES = 8;
|
|
409
405
|
/**
|
|
410
406
|
* The word index's dense file-id space: canonical path key → integer id →
|
|
411
407
|
* display path.
|
|
@@ -725,17 +725,6 @@ async function updateWordIndexDocumentAsyncUnsafe(index, doc, shouldContinue) {
|
|
|
725
725
|
commitWordIndexDocumentReplacement(index, doc, perTokenHits, docLength, startedAt);
|
|
726
726
|
return true;
|
|
727
727
|
}
|
|
728
|
-
/** Bounds shared by every word-index build path — keep the walk off the
|
|
729
|
-
* critical path on large repos: cap the file count, and skip files too large
|
|
730
|
-
* to be hand-written source (generated/bundled output the source filter
|
|
731
|
-
* didn't already exclude).
|
|
732
|
-
*
|
|
733
|
-
* Deprecated (#776): `collectWordIndexDocs` below no longer reads this
|
|
734
|
-
* constant directly — it derives its cap from `getWordIndexMaxFilesDerived`
|
|
735
|
-
* (project-scale.ts's `maxProjectFiles` knob), which reproduces this same
|
|
736
|
-
* 6,000 default at the default base. Kept exported for tests/callers that
|
|
737
|
-
* still reference the literal. */
|
|
738
|
-
export const WORD_INDEX_MAX_FILES = 6000;
|
|
739
728
|
export const WORD_INDEX_MAX_BYTES = 512 * 1024;
|
|
740
729
|
/**
|
|
741
730
|
* Collect the bounded `{path, content}` doc set `buildWordIndex` consumes —
|
|
@@ -748,9 +737,9 @@ export const WORD_INDEX_MAX_BYTES = 512 * 1024;
|
|
|
748
737
|
export async function collectWordIndexDocs(root, shouldContinue = () => true, preflightFiles) {
|
|
749
738
|
const { collectSourceFilesAsync } = await import("./source-filter.js");
|
|
750
739
|
// #747 hardening: pass the cap INTO the walk — without it,
|
|
751
|
-
// `collectSourceFilesAsync` defaults to an unbounded traversal and
|
|
752
|
-
//
|
|
753
|
-
//
|
|
740
|
+
// `collectSourceFilesAsync` defaults to an unbounded traversal and any
|
|
741
|
+
// slice below would only trim the result AFTER the whole tree (all of
|
|
742
|
+
// $HOME, on a misrooted cwd) has already been enumerated.
|
|
754
743
|
// #760: the walk is additionally bounded by source-filter's default
|
|
755
744
|
// visited-entry budget (DEFAULT_MAX_SCAN_ENTRIES), so a mixed tree with few
|
|
756
745
|
// source files among a huge pile of non-source files can't force a
|
|
@@ -811,7 +800,7 @@ export async function collectWordIndexDocs(root, shouldContinue = () => true, pr
|
|
|
811
800
|
// Node's fs.promises.stat runs on libuv's threadpool (default 4 slots), so
|
|
812
801
|
// real parallelism tops out there; the surplus workers are queue depth that
|
|
813
802
|
// keeps the pool saturated without starving other threadpool consumers.
|
|
814
|
-
|
|
803
|
+
const WORD_INDEX_STAT_CONCURRENCY = 8;
|
|
815
804
|
const WORD_INDEX_INCREMENTAL_CHURN_THRESHOLD = 0.3;
|
|
816
805
|
// A ratio alone misclassifies one stale file in a three-file project as dense.
|
|
817
806
|
// Below this absolute floor, per-document replacement is bounded and cheaper
|
|
@@ -1092,7 +1081,11 @@ export async function refreshWordIndexIncrementally(index, root, shouldContinue
|
|
|
1092
1081
|
timings,
|
|
1093
1082
|
};
|
|
1094
1083
|
}
|
|
1095
|
-
|
|
1084
|
+
const WORD_INDEX_QUERY_FILTER_KEYS = [
|
|
1085
|
+
"lang",
|
|
1086
|
+
"file",
|
|
1087
|
+
"ext",
|
|
1088
|
+
];
|
|
1096
1089
|
/** Thrown by {@link parseWordIndexQuery}/{@link buildWordIndexQueryFilter} for
|
|
1097
1090
|
* an unrecognized `key:` prefix or an unrecognized `lang:` value — a query
|
|
1098
1091
|
* typo fails loudly with the supported list instead of silently degrading
|
|
@@ -15,7 +15,7 @@ import { classifyProbeFailure, createAvailabilityLatch, logAvailabilityDecision,
|
|
|
15
15
|
// presence of one is the repo's deliberate opt-in: it carries the author's
|
|
16
16
|
// chosen severities/ignores, so we let zizmor findings BLOCK in that workspace
|
|
17
17
|
// (advisory-only otherwise, like Opengrep's local-rules gate).
|
|
18
|
-
|
|
18
|
+
const LOCAL_ZIZMOR_CONFIG_NAMES = [
|
|
19
19
|
path.join(".github", "zizmor.yml"),
|
|
20
20
|
path.join(".github", "zizmor.yaml"),
|
|
21
21
|
"zizmor.yml",
|