@herbertgao/pi-extensions 2026.9.7 → 2026.9.9
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 +8 -4
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/node_modules/@herbertgao/pi-bark/package.json +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +4 -4
- package/node_modules/@herbertgao/resume-from/package.json +2 -2
- package/node_modules/@narumitw/pi-btw/README.md +6 -1
- package/node_modules/@narumitw/pi-btw/dist/index.ts +209 -23
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +4 -4
- package/node_modules/@narumitw/pi-btw/package.json +1 -1
- package/node_modules/@narumitw/pi-btw/src/btw.ts +1 -12
- package/node_modules/@narumitw/pi-btw/src/menu.ts +244 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +5 -0
- package/node_modules/grok-mermaid/CHANGELOG.md +46 -0
- package/node_modules/grok-mermaid/LICENSE +205 -0
- package/node_modules/grok-mermaid/README.md +191 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts +16 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/ansi.js +23 -0
- package/node_modules/grok-mermaid/dist/ansi.js.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.js +366 -0
- package/node_modules/grok-mermaid/dist/canvas.js.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts +74 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.js +91 -0
- package/node_modules/grok-mermaid/dist/graph.js.map +1 -0
- package/node_modules/grok-mermaid/dist/index.d.ts +32 -0
- package/node_modules/grok-mermaid/dist/index.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/index.js +100 -0
- package/node_modules/grok-mermaid/dist/index.js.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts +62 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.js +324 -0
- package/node_modules/grok-mermaid/dist/labels.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts +12 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js +194 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.js +881 -0
- package/node_modules/grok-mermaid/dist/layout.js.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts +83 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.js +1151 -0
- package/node_modules/grok-mermaid/dist/parse.js.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.js +78 -0
- package/node_modules/grok-mermaid/dist/source-box.js.map +1 -0
- package/node_modules/grok-mermaid/dist/types.d.ts +42 -0
- package/node_modules/grok-mermaid/dist/types.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/types.js +1 -0
- package/node_modules/grok-mermaid/dist/types.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts +2 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.js +994 -0
- package/node_modules/grok-mermaid/dist/width-data.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/width.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width.js +76 -0
- package/node_modules/grok-mermaid/dist/width.js.map +1 -0
- package/node_modules/grok-mermaid/package.json +49 -0
- package/node_modules/grok-mermaid/src/ansi.ts +34 -0
- package/node_modules/grok-mermaid/src/canvas.ts +373 -0
- package/node_modules/grok-mermaid/src/graph.ts +142 -0
- package/node_modules/grok-mermaid/src/index.ts +104 -0
- package/node_modules/grok-mermaid/src/labels.ts +326 -0
- package/node_modules/grok-mermaid/src/layout-seq.ts +203 -0
- package/node_modules/grok-mermaid/src/layout.ts +1015 -0
- package/node_modules/grok-mermaid/src/parse.ts +1189 -0
- package/node_modules/grok-mermaid/src/source-box.ts +89 -0
- package/node_modules/grok-mermaid/src/types.ts +43 -0
- package/node_modules/grok-mermaid/src/width-data.ts +993 -0
- package/node_modules/grok-mermaid/src/width.ts +74 -0
- package/node_modules/pi-jev-auto-mode/CHANGELOG.md +110 -0
- package/node_modules/pi-jev-auto-mode/LICENSE +21 -0
- package/node_modules/pi-jev-auto-mode/README.md +285 -0
- package/node_modules/pi-jev-auto-mode/SECURITY.md +32 -0
- package/node_modules/pi-jev-auto-mode/docs/calibration.md +154 -0
- package/node_modules/pi-jev-auto-mode/docs/design.md +164 -0
- package/node_modules/pi-jev-auto-mode/docs/security.md +124 -0
- package/node_modules/pi-jev-auto-mode/index.ts +1 -0
- package/node_modules/pi-jev-auto-mode/package.json +72 -0
- package/node_modules/pi-jev-auto-mode/src/call.ts +180 -0
- package/node_modules/pi-jev-auto-mode/src/decide.ts +86 -0
- package/node_modules/pi-jev-auto-mode/src/extension.ts +862 -0
- package/node_modules/pi-jev-auto-mode/src/intent.ts +71 -0
- package/node_modules/pi-jev-auto-mode/src/jev/availability.ts +53 -0
- package/node_modules/pi-jev-auto-mode/src/jev/criteria.ts +19 -0
- package/node_modules/pi-jev-auto-mode/src/jev/decide.ts +187 -0
- package/node_modules/pi-jev-auto-mode/src/jev/engine.ts +165 -0
- package/node_modules/pi-jev-auto-mode/src/jev/index.ts +20 -0
- package/node_modules/pi-jev-auto-mode/src/jev/questions.ts +273 -0
- package/node_modules/pi-jev-auto-mode/src/jev/response.ts +64 -0
- package/node_modules/pi-jev-auto-mode/src/jev/state.ts +20 -0
- package/node_modules/pi-jev-auto-mode/src/jev/transport.ts +117 -0
- package/node_modules/pi-jev-auto-mode/src/jev/types.ts +46 -0
- package/node_modules/pi-jev-auto-mode/src/policy.ts +558 -0
- package/node_modules/pi-jev-auto-mode/src/records.ts +118 -0
- package/node_modules/pi-jev-auto-mode/src/settings.ts +327 -0
- package/node_modules/pi-jev-auto-mode/src/ui.ts +233 -0
- package/node_modules/pi-lens/CHANGELOG.md +45 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +21 -9
- package/node_modules/pi-lens/dist/clients/cascade-format.js +24 -0
- package/node_modules/pi-lens/dist/clients/extension-log.js +48 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +11 -12
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +3 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +41 -7
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +9 -2
- package/node_modules/pi-lens/dist/clients/path-utils.js +51 -9
- package/node_modules/pi-lens/dist/clients/persistent-reverify.js +271 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +15 -1
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +124 -7
- package/node_modules/pi-lens/dist/clients/skills-resolver.js +38 -2
- package/node_modules/pi-lens/dist/clients/widget-state.js +152 -6
- package/node_modules/pi-lens/dist/index.js +729 -344
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +14 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +84 -17
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +32 -5
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-typesafe/LICENSE +21 -0
- package/node_modules/pi-typesafe/README.md +153 -0
- package/node_modules/pi-typesafe/dist/ask.d.ts +32 -0
- package/node_modules/pi-typesafe/dist/ask.js +25 -0
- package/node_modules/pi-typesafe/dist/auth.d.ts +56 -0
- package/node_modules/pi-typesafe/dist/auth.js +114 -0
- package/node_modules/pi-typesafe/dist/batch.d.ts +74 -0
- package/node_modules/pi-typesafe/dist/batch.js +116 -0
- package/node_modules/pi-typesafe/dist/calibrate.d.ts +106 -0
- package/node_modules/pi-typesafe/dist/calibrate.js +157 -0
- package/node_modules/pi-typesafe/dist/client.d.ts +69 -0
- package/node_modules/pi-typesafe/dist/client.js +188 -0
- package/node_modules/pi-typesafe/dist/credentials.d.ts +46 -0
- package/node_modules/pi-typesafe/dist/credentials.js +112 -0
- package/node_modules/pi-typesafe/dist/errors.d.ts +9 -0
- package/node_modules/pi-typesafe/dist/errors.js +31 -0
- package/node_modules/pi-typesafe/dist/extension.d.ts +3 -0
- package/node_modules/pi-typesafe/dist/extension.js +222 -0
- package/node_modules/pi-typesafe/dist/index.d.ts +18 -0
- package/node_modules/pi-typesafe/dist/index.js +9 -0
- package/node_modules/pi-typesafe/dist/key-prompt.d.ts +3 -0
- package/node_modules/pi-typesafe/dist/key-prompt.js +43 -0
- package/node_modules/pi-typesafe/dist/login.d.ts +27 -0
- package/node_modules/pi-typesafe/dist/login.js +38 -0
- package/node_modules/pi-typesafe/dist/schema.d.ts +43 -0
- package/node_modules/pi-typesafe/dist/schema.js +152 -0
- package/node_modules/pi-typesafe/dist/ui.d.ts +3 -0
- package/node_modules/pi-typesafe/dist/ui.js +3 -0
- package/node_modules/pi-typesafe/dist/usage.d.ts +73 -0
- package/node_modules/pi-typesafe/dist/usage.js +182 -0
- package/node_modules/pi-typesafe/examples/decision-extension.ts +41 -0
- package/node_modules/pi-typesafe/extensions/index.js +2 -0
- package/node_modules/pi-typesafe/package.json +89 -0
- package/package.json +16 -8
|
@@ -2041,16 +2041,17 @@ function adoptCanonicalCasing(held, canonical) {
|
|
|
2041
2041
|
function normalizeFilePath(filePath) {
|
|
2042
2042
|
const normalized = filePath.replace(/\\/g, "/");
|
|
2043
2043
|
if (process.platform !== "win32" && !isWindowsPath(normalized)) {
|
|
2044
|
+
const folded = normalized === "" || normalized.startsWith("//") ? normalized : path2.posix.normalize(normalized);
|
|
2044
2045
|
try {
|
|
2045
|
-
const canonical = realpathSync.native(
|
|
2046
|
-
if (canonical ===
|
|
2047
|
-
return
|
|
2048
|
-
const adopted = adoptCanonicalCasing(
|
|
2049
|
-
if (adopted ===
|
|
2050
|
-
return
|
|
2051
|
-
return realpathSync.native(adopted) === canonical ? adopted :
|
|
2046
|
+
const canonical = realpathSync.native(folded);
|
|
2047
|
+
if (canonical === folded)
|
|
2048
|
+
return folded;
|
|
2049
|
+
const adopted = adoptCanonicalCasing(folded, canonical);
|
|
2050
|
+
if (adopted === folded)
|
|
2051
|
+
return folded;
|
|
2052
|
+
return realpathSync.native(adopted) === canonical ? adopted : folded;
|
|
2052
2053
|
} catch {
|
|
2053
|
-
return
|
|
2054
|
+
return folded;
|
|
2054
2055
|
}
|
|
2055
2056
|
}
|
|
2056
2057
|
try {
|
|
@@ -3744,6 +3745,9 @@ function inCaptureWindow(fn) {
|
|
|
3744
3745
|
function isCaptureSeam(prop) {
|
|
3745
3746
|
return prop === "on" || typeof prop === "string" && prop.startsWith("register");
|
|
3746
3747
|
}
|
|
3748
|
+
function isCallableSchema(value) {
|
|
3749
|
+
return typeof value === "function" && typeof value.toJsonSchema === "function" && typeof value.assert === "function";
|
|
3750
|
+
}
|
|
3747
3751
|
function wrapFunctionsInPlace(value) {
|
|
3748
3752
|
if (typeof value === "function") {
|
|
3749
3753
|
return inCaptureWindow(value);
|
|
@@ -3754,7 +3758,7 @@ function wrapFunctionsInPlace(value) {
|
|
|
3754
3758
|
const obj = value;
|
|
3755
3759
|
for (const key4 of Object.keys(obj)) {
|
|
3756
3760
|
const propValue = obj[key4];
|
|
3757
|
-
if (typeof propValue === "function") {
|
|
3761
|
+
if (typeof propValue === "function" && !isCallableSchema(propValue)) {
|
|
3758
3762
|
assignWrapped(obj, key4, propValue);
|
|
3759
3763
|
}
|
|
3760
3764
|
}
|
|
@@ -6413,7 +6417,7 @@ var require_parallel = __commonJS({
|
|
|
6413
6417
|
var require_cpu = __commonJS({
|
|
6414
6418
|
"node_modules/pidusage/lib/helpers/cpu.js"(exports, module) {
|
|
6415
6419
|
var os37 = __require("os");
|
|
6416
|
-
var
|
|
6420
|
+
var fs135 = __require("fs");
|
|
6417
6421
|
var exec = __require("child_process").exec;
|
|
6418
6422
|
var parallel = require_parallel();
|
|
6419
6423
|
function updateCpu(cpu, next) {
|
|
@@ -6440,7 +6444,7 @@ var require_cpu = __commonJS({
|
|
|
6440
6444
|
}
|
|
6441
6445
|
module.exports = updateCpu;
|
|
6442
6446
|
function getRealUptime(next) {
|
|
6443
|
-
|
|
6447
|
+
fs135.readFile("/proc/uptime", "utf8", function(err, uptime) {
|
|
6444
6448
|
if (err || uptime === void 0) {
|
|
6445
6449
|
if (!process.env.PIDUSAGE_SILENT) {
|
|
6446
6450
|
console.warn("[pidusage] We couldn't find uptime from /proc/uptime, using os.uptime() value");
|
|
@@ -6546,7 +6550,7 @@ var require_safe_buffer = __commonJS({
|
|
|
6546
6550
|
// node_modules/pidusage/lib/procfile.js
|
|
6547
6551
|
var require_procfile = __commonJS({
|
|
6548
6552
|
"node_modules/pidusage/lib/procfile.js"(exports, module) {
|
|
6549
|
-
var
|
|
6553
|
+
var fs135 = __require("fs");
|
|
6550
6554
|
var path211 = __require("path");
|
|
6551
6555
|
var updateCpu = require_cpu();
|
|
6552
6556
|
var parallel = require_parallel();
|
|
@@ -6560,11 +6564,11 @@ var require_procfile = __commonJS({
|
|
|
6560
6564
|
if (history2.fd) {
|
|
6561
6565
|
return cb(null, history2.fd);
|
|
6562
6566
|
}
|
|
6563
|
-
|
|
6567
|
+
fs135.open(path212, "r", cb);
|
|
6564
6568
|
}
|
|
6565
6569
|
function close(history2) {
|
|
6566
6570
|
if (history2.fd) {
|
|
6567
|
-
|
|
6571
|
+
fs135.close(history2.fd, noop);
|
|
6568
6572
|
}
|
|
6569
6573
|
}
|
|
6570
6574
|
function readUntilEnd(fd, buf, cb) {
|
|
@@ -6574,7 +6578,7 @@ var require_procfile = __commonJS({
|
|
|
6574
6578
|
buf = Buffer2.alloc(SIZE);
|
|
6575
6579
|
firstRead = true;
|
|
6576
6580
|
}
|
|
6577
|
-
|
|
6581
|
+
fs135.read(fd, buf, 0, SIZE, 0, function(err, bytesRead, buffer) {
|
|
6578
6582
|
if (err) {
|
|
6579
6583
|
cb(err);
|
|
6580
6584
|
return;
|
|
@@ -6857,7 +6861,7 @@ var require_gwmi = __commonJS({
|
|
|
6857
6861
|
var require_stats = __commonJS({
|
|
6858
6862
|
"node_modules/pidusage/lib/stats.js"(exports, module) {
|
|
6859
6863
|
"use strict";
|
|
6860
|
-
var
|
|
6864
|
+
var fs135 = __require("fs");
|
|
6861
6865
|
var os37 = __require("os");
|
|
6862
6866
|
var spawn3 = __require("child_process").spawn;
|
|
6863
6867
|
var requireMap = {
|
|
@@ -6881,7 +6885,7 @@ var require_stats = __commonJS({
|
|
|
6881
6885
|
win: "wmic"
|
|
6882
6886
|
};
|
|
6883
6887
|
var platform = os37.platform();
|
|
6884
|
-
if (
|
|
6888
|
+
if (fs135.existsSync("/etc/alpine-release")) {
|
|
6885
6889
|
platform = "alpine";
|
|
6886
6890
|
}
|
|
6887
6891
|
if (platform.match(/^win/)) {
|
|
@@ -15822,8 +15826,8 @@ var init_path_keyed_map = __esm({
|
|
|
15822
15826
|
* already-resident path is an update, and must not drop an unrelated file
|
|
15823
15827
|
* to make room for a key that needs none.
|
|
15824
15828
|
*/
|
|
15825
|
-
constructor(
|
|
15826
|
-
this.normalize =
|
|
15829
|
+
constructor(normalize2, maxEntries) {
|
|
15830
|
+
this.normalize = normalize2;
|
|
15827
15831
|
this.store = maxEntries === void 0 ? /* @__PURE__ */ new Map() : new BoundedFifoMap(maxEntries);
|
|
15828
15832
|
}
|
|
15829
15833
|
get size() {
|
|
@@ -18256,7 +18260,7 @@ function createGenerationSource(name) {
|
|
|
18256
18260
|
}
|
|
18257
18261
|
function createGenerationMap(name, options = {}) {
|
|
18258
18262
|
declare(name);
|
|
18259
|
-
const
|
|
18263
|
+
const normalize2 = options.normalizeKey ?? ((key4) => key4);
|
|
18260
18264
|
const maxKeys = Math.max(1, options.maxKeys ?? DEFAULT_MAX_KEYS);
|
|
18261
18265
|
const stamps = new BoundedFifoMap(maxKeys);
|
|
18262
18266
|
let nextTicket = 0;
|
|
@@ -18272,25 +18276,25 @@ function createGenerationMap(name, options = {}) {
|
|
|
18272
18276
|
return {
|
|
18273
18277
|
name,
|
|
18274
18278
|
current(key4) {
|
|
18275
|
-
return read(
|
|
18279
|
+
return read(normalize2(key4));
|
|
18276
18280
|
},
|
|
18277
18281
|
bump(key4) {
|
|
18278
18282
|
invalidations += 1;
|
|
18279
|
-
return issue(
|
|
18283
|
+
return issue(normalize2(key4));
|
|
18280
18284
|
},
|
|
18281
18285
|
capture(key4) {
|
|
18282
|
-
const normalized =
|
|
18286
|
+
const normalized = normalize2(key4);
|
|
18283
18287
|
const stamp2 = read(normalized) || issue(normalized);
|
|
18284
18288
|
const capturedInvalidations = invalidations;
|
|
18285
18289
|
return makeHandle(`${name}[${normalized}]`, stamp2, () => {
|
|
18286
18290
|
if (invalidations === capturedInvalidations)
|
|
18287
18291
|
return stamp2;
|
|
18288
|
-
return read(
|
|
18292
|
+
return read(normalize2(key4));
|
|
18289
18293
|
});
|
|
18290
18294
|
},
|
|
18291
18295
|
forget(key4) {
|
|
18292
18296
|
invalidations += 1;
|
|
18293
|
-
stamps.delete(
|
|
18297
|
+
stamps.delete(normalize2(key4));
|
|
18294
18298
|
},
|
|
18295
18299
|
clear() {
|
|
18296
18300
|
invalidations += 1;
|
|
@@ -31632,13 +31636,13 @@ async function findAncestorFile(startDir, ...relativeSegments) {
|
|
|
31632
31636
|
return findAncestorFileAmong(startDir, [relativeSegments]);
|
|
31633
31637
|
}
|
|
31634
31638
|
async function findAncestorFileAmong(startDir, candidateSegmentLists) {
|
|
31635
|
-
const
|
|
31639
|
+
const fs135 = await import("node:fs/promises");
|
|
31636
31640
|
let currentDir = path50.resolve(startDir);
|
|
31637
31641
|
while (!isAtOrAboveHomeDir(currentDir)) {
|
|
31638
31642
|
for (const segments of candidateSegmentLists) {
|
|
31639
31643
|
const candidate = path50.join(currentDir, ...segments);
|
|
31640
31644
|
try {
|
|
31641
|
-
await
|
|
31645
|
+
await fs135.access(candidate);
|
|
31642
31646
|
return candidate;
|
|
31643
31647
|
} catch {
|
|
31644
31648
|
}
|
|
@@ -31692,13 +31696,13 @@ async function typescriptVersionForTsc(tscPath) {
|
|
|
31692
31696
|
return void 0;
|
|
31693
31697
|
}
|
|
31694
31698
|
async function findTsserverPath(root, allowInstall) {
|
|
31695
|
-
const
|
|
31699
|
+
const fs135 = await import("node:fs/promises");
|
|
31696
31700
|
const ancestorHit = await findAncestorFile(root, "node_modules", "typescript", "lib", "tsserver.js");
|
|
31697
31701
|
if (ancestorHit)
|
|
31698
31702
|
return ancestorHit;
|
|
31699
31703
|
const cwdCandidate = path50.join(process.cwd(), "node_modules", "typescript", "lib", "tsserver.js");
|
|
31700
31704
|
try {
|
|
31701
|
-
await
|
|
31705
|
+
await fs135.access(cwdCandidate);
|
|
31702
31706
|
return cwdCandidate;
|
|
31703
31707
|
} catch {
|
|
31704
31708
|
}
|
|
@@ -31708,7 +31712,7 @@ async function findTsserverPath(root, allowInstall) {
|
|
|
31708
31712
|
for (const dir of typescriptDirsForTsc(tscPath)) {
|
|
31709
31713
|
const candidate = path50.join(dir, "lib", "tsserver.js");
|
|
31710
31714
|
try {
|
|
31711
|
-
await
|
|
31715
|
+
await fs135.access(candidate);
|
|
31712
31716
|
return candidate;
|
|
31713
31717
|
} catch {
|
|
31714
31718
|
}
|
|
@@ -32203,7 +32207,7 @@ var init_server = __esm({
|
|
|
32203
32207
|
root: TypeScriptRoot,
|
|
32204
32208
|
rootMarkers: TypeScriptRoot.rootMarkers,
|
|
32205
32209
|
async spawn(root, options) {
|
|
32206
|
-
const
|
|
32210
|
+
const fs135 = await import("node:fs/promises");
|
|
32207
32211
|
const nativeLsp = await findNativeTypeScriptLsp(root);
|
|
32208
32212
|
if (nativeLsp) {
|
|
32209
32213
|
const env2 = await getToolEnvironment();
|
|
@@ -32233,7 +32237,7 @@ var init_server = __esm({
|
|
|
32233
32237
|
if (!tsserverPath) {
|
|
32234
32238
|
const localCandidate = path50.join(path50.dirname(lspPath), "..", "typescript", "lib", "tsserver.js");
|
|
32235
32239
|
try {
|
|
32236
|
-
await
|
|
32240
|
+
await fs135.access(localCandidate);
|
|
32237
32241
|
tsserverPath = localCandidate;
|
|
32238
32242
|
} catch {
|
|
32239
32243
|
}
|
|
@@ -57915,7 +57919,7 @@ var require_main = __commonJS({
|
|
|
57915
57919
|
ril_1.default.install();
|
|
57916
57920
|
var path211 = __importStar(__require("path"));
|
|
57917
57921
|
var os37 = __importStar(__require("os"));
|
|
57918
|
-
var
|
|
57922
|
+
var fs135 = __importStar(__require("fs"));
|
|
57919
57923
|
var crypto_1 = __require("crypto");
|
|
57920
57924
|
var net_1 = __require("net");
|
|
57921
57925
|
var api_1 = require_api();
|
|
@@ -58056,7 +58060,7 @@ var require_main = __commonJS({
|
|
|
58056
58060
|
}
|
|
58057
58061
|
let randomLength = 32;
|
|
58058
58062
|
const fixedLength = "/lsp-.sock".length;
|
|
58059
|
-
const tmpDir =
|
|
58063
|
+
const tmpDir = fs135.realpathSync(XDG_RUNTIME_DIR ?? os37.tmpdir());
|
|
58060
58064
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
58061
58065
|
if (limit !== void 0) {
|
|
58062
58066
|
randomLength = Math.min(limit - tmpDir.length - fixedLength, randomLength);
|
|
@@ -66137,6 +66141,7 @@ var init_lsp = __esm({
|
|
|
66137
66141
|
let auxUnconfirmedServerIds;
|
|
66138
66142
|
let lateDeliveryServerIds;
|
|
66139
66143
|
let tsserverSyncEligible = false;
|
|
66144
|
+
const isWarmupTouch = source === "lsp_sweep_warmup";
|
|
66140
66145
|
let tsserverSyncConfirmed;
|
|
66141
66146
|
let diagnosticsUnsupportedServerIds = [];
|
|
66142
66147
|
if (diagnosticsMode !== "none") {
|
|
@@ -66209,7 +66214,7 @@ var init_lsp = __esm({
|
|
|
66209
66214
|
timeoutFor = () => callerCap ?? modeFloor;
|
|
66210
66215
|
}
|
|
66211
66216
|
const timeoutMs = Math.max(0, ...spawned.filter((e) => !deferredResyncServerIds.has(e.info.id)).map((e) => timeoutFor(e.client.serverId)));
|
|
66212
|
-
if (!notifyWriteTimedOut && options.collectDiagnostics === true && clientScope === "primary" && spawned.length === 1 && spawned[0].client.serverId === "typescript" && getStrategy(spawned[0].client.serverId, spawned[0].client.getLaunchVariant?.()).silentOnClean === true) {
|
|
66217
|
+
if (!notifyWriteTimedOut && (options.collectDiagnostics === true || isWarmupTouch) && clientScope === "primary" && spawned.length === 1 && spawned[0].client.serverId === "typescript" && getStrategy(spawned[0].client.serverId, spawned[0].client.getLaunchVariant?.()).silentOnClean === true) {
|
|
66213
66218
|
try {
|
|
66214
66219
|
const snapshots = await this.getCapabilitySnapshots(filePath);
|
|
66215
66220
|
tsserverSyncEligible = classifyCascadeWaitTier(this, filePath, snapshots) === "tier3-silent";
|
|
@@ -66283,7 +66288,6 @@ var init_lsp = __esm({
|
|
|
66283
66288
|
const serverTimeout = perServerWaitTimeouts[entryIndex];
|
|
66284
66289
|
const baseline = diagnosticBaselines.get(entry.client);
|
|
66285
66290
|
const pullOnly = classifyServerWaitTier(entry.client.serverId, pressureSnapshots.find((snapshot) => snapshot.serverId === entry.client.serverId)) === "pull-capable";
|
|
66286
|
-
const isWarmupTouch = source === "lsp_sweep_warmup";
|
|
66287
66291
|
const waitForDiagnostics = () => !notifySkippedServerIds.has(entry.info.id) && Number.isFinite(baseline) ? entry.client.waitForDiagnostics(filePath, serverTimeout, {
|
|
66288
66292
|
minVersion: baseline,
|
|
66289
66293
|
...pullOnly && { pullOnly: true },
|
|
@@ -66712,7 +66716,17 @@ var init_lsp = __esm({
|
|
|
66712
66716
|
if (diagnosticsTimedOut && // #1549: primary-scoped, like the aggregate gate. `spawned.length === 1`
|
|
66713
66717
|
// below means the one server IS the primary, so this is the same condition
|
|
66714
66718
|
// written in the vocabulary the rest of the merge now uses.
|
|
66715
|
-
!primaryNotifyWriteTimedOut &&
|
|
66719
|
+
!primaryNotifyWriteTimedOut && // #3187: the warm-up is sync-ELIGIBLE now, and eligibility alone must
|
|
66720
|
+
// not cost it this fallback. For a collecting touch the exclusion is
|
|
66721
|
+
// #707's contract (the end-of-wait retry above is typescript's second
|
|
66722
|
+
// chance, and failing it stays inconclusive); the warm-up collects
|
|
66723
|
+
// nothing, so that retry's `collected !== undefined` precondition can
|
|
66724
|
+
// never hold for it and the exclusion would leave a server whose
|
|
66725
|
+
// `typescript.tsserverRequest` is unavailable stranded inconclusive —
|
|
66726
|
+
// a #744 warm-up failure, its retry, and a SKIPPED sweep group, where
|
|
66727
|
+
// today it is certified clean. Reaching here at all means the race
|
|
66728
|
+
// produced no answer, so this decides nothing the sync already decided.
|
|
66729
|
+
(!tsserverSyncEligible || isWarmupTouch) && clientScope === "primary" && spawned.length === 1 && getStrategy(spawned[0].client.serverId, spawned[0].client.getLaunchVariant?.()).silentOnClean === true) {
|
|
66716
66730
|
try {
|
|
66717
66731
|
const snapshots = await this.getCapabilitySnapshots(filePath);
|
|
66718
66732
|
if (classifyCascadeWaitTier(this, filePath, snapshots) === "tier3-silent") {
|
|
@@ -68057,6 +68071,13 @@ var init_lsp = __esm({
|
|
|
68057
68071
|
});
|
|
68058
68072
|
const warmupAttempt = this.touchFile(representativeFile, content, {
|
|
68059
68073
|
diagnostics: "document",
|
|
68074
|
+
// #3187: stays FALSE. This touch wants a verdict, not findings: its
|
|
68075
|
+
// `clientScope: "primary"` evidence does not speak for the auxiliaries
|
|
68076
|
+
// the sweep's own `clientScope: "all"` touch waits on, so collecting
|
|
68077
|
+
// here would prime this file's `lastKnownDiagnostics` from a narrower
|
|
68078
|
+
// scope than the result that follows (and an empty confirm would delete
|
|
68079
|
+
// a previously confirmed record). `touchFile`'s sync-confirm gates key
|
|
68080
|
+
// off `source` instead, so the verdict still arrives at ~grace+RTT.
|
|
68060
68081
|
collectDiagnostics: false,
|
|
68061
68082
|
clientScope: "primary",
|
|
68062
68083
|
source: "lsp_sweep_warmup",
|
|
@@ -71656,8 +71677,39 @@ var init_blocker_freshness = __esm({
|
|
|
71656
71677
|
}
|
|
71657
71678
|
});
|
|
71658
71679
|
|
|
71659
|
-
// dist/clients/
|
|
71680
|
+
// dist/clients/finding-identity.js
|
|
71681
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
71660
71682
|
import * as path101 from "node:path";
|
|
71683
|
+
function normalizeMessage(message) {
|
|
71684
|
+
return message.replace(/\s+/g, " ").trim().toLowerCase();
|
|
71685
|
+
}
|
|
71686
|
+
function hashText(value, length = FINDING_ID_HASH_LENGTH) {
|
|
71687
|
+
return createHash14("sha256").update(value).digest("hex").slice(0, length);
|
|
71688
|
+
}
|
|
71689
|
+
function relativeFile(filePath, cwd) {
|
|
71690
|
+
const canonicalCwd = normalizeMapKey(cwd);
|
|
71691
|
+
const canonicalFile = normalizeMapKey(filePath);
|
|
71692
|
+
const rel = path101.relative(canonicalCwd, canonicalFile).replace(/\\/g, "/");
|
|
71693
|
+
return rel && !rel.startsWith("..") ? rel : canonicalFile;
|
|
71694
|
+
}
|
|
71695
|
+
function stableFindingId(prefix, args) {
|
|
71696
|
+
const joined = [
|
|
71697
|
+
relativeFile(args.filePath, args.cwd),
|
|
71698
|
+
...args.parts.map((part) => part === void 0 || part === null ? "" : String(part))
|
|
71699
|
+
].join("|");
|
|
71700
|
+
return `${prefix}${hashText(joined)}`;
|
|
71701
|
+
}
|
|
71702
|
+
var FINDING_ID_HASH_LENGTH;
|
|
71703
|
+
var init_finding_identity = __esm({
|
|
71704
|
+
"dist/clients/finding-identity.js"() {
|
|
71705
|
+
"use strict";
|
|
71706
|
+
init_path_utils();
|
|
71707
|
+
FINDING_ID_HASH_LENGTH = 12;
|
|
71708
|
+
}
|
|
71709
|
+
});
|
|
71710
|
+
|
|
71711
|
+
// dist/clients/disposition-logger.js
|
|
71712
|
+
import * as path102 from "node:path";
|
|
71661
71713
|
function logDispositionEvent(entry) {
|
|
71662
71714
|
if (isTestMode()) {
|
|
71663
71715
|
return;
|
|
@@ -71672,8 +71724,8 @@ var init_disposition_logger = __esm({
|
|
|
71672
71724
|
init_probe_home_state();
|
|
71673
71725
|
init_ndjson_logger();
|
|
71674
71726
|
DISPOSITION_LOG_DIR = getGlobalPiLensLogDir();
|
|
71675
|
-
DISPOSITION_LOG_FILE =
|
|
71676
|
-
DISPOSITION_LOG_BACKUP_FILE =
|
|
71727
|
+
DISPOSITION_LOG_FILE = path102.join(DISPOSITION_LOG_DIR, "dispositions.log");
|
|
71728
|
+
DISPOSITION_LOG_BACKUP_FILE = path102.join(DISPOSITION_LOG_DIR, "dispositions.log.1");
|
|
71677
71729
|
MAX_LOG_BYTES2 = Math.max(128 * 1024, Number.parseInt(process.env.PI_LENS_DISPOSITION_LOG_MAX_BYTES ?? "1048576", 10) || 1048576);
|
|
71678
71730
|
writer7 = createNdjsonLogger({
|
|
71679
71731
|
filePath: DISPOSITION_LOG_FILE,
|
|
@@ -71684,7 +71736,7 @@ var init_disposition_logger = __esm({
|
|
|
71684
71736
|
});
|
|
71685
71737
|
|
|
71686
71738
|
// dist/clients/bus-events-logger.js
|
|
71687
|
-
import * as
|
|
71739
|
+
import * as path103 from "node:path";
|
|
71688
71740
|
function bumpRollupCount(event, outcome) {
|
|
71689
71741
|
const existing = eventRollupCounts.get(event) ?? {
|
|
71690
71742
|
emitted: 0,
|
|
@@ -71727,7 +71779,7 @@ var init_bus_events_logger = __esm({
|
|
|
71727
71779
|
init_ndjson_logger();
|
|
71728
71780
|
init_log_cleanup();
|
|
71729
71781
|
init_latency_logger();
|
|
71730
|
-
BUS_EVENTS_LOG_FILE =
|
|
71782
|
+
BUS_EVENTS_LOG_FILE = path103.join(getGlobalPiLensLogDir(), "bus-events.log");
|
|
71731
71783
|
writer8 = createNdjsonLogger({
|
|
71732
71784
|
filePath: BUS_EVENTS_LOG_FILE,
|
|
71733
71785
|
maxBytes: getMaxLogSizeMB() * 1024 * 1024
|
|
@@ -71738,9 +71790,9 @@ var init_bus_events_logger = __esm({
|
|
|
71738
71790
|
|
|
71739
71791
|
// dist/clients/recent-touches.js
|
|
71740
71792
|
import * as fs81 from "node:fs";
|
|
71741
|
-
import * as
|
|
71793
|
+
import * as path104 from "node:path";
|
|
71742
71794
|
function recentTouchesPath(cwd) {
|
|
71743
|
-
return
|
|
71795
|
+
return path104.join(getProjectDataDir(cwd), "recent-touches.json");
|
|
71744
71796
|
}
|
|
71745
71797
|
function isRecentTouchesEnabled() {
|
|
71746
71798
|
if (_enabledCache2 === void 0) {
|
|
@@ -72294,37 +72346,6 @@ var init_disposition_publish = __esm({
|
|
|
72294
72346
|
}
|
|
72295
72347
|
});
|
|
72296
72348
|
|
|
72297
|
-
// dist/clients/finding-identity.js
|
|
72298
|
-
import { createHash as createHash14 } from "node:crypto";
|
|
72299
|
-
import * as path104 from "node:path";
|
|
72300
|
-
function normalizeMessage(message) {
|
|
72301
|
-
return message.replace(/\s+/g, " ").trim().toLowerCase();
|
|
72302
|
-
}
|
|
72303
|
-
function hashText(value, length = FINDING_ID_HASH_LENGTH) {
|
|
72304
|
-
return createHash14("sha256").update(value).digest("hex").slice(0, length);
|
|
72305
|
-
}
|
|
72306
|
-
function relativeFile(filePath, cwd) {
|
|
72307
|
-
const canonicalCwd = normalizeMapKey(cwd);
|
|
72308
|
-
const canonicalFile = normalizeMapKey(filePath);
|
|
72309
|
-
const rel = path104.relative(canonicalCwd, canonicalFile).replace(/\\/g, "/");
|
|
72310
|
-
return rel && !rel.startsWith("..") ? rel : canonicalFile;
|
|
72311
|
-
}
|
|
72312
|
-
function stableFindingId(prefix, args) {
|
|
72313
|
-
const joined = [
|
|
72314
|
-
relativeFile(args.filePath, args.cwd),
|
|
72315
|
-
...args.parts.map((part) => part === void 0 || part === null ? "" : String(part))
|
|
72316
|
-
].join("|");
|
|
72317
|
-
return `${prefix}${hashText(joined)}`;
|
|
72318
|
-
}
|
|
72319
|
-
var FINDING_ID_HASH_LENGTH;
|
|
72320
|
-
var init_finding_identity = __esm({
|
|
72321
|
-
"dist/clients/finding-identity.js"() {
|
|
72322
|
-
"use strict";
|
|
72323
|
-
init_path_utils();
|
|
72324
|
-
FINDING_ID_HASH_LENGTH = 12;
|
|
72325
|
-
}
|
|
72326
|
-
});
|
|
72327
|
-
|
|
72328
72349
|
// dist/clients/diagnostic-dispositions.js
|
|
72329
72350
|
import * as fs82 from "node:fs";
|
|
72330
72351
|
import * as path105 from "node:path";
|
|
@@ -72629,6 +72650,8 @@ function fileMapKey(filePath) {
|
|
|
72629
72650
|
return normalizeEphemeralMapKey(filePath);
|
|
72630
72651
|
}
|
|
72631
72652
|
function isBlocking(d) {
|
|
72653
|
+
if (d.disposition)
|
|
72654
|
+
return false;
|
|
72632
72655
|
if (d.stale)
|
|
72633
72656
|
return false;
|
|
72634
72657
|
if (d.semantic === "blocking")
|
|
@@ -72680,20 +72703,24 @@ function reconcileWidgetDisposition(cwd, target, _disposition, content) {
|
|
|
72680
72703
|
}
|
|
72681
72704
|
}
|
|
72682
72705
|
const active = new Set(applyDispositions(current, cwd, target.filePath, source));
|
|
72683
|
-
const normalized = current.
|
|
72706
|
+
const normalized = current.flatMap((diagnostic) => {
|
|
72684
72707
|
const { strict, weak } = anchorsForDiagnostic(cwd, target.filePath, diagnostic, source);
|
|
72685
72708
|
const entry = getDisposition(cwd, strict) ?? getDisposition(cwd, weak);
|
|
72686
72709
|
if (!active.has(diagnostic) && (entry?.disposition === "false-positive" || entry?.disposition === "suppress")) {
|
|
72687
|
-
return
|
|
72710
|
+
return [
|
|
72711
|
+
{ ...diagnostic, disposition: entry.disposition, flagged: false }
|
|
72712
|
+
];
|
|
72688
72713
|
}
|
|
72714
|
+
if (diagnostic.suppressedRetained)
|
|
72715
|
+
return [];
|
|
72689
72716
|
const { disposition: _disposition2, flagged: _flagged, ...baseDiagnostic } = diagnostic;
|
|
72690
|
-
return entry?.disposition === "flagged" ? { ...baseDiagnostic, flagged: true } : baseDiagnostic;
|
|
72717
|
+
return entry?.disposition === "flagged" ? [{ ...baseDiagnostic, flagged: true }] : [baseDiagnostic];
|
|
72691
72718
|
});
|
|
72692
72719
|
const rec = getOrCreate(target.filePath);
|
|
72693
72720
|
const writeIndex = admitWidgetDiagnosticsWrite(target.filePath);
|
|
72694
72721
|
if (!diagnosticsWriteGuard.shouldWrite(fileMapKey(target.filePath), writeIndex))
|
|
72695
72722
|
return;
|
|
72696
|
-
commitDiagnostics(rec, target.filePath, normalized, Date.now());
|
|
72723
|
+
commitDiagnostics(rec, target.filePath, normalized, Date.now(), fileMapKey(target.filePath), false);
|
|
72697
72724
|
}
|
|
72698
72725
|
function admitWidgetDiagnosticsWrite(filePath, writeIndex) {
|
|
72699
72726
|
const key4 = fileMapKey(filePath);
|
|
@@ -72858,7 +72885,35 @@ function normalizeDiagnostics(filePath, diagnostics, observedTs) {
|
|
|
72858
72885
|
};
|
|
72859
72886
|
});
|
|
72860
72887
|
}
|
|
72861
|
-
function
|
|
72888
|
+
function retentionIdentity(d) {
|
|
72889
|
+
return JSON.stringify([
|
|
72890
|
+
d.tool ?? "",
|
|
72891
|
+
d.rule ?? "",
|
|
72892
|
+
normalizeMessage(d.message)
|
|
72893
|
+
]);
|
|
72894
|
+
}
|
|
72895
|
+
function retainSuppressedRows(previous, incoming, filePath) {
|
|
72896
|
+
const tagged = previous.filter((d) => d.disposition !== void 0);
|
|
72897
|
+
if (tagged.length === 0)
|
|
72898
|
+
return incoming;
|
|
72899
|
+
const reported = new Set(incoming.map(retentionIdentity));
|
|
72900
|
+
const retained = tagged.filter((d) => !reported.has(retentionIdentity(d)));
|
|
72901
|
+
if (retained.length > MAX_RETAINED_SUPPRESSED_PER_FILE) {
|
|
72902
|
+
retained.sort((a, b) => (b.observedAt ?? 0) - (a.observedAt ?? 0));
|
|
72903
|
+
recordDegradationOnce({
|
|
72904
|
+
kind: "widget-suppressed-retention-capped",
|
|
72905
|
+
subject: filePath,
|
|
72906
|
+
reason: `${retained.length - MAX_RETAINED_SUPPRESSED_PER_FILE} suppressed row(s) beyond the ${MAX_RETAINED_SUPPRESSED_PER_FILE}-row per-file retention cap are no longer counted by the footer chip`
|
|
72907
|
+
});
|
|
72908
|
+
retained.length = MAX_RETAINED_SUPPRESSED_PER_FILE;
|
|
72909
|
+
}
|
|
72910
|
+
return [
|
|
72911
|
+
...incoming,
|
|
72912
|
+
...retained.map((d) => d.suppressedRetained ? d : { ...d, suppressedRetained: true })
|
|
72913
|
+
];
|
|
72914
|
+
}
|
|
72915
|
+
function commitDiagnostics(rec, filePath, incoming, observedAt, key4 = fileMapKey(filePath), retainSuppressed = true) {
|
|
72916
|
+
const normalized = retainSuppressed ? retainSuppressedRows(rec.allDiagnostics, incoming, filePath) : incoming;
|
|
72862
72917
|
rec.diagnosticCounts = countDiagnostics(normalized);
|
|
72863
72918
|
rec.diagnostics = capStoredDiagnostics(normalized);
|
|
72864
72919
|
rec.allDiagnostics = normalized;
|
|
@@ -73149,6 +73204,16 @@ function getFileDiagnosticSummaries() {
|
|
|
73149
73204
|
};
|
|
73150
73205
|
});
|
|
73151
73206
|
}
|
|
73207
|
+
function countRetainedSuppressedRows(filePath) {
|
|
73208
|
+
const rec = files.get(fileMapKey(filePath));
|
|
73209
|
+
if (!rec)
|
|
73210
|
+
return 0;
|
|
73211
|
+
let n = 0;
|
|
73212
|
+
for (const d of rec.allDiagnostics)
|
|
73213
|
+
if (d.suppressedRetained)
|
|
73214
|
+
n += 1;
|
|
73215
|
+
return n;
|
|
73216
|
+
}
|
|
73152
73217
|
function getFileDiagnostics(filePath) {
|
|
73153
73218
|
const rec = files.get(fileMapKey(filePath));
|
|
73154
73219
|
if (!rec)
|
|
@@ -73459,7 +73524,7 @@ function dedupeByBasename(recs) {
|
|
|
73459
73524
|
}
|
|
73460
73525
|
return [...seen.values()].sort((a, b) => b.touchedAt - a.touchedAt);
|
|
73461
73526
|
}
|
|
73462
|
-
var files, sessionLanguages, requestRenderFn, diagnosticsWriteGuard, runnerWriteGuard, MAX_STORED_DIAGNOSTICS_PER_FILE, MAX_INACTIVE_FILE_RECORDS, ACTIVE_FILE_IDLE_MS, MAX_LSP_SERVER_RECORDS, lspServers, nextInactivePruneSize, renderedDependencyDriftFiles, WIDGET_STATE_VERSION, staleReconcileTimer, STALE_RECONCILE_DEBOUNCE_MS, HORIZONTAL_MIN_WIDTH;
|
|
73527
|
+
var files, sessionLanguages, requestRenderFn, diagnosticsWriteGuard, runnerWriteGuard, MAX_STORED_DIAGNOSTICS_PER_FILE, MAX_RETAINED_SUPPRESSED_PER_FILE, MAX_INACTIVE_FILE_RECORDS, ACTIVE_FILE_IDLE_MS, MAX_LSP_SERVER_RECORDS, lspServers, nextInactivePruneSize, renderedDependencyDriftFiles, WIDGET_STATE_VERSION, staleReconcileTimer, STALE_RECONCILE_DEBOUNCE_MS, HORIZONTAL_MIN_WIDTH;
|
|
73463
73528
|
var init_widget_state = __esm({
|
|
73464
73529
|
"dist/clients/widget-state.js"() {
|
|
73465
73530
|
"use strict";
|
|
@@ -73470,6 +73535,7 @@ var init_widget_state = __esm({
|
|
|
73470
73535
|
init_tui_fit();
|
|
73471
73536
|
init_write_ordering_guard();
|
|
73472
73537
|
init_blocker_freshness();
|
|
73538
|
+
init_finding_identity();
|
|
73473
73539
|
init_freshness();
|
|
73474
73540
|
init_diagnostic_line_freshness();
|
|
73475
73541
|
init_stale_marker();
|
|
@@ -73481,6 +73547,7 @@ var init_widget_state = __esm({
|
|
|
73481
73547
|
diagnosticsWriteGuard = new WriteOrderingGuard();
|
|
73482
73548
|
runnerWriteGuard = new WriteOrderingGuard();
|
|
73483
73549
|
MAX_STORED_DIAGNOSTICS_PER_FILE = 12;
|
|
73550
|
+
MAX_RETAINED_SUPPRESSED_PER_FILE = 12;
|
|
73484
73551
|
MAX_INACTIVE_FILE_RECORDS = 1024;
|
|
73485
73552
|
ACTIVE_FILE_IDLE_MS = 30 * 6e4;
|
|
73486
73553
|
MAX_LSP_SERVER_RECORDS = 128;
|
|
@@ -76024,6 +76091,194 @@ var init_finding_policy = __esm({
|
|
|
76024
76091
|
}
|
|
76025
76092
|
});
|
|
76026
76093
|
|
|
76094
|
+
// dist/clients/finding-delivery-gate.js
|
|
76095
|
+
function markUnreconciledFindings(findings) {
|
|
76096
|
+
return findings.map((finding) => ({ ...finding, stale: true }));
|
|
76097
|
+
}
|
|
76098
|
+
function formatCacheAgeLabel(scannedAt, nowMs = Date.now()) {
|
|
76099
|
+
if (scannedAt === void 0 || scannedAt === null || scannedAt === "") {
|
|
76100
|
+
return "scan age unknown";
|
|
76101
|
+
}
|
|
76102
|
+
const scannedAtMs = typeof scannedAt === "number" ? scannedAt : Date.parse(scannedAt);
|
|
76103
|
+
if (!Number.isFinite(scannedAtMs))
|
|
76104
|
+
return "scan age unknown";
|
|
76105
|
+
const ageMs = Math.max(0, nowMs - scannedAtMs);
|
|
76106
|
+
const ageMinutes = Math.round(ageMs / MS_PER_MINUTE);
|
|
76107
|
+
if (ageMinutes < 1)
|
|
76108
|
+
return "scanned <1m ago";
|
|
76109
|
+
if (ageMinutes < 60)
|
|
76110
|
+
return `scanned ${ageMinutes}m ago`;
|
|
76111
|
+
const ageHours = Math.floor(ageMinutes / 60);
|
|
76112
|
+
const remMinutes = ageMinutes % 60;
|
|
76113
|
+
return remMinutes === 0 ? `scanned ${ageHours}h ago` : `scanned ${ageHours}h ${remMinutes}m ago`;
|
|
76114
|
+
}
|
|
76115
|
+
function gated(file, description, gates, evidence, extra = {}) {
|
|
76116
|
+
return { mode: "gated", file, description, gates, evidence, ...extra };
|
|
76117
|
+
}
|
|
76118
|
+
function labeled(file, description, reason, ageSource, evidence = [], extra = {}) {
|
|
76119
|
+
return {
|
|
76120
|
+
mode: "labeled",
|
|
76121
|
+
file,
|
|
76122
|
+
description,
|
|
76123
|
+
reason,
|
|
76124
|
+
ageSource,
|
|
76125
|
+
evidence,
|
|
76126
|
+
...extra
|
|
76127
|
+
};
|
|
76128
|
+
}
|
|
76129
|
+
var MS_PER_MINUTE, RUNTIME_TURN_FILE, LENS_DIAGNOSTICS_FILE, DELIVERY_SURFACES;
|
|
76130
|
+
var init_finding_delivery_gate = __esm({
|
|
76131
|
+
"dist/clients/finding-delivery-gate.js"() {
|
|
76132
|
+
"use strict";
|
|
76133
|
+
MS_PER_MINUTE = 6e4;
|
|
76134
|
+
RUNTIME_TURN_FILE = "clients/runtime-turn.ts";
|
|
76135
|
+
LENS_DIAGNOSTICS_FILE = "tools/lens-diagnostics.ts";
|
|
76136
|
+
DELIVERY_SURFACES = {
|
|
76137
|
+
"runtime-turn:secrets-gitleaks": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F534} secrets blocker, gitleaks cache.", ["gateFindingsByPathFreshness"], ['store: "gitleaks"']),
|
|
76138
|
+
"runtime-turn:secrets-trivy": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F534} secrets blocker, trivy secrets cache.", ["gateFindingsByPathFreshness"], ['store: "trivy-secrets"']),
|
|
76139
|
+
"runtime-turn:govulncheck-advisory": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F6E1}\uFE0F Go CVE advisory (call-site line only).", ["gateFindingsByPathFreshness"], ['store: "govulncheck"']),
|
|
76140
|
+
// Two tagged seams (the stale and live render branches below the same
|
|
76141
|
+
// `sweepInlineBlockerFreshness` call) legitimately share one evidence
|
|
76142
|
+
// occurrence — evidenceMin: 2 tells the exclusive-assignment check both
|
|
76143
|
+
// are expected claimants, not a rogue seam contesting the real one.
|
|
76144
|
+
"runtime-turn:unresolved-inline-blocker": gated(
|
|
76145
|
+
RUNTIME_TURN_FILE,
|
|
76146
|
+
"Turn-end re-surfaced unresolved inline blockers.",
|
|
76147
|
+
["sweepInlineBlockerFreshness"],
|
|
76148
|
+
// #1790: the call now passes `additionalEntries` (widget-store rows) as a
|
|
76149
|
+
// third argument, so the literal is the call's opening rather than the
|
|
76150
|
+
// whole single-line invocation.
|
|
76151
|
+
["sweepInlineBlockerFreshness(runtime, cwd, {"],
|
|
76152
|
+
{ evidenceMin: 2 }
|
|
76153
|
+
),
|
|
76154
|
+
// Same two gate calls as the live secrets tier — this tier renders their
|
|
76155
|
+
// `.stale` arm, so it has no OWN gate call to point at.
|
|
76156
|
+
"runtime-turn:stale-secrets-tier": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F511} demoted-secrets tier (drifted since scan).", ["gateFindingsByPathFreshness"], ['store: "gitleaks"', 'store: "trivy-secrets"']),
|
|
76157
|
+
// The evidence below is the literal header FRAGMENT including the
|
|
76158
|
+
// interpolation — proves the label is actually rendered, not merely
|
|
76159
|
+
// computed and discarded (review round F1's "deleted the age
|
|
76160
|
+
// interpolations" attack).
|
|
76161
|
+
"runtime-turn:trivy-critical-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F534} CRITICAL dependency CVE blocker (trivy).", "Package-pinned finding with no cited file:line to stat \u2014 freshness has nothing to check drift against. The session_start cache can be arbitrarily old, so its age is stated instead. Also routes through `filterFindingsByDisposition` (#1625) first \u2014 a suppressed/false-positive finding never reaches this render, so the age label and the disposition filter compose rather than substitute for each other.", "TrivyResult.scannedAt", ["CRITICAL dependency CVEs (trivy, ${trivyAgeLabel}"]),
|
|
76162
|
+
"runtime-turn:trivy-cve-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F6E1}\uFE0F non-critical dependency CVE advisory (trivy).", "Same package-pinned shape and #1625 disposition composition as the CRITICAL blocker above.", "TrivyResult.scannedAt", ["Dependency CVEs (trivy, ${trivyAgeLabel}"]),
|
|
76163
|
+
"runtime-turn:trivy-license-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F4DC} dependency license-risk advisory (trivy).", "Same package-pinned shape as the CRITICAL blocker above.", "TrivyResult.scannedAt", ["Dependency license risk (trivy, ${trivyAgeLabel}"]),
|
|
76164
|
+
"runtime-turn:dead-code-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end dead-code delta advisory (knip/vulture/etc).", "The delta shown is computed from THIS turn's own analyze() call, diffed against the previous cache \u2014 never a replay of a stale cache.", "live"),
|
|
76165
|
+
"runtime-turn:knip-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F534} Knip unresolved-imports/deps blocker.", "Same shape as the dead-code advisory: `await knipClient.analyze(cwd, ...)` runs fresh THIS turn, diffed against the previous cache and filtered to files edited this turn \u2014 never a replay of a stale cache.", "live"),
|
|
76166
|
+
"runtime-turn:knip-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u26A0\uFE0F Knip newly-unused-exports advisory.", "Same live-this-turn shape as the Knip blocker above.", "live"),
|
|
76167
|
+
"runtime-turn:actionable-warnings-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end actionable-warnings advisory (ast-grep etc).", "`peekActionableWarnings` reads `_actionableWarningsThisTurn` \u2014 recorded fresh from this turn's own dispatch, never a cross-turn cache.", "live"),
|
|
76168
|
+
"runtime-turn:code-quality-warnings-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end code-quality-warnings advisory.", "`peekCodeQualityWarnings` reads `_codeQualityWarningsThisTurn` \u2014 the same per-turn accumulator shape as actionable-warnings above.", "live"),
|
|
76169
|
+
"runtime-turn:disposition-suppressed-notice": labeled(RUNTIME_TURN_FILE, "Turn-end running disposition-suppressed-count notice (#1616).", "A live running total accumulated from this turn's own gate/disposition calls above (`dispositionSuppressedTotal`) \u2014 telemetry ABOUT the other gated surfaces, not a cache of its own.", "live"),
|
|
76170
|
+
// #2001/#2002 collect-later: findings an auxiliary LSP published AFTER its
|
|
76171
|
+
// aux-grace window expired, probed from the client cache at the next
|
|
76172
|
+
// turn_end. Gated on the mark timestamp: a cited file deleted or edited
|
|
76173
|
+
// since the mark drops its findings (never delivered before, and the
|
|
76174
|
+
// drifting edit already re-touched the file — a fresh pending pair
|
|
76175
|
+
// supersedes this one), with both drop arms counted in the
|
|
76176
|
+
// `late_auxiliary_findings` latency record rather than silenced.
|
|
76177
|
+
//
|
|
76178
|
+
// #3102: freshness is only half the gate. The survivors also take the shared
|
|
76179
|
+
// `clients/dispatch/finding-policy.ts` stack (inline `pi-lens-ignore` →
|
|
76180
|
+
// stored dispositions → `.pi-lens.json` rule policy) the per-edit dispatcher,
|
|
76181
|
+
// `mode=full` and the `source=lsp` probe lane apply — without it a finding
|
|
76182
|
+
// the agent marked `false-positive` re-reported on every drain. Per #3088
|
|
76183
|
+
// round-2 F4, the evidence is the CALL TEXT of that filter, which exists
|
|
76184
|
+
// nowhere else in this file: a bare `applyFindingPolicy` would also be
|
|
76185
|
+
// satisfied by an import line or an unrelated caller.
|
|
76186
|
+
"runtime-turn:late-auxiliary-findings": gated(RUNTIME_TURN_FILE, "Turn-end late-auxiliary LSP findings (collect-later probe of aux client caches whose grace window expired).", ["gateFindingsByPathFreshness", "applyFindingPolicy"], ['store: "late-auxiliary-findings"', "applyFindingPolicy(gate.live, {"]),
|
|
76187
|
+
"runtime-turn:late-runner-findings": gated(RUNTIME_TURN_FILE, "Turn-end CLI runner findings collected after the post-write path.", ["gateFindingsByPathFreshness"], ['store: "late-runner-findings"'], { evidenceMin: 2 }),
|
|
76188
|
+
"runtime-turn:cascade-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F9EA} cascade neighbor blocker.", "Cascade results settle synchronously this turn where possible (`settleCascadeRuns`), but an unsettled compute can carry over to a later turn (bounded by a carry cap) \u2014 a carried-over result renders with an explicit `(carried N turns \xB7 scanned Xm ago)` label (#3167, #3168 F3), so the agent can tell it from a fresh observation.", "live", ["cascadeCarrySuffix("], { evidenceMin: 1 }),
|
|
76189
|
+
"runtime-turn:cascade-coverage-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end cascade-coverage-gap advisories (graph/binding/budget).", "Explains what the cascade check could NOT confirm this turn \u2014 not a finding with a cited path, an absence-of-coverage disclosure computed from this turn's own indeterminate-run list. An advisory computed from a carried indeterminate run is labeled `(carried N turns \xB7 <age>)` (#3167, #3168 F4 \u2014 dropped on mixed carried/fresh buckets). The age half reads `scan age unknown` on this surface today: no indeterminate-run producer stamps `observedAt` (only the resolved-found plumb does, `clients/cascade-format.ts`), and one unstamped carried run collapses the whole bucket's age rather than claiming the stamped runs' (#3168 F13). The carry COUNT is always real.", "live", ["withCarryLabel("], { evidenceMin: 3 }),
|
|
76190
|
+
// #3102: the cold-neighbour cascade run is BUILT here, in the quiet-window
|
|
76191
|
+
// reconcile (`onResolvedFound` in index.ts), a turn earlier than the
|
|
76192
|
+
// `runtime-turn:cascade-blocker` render that finally carries it — so it is
|
|
76193
|
+
// its own delivery lane, and it was the one that rendered raw LSP findings
|
|
76194
|
+
// with no policy filter at all. The evidence is the CALL TEXT of the shared
|
|
76195
|
+
// filter (#3088 round-2 F4): a bare `applyFindingPolicy` would also be
|
|
76196
|
+
// satisfied by the import line.
|
|
76197
|
+
"cascade-format:resolved-found-run": gated("clients/cascade-format.ts", "Cold-neighbour ERROR diagnostics formatted into the turn-end cascade run by `buildResolvedFoundCascadeRun` (quiet-window reconcile of a cascade touch that skipped its in-lane wait).", ["applyFindingPolicy"], ["applyFindingPolicy(retained, {"]),
|
|
76198
|
+
// #3157: the IN-LANE cascade — a different delivery lane from the
|
|
76199
|
+
// quiet-window run above, and the one #3102's sweep cleared WRONGLY. Its four
|
|
76200
|
+
// display sites (passive cold snapshot, fresh touch, touch-error fallback,
|
|
76201
|
+
// degraded fallback) assemble `CascadeNeighborResult.diagnostics` and reach
|
|
76202
|
+
// the agent through `formatCascadeNeighborDiagnostics` without ever entering
|
|
76203
|
+
// the dispatcher's `applyOutputFilters` pipeline: the sweep's file-level
|
|
76204
|
+
// verdict ("the per-edit dispatch path, which already filters in
|
|
76205
|
+
// dispatcher.ts") was true only of the per-edit RUNNER output in
|
|
76206
|
+
// `runners/lsp.ts`, which is a different call site in a different file.
|
|
76207
|
+
//
|
|
76208
|
+
// Evidence is the CALL TEXT (#3088 round-2 F4), counted: `cascadeDisplay(` is
|
|
76209
|
+
// the one seam all four sites route through, so `evidenceMin: 4` is the count
|
|
76210
|
+
// of display sites in the file and dropping ANY of them back to a raw
|
|
76211
|
+
// `convertLspDiagnostics` reds this suite. Identity-stubbing the callee
|
|
76212
|
+
// instead is caught behaviourally — it reds twelve cases in
|
|
76213
|
+
// `tests/clients/inlane-cascade-finding-policy.test.ts`, which is a stronger
|
|
76214
|
+
// signal than the R2 proximity heuristic. Residual, stated: a FIFTH display
|
|
76215
|
+
// site that open-codes the conversion keeps the count at 4 and is caught by
|
|
76216
|
+
// review, not by this row.
|
|
76217
|
+
"dispatch-integration:in-lane-cascade": gated("clients/dispatch/integration.ts", "In-lane per-edit cascade neighbour ERROR diagnostics, rendered into the turn-end cascade block by `computeCascadeForFile`.", ["applyCascadeDisplayPolicy"], ["cascadeDisplay("], { evidenceMin: 4 }),
|
|
76218
|
+
"runtime-turn:call-graph-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F4CA} call-graph impact advisory.", "`runtime.callGraph` is a session-lifetime in-memory structure; this round does not verify or gate ITS OWN freshness policy (how/when it incorporates edits made earlier in the session).", "live", [], {
|
|
76219
|
+
status: "partial",
|
|
76220
|
+
partialReason: "call-graph freshness/invalidation policy is out of this PR's scope \u2014 tracked as a follow-up, not silently assumed fresh."
|
|
76221
|
+
}),
|
|
76222
|
+
// #3088 round 2 F4: this row used to name `applyDispositions`/`applyRulePolicy`
|
|
76223
|
+
// with whole-file evidence literals. Once #3088 folded mode=full's stack onto
|
|
76224
|
+
// `applyFindingPolicy`, those two literals survived only in UNRELATED
|
|
76225
|
+
// mode=delta helpers in the same file, so deleting the entire policy stack out
|
|
76226
|
+
// of `applyInlineSuppressionsToSummaries` left this gate — and the ratchet —
|
|
76227
|
+
// green while five behaviour cases redded. The evidence is now the call text
|
|
76228
|
+
// of the merge's own filter, which exists nowhere else in the file.
|
|
76229
|
+
"lens-diagnostics:mode-full": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=full` report.", ["applyFindingPolicy", "reconcileProjectDiagnosticsSnapshot"], [
|
|
76230
|
+
"applyFindingPolicy(summary.diagnostics, {",
|
|
76231
|
+
"reconcileProjectDiagnosticsSnapshot("
|
|
76232
|
+
]),
|
|
76233
|
+
"lens-diagnostics:mode-all": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=all` report (widget-state read).", ["reconcileStaleWidgetFiles", "reconcileStaleWidgetDependencyBlockers"], ["reconcileStaleWidgetFiles(", "reconcileStaleWidgetDependencyBlockers("]),
|
|
76234
|
+
// #1634 review round F3: this was the most important gap — the tool's
|
|
76235
|
+
// DEFAULT mode rendered cached `file:line` findings with zero freshness
|
|
76236
|
+
// check. `applyDeltaFreshnessGate` (this file's sibling in
|
|
76237
|
+
// tools/lens-diagnostics.ts) now routes the actionable/quality-warnings
|
|
76238
|
+
// caches through the shared gate using each report's own `generatedAt`.
|
|
76239
|
+
// Round R3: mode=delta has a THIRD arm — the persisted project-diagnostics
|
|
76240
|
+
// delta report, rendered by `appendProjectDiagnosticsDeltaLines` — which
|
|
76241
|
+
// carried the identical unfixed shape. It now gates the same way, against
|
|
76242
|
+
// its own `generatedAt`.
|
|
76243
|
+
"lens-diagnostics:mode-delta": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=delta` report (the tool's DEFAULT mode) \u2014 re-serves the actionable-warnings/code-quality-warnings caches AND the persisted project-diagnostics delta report.", ["gateFindingsByPathFreshness"], [
|
|
76244
|
+
'store: "lens-diagnostics-delta"',
|
|
76245
|
+
"applyDeltaFreshnessGate(",
|
|
76246
|
+
'store: "lens-diagnostics-delta-project"'
|
|
76247
|
+
]),
|
|
76248
|
+
"widget-state:footer": gated("clients/widget-state.ts", "TUI footer blocking/error/warning tally.", ["reconcileStaleWidgetFiles", "isBlocking"], ["isBlocking(diagnostic)", "reconcileStaleWidgetFiles()"]),
|
|
76249
|
+
"agent-nudge:context-message": labeled("clients/agent-nudge.ts", "Post-edit file-touch nudge injected via `context`.", "Not a scanner finding store: no severity, no cited line, no cache \u2014 the accumulator is drained and cleared at the moment of injection, so the content IS the current state by construction.", "live"),
|
|
76250
|
+
"test-runner-delivery:custom-entry": labeled("clients/test-runner-delivery.ts", "Post-agent test-runner failures in a non-context custom entry.", "The cache remains authoritative for pull diagnostics and the commit guard; this surface appends only after provenance validation and an idle recheck.", "live"),
|
|
76251
|
+
"project-diagnostics:persisted-snapshot": gated(LENS_DIAGNOSTICS_FILE, "Cross-session persisted project-diagnostics snapshot read.", ["reconcileProjectDiagnosticsSnapshot"], ["reconcileProjectDiagnosticsSnapshot("]),
|
|
76252
|
+
// ── #2028: the remaining agent-facing surfaces ──────────────────────────
|
|
76253
|
+
// Registered after #2028's root-cause review found the 🔴 STOP block
|
|
76254
|
+
// rendering stale/deleted-file blockers because its surface was never in
|
|
76255
|
+
// this registry — the exact "gated or labeled, never neither" gap this
|
|
76256
|
+
// module exists to close.
|
|
76257
|
+
"tool-call:stop-blocker": gated("clients/pipeline.ts", "Per-edit \u{1F534} STOP blocker output appended to the write/edit tool result.", ["dropFindingsForMissingPaths"], ['store: "stop-blocker"']),
|
|
76258
|
+
// The freshness stack itself (own-file mtime + reverse-dependency mtimes
|
|
76259
|
+
// via isEntryFresh, plus the #1095 content binding) lives inside
|
|
76260
|
+
// clients/lsp/workspace-diagnostics-cache.ts; the two evidence calls are
|
|
76261
|
+
// the tool's literal entry points into that gated path.
|
|
76262
|
+
"lsp-diagnostics:tool-output": gated("tools/lsp-diagnostics.ts", "`lsp_diagnostics` batch/directory sweep results. Cache hits replay through the shared workspace-diagnostics cache: createWorkspaceDiagnosticsCacheContext is the tool's entry, and its lookup() applies the #671/#672 freshness stack (own-file mtime + reverse-dependency mtimes via isEntryFresh) plus the #1095 content binding. #3088: every route out of this tool \u2014 fresh, cache replay, single file, directory \u2014 also passes applyProbeFindingPolicy, the stored-disposition / .pi-lens.json rule-policy / inline pi-lens-ignore stack the per-edit dispatch path and mode=full apply.", [
|
|
76263
|
+
"createWorkspaceDiagnosticsCacheContext",
|
|
76264
|
+
"isEntryFresh",
|
|
76265
|
+
"cacheCtx.lookup",
|
|
76266
|
+
"applyProbeFindingPolicy"
|
|
76267
|
+
], [
|
|
76268
|
+
"createWorkspaceDiagnosticsCacheContext(resolvedCwd)",
|
|
76269
|
+
"cacheCtx.lookup(file, scopeKey)",
|
|
76270
|
+
"applyProbeFindingPolicy("
|
|
76271
|
+
]),
|
|
76272
|
+
"git-guard:commit-blocked": labeled("clients/git-guard.ts", "Git-guard commit/push \u{1F534} COMMIT BLOCKED verdict (--lens-guard).", "Synchronous preflight rejection returned inline with the failed git command \u2014 no stored state is delivered, so nothing can go stale between detection and delivery.", "live"),
|
|
76273
|
+
"shared-checkout-guard:worktree-mutation-blocked": labeled("clients/shared-checkout-guard.ts", "Shared-checkout \u{1F534} WORKING-TREE CHANGE BLOCKED verdict (--lens-checkout-guard).", "Synchronous preflight rejection returned inline with the failed git command. Both inputs are read at decision time \u2014 the instance registry and `git status` \u2014 so no stored finding is replayed and nothing can go stale between detection and delivery.", "live"),
|
|
76274
|
+
"read-guard-tool-lines:preflight-errors": labeled("clients/read-guard-tool-lines.ts", "Read-guard hashline BLOCKED / RE-READ REQUIRED / PARTIAL APPLY / ALREADY APPLIED preflight errors (#2402).", "Computed fresh per edit attempt and returned as that attempt's rejection \u2014 no cached findings are replayed, so there is no staleness window. The PARTIAL APPLY and ALREADY APPLIED variants describe the same attempt's commit outcome; applied-edit recognition reads RuntimeCoordinator's session-scoped record, which resets with the session.", "live"),
|
|
76275
|
+
"mutating-tool:adapter-preflight-errors": labeled("clients/mutating-tool.ts", "Shape-adapter BLOCKED preflight errors for hashline edit inputs the adapter recognized but could not resolve to a range (#2423).", "Computed fresh from the tool input on each attempt and returned as that attempt's rejection, so there is no staleness window. The adapters read only the call's own arguments; nothing cached is replayed.", "live"),
|
|
76276
|
+
"tool-call:duplicate-export-blocker": labeled("clients/runtime-tool-call.ts", "Duplicate-export STOP rejection returned inline with the failed edit.", "Synchronous preflight rejection computed per edit attempt; no stored state.", "live"),
|
|
76277
|
+
"agent-behavior:thrashing-notice": labeled("clients/agent-behavior-client.ts", "In-result thrashing/blind-write detection notice.", "Ephemeral notice computed at detection time inside the same tool result \u2014 no persistence and no cache, so nothing can be stale.", "live")
|
|
76278
|
+
};
|
|
76279
|
+
}
|
|
76280
|
+
});
|
|
76281
|
+
|
|
76027
76282
|
// dist/clients/cascade-format.js
|
|
76028
76283
|
import * as fs88 from "node:fs";
|
|
76029
76284
|
function formatCascadeNeighborDiagnostics(cwd, neighbors, options = {}) {
|
|
@@ -76114,7 +76369,11 @@ suppressed by disposition: ${suppressed} finding(s) (marked false-positive or wo
|
|
|
76114
76369
|
formatted
|
|
76115
76370
|
},
|
|
76116
76371
|
neighborCount: 1,
|
|
76117
|
-
diagnosticCount: diagnostics.length
|
|
76372
|
+
diagnosticCount: diagnostics.length,
|
|
76373
|
+
// #3168 F3: the #1444 publish stamp — the run's own observation time, so
|
|
76374
|
+
// the carried-render age label states the real age instead of claiming
|
|
76375
|
+
// no stamp exists.
|
|
76376
|
+
...neighbor.publishedAt !== void 0 ? { observedAt: neighbor.publishedAt } : {}
|
|
76118
76377
|
};
|
|
76119
76378
|
}
|
|
76120
76379
|
function applyCascadeDisplayPolicy(errors, options) {
|
|
@@ -76170,6 +76429,12 @@ function readNeighborContent(filePath) {
|
|
|
76170
76429
|
return void 0;
|
|
76171
76430
|
}
|
|
76172
76431
|
}
|
|
76432
|
+
function cascadeCarrySuffix(carriedTurns, observedAt) {
|
|
76433
|
+
if (carriedTurns === void 0 || carriedTurns < 1)
|
|
76434
|
+
return void 0;
|
|
76435
|
+
const noun = carriedTurns === 1 ? "turn" : "turns";
|
|
76436
|
+
return `(carried ${carriedTurns} ${noun} \xB7 ${formatCacheAgeLabel(observedAt)})`;
|
|
76437
|
+
}
|
|
76173
76438
|
var init_cascade_format = __esm({
|
|
76174
76439
|
"dist/clients/cascade-format.js"() {
|
|
76175
76440
|
"use strict";
|
|
@@ -76177,6 +76442,7 @@ var init_cascade_format = __esm({
|
|
|
76177
76442
|
init_finding_policy();
|
|
76178
76443
|
init_file_role();
|
|
76179
76444
|
init_latency_logger();
|
|
76445
|
+
init_finding_delivery_gate();
|
|
76180
76446
|
init_lsp_diagnostics();
|
|
76181
76447
|
init_runner_context();
|
|
76182
76448
|
}
|
|
@@ -76457,7 +76723,8 @@ function registerCascadeTierReconcileTask(getLspService, options = {}) {
|
|
|
76457
76723
|
options.onResolvedFound?.({
|
|
76458
76724
|
filePath: o.filePath,
|
|
76459
76725
|
serverId: o.serverId,
|
|
76460
|
-
diagnostics: o.diagnostics
|
|
76726
|
+
diagnostics: o.diagnostics,
|
|
76727
|
+
...o.publishedAt !== void 0 ? { publishedAt: o.publishedAt } : {}
|
|
76461
76728
|
});
|
|
76462
76729
|
} else if (o.outcome === "resolved-clean" && o.publishedAt != null) {
|
|
76463
76730
|
options.onResolvedClean?.({
|
|
@@ -95750,7 +96017,7 @@ __export(lens_map_exports, {
|
|
|
95750
96017
|
parseUntrackedIgnoredOutput: () => parseUntrackedIgnoredOutput,
|
|
95751
96018
|
renderMapHtml: () => renderMapHtml
|
|
95752
96019
|
});
|
|
95753
|
-
import * as
|
|
96020
|
+
import * as fs133 from "node:fs";
|
|
95754
96021
|
import * as path209 from "node:path";
|
|
95755
96022
|
function aggregateGraphToFiles(graph, options) {
|
|
95756
96023
|
const maxNodes = Math.max(1, options?.maxNodes ?? DEFAULT_MAX_MAP_NODES);
|
|
@@ -96701,9 +96968,9 @@ async function generateLensMap(cwd) {
|
|
|
96701
96968
|
};
|
|
96702
96969
|
const html = renderMapHtml(payload);
|
|
96703
96970
|
const outDir = path209.join(getProjectDataDir(cwd), "reports");
|
|
96704
|
-
|
|
96971
|
+
fs133.mkdirSync(outDir, { recursive: true });
|
|
96705
96972
|
const filePath = path209.join(outDir, "lens-map.html");
|
|
96706
|
-
|
|
96973
|
+
fs133.writeFileSync(filePath, html, "utf-8");
|
|
96707
96974
|
return {
|
|
96708
96975
|
filePath,
|
|
96709
96976
|
fileCount: aggregated.nodes.length,
|
|
@@ -96747,7 +97014,7 @@ __export(performance_report_exports, {
|
|
|
96747
97014
|
resolveLogByteBudget: () => resolveLogByteBudget,
|
|
96748
97015
|
summarizePhaseLatency: () => summarizePhaseLatency
|
|
96749
97016
|
});
|
|
96750
|
-
import * as
|
|
97017
|
+
import * as fs134 from "node:fs";
|
|
96751
97018
|
import * as readline from "node:readline";
|
|
96752
97019
|
function resolveLogByteBudget() {
|
|
96753
97020
|
return getMaxLogSizeMB() * 1024 * 1024;
|
|
@@ -96879,7 +97146,7 @@ async function readPhaseLogTail(filePath, windowBytes, maxSamples, processId, se
|
|
|
96879
97146
|
});
|
|
96880
97147
|
let handle;
|
|
96881
97148
|
try {
|
|
96882
|
-
handle = await
|
|
97149
|
+
handle = await fs134.promises.open(filePath, "r");
|
|
96883
97150
|
const stat4 = await handle.stat();
|
|
96884
97151
|
if (!stat4.isFile()) {
|
|
96885
97152
|
const notAFile = new Error(`EISDIR: illegal operation on a directory, read '${filePath}'`);
|
|
@@ -99321,8 +99588,11 @@ function resolveSkillPaths(importMetaUrl) {
|
|
|
99321
99588
|
});
|
|
99322
99589
|
if (health.status !== "healthy") {
|
|
99323
99590
|
const entryDir = path85.dirname(fileURLToPath6(importMetaUrl));
|
|
99324
|
-
const
|
|
99325
|
-
|
|
99591
|
+
const healthDescription = describeBundledResourceHealth(health, skillsDir, `no SKILL.md (or loadable .md) found under ${skillsDir}`);
|
|
99592
|
+
const notifyReason = `${healthDescription} (entry loaded from ${entryDir})`;
|
|
99593
|
+
const classification = health.status === "unreadable" ? `cannot read (${health.fsErrorCode})` : health.status === "empty" ? "no SKILL.md found" : "no such directory";
|
|
99594
|
+
const ledgerReason = `${classification} (entry loaded from ${entryDir})`;
|
|
99595
|
+
reportBundledResourceDirHealth(SKILLS_DIR_MISSING_KIND, skillsDir, health, "skills", ledgerReason, `pi-lens: registers zero skills \u2014 ${notifyReason}.`);
|
|
99326
99596
|
}
|
|
99327
99597
|
return [skillsDir];
|
|
99328
99598
|
}
|
|
@@ -104075,7 +104345,19 @@ function mergeActionableWarningsReports(args) {
|
|
|
104075
104345
|
continue;
|
|
104076
104346
|
}
|
|
104077
104347
|
mergedFiles++;
|
|
104078
|
-
const merged = incumbent ?
|
|
104348
|
+
const merged = incumbent ? incumbent.reVerified || incumbent.reVerifyIncomplete ? (
|
|
104349
|
+
// #3170: the runtime just RE-OBSERVED this file (the bounded
|
|
104350
|
+
// persistent-reverify pass) — the fresh observation supersedes
|
|
104351
|
+
// the carried entry instead of unioning with it: a converged
|
|
104352
|
+
// finding would otherwise survive its own supersession via the
|
|
104353
|
+
// id-union in `mergeWarnings`.
|
|
104354
|
+
{
|
|
104355
|
+
...incumbent,
|
|
104356
|
+
fileSeq: incumbent.fileSeq ?? entry.fileSeq,
|
|
104357
|
+
generatedAt: olderStamp(incumbent.generatedAt ?? newerReport?.generatedAt, entry.generatedAt ?? olderReport?.generatedAt),
|
|
104358
|
+
warnings: incumbent.warnings
|
|
104359
|
+
}
|
|
104360
|
+
) : {
|
|
104079
104361
|
...incumbent,
|
|
104080
104362
|
fileSeq: incumbent.fileSeq ?? entry.fileSeq,
|
|
104081
104363
|
generatedAt: olderStamp(incumbent.generatedAt ?? newerReport?.generatedAt, entry.generatedAt ?? olderReport?.generatedAt),
|
|
@@ -104400,7 +104682,7 @@ function formatActionableWarningsAdvisory(report, cwd, host = "pi") {
|
|
|
104400
104682
|
if (report.summary.unsuppressed === 0)
|
|
104401
104683
|
return void 0;
|
|
104402
104684
|
const files2 = report.files.filter((file) => file.warnings.some((warning) => !warning.suppressed));
|
|
104403
|
-
const fileList = files2.slice(0, 5).map((file) => ` ${file.displayPath}: ${file.warnings.filter((warning) => !warning.suppressed).length}`).join("\n");
|
|
104685
|
+
const fileList = files2.slice(0, 5).map((file) => ` ${file.displayPath}: ${file.warnings.filter((warning) => !warning.suppressed).length}${file.reVerifyIncomplete ? " (re-verify incomplete)" : ""}`).join("\n");
|
|
104404
104686
|
const more = files2.length > 5 ? `
|
|
104405
104687
|
... and ${files2.length - 5} more file(s)` : "";
|
|
104406
104688
|
const safe2 = report.summary.autoFixEligible > 0 ? ` ${report.summary.autoFixEligible} appear to have conservative preferred quickfixes.` : "";
|
|
@@ -105660,6 +105942,8 @@ async function runFormatPhase(filePath, getFormatService2, dbg2, signal, budgetM
|
|
|
105660
105942
|
};
|
|
105661
105943
|
}
|
|
105662
105944
|
function buildEnrichedBlockerOutput(blockers, fileContent = "") {
|
|
105945
|
+
if (blockers.length === 0)
|
|
105946
|
+
return "";
|
|
105663
105947
|
const fileLines = fileContent ? fileContent.split("\n") : [];
|
|
105664
105948
|
const MAX_SNIPPET = 120;
|
|
105665
105949
|
let out = `
|
|
@@ -105898,7 +106182,8 @@ async function runPipeline(ctx, deps) {
|
|
|
105898
106182
|
const rest = dispatchResult.output.slice(dispatchResult.blockerOutput.length);
|
|
105899
106183
|
if (rest)
|
|
105900
106184
|
gatedOut += rest;
|
|
105901
|
-
|
|
106185
|
+
if (gatedOut)
|
|
106186
|
+
output += `
|
|
105902
106187
|
|
|
105903
106188
|
${gatedOut}`;
|
|
105904
106189
|
} else {
|
|
@@ -113944,7 +114229,7 @@ function wrapSessionEventHandlerWithResult(eventName, handler, options) {
|
|
|
113944
114229
|
init_session_lifecycle();
|
|
113945
114230
|
|
|
113946
114231
|
// dist/clients/runtime-turn.js
|
|
113947
|
-
import * as
|
|
114232
|
+
import * as fs124 from "node:fs";
|
|
113948
114233
|
import * as path187 from "node:path";
|
|
113949
114234
|
init_cascade_budget();
|
|
113950
114235
|
init_cascade_logger();
|
|
@@ -113952,196 +114237,7 @@ init_path_utils();
|
|
|
113952
114237
|
init_string_utils();
|
|
113953
114238
|
init_runner_context();
|
|
113954
114239
|
init_file_utils();
|
|
113955
|
-
|
|
113956
|
-
// dist/clients/finding-delivery-gate.js
|
|
113957
|
-
var MS_PER_MINUTE = 6e4;
|
|
113958
|
-
function markUnreconciledFindings(findings) {
|
|
113959
|
-
return findings.map((finding) => ({ ...finding, stale: true }));
|
|
113960
|
-
}
|
|
113961
|
-
function formatCacheAgeLabel(scannedAt, nowMs = Date.now()) {
|
|
113962
|
-
if (scannedAt === void 0 || scannedAt === null || scannedAt === "") {
|
|
113963
|
-
return "scan age unknown";
|
|
113964
|
-
}
|
|
113965
|
-
const scannedAtMs = typeof scannedAt === "number" ? scannedAt : Date.parse(scannedAt);
|
|
113966
|
-
if (!Number.isFinite(scannedAtMs))
|
|
113967
|
-
return "scan age unknown";
|
|
113968
|
-
const ageMs = Math.max(0, nowMs - scannedAtMs);
|
|
113969
|
-
const ageMinutes = Math.round(ageMs / MS_PER_MINUTE);
|
|
113970
|
-
if (ageMinutes < 1)
|
|
113971
|
-
return "scanned <1m ago";
|
|
113972
|
-
if (ageMinutes < 60)
|
|
113973
|
-
return `scanned ${ageMinutes}m ago`;
|
|
113974
|
-
const ageHours = Math.floor(ageMinutes / 60);
|
|
113975
|
-
const remMinutes = ageMinutes % 60;
|
|
113976
|
-
return remMinutes === 0 ? `scanned ${ageHours}h ago` : `scanned ${ageHours}h ${remMinutes}m ago`;
|
|
113977
|
-
}
|
|
113978
|
-
function gated(file, description, gates, evidence, extra = {}) {
|
|
113979
|
-
return { mode: "gated", file, description, gates, evidence, ...extra };
|
|
113980
|
-
}
|
|
113981
|
-
function labeled(file, description, reason, ageSource, evidence = [], extra = {}) {
|
|
113982
|
-
return {
|
|
113983
|
-
mode: "labeled",
|
|
113984
|
-
file,
|
|
113985
|
-
description,
|
|
113986
|
-
reason,
|
|
113987
|
-
ageSource,
|
|
113988
|
-
evidence,
|
|
113989
|
-
...extra
|
|
113990
|
-
};
|
|
113991
|
-
}
|
|
113992
|
-
var RUNTIME_TURN_FILE = "clients/runtime-turn.ts";
|
|
113993
|
-
var LENS_DIAGNOSTICS_FILE = "tools/lens-diagnostics.ts";
|
|
113994
|
-
var DELIVERY_SURFACES = {
|
|
113995
|
-
"runtime-turn:secrets-gitleaks": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F534} secrets blocker, gitleaks cache.", ["gateFindingsByPathFreshness"], ['store: "gitleaks"']),
|
|
113996
|
-
"runtime-turn:secrets-trivy": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F534} secrets blocker, trivy secrets cache.", ["gateFindingsByPathFreshness"], ['store: "trivy-secrets"']),
|
|
113997
|
-
"runtime-turn:govulncheck-advisory": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F6E1}\uFE0F Go CVE advisory (call-site line only).", ["gateFindingsByPathFreshness"], ['store: "govulncheck"']),
|
|
113998
|
-
// Two tagged seams (the stale and live render branches below the same
|
|
113999
|
-
// `sweepInlineBlockerFreshness` call) legitimately share one evidence
|
|
114000
|
-
// occurrence — evidenceMin: 2 tells the exclusive-assignment check both
|
|
114001
|
-
// are expected claimants, not a rogue seam contesting the real one.
|
|
114002
|
-
"runtime-turn:unresolved-inline-blocker": gated(
|
|
114003
|
-
RUNTIME_TURN_FILE,
|
|
114004
|
-
"Turn-end re-surfaced unresolved inline blockers.",
|
|
114005
|
-
["sweepInlineBlockerFreshness"],
|
|
114006
|
-
// #1790: the call now passes `additionalEntries` (widget-store rows) as a
|
|
114007
|
-
// third argument, so the literal is the call's opening rather than the
|
|
114008
|
-
// whole single-line invocation.
|
|
114009
|
-
["sweepInlineBlockerFreshness(runtime, cwd, {"],
|
|
114010
|
-
{ evidenceMin: 2 }
|
|
114011
|
-
),
|
|
114012
|
-
// Same two gate calls as the live secrets tier — this tier renders their
|
|
114013
|
-
// `.stale` arm, so it has no OWN gate call to point at.
|
|
114014
|
-
"runtime-turn:stale-secrets-tier": gated(RUNTIME_TURN_FILE, "Turn-end \u{1F511} demoted-secrets tier (drifted since scan).", ["gateFindingsByPathFreshness"], ['store: "gitleaks"', 'store: "trivy-secrets"']),
|
|
114015
|
-
// The evidence below is the literal header FRAGMENT including the
|
|
114016
|
-
// interpolation — proves the label is actually rendered, not merely
|
|
114017
|
-
// computed and discarded (review round F1's "deleted the age
|
|
114018
|
-
// interpolations" attack).
|
|
114019
|
-
"runtime-turn:trivy-critical-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F534} CRITICAL dependency CVE blocker (trivy).", "Package-pinned finding with no cited file:line to stat \u2014 freshness has nothing to check drift against. The session_start cache can be arbitrarily old, so its age is stated instead. Also routes through `filterFindingsByDisposition` (#1625) first \u2014 a suppressed/false-positive finding never reaches this render, so the age label and the disposition filter compose rather than substitute for each other.", "TrivyResult.scannedAt", ["CRITICAL dependency CVEs (trivy, ${trivyAgeLabel}"]),
|
|
114020
|
-
"runtime-turn:trivy-cve-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F6E1}\uFE0F non-critical dependency CVE advisory (trivy).", "Same package-pinned shape and #1625 disposition composition as the CRITICAL blocker above.", "TrivyResult.scannedAt", ["Dependency CVEs (trivy, ${trivyAgeLabel}"]),
|
|
114021
|
-
"runtime-turn:trivy-license-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F4DC} dependency license-risk advisory (trivy).", "Same package-pinned shape as the CRITICAL blocker above.", "TrivyResult.scannedAt", ["Dependency license risk (trivy, ${trivyAgeLabel}"]),
|
|
114022
|
-
"runtime-turn:dead-code-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end dead-code delta advisory (knip/vulture/etc).", "The delta shown is computed from THIS turn's own analyze() call, diffed against the previous cache \u2014 never a replay of a stale cache.", "live"),
|
|
114023
|
-
"runtime-turn:knip-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F534} Knip unresolved-imports/deps blocker.", "Same shape as the dead-code advisory: `await knipClient.analyze(cwd, ...)` runs fresh THIS turn, diffed against the previous cache and filtered to files edited this turn \u2014 never a replay of a stale cache.", "live"),
|
|
114024
|
-
"runtime-turn:knip-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u26A0\uFE0F Knip newly-unused-exports advisory.", "Same live-this-turn shape as the Knip blocker above.", "live"),
|
|
114025
|
-
"runtime-turn:actionable-warnings-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end actionable-warnings advisory (ast-grep etc).", "`peekActionableWarnings` reads `_actionableWarningsThisTurn` \u2014 recorded fresh from this turn's own dispatch, never a cross-turn cache.", "live"),
|
|
114026
|
-
"runtime-turn:code-quality-warnings-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end code-quality-warnings advisory.", "`peekCodeQualityWarnings` reads `_codeQualityWarningsThisTurn` \u2014 the same per-turn accumulator shape as actionable-warnings above.", "live"),
|
|
114027
|
-
"runtime-turn:disposition-suppressed-notice": labeled(RUNTIME_TURN_FILE, "Turn-end running disposition-suppressed-count notice (#1616).", "A live running total accumulated from this turn's own gate/disposition calls above (`dispositionSuppressedTotal`) \u2014 telemetry ABOUT the other gated surfaces, not a cache of its own.", "live"),
|
|
114028
|
-
// #2001/#2002 collect-later: findings an auxiliary LSP published AFTER its
|
|
114029
|
-
// aux-grace window expired, probed from the client cache at the next
|
|
114030
|
-
// turn_end. Gated on the mark timestamp: a cited file deleted or edited
|
|
114031
|
-
// since the mark drops its findings (never delivered before, and the
|
|
114032
|
-
// drifting edit already re-touched the file — a fresh pending pair
|
|
114033
|
-
// supersedes this one), with both drop arms counted in the
|
|
114034
|
-
// `late_auxiliary_findings` latency record rather than silenced.
|
|
114035
|
-
//
|
|
114036
|
-
// #3102: freshness is only half the gate. The survivors also take the shared
|
|
114037
|
-
// `clients/dispatch/finding-policy.ts` stack (inline `pi-lens-ignore` →
|
|
114038
|
-
// stored dispositions → `.pi-lens.json` rule policy) the per-edit dispatcher,
|
|
114039
|
-
// `mode=full` and the `source=lsp` probe lane apply — without it a finding
|
|
114040
|
-
// the agent marked `false-positive` re-reported on every drain. Per #3088
|
|
114041
|
-
// round-2 F4, the evidence is the CALL TEXT of that filter, which exists
|
|
114042
|
-
// nowhere else in this file: a bare `applyFindingPolicy` would also be
|
|
114043
|
-
// satisfied by an import line or an unrelated caller.
|
|
114044
|
-
"runtime-turn:late-auxiliary-findings": gated(RUNTIME_TURN_FILE, "Turn-end late-auxiliary LSP findings (collect-later probe of aux client caches whose grace window expired).", ["gateFindingsByPathFreshness", "applyFindingPolicy"], ['store: "late-auxiliary-findings"', "applyFindingPolicy(gate.live, {"]),
|
|
114045
|
-
"runtime-turn:late-runner-findings": gated(RUNTIME_TURN_FILE, "Turn-end CLI runner findings collected after the post-write path.", ["gateFindingsByPathFreshness"], ['store: "late-runner-findings"'], { evidenceMin: 2 }),
|
|
114046
|
-
"runtime-turn:cascade-blocker": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F9EA} cascade neighbor blocker.", "Cascade results settle synchronously this turn where possible (`settleCascadeRuns`), but an unsettled compute can carry over to a later turn (bounded by a carry cap) \u2014 this round does not freshness-gate that carry-over window.", "live", [], {
|
|
114047
|
-
status: "partial",
|
|
114048
|
-
partialReason: "A carried-over cascade result (run.carriedTurns > 0) is rendered without an age label. Follow-up: surface carriedTurns as an explicit label when > 0, or route through formatCacheAgeLabel using the run's own timestamp."
|
|
114049
|
-
}),
|
|
114050
|
-
"runtime-turn:cascade-coverage-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end cascade-coverage-gap advisories (graph/binding/budget).", "Explains what the cascade check could NOT confirm this turn \u2014 not a finding with a cited path, an absence-of-coverage disclosure computed from this turn's own indeterminate-run list.", "live", [], {
|
|
114051
|
-
status: "partial",
|
|
114052
|
-
partialReason: "Same cascade carry-over caveat as runtime-turn:cascade-blocker."
|
|
114053
|
-
}),
|
|
114054
|
-
// #3102: the cold-neighbour cascade run is BUILT here, in the quiet-window
|
|
114055
|
-
// reconcile (`onResolvedFound` in index.ts), a turn earlier than the
|
|
114056
|
-
// `runtime-turn:cascade-blocker` render that finally carries it — so it is
|
|
114057
|
-
// its own delivery lane, and it was the one that rendered raw LSP findings
|
|
114058
|
-
// with no policy filter at all. The evidence is the CALL TEXT of the shared
|
|
114059
|
-
// filter (#3088 round-2 F4): a bare `applyFindingPolicy` would also be
|
|
114060
|
-
// satisfied by the import line.
|
|
114061
|
-
"cascade-format:resolved-found-run": gated("clients/cascade-format.ts", "Cold-neighbour ERROR diagnostics formatted into the turn-end cascade run by `buildResolvedFoundCascadeRun` (quiet-window reconcile of a cascade touch that skipped its in-lane wait).", ["applyFindingPolicy"], ["applyFindingPolicy(retained, {"]),
|
|
114062
|
-
// #3157: the IN-LANE cascade — a different delivery lane from the
|
|
114063
|
-
// quiet-window run above, and the one #3102's sweep cleared WRONGLY. Its four
|
|
114064
|
-
// display sites (passive cold snapshot, fresh touch, touch-error fallback,
|
|
114065
|
-
// degraded fallback) assemble `CascadeNeighborResult.diagnostics` and reach
|
|
114066
|
-
// the agent through `formatCascadeNeighborDiagnostics` without ever entering
|
|
114067
|
-
// the dispatcher's `applyOutputFilters` pipeline: the sweep's file-level
|
|
114068
|
-
// verdict ("the per-edit dispatch path, which already filters in
|
|
114069
|
-
// dispatcher.ts") was true only of the per-edit RUNNER output in
|
|
114070
|
-
// `runners/lsp.ts`, which is a different call site in a different file.
|
|
114071
|
-
//
|
|
114072
|
-
// Evidence is the CALL TEXT (#3088 round-2 F4), counted: `cascadeDisplay(` is
|
|
114073
|
-
// the one seam all four sites route through, so `evidenceMin: 4` is the count
|
|
114074
|
-
// of display sites in the file and dropping ANY of them back to a raw
|
|
114075
|
-
// `convertLspDiagnostics` reds this suite. Identity-stubbing the callee
|
|
114076
|
-
// instead is caught behaviourally — it reds twelve cases in
|
|
114077
|
-
// `tests/clients/inlane-cascade-finding-policy.test.ts`, which is a stronger
|
|
114078
|
-
// signal than the R2 proximity heuristic. Residual, stated: a FIFTH display
|
|
114079
|
-
// site that open-codes the conversion keeps the count at 4 and is caught by
|
|
114080
|
-
// review, not by this row.
|
|
114081
|
-
"dispatch-integration:in-lane-cascade": gated("clients/dispatch/integration.ts", "In-lane per-edit cascade neighbour ERROR diagnostics, rendered into the turn-end cascade block by `computeCascadeForFile`.", ["applyCascadeDisplayPolicy"], ["cascadeDisplay("], { evidenceMin: 4 }),
|
|
114082
|
-
"runtime-turn:call-graph-advisory": labeled(RUNTIME_TURN_FILE, "Turn-end \u{1F4CA} call-graph impact advisory.", "`runtime.callGraph` is a session-lifetime in-memory structure; this round does not verify or gate ITS OWN freshness policy (how/when it incorporates edits made earlier in the session).", "live", [], {
|
|
114083
|
-
status: "partial",
|
|
114084
|
-
partialReason: "call-graph freshness/invalidation policy is out of this PR's scope \u2014 tracked as a follow-up, not silently assumed fresh."
|
|
114085
|
-
}),
|
|
114086
|
-
// #3088 round 2 F4: this row used to name `applyDispositions`/`applyRulePolicy`
|
|
114087
|
-
// with whole-file evidence literals. Once #3088 folded mode=full's stack onto
|
|
114088
|
-
// `applyFindingPolicy`, those two literals survived only in UNRELATED
|
|
114089
|
-
// mode=delta helpers in the same file, so deleting the entire policy stack out
|
|
114090
|
-
// of `applyInlineSuppressionsToSummaries` left this gate — and the ratchet —
|
|
114091
|
-
// green while five behaviour cases redded. The evidence is now the call text
|
|
114092
|
-
// of the merge's own filter, which exists nowhere else in the file.
|
|
114093
|
-
"lens-diagnostics:mode-full": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=full` report.", ["applyFindingPolicy", "reconcileProjectDiagnosticsSnapshot"], [
|
|
114094
|
-
"applyFindingPolicy(summary.diagnostics, {",
|
|
114095
|
-
"reconcileProjectDiagnosticsSnapshot("
|
|
114096
|
-
]),
|
|
114097
|
-
"lens-diagnostics:mode-all": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=all` report (widget-state read).", ["reconcileStaleWidgetFiles", "reconcileStaleWidgetDependencyBlockers"], ["reconcileStaleWidgetFiles(", "reconcileStaleWidgetDependencyBlockers("]),
|
|
114098
|
-
// #1634 review round F3: this was the most important gap — the tool's
|
|
114099
|
-
// DEFAULT mode rendered cached `file:line` findings with zero freshness
|
|
114100
|
-
// check. `applyDeltaFreshnessGate` (this file's sibling in
|
|
114101
|
-
// tools/lens-diagnostics.ts) now routes the actionable/quality-warnings
|
|
114102
|
-
// caches through the shared gate using each report's own `generatedAt`.
|
|
114103
|
-
// Round R3: mode=delta has a THIRD arm — the persisted project-diagnostics
|
|
114104
|
-
// delta report, rendered by `appendProjectDiagnosticsDeltaLines` — which
|
|
114105
|
-
// carried the identical unfixed shape. It now gates the same way, against
|
|
114106
|
-
// its own `generatedAt`.
|
|
114107
|
-
"lens-diagnostics:mode-delta": gated(LENS_DIAGNOSTICS_FILE, "`lens_diagnostics mode=delta` report (the tool's DEFAULT mode) \u2014 re-serves the actionable-warnings/code-quality-warnings caches AND the persisted project-diagnostics delta report.", ["gateFindingsByPathFreshness"], [
|
|
114108
|
-
'store: "lens-diagnostics-delta"',
|
|
114109
|
-
"applyDeltaFreshnessGate(",
|
|
114110
|
-
'store: "lens-diagnostics-delta-project"'
|
|
114111
|
-
]),
|
|
114112
|
-
"widget-state:footer": gated("clients/widget-state.ts", "TUI footer blocking/error/warning tally.", ["reconcileStaleWidgetFiles", "isBlocking"], ["isBlocking(diagnostic)", "reconcileStaleWidgetFiles()"]),
|
|
114113
|
-
"agent-nudge:context-message": labeled("clients/agent-nudge.ts", "Post-edit file-touch nudge injected via `context`.", "Not a scanner finding store: no severity, no cited line, no cache \u2014 the accumulator is drained and cleared at the moment of injection, so the content IS the current state by construction.", "live"),
|
|
114114
|
-
"test-runner-delivery:custom-entry": labeled("clients/test-runner-delivery.ts", "Post-agent test-runner failures in a non-context custom entry.", "The cache remains authoritative for pull diagnostics and the commit guard; this surface appends only after provenance validation and an idle recheck.", "live"),
|
|
114115
|
-
"project-diagnostics:persisted-snapshot": gated(LENS_DIAGNOSTICS_FILE, "Cross-session persisted project-diagnostics snapshot read.", ["reconcileProjectDiagnosticsSnapshot"], ["reconcileProjectDiagnosticsSnapshot("]),
|
|
114116
|
-
// ── #2028: the remaining agent-facing surfaces ──────────────────────────
|
|
114117
|
-
// Registered after #2028's root-cause review found the 🔴 STOP block
|
|
114118
|
-
// rendering stale/deleted-file blockers because its surface was never in
|
|
114119
|
-
// this registry — the exact "gated or labeled, never neither" gap this
|
|
114120
|
-
// module exists to close.
|
|
114121
|
-
"tool-call:stop-blocker": gated("clients/pipeline.ts", "Per-edit \u{1F534} STOP blocker output appended to the write/edit tool result.", ["dropFindingsForMissingPaths"], ['store: "stop-blocker"']),
|
|
114122
|
-
// The freshness stack itself (own-file mtime + reverse-dependency mtimes
|
|
114123
|
-
// via isEntryFresh, plus the #1095 content binding) lives inside
|
|
114124
|
-
// clients/lsp/workspace-diagnostics-cache.ts; the two evidence calls are
|
|
114125
|
-
// the tool's literal entry points into that gated path.
|
|
114126
|
-
"lsp-diagnostics:tool-output": gated("tools/lsp-diagnostics.ts", "`lsp_diagnostics` batch/directory sweep results. Cache hits replay through the shared workspace-diagnostics cache: createWorkspaceDiagnosticsCacheContext is the tool's entry, and its lookup() applies the #671/#672 freshness stack (own-file mtime + reverse-dependency mtimes via isEntryFresh) plus the #1095 content binding. #3088: every route out of this tool \u2014 fresh, cache replay, single file, directory \u2014 also passes applyProbeFindingPolicy, the stored-disposition / .pi-lens.json rule-policy / inline pi-lens-ignore stack the per-edit dispatch path and mode=full apply.", [
|
|
114127
|
-
"createWorkspaceDiagnosticsCacheContext",
|
|
114128
|
-
"isEntryFresh",
|
|
114129
|
-
"cacheCtx.lookup",
|
|
114130
|
-
"applyProbeFindingPolicy"
|
|
114131
|
-
], [
|
|
114132
|
-
"createWorkspaceDiagnosticsCacheContext(resolvedCwd)",
|
|
114133
|
-
"cacheCtx.lookup(file, scopeKey)",
|
|
114134
|
-
"applyProbeFindingPolicy("
|
|
114135
|
-
]),
|
|
114136
|
-
"git-guard:commit-blocked": labeled("clients/git-guard.ts", "Git-guard commit/push \u{1F534} COMMIT BLOCKED verdict (--lens-guard).", "Synchronous preflight rejection returned inline with the failed git command \u2014 no stored state is delivered, so nothing can go stale between detection and delivery.", "live"),
|
|
114137
|
-
"shared-checkout-guard:worktree-mutation-blocked": labeled("clients/shared-checkout-guard.ts", "Shared-checkout \u{1F534} WORKING-TREE CHANGE BLOCKED verdict (--lens-checkout-guard).", "Synchronous preflight rejection returned inline with the failed git command. Both inputs are read at decision time \u2014 the instance registry and `git status` \u2014 so no stored finding is replayed and nothing can go stale between detection and delivery.", "live"),
|
|
114138
|
-
"read-guard-tool-lines:preflight-errors": labeled("clients/read-guard-tool-lines.ts", "Read-guard hashline BLOCKED / RE-READ REQUIRED / PARTIAL APPLY / ALREADY APPLIED preflight errors (#2402).", "Computed fresh per edit attempt and returned as that attempt's rejection \u2014 no cached findings are replayed, so there is no staleness window. The PARTIAL APPLY and ALREADY APPLIED variants describe the same attempt's commit outcome; applied-edit recognition reads RuntimeCoordinator's session-scoped record, which resets with the session.", "live"),
|
|
114139
|
-
"mutating-tool:adapter-preflight-errors": labeled("clients/mutating-tool.ts", "Shape-adapter BLOCKED preflight errors for hashline edit inputs the adapter recognized but could not resolve to a range (#2423).", "Computed fresh from the tool input on each attempt and returned as that attempt's rejection, so there is no staleness window. The adapters read only the call's own arguments; nothing cached is replayed.", "live"),
|
|
114140
|
-
"tool-call:duplicate-export-blocker": labeled("clients/runtime-tool-call.ts", "Duplicate-export STOP rejection returned inline with the failed edit.", "Synchronous preflight rejection computed per edit attempt; no stored state.", "live"),
|
|
114141
|
-
"agent-behavior:thrashing-notice": labeled("clients/agent-behavior-client.ts", "In-result thrashing/blind-write detection notice.", "Ephemeral notice computed at detection time inside the same tool result \u2014 no persistence and no cache, so nothing can be stale.", "live")
|
|
114142
|
-
};
|
|
114143
|
-
|
|
114144
|
-
// dist/clients/runtime-turn.js
|
|
114240
|
+
init_finding_delivery_gate();
|
|
114145
114241
|
init_workspace_sweep_hold();
|
|
114146
114242
|
init_collateral_test_role();
|
|
114147
114243
|
init_gitleaks_client();
|
|
@@ -114566,6 +114662,176 @@ init_lsp();
|
|
|
114566
114662
|
init_pending_aux_coverage();
|
|
114567
114663
|
init_lsp_diagnostics();
|
|
114568
114664
|
init_auxiliary_lsp();
|
|
114665
|
+
|
|
114666
|
+
// dist/clients/persistent-reverify.js
|
|
114667
|
+
import * as fs123 from "node:fs";
|
|
114668
|
+
init_deadline_utils();
|
|
114669
|
+
init_latency_logger();
|
|
114670
|
+
init_diagnostic_binding();
|
|
114671
|
+
init_auxiliary_lsp();
|
|
114672
|
+
var MAX_REVERIFY_FILES = 4;
|
|
114673
|
+
var REVERIFY_BUDGET_MS = 3e3;
|
|
114674
|
+
var TOUCH_SOURCE = "persistent_reverify";
|
|
114675
|
+
function selectPersistentReverifyFiles(report, nowMs = Date.now()) {
|
|
114676
|
+
const candidates = [];
|
|
114677
|
+
let skippedChanged = 0;
|
|
114678
|
+
for (const entry of report.files) {
|
|
114679
|
+
if (entry.origin !== "deferred")
|
|
114680
|
+
continue;
|
|
114681
|
+
if (entry.warnings.some((w) => findAuxiliaryProfileForSource(w.source ?? "") !== void 0)) {
|
|
114682
|
+
continue;
|
|
114683
|
+
}
|
|
114684
|
+
const stamp2 = entry.generatedAt ? Date.parse(entry.generatedAt) : NaN;
|
|
114685
|
+
if (!Number.isFinite(stamp2) || stamp2 > nowMs)
|
|
114686
|
+
continue;
|
|
114687
|
+
let mtimeMs;
|
|
114688
|
+
try {
|
|
114689
|
+
mtimeMs = fs123.statSync(entry.filePath).mtimeMs;
|
|
114690
|
+
} catch {
|
|
114691
|
+
continue;
|
|
114692
|
+
}
|
|
114693
|
+
if (mtimeMs > stamp2) {
|
|
114694
|
+
skippedChanged += 1;
|
|
114695
|
+
continue;
|
|
114696
|
+
}
|
|
114697
|
+
if (candidates.length < MAX_REVERIFY_FILES)
|
|
114698
|
+
candidates.push(entry);
|
|
114699
|
+
}
|
|
114700
|
+
return { candidates, skippedChanged };
|
|
114701
|
+
}
|
|
114702
|
+
async function runPersistentReverify(args) {
|
|
114703
|
+
const started = Date.now();
|
|
114704
|
+
const deadlineAt = started + (args.budgetMs ?? REVERIFY_BUDGET_MS);
|
|
114705
|
+
const nowMs = args.nowMs ?? started;
|
|
114706
|
+
const { candidates, skippedChanged } = selectPersistentReverifyFiles(args.report, nowMs);
|
|
114707
|
+
const outcomes = [];
|
|
114708
|
+
const replacementFiles = [];
|
|
114709
|
+
let touched = 0;
|
|
114710
|
+
const buildArgs = {
|
|
114711
|
+
cwd: args.cwd,
|
|
114712
|
+
sessionId: args.report.sessionId,
|
|
114713
|
+
turnIndex: 0,
|
|
114714
|
+
files: [],
|
|
114715
|
+
modifiedRangesByFile: /* @__PURE__ */ new Map(),
|
|
114716
|
+
dispatchWarnings: [],
|
|
114717
|
+
includeLspCodeActions: true,
|
|
114718
|
+
deltaOnly: false,
|
|
114719
|
+
...args.signal !== void 0 ? { signal: args.signal } : {},
|
|
114720
|
+
lspBudgetMs: REVERIFY_BUDGET_MS,
|
|
114721
|
+
dbg: () => {
|
|
114722
|
+
}
|
|
114723
|
+
};
|
|
114724
|
+
let processed = 0;
|
|
114725
|
+
for (const entry of candidates) {
|
|
114726
|
+
if (args.signal?.aborted || Date.now() >= deadlineAt)
|
|
114727
|
+
break;
|
|
114728
|
+
processed += 1;
|
|
114729
|
+
let content;
|
|
114730
|
+
try {
|
|
114731
|
+
content = fs123.readFileSync(entry.filePath, "utf-8");
|
|
114732
|
+
} catch {
|
|
114733
|
+
outcomes.push({
|
|
114734
|
+
filePath: entry.filePath,
|
|
114735
|
+
displayPath: entry.displayPath,
|
|
114736
|
+
outcome: "unconfirmed",
|
|
114737
|
+
dropped: 0,
|
|
114738
|
+
kept: entry.warnings.length
|
|
114739
|
+
});
|
|
114740
|
+
replacementFiles.push({ ...entry, reVerifyIncomplete: true });
|
|
114741
|
+
continue;
|
|
114742
|
+
}
|
|
114743
|
+
let touchedResult;
|
|
114744
|
+
try {
|
|
114745
|
+
touchedResult = await bounded(args.lspService.touchFile(entry.filePath, content, {
|
|
114746
|
+
diagnostics: "document",
|
|
114747
|
+
collectDiagnostics: true,
|
|
114748
|
+
source: TOUCH_SOURCE,
|
|
114749
|
+
clientScope: "primary"
|
|
114750
|
+
}), {
|
|
114751
|
+
ms: Math.max(250, deadlineAt - Date.now()),
|
|
114752
|
+
signal: args.signal,
|
|
114753
|
+
hook: "turn_end",
|
|
114754
|
+
label: "persistent_reverify_touch"
|
|
114755
|
+
});
|
|
114756
|
+
} catch {
|
|
114757
|
+
touchedResult = void 0;
|
|
114758
|
+
}
|
|
114759
|
+
if (touchedResult === void 0 || touchedResult.inconclusive === true || touchedResult.skipReason !== void 0 || (touchedResult.diagnosticsUnsupportedServerIds ?? []).length > 0 || !touchCompletedConfirmationPolicy(touchedResult)) {
|
|
114760
|
+
outcomes.push({
|
|
114761
|
+
filePath: entry.filePath,
|
|
114762
|
+
displayPath: entry.displayPath,
|
|
114763
|
+
outcome: "unconfirmed",
|
|
114764
|
+
dropped: 0,
|
|
114765
|
+
kept: entry.warnings.length
|
|
114766
|
+
});
|
|
114767
|
+
replacementFiles.push({ ...entry, reVerifyIncomplete: true });
|
|
114768
|
+
continue;
|
|
114769
|
+
}
|
|
114770
|
+
touched += 1;
|
|
114771
|
+
const freshRecords = await bounded(enrichFileFromLsp(args.cwd, buildArgs, { filePath: entry.filePath, cached: touchedResult.diags }, {
|
|
114772
|
+
lspService: args.lspService,
|
|
114773
|
+
pullTimeoutMs: 2e3,
|
|
114774
|
+
deadlineAt,
|
|
114775
|
+
...args.signal !== void 0 ? { signal: args.signal } : {},
|
|
114776
|
+
site: { hook: "turn_end", label: "persistent_reverify" }
|
|
114777
|
+
}), {
|
|
114778
|
+
ms: Math.max(250, deadlineAt - Date.now()),
|
|
114779
|
+
signal: args.signal,
|
|
114780
|
+
hook: "turn_end",
|
|
114781
|
+
label: "persistent_reverify_enrich"
|
|
114782
|
+
}) ?? [];
|
|
114783
|
+
let dropped = 0;
|
|
114784
|
+
let kept = 0;
|
|
114785
|
+
for (const warning of entry.warnings) {
|
|
114786
|
+
const stillThere = freshRecords.some((record6) => record6.rule === warning.rule && record6.message === warning.message);
|
|
114787
|
+
if (stillThere)
|
|
114788
|
+
kept += 1;
|
|
114789
|
+
else
|
|
114790
|
+
dropped += 1;
|
|
114791
|
+
}
|
|
114792
|
+
const outcome = freshRecords.length === 0 ? "clean" : dropped === 0 ? "reconfirmed" : "mixed";
|
|
114793
|
+
outcomes.push({
|
|
114794
|
+
filePath: entry.filePath,
|
|
114795
|
+
displayPath: entry.displayPath,
|
|
114796
|
+
outcome,
|
|
114797
|
+
dropped,
|
|
114798
|
+
kept
|
|
114799
|
+
});
|
|
114800
|
+
replacementFiles.push({
|
|
114801
|
+
...entry,
|
|
114802
|
+
warnings: freshRecords,
|
|
114803
|
+
reVerified: true,
|
|
114804
|
+
generatedAt: new Date(nowMs).toISOString()
|
|
114805
|
+
});
|
|
114806
|
+
}
|
|
114807
|
+
logLatency({
|
|
114808
|
+
type: "phase",
|
|
114809
|
+
toolName: "turn_end",
|
|
114810
|
+
filePath: args.cwd,
|
|
114811
|
+
phase: "persistent_reverify",
|
|
114812
|
+
durationMs: Date.now() - started,
|
|
114813
|
+
metadata: {
|
|
114814
|
+
candidates: candidates.length,
|
|
114815
|
+
touched,
|
|
114816
|
+
clean: outcomes.filter((o) => o.outcome === "clean").length,
|
|
114817
|
+
reconfirmed: outcomes.filter((o) => o.outcome === "reconfirmed").length,
|
|
114818
|
+
mixed: outcomes.filter((o) => o.outcome === "mixed").length,
|
|
114819
|
+
unconfirmed: outcomes.filter((o) => o.outcome === "unconfirmed").length,
|
|
114820
|
+
skippedChanged,
|
|
114821
|
+
skippedBudget: candidates.length - processed
|
|
114822
|
+
}
|
|
114823
|
+
});
|
|
114824
|
+
return {
|
|
114825
|
+
outcomes,
|
|
114826
|
+
replacementFiles,
|
|
114827
|
+
candidates: candidates.length,
|
|
114828
|
+
touched,
|
|
114829
|
+
skippedChanged
|
|
114830
|
+
};
|
|
114831
|
+
}
|
|
114832
|
+
|
|
114833
|
+
// dist/clients/runtime-turn.js
|
|
114834
|
+
init_cascade_format();
|
|
114569
114835
|
init_finding_policy();
|
|
114570
114836
|
init_file_role();
|
|
114571
114837
|
init_pending_runner_findings();
|
|
@@ -115069,6 +115335,17 @@ ${summary}`);
|
|
|
115069
115335
|
return true;
|
|
115070
115336
|
});
|
|
115071
115337
|
const cascadeResults = cascadeRuns.flatMap((r) => r.result ? [r.result] : []);
|
|
115338
|
+
let carriedRunsRendered = 0;
|
|
115339
|
+
let labeledAdvisories = 0;
|
|
115340
|
+
const carriedMetaByResult = /* @__PURE__ */ new Map();
|
|
115341
|
+
for (const r of cascadeRuns) {
|
|
115342
|
+
if (r.result && (r.carriedTurns ?? 0) > 0 && r.carriedTurns !== void 0) {
|
|
115343
|
+
carriedMetaByResult.set(r.result, {
|
|
115344
|
+
carriedTurns: r.carriedTurns,
|
|
115345
|
+
observedAt: r.observedAt
|
|
115346
|
+
});
|
|
115347
|
+
}
|
|
115348
|
+
}
|
|
115072
115349
|
const cascadeLogFilePath = cascadeResults[0]?.filePath ?? files2[0] ?? cwd;
|
|
115073
115350
|
if (cascadeResults.length > 0) {
|
|
115074
115351
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -115092,7 +115369,12 @@ ${summary}`);
|
|
|
115092
115369
|
const pk = normalizeMapKey(result.filePath);
|
|
115093
115370
|
const ownsAny = result.neighbors.some((n) => neighborOwner.get(normalizeMapKey(n.filePath)) === pk);
|
|
115094
115371
|
if (ownsAny && result.formatted) {
|
|
115095
|
-
|
|
115372
|
+
const carryMeta = carriedMetaByResult.get(result);
|
|
115373
|
+
const carrySuffix = cascadeCarrySuffix(carryMeta?.carriedTurns, carryMeta?.observedAt);
|
|
115374
|
+
parts.push(carrySuffix ? `${result.formatted}
|
|
115375
|
+
${carrySuffix}` : result.formatted);
|
|
115376
|
+
if (carrySuffix)
|
|
115377
|
+
carriedRunsRendered += 1;
|
|
115096
115378
|
injectedNeighborCount += result.neighbors.length;
|
|
115097
115379
|
injectedDiagnosticCount += result.neighbors.reduce((s, n) => s + n.diagnostics.length, 0);
|
|
115098
115380
|
} else if (!ownsAny && result.formatted) {
|
|
@@ -115181,19 +115463,35 @@ ${lines.join("\n")}`;
|
|
|
115181
115463
|
const graphRuns = indeterminateRuns.filter((r) => r.indeterminate?.reason !== "lsp_binding_rejected" && r.indeterminate?.reason !== "excluded_by_role" && r.indeterminate?.reason !== "budget_truncated" && r.indeterminate?.budget === void 0);
|
|
115182
115464
|
const bindingRuns = indeterminateRuns.filter((r) => r.indeterminate?.reason === "lsp_binding_rejected" && r.indeterminate?.budget === void 0);
|
|
115183
115465
|
const budgetRuns = indeterminateRuns.filter((r) => r.indeterminate?.reason === "budget_truncated" || r.indeterminate?.budget !== void 0);
|
|
115184
|
-
const
|
|
115466
|
+
const withCarryLabel = (advisory, runs) => {
|
|
115467
|
+
if (advisory === void 0)
|
|
115468
|
+
return void 0;
|
|
115469
|
+
const carried = runs.filter((r) => (r.carriedTurns ?? 0) > 0);
|
|
115470
|
+
if (carried.length === 0 || carried.length !== runs.length) {
|
|
115471
|
+
return advisory;
|
|
115472
|
+
}
|
|
115473
|
+
const stamps = carried.map((r) => r.observedAt);
|
|
115474
|
+
const observedAt = stamps.every((s) => s !== void 0) ? Math.min(...stamps) : void 0;
|
|
115475
|
+
const suffix = cascadeCarrySuffix(carried[0]?.carriedTurns, observedAt);
|
|
115476
|
+
if (!suffix)
|
|
115477
|
+
return advisory;
|
|
115478
|
+
labeledAdvisories += 1;
|
|
115479
|
+
return `${advisory}
|
|
115480
|
+
${suffix}`;
|
|
115481
|
+
};
|
|
115482
|
+
const graphAdvisory = withCarryLabel(buildAdvisory(graphRuns, {
|
|
115185
115483
|
lead: (fileCount2, reasons) => `Cascade could not compute downstream impact for ${fileCount2} edited file(s) this turn \u2014 the review graph was unavailable (${reasons}), so their dependents were not cascade-checked and a clean cascade result does not cover them.`,
|
|
115186
115484
|
fallbackDetail: (r) => r.indeterminate?.reason === "missing_node" ? "changed file not in the review graph" : "review graph unavailable"
|
|
115187
|
-
});
|
|
115485
|
+
}), graphRuns);
|
|
115188
115486
|
if (graphAdvisory)
|
|
115189
115487
|
advisoryParts.push(graphAdvisory);
|
|
115190
|
-
const bindingAdvisory = buildAdvisory(bindingRuns, {
|
|
115488
|
+
const bindingAdvisory = withCarryLabel(buildAdvisory(bindingRuns, {
|
|
115191
115489
|
lead: (fileCount2, reasons) => `Cascade identified dependents for ${fileCount2} edited file(s) this turn, but their diagnostics could not be freshly confirmed (${reasons}) and were withheld \u2014 a clean cascade result does not cover them.`,
|
|
115192
115490
|
fallbackDetail: () => "cascade diagnostics withheld (binding rejected)"
|
|
115193
|
-
});
|
|
115491
|
+
}), bindingRuns);
|
|
115194
115492
|
if (bindingAdvisory)
|
|
115195
115493
|
advisoryParts.push(bindingAdvisory);
|
|
115196
|
-
const budgetAdvisory = buildAdvisory(budgetRuns, {
|
|
115494
|
+
const budgetAdvisory = withCarryLabel(buildAdvisory(budgetRuns, {
|
|
115197
115495
|
lead: (fileCount2, reasons) => `Cascade checked the selected neighbors for ${fileCount2} edited file(s) this turn, but some eligible dependents were not checked because the cascade budget was exhausted (${reasons}); a clean cascade result does not cover them.`,
|
|
115198
115496
|
fallbackDetail: (r) => {
|
|
115199
115497
|
const budget = r.indeterminate?.budget;
|
|
@@ -115202,7 +115500,7 @@ ${lines.join("\n")}`;
|
|
|
115202
115500
|
const detail = `cascade budget checked ${budget.selectedCount} of ${budget.eligibleCount} eligible dependents (${budget.truncatedCount} omitted)`;
|
|
115203
115501
|
return budget.transitiveTruncated ? `${detail}; transitive expansion was capped before all eligible dependents were enumerated` : detail;
|
|
115204
115502
|
}
|
|
115205
|
-
});
|
|
115503
|
+
}), budgetRuns);
|
|
115206
115504
|
if (budgetAdvisory)
|
|
115207
115505
|
advisoryParts.push(budgetAdvisory);
|
|
115208
115506
|
const fileCount = new Set(indeterminateRuns.map((r) => normalizeMapKey(r.filePath))).size;
|
|
@@ -115228,6 +115526,13 @@ ${lines.join("\n")}`;
|
|
|
115228
115526
|
}
|
|
115229
115527
|
});
|
|
115230
115528
|
}
|
|
115529
|
+
if (carriedRunsRendered > 0 || labeledAdvisories > 0) {
|
|
115530
|
+
logCascade({
|
|
115531
|
+
phase: "cascade_carry_rendered",
|
|
115532
|
+
filePath: cascadeLogFilePath,
|
|
115533
|
+
metadata: { carriedRunsRendered, labeledAdvisories }
|
|
115534
|
+
});
|
|
115535
|
+
}
|
|
115231
115536
|
const cascadeSkipped = {
|
|
115232
115537
|
blockers: 0,
|
|
115233
115538
|
non_code: 0,
|
|
@@ -115761,7 +116066,7 @@ The cached line numbers are no longer trustworthy, so they are withheld. Re-run
|
|
|
115761
116066
|
continue;
|
|
115762
116067
|
}
|
|
115763
116068
|
const config = RUNNERS[carried.runner];
|
|
115764
|
-
if (!config || isExcludedTestTarget(testFile, cwd) || !
|
|
116069
|
+
if (!config || isExcludedTestTarget(testFile, cwd) || !fs124.existsSync(testFile)) {
|
|
115765
116070
|
resolvedDeferralKeys.add(carriedKey);
|
|
115766
116071
|
deadDeferred++;
|
|
115767
116072
|
continue;
|
|
@@ -115836,7 +116141,7 @@ The cached line numbers are no longer trustworthy, so they are withheld. Re-run
|
|
|
115836
116141
|
dbg2(`turn_end: ${display} \u2192 test target excluded (integration/e2e), skipping spawn (${path187.relative(cwd, target.testFile)})`);
|
|
115837
116142
|
continue;
|
|
115838
116143
|
}
|
|
115839
|
-
if (!
|
|
116144
|
+
if (!fs124.existsSync(target.testFile)) {
|
|
115840
116145
|
missingTargetFiles++;
|
|
115841
116146
|
dbg2(`turn_end: ${display} \u2192 test file missing, skipping spawn (${path187.relative(cwd, target.testFile)})`);
|
|
115842
116147
|
continue;
|
|
@@ -116238,7 +116543,25 @@ ${impactLines.join("\n")}`);
|
|
|
116238
116543
|
fileSeqByPath.set(filePath, getFileSeq.call(runtime2, filePath));
|
|
116239
116544
|
}
|
|
116240
116545
|
}
|
|
116546
|
+
let reverify;
|
|
116241
116547
|
if (getFlag("lens-actionable-warnings")) {
|
|
116548
|
+
const persistedReport = cacheManager2.readCache("actionable-warnings", cwd, Number.MAX_SAFE_INTEGER)?.data;
|
|
116549
|
+
if (persistedReport?.files?.some((entry) => entry.origin === "deferred")) {
|
|
116550
|
+
const reverifyLspService = getLSPService();
|
|
116551
|
+
if (reverifyLspService) {
|
|
116552
|
+
reverify = await bounded(runPersistentReverify({
|
|
116553
|
+
report: persistedReport,
|
|
116554
|
+
cwd,
|
|
116555
|
+
lspService: reverifyLspService,
|
|
116556
|
+
signal: getAmbientAbortSignal()
|
|
116557
|
+
}), {
|
|
116558
|
+
ms: HOOK_WALL_BUDGET_MS.turn_end,
|
|
116559
|
+
signal: getAmbientAbortSignal(),
|
|
116560
|
+
hook: "turn_end",
|
|
116561
|
+
label: "persistent_reverify"
|
|
116562
|
+
});
|
|
116563
|
+
}
|
|
116564
|
+
}
|
|
116242
116565
|
try {
|
|
116243
116566
|
const report = await buildActionableWarningsReport({
|
|
116244
116567
|
cwd,
|
|
@@ -116281,6 +116604,19 @@ ${impactLines.join("\n")}`);
|
|
|
116281
116604
|
}
|
|
116282
116605
|
}
|
|
116283
116606
|
});
|
|
116607
|
+
if (reverify?.replacementFiles.length) {
|
|
116608
|
+
const replacementByPath = new Map(reverify.replacementFiles.map((file) => [
|
|
116609
|
+
normalizeMapKey(file.filePath),
|
|
116610
|
+
file
|
|
116611
|
+
]));
|
|
116612
|
+
const files3 = (report.files ?? []).map((file) => replacementByPath.get(normalizeMapKey(file.filePath)) ?? file);
|
|
116613
|
+
for (const replacement of reverify.replacementFiles) {
|
|
116614
|
+
if (!files3.some((file) => normalizeMapKey(file.filePath) === normalizeMapKey(replacement.filePath))) {
|
|
116615
|
+
files3.push(replacement);
|
|
116616
|
+
}
|
|
116617
|
+
}
|
|
116618
|
+
report.files = files3;
|
|
116619
|
+
}
|
|
116284
116620
|
const publishResult = publishActionableWarningsReport(cacheManager2, cwd, report, {
|
|
116285
116621
|
origin: "in-band",
|
|
116286
116622
|
getFileSeq: getFileSeq ? (filePath) => getFileSeq.call(runtime2, filePath) : void 0,
|
|
@@ -116484,7 +116820,7 @@ ${lines.join("\n")}`);
|
|
|
116484
116820
|
if (!lateAuxContentRead) {
|
|
116485
116821
|
lateAuxContentRead = true;
|
|
116486
116822
|
try {
|
|
116487
|
-
lateAuxContentValue =
|
|
116823
|
+
lateAuxContentValue = fs124.readFileSync(lateAuxPath, "utf-8");
|
|
116488
116824
|
} catch {
|
|
116489
116825
|
lateAuxContentValue = void 0;
|
|
116490
116826
|
}
|
|
@@ -116965,13 +117301,14 @@ function createActivateToolsTool(pi, lazyTools, options = {}) {
|
|
|
116965
117301
|
|
|
116966
117302
|
// dist/tools/lens-diagnostics.js
|
|
116967
117303
|
init_bounded_cache();
|
|
116968
|
-
import { promises as
|
|
117304
|
+
import { promises as fs130 } from "node:fs";
|
|
116969
117305
|
import * as fsSync from "node:fs";
|
|
116970
117306
|
import * as path200 from "node:path";
|
|
116971
117307
|
init_diagnostic_dispositions();
|
|
116972
117308
|
init_blocker_freshness();
|
|
116973
117309
|
init_freshness();
|
|
116974
117310
|
init_finding_policy();
|
|
117311
|
+
init_finding_delivery_gate();
|
|
116975
117312
|
init_rule_id_normalize();
|
|
116976
117313
|
init_rule_policy();
|
|
116977
117314
|
init_deadline_utils();
|
|
@@ -117048,7 +117385,7 @@ init_gitleaks_client();
|
|
|
117048
117385
|
init_govulncheck_client();
|
|
117049
117386
|
init_project_trust();
|
|
117050
117387
|
init_trivy_client();
|
|
117051
|
-
import * as
|
|
117388
|
+
import * as fs126 from "node:fs";
|
|
117052
117389
|
import * as os35 from "node:os";
|
|
117053
117390
|
import * as path192 from "node:path";
|
|
117054
117391
|
|
|
@@ -117154,7 +117491,7 @@ function opengrepResultToProjectDiagnostics(cwd, result) {
|
|
|
117154
117491
|
|
|
117155
117492
|
// dist/clients/project-diagnostics/runner-adapters/runner-findings.js
|
|
117156
117493
|
init_test_runner_client();
|
|
117157
|
-
import * as
|
|
117494
|
+
import * as fs125 from "node:fs";
|
|
117158
117495
|
import * as path191 from "node:path";
|
|
117159
117496
|
function failureMessage(failure) {
|
|
117160
117497
|
const firstLine2 = failure.message.split("\n")[0]?.slice(0, 300) ?? "";
|
|
@@ -117221,7 +117558,7 @@ function testRunnerFindingsToProjectDiagnostics(cache2, cwd, runtime2) {
|
|
|
117221
117558
|
return [];
|
|
117222
117559
|
const validation = cwd ? validateAdvisoryProvenance(cache2, cwd, runtime2) : { status: "unknown", reasons: ["validation-context-missing"] };
|
|
117223
117560
|
const root = cwd ?? process.cwd();
|
|
117224
|
-
const missingKeys = new Set((cache2.provenance?.files ?? []).filter((file) => !
|
|
117561
|
+
const missingKeys = new Set((cache2.provenance?.files ?? []).filter((file) => !fs125.existsSync(path191.resolve(root, file.path))).map((file) => advisoryPathKey(file.path, root)));
|
|
117225
117562
|
const historical = cache2.superseded === true || cache2.stale === true || validation.status !== "current";
|
|
117226
117563
|
return cache2.results.filter((result) => !missingKeys.has(advisoryPathKey(result.file, root))).flatMap((result) => testResultToProjectDiagnostics(result, historical)).map((diagnostic) => historical ? {
|
|
117227
117564
|
...diagnostic,
|
|
@@ -117253,10 +117590,10 @@ async function fetchFreshProjectDiagnostics(cacheManager2, cwd, clients, signal,
|
|
|
117253
117590
|
let analysisRootValidation;
|
|
117254
117591
|
if (options.analysisRoot !== void 0) {
|
|
117255
117592
|
try {
|
|
117256
|
-
if (!
|
|
117593
|
+
if (!fs126.statSync(requestedRoot).isDirectory()) {
|
|
117257
117594
|
throw new Error("is not a directory");
|
|
117258
117595
|
}
|
|
117259
|
-
analysisRoot =
|
|
117596
|
+
analysisRoot = fs126.realpathSync(requestedRoot);
|
|
117260
117597
|
} catch (error) {
|
|
117261
117598
|
const detail = error instanceof Error ? error.message : String(error);
|
|
117262
117599
|
const reason = `the explicit analysis root ${requestedRoot} is unavailable or ${detail}`;
|
|
@@ -117407,7 +117744,7 @@ async function fetchFreshProjectDiagnostics(cacheManager2, cwd, clients, signal,
|
|
|
117407
117744
|
markCold("jscpd", reasonFromAvailabilityVerdict("jscpd", clients.jscpdClient.getAvailabilityVerdict?.()));
|
|
117408
117745
|
return;
|
|
117409
117746
|
}
|
|
117410
|
-
const isTsProject =
|
|
117747
|
+
const isTsProject = fs126.existsSync(path192.join(analysisRoot, "tsconfig.json"));
|
|
117411
117748
|
const scannerKey = isTsProject ? "jscpd-ts" : "jscpd";
|
|
117412
117749
|
const startMs = Date.now();
|
|
117413
117750
|
const result = await clients.jscpdClient.scan(analysisRoot, void 0, void 0, isTsProject);
|
|
@@ -117820,7 +118157,7 @@ init_source_filter();
|
|
|
117820
118157
|
init_tree_sitter_logger();
|
|
117821
118158
|
init_tree_sitter_query_loader();
|
|
117822
118159
|
init_tree_sitter_shared();
|
|
117823
|
-
import * as
|
|
118160
|
+
import * as fs127 from "node:fs";
|
|
117824
118161
|
import * as path194 from "node:path";
|
|
117825
118162
|
init_diagnostic_binding();
|
|
117826
118163
|
init_integration();
|
|
@@ -117961,7 +118298,7 @@ async function scanFileMajorRules(cwd, files2, signal) {
|
|
|
117961
118298
|
let astGrepLang;
|
|
117962
118299
|
if (sgModule && canHandle(filePath)) {
|
|
117963
118300
|
try {
|
|
117964
|
-
if (
|
|
118301
|
+
if (fs127.statSync(filePath).size <= AST_GREP_MAX_FILE_BYTES) {
|
|
117965
118302
|
astGrepLang = getLang(filePath, sgModule);
|
|
117966
118303
|
}
|
|
117967
118304
|
} catch {
|
|
@@ -117974,7 +118311,7 @@ async function scanFileMajorRules(cwd, files2, signal) {
|
|
|
117974
118311
|
let content;
|
|
117975
118312
|
let contentBytes;
|
|
117976
118313
|
try {
|
|
117977
|
-
const buf =
|
|
118314
|
+
const buf = fs127.readFileSync(filePath);
|
|
117978
118315
|
contentBytes = buf.length;
|
|
117979
118316
|
content = buf.toString("utf-8");
|
|
117980
118317
|
} catch {
|
|
@@ -118237,7 +118574,7 @@ var turnEndQueue = new TurnEndQueue();
|
|
|
118237
118574
|
// dist/clients/module-report.js
|
|
118238
118575
|
init_file_kinds();
|
|
118239
118576
|
init_latency_logger();
|
|
118240
|
-
import * as
|
|
118577
|
+
import * as fs128 from "node:fs";
|
|
118241
118578
|
import * as path195 from "node:path";
|
|
118242
118579
|
|
|
118243
118580
|
// dist/clients/middle-man-analysis.js
|
|
@@ -119383,7 +119720,7 @@ async function moduleReport(file, cwd, options) {
|
|
|
119383
119720
|
const normalizedPath = normalizeMapKey(absPath);
|
|
119384
119721
|
let content;
|
|
119385
119722
|
try {
|
|
119386
|
-
content =
|
|
119723
|
+
content = fs128.readFileSync(absPath, "utf-8");
|
|
119387
119724
|
} catch {
|
|
119388
119725
|
return unavailableReport(toDisplayPath(absPath, cwd));
|
|
119389
119726
|
}
|
|
@@ -119708,7 +120045,7 @@ async function readSymbol(file, symbolName, cwd, options = {}) {
|
|
|
119708
120045
|
};
|
|
119709
120046
|
let content;
|
|
119710
120047
|
try {
|
|
119711
|
-
content =
|
|
120048
|
+
content = fs128.readFileSync(absPath, "utf-8");
|
|
119712
120049
|
} catch {
|
|
119713
120050
|
log2(false);
|
|
119714
120051
|
return { found: false, path: absPath, name: symbolName };
|
|
@@ -119884,7 +120221,7 @@ async function readEnclosing(file, line, cwd, options) {
|
|
|
119884
120221
|
};
|
|
119885
120222
|
let content;
|
|
119886
120223
|
try {
|
|
119887
|
-
content =
|
|
120224
|
+
content = fs128.readFileSync(absPath, "utf-8");
|
|
119888
120225
|
} catch {
|
|
119889
120226
|
log2(false);
|
|
119890
120227
|
return { found: false, path: absPath, line: targetLine };
|
|
@@ -120926,8 +121263,9 @@ init_wait_policy();
|
|
|
120926
121263
|
init_tsserver_sync();
|
|
120927
121264
|
init_lsp_diagnostics();
|
|
120928
121265
|
init_inferred_project();
|
|
121266
|
+
init_path_utils();
|
|
120929
121267
|
init_widget_state();
|
|
120930
|
-
import * as
|
|
121268
|
+
import * as fs129 from "node:fs";
|
|
120931
121269
|
import * as path199 from "node:path";
|
|
120932
121270
|
init_warm_attach();
|
|
120933
121271
|
init_language_registry();
|
|
@@ -120981,7 +121319,7 @@ async function collectFiles(dir, extensions, maxFiles, isIgnored = () => false)
|
|
|
120981
121319
|
return;
|
|
120982
121320
|
let entries;
|
|
120983
121321
|
try {
|
|
120984
|
-
entries = await
|
|
121322
|
+
entries = await fs129.promises.readdir(current, { withFileTypes: true });
|
|
120985
121323
|
} catch {
|
|
120986
121324
|
return;
|
|
120987
121325
|
}
|
|
@@ -121051,7 +121389,7 @@ function createLspDiagnosticsTool(nextWriteIndex, onConfirmedNoBlockers, getServ
|
|
|
121051
121389
|
details: { mode: "batch", filesChecked: 0 }
|
|
121052
121390
|
};
|
|
121053
121391
|
}
|
|
121054
|
-
const absPaths = rawPaths.map((entry) =>
|
|
121392
|
+
const absPaths = rawPaths.map((entry) => normalizeMapKey(path199.resolve(cwd, entry)));
|
|
121055
121393
|
return runBatchFileDiagnostics(absPaths, severity, lspService, {
|
|
121056
121394
|
concurrency,
|
|
121057
121395
|
waitMs,
|
|
@@ -121076,10 +121414,10 @@ function createLspDiagnosticsTool(nextWriteIndex, onConfirmedNoBlockers, getServ
|
|
|
121076
121414
|
details: {}
|
|
121077
121415
|
};
|
|
121078
121416
|
}
|
|
121079
|
-
const absPath =
|
|
121417
|
+
const absPath = normalizeMapKey(path199.resolve(cwd, rawPath));
|
|
121080
121418
|
let stat4;
|
|
121081
121419
|
try {
|
|
121082
|
-
stat4 =
|
|
121420
|
+
stat4 = fs129.statSync(absPath);
|
|
121083
121421
|
} catch {
|
|
121084
121422
|
return {
|
|
121085
121423
|
content: [
|
|
@@ -121110,7 +121448,7 @@ async function collectDiagnosticsForFile(absPath, lspService, scanRoot, waitMs,
|
|
|
121110
121448
|
let content;
|
|
121111
121449
|
let touched;
|
|
121112
121450
|
try {
|
|
121113
|
-
content =
|
|
121451
|
+
content = fs129.readFileSync(absPath, "utf-8");
|
|
121114
121452
|
if (isWarmAttached()) {
|
|
121115
121453
|
const attachedBudgetMs = waitMs ?? 15e3;
|
|
121116
121454
|
const attached = await tryWarmAttachedDiagnostics(absPath, content, attachedBudgetMs, "sweep");
|
|
@@ -121265,7 +121603,8 @@ function applyProbeFindingPolicy(file, diagnostics, cwd, content, severity) {
|
|
|
121265
121603
|
durationMs: Date.now() - started,
|
|
121266
121604
|
metadata: {
|
|
121267
121605
|
suppressed,
|
|
121268
|
-
total: inScopeBefore
|
|
121606
|
+
total: inScopeBefore,
|
|
121607
|
+
retainedSuppressed: countRetainedSuppressedRows(file)
|
|
121269
121608
|
}
|
|
121270
121609
|
});
|
|
121271
121610
|
}
|
|
@@ -121283,7 +121622,7 @@ function replayContentForStrictMarks(file, cwd) {
|
|
|
121283
121622
|
if (!hasStrictDispositionMarks(cwd))
|
|
121284
121623
|
return void 0;
|
|
121285
121624
|
try {
|
|
121286
|
-
return
|
|
121625
|
+
return fs129.readFileSync(file, "utf-8");
|
|
121287
121626
|
} catch {
|
|
121288
121627
|
return void 0;
|
|
121289
121628
|
}
|
|
@@ -121309,7 +121648,7 @@ async function collectFileDiagnosticResult(file, severity, lspService, waitMs, n
|
|
|
121309
121648
|
const writeIndex = nextWriteIndex?.();
|
|
121310
121649
|
let stat4;
|
|
121311
121650
|
try {
|
|
121312
|
-
stat4 =
|
|
121651
|
+
stat4 = fs129.statSync(file);
|
|
121313
121652
|
if (!stat4.isFile()) {
|
|
121314
121653
|
return { file, diagnostics: [], error: `${file}: not a file` };
|
|
121315
121654
|
}
|
|
@@ -121957,7 +122296,7 @@ async function findFullScanBindingMismatches(results) {
|
|
|
121957
122296
|
result.boundToCurrentDisk !== true && result.contentHash !== void 0
|
|
121958
122297
|
) {
|
|
121959
122298
|
try {
|
|
121960
|
-
const content = await
|
|
122299
|
+
const content = await fs130.readFile(result.filePath, "utf-8");
|
|
121961
122300
|
if (hashDiagnosticContent(content) !== result.contentHash) {
|
|
121962
122301
|
mismatched.add(result);
|
|
121963
122302
|
}
|
|
@@ -122232,7 +122571,7 @@ function formatProjectDeltaDiagnostic(diagnostic, stale) {
|
|
|
122232
122571
|
const where = stale ? STALE_LINE_MARKER : `L${diagnostic.line ?? "?"}`;
|
|
122233
122572
|
return ` ${marker} ${where} ${rule} ${diagnostic.message}`;
|
|
122234
122573
|
}
|
|
122235
|
-
function appendProjectDiagnosticsDeltaLines(
|
|
122574
|
+
function appendProjectDiagnosticsDeltaLines(groups2, cwd, report, severity, includeFile) {
|
|
122236
122575
|
const scoped = (report?.diagnostics ?? []).filter((diagnostic) => includeFile(diagnostic.filePath) && matchesSeverity(projectDiagnosticToWidget(diagnostic, diagnostic.filePath), severity));
|
|
122237
122576
|
const gated2 = gateFindingsByPathFreshness({
|
|
122238
122577
|
store: "lens-diagnostics-delta-project",
|
|
@@ -122252,11 +122591,9 @@ function appendProjectDiagnosticsDeltaLines(lines, cwd, report, severity, includ
|
|
|
122252
122591
|
byFile.set(filePath, bucket);
|
|
122253
122592
|
}
|
|
122254
122593
|
for (const [filePath, fileDiagnostics] of byFile) {
|
|
122255
|
-
const
|
|
122256
|
-
if (!lines.includes(rel))
|
|
122257
|
-
lines.push(rel);
|
|
122594
|
+
const group = getDeltaFileGroup(groups2, cwd, filePath);
|
|
122258
122595
|
for (const diagnostic of fileDiagnostics) {
|
|
122259
|
-
|
|
122596
|
+
group.projectLines.push(formatProjectDeltaDiagnostic(diagnostic, staleSet.has(diagnostic)));
|
|
122260
122597
|
}
|
|
122261
122598
|
}
|
|
122262
122599
|
return diagnostics.length;
|
|
@@ -122355,7 +122692,12 @@ function applyDeltaFreshnessGate(files2, cwd, generatedAt) {
|
|
|
122355
122692
|
}
|
|
122356
122693
|
for (const f of gated2.stale) {
|
|
122357
122694
|
const arr = byFile.get(f.filePath) ?? [];
|
|
122358
|
-
arr.push({
|
|
122695
|
+
arr.push({
|
|
122696
|
+
...f.warning,
|
|
122697
|
+
stale: true,
|
|
122698
|
+
line: void 0,
|
|
122699
|
+
staleAsOf: effectiveAt
|
|
122700
|
+
});
|
|
122359
122701
|
byFile.set(f.filePath, arr);
|
|
122360
122702
|
}
|
|
122361
122703
|
return files2.map((file) => ({
|
|
@@ -122363,9 +122705,25 @@ function applyDeltaFreshnessGate(files2, cwd, generatedAt) {
|
|
|
122363
122705
|
warnings: byFile.get(file.filePath) ?? []
|
|
122364
122706
|
})).filter((file) => file.warnings.length > 0);
|
|
122365
122707
|
}
|
|
122708
|
+
function getDeltaFileGroup(groups2, cwd, filePath) {
|
|
122709
|
+
const rel = path200.relative(cwd, filePath);
|
|
122710
|
+
let group = groups2.get(rel);
|
|
122711
|
+
if (!group) {
|
|
122712
|
+
group = {
|
|
122713
|
+
rel,
|
|
122714
|
+
actionableLines: [],
|
|
122715
|
+
qualityLines: [],
|
|
122716
|
+
projectLines: [],
|
|
122717
|
+
incomplete: false
|
|
122718
|
+
};
|
|
122719
|
+
groups2.set(rel, group);
|
|
122720
|
+
}
|
|
122721
|
+
return group;
|
|
122722
|
+
}
|
|
122366
122723
|
function formatDeltaMode(cacheManager2, cwd, severity, pathsScope) {
|
|
122367
122724
|
const actionableEntry = cacheManager2.readCache("actionable-warnings", cwd);
|
|
122368
122725
|
const qualityEntry = cacheManager2.readCache("code-quality-warnings", cwd);
|
|
122726
|
+
const reverifyIncompletePaths = new Set((actionableEntry?.data?.files ?? []).filter((file) => file.reVerifyIncomplete).map((file) => normalizeMapKey(file.filePath)));
|
|
122369
122727
|
const actionable = actionableEntry?.data;
|
|
122370
122728
|
const quality = qualityEntry?.data;
|
|
122371
122729
|
const policyMap = loadProjectRulePolicyMap(cwd);
|
|
@@ -122389,29 +122747,54 @@ function formatDeltaMode(cacheManager2, cwd, severity, pathsScope) {
|
|
|
122389
122747
|
...file,
|
|
122390
122748
|
warnings: matchingWarnings(file.warnings)
|
|
122391
122749
|
})).filter((file) => file.warnings.length > 0);
|
|
122392
|
-
const
|
|
122750
|
+
const groups2 = /* @__PURE__ */ new Map();
|
|
122393
122751
|
if (filteredActionableFiles.length > 0) {
|
|
122394
122752
|
for (const file of filteredActionableFiles) {
|
|
122395
|
-
const
|
|
122396
|
-
lines.push(`${rel}`);
|
|
122753
|
+
const group = getDeltaFileGroup(groups2, cwd, file.filePath);
|
|
122397
122754
|
for (const w of file.warnings) {
|
|
122398
122755
|
const where = w.stale ? STALE_LINE_MARKER : `L${w.line ?? "?"}`;
|
|
122399
|
-
|
|
122756
|
+
group.actionableLines.push(` \u26A0 ${where} ${w.rule ?? w.code ?? w.tool} ${w.message}`);
|
|
122757
|
+
}
|
|
122758
|
+
const key4 = normalizeMapKey(file.filePath);
|
|
122759
|
+
if (reverifyIncompletePaths.has(key4))
|
|
122760
|
+
group.incomplete = true;
|
|
122761
|
+
if (!group.staleRow) {
|
|
122762
|
+
const staleWarning = file.warnings.find((w) => w.stale);
|
|
122763
|
+
if (staleWarning)
|
|
122764
|
+
group.staleRow = { staleAsOf: staleWarning.staleAsOf };
|
|
122400
122765
|
}
|
|
122401
122766
|
}
|
|
122402
122767
|
}
|
|
122403
122768
|
if (filteredQualityFiles.length > 0) {
|
|
122404
122769
|
for (const file of filteredQualityFiles) {
|
|
122405
|
-
const
|
|
122406
|
-
if (!lines.includes(rel))
|
|
122407
|
-
lines.push(rel);
|
|
122770
|
+
const group = getDeltaFileGroup(groups2, cwd, file.filePath);
|
|
122408
122771
|
for (const w of file.warnings) {
|
|
122409
122772
|
const where = w.stale ? STALE_LINE_MARKER : `L${w.line ?? "?"}`;
|
|
122410
|
-
|
|
122773
|
+
group.qualityLines.push(` \u2139 ${where} ${w.rule ?? w.code ?? w.tool} ${w.message}`);
|
|
122774
|
+
}
|
|
122775
|
+
const key4 = normalizeMapKey(file.filePath);
|
|
122776
|
+
if (reverifyIncompletePaths.has(key4))
|
|
122777
|
+
group.incomplete = true;
|
|
122778
|
+
if (!group.staleRow) {
|
|
122779
|
+
const staleWarning = file.warnings.find((w) => w.stale);
|
|
122780
|
+
if (staleWarning)
|
|
122781
|
+
group.staleRow = { staleAsOf: staleWarning.staleAsOf };
|
|
122411
122782
|
}
|
|
122412
122783
|
}
|
|
122413
122784
|
}
|
|
122414
|
-
const projectDeltaCount = appendProjectDiagnosticsDeltaLines(
|
|
122785
|
+
const projectDeltaCount = appendProjectDiagnosticsDeltaLines(groups2, cwd, projectDelta, severity, includeFile);
|
|
122786
|
+
const lines = [];
|
|
122787
|
+
for (const group of groups2.values()) {
|
|
122788
|
+
lines.push(group.rel);
|
|
122789
|
+
lines.push(...group.actionableLines);
|
|
122790
|
+
lines.push(...group.qualityLines);
|
|
122791
|
+
lines.push(...group.projectLines);
|
|
122792
|
+
if (group.staleRow) {
|
|
122793
|
+
lines.push(` (${formatCacheAgeLabel(group.staleRow.staleAsOf)})`);
|
|
122794
|
+
}
|
|
122795
|
+
if (group.incomplete)
|
|
122796
|
+
lines.push(" (re-verify incomplete)");
|
|
122797
|
+
}
|
|
122415
122798
|
const selectedActionableFiles = filteredActionableFiles;
|
|
122416
122799
|
const selectedQualityFiles = filteredQualityFiles;
|
|
122417
122800
|
const aw = selectedActionableFiles.reduce((count, file) => count + file.warnings.length, 0);
|
|
@@ -122811,7 +123194,7 @@ async function applyInlineSuppressionsToSummaries(summaries, cwd, policyMap) {
|
|
|
122811
123194
|
return summary;
|
|
122812
123195
|
let content;
|
|
122813
123196
|
try {
|
|
122814
|
-
content = await
|
|
123197
|
+
content = await fs130.readFile(summary.filePath, "utf8");
|
|
122815
123198
|
} catch {
|
|
122816
123199
|
const policyKept2 = applyRulePolicy(summary.diagnostics, policyMap);
|
|
122817
123200
|
return policyKept2.length === summary.diagnostics.length ? summary : summarizeDiagnostics(summary.filePath, policyKept2, summary.hasFinalSnapshot);
|
|
@@ -123407,7 +123790,7 @@ Summary (${visibleSummaries.length} files diagnosed this session):`,
|
|
|
123407
123790
|
}
|
|
123408
123791
|
|
|
123409
123792
|
// dist/tools/lens-diagnostic-mark.js
|
|
123410
|
-
import { promises as
|
|
123793
|
+
import { promises as fs131 } from "node:fs";
|
|
123411
123794
|
import * as path202 from "node:path";
|
|
123412
123795
|
init_diagnostic_dispositions();
|
|
123413
123796
|
|
|
@@ -123462,8 +123845,9 @@ function insertSuppressComment(content, filePath, line, rule) {
|
|
|
123462
123845
|
}
|
|
123463
123846
|
|
|
123464
123847
|
// dist/tools/lens-diagnostic-mark.js
|
|
123465
|
-
|
|
123848
|
+
init_path_utils();
|
|
123466
123849
|
init_tool_config();
|
|
123850
|
+
init_widget_state();
|
|
123467
123851
|
var DISPOSITIONS = [
|
|
123468
123852
|
"false-positive",
|
|
123469
123853
|
"suppress",
|
|
@@ -123477,7 +123861,7 @@ function isBlank(text) {
|
|
|
123477
123861
|
function widgetCrossCheck(absPath, tool, rule, message, callerLine) {
|
|
123478
123862
|
let diagnostics;
|
|
123479
123863
|
try {
|
|
123480
|
-
diagnostics = getFileDiagnostics(absPath);
|
|
123864
|
+
diagnostics = getFileDiagnostics(normalizeMapKey(absPath));
|
|
123481
123865
|
} catch {
|
|
123482
123866
|
return void 0;
|
|
123483
123867
|
}
|
|
@@ -123612,7 +123996,7 @@ function createLensDiagnosticMarkTool(getCwd, getIdentity) {
|
|
|
123612
123996
|
const absPath = path202.isAbsolute(filePathArg) ? filePathArg : path202.resolve(cwd, filePathArg);
|
|
123613
123997
|
let content;
|
|
123614
123998
|
try {
|
|
123615
|
-
content = await
|
|
123999
|
+
content = await fs131.readFile(absPath, "utf-8");
|
|
123616
124000
|
} catch (err) {
|
|
123617
124001
|
return {
|
|
123618
124002
|
content: [
|
|
@@ -123682,7 +124066,7 @@ function createLensDiagnosticMarkTool(getCwd, getIdentity) {
|
|
|
123682
124066
|
details: {}
|
|
123683
124067
|
};
|
|
123684
124068
|
}
|
|
123685
|
-
await
|
|
124069
|
+
await fs131.writeFile(absPath, updated, "utf-8");
|
|
123686
124070
|
}
|
|
123687
124071
|
const anchor = markDisposition(cwd, {
|
|
123688
124072
|
cwd,
|
|
@@ -128166,7 +128550,7 @@ init_env_utils();
|
|
|
128166
128550
|
init_package_root();
|
|
128167
128551
|
init_path_utils();
|
|
128168
128552
|
init_git_identity();
|
|
128169
|
-
import * as
|
|
128553
|
+
import * as fs132 from "node:fs";
|
|
128170
128554
|
import * as path208 from "node:path";
|
|
128171
128555
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
128172
128556
|
function resolveOwnedCommit(root) {
|
|
@@ -128180,7 +128564,7 @@ function resolveOwnedCommit(root) {
|
|
|
128180
128564
|
}
|
|
128181
128565
|
function readPackageVersion(root) {
|
|
128182
128566
|
try {
|
|
128183
|
-
const raw =
|
|
128567
|
+
const raw = fs132.readFileSync(path208.join(root, "package.json"), "utf-8");
|
|
128184
128568
|
const pkg = JSON.parse(raw);
|
|
128185
128569
|
return pkg.version ?? "unknown";
|
|
128186
128570
|
} catch {
|
|
@@ -128189,7 +128573,7 @@ function readPackageVersion(root) {
|
|
|
128189
128573
|
}
|
|
128190
128574
|
function statEntryMtime(entryImportMetaUrl) {
|
|
128191
128575
|
try {
|
|
128192
|
-
return
|
|
128576
|
+
return fs132.statSync(fileURLToPath11(entryImportMetaUrl)).mtime.toISOString();
|
|
128193
128577
|
} catch {
|
|
128194
128578
|
return "unknown";
|
|
128195
128579
|
}
|
|
@@ -129855,10 +130239,11 @@ ${degradationLines.join("\n")}` : "";
|
|
|
129855
130239
|
});
|
|
129856
130240
|
}
|
|
129857
130241
|
registerCascadeTierReconcileTask(() => getLSPService(), {
|
|
129858
|
-
onResolvedFound: ({ filePath, diagnostics }) => {
|
|
130242
|
+
onResolvedFound: ({ filePath, diagnostics, publishedAt }) => {
|
|
129859
130243
|
const run = buildResolvedFoundCascadeRun(runtime.projectRoot, {
|
|
129860
130244
|
filePath,
|
|
129861
|
-
diagnostics
|
|
130245
|
+
diagnostics,
|
|
130246
|
+
publishedAt
|
|
129862
130247
|
});
|
|
129863
130248
|
if (run)
|
|
129864
130249
|
runtime.appendCascadeRun(run);
|