@lousy-agents/lint 5.15.3 → 5.15.5

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.
Files changed (2) hide show
  1. package/dist/index.js +270 -51
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -566,7 +566,7 @@ module.exports = webpackEmptyAsyncContext;
566
566
 
567
567
 
568
568
  },
569
- 9884(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
569
+ 2749(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
570
570
 
571
571
  // EXPORTS
572
572
  __webpack_require__.d(__webpack_exports__, {
@@ -978,6 +978,7 @@ function hasNonEmptyString(value) {
978
978
 
979
979
 
980
980
 
981
+
981
982
  const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]);
982
983
  const SYMLINK_OPEN_CODES = new Set(["ELOOP", "EINVAL", "ENOTSUP"]);
983
984
  const POSIX_SEPARATOR_CHAR_CODE = 0x2f;
@@ -1177,6 +1178,29 @@ function directory_guard_createNearestExistingSyncDirectoryGuard(rootReal, targe
1177
1178
  return directory_guard_createSyncDirectoryGuard(root);
1178
1179
  }
1179
1180
 
1181
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/fsync.js
1182
+
1183
+
1184
+ async function syncDirectoryBestEffort(dirPath) {
1185
+ if (process.platform === "win32") {
1186
+ return;
1187
+ }
1188
+ let handle;
1189
+ try {
1190
+ const flags = external_node_fs_.constants.O_RDONLY |
1191
+ ("O_DIRECTORY" in external_node_fs_.constants ? external_node_fs_.constants.O_DIRECTORY : 0) |
1192
+ ("O_NOFOLLOW" in external_node_fs_.constants ? external_node_fs_.constants.O_NOFOLLOW : 0);
1193
+ handle = await promises_.open(dirPath, flags);
1194
+ await handle.sync();
1195
+ }
1196
+ catch {
1197
+ // Some filesystems reject directory handles; keep the write usable there.
1198
+ }
1199
+ finally {
1200
+ await handle?.close().catch(() => undefined);
1201
+ }
1202
+ }
1203
+
1180
1204
  ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js
1181
1205
 
1182
1206
 
@@ -2275,6 +2299,7 @@ async function runPinnedPathHelper(params) {
2275
2299
 
2276
2300
 
2277
2301
 
2302
+
2278
2303
  function byteLength(input, encoding) {
2279
2304
  return typeof input === "string"
2280
2305
  ? Buffer.byteLength(input, encoding ?? "utf8")
@@ -2467,11 +2492,13 @@ async function runPinnedWriteFallback(params) {
2467
2492
  throw new errors_FsSafeError("path-mismatch", "fallback temp path changed during write");
2468
2493
  }
2469
2494
  const expectedTempStat = tempStat;
2495
+ await handle.sync();
2470
2496
  await handle.close().catch(() => undefined);
2471
2497
  handle = undefined;
2472
2498
  await withAsyncDirectoryGuards([parentGuard], async () => {
2473
2499
  await promises_.rename(tempPath, targetPath);
2474
2500
  renamed = true;
2501
+ await syncDirectoryBestEffort(parentPath);
2475
2502
  targetStat = await promises_.lstat(targetPath);
2476
2503
  if (targetStat.isSymbolicLink() || !file_identity_sameFileIdentity(targetStat, expectedTempStat)) {
2477
2504
  throw new errors_FsSafeError("path-mismatch", "fallback target changed during write");
@@ -3145,6 +3172,197 @@ function path_policy_shortPath(value) {
3145
3172
  return value;
3146
3173
  }
3147
3174
 
3175
+ // EXTERNAL MODULE: external "node:url"
3176
+ var external_node_url_ = __webpack_require__(3136);
3177
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/local-file-access.js
3178
+
3179
+
3180
+
3181
+ const ENCODED_FILE_URL_SEPARATOR_RE = /%(?:2f|5c)/i;
3182
+ function isLocalFileUrlHost(hostname) {
3183
+ const normalized = normalizeLowercaseStringOrEmpty(hostname);
3184
+ return normalized === "" || normalized === "localhost";
3185
+ }
3186
+ function hasEncodedFileUrlSeparator(pathname) {
3187
+ return ENCODED_FILE_URL_SEPARATOR_RE.test(pathname);
3188
+ }
3189
+ function isWindowsNetworkPath(filePath, platform = process.platform) {
3190
+ if (platform !== "win32") {
3191
+ return false;
3192
+ }
3193
+ const normalized = filePath.replace(/\//g, "\\");
3194
+ return normalized.startsWith("\\\\?\\UNC\\") || normalized.startsWith("\\\\");
3195
+ }
3196
+ function isWindowsDriveLetterPath(filePath, platform = process.platform) {
3197
+ return platform === "win32" && /^[A-Za-z]:[\\/]/.test(filePath);
3198
+ }
3199
+ function assertNoWindowsNetworkPath(filePath, label = "Path") {
3200
+ if (isWindowsNetworkPath(filePath)) {
3201
+ throw new Error(`${label} cannot use Windows network paths: ${filePath}`);
3202
+ }
3203
+ }
3204
+ function safeFileURLToPath(fileUrl) {
3205
+ let parsed;
3206
+ try {
3207
+ parsed = new external_node_url_.URL(fileUrl);
3208
+ }
3209
+ catch {
3210
+ throw new Error(`Invalid file:// URL: ${fileUrl}`);
3211
+ }
3212
+ if (parsed.protocol !== "file:") {
3213
+ throw new Error(`Invalid file:// URL: ${fileUrl}`);
3214
+ }
3215
+ if (!isLocalFileUrlHost(parsed.hostname)) {
3216
+ throw new Error(`file:// URLs with remote hosts are not allowed: ${fileUrl}`);
3217
+ }
3218
+ if (hasEncodedFileUrlSeparator(parsed.pathname)) {
3219
+ throw new Error(`file:// URLs cannot encode path separators: ${fileUrl}`);
3220
+ }
3221
+ const filePath = (0,external_node_url_.fileURLToPath)(parsed);
3222
+ assertNoWindowsNetworkPath(filePath, "Local file URL");
3223
+ return filePath;
3224
+ }
3225
+ function trySafeFileURLToPath(fileUrl) {
3226
+ try {
3227
+ return safeFileURLToPath(fileUrl);
3228
+ }
3229
+ catch {
3230
+ return undefined;
3231
+ }
3232
+ }
3233
+ function basenameFromMediaSource(source) {
3234
+ if (!source) {
3235
+ return undefined;
3236
+ }
3237
+ if (source.startsWith("file://")) {
3238
+ const filePath = trySafeFileURLToPath(source);
3239
+ return filePath ? path.basename(filePath) || undefined : undefined;
3240
+ }
3241
+ if (/^https?:\/\//i.test(source)) {
3242
+ try {
3243
+ return path.basename(new URL(source).pathname) || undefined;
3244
+ }
3245
+ catch {
3246
+ return undefined;
3247
+ }
3248
+ }
3249
+ return path.basename(source) || undefined;
3250
+ }
3251
+
3252
+ ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/device-path.js
3253
+
3254
+
3255
+
3256
+ const POSIX_BLOCKED_DEVICE_PATHS = new Set([
3257
+ "/dev/zero",
3258
+ "/dev/random",
3259
+ "/dev/urandom",
3260
+ "/dev/full",
3261
+ "/dev/stdin",
3262
+ "/dev/stdout",
3263
+ "/dev/stderr",
3264
+ "/dev/tty",
3265
+ "/dev/console",
3266
+ ]);
3267
+ const WINDOWS_RESERVED_DEVICE_NAMES = new Set([
3268
+ "CON",
3269
+ "PRN",
3270
+ "AUX",
3271
+ "NUL",
3272
+ "CLOCK$",
3273
+ "CONIN$",
3274
+ "CONOUT$",
3275
+ "COM1",
3276
+ "COM2",
3277
+ "COM3",
3278
+ "COM4",
3279
+ "COM5",
3280
+ "COM6",
3281
+ "COM7",
3282
+ "COM8",
3283
+ "COM9",
3284
+ "COM¹",
3285
+ "COM²",
3286
+ "COM³",
3287
+ "LPT1",
3288
+ "LPT2",
3289
+ "LPT3",
3290
+ "LPT4",
3291
+ "LPT5",
3292
+ "LPT6",
3293
+ "LPT7",
3294
+ "LPT8",
3295
+ "LPT9",
3296
+ "LPT¹",
3297
+ "LPT²",
3298
+ "LPT³",
3299
+ ]);
3300
+ function candidateReadPaths(filePath) {
3301
+ if (!filePath.startsWith("file://")) {
3302
+ return [filePath];
3303
+ }
3304
+ const parsed = trySafeFileURLToPath(filePath);
3305
+ return parsed === undefined ? [filePath] : [filePath, parsed];
3306
+ }
3307
+ function normalizePosixPath(filePath, cwd) {
3308
+ if (external_node_path_.posix.isAbsolute(filePath)) {
3309
+ return external_node_path_.posix.normalize(filePath);
3310
+ }
3311
+ const base = cwd && external_node_path_.posix.isAbsolute(cwd) ? cwd : process.cwd();
3312
+ return external_node_path_.posix.resolve(base, filePath);
3313
+ }
3314
+ function matchPosixDeviceReadPath(filePath, cwd) {
3315
+ const normalized = normalizePosixPath(filePath, cwd);
3316
+ if (POSIX_BLOCKED_DEVICE_PATHS.has(normalized)) {
3317
+ return { path: normalized, reason: "posix-device" };
3318
+ }
3319
+ if (normalized === "/dev/fd" || normalized.startsWith("/dev/fd/")) {
3320
+ return { path: normalized, reason: "posix-fd" };
3321
+ }
3322
+ if (/^\/proc\/(?:self|thread-self|\d+)\/fd(?:\/|$)/.test(normalized)) {
3323
+ return { path: normalized, reason: "posix-fd" };
3324
+ }
3325
+ return undefined;
3326
+ }
3327
+ function normalizeWindowsDeviceBaseName(filePath) {
3328
+ const normalized = filePath.replace(/\//g, "\\").replace(/[\\]+$/g, "");
3329
+ const lastSegment = normalized.split("\\").filter(Boolean).at(-1) ?? normalized;
3330
+ const withoutStream = lastSegment.split(":")[0] ?? lastSegment;
3331
+ const withoutTrailingIgnoredChars = withoutStream.replace(/[ .]+$/g, "");
3332
+ return (withoutTrailingIgnoredChars.split(".")[0] ?? withoutTrailingIgnoredChars).toUpperCase();
3333
+ }
3334
+ function matchWindowsDeviceReadPath(filePath) {
3335
+ const normalized = filePath.replace(/\//g, "\\");
3336
+ if (/^\\\\\.\\/.test(normalized) || /^\\\\\?\\GLOBALROOT\\Device\\/i.test(normalized)) {
3337
+ return { path: normalized, reason: "windows-device" };
3338
+ }
3339
+ const baseName = normalizeWindowsDeviceBaseName(filePath);
3340
+ if (WINDOWS_RESERVED_DEVICE_NAMES.has(baseName)) {
3341
+ return { path: normalized, reason: "windows-device" };
3342
+ }
3343
+ return undefined;
3344
+ }
3345
+ function matchUnsafeDeviceReadPath(filePath, options = {}) {
3346
+ const platform = options.platform ?? process.platform;
3347
+ for (const candidate of candidateReadPaths(filePath)) {
3348
+ const match = platform === "win32"
3349
+ ? matchWindowsDeviceReadPath(candidate)
3350
+ : matchPosixDeviceReadPath(candidate, options.cwd);
3351
+ if (match) {
3352
+ return match;
3353
+ }
3354
+ }
3355
+ return undefined;
3356
+ }
3357
+ function isUnsafeDeviceReadPath(filePath, options) {
3358
+ return matchUnsafeDeviceReadPath(filePath, options) !== undefined;
3359
+ }
3360
+ function assertNoUnsafeDeviceReadPath(filePath, options) {
3361
+ if (matchUnsafeDeviceReadPath(filePath, options)) {
3362
+ throw new errors_FsSafeError("device-path", `file reads from unsafe device paths are not allowed: ${filePath}`);
3363
+ }
3364
+ }
3365
+
3148
3366
  ;// CONCATENATED MODULE: ../../node_modules/@openclaw/fs-safe/dist/read-opened-file.js
3149
3367
 
3150
3368
  async function read_opened_file_readOpenedFileSafely(params) {
@@ -3496,6 +3714,7 @@ async function serializePathWrite(key, run) {
3496
3714
 
3497
3715
 
3498
3716
 
3717
+
3499
3718
 
3500
3719
 
3501
3720
  function logWarn(message) {
@@ -3521,20 +3740,16 @@ const OPEN_APPEND_CREATE_FLAGS = external_node_fs_.constants.O_RDWR |
3521
3740
  external_node_fs_.constants.O_EXCL |
3522
3741
  (SUPPORTS_NOFOLLOW ? external_node_fs_.constants.O_NOFOLLOW : 0);
3523
3742
  const DEFAULT_ROOT_MAX_BYTES = 16 * 1024 * 1024;
3524
- function closeHandleForDispose(handle) {
3525
- return handle.close().catch(() => undefined);
3526
- }
3527
3743
  function openResult(params) {
3528
3744
  return {
3529
3745
  handle: params.handle,
3530
3746
  realPath: params.realPath,
3531
3747
  stat: params.stat,
3532
- [Symbol.asyncDispose]: async () => {
3533
- await closeHandleForDispose(params.handle);
3534
- },
3748
+ [Symbol.asyncDispose]: () => params.handle.close().catch(() => undefined),
3535
3749
  };
3536
3750
  }
3537
3751
  async function openVerifiedLocalFile(filePath, options) {
3752
+ assertNoUnsafeDeviceReadPath(filePath);
3538
3753
  const fsSafeTestHooks = getFsSafeTestHooks();
3539
3754
  // Reject directories before opening so we never surface EISDIR to callers (e.g. tool
3540
3755
  // results that get sent to messaging channels). See openclaw/openclaw#31186.
@@ -4059,9 +4274,7 @@ async function openWritableFileInRoot(root, params) {
4059
4274
  createdForWrite,
4060
4275
  realPath,
4061
4276
  stat,
4062
- [Symbol.asyncDispose]: async () => {
4063
- await closeHandleForDispose(handle);
4064
- },
4277
+ [Symbol.asyncDispose]: () => handle.close().catch(() => undefined),
4065
4278
  };
4066
4279
  }
4067
4280
  catch (err) {
@@ -4098,10 +4311,15 @@ async function appendFileInRoot(root, params) {
4098
4311
  }
4099
4312
  if (typeof params.data === "string") {
4100
4313
  await target.handle.appendFile(`${prefix}${params.data}`, params.encoding ?? "utf8");
4101
- return;
4102
4314
  }
4103
- const payload = prefix.length > 0 ? Buffer.concat([Buffer.from(prefix, "utf8"), params.data]) : params.data;
4104
- await target.handle.appendFile(payload);
4315
+ else {
4316
+ const payload = prefix.length > 0 ? Buffer.concat([Buffer.from(prefix, "utf8"), params.data]) : params.data;
4317
+ await target.handle.appendFile(payload);
4318
+ }
4319
+ await target.handle.sync();
4320
+ if (target.createdForWrite) {
4321
+ await syncDirectoryBestEffort(external_node_path_.dirname(target.realPath));
4322
+ }
4105
4323
  }
4106
4324
  finally {
4107
4325
  await target.handle.close().catch(() => { });
@@ -4158,42 +4376,45 @@ async function writeFileInRoot(root, params) {
4158
4376
  }
4159
4377
  const pinned = await resolvePinnedWriteTargetInRoot(root, params.relativePath, params.mode, params.denyMutations);
4160
4378
  await serializePathWrite(pinned.targetPath, async () => {
4161
- let identity;
4162
- try {
4163
- identity = await runPinnedWriteHelper({
4164
- rootPath: pinned.rootReal,
4165
- relativeParentPath: pinned.relativeParentPath,
4166
- basename: pinned.basename,
4167
- mkdir: params.mkdir !== false,
4168
- mode: params.mode ?? pinned.mode,
4169
- overwrite: params.overwrite,
4170
- input: {
4171
- kind: "buffer",
4172
- data: params.data,
4173
- encoding: params.encoding,
4174
- },
4175
- });
4176
- }
4177
- catch (error) {
4178
- if (params.overwrite === false && isAlreadyExistsError(error)) {
4179
- throw new errors_FsSafeError("already-exists", "file already exists", {
4180
- cause: error instanceof Error ? error : undefined,
4181
- });
4182
- }
4183
- throw normalizePinnedWriteError(error);
4184
- }
4185
- try {
4186
- await verifyAtomicWriteResult({
4187
- root,
4188
- targetPath: pinned.targetPath,
4189
- expectedIdentity: identity,
4379
+ await commitPinnedWriteInRoot(root, pinned, params);
4380
+ });
4381
+ }
4382
+ async function commitPinnedWriteInRoot(root, pinned, params) {
4383
+ let identity;
4384
+ try {
4385
+ identity = await runPinnedWriteHelper({
4386
+ rootPath: pinned.rootReal,
4387
+ relativeParentPath: pinned.relativeParentPath,
4388
+ basename: pinned.basename,
4389
+ mkdir: params.mkdir !== false,
4390
+ mode: params.mode ?? pinned.mode,
4391
+ overwrite: params.overwrite,
4392
+ input: {
4393
+ kind: "buffer",
4394
+ data: params.data,
4395
+ encoding: params.encoding,
4396
+ },
4397
+ });
4398
+ }
4399
+ catch (error) {
4400
+ if (params.overwrite === false && isAlreadyExistsError(error)) {
4401
+ throw new errors_FsSafeError("already-exists", "file already exists", {
4402
+ cause: error instanceof Error ? error : undefined,
4190
4403
  });
4191
4404
  }
4192
- catch (err) {
4193
- emitWriteBoundaryWarning(`post-write verification failed: ${String(err)}`);
4194
- throw err;
4195
- }
4196
- });
4405
+ throw normalizePinnedWriteError(error);
4406
+ }
4407
+ try {
4408
+ await verifyAtomicWriteResult({
4409
+ root,
4410
+ targetPath: pinned.targetPath,
4411
+ expectedIdentity: identity,
4412
+ });
4413
+ }
4414
+ catch (err) {
4415
+ emitWriteBoundaryWarning(`post-write verification failed: ${String(err)}`);
4416
+ throw err;
4417
+ }
4197
4418
  }
4198
4419
  async function copyFileInRoot(root, params) {
4199
4420
  assertValidRootRelativePath(params.relativePath);
@@ -21965,8 +22186,6 @@ function isUrl(fileUrlOrPath) {
21965
22186
  )
21966
22187
  }
21967
22188
 
21968
- // EXTERNAL MODULE: external "node:url"
21969
- var external_node_url_ = __webpack_require__(3136);
21970
22189
  ;// CONCATENATED MODULE: ../../node_modules/vfile/lib/index.js
21971
22190
  /**
21972
22191
  * @import {Node, Point, Position} from 'unist'
@@ -25783,7 +26002,7 @@ const regexes_base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0
25783
26002
  const regexes_base64url = /^[A-Za-z0-9_-]*$/;
25784
26003
  // based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
25785
26004
  // export const hostname: RegExp = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
25786
- const hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
26005
+ const regexes_hostname = /^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
25787
26006
  const domain = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
25788
26007
  const httpProtocol = /^https?$/;
25789
26008
  // https://blog.stevenlevithan.com/archives/validate-phone-number#r4-3 (regex sans spaces)
@@ -46330,7 +46549,7 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
46330
46549
  // module factories are used so entry inlining is disabled
46331
46550
  // startup
46332
46551
  // Load entry module and return exports
46333
- var __webpack_exports__ = __webpack_require__(9884);
46552
+ var __webpack_exports__ = __webpack_require__(2749);
46334
46553
  var __webpack_exports__DEFAULT_LINT_RULES = __webpack_exports__.Kd;
46335
46554
  var __webpack_exports__LintValidationError = __webpack_exports__.F5;
46336
46555
  var __webpack_exports__createFormatter = __webpack_exports__.xi;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/lint",
3
- "version": "5.15.3",
3
+ "version": "5.15.5",
4
4
  "description": "Programmatic lint API for validating AI coding assistant configurations — skills, agents, hooks, and instructions",
5
5
  "type": "module",
6
6
  "repository": {