@vibecheck-ai/cli 20.2.0 → 23.0.1
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 +247 -86
- package/dist/index.js +12699 -1449
- package/dist/index.js.map +4 -4
- package/dist/runner/FileRunner.js +774 -120
- package/dist/runner/FileRunner.js.map +4 -4
- package/package.json +6 -4
|
@@ -110,7 +110,7 @@ var require_path = __commonJS({
|
|
|
110
110
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
111
111
|
exports2.convertPosixPathToPattern = exports2.convertWindowsPathToPattern = exports2.convertPathToPattern = exports2.escapePosixPath = exports2.escapeWindowsPath = exports2.escape = exports2.removeLeadingDotSegment = exports2.makeAbsolute = exports2.unixify = void 0;
|
|
112
112
|
var os2 = require("os");
|
|
113
|
-
var
|
|
113
|
+
var path6 = require("path");
|
|
114
114
|
var IS_WINDOWS_PLATFORM = os2.platform() === "win32";
|
|
115
115
|
var LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2;
|
|
116
116
|
var POSIX_UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\()|\\(?![!()*+?@[\]{|}]))/g;
|
|
@@ -123,7 +123,7 @@ var require_path = __commonJS({
|
|
|
123
123
|
__name(unixify, "unixify");
|
|
124
124
|
exports2.unixify = unixify;
|
|
125
125
|
function makeAbsolute(cwd, filepath) {
|
|
126
|
-
return
|
|
126
|
+
return path6.resolve(cwd, filepath);
|
|
127
127
|
}
|
|
128
128
|
__name(makeAbsolute, "makeAbsolute");
|
|
129
129
|
exports2.makeAbsolute = makeAbsolute;
|
|
@@ -1440,7 +1440,7 @@ var require_braces = __commonJS({
|
|
|
1440
1440
|
var require_constants2 = __commonJS({
|
|
1441
1441
|
"../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/constants.js"(exports2, module2) {
|
|
1442
1442
|
"use strict";
|
|
1443
|
-
var
|
|
1443
|
+
var path6 = require("path");
|
|
1444
1444
|
var WIN_SLASH = "\\\\/";
|
|
1445
1445
|
var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
1446
1446
|
var DOT_LITERAL = "\\.";
|
|
@@ -1610,7 +1610,7 @@ var require_constants2 = __commonJS({
|
|
|
1610
1610
|
/* | */
|
|
1611
1611
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
|
|
1612
1612
|
/* \uFEFF */
|
|
1613
|
-
SEP:
|
|
1613
|
+
SEP: path6.sep,
|
|
1614
1614
|
/**
|
|
1615
1615
|
* Create EXTGLOB_CHARS
|
|
1616
1616
|
*/
|
|
@@ -1637,7 +1637,7 @@ var require_constants2 = __commonJS({
|
|
|
1637
1637
|
var require_utils2 = __commonJS({
|
|
1638
1638
|
"../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/utils.js"(exports2) {
|
|
1639
1639
|
"use strict";
|
|
1640
|
-
var
|
|
1640
|
+
var path6 = require("path");
|
|
1641
1641
|
var win32 = process.platform === "win32";
|
|
1642
1642
|
var {
|
|
1643
1643
|
REGEX_BACKSLASH,
|
|
@@ -1666,7 +1666,7 @@ var require_utils2 = __commonJS({
|
|
|
1666
1666
|
if (options && typeof options.windows === "boolean") {
|
|
1667
1667
|
return options.windows;
|
|
1668
1668
|
}
|
|
1669
|
-
return win32 === true ||
|
|
1669
|
+
return win32 === true || path6.sep === "\\";
|
|
1670
1670
|
};
|
|
1671
1671
|
exports2.escapeLast = (input, char, lastIdx) => {
|
|
1672
1672
|
const idx = input.lastIndexOf(char, lastIdx);
|
|
@@ -2801,7 +2801,7 @@ var require_parse2 = __commonJS({
|
|
|
2801
2801
|
var require_picomatch = __commonJS({
|
|
2802
2802
|
"../../node_modules/.pnpm/picomatch@2.3.1/node_modules/picomatch/lib/picomatch.js"(exports2, module2) {
|
|
2803
2803
|
"use strict";
|
|
2804
|
-
var
|
|
2804
|
+
var path6 = require("path");
|
|
2805
2805
|
var scan = require_scan();
|
|
2806
2806
|
var parse = require_parse2();
|
|
2807
2807
|
var utils = require_utils2();
|
|
@@ -2886,7 +2886,7 @@ var require_picomatch = __commonJS({
|
|
|
2886
2886
|
};
|
|
2887
2887
|
picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
|
|
2888
2888
|
const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
|
|
2889
|
-
return regex.test(
|
|
2889
|
+
return regex.test(path6.basename(input));
|
|
2890
2890
|
};
|
|
2891
2891
|
picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
|
|
2892
2892
|
picomatch.parse = (pattern, options) => {
|
|
@@ -3113,7 +3113,7 @@ var require_pattern = __commonJS({
|
|
|
3113
3113
|
"use strict";
|
|
3114
3114
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3115
3115
|
exports2.isAbsolute = exports2.partitionAbsoluteAndRelative = exports2.removeDuplicateSlashes = exports2.matchAny = exports2.convertPatternsToRe = exports2.makeRe = exports2.getPatternParts = exports2.expandBraceExpansion = exports2.expandPatternsWithBraceExpansion = exports2.isAffectDepthOfReadingPattern = exports2.endsWithSlashGlobStar = exports2.hasGlobStar = exports2.getBaseDirectory = exports2.isPatternRelatedToParentDirectory = exports2.getPatternsOutsideCurrentDirectory = exports2.getPatternsInsideCurrentDirectory = exports2.getPositivePatterns = exports2.getNegativePatterns = exports2.isPositivePattern = exports2.isNegativePattern = exports2.convertToNegativePattern = exports2.convertToPositivePattern = exports2.isDynamicPattern = exports2.isStaticPattern = void 0;
|
|
3116
|
-
var
|
|
3116
|
+
var path6 = require("path");
|
|
3117
3117
|
var globParent = require_glob_parent();
|
|
3118
3118
|
var micromatch = require_micromatch();
|
|
3119
3119
|
var GLOBSTAR = "**";
|
|
@@ -3223,7 +3223,7 @@ var require_pattern = __commonJS({
|
|
|
3223
3223
|
__name(endsWithSlashGlobStar, "endsWithSlashGlobStar");
|
|
3224
3224
|
exports2.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
3225
3225
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
3226
|
-
const basename =
|
|
3226
|
+
const basename = path6.basename(pattern);
|
|
3227
3227
|
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename);
|
|
3228
3228
|
}
|
|
3229
3229
|
__name(isAffectDepthOfReadingPattern, "isAffectDepthOfReadingPattern");
|
|
@@ -3290,7 +3290,7 @@ var require_pattern = __commonJS({
|
|
|
3290
3290
|
__name(partitionAbsoluteAndRelative, "partitionAbsoluteAndRelative");
|
|
3291
3291
|
exports2.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
|
|
3292
3292
|
function isAbsolute(pattern) {
|
|
3293
|
-
return
|
|
3293
|
+
return path6.isAbsolute(pattern);
|
|
3294
3294
|
}
|
|
3295
3295
|
__name(isAbsolute, "isAbsolute");
|
|
3296
3296
|
exports2.isAbsolute = isAbsolute;
|
|
@@ -3479,10 +3479,10 @@ var require_utils3 = __commonJS({
|
|
|
3479
3479
|
exports2.array = array;
|
|
3480
3480
|
var errno = require_errno();
|
|
3481
3481
|
exports2.errno = errno;
|
|
3482
|
-
var
|
|
3483
|
-
exports2.fs =
|
|
3484
|
-
var
|
|
3485
|
-
exports2.path =
|
|
3482
|
+
var fs6 = require_fs();
|
|
3483
|
+
exports2.fs = fs6;
|
|
3484
|
+
var path6 = require_path();
|
|
3485
|
+
exports2.path = path6;
|
|
3486
3486
|
var pattern = require_pattern();
|
|
3487
3487
|
exports2.pattern = pattern;
|
|
3488
3488
|
var stream = require_stream();
|
|
@@ -3602,8 +3602,8 @@ var require_async = __commonJS({
|
|
|
3602
3602
|
"use strict";
|
|
3603
3603
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3604
3604
|
exports2.read = void 0;
|
|
3605
|
-
function read(
|
|
3606
|
-
settings.fs.lstat(
|
|
3605
|
+
function read(path6, settings, callback) {
|
|
3606
|
+
settings.fs.lstat(path6, (lstatError, lstat) => {
|
|
3607
3607
|
if (lstatError !== null) {
|
|
3608
3608
|
callFailureCallback(callback, lstatError);
|
|
3609
3609
|
return;
|
|
@@ -3612,7 +3612,7 @@ var require_async = __commonJS({
|
|
|
3612
3612
|
callSuccessCallback(callback, lstat);
|
|
3613
3613
|
return;
|
|
3614
3614
|
}
|
|
3615
|
-
settings.fs.stat(
|
|
3615
|
+
settings.fs.stat(path6, (statError, stat4) => {
|
|
3616
3616
|
if (statError !== null) {
|
|
3617
3617
|
if (settings.throwErrorOnBrokenSymbolicLink) {
|
|
3618
3618
|
callFailureCallback(callback, statError);
|
|
@@ -3622,9 +3622,9 @@ var require_async = __commonJS({
|
|
|
3622
3622
|
return;
|
|
3623
3623
|
}
|
|
3624
3624
|
if (settings.markSymbolicLink) {
|
|
3625
|
-
|
|
3625
|
+
stat4.isSymbolicLink = () => true;
|
|
3626
3626
|
}
|
|
3627
|
-
callSuccessCallback(callback,
|
|
3627
|
+
callSuccessCallback(callback, stat4);
|
|
3628
3628
|
});
|
|
3629
3629
|
});
|
|
3630
3630
|
}
|
|
@@ -3647,17 +3647,17 @@ var require_sync = __commonJS({
|
|
|
3647
3647
|
"use strict";
|
|
3648
3648
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3649
3649
|
exports2.read = void 0;
|
|
3650
|
-
function read(
|
|
3651
|
-
const lstat = settings.fs.lstatSync(
|
|
3650
|
+
function read(path6, settings) {
|
|
3651
|
+
const lstat = settings.fs.lstatSync(path6);
|
|
3652
3652
|
if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) {
|
|
3653
3653
|
return lstat;
|
|
3654
3654
|
}
|
|
3655
3655
|
try {
|
|
3656
|
-
const
|
|
3656
|
+
const stat4 = settings.fs.statSync(path6);
|
|
3657
3657
|
if (settings.markSymbolicLink) {
|
|
3658
|
-
|
|
3658
|
+
stat4.isSymbolicLink = () => true;
|
|
3659
3659
|
}
|
|
3660
|
-
return
|
|
3660
|
+
return stat4;
|
|
3661
3661
|
} catch (error) {
|
|
3662
3662
|
if (!settings.throwErrorOnBrokenSymbolicLink) {
|
|
3663
3663
|
return lstat;
|
|
@@ -3676,12 +3676,12 @@ var require_fs2 = __commonJS({
|
|
|
3676
3676
|
"use strict";
|
|
3677
3677
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3678
3678
|
exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
|
|
3679
|
-
var
|
|
3679
|
+
var fs6 = require("fs");
|
|
3680
3680
|
exports2.FILE_SYSTEM_ADAPTER = {
|
|
3681
|
-
lstat:
|
|
3682
|
-
stat:
|
|
3683
|
-
lstatSync:
|
|
3684
|
-
statSync:
|
|
3681
|
+
lstat: fs6.lstat,
|
|
3682
|
+
stat: fs6.stat,
|
|
3683
|
+
lstatSync: fs6.lstatSync,
|
|
3684
|
+
statSync: fs6.statSync
|
|
3685
3685
|
};
|
|
3686
3686
|
function createFileSystemAdapter(fsMethods) {
|
|
3687
3687
|
if (fsMethods === void 0) {
|
|
@@ -3699,7 +3699,7 @@ var require_settings = __commonJS({
|
|
|
3699
3699
|
"../../node_modules/.pnpm/@nodelib+fs.stat@2.0.5/node_modules/@nodelib/fs.stat/out/settings.js"(exports2) {
|
|
3700
3700
|
"use strict";
|
|
3701
3701
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3702
|
-
var
|
|
3702
|
+
var fs6 = require_fs2();
|
|
3703
3703
|
var Settings = class {
|
|
3704
3704
|
static {
|
|
3705
3705
|
__name(this, "Settings");
|
|
@@ -3707,7 +3707,7 @@ var require_settings = __commonJS({
|
|
|
3707
3707
|
constructor(_options = {}) {
|
|
3708
3708
|
this._options = _options;
|
|
3709
3709
|
this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true);
|
|
3710
|
-
this.fs =
|
|
3710
|
+
this.fs = fs6.createFileSystemAdapter(this._options.fs);
|
|
3711
3711
|
this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false);
|
|
3712
3712
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
|
3713
3713
|
}
|
|
@@ -3729,21 +3729,21 @@ var require_out = __commonJS({
|
|
|
3729
3729
|
var sync = require_sync();
|
|
3730
3730
|
var settings_1 = require_settings();
|
|
3731
3731
|
exports2.Settings = settings_1.default;
|
|
3732
|
-
function
|
|
3732
|
+
function stat4(path6, optionsOrSettingsOrCallback, callback) {
|
|
3733
3733
|
if (typeof optionsOrSettingsOrCallback === "function") {
|
|
3734
|
-
async.read(
|
|
3734
|
+
async.read(path6, getSettings(), optionsOrSettingsOrCallback);
|
|
3735
3735
|
return;
|
|
3736
3736
|
}
|
|
3737
|
-
async.read(
|
|
3737
|
+
async.read(path6, getSettings(optionsOrSettingsOrCallback), callback);
|
|
3738
3738
|
}
|
|
3739
|
-
__name(
|
|
3740
|
-
exports2.stat =
|
|
3741
|
-
function
|
|
3739
|
+
__name(stat4, "stat");
|
|
3740
|
+
exports2.stat = stat4;
|
|
3741
|
+
function statSync2(path6, optionsOrSettings) {
|
|
3742
3742
|
const settings = getSettings(optionsOrSettings);
|
|
3743
|
-
return sync.read(
|
|
3743
|
+
return sync.read(path6, settings);
|
|
3744
3744
|
}
|
|
3745
|
-
__name(
|
|
3746
|
-
exports2.statSync =
|
|
3745
|
+
__name(statSync2, "statSync");
|
|
3746
|
+
exports2.statSync = statSync2;
|
|
3747
3747
|
function getSettings(settingsOrOptions = {}) {
|
|
3748
3748
|
if (settingsOrOptions instanceof settings_1.default) {
|
|
3749
3749
|
return settingsOrOptions;
|
|
@@ -3873,8 +3873,8 @@ var require_utils4 = __commonJS({
|
|
|
3873
3873
|
"use strict";
|
|
3874
3874
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3875
3875
|
exports2.fs = void 0;
|
|
3876
|
-
var
|
|
3877
|
-
exports2.fs =
|
|
3876
|
+
var fs6 = require_fs3();
|
|
3877
|
+
exports2.fs = fs6;
|
|
3878
3878
|
}
|
|
3879
3879
|
});
|
|
3880
3880
|
|
|
@@ -3970,16 +3970,16 @@ var require_async2 = __commonJS({
|
|
|
3970
3970
|
return;
|
|
3971
3971
|
}
|
|
3972
3972
|
const tasks = names.map((name) => {
|
|
3973
|
-
const
|
|
3973
|
+
const path6 = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
|
|
3974
3974
|
return (done) => {
|
|
3975
|
-
fsStat.stat(
|
|
3975
|
+
fsStat.stat(path6, settings.fsStatSettings, (error, stats) => {
|
|
3976
3976
|
if (error !== null) {
|
|
3977
3977
|
done(error);
|
|
3978
3978
|
return;
|
|
3979
3979
|
}
|
|
3980
3980
|
const entry = {
|
|
3981
3981
|
name,
|
|
3982
|
-
path:
|
|
3982
|
+
path: path6,
|
|
3983
3983
|
dirent: utils.fs.createDirentFromStats(name, stats)
|
|
3984
3984
|
};
|
|
3985
3985
|
if (settings.stats) {
|
|
@@ -4079,14 +4079,14 @@ var require_fs4 = __commonJS({
|
|
|
4079
4079
|
"use strict";
|
|
4080
4080
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
4081
4081
|
exports2.createFileSystemAdapter = exports2.FILE_SYSTEM_ADAPTER = void 0;
|
|
4082
|
-
var
|
|
4082
|
+
var fs6 = require("fs");
|
|
4083
4083
|
exports2.FILE_SYSTEM_ADAPTER = {
|
|
4084
|
-
lstat:
|
|
4085
|
-
stat:
|
|
4086
|
-
lstatSync:
|
|
4087
|
-
statSync:
|
|
4088
|
-
readdir:
|
|
4089
|
-
readdirSync:
|
|
4084
|
+
lstat: fs6.lstat,
|
|
4085
|
+
stat: fs6.stat,
|
|
4086
|
+
lstatSync: fs6.lstatSync,
|
|
4087
|
+
statSync: fs6.statSync,
|
|
4088
|
+
readdir: fs6.readdir,
|
|
4089
|
+
readdirSync: fs6.readdirSync
|
|
4090
4090
|
};
|
|
4091
4091
|
function createFileSystemAdapter(fsMethods) {
|
|
4092
4092
|
if (fsMethods === void 0) {
|
|
@@ -4104,9 +4104,9 @@ var require_settings2 = __commonJS({
|
|
|
4104
4104
|
"../../node_modules/.pnpm/@nodelib+fs.scandir@2.1.5/node_modules/@nodelib/fs.scandir/out/settings.js"(exports2) {
|
|
4105
4105
|
"use strict";
|
|
4106
4106
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
4107
|
-
var
|
|
4107
|
+
var path6 = require("path");
|
|
4108
4108
|
var fsStat = require_out();
|
|
4109
|
-
var
|
|
4109
|
+
var fs6 = require_fs4();
|
|
4110
4110
|
var Settings = class {
|
|
4111
4111
|
static {
|
|
4112
4112
|
__name(this, "Settings");
|
|
@@ -4114,8 +4114,8 @@ var require_settings2 = __commonJS({
|
|
|
4114
4114
|
constructor(_options = {}) {
|
|
4115
4115
|
this._options = _options;
|
|
4116
4116
|
this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false);
|
|
4117
|
-
this.fs =
|
|
4118
|
-
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator,
|
|
4117
|
+
this.fs = fs6.createFileSystemAdapter(this._options.fs);
|
|
4118
|
+
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path6.sep);
|
|
4119
4119
|
this.stats = this._getValue(this._options.stats, false);
|
|
4120
4120
|
this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true);
|
|
4121
4121
|
this.fsStatSettings = new fsStat.Settings({
|
|
@@ -4142,18 +4142,18 @@ var require_out2 = __commonJS({
|
|
|
4142
4142
|
var sync = require_sync2();
|
|
4143
4143
|
var settings_1 = require_settings2();
|
|
4144
4144
|
exports2.Settings = settings_1.default;
|
|
4145
|
-
function scandir(
|
|
4145
|
+
function scandir(path6, optionsOrSettingsOrCallback, callback) {
|
|
4146
4146
|
if (typeof optionsOrSettingsOrCallback === "function") {
|
|
4147
|
-
async.read(
|
|
4147
|
+
async.read(path6, getSettings(), optionsOrSettingsOrCallback);
|
|
4148
4148
|
return;
|
|
4149
4149
|
}
|
|
4150
|
-
async.read(
|
|
4150
|
+
async.read(path6, getSettings(optionsOrSettingsOrCallback), callback);
|
|
4151
4151
|
}
|
|
4152
4152
|
__name(scandir, "scandir");
|
|
4153
4153
|
exports2.scandir = scandir;
|
|
4154
|
-
function scandirSync(
|
|
4154
|
+
function scandirSync(path6, optionsOrSettings) {
|
|
4155
4155
|
const settings = getSettings(optionsOrSettings);
|
|
4156
|
-
return sync.read(
|
|
4156
|
+
return sync.read(path6, settings);
|
|
4157
4157
|
}
|
|
4158
4158
|
__name(scandirSync, "scandirSync");
|
|
4159
4159
|
exports2.scandirSync = scandirSync;
|
|
@@ -4454,13 +4454,13 @@ var require_queue = __commonJS({
|
|
|
4454
4454
|
queue.drained = drained;
|
|
4455
4455
|
return queue;
|
|
4456
4456
|
function push(value) {
|
|
4457
|
-
var p = new Promise(function(
|
|
4457
|
+
var p = new Promise(function(resolve2, reject) {
|
|
4458
4458
|
pushCb(value, function(err, result) {
|
|
4459
4459
|
if (err) {
|
|
4460
4460
|
reject(err);
|
|
4461
4461
|
return;
|
|
4462
4462
|
}
|
|
4463
|
-
|
|
4463
|
+
resolve2(result);
|
|
4464
4464
|
});
|
|
4465
4465
|
});
|
|
4466
4466
|
p.catch(noop);
|
|
@@ -4468,13 +4468,13 @@ var require_queue = __commonJS({
|
|
|
4468
4468
|
}
|
|
4469
4469
|
__name(push, "push");
|
|
4470
4470
|
function unshift(value) {
|
|
4471
|
-
var p = new Promise(function(
|
|
4471
|
+
var p = new Promise(function(resolve2, reject) {
|
|
4472
4472
|
unshiftCb(value, function(err, result) {
|
|
4473
4473
|
if (err) {
|
|
4474
4474
|
reject(err);
|
|
4475
4475
|
return;
|
|
4476
4476
|
}
|
|
4477
|
-
|
|
4477
|
+
resolve2(result);
|
|
4478
4478
|
});
|
|
4479
4479
|
});
|
|
4480
4480
|
p.catch(noop);
|
|
@@ -4482,15 +4482,15 @@ var require_queue = __commonJS({
|
|
|
4482
4482
|
}
|
|
4483
4483
|
__name(unshift, "unshift");
|
|
4484
4484
|
function drained() {
|
|
4485
|
-
var p = new Promise(function(
|
|
4485
|
+
var p = new Promise(function(resolve2) {
|
|
4486
4486
|
process.nextTick(function() {
|
|
4487
4487
|
if (queue.idle()) {
|
|
4488
|
-
|
|
4488
|
+
resolve2();
|
|
4489
4489
|
} else {
|
|
4490
4490
|
var previousDrain = queue.drain;
|
|
4491
4491
|
queue.drain = function() {
|
|
4492
4492
|
if (typeof previousDrain === "function") previousDrain();
|
|
4493
|
-
|
|
4493
|
+
resolve2();
|
|
4494
4494
|
queue.drain = previousDrain;
|
|
4495
4495
|
};
|
|
4496
4496
|
}
|
|
@@ -4850,7 +4850,7 @@ var require_settings3 = __commonJS({
|
|
|
4850
4850
|
"../../node_modules/.pnpm/@nodelib+fs.walk@1.2.8/node_modules/@nodelib/fs.walk/out/settings.js"(exports2) {
|
|
4851
4851
|
"use strict";
|
|
4852
4852
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
4853
|
-
var
|
|
4853
|
+
var path6 = require("path");
|
|
4854
4854
|
var fsScandir = require_out2();
|
|
4855
4855
|
var Settings = class {
|
|
4856
4856
|
static {
|
|
@@ -4863,7 +4863,7 @@ var require_settings3 = __commonJS({
|
|
|
4863
4863
|
this.deepFilter = this._getValue(this._options.deepFilter, null);
|
|
4864
4864
|
this.entryFilter = this._getValue(this._options.entryFilter, null);
|
|
4865
4865
|
this.errorFilter = this._getValue(this._options.errorFilter, null);
|
|
4866
|
-
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator,
|
|
4866
|
+
this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path6.sep);
|
|
4867
4867
|
this.fsScandirSettings = new fsScandir.Settings({
|
|
4868
4868
|
followSymbolicLinks: this._options.followSymbolicLinks,
|
|
4869
4869
|
fs: this._options.fs,
|
|
@@ -4929,7 +4929,7 @@ var require_reader2 = __commonJS({
|
|
|
4929
4929
|
"../../node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/readers/reader.js"(exports2) {
|
|
4930
4930
|
"use strict";
|
|
4931
4931
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
4932
|
-
var
|
|
4932
|
+
var path6 = require("path");
|
|
4933
4933
|
var fsStat = require_out();
|
|
4934
4934
|
var utils = require_utils3();
|
|
4935
4935
|
var Reader = class {
|
|
@@ -4945,7 +4945,7 @@ var require_reader2 = __commonJS({
|
|
|
4945
4945
|
});
|
|
4946
4946
|
}
|
|
4947
4947
|
_getFullEntryPath(filepath) {
|
|
4948
|
-
return
|
|
4948
|
+
return path6.resolve(this._settings.cwd, filepath);
|
|
4949
4949
|
}
|
|
4950
4950
|
_makeEntry(stats, pattern) {
|
|
4951
4951
|
const entry = {
|
|
@@ -5015,9 +5015,9 @@ var require_stream3 = __commonJS({
|
|
|
5015
5015
|
});
|
|
5016
5016
|
}
|
|
5017
5017
|
_getStat(filepath) {
|
|
5018
|
-
return new Promise((
|
|
5018
|
+
return new Promise((resolve2, reject) => {
|
|
5019
5019
|
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
|
5020
|
-
return error === null ?
|
|
5020
|
+
return error === null ? resolve2(stats) : reject(error);
|
|
5021
5021
|
});
|
|
5022
5022
|
});
|
|
5023
5023
|
}
|
|
@@ -5044,10 +5044,10 @@ var require_async5 = __commonJS({
|
|
|
5044
5044
|
this._readerStream = new stream_1.default(this._settings);
|
|
5045
5045
|
}
|
|
5046
5046
|
dynamic(root, options) {
|
|
5047
|
-
return new Promise((
|
|
5047
|
+
return new Promise((resolve2, reject) => {
|
|
5048
5048
|
this._walkAsync(root, options, (error, entries) => {
|
|
5049
5049
|
if (error === null) {
|
|
5050
|
-
|
|
5050
|
+
resolve2(entries);
|
|
5051
5051
|
} else {
|
|
5052
5052
|
reject(error);
|
|
5053
5053
|
}
|
|
@@ -5057,10 +5057,10 @@ var require_async5 = __commonJS({
|
|
|
5057
5057
|
async static(patterns, options) {
|
|
5058
5058
|
const entries = [];
|
|
5059
5059
|
const stream = this._readerStream.static(patterns, options);
|
|
5060
|
-
return new Promise((
|
|
5060
|
+
return new Promise((resolve2, reject) => {
|
|
5061
5061
|
stream.once("error", reject);
|
|
5062
5062
|
stream.on("data", (entry) => entries.push(entry));
|
|
5063
|
-
stream.once("end", () =>
|
|
5063
|
+
stream.once("end", () => resolve2(entries));
|
|
5064
5064
|
});
|
|
5065
5065
|
}
|
|
5066
5066
|
};
|
|
@@ -5385,7 +5385,7 @@ var require_provider = __commonJS({
|
|
|
5385
5385
|
"../../node_modules/.pnpm/fast-glob@3.3.3/node_modules/fast-glob/out/providers/provider.js"(exports2) {
|
|
5386
5386
|
"use strict";
|
|
5387
5387
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
5388
|
-
var
|
|
5388
|
+
var path6 = require("path");
|
|
5389
5389
|
var deep_1 = require_deep();
|
|
5390
5390
|
var entry_1 = require_entry();
|
|
5391
5391
|
var error_1 = require_error();
|
|
@@ -5402,7 +5402,7 @@ var require_provider = __commonJS({
|
|
|
5402
5402
|
this.entryTransformer = new entry_2.default(this._settings);
|
|
5403
5403
|
}
|
|
5404
5404
|
_getRootDirectory(task) {
|
|
5405
|
-
return
|
|
5405
|
+
return path6.resolve(this._settings.cwd, task.base);
|
|
5406
5406
|
}
|
|
5407
5407
|
_getReaderOptions(task) {
|
|
5408
5408
|
const basePath = task.base === "." ? "" : task.base;
|
|
@@ -5595,16 +5595,16 @@ var require_settings4 = __commonJS({
|
|
|
5595
5595
|
"use strict";
|
|
5596
5596
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
5597
5597
|
exports2.DEFAULT_FILE_SYSTEM_ADAPTER = void 0;
|
|
5598
|
-
var
|
|
5598
|
+
var fs6 = require("fs");
|
|
5599
5599
|
var os2 = require("os");
|
|
5600
5600
|
var CPU_COUNT = Math.max(os2.cpus().length, 1);
|
|
5601
5601
|
exports2.DEFAULT_FILE_SYSTEM_ADAPTER = {
|
|
5602
|
-
lstat:
|
|
5603
|
-
lstatSync:
|
|
5604
|
-
stat:
|
|
5605
|
-
statSync:
|
|
5606
|
-
readdir:
|
|
5607
|
-
readdirSync:
|
|
5602
|
+
lstat: fs6.lstat,
|
|
5603
|
+
lstatSync: fs6.lstatSync,
|
|
5604
|
+
stat: fs6.stat,
|
|
5605
|
+
statSync: fs6.statSync,
|
|
5606
|
+
readdir: fs6.readdir,
|
|
5607
|
+
readdirSync: fs6.readdirSync
|
|
5608
5608
|
};
|
|
5609
5609
|
var Settings = class {
|
|
5610
5610
|
static {
|
|
@@ -5777,10 +5777,10 @@ __export(FileRunner_exports, {
|
|
|
5777
5777
|
});
|
|
5778
5778
|
module.exports = __toCommonJS(FileRunner_exports);
|
|
5779
5779
|
var import_events = require("events");
|
|
5780
|
-
var
|
|
5781
|
-
var
|
|
5780
|
+
var fs5 = __toESM(require("fs"));
|
|
5781
|
+
var fsp4 = __toESM(require("fs/promises"));
|
|
5782
5782
|
var os = __toESM(require("os"));
|
|
5783
|
-
var
|
|
5783
|
+
var path5 = __toESM(require("path"));
|
|
5784
5784
|
|
|
5785
5785
|
// ../discovery/dist/index.js
|
|
5786
5786
|
var import_fast_glob = __toESM(require_out4(), 1);
|
|
@@ -5994,6 +5994,564 @@ __name(discoverFilesInDirs, "discoverFilesInDirs");
|
|
|
5994
5994
|
|
|
5995
5995
|
// src/runner/FileRunner.ts
|
|
5996
5996
|
var import_engines = require("@vibecheck/engines");
|
|
5997
|
+
|
|
5998
|
+
// src/cache/ScanCache.ts
|
|
5999
|
+
var fs2 = __toESM(require("fs"));
|
|
6000
|
+
var fsp = __toESM(require("fs/promises"));
|
|
6001
|
+
var path2 = __toESM(require("path"));
|
|
6002
|
+
var CACHE_VERSION = 1;
|
|
6003
|
+
var CACHE_FILENAME = "scan-cache.json";
|
|
6004
|
+
var CACHE_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
6005
|
+
var MAX_CACHE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
6006
|
+
var PRUNE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
6007
|
+
var ENGINE_VERSION = "3.0.0";
|
|
6008
|
+
var ScanCache = class {
|
|
6009
|
+
static {
|
|
6010
|
+
__name(this, "ScanCache");
|
|
6011
|
+
}
|
|
6012
|
+
_cachePath;
|
|
6013
|
+
_entries = /* @__PURE__ */ new Map();
|
|
6014
|
+
_metadata;
|
|
6015
|
+
_dirty = false;
|
|
6016
|
+
_hits = 0;
|
|
6017
|
+
_misses = 0;
|
|
6018
|
+
constructor(workspaceRoot) {
|
|
6019
|
+
const cacheDir = path2.join(workspaceRoot, ".vibecheck");
|
|
6020
|
+
this._cachePath = path2.join(cacheDir, CACHE_FILENAME);
|
|
6021
|
+
this._metadata = {
|
|
6022
|
+
version: CACHE_VERSION,
|
|
6023
|
+
createdAt: Date.now(),
|
|
6024
|
+
lastPruned: Date.now(),
|
|
6025
|
+
totalEntries: 0,
|
|
6026
|
+
totalSizeBytes: 0
|
|
6027
|
+
};
|
|
6028
|
+
}
|
|
6029
|
+
/**
|
|
6030
|
+
* Load cache from disk. Non-blocking — returns immediately if file doesn't exist.
|
|
6031
|
+
*/
|
|
6032
|
+
async load() {
|
|
6033
|
+
try {
|
|
6034
|
+
if (!fs2.existsSync(this._cachePath)) return;
|
|
6035
|
+
const raw = await fsp.readFile(this._cachePath, "utf-8");
|
|
6036
|
+
const data = JSON.parse(raw);
|
|
6037
|
+
if (data.metadata.version !== CACHE_VERSION) {
|
|
6038
|
+
this._entries.clear();
|
|
6039
|
+
this._dirty = true;
|
|
6040
|
+
return;
|
|
6041
|
+
}
|
|
6042
|
+
this._metadata = data.metadata;
|
|
6043
|
+
this._entries = new Map(Object.entries(data.entries));
|
|
6044
|
+
if (Date.now() - this._metadata.lastPruned > PRUNE_INTERVAL_MS) {
|
|
6045
|
+
this._prune();
|
|
6046
|
+
}
|
|
6047
|
+
} catch (err) {
|
|
6048
|
+
this._entries.clear();
|
|
6049
|
+
this._dirty = true;
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
/**
|
|
6053
|
+
* Get cached result for a file. Returns null if not cached or invalid.
|
|
6054
|
+
*/
|
|
6055
|
+
get(relativePath, contentHash, confidenceThreshold) {
|
|
6056
|
+
const entry = this._entries.get(relativePath);
|
|
6057
|
+
if (!entry) {
|
|
6058
|
+
this._misses++;
|
|
6059
|
+
return null;
|
|
6060
|
+
}
|
|
6061
|
+
if (entry.contentHash !== contentHash) {
|
|
6062
|
+
this._entries.delete(relativePath);
|
|
6063
|
+
this._dirty = true;
|
|
6064
|
+
this._misses++;
|
|
6065
|
+
return null;
|
|
6066
|
+
}
|
|
6067
|
+
if (entry.engineVersion !== ENGINE_VERSION) {
|
|
6068
|
+
this._entries.delete(relativePath);
|
|
6069
|
+
this._dirty = true;
|
|
6070
|
+
this._misses++;
|
|
6071
|
+
return null;
|
|
6072
|
+
}
|
|
6073
|
+
if (entry.confidenceThreshold !== confidenceThreshold) {
|
|
6074
|
+
this._entries.delete(relativePath);
|
|
6075
|
+
this._dirty = true;
|
|
6076
|
+
this._misses++;
|
|
6077
|
+
return null;
|
|
6078
|
+
}
|
|
6079
|
+
if (Date.now() - entry.cachedAt > CACHE_TTL_MS2) {
|
|
6080
|
+
this._entries.delete(relativePath);
|
|
6081
|
+
this._dirty = true;
|
|
6082
|
+
this._misses++;
|
|
6083
|
+
return null;
|
|
6084
|
+
}
|
|
6085
|
+
this._hits++;
|
|
6086
|
+
return entry;
|
|
6087
|
+
}
|
|
6088
|
+
/**
|
|
6089
|
+
* Store scan result in cache.
|
|
6090
|
+
*/
|
|
6091
|
+
set(relativePath, contentHash, findings, confidenceThreshold, fileSizeBytes, scanDurationMs) {
|
|
6092
|
+
const entry = {
|
|
6093
|
+
file: relativePath,
|
|
6094
|
+
contentHash,
|
|
6095
|
+
findings,
|
|
6096
|
+
cachedAt: Date.now(),
|
|
6097
|
+
engineVersion: ENGINE_VERSION,
|
|
6098
|
+
confidenceThreshold,
|
|
6099
|
+
fileSizeBytes,
|
|
6100
|
+
scanDurationMs
|
|
6101
|
+
};
|
|
6102
|
+
this._entries.set(relativePath, entry);
|
|
6103
|
+
this._dirty = true;
|
|
6104
|
+
}
|
|
6105
|
+
/**
|
|
6106
|
+
* Invalidate a specific file (e.g., when user edits it).
|
|
6107
|
+
*/
|
|
6108
|
+
invalidate(relativePath) {
|
|
6109
|
+
if (this._entries.delete(relativePath)) {
|
|
6110
|
+
this._dirty = true;
|
|
6111
|
+
}
|
|
6112
|
+
}
|
|
6113
|
+
/**
|
|
6114
|
+
* Clear entire cache.
|
|
6115
|
+
*/
|
|
6116
|
+
clear() {
|
|
6117
|
+
this._entries.clear();
|
|
6118
|
+
this._dirty = true;
|
|
6119
|
+
this._hits = 0;
|
|
6120
|
+
this._misses = 0;
|
|
6121
|
+
}
|
|
6122
|
+
/**
|
|
6123
|
+
* Persist cache to disk. Only writes if dirty.
|
|
6124
|
+
*/
|
|
6125
|
+
async save() {
|
|
6126
|
+
if (!this._dirty) return;
|
|
6127
|
+
try {
|
|
6128
|
+
const cacheDir = path2.dirname(this._cachePath);
|
|
6129
|
+
if (!fs2.existsSync(cacheDir)) {
|
|
6130
|
+
await fsp.mkdir(cacheDir, { recursive: true });
|
|
6131
|
+
}
|
|
6132
|
+
this._metadata.totalEntries = this._entries.size;
|
|
6133
|
+
this._metadata.lastPruned = Date.now();
|
|
6134
|
+
const data = {
|
|
6135
|
+
metadata: this._metadata,
|
|
6136
|
+
entries: Object.fromEntries(this._entries)
|
|
6137
|
+
};
|
|
6138
|
+
const json = JSON.stringify(data, null, 2);
|
|
6139
|
+
this._metadata.totalSizeBytes = Buffer.byteLength(json, "utf-8");
|
|
6140
|
+
if (this._metadata.totalSizeBytes > MAX_CACHE_SIZE_BYTES) {
|
|
6141
|
+
this._prune();
|
|
6142
|
+
const prunedData = {
|
|
6143
|
+
metadata: this._metadata,
|
|
6144
|
+
entries: Object.fromEntries(this._entries)
|
|
6145
|
+
};
|
|
6146
|
+
await fsp.writeFile(this._cachePath, JSON.stringify(prunedData, null, 2), "utf-8");
|
|
6147
|
+
} else {
|
|
6148
|
+
await fsp.writeFile(this._cachePath, json, "utf-8");
|
|
6149
|
+
}
|
|
6150
|
+
this._dirty = false;
|
|
6151
|
+
} catch (err) {
|
|
6152
|
+
process.stderr.write(`[vibecheck] Cache write failed: ${err.message}
|
|
6153
|
+
`);
|
|
6154
|
+
}
|
|
6155
|
+
}
|
|
6156
|
+
/**
|
|
6157
|
+
* Get cache statistics.
|
|
6158
|
+
*/
|
|
6159
|
+
getStats() {
|
|
6160
|
+
const total = this._hits + this._misses;
|
|
6161
|
+
const hitRate = total > 0 ? this._hits / total : 0;
|
|
6162
|
+
let oldestAge = 0;
|
|
6163
|
+
let newestAge = Infinity;
|
|
6164
|
+
const now = Date.now();
|
|
6165
|
+
for (const entry of this._entries.values()) {
|
|
6166
|
+
const age = now - entry.cachedAt;
|
|
6167
|
+
if (age > oldestAge) oldestAge = age;
|
|
6168
|
+
if (age < newestAge) newestAge = age;
|
|
6169
|
+
}
|
|
6170
|
+
return {
|
|
6171
|
+
hits: this._hits,
|
|
6172
|
+
misses: this._misses,
|
|
6173
|
+
hitRate,
|
|
6174
|
+
totalEntries: this._entries.size,
|
|
6175
|
+
cacheSizeBytes: this._metadata.totalSizeBytes,
|
|
6176
|
+
oldestEntryAge: oldestAge,
|
|
6177
|
+
newestEntryAge: newestAge === Infinity ? 0 : newestAge
|
|
6178
|
+
};
|
|
6179
|
+
}
|
|
6180
|
+
/**
|
|
6181
|
+
* Prune old entries to keep cache size under limit.
|
|
6182
|
+
* Removes oldest entries first (LRU-style).
|
|
6183
|
+
*/
|
|
6184
|
+
_prune() {
|
|
6185
|
+
const now = Date.now();
|
|
6186
|
+
const entries = [...this._entries.entries()];
|
|
6187
|
+
for (const [key, entry] of entries) {
|
|
6188
|
+
if (now - entry.cachedAt > CACHE_TTL_MS2) {
|
|
6189
|
+
this._entries.delete(key);
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
const remaining = [...this._entries.entries()];
|
|
6193
|
+
remaining.sort((a, b) => a[1].cachedAt - b[1].cachedAt);
|
|
6194
|
+
const avgEntrySize = 2048;
|
|
6195
|
+
const maxEntries = Math.floor(MAX_CACHE_SIZE_BYTES / avgEntrySize);
|
|
6196
|
+
if (remaining.length > maxEntries) {
|
|
6197
|
+
const toRemove = remaining.length - maxEntries;
|
|
6198
|
+
for (let i = 0; i < toRemove; i++) {
|
|
6199
|
+
this._entries.delete(remaining[i][0]);
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
this._metadata.lastPruned = now;
|
|
6203
|
+
this._dirty = true;
|
|
6204
|
+
}
|
|
6205
|
+
};
|
|
6206
|
+
|
|
6207
|
+
// src/cache/ChangeDetector.ts
|
|
6208
|
+
var fs3 = __toESM(require("fs"));
|
|
6209
|
+
var fsp2 = __toESM(require("fs/promises"));
|
|
6210
|
+
var path3 = __toESM(require("path"));
|
|
6211
|
+
var import_child_process = require("child_process");
|
|
6212
|
+
var import_util = require("util");
|
|
6213
|
+
var execFileAsync = (0, import_util.promisify)(import_child_process.execFile);
|
|
6214
|
+
var ChangeDetector = class {
|
|
6215
|
+
static {
|
|
6216
|
+
__name(this, "ChangeDetector");
|
|
6217
|
+
}
|
|
6218
|
+
_workspaceRoot;
|
|
6219
|
+
constructor(workspaceRoot) {
|
|
6220
|
+
this._workspaceRoot = workspaceRoot;
|
|
6221
|
+
}
|
|
6222
|
+
/**
|
|
6223
|
+
* Detect changed files using best available strategy.
|
|
6224
|
+
*/
|
|
6225
|
+
async detect(options) {
|
|
6226
|
+
const { allFiles, lastScanTime, forceFull } = options;
|
|
6227
|
+
if (forceFull) {
|
|
6228
|
+
return {
|
|
6229
|
+
changedFiles: new Set(allFiles),
|
|
6230
|
+
allFiles,
|
|
6231
|
+
strategy: "full"
|
|
6232
|
+
};
|
|
6233
|
+
}
|
|
6234
|
+
if (!lastScanTime) {
|
|
6235
|
+
return {
|
|
6236
|
+
changedFiles: new Set(allFiles),
|
|
6237
|
+
allFiles,
|
|
6238
|
+
strategy: "full"
|
|
6239
|
+
};
|
|
6240
|
+
}
|
|
6241
|
+
const gitResult = await this._detectViaGit(allFiles, lastScanTime);
|
|
6242
|
+
if (gitResult) return gitResult;
|
|
6243
|
+
const mtimeResult = await this._detectViaMtime(allFiles, lastScanTime);
|
|
6244
|
+
return mtimeResult;
|
|
6245
|
+
}
|
|
6246
|
+
/**
|
|
6247
|
+
* Git-based change detection.
|
|
6248
|
+
* Returns files changed since last scan timestamp.
|
|
6249
|
+
*/
|
|
6250
|
+
async _detectViaGit(allFiles, lastScanTime) {
|
|
6251
|
+
try {
|
|
6252
|
+
const { stdout: gitRoot } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
6253
|
+
cwd: this._workspaceRoot,
|
|
6254
|
+
timeout: 2e3
|
|
6255
|
+
});
|
|
6256
|
+
if (!gitRoot.trim()) return null;
|
|
6257
|
+
const sinceDate = new Date(lastScanTime).toISOString();
|
|
6258
|
+
const { stdout: diffOutput } = await execFileAsync(
|
|
6259
|
+
"git",
|
|
6260
|
+
["diff", "--name-only", `--since=${sinceDate}`, "HEAD"],
|
|
6261
|
+
{
|
|
6262
|
+
cwd: this._workspaceRoot,
|
|
6263
|
+
timeout: 5e3
|
|
6264
|
+
}
|
|
6265
|
+
);
|
|
6266
|
+
const { stdout: statusOutput } = await execFileAsync(
|
|
6267
|
+
"git",
|
|
6268
|
+
["status", "--porcelain", "--untracked-files=all"],
|
|
6269
|
+
{
|
|
6270
|
+
cwd: this._workspaceRoot,
|
|
6271
|
+
timeout: 5e3
|
|
6272
|
+
}
|
|
6273
|
+
);
|
|
6274
|
+
const changedPaths = /* @__PURE__ */ new Set();
|
|
6275
|
+
for (const line of diffOutput.split("\n")) {
|
|
6276
|
+
const trimmed = line.trim();
|
|
6277
|
+
if (trimmed) {
|
|
6278
|
+
const absPath = path3.resolve(this._workspaceRoot, trimmed);
|
|
6279
|
+
changedPaths.add(absPath);
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
for (const line of statusOutput.split("\n")) {
|
|
6283
|
+
const trimmed = line.trim();
|
|
6284
|
+
if (!trimmed) continue;
|
|
6285
|
+
const filename = trimmed.slice(3);
|
|
6286
|
+
if (filename) {
|
|
6287
|
+
const absPath = path3.resolve(this._workspaceRoot, filename);
|
|
6288
|
+
changedPaths.add(absPath);
|
|
6289
|
+
}
|
|
6290
|
+
}
|
|
6291
|
+
const allFilesSet = new Set(allFiles);
|
|
6292
|
+
const changedFiles = new Set(
|
|
6293
|
+
[...changedPaths].filter((f) => allFilesSet.has(f))
|
|
6294
|
+
);
|
|
6295
|
+
if (changedFiles.size === 0) {
|
|
6296
|
+
const newFiles = allFiles.filter((f) => {
|
|
6297
|
+
try {
|
|
6298
|
+
const stat4 = fs3.statSync(f);
|
|
6299
|
+
return stat4.mtimeMs > lastScanTime;
|
|
6300
|
+
} catch {
|
|
6301
|
+
return false;
|
|
6302
|
+
}
|
|
6303
|
+
});
|
|
6304
|
+
for (const f of newFiles) changedFiles.add(f);
|
|
6305
|
+
}
|
|
6306
|
+
return {
|
|
6307
|
+
changedFiles,
|
|
6308
|
+
allFiles,
|
|
6309
|
+
strategy: "git-diff",
|
|
6310
|
+
lastScanTime
|
|
6311
|
+
};
|
|
6312
|
+
} catch (err) {
|
|
6313
|
+
return null;
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
/**
|
|
6317
|
+
* Mtime-based change detection (fallback).
|
|
6318
|
+
* Returns files modified after last scan timestamp.
|
|
6319
|
+
*/
|
|
6320
|
+
async _detectViaMtime(allFiles, lastScanTime) {
|
|
6321
|
+
const changedFiles = /* @__PURE__ */ new Set();
|
|
6322
|
+
await Promise.all(
|
|
6323
|
+
allFiles.map(async (file) => {
|
|
6324
|
+
try {
|
|
6325
|
+
const stat4 = await fsp2.stat(file);
|
|
6326
|
+
if (stat4.mtimeMs > lastScanTime) {
|
|
6327
|
+
changedFiles.add(file);
|
|
6328
|
+
}
|
|
6329
|
+
} catch {
|
|
6330
|
+
}
|
|
6331
|
+
})
|
|
6332
|
+
);
|
|
6333
|
+
return {
|
|
6334
|
+
changedFiles,
|
|
6335
|
+
allFiles,
|
|
6336
|
+
strategy: "mtime",
|
|
6337
|
+
lastScanTime
|
|
6338
|
+
};
|
|
6339
|
+
}
|
|
6340
|
+
/**
|
|
6341
|
+
* Get list of files changed in git working directory (staged + unstaged).
|
|
6342
|
+
* Used for `vibecheck scan staged` and watch mode.
|
|
6343
|
+
*/
|
|
6344
|
+
async getGitChangedFiles() {
|
|
6345
|
+
try {
|
|
6346
|
+
const { stdout } = await execFileAsync(
|
|
6347
|
+
"git",
|
|
6348
|
+
["status", "--porcelain", "--untracked-files=all"],
|
|
6349
|
+
{
|
|
6350
|
+
cwd: this._workspaceRoot,
|
|
6351
|
+
timeout: 5e3
|
|
6352
|
+
}
|
|
6353
|
+
);
|
|
6354
|
+
const files = [];
|
|
6355
|
+
for (const line of stdout.split("\n")) {
|
|
6356
|
+
const trimmed = line.trim();
|
|
6357
|
+
if (!trimmed) continue;
|
|
6358
|
+
const filename = trimmed.slice(3);
|
|
6359
|
+
if (filename) {
|
|
6360
|
+
const absPath = path3.resolve(this._workspaceRoot, filename);
|
|
6361
|
+
files.push(absPath);
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
return files;
|
|
6365
|
+
} catch {
|
|
6366
|
+
return [];
|
|
6367
|
+
}
|
|
6368
|
+
}
|
|
6369
|
+
/**
|
|
6370
|
+
* Get list of staged files only.
|
|
6371
|
+
*/
|
|
6372
|
+
async getGitStagedFiles() {
|
|
6373
|
+
try {
|
|
6374
|
+
const { stdout } = await execFileAsync(
|
|
6375
|
+
"git",
|
|
6376
|
+
["diff", "--cached", "--name-only"],
|
|
6377
|
+
{
|
|
6378
|
+
cwd: this._workspaceRoot,
|
|
6379
|
+
timeout: 5e3
|
|
6380
|
+
}
|
|
6381
|
+
);
|
|
6382
|
+
const files = [];
|
|
6383
|
+
for (const line of stdout.split("\n")) {
|
|
6384
|
+
const trimmed = line.trim();
|
|
6385
|
+
if (trimmed) {
|
|
6386
|
+
const absPath = path3.resolve(this._workspaceRoot, trimmed);
|
|
6387
|
+
files.push(absPath);
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6390
|
+
return files;
|
|
6391
|
+
} catch {
|
|
6392
|
+
return [];
|
|
6393
|
+
}
|
|
6394
|
+
}
|
|
6395
|
+
};
|
|
6396
|
+
async function saveLastScanTime(workspaceRoot) {
|
|
6397
|
+
const timestampFile = path3.join(workspaceRoot, ".vibecheck", "last-scan.txt");
|
|
6398
|
+
const cacheDir = path3.dirname(timestampFile);
|
|
6399
|
+
try {
|
|
6400
|
+
if (!fs3.existsSync(cacheDir)) {
|
|
6401
|
+
await fsp2.mkdir(cacheDir, { recursive: true });
|
|
6402
|
+
}
|
|
6403
|
+
await fsp2.writeFile(timestampFile, Date.now().toString(), "utf-8");
|
|
6404
|
+
} catch {
|
|
6405
|
+
}
|
|
6406
|
+
}
|
|
6407
|
+
__name(saveLastScanTime, "saveLastScanTime");
|
|
6408
|
+
async function loadLastScanTime(workspaceRoot) {
|
|
6409
|
+
const timestampFile = path3.join(workspaceRoot, ".vibecheck", "last-scan.txt");
|
|
6410
|
+
try {
|
|
6411
|
+
if (!fs3.existsSync(timestampFile)) return void 0;
|
|
6412
|
+
const content = await fsp2.readFile(timestampFile, "utf-8");
|
|
6413
|
+
const timestamp = parseInt(content.trim(), 10);
|
|
6414
|
+
return isNaN(timestamp) ? void 0 : timestamp;
|
|
6415
|
+
} catch {
|
|
6416
|
+
return void 0;
|
|
6417
|
+
}
|
|
6418
|
+
}
|
|
6419
|
+
__name(loadLastScanTime, "loadLastScanTime");
|
|
6420
|
+
|
|
6421
|
+
// src/cache/PerformanceMetrics.ts
|
|
6422
|
+
var fs4 = __toESM(require("fs"));
|
|
6423
|
+
var fsp3 = __toESM(require("fs/promises"));
|
|
6424
|
+
var path4 = __toESM(require("path"));
|
|
6425
|
+
var PerformanceTracker = class {
|
|
6426
|
+
static {
|
|
6427
|
+
__name(this, "PerformanceTracker");
|
|
6428
|
+
}
|
|
6429
|
+
_startTime = 0;
|
|
6430
|
+
_discoveryStartTime = 0;
|
|
6431
|
+
_discoveryEndTime = 0;
|
|
6432
|
+
_scanStartTime = 0;
|
|
6433
|
+
_scanEndTime = 0;
|
|
6434
|
+
_workspaceRoot;
|
|
6435
|
+
_historyPath;
|
|
6436
|
+
constructor(workspaceRoot) {
|
|
6437
|
+
this._workspaceRoot = workspaceRoot;
|
|
6438
|
+
this._historyPath = path4.join(workspaceRoot, ".vibecheck", "perf-history.json");
|
|
6439
|
+
}
|
|
6440
|
+
/**
|
|
6441
|
+
* Mark CLI startup complete.
|
|
6442
|
+
*/
|
|
6443
|
+
markStartup() {
|
|
6444
|
+
this._startTime = performance.now();
|
|
6445
|
+
}
|
|
6446
|
+
/**
|
|
6447
|
+
* Mark discovery phase start.
|
|
6448
|
+
*/
|
|
6449
|
+
markDiscoveryStart() {
|
|
6450
|
+
this._discoveryStartTime = performance.now();
|
|
6451
|
+
}
|
|
6452
|
+
/**
|
|
6453
|
+
* Mark discovery phase end.
|
|
6454
|
+
*/
|
|
6455
|
+
markDiscoveryEnd() {
|
|
6456
|
+
this._discoveryEndTime = performance.now();
|
|
6457
|
+
}
|
|
6458
|
+
/**
|
|
6459
|
+
* Mark scan phase start.
|
|
6460
|
+
*/
|
|
6461
|
+
markScanStart() {
|
|
6462
|
+
this._scanStartTime = performance.now();
|
|
6463
|
+
}
|
|
6464
|
+
/**
|
|
6465
|
+
* Mark scan phase end.
|
|
6466
|
+
*/
|
|
6467
|
+
markScanEnd() {
|
|
6468
|
+
this._scanEndTime = performance.now();
|
|
6469
|
+
}
|
|
6470
|
+
/**
|
|
6471
|
+
* Create performance snapshot from current metrics.
|
|
6472
|
+
*/
|
|
6473
|
+
createSnapshot(filesScanned, cacheHits, cacheMisses, engineLatencies) {
|
|
6474
|
+
const now = performance.now();
|
|
6475
|
+
const startupMs = this._discoveryStartTime - this._startTime;
|
|
6476
|
+
const discoveryMs = this._discoveryEndTime - this._discoveryStartTime;
|
|
6477
|
+
const totalScanMs = this._scanEndTime - this._scanStartTime;
|
|
6478
|
+
const throughput = totalScanMs > 0 ? filesScanned / totalScanMs * 1e3 : 0;
|
|
6479
|
+
const cacheTotal = cacheHits + cacheMisses;
|
|
6480
|
+
const cacheHitRate = cacheTotal > 0 ? cacheHits / cacheTotal : 0;
|
|
6481
|
+
const memoryUsageMB = process.memoryUsage().heapUsed / 1024 / 1024;
|
|
6482
|
+
return {
|
|
6483
|
+
timestamp: Date.now(),
|
|
6484
|
+
startupMs: Math.round(startupMs),
|
|
6485
|
+
discoveryMs: Math.round(discoveryMs),
|
|
6486
|
+
totalScanMs: Math.round(totalScanMs),
|
|
6487
|
+
filesScanned,
|
|
6488
|
+
throughput: Math.round(throughput * 100) / 100,
|
|
6489
|
+
cacheHitRate: Math.round(cacheHitRate * 100) / 100,
|
|
6490
|
+
cacheHits,
|
|
6491
|
+
cacheMisses,
|
|
6492
|
+
engineLatencies,
|
|
6493
|
+
memoryUsageMB: Math.round(memoryUsageMB * 100) / 100
|
|
6494
|
+
};
|
|
6495
|
+
}
|
|
6496
|
+
/**
|
|
6497
|
+
* Save snapshot to performance history.
|
|
6498
|
+
*/
|
|
6499
|
+
async saveSnapshot(snapshot) {
|
|
6500
|
+
try {
|
|
6501
|
+
const cacheDir = path4.dirname(this._historyPath);
|
|
6502
|
+
if (!fs4.existsSync(cacheDir)) {
|
|
6503
|
+
await fsp3.mkdir(cacheDir, { recursive: true });
|
|
6504
|
+
}
|
|
6505
|
+
let history;
|
|
6506
|
+
if (fs4.existsSync(this._historyPath)) {
|
|
6507
|
+
const raw = await fsp3.readFile(this._historyPath, "utf-8");
|
|
6508
|
+
history = JSON.parse(raw);
|
|
6509
|
+
} else {
|
|
6510
|
+
history = { snapshots: [], maxSnapshots: 10 };
|
|
6511
|
+
}
|
|
6512
|
+
history.snapshots.push(snapshot);
|
|
6513
|
+
if (history.snapshots.length > history.maxSnapshots) {
|
|
6514
|
+
history.snapshots = history.snapshots.slice(-history.maxSnapshots);
|
|
6515
|
+
}
|
|
6516
|
+
await fsp3.writeFile(this._historyPath, JSON.stringify(history, null, 2), "utf-8");
|
|
6517
|
+
} catch {
|
|
6518
|
+
}
|
|
6519
|
+
}
|
|
6520
|
+
/**
|
|
6521
|
+
* Load performance history from disk.
|
|
6522
|
+
*/
|
|
6523
|
+
async loadHistory() {
|
|
6524
|
+
try {
|
|
6525
|
+
if (!fs4.existsSync(this._historyPath)) return null;
|
|
6526
|
+
const raw = await fsp3.readFile(this._historyPath, "utf-8");
|
|
6527
|
+
return JSON.parse(raw);
|
|
6528
|
+
} catch {
|
|
6529
|
+
return null;
|
|
6530
|
+
}
|
|
6531
|
+
}
|
|
6532
|
+
/**
|
|
6533
|
+
* Get performance trend (last N runs).
|
|
6534
|
+
*/
|
|
6535
|
+
async getTrend(metric, count = 5) {
|
|
6536
|
+
const history = await this.loadHistory();
|
|
6537
|
+
if (!history) return [];
|
|
6538
|
+
return history.snapshots.slice(-count).map((s) => s[metric]).filter((v) => typeof v === "number");
|
|
6539
|
+
}
|
|
6540
|
+
/**
|
|
6541
|
+
* Detect performance regression.
|
|
6542
|
+
* Returns true if latest run is significantly slower than average.
|
|
6543
|
+
*/
|
|
6544
|
+
async detectRegression(threshold = 0.2) {
|
|
6545
|
+
const trend = await this.getTrend("totalScanMs", 5);
|
|
6546
|
+
if (trend.length < 3) return false;
|
|
6547
|
+
const latest = trend[trend.length - 1];
|
|
6548
|
+
const previous = trend.slice(0, -1);
|
|
6549
|
+
const avg = previous.reduce((sum, v) => sum + v, 0) / previous.length;
|
|
6550
|
+
return latest > avg * (1 + threshold);
|
|
6551
|
+
}
|
|
6552
|
+
};
|
|
6553
|
+
|
|
6554
|
+
// src/runner/FileRunner.ts
|
|
5997
6555
|
var import_engines2 = require("@vibecheck/engines");
|
|
5998
6556
|
var DEFAULT_ENGINE_THRESHOLDS = {
|
|
5999
6557
|
env_var: 0.72,
|
|
@@ -6023,16 +6581,16 @@ var IgnoreFilter = class _IgnoreFilter {
|
|
|
6023
6581
|
_cache = /* @__PURE__ */ new Map();
|
|
6024
6582
|
static _CACHE_MAX = 4096;
|
|
6025
6583
|
constructor(workspaceRoot, ignoreFile, respectGitignore = true) {
|
|
6026
|
-
const vcIgnorePath = ignoreFile ??
|
|
6584
|
+
const vcIgnorePath = ignoreFile ?? path5.join(workspaceRoot, ".vibecheckignore");
|
|
6027
6585
|
this._loadFile(vcIgnorePath);
|
|
6028
6586
|
if (respectGitignore) {
|
|
6029
|
-
this._loadFile(
|
|
6587
|
+
this._loadFile(path5.join(workspaceRoot, ".gitignore"));
|
|
6030
6588
|
}
|
|
6031
6589
|
}
|
|
6032
6590
|
_loadFile(filePath) {
|
|
6033
6591
|
try {
|
|
6034
|
-
if (!
|
|
6035
|
-
const content =
|
|
6592
|
+
if (!fs5.existsSync(filePath)) return;
|
|
6593
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
6036
6594
|
for (const raw of content.split("\n")) {
|
|
6037
6595
|
const line = raw.replace(/#.*$/, "").trim();
|
|
6038
6596
|
if (!line) continue;
|
|
@@ -6124,11 +6682,11 @@ async function discoverFiles2(targets, workspaceRoot, filter, signal) {
|
|
|
6124
6682
|
for (const target of targets) {
|
|
6125
6683
|
if (signal?.aborted) break;
|
|
6126
6684
|
try {
|
|
6127
|
-
const
|
|
6128
|
-
if (
|
|
6685
|
+
const stat4 = await fsp4.stat(target);
|
|
6686
|
+
if (stat4.isDirectory()) {
|
|
6129
6687
|
dirsToScan.push(target);
|
|
6130
|
-
} else if (
|
|
6131
|
-
const rel =
|
|
6688
|
+
} else if (stat4.isFile() && CHECKED_EXTS.has(path5.extname(target).toLowerCase())) {
|
|
6689
|
+
const rel = path5.relative(workspaceRoot, target).replace(/\\/g, "/");
|
|
6132
6690
|
if (!filter.isIgnored(rel)) explicitFiles.push(target);
|
|
6133
6691
|
}
|
|
6134
6692
|
} catch (err) {
|
|
@@ -6145,7 +6703,7 @@ async function discoverFiles2(targets, workspaceRoot, filter, signal) {
|
|
|
6145
6703
|
rootDir: workspaceRoot
|
|
6146
6704
|
});
|
|
6147
6705
|
return result.files.filter((f) => {
|
|
6148
|
-
const rel =
|
|
6706
|
+
const rel = path5.relative(workspaceRoot, f).replace(/\\/g, "/");
|
|
6149
6707
|
return !filter.isIgnored(rel);
|
|
6150
6708
|
});
|
|
6151
6709
|
}
|
|
@@ -6173,14 +6731,14 @@ async function discoverFiles2(targets, workspaceRoot, filter, signal) {
|
|
|
6173
6731
|
discoveredFiles.sort();
|
|
6174
6732
|
}
|
|
6175
6733
|
const filtered = discoveredFiles.filter((f) => {
|
|
6176
|
-
const rel =
|
|
6734
|
+
const rel = path5.relative(workspaceRoot, f).replace(/\\/g, "/");
|
|
6177
6735
|
return !filter.isIgnored(rel);
|
|
6178
6736
|
});
|
|
6179
6737
|
return [.../* @__PURE__ */ new Set([...explicitFiles, ...filtered])];
|
|
6180
6738
|
}
|
|
6181
6739
|
__name(discoverFiles2, "discoverFiles");
|
|
6182
6740
|
function makeDelta(filePath, text) {
|
|
6183
|
-
const ext =
|
|
6741
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
6184
6742
|
const lines = text.split("\n");
|
|
6185
6743
|
return {
|
|
6186
6744
|
documentUri: filePath,
|
|
@@ -6309,7 +6867,11 @@ async function runOnFiles(targets, options) {
|
|
|
6309
6867
|
files: explicitFiles,
|
|
6310
6868
|
allowlist = {},
|
|
6311
6869
|
engineToggles = null,
|
|
6312
|
-
suppressRules = []
|
|
6870
|
+
suppressRules = [],
|
|
6871
|
+
enableCache = true,
|
|
6872
|
+
enableIncremental = true,
|
|
6873
|
+
clearCache = false,
|
|
6874
|
+
trackPerformance = false
|
|
6313
6875
|
} = options;
|
|
6314
6876
|
const suppressRulesSet = new Set(suppressRules.map((r) => r.toUpperCase()));
|
|
6315
6877
|
const getThreshold = /* @__PURE__ */ __name((engineId) => engineConfidenceThresholds[engineId] ?? DEFAULT_ENGINE_THRESHOLDS[engineId] ?? confidenceThreshold, "getThreshold");
|
|
@@ -6332,6 +6894,15 @@ async function runOnFiles(targets, options) {
|
|
|
6332
6894
|
signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
6333
6895
|
}
|
|
6334
6896
|
}
|
|
6897
|
+
const scanCache = enableCache ? new ScanCache(workspaceRoot) : null;
|
|
6898
|
+
const changeDetector = enableIncremental ? new ChangeDetector(workspaceRoot) : null;
|
|
6899
|
+
const perfTracker = trackPerformance ? new PerformanceTracker(workspaceRoot) : null;
|
|
6900
|
+
if (scanCache && clearCache) {
|
|
6901
|
+
await scanCache.clear();
|
|
6902
|
+
}
|
|
6903
|
+
if (perfTracker) {
|
|
6904
|
+
perfTracker.markStartup();
|
|
6905
|
+
}
|
|
6335
6906
|
const internalSignal = ac.signal;
|
|
6336
6907
|
(0, import_events.setMaxListeners)(64, internalSignal);
|
|
6337
6908
|
const emitProgress = /* @__PURE__ */ __name((patch) => {
|
|
@@ -6345,13 +6916,31 @@ async function runOnFiles(targets, options) {
|
|
|
6345
6916
|
...patch
|
|
6346
6917
|
});
|
|
6347
6918
|
}, "emitProgress");
|
|
6919
|
+
if (perfTracker) {
|
|
6920
|
+
perfTracker.markDiscoveryStart();
|
|
6921
|
+
}
|
|
6348
6922
|
emitProgress({ phase: "discovery" });
|
|
6349
6923
|
const filter = new IgnoreFilter(workspaceRoot, ignoreFile, respectGitignore);
|
|
6350
|
-
|
|
6351
|
-
const ext =
|
|
6352
|
-
const rel =
|
|
6924
|
+
let files = explicitFiles ? explicitFiles.filter((f) => {
|
|
6925
|
+
const ext = path5.extname(f).toLowerCase();
|
|
6926
|
+
const rel = path5.relative(workspaceRoot, f).replace(/\\/g, "/");
|
|
6353
6927
|
return CHECKED_EXTS.has(ext) && !filter.isIgnored(rel);
|
|
6354
6928
|
}) : await discoverFiles2(targets, workspaceRoot, filter, internalSignal);
|
|
6929
|
+
if (perfTracker) {
|
|
6930
|
+
perfTracker.markDiscoveryEnd();
|
|
6931
|
+
}
|
|
6932
|
+
if (changeDetector && files.length > 0) {
|
|
6933
|
+
const lastScanTime = await loadLastScanTime(workspaceRoot);
|
|
6934
|
+
const changeResult = await changeDetector.detect({
|
|
6935
|
+
workspaceRoot,
|
|
6936
|
+
allFiles: files,
|
|
6937
|
+
lastScanTime,
|
|
6938
|
+
forceFull: false
|
|
6939
|
+
});
|
|
6940
|
+
if (changeResult.strategy !== "full") {
|
|
6941
|
+
files = files.filter((f) => changeResult.changedFiles.has(f));
|
|
6942
|
+
}
|
|
6943
|
+
}
|
|
6355
6944
|
if (internalSignal.aborted) {
|
|
6356
6945
|
return { files: [], summary: buildSummary([], 0, performance.now() - startTime) };
|
|
6357
6946
|
}
|
|
@@ -6362,6 +6951,9 @@ async function runOnFiles(targets, options) {
|
|
|
6362
6951
|
summary: buildSummary([], 0, performance.now() - startTime)
|
|
6363
6952
|
};
|
|
6364
6953
|
}
|
|
6954
|
+
if (perfTracker) {
|
|
6955
|
+
perfTracker.markScanStart();
|
|
6956
|
+
}
|
|
6365
6957
|
emitProgress({ phase: "activating", filesDiscovered: files.length });
|
|
6366
6958
|
const allowlistEnvVars = allowlist.envVars;
|
|
6367
6959
|
const truthpack = await (0, import_engines.loadTruthpack)(workspaceRoot);
|
|
@@ -6375,7 +6967,7 @@ async function runOnFiles(targets, options) {
|
|
|
6375
6967
|
return loader;
|
|
6376
6968
|
})();
|
|
6377
6969
|
const ghostRouteIndex = truthpack ? (0, import_engines.truthpackToRouteIndex)(truthpack.routes, workspaceRoot) : void 0;
|
|
6378
|
-
const sdkMapsDir =
|
|
6970
|
+
const sdkMapsDir = path5.join(__dirname, "..", "engines", "sdk-maps");
|
|
6379
6971
|
const registry = (0, import_engines.createDefaultRegistry)();
|
|
6380
6972
|
registry.register(
|
|
6381
6973
|
new import_engines.EnvVarEngine(envIndex, {
|
|
@@ -6396,7 +6988,7 @@ async function runOnFiles(targets, options) {
|
|
|
6396
6988
|
);
|
|
6397
6989
|
const phantomConfig = {
|
|
6398
6990
|
confidenceThreshold: getThreshold("phantom_dep"),
|
|
6399
|
-
registryCachePath:
|
|
6991
|
+
registryCachePath: path5.join(workspaceRoot, ".vibecheck", "registry-cache.json")
|
|
6400
6992
|
};
|
|
6401
6993
|
registry.register(new import_engines.PhantomDepEngine(workspaceRoot, phantomConfig), {
|
|
6402
6994
|
timeoutMs: options.engineTimeouts?.["phantom-dep"] ?? 100,
|
|
@@ -6443,6 +7035,9 @@ async function runOnFiles(targets, options) {
|
|
|
6443
7035
|
}
|
|
6444
7036
|
let scannedCount = 0;
|
|
6445
7037
|
let findingsCount = 0;
|
|
7038
|
+
let cacheHits = 0;
|
|
7039
|
+
let cacheMisses = 0;
|
|
7040
|
+
const engineLatencyMap = /* @__PURE__ */ new Map();
|
|
6446
7041
|
const fileResults = await mapPool(
|
|
6447
7042
|
files,
|
|
6448
7043
|
concurrency,
|
|
@@ -6450,29 +7045,56 @@ async function runOnFiles(targets, options) {
|
|
|
6450
7045
|
if (internalSignal.aborted) {
|
|
6451
7046
|
return makeSkippedResult(file, workspaceRoot, "Scan aborted");
|
|
6452
7047
|
}
|
|
6453
|
-
let
|
|
7048
|
+
let stat4;
|
|
6454
7049
|
try {
|
|
6455
|
-
|
|
7050
|
+
stat4 = await fsp4.stat(file);
|
|
6456
7051
|
} catch (err) {
|
|
6457
7052
|
return makeSkippedResult(file, workspaceRoot, `Stat error: ${err.message}`);
|
|
6458
7053
|
}
|
|
6459
|
-
if (
|
|
6460
|
-
return makeSkippedResult(file, workspaceRoot, `File too large (${Math.round(
|
|
7054
|
+
if (stat4.size > MAX_FILE_SIZE) {
|
|
7055
|
+
return makeSkippedResult(file, workspaceRoot, `File too large (${Math.round(stat4.size / 1024)}KB > 1MB limit)`);
|
|
6461
7056
|
}
|
|
6462
|
-
if (
|
|
7057
|
+
if (stat4.size === 0) {
|
|
6463
7058
|
return makeSkippedResult(file, workspaceRoot, "Empty file");
|
|
6464
7059
|
}
|
|
6465
7060
|
let text;
|
|
6466
7061
|
try {
|
|
6467
|
-
text = await
|
|
7062
|
+
text = await fsp4.readFile(file, "utf-8");
|
|
6468
7063
|
} catch (err) {
|
|
6469
7064
|
return makeSkippedResult(file, workspaceRoot, `Read error: ${err.message}`);
|
|
6470
7065
|
}
|
|
6471
7066
|
if (text.trim().length === 0) {
|
|
6472
7067
|
return makeSkippedResult(file, workspaceRoot, "Empty file");
|
|
6473
7068
|
}
|
|
7069
|
+
if (scanCache) {
|
|
7070
|
+
const cached = await scanCache.get(file, text, confidenceThreshold);
|
|
7071
|
+
if (cached) {
|
|
7072
|
+
cacheHits++;
|
|
7073
|
+
scannedCount++;
|
|
7074
|
+
findingsCount += cached.findings.length;
|
|
7075
|
+
emitProgress({
|
|
7076
|
+
phase: "scanning",
|
|
7077
|
+
filesDiscovered: files.length,
|
|
7078
|
+
filesScanned: scannedCount,
|
|
7079
|
+
filesTotal: files.length,
|
|
7080
|
+
findingsSoFar: findingsCount,
|
|
7081
|
+
currentFile: path5.relative(workspaceRoot, file).replace(/\\/g, "/")
|
|
7082
|
+
});
|
|
7083
|
+
const rel2 = path5.relative(workspaceRoot, file).replace(/\\/g, "/");
|
|
7084
|
+
return {
|
|
7085
|
+
file,
|
|
7086
|
+
relativePath: rel2,
|
|
7087
|
+
findings: cached.findings,
|
|
7088
|
+
engineMetrics: [],
|
|
7089
|
+
scanDurationMs: 0,
|
|
7090
|
+
fileSizeBytes: stat4.size,
|
|
7091
|
+
skipped: false
|
|
7092
|
+
};
|
|
7093
|
+
}
|
|
7094
|
+
cacheMisses++;
|
|
7095
|
+
}
|
|
6474
7096
|
const delta = makeDelta(file, text);
|
|
6475
|
-
const fileExt =
|
|
7097
|
+
const fileExt = path5.extname(file).toLowerCase();
|
|
6476
7098
|
const fileStart = performance.now();
|
|
6477
7099
|
const applicableSlots = registry.getActive().filter((s) => {
|
|
6478
7100
|
const exts = s.engine.supportedExtensions ?? s.extensions;
|
|
@@ -6505,22 +7127,33 @@ async function runOnFiles(targets, options) {
|
|
|
6505
7127
|
}
|
|
6506
7128
|
scannedCount++;
|
|
6507
7129
|
findingsCount += deduped.length;
|
|
7130
|
+
const scanDurationMs = Math.round(performance.now() - fileStart);
|
|
7131
|
+
if (scanCache) {
|
|
7132
|
+
await scanCache.set(file, text, deduped, confidenceThreshold, stat4.size, scanDurationMs);
|
|
7133
|
+
}
|
|
7134
|
+
for (const metric of metrics) {
|
|
7135
|
+
if (metric.status === "ok") {
|
|
7136
|
+
const latencies = engineLatencyMap.get(metric.engineId) ?? [];
|
|
7137
|
+
latencies.push(metric.durationMs);
|
|
7138
|
+
engineLatencyMap.set(metric.engineId, latencies);
|
|
7139
|
+
}
|
|
7140
|
+
}
|
|
6508
7141
|
emitProgress({
|
|
6509
7142
|
phase: "scanning",
|
|
6510
7143
|
filesDiscovered: files.length,
|
|
6511
7144
|
filesScanned: scannedCount,
|
|
6512
7145
|
filesTotal: files.length,
|
|
6513
7146
|
findingsSoFar: findingsCount,
|
|
6514
|
-
currentFile:
|
|
7147
|
+
currentFile: path5.relative(workspaceRoot, file).replace(/\\/g, "/")
|
|
6515
7148
|
});
|
|
6516
|
-
const rel =
|
|
7149
|
+
const rel = path5.relative(workspaceRoot, file).replace(/\\/g, "/");
|
|
6517
7150
|
return {
|
|
6518
7151
|
file,
|
|
6519
7152
|
relativePath: rel,
|
|
6520
7153
|
findings: deduped,
|
|
6521
7154
|
engineMetrics: metrics,
|
|
6522
|
-
scanDurationMs
|
|
6523
|
-
fileSizeBytes:
|
|
7155
|
+
scanDurationMs,
|
|
7156
|
+
fileSizeBytes: stat4.size,
|
|
6524
7157
|
skipped: false
|
|
6525
7158
|
};
|
|
6526
7159
|
},
|
|
@@ -6530,6 +7163,27 @@ async function runOnFiles(targets, options) {
|
|
|
6530
7163
|
registry.dispose();
|
|
6531
7164
|
const totalMs = performance.now() - startTime;
|
|
6532
7165
|
const summary = buildSummary(fileResults, files.length, totalMs);
|
|
7166
|
+
if (perfTracker) {
|
|
7167
|
+
perfTracker.markScanEnd();
|
|
7168
|
+
const engineLatencies = {};
|
|
7169
|
+
for (const [engineId, latencies] of engineLatencyMap.entries()) {
|
|
7170
|
+
if (latencies.length > 0) {
|
|
7171
|
+
const sorted = [...latencies].sort((a, b) => a - b);
|
|
7172
|
+
const p95Idx = Math.ceil(sorted.length * 0.95) - 1;
|
|
7173
|
+
engineLatencies[engineId] = sorted[Math.max(0, p95Idx)] ?? 0;
|
|
7174
|
+
}
|
|
7175
|
+
}
|
|
7176
|
+
const snapshot = perfTracker.createSnapshot(
|
|
7177
|
+
summary.filesScanned,
|
|
7178
|
+
cacheHits,
|
|
7179
|
+
cacheMisses,
|
|
7180
|
+
engineLatencies
|
|
7181
|
+
);
|
|
7182
|
+
await perfTracker.saveSnapshot(snapshot);
|
|
7183
|
+
}
|
|
7184
|
+
if (changeDetector) {
|
|
7185
|
+
await saveLastScanTime(workspaceRoot);
|
|
7186
|
+
}
|
|
6533
7187
|
emitProgress({
|
|
6534
7188
|
phase: "complete",
|
|
6535
7189
|
filesDiscovered: files.length,
|
|
@@ -6576,7 +7230,7 @@ __name(filterInlineSuppressions, "filterInlineSuppressions");
|
|
|
6576
7230
|
function makeSkippedResult(file, workspaceRoot, reason) {
|
|
6577
7231
|
return {
|
|
6578
7232
|
file,
|
|
6579
|
-
relativePath:
|
|
7233
|
+
relativePath: path5.relative(workspaceRoot, file).replace(/\\/g, "/"),
|
|
6580
7234
|
findings: [],
|
|
6581
7235
|
engineMetrics: [],
|
|
6582
7236
|
scanDurationMs: 0,
|