@csark0812/skeleton 3.0.0 → 4.0.0
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 +6 -5
- package/dist/cli.js +531 -716
- package/dist/hooks/customize-on-skill-read.js +416 -126
- package/package.json +2 -2
- package/dist/references/check.d.ts +0 -10
- package/dist/references/constants.d.ts +0 -9
- package/dist/references/discover.d.ts +0 -19
package/dist/cli.js
CHANGED
|
@@ -3036,7 +3036,25 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3036
3036
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
3037
3037
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3038
3038
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3039
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3039
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3040
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3041
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3042
|
+
var BYTE_HEX = new Array(256);
|
|
3043
|
+
{
|
|
3044
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3045
|
+
for (let i = 0;i < 256; i++) {
|
|
3046
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
function percentEncodeNonAscii(cp) {
|
|
3050
|
+
if (cp < 2048) {
|
|
3051
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3052
|
+
}
|
|
3053
|
+
if (cp < 65536) {
|
|
3054
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3055
|
+
}
|
|
3056
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3057
|
+
}
|
|
3040
3058
|
function stringArrayToHexStripped(input) {
|
|
3041
3059
|
let acc = "";
|
|
3042
3060
|
let code = 0;
|
|
@@ -3061,91 +3079,122 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3061
3079
|
}
|
|
3062
3080
|
return acc;
|
|
3063
3081
|
}
|
|
3082
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3083
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3084
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3064
3085
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3065
|
-
function
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
} else {
|
|
3075
|
-
output.error = true;
|
|
3076
|
-
return false;
|
|
3086
|
+
function isZoneIdentifier(zone) {
|
|
3087
|
+
if (zone.length === 0)
|
|
3088
|
+
return false;
|
|
3089
|
+
for (let i = 0;i < zone.length; i++) {
|
|
3090
|
+
if (isZoneCharacter(zone[i]))
|
|
3091
|
+
continue;
|
|
3092
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3093
|
+
i += 2;
|
|
3094
|
+
continue;
|
|
3077
3095
|
}
|
|
3078
|
-
|
|
3096
|
+
return false;
|
|
3079
3097
|
}
|
|
3080
3098
|
return true;
|
|
3081
3099
|
}
|
|
3082
|
-
function
|
|
3083
|
-
let
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
let
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
if (cursor === ":") {
|
|
3096
|
-
if (endipv6Encountered === true) {
|
|
3097
|
-
endIpv6 = true;
|
|
3098
|
-
}
|
|
3099
|
-
if (!consume(buffer, address, output)) {
|
|
3100
|
-
break;
|
|
3101
|
-
}
|
|
3102
|
-
if (++tokenCount > 7) {
|
|
3103
|
-
output.error = true;
|
|
3104
|
-
break;
|
|
3100
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3101
|
+
let bestStart = -1;
|
|
3102
|
+
let bestLength = 0;
|
|
3103
|
+
let runStart = -1;
|
|
3104
|
+
let runLength = 0;
|
|
3105
|
+
for (let i = 0;i < hextets.length; i++) {
|
|
3106
|
+
if (hextets[i] === "0") {
|
|
3107
|
+
if (runStart === -1)
|
|
3108
|
+
runStart = i;
|
|
3109
|
+
runLength++;
|
|
3110
|
+
if (runLength > bestLength) {
|
|
3111
|
+
bestLength = runLength;
|
|
3112
|
+
bestStart = runStart;
|
|
3105
3113
|
}
|
|
3106
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3107
|
-
endipv6Encountered = true;
|
|
3108
|
-
}
|
|
3109
|
-
address.push(":");
|
|
3110
|
-
continue;
|
|
3111
|
-
} else if (cursor === "%") {
|
|
3112
|
-
if (!consume(buffer, address, output)) {
|
|
3113
|
-
break;
|
|
3114
|
-
}
|
|
3115
|
-
consume = consumeIsZone;
|
|
3116
3114
|
} else {
|
|
3117
|
-
|
|
3118
|
-
|
|
3115
|
+
runStart = -1;
|
|
3116
|
+
runLength = 0;
|
|
3119
3117
|
}
|
|
3120
3118
|
}
|
|
3121
|
-
if (
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3119
|
+
if (bestLength < 2)
|
|
3120
|
+
return hextets.join(":");
|
|
3121
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3122
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3123
|
+
return head + "::" + tail;
|
|
3124
|
+
}
|
|
3125
|
+
function normalizeIPv6Address(input) {
|
|
3126
|
+
const compression = input.indexOf("::");
|
|
3127
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1)
|
|
3128
|
+
return;
|
|
3129
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3130
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3131
|
+
if (compression !== -1) {
|
|
3132
|
+
if (left.length === 1 && left[0] === "")
|
|
3133
|
+
left.length = 0;
|
|
3134
|
+
if (right.length === 1 && right[0] === "")
|
|
3135
|
+
right.length = 0;
|
|
3136
|
+
}
|
|
3137
|
+
const parts = left.concat(right);
|
|
3138
|
+
let hextetCount = 0;
|
|
3139
|
+
for (let i = 0;i < parts.length; i++) {
|
|
3140
|
+
const part = parts[i];
|
|
3141
|
+
if (part === "")
|
|
3142
|
+
return;
|
|
3143
|
+
if (part.indexOf(".") !== -1) {
|
|
3144
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part))
|
|
3145
|
+
return;
|
|
3146
|
+
hextetCount += 2;
|
|
3147
|
+
continue;
|
|
3128
3148
|
}
|
|
3149
|
+
if (!isHextet(part))
|
|
3150
|
+
return;
|
|
3151
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3152
|
+
hextetCount++;
|
|
3129
3153
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3154
|
+
if (compression === -1) {
|
|
3155
|
+
if (hextetCount !== 8)
|
|
3156
|
+
return;
|
|
3157
|
+
return compressIPv6ZeroRun(parts);
|
|
3158
|
+
}
|
|
3159
|
+
if (hextetCount >= 8)
|
|
3160
|
+
return;
|
|
3161
|
+
const expanded = parts.slice(0, left.length);
|
|
3162
|
+
for (let i = hextetCount;i < 8; i++)
|
|
3163
|
+
expanded.push("0");
|
|
3164
|
+
for (let i = left.length;i < parts.length; i++)
|
|
3165
|
+
expanded.push(parts[i]);
|
|
3166
|
+
return compressIPv6ZeroRun(expanded);
|
|
3132
3167
|
}
|
|
3133
3168
|
function normalizeIPv6(host) {
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3169
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3170
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3171
|
+
if (hasBracket && !bracketed)
|
|
3172
|
+
return { host, isIPV6: false, error: true };
|
|
3173
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3174
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3175
|
+
input = input.toLowerCase();
|
|
3176
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3177
|
+
}
|
|
3178
|
+
if (findToken(input, ":") < 2) {
|
|
3179
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3180
|
+
}
|
|
3181
|
+
let zoneIdentifier = "";
|
|
3182
|
+
const zoneSeparator = input.indexOf("%");
|
|
3183
|
+
if (zoneSeparator !== -1) {
|
|
3184
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3185
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3186
|
+
if (!isZoneIdentifier(zoneIdentifier))
|
|
3187
|
+
return { host, isIPV6: false, error: true };
|
|
3188
|
+
input = input.slice(0, zoneSeparator);
|
|
3189
|
+
}
|
|
3190
|
+
const address = normalizeIPv6Address(input);
|
|
3191
|
+
if (address === undefined)
|
|
3192
|
+
return { host, isIPV6: false, error: true };
|
|
3193
|
+
return {
|
|
3194
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3195
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3196
|
+
isIPV6: true
|
|
3197
|
+
};
|
|
3149
3198
|
}
|
|
3150
3199
|
function findToken(str, token) {
|
|
3151
3200
|
let ind = 0;
|
|
@@ -3265,7 +3314,8 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3265
3314
|
function normalizePathEncoding(input) {
|
|
3266
3315
|
let output = "";
|
|
3267
3316
|
for (let i = 0;i < input.length; i++) {
|
|
3268
|
-
|
|
3317
|
+
const ch = input[i];
|
|
3318
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3269
3319
|
const hex = input.slice(i + 1, i + 3);
|
|
3270
3320
|
if (isHexPair(hex)) {
|
|
3271
3321
|
const normalizedHex = hex.toUpperCase();
|
|
@@ -3279,10 +3329,152 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3279
3329
|
continue;
|
|
3280
3330
|
}
|
|
3281
3331
|
}
|
|
3282
|
-
if (isPathCharacter(
|
|
3283
|
-
output +=
|
|
3332
|
+
if (isPathCharacter(ch)) {
|
|
3333
|
+
output += ch;
|
|
3284
3334
|
} else {
|
|
3285
|
-
|
|
3335
|
+
const code = input.charCodeAt(i);
|
|
3336
|
+
if (code < 128) {
|
|
3337
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3338
|
+
} else if (code < 55296 || code > 57343) {
|
|
3339
|
+
output += percentEncodeNonAscii(code);
|
|
3340
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3341
|
+
const low = input.charCodeAt(i + 1);
|
|
3342
|
+
if (low >= 56320 && low <= 57343) {
|
|
3343
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3344
|
+
i++;
|
|
3345
|
+
} else {
|
|
3346
|
+
output += percentEncodeNonAscii(65533);
|
|
3347
|
+
}
|
|
3348
|
+
} else {
|
|
3349
|
+
output += percentEncodeNonAscii(65533);
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
return output;
|
|
3354
|
+
}
|
|
3355
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3356
|
+
let output = "";
|
|
3357
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3358
|
+
for (let i = 0;i < input.length; i++) {
|
|
3359
|
+
const ch = input[i];
|
|
3360
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3361
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3362
|
+
if (isHexPair(hex)) {
|
|
3363
|
+
output += "%" + hex.toUpperCase();
|
|
3364
|
+
i += 2;
|
|
3365
|
+
continue;
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
if (ch === "/") {
|
|
3369
|
+
firstSegment = false;
|
|
3370
|
+
}
|
|
3371
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3372
|
+
output += ch;
|
|
3373
|
+
} else {
|
|
3374
|
+
const code = input.charCodeAt(i);
|
|
3375
|
+
if (code < 128) {
|
|
3376
|
+
output += BYTE_HEX[code];
|
|
3377
|
+
} else if (code < 55296 || code > 57343) {
|
|
3378
|
+
output += percentEncodeNonAscii(code);
|
|
3379
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3380
|
+
const low = input.charCodeAt(i + 1);
|
|
3381
|
+
if (low >= 56320 && low <= 57343) {
|
|
3382
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3383
|
+
i++;
|
|
3384
|
+
} else {
|
|
3385
|
+
output += percentEncodeNonAscii(65533);
|
|
3386
|
+
}
|
|
3387
|
+
} else {
|
|
3388
|
+
output += percentEncodeNonAscii(65533);
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
return output;
|
|
3393
|
+
}
|
|
3394
|
+
function encodeComponent(input, isAllowed) {
|
|
3395
|
+
let output = "";
|
|
3396
|
+
for (let i = 0;i < input.length; i++) {
|
|
3397
|
+
const ch = input[i];
|
|
3398
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3399
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3400
|
+
if (isHexPair(hex)) {
|
|
3401
|
+
output += "%" + hex.toUpperCase();
|
|
3402
|
+
i += 2;
|
|
3403
|
+
continue;
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
if (isAllowed(ch)) {
|
|
3407
|
+
output += ch;
|
|
3408
|
+
} else {
|
|
3409
|
+
const code = input.charCodeAt(i);
|
|
3410
|
+
if (code < 128) {
|
|
3411
|
+
output += BYTE_HEX[code];
|
|
3412
|
+
} else if (code < 55296 || code > 57343) {
|
|
3413
|
+
output += percentEncodeNonAscii(code);
|
|
3414
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3415
|
+
const low = input.charCodeAt(i + 1);
|
|
3416
|
+
if (low >= 56320 && low <= 57343) {
|
|
3417
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3418
|
+
i++;
|
|
3419
|
+
} else {
|
|
3420
|
+
output += percentEncodeNonAscii(65533);
|
|
3421
|
+
}
|
|
3422
|
+
} else {
|
|
3423
|
+
output += percentEncodeNonAscii(65533);
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
return output;
|
|
3428
|
+
}
|
|
3429
|
+
function encodeUserinfo(input) {
|
|
3430
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3431
|
+
}
|
|
3432
|
+
function encodeQuery(input) {
|
|
3433
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3434
|
+
}
|
|
3435
|
+
function encodeFragment(input) {
|
|
3436
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3437
|
+
}
|
|
3438
|
+
function isEscapeSafe(cp) {
|
|
3439
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
3440
|
+
}
|
|
3441
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3442
|
+
let output = "";
|
|
3443
|
+
for (let i = 0;i < input.length; i++) {
|
|
3444
|
+
const ch = input[i];
|
|
3445
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3446
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3447
|
+
if (isHexPair(hex)) {
|
|
3448
|
+
const normalizedHex = hex.toUpperCase();
|
|
3449
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3450
|
+
if (isUnreserved(decoded)) {
|
|
3451
|
+
output += decoded;
|
|
3452
|
+
} else {
|
|
3453
|
+
output += "%" + normalizedHex;
|
|
3454
|
+
}
|
|
3455
|
+
i += 2;
|
|
3456
|
+
continue;
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3460
|
+
output += ch;
|
|
3461
|
+
} else {
|
|
3462
|
+
const code = input.charCodeAt(i);
|
|
3463
|
+
if (code < 128) {
|
|
3464
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3465
|
+
} else if (code < 55296 || code > 57343) {
|
|
3466
|
+
output += percentEncodeNonAscii(code);
|
|
3467
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3468
|
+
const low = input.charCodeAt(i + 1);
|
|
3469
|
+
if (low >= 56320 && low <= 57343) {
|
|
3470
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3471
|
+
i++;
|
|
3472
|
+
} else {
|
|
3473
|
+
output += percentEncodeNonAscii(65533);
|
|
3474
|
+
}
|
|
3475
|
+
} else {
|
|
3476
|
+
output += percentEncodeNonAscii(65533);
|
|
3477
|
+
}
|
|
3286
3478
|
}
|
|
3287
3479
|
}
|
|
3288
3480
|
return output;
|
|
@@ -3305,14 +3497,18 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3305
3497
|
function recomposeAuthority(component) {
|
|
3306
3498
|
const uriTokens = [];
|
|
3307
3499
|
if (component.userinfo !== undefined) {
|
|
3308
|
-
uriTokens.push(component.userinfo);
|
|
3500
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3309
3501
|
uriTokens.push("@");
|
|
3310
3502
|
}
|
|
3311
3503
|
if (component.host !== undefined) {
|
|
3312
|
-
let host =
|
|
3504
|
+
let host = component.host;
|
|
3313
3505
|
if (!isIPv4(host)) {
|
|
3314
|
-
|
|
3315
|
-
if (ipV6res.isIPV6
|
|
3506
|
+
let ipV6res = normalizeIPv6(host);
|
|
3507
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3508
|
+
host = normalizePercentEncoding(host, true);
|
|
3509
|
+
ipV6res = normalizeIPv6(host);
|
|
3510
|
+
}
|
|
3511
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3316
3512
|
host = `[${ipV6res.escapedHost}]`;
|
|
3317
3513
|
} else {
|
|
3318
3514
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3332,6 +3528,11 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3332
3528
|
reescapeHostDelimiters,
|
|
3333
3529
|
normalizePercentEncoding,
|
|
3334
3530
|
normalizePathEncoding,
|
|
3531
|
+
serializePathEncoding,
|
|
3532
|
+
normalizeQueryFragmentEncoding,
|
|
3533
|
+
encodeUserinfo,
|
|
3534
|
+
encodeQuery,
|
|
3535
|
+
encodeFragment,
|
|
3335
3536
|
escapePreservingEscapes,
|
|
3336
3537
|
removeDotSegments,
|
|
3337
3538
|
isIPv4,
|
|
@@ -3344,7 +3545,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3344
3545
|
// node_modules/fast-uri/lib/schemes.js
|
|
3345
3546
|
var require_schemes = __commonJS((exports, module) => {
|
|
3346
3547
|
var { isUUID } = require_utils();
|
|
3347
|
-
var URN_REG =
|
|
3548
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3348
3549
|
var supportedSchemeNames = [
|
|
3349
3550
|
"http",
|
|
3350
3551
|
"https",
|
|
@@ -3399,9 +3600,10 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
3399
3600
|
wsComponent.secure = undefined;
|
|
3400
3601
|
}
|
|
3401
3602
|
if (wsComponent.resourceName) {
|
|
3402
|
-
const
|
|
3603
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3604
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3403
3605
|
wsComponent.path = path && path !== "/" ? path : undefined;
|
|
3404
|
-
wsComponent.query =
|
|
3606
|
+
wsComponent.query = queryIndex === -1 ? undefined : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3405
3607
|
wsComponent.resourceName = undefined;
|
|
3406
3608
|
}
|
|
3407
3609
|
wsComponent.fragment = undefined;
|
|
@@ -3413,7 +3615,7 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
3413
3615
|
return urnComponent;
|
|
3414
3616
|
}
|
|
3415
3617
|
const matches = urnComponent.path.match(URN_REG);
|
|
3416
|
-
if (matches) {
|
|
3618
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3417
3619
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3418
3620
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3419
3621
|
urnComponent.nss = matches[2];
|
|
@@ -3517,8 +3719,17 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
3517
3719
|
|
|
3518
3720
|
// node_modules/fast-uri/index.js
|
|
3519
3721
|
var require_fast_uri = __commonJS((exports, module) => {
|
|
3520
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3722
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3521
3723
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3724
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3725
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3726
|
+
function decodeValidScheme(scheme) {
|
|
3727
|
+
const decodedScheme = unescape(String(scheme));
|
|
3728
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3729
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3730
|
+
}
|
|
3731
|
+
return decodedScheme;
|
|
3732
|
+
}
|
|
3522
3733
|
function normalize(uri, options) {
|
|
3523
3734
|
if (typeof uri === "string") {
|
|
3524
3735
|
uri = normalizeString(uri, options);
|
|
@@ -3529,12 +3740,34 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3529
3740
|
}
|
|
3530
3741
|
function resolve(baseURI, relativeURI, options) {
|
|
3531
3742
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3532
|
-
const {
|
|
3533
|
-
|
|
3534
|
-
|
|
3743
|
+
const {
|
|
3744
|
+
parsed: baseParsed,
|
|
3745
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3746
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3747
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3748
|
+
malformedHost: baseMalformedHost,
|
|
3749
|
+
malformedScheme: baseMalformedScheme
|
|
3750
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3751
|
+
const {
|
|
3752
|
+
parsed: relativeParsed,
|
|
3753
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3754
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3755
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3756
|
+
malformedHost: relativeMalformedHost,
|
|
3757
|
+
malformedScheme: relativeMalformedScheme
|
|
3758
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3759
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3535
3760
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3536
3761
|
}
|
|
3537
3762
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3763
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3764
|
+
const resolvedHost = resolved.host;
|
|
3765
|
+
const resolvedHostIsIP = resolvedHost !== undefined && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3766
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3767
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
3768
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3769
|
+
throw new Error(resolved.error);
|
|
3770
|
+
}
|
|
3538
3771
|
schemelessOptions.skipEscape = true;
|
|
3539
3772
|
return serialize(resolved, schemelessOptions);
|
|
3540
3773
|
}
|
|
@@ -3594,7 +3827,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3594
3827
|
function equal(uriA, uriB, options) {
|
|
3595
3828
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3596
3829
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3597
|
-
return normalizedA !== undefined && normalizedB !== undefined && normalizedA
|
|
3830
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA === normalizedB;
|
|
3598
3831
|
}
|
|
3599
3832
|
function serialize(cmpts, opts) {
|
|
3600
3833
|
const component = {
|
|
@@ -3615,20 +3848,23 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3615
3848
|
};
|
|
3616
3849
|
const options = Object.assign({}, opts);
|
|
3617
3850
|
const uriTokens = [];
|
|
3851
|
+
if (component.scheme) {
|
|
3852
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3853
|
+
}
|
|
3618
3854
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3619
3855
|
if (schemeHandler && schemeHandler.serialize)
|
|
3620
3856
|
schemeHandler.serialize(component, options);
|
|
3857
|
+
const hasAuthority = component.userinfo !== undefined || component.host !== undefined || component.port !== undefined;
|
|
3858
|
+
const pathNoScheme = !options.skipEscape && component.scheme === undefined && !hasAuthority;
|
|
3621
3859
|
if (component.path !== undefined) {
|
|
3622
3860
|
if (!options.skipEscape) {
|
|
3623
|
-
component.path =
|
|
3624
|
-
if (component.scheme !== undefined) {
|
|
3625
|
-
component.path = component.path.split("%3A").join(":");
|
|
3626
|
-
}
|
|
3861
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3627
3862
|
} else {
|
|
3628
3863
|
component.path = normalizePercentEncoding(component.path);
|
|
3629
3864
|
}
|
|
3630
3865
|
}
|
|
3631
3866
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3867
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3632
3868
|
uriTokens.push(component.scheme, ":");
|
|
3633
3869
|
}
|
|
3634
3870
|
const authority = recomposeAuthority(component);
|
|
@@ -3646,16 +3882,19 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3646
3882
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3647
3883
|
s = removeDotSegments(s);
|
|
3648
3884
|
}
|
|
3885
|
+
if (pathNoScheme) {
|
|
3886
|
+
s = serializePathEncoding(s, true);
|
|
3887
|
+
}
|
|
3649
3888
|
if (authority === undefined && s[0] === "/" && s[1] === "/") {
|
|
3650
3889
|
s = "/%2F" + s.slice(2);
|
|
3651
3890
|
}
|
|
3652
3891
|
uriTokens.push(s);
|
|
3653
3892
|
}
|
|
3654
3893
|
if (component.query !== undefined) {
|
|
3655
|
-
uriTokens.push("?", component.query);
|
|
3894
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3656
3895
|
}
|
|
3657
3896
|
if (component.fragment !== undefined) {
|
|
3658
|
-
uriTokens.push("#", component.fragment);
|
|
3897
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3659
3898
|
}
|
|
3660
3899
|
return uriTokens.join("");
|
|
3661
3900
|
}
|
|
@@ -3671,6 +3910,33 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3671
3910
|
}
|
|
3672
3911
|
return;
|
|
3673
3912
|
}
|
|
3913
|
+
function hasMalformedPercentEncoding(component) {
|
|
3914
|
+
if (component === undefined)
|
|
3915
|
+
return false;
|
|
3916
|
+
let percent = component.indexOf("%");
|
|
3917
|
+
while (percent !== -1) {
|
|
3918
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
3919
|
+
return true;
|
|
3920
|
+
}
|
|
3921
|
+
percent = component.indexOf("%", percent + 3);
|
|
3922
|
+
}
|
|
3923
|
+
return false;
|
|
3924
|
+
}
|
|
3925
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
3926
|
+
const host = matches[4];
|
|
3927
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== undefined && !(host[0] === "[" && host[host.length - 1] === "]") && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
3928
|
+
}
|
|
3929
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
3930
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && parsed.host[0] !== "[" && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3931
|
+
try {
|
|
3932
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3933
|
+
} catch (e) {
|
|
3934
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3935
|
+
return true;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
return false;
|
|
3939
|
+
}
|
|
3674
3940
|
function parseWithStatus(uri, opts) {
|
|
3675
3941
|
const options = Object.assign({}, opts);
|
|
3676
3942
|
const parsed = {
|
|
@@ -3683,6 +3949,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3683
3949
|
fragment: undefined
|
|
3684
3950
|
};
|
|
3685
3951
|
let malformedAuthorityOrPort = false;
|
|
3952
|
+
let malformedPercentEncoding = false;
|
|
3953
|
+
let malformedSchemeSpecific = false;
|
|
3954
|
+
let malformedHost = false;
|
|
3955
|
+
let malformedIPLiteral = false;
|
|
3956
|
+
let malformedScheme = false;
|
|
3686
3957
|
let isIP = false;
|
|
3687
3958
|
if (options.reference === "suffix") {
|
|
3688
3959
|
if (options.scheme) {
|
|
@@ -3719,6 +3990,19 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3719
3990
|
parsed.path = matches[6] || "";
|
|
3720
3991
|
parsed.query = matches[7];
|
|
3721
3992
|
parsed.fragment = matches[8];
|
|
3993
|
+
if (parsed.scheme !== undefined) {
|
|
3994
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
3995
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
3996
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
3997
|
+
} else {
|
|
3998
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
3999
|
+
malformedScheme = true;
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4003
|
+
if (malformedPercentEncoding) {
|
|
4004
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4005
|
+
}
|
|
3722
4006
|
if (isNaN(parsed.port)) {
|
|
3723
4007
|
parsed.port = matches[5];
|
|
3724
4008
|
}
|
|
@@ -3730,9 +4014,15 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3730
4014
|
if (parsed.host) {
|
|
3731
4015
|
const ipv4result = isIPv4(parsed.host);
|
|
3732
4016
|
if (ipv4result === false) {
|
|
4017
|
+
const bracketedIPLiteral = parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
|
|
3733
4018
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3734
|
-
|
|
3735
|
-
|
|
4019
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4020
|
+
malformedIPLiteral = bracketedIPLiteral && ipv6result.error === true;
|
|
4021
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4022
|
+
if (malformedIPLiteral) {
|
|
4023
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4024
|
+
malformedAuthorityOrPort = true;
|
|
4025
|
+
}
|
|
3736
4026
|
} else {
|
|
3737
4027
|
isIP = true;
|
|
3738
4028
|
}
|
|
@@ -3750,42 +4040,34 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3750
4040
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3751
4041
|
}
|
|
3752
4042
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3753
|
-
|
|
3754
|
-
if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3755
|
-
try {
|
|
3756
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3757
|
-
} catch (e) {
|
|
3758
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3759
|
-
}
|
|
3760
|
-
}
|
|
3761
|
-
}
|
|
4043
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
3762
4044
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3763
4045
|
if (uri.indexOf("%") !== -1) {
|
|
3764
|
-
if (parsed.
|
|
3765
|
-
parsed.
|
|
3766
|
-
|
|
3767
|
-
if (parsed.host !== undefined) {
|
|
3768
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4046
|
+
if (parsed.host !== undefined && !malformedIPLiteral) {
|
|
4047
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4048
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3769
4049
|
}
|
|
3770
4050
|
}
|
|
3771
4051
|
if (parsed.path) {
|
|
3772
4052
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3773
4053
|
}
|
|
4054
|
+
if (parsed.query) {
|
|
4055
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4056
|
+
}
|
|
3774
4057
|
if (parsed.fragment) {
|
|
3775
|
-
|
|
3776
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3777
|
-
} catch {
|
|
3778
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3779
|
-
}
|
|
4058
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3780
4059
|
}
|
|
3781
4060
|
}
|
|
3782
4061
|
if (schemeHandler && schemeHandler.parse) {
|
|
3783
4062
|
schemeHandler.parse(parsed, options);
|
|
4063
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === undefined) {
|
|
4064
|
+
malformedSchemeSpecific = true;
|
|
4065
|
+
}
|
|
3784
4066
|
}
|
|
3785
4067
|
} else {
|
|
3786
4068
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3787
4069
|
}
|
|
3788
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4070
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3789
4071
|
}
|
|
3790
4072
|
function parse(uri, opts) {
|
|
3791
4073
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3794,20 +4076,28 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3794
4076
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3795
4077
|
}
|
|
3796
4078
|
function normalizeStringWithStatus(uri, opts) {
|
|
3797
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4079
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3798
4080
|
return {
|
|
3799
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3800
|
-
malformedAuthorityOrPort
|
|
4081
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4082
|
+
malformedAuthorityOrPort,
|
|
4083
|
+
malformedPercentEncoding,
|
|
4084
|
+
malformedSchemeSpecific,
|
|
4085
|
+
malformedHost,
|
|
4086
|
+
malformedScheme
|
|
3801
4087
|
};
|
|
3802
4088
|
}
|
|
3803
4089
|
function normalizeComparableURI(uri, opts) {
|
|
3804
|
-
if (typeof uri
|
|
3805
|
-
|
|
3806
|
-
return malformedAuthorityOrPort ? undefined : normalized;
|
|
4090
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4091
|
+
return;
|
|
3807
4092
|
}
|
|
3808
|
-
|
|
3809
|
-
|
|
4093
|
+
let value;
|
|
4094
|
+
try {
|
|
4095
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4096
|
+
} catch {
|
|
4097
|
+
return;
|
|
3810
4098
|
}
|
|
4099
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4100
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized;
|
|
3811
4101
|
}
|
|
3812
4102
|
var fastUri = {
|
|
3813
4103
|
SCHEMES,
|
|
@@ -15678,8 +15968,8 @@ var require_extend = __commonJS((exports, module) => {
|
|
|
15678
15968
|
});
|
|
15679
15969
|
|
|
15680
15970
|
// src/cli.ts
|
|
15681
|
-
import { readFileSync as
|
|
15682
|
-
import
|
|
15971
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
15972
|
+
import process7 from "node:process";
|
|
15683
15973
|
|
|
15684
15974
|
// src/audit/config/load.ts
|
|
15685
15975
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
@@ -30993,287 +31283,6 @@ function runReviewProofRule(ctx) {
|
|
|
30993
31283
|
}
|
|
30994
31284
|
var reviewProofRule = { id: "review-proof", run: runReviewProofRule };
|
|
30995
31285
|
|
|
30996
|
-
// src/references/check.ts
|
|
30997
|
-
import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync13 } from "node:fs";
|
|
30998
|
-
import { join as join12, relative as relative8 } from "node:path";
|
|
30999
|
-
|
|
31000
|
-
// src/references/constants.ts
|
|
31001
|
-
var CANONICAL_REFS_DIR = ".skeleton/references";
|
|
31002
|
-
var GENERATED_MARKER_START = "<!-- skeleton: generated-reference";
|
|
31003
|
-
var GENERATED_MARKER_RE = /<!-- skeleton: generated-reference\s*\nsource: ([^\n]+)\s*\nredundancy: intentional\s*\n-->\s*\n?/;
|
|
31004
|
-
var SHARED_REF_LINK_RE = /\((?:\.\.\/)+references\/([^)]+)\)/g;
|
|
31005
|
-
function formatGeneratedHeader(sourceRelPath) {
|
|
31006
|
-
return `${GENERATED_MARKER_START}
|
|
31007
|
-
source: ${sourceRelPath}
|
|
31008
|
-
redundancy: intentional
|
|
31009
|
-
-->
|
|
31010
|
-
|
|
31011
|
-
`;
|
|
31012
|
-
}
|
|
31013
|
-
function stripGeneratedHeader(content3) {
|
|
31014
|
-
return content3.replace(GENERATED_MARKER_RE, "");
|
|
31015
|
-
}
|
|
31016
|
-
function isGeneratedReference(content3) {
|
|
31017
|
-
return content3.startsWith(GENERATED_MARKER_START);
|
|
31018
|
-
}
|
|
31019
|
-
|
|
31020
|
-
// src/references/discover.ts
|
|
31021
|
-
import { existsSync as existsSync14, readdirSync as readdirSync2, readFileSync as readFileSync12 } from "node:fs";
|
|
31022
|
-
import { join as join11, relative as relative7 } from "node:path";
|
|
31023
|
-
function walkMarkdownFiles(dir, root2) {
|
|
31024
|
-
const files = [];
|
|
31025
|
-
if (!existsSync14(dir))
|
|
31026
|
-
return files;
|
|
31027
|
-
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
31028
|
-
if (entry.name.startsWith("."))
|
|
31029
|
-
continue;
|
|
31030
|
-
const fullPath = join11(dir, entry.name);
|
|
31031
|
-
if (entry.isDirectory()) {
|
|
31032
|
-
files.push(...walkMarkdownFiles(fullPath, root2));
|
|
31033
|
-
continue;
|
|
31034
|
-
}
|
|
31035
|
-
if (entry.name.endsWith(".md")) {
|
|
31036
|
-
files.push(normalizeRelPath(relative7(root2, fullPath)));
|
|
31037
|
-
}
|
|
31038
|
-
}
|
|
31039
|
-
return files;
|
|
31040
|
-
}
|
|
31041
|
-
function canonicalExists(root2, refPath) {
|
|
31042
|
-
return existsSync14(join11(root2, CANONICAL_REFS_DIR, refPath));
|
|
31043
|
-
}
|
|
31044
|
-
function findSharedRefLinks(content3, sourceFile) {
|
|
31045
|
-
const links = [];
|
|
31046
|
-
for (const match of content3.matchAll(SHARED_REF_LINK_RE)) {
|
|
31047
|
-
const refPath = match[1];
|
|
31048
|
-
if (!refPath)
|
|
31049
|
-
continue;
|
|
31050
|
-
links.push({ refPath: normalizeRelPath(refPath), sourceFile });
|
|
31051
|
-
}
|
|
31052
|
-
return links;
|
|
31053
|
-
}
|
|
31054
|
-
function findSiblingRefLinks(root2, content3, sourceFile) {
|
|
31055
|
-
const links = [];
|
|
31056
|
-
if (!/\/references\//.test(sourceFile))
|
|
31057
|
-
return links;
|
|
31058
|
-
const refsIdx = sourceFile.lastIndexOf("/references/");
|
|
31059
|
-
const withinRefs = sourceFile.slice(refsIdx + "/references/".length);
|
|
31060
|
-
const withinDir = withinRefs.includes("/") ? withinRefs.slice(0, withinRefs.lastIndexOf("/")) : "";
|
|
31061
|
-
const siblingRe = /\((?!https?:|#|\.\.\/)([a-z0-9./_-]+\.md)\)/gi;
|
|
31062
|
-
for (const match of content3.matchAll(siblingRe)) {
|
|
31063
|
-
const raw = normalizeRelPath(match[1] ?? "");
|
|
31064
|
-
if (!raw)
|
|
31065
|
-
continue;
|
|
31066
|
-
const refPath = withinDir ? normalizeRelPath(join11(withinDir, raw)) : raw;
|
|
31067
|
-
if (!canonicalExists(root2, refPath))
|
|
31068
|
-
continue;
|
|
31069
|
-
links.push({ refPath, sourceFile });
|
|
31070
|
-
}
|
|
31071
|
-
return links;
|
|
31072
|
-
}
|
|
31073
|
-
function findLocalCanonicalLinks(root2, content3, sourceFile) {
|
|
31074
|
-
const links = [];
|
|
31075
|
-
const localRefRe = /\((?:\.\/)?references\/([^)]+)\)/g;
|
|
31076
|
-
for (const match of content3.matchAll(localRefRe)) {
|
|
31077
|
-
const refPath = normalizeRelPath(match[1] ?? "");
|
|
31078
|
-
if (!(refPath && canonicalExists(root2, refPath)))
|
|
31079
|
-
continue;
|
|
31080
|
-
links.push({ refPath, sourceFile });
|
|
31081
|
-
}
|
|
31082
|
-
links.push(...findSiblingRefLinks(root2, content3, sourceFile));
|
|
31083
|
-
return links;
|
|
31084
|
-
}
|
|
31085
|
-
function collectLinksForFile(root2, relFile) {
|
|
31086
|
-
const content3 = readFileSync12(join11(root2, relFile), "utf8");
|
|
31087
|
-
if (isGeneratedReference(content3))
|
|
31088
|
-
return [];
|
|
31089
|
-
return [
|
|
31090
|
-
...findSharedRefLinks(content3, relFile),
|
|
31091
|
-
...findLocalCanonicalLinks(root2, content3, relFile)
|
|
31092
|
-
];
|
|
31093
|
-
}
|
|
31094
|
-
function expandTransitiveRefs(input) {
|
|
31095
|
-
const { root: root2, skillDir, refPaths, links } = input;
|
|
31096
|
-
const queue = [...refPaths];
|
|
31097
|
-
while (queue.length > 0) {
|
|
31098
|
-
const refPath = queue.pop();
|
|
31099
|
-
if (!(refPath && canonicalExists(root2, refPath)))
|
|
31100
|
-
continue;
|
|
31101
|
-
const canonicalContent = readFileSync12(join11(root2, CANONICAL_REFS_DIR, refPath), "utf8");
|
|
31102
|
-
const syntheticSource = generatedRefPath(skillDir, refPath);
|
|
31103
|
-
for (const link2 of findLocalCanonicalLinks(root2, canonicalContent, syntheticSource)) {
|
|
31104
|
-
if (refPaths.has(link2.refPath))
|
|
31105
|
-
continue;
|
|
31106
|
-
refPaths.add(link2.refPath);
|
|
31107
|
-
links.push(link2);
|
|
31108
|
-
queue.push(link2.refPath);
|
|
31109
|
-
}
|
|
31110
|
-
}
|
|
31111
|
-
}
|
|
31112
|
-
function planForSkill(root2, slug2, skillDir) {
|
|
31113
|
-
const absSkillDir = join11(root2, skillDir);
|
|
31114
|
-
if (!existsSync14(join11(absSkillDir, "SKILL.md")))
|
|
31115
|
-
return null;
|
|
31116
|
-
const refPaths = new Set;
|
|
31117
|
-
const links = [];
|
|
31118
|
-
for (const relFile of walkMarkdownFiles(absSkillDir, root2)) {
|
|
31119
|
-
for (const link2 of collectLinksForFile(root2, relFile)) {
|
|
31120
|
-
refPaths.add(link2.refPath);
|
|
31121
|
-
links.push(link2);
|
|
31122
|
-
}
|
|
31123
|
-
}
|
|
31124
|
-
expandTransitiveRefs({ root: root2, skillDir, refPaths, links });
|
|
31125
|
-
return refPaths.size > 0 ? { skill: slug2, skillDir, refPaths, links } : null;
|
|
31126
|
-
}
|
|
31127
|
-
function concreteSkillDirs(root2, index2, slug2) {
|
|
31128
|
-
const dirs = [];
|
|
31129
|
-
for (const skillRoot of index2.roots) {
|
|
31130
|
-
const rel = normalizeRelPath(skillRoot.kind === "nested" ? join11(skillRoot.relPath, slug2) : slug2);
|
|
31131
|
-
if (existsSync14(join11(root2, rel, "SKILL.md")))
|
|
31132
|
-
dirs.push(rel);
|
|
31133
|
-
}
|
|
31134
|
-
return [...new Set(dirs)];
|
|
31135
|
-
}
|
|
31136
|
-
function discoverSkillReferencePlans(root2, ownership) {
|
|
31137
|
-
const index2 = buildSkillIndex(root2, ownership);
|
|
31138
|
-
const plans = [];
|
|
31139
|
-
for (const slug2 of index2.ownedSlugs) {
|
|
31140
|
-
for (const skillDir of concreteSkillDirs(root2, index2, slug2)) {
|
|
31141
|
-
const plan = planForSkill(root2, slug2, skillDir);
|
|
31142
|
-
if (plan)
|
|
31143
|
-
plans.push(plan);
|
|
31144
|
-
}
|
|
31145
|
-
}
|
|
31146
|
-
return plans.sort((a, b) => a.skillDir.localeCompare(b.skillDir));
|
|
31147
|
-
}
|
|
31148
|
-
function generatedRefPath(skillDir, refPath) {
|
|
31149
|
-
return normalizeRelPath(join11(skillDir, "references", refPath));
|
|
31150
|
-
}
|
|
31151
|
-
function rewriteSharedRefTarget(sourceFile, skillDir, refPath) {
|
|
31152
|
-
const sourceDir = sourceFile.slice(0, sourceFile.lastIndexOf("/"));
|
|
31153
|
-
const target = generatedRefPath(skillDir, refPath);
|
|
31154
|
-
if (!sourceDir)
|
|
31155
|
-
return target;
|
|
31156
|
-
const fromParts = sourceDir.split("/");
|
|
31157
|
-
const toParts = target.split("/");
|
|
31158
|
-
let i = 0;
|
|
31159
|
-
while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
|
|
31160
|
-
i++;
|
|
31161
|
-
}
|
|
31162
|
-
const ups = fromParts.length - i;
|
|
31163
|
-
const down = toParts.slice(i);
|
|
31164
|
-
const rel = [...Array(ups).fill(".."), ...down].join("/");
|
|
31165
|
-
return rel || (toParts.at(-1) ?? refPath);
|
|
31166
|
-
}
|
|
31167
|
-
function rewriteSharedRefLinks(content3, sourceFile, skillDir) {
|
|
31168
|
-
return content3.replace(SHARED_REF_LINK_RE, (_match, refPath) => {
|
|
31169
|
-
const rewritten = rewriteSharedRefTarget(sourceFile, skillDir, normalizeRelPath(refPath));
|
|
31170
|
-
return `(${rewritten})`;
|
|
31171
|
-
});
|
|
31172
|
-
}
|
|
31173
|
-
|
|
31174
|
-
// src/references/check.ts
|
|
31175
|
-
function walkMarkdown(dir, onFile) {
|
|
31176
|
-
if (!existsSync15(dir))
|
|
31177
|
-
return;
|
|
31178
|
-
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
31179
|
-
if (entry.name.startsWith("."))
|
|
31180
|
-
continue;
|
|
31181
|
-
const fullPath = join12(dir, entry.name);
|
|
31182
|
-
if (entry.isDirectory()) {
|
|
31183
|
-
walkMarkdown(fullPath, onFile);
|
|
31184
|
-
continue;
|
|
31185
|
-
}
|
|
31186
|
-
if (!entry.name.endsWith(".md"))
|
|
31187
|
-
continue;
|
|
31188
|
-
onFile(fullPath);
|
|
31189
|
-
}
|
|
31190
|
-
}
|
|
31191
|
-
function listAllGeneratedFiles(root2) {
|
|
31192
|
-
const files = [];
|
|
31193
|
-
walkMarkdown(root2, (fullPath) => {
|
|
31194
|
-
const content3 = readFileSync13(fullPath, "utf8");
|
|
31195
|
-
if (isGeneratedReference(content3)) {
|
|
31196
|
-
files.push(normalizeRelPath(relative8(root2, fullPath)));
|
|
31197
|
-
}
|
|
31198
|
-
});
|
|
31199
|
-
return files;
|
|
31200
|
-
}
|
|
31201
|
-
function checkNeededCopy(root2, targetRel) {
|
|
31202
|
-
const targetPath = join12(root2, targetRel);
|
|
31203
|
-
if (!existsSync15(targetPath)) {
|
|
31204
|
-
return issue("generated-references", targetRel, "missing generated copy — run skeleton references sync");
|
|
31205
|
-
}
|
|
31206
|
-
const generated = readFileSync13(targetPath, "utf8");
|
|
31207
|
-
if (!isGeneratedReference(generated)) {
|
|
31208
|
-
return issue("generated-references", targetRel, "expected generated-reference provenance header");
|
|
31209
|
-
}
|
|
31210
|
-
const body = stripGeneratedHeader(generated);
|
|
31211
|
-
const sourceRel = normalizeRelPath(generated.match(/source: ([^\n]+)/)?.[1] ?? join12(CANONICAL_REFS_DIR, targetRel.split("/references/")[1] ?? ""));
|
|
31212
|
-
const canonicalPath = join12(root2, sourceRel);
|
|
31213
|
-
if (!existsSync15(canonicalPath)) {
|
|
31214
|
-
return issue("generated-references", targetRel, `canonical source missing: ${sourceRel}`);
|
|
31215
|
-
}
|
|
31216
|
-
const canonical = readFileSync13(canonicalPath, "utf8");
|
|
31217
|
-
if (body !== canonical) {
|
|
31218
|
-
return issue("generated-references", targetRel, "stale generated copy — run skeleton references sync");
|
|
31219
|
-
}
|
|
31220
|
-
return null;
|
|
31221
|
-
}
|
|
31222
|
-
function checkOrphanedCopies(root2, needed, skillIndex) {
|
|
31223
|
-
const issues = [];
|
|
31224
|
-
for (const generatedRel of listAllGeneratedFiles(root2)) {
|
|
31225
|
-
if (isForeignSkillPath(generatedRel, skillIndex))
|
|
31226
|
-
continue;
|
|
31227
|
-
if (!needed.has(generatedRel)) {
|
|
31228
|
-
issues.push(issue("generated-references", generatedRel, "orphaned generated copy — run skeleton references sync"));
|
|
31229
|
-
}
|
|
31230
|
-
}
|
|
31231
|
-
return issues;
|
|
31232
|
-
}
|
|
31233
|
-
function checkStaleSharedLinks(root2, skillDir) {
|
|
31234
|
-
const issues = [];
|
|
31235
|
-
walkMarkdown(skillDir, (fullPath) => {
|
|
31236
|
-
const relFile = normalizeRelPath(relative8(root2, fullPath));
|
|
31237
|
-
const content3 = readFileSync13(fullPath, "utf8");
|
|
31238
|
-
if (!content3.match(SHARED_REF_LINK_RE))
|
|
31239
|
-
return;
|
|
31240
|
-
issues.push(issue("generated-references", relFile, "still links to shared root references/ — run skeleton references sync"));
|
|
31241
|
-
});
|
|
31242
|
-
return issues;
|
|
31243
|
-
}
|
|
31244
|
-
function runGeneratedReferencesCheck(root2, ownership) {
|
|
31245
|
-
const issues = [];
|
|
31246
|
-
const canonicalDir = join12(root2, CANONICAL_REFS_DIR);
|
|
31247
|
-
if (!existsSync15(canonicalDir))
|
|
31248
|
-
return issues;
|
|
31249
|
-
const skillIndex = buildSkillIndex(root2, ownership);
|
|
31250
|
-
const plans = discoverSkillReferencePlans(root2, ownership);
|
|
31251
|
-
const needed = new Set;
|
|
31252
|
-
for (const plan of plans) {
|
|
31253
|
-
for (const refPath of plan.refPaths) {
|
|
31254
|
-
needed.add(generatedRefPath(plan.skillDir, refPath));
|
|
31255
|
-
}
|
|
31256
|
-
}
|
|
31257
|
-
for (const targetRel of needed) {
|
|
31258
|
-
const found = checkNeededCopy(root2, targetRel);
|
|
31259
|
-
if (found)
|
|
31260
|
-
issues.push(found);
|
|
31261
|
-
}
|
|
31262
|
-
issues.push(...checkOrphanedCopies(root2, needed, skillIndex));
|
|
31263
|
-
for (const plan of plans) {
|
|
31264
|
-
issues.push(...checkStaleSharedLinks(root2, join12(root2, plan.skillDir)));
|
|
31265
|
-
}
|
|
31266
|
-
return issues;
|
|
31267
|
-
}
|
|
31268
|
-
function runGeneratedReferencesRule(ctx) {
|
|
31269
|
-
return runGeneratedReferencesCheck(ctx.root, ctx.config.skillOwnership);
|
|
31270
|
-
}
|
|
31271
|
-
var generatedReferencesRule = {
|
|
31272
|
-
id: "generated-references",
|
|
31273
|
-
global: true,
|
|
31274
|
-
run: runGeneratedReferencesRule
|
|
31275
|
-
};
|
|
31276
|
-
|
|
31277
31286
|
// src/audit/rules/banned.ts
|
|
31278
31287
|
function runBannedRule(ctx) {
|
|
31279
31288
|
const issues = [];
|
|
@@ -31286,8 +31295,8 @@ function runBannedRule(ctx) {
|
|
|
31286
31295
|
var bannedRule = { id: "banned", run: runBannedRule };
|
|
31287
31296
|
|
|
31288
31297
|
// src/audit/rules/doc-meta.ts
|
|
31289
|
-
import { existsSync as
|
|
31290
|
-
import { join as
|
|
31298
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
|
|
31299
|
+
import { join as join11 } from "node:path";
|
|
31291
31300
|
function checkDocMetaBanner(relPath2, content3) {
|
|
31292
31301
|
if (DOC_META_RE.test(content3))
|
|
31293
31302
|
return null;
|
|
@@ -31342,10 +31351,10 @@ function runDocMetaRule(ctx) {
|
|
|
31342
31351
|
const issues = [];
|
|
31343
31352
|
const today = new Date;
|
|
31344
31353
|
for (const relPath2 of ctx.docMetaPaths) {
|
|
31345
|
-
const abs =
|
|
31346
|
-
if (!
|
|
31354
|
+
const abs = join11(ctx.root, relPath2);
|
|
31355
|
+
if (!existsSync14(abs))
|
|
31347
31356
|
continue;
|
|
31348
|
-
const content3 =
|
|
31357
|
+
const content3 = readFileSync12(abs, "utf8");
|
|
31349
31358
|
const banner = checkDocMetaBanner(relPath2, content3);
|
|
31350
31359
|
if (banner) {
|
|
31351
31360
|
issues.push(banner);
|
|
@@ -31373,7 +31382,7 @@ function runDocMetaRule(ctx) {
|
|
|
31373
31382
|
var docMetaRule = { id: "doc-meta", run: runDocMetaRule };
|
|
31374
31383
|
|
|
31375
31384
|
// src/audit/rules/links.ts
|
|
31376
|
-
import { existsSync as
|
|
31385
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
|
|
31377
31386
|
import { dirname as dirname9, resolve as resolve5 } from "node:path";
|
|
31378
31387
|
function resolveLink2(sourceFile, target) {
|
|
31379
31388
|
const withoutAnchor = target.split("#")[0]?.split("?")[0] ?? "";
|
|
@@ -31397,13 +31406,13 @@ function checkAgentFile(input, resolved, relSource) {
|
|
|
31397
31406
|
return null;
|
|
31398
31407
|
}
|
|
31399
31408
|
const agentPath = resolved.endsWith(".md") ? resolved : `${resolved}.md`;
|
|
31400
|
-
if (
|
|
31409
|
+
if (existsSync15(agentPath))
|
|
31401
31410
|
return null;
|
|
31402
31411
|
return issue("links", relSource, { message: "missing agent file", link: input.linkLabel });
|
|
31403
31412
|
}
|
|
31404
31413
|
function checkBrokenPath(ctx) {
|
|
31405
31414
|
const { input, pathPart, resolved, relSource, relTarget } = ctx;
|
|
31406
|
-
if (!(pathPart && !
|
|
31415
|
+
if (!(pathPart && !existsSync15(resolved)))
|
|
31407
31416
|
return null;
|
|
31408
31417
|
return issue("links", relSource, {
|
|
31409
31418
|
message: `broken link → ${relTarget}`,
|
|
@@ -31412,9 +31421,9 @@ function checkBrokenPath(ctx) {
|
|
|
31412
31421
|
}
|
|
31413
31422
|
function checkBrokenAnchor(ctx) {
|
|
31414
31423
|
const { input, anchor, resolved, relSource, relTarget } = ctx;
|
|
31415
|
-
if (!(anchor &&
|
|
31424
|
+
if (!(anchor && existsSync15(resolved)))
|
|
31416
31425
|
return null;
|
|
31417
|
-
const targetContent =
|
|
31426
|
+
const targetContent = readFileSync13(resolved, "utf8");
|
|
31418
31427
|
const slugs = extractHeadingSlugs(targetContent, resolved);
|
|
31419
31428
|
const anchorSlug = slugifyAnchor(anchor);
|
|
31420
31429
|
if (slugs.has(anchorSlug))
|
|
@@ -31466,8 +31475,8 @@ function runLinksRule(ctx) {
|
|
|
31466
31475
|
var linksRule = { id: "links", run: runLinksRule };
|
|
31467
31476
|
|
|
31468
31477
|
// src/audit/rules/near-duplicate.ts
|
|
31469
|
-
import { readFileSync as
|
|
31470
|
-
import { join as
|
|
31478
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
31479
|
+
import { join as join12 } from "node:path";
|
|
31471
31480
|
|
|
31472
31481
|
// src/audit/core/ssot-fit.ts
|
|
31473
31482
|
var DEFAULT_SSOT_OVERLAP_MIN = 0.35;
|
|
@@ -31755,7 +31764,7 @@ function runNearDuplicateRule(ctx) {
|
|
|
31755
31764
|
const ignored = ignoredPairSet(ctx);
|
|
31756
31765
|
const entries = eligibleEntries(ctx);
|
|
31757
31766
|
const fingerprints = entries.map((e) => {
|
|
31758
|
-
const content3 =
|
|
31767
|
+
const content3 = readFileSync14(join12(ctx.root, e.path), "utf8");
|
|
31759
31768
|
const tokens = tokenize2(bodyWithoutSsotNoise(content3));
|
|
31760
31769
|
return {
|
|
31761
31770
|
path: e.path,
|
|
@@ -31851,11 +31860,11 @@ function runProsePolicyRule(ctx) {
|
|
|
31851
31860
|
var prosePolicyRule = { id: "prose-policy", run: runProsePolicyRule };
|
|
31852
31861
|
|
|
31853
31862
|
// src/audit/rules/review-deps.ts
|
|
31854
|
-
import { relative as
|
|
31863
|
+
import { relative as relative7 } from "node:path";
|
|
31855
31864
|
function runReviewDepsRule(ctx) {
|
|
31856
31865
|
const issues = [];
|
|
31857
31866
|
for (const abs of collectScanFiles(ctx.config, ctx.root, ctx.skillIndex)) {
|
|
31858
|
-
const path3 = normalizeRelPath(
|
|
31867
|
+
const path3 = normalizeRelPath(relative7(ctx.root, abs));
|
|
31859
31868
|
for (const marker of parseReviewDepsMarkers(readFileContent(abs))) {
|
|
31860
31869
|
issues.push(...validateMarker(ctx.root, path3, marker.paths));
|
|
31861
31870
|
}
|
|
@@ -31916,16 +31925,16 @@ function runScanRootsRule(ctx) {
|
|
|
31916
31925
|
var scanRootsRule = { id: "scan-roots", run: runScanRootsRule };
|
|
31917
31926
|
|
|
31918
31927
|
// src/audit/rules/skill-index.ts
|
|
31919
|
-
import { existsSync as
|
|
31920
|
-
import { join as
|
|
31928
|
+
import { existsSync as existsSync16, readdirSync as readdirSync2, readFileSync as readFileSync15 } from "node:fs";
|
|
31929
|
+
import { join as join13, relative as relative8 } from "node:path";
|
|
31921
31930
|
function walkSkillMarkdown(dir) {
|
|
31922
31931
|
const files = [];
|
|
31923
|
-
if (!
|
|
31932
|
+
if (!existsSync16(dir))
|
|
31924
31933
|
return files;
|
|
31925
|
-
for (const entry of
|
|
31934
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
31926
31935
|
if (entry.name.startsWith("."))
|
|
31927
31936
|
continue;
|
|
31928
|
-
const fullPath =
|
|
31937
|
+
const fullPath = join13(dir, entry.name);
|
|
31929
31938
|
if (entry.isDirectory()) {
|
|
31930
31939
|
files.push(...walkSkillMarkdown(fullPath));
|
|
31931
31940
|
continue;
|
|
@@ -31951,10 +31960,8 @@ function parseReadmeTaxonomySlugs(content3) {
|
|
|
31951
31960
|
}
|
|
31952
31961
|
function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
31953
31962
|
const issues = [];
|
|
31954
|
-
const rel =
|
|
31955
|
-
const content3 =
|
|
31956
|
-
if (isGeneratedReference(content3))
|
|
31957
|
-
return issues;
|
|
31963
|
+
const rel = relative8(ctx.root, filePath).replace(/\\/g, "/");
|
|
31964
|
+
const content3 = readFileSync15(filePath, "utf8");
|
|
31958
31965
|
for (const match of content3.matchAll(SKILL_LINK_RE)) {
|
|
31959
31966
|
const slug2 = match[1];
|
|
31960
31967
|
if (!slug2)
|
|
@@ -31967,14 +31974,14 @@ function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
|
31967
31974
|
}
|
|
31968
31975
|
function taxonomyIssuesForReadme(input) {
|
|
31969
31976
|
const { ctx, index: index2, skillRoot, diskSlugs, nonPublic } = input;
|
|
31970
|
-
const readmePath =
|
|
31971
|
-
if (!
|
|
31977
|
+
const readmePath = join13(ctx.root, skillRoot.relPath, "README.md");
|
|
31978
|
+
if (!existsSync16(readmePath))
|
|
31972
31979
|
return [];
|
|
31973
|
-
const readme =
|
|
31980
|
+
const readme = readFileSync15(readmePath, "utf8");
|
|
31974
31981
|
if (!readme.includes("## Taxonomy"))
|
|
31975
31982
|
return [];
|
|
31976
31983
|
const taxonomySlugs = parseReadmeTaxonomySlugs(readme);
|
|
31977
|
-
const nestedSlugs = diskSlugs.filter((slug2) =>
|
|
31984
|
+
const nestedSlugs = diskSlugs.filter((slug2) => existsSync16(join13(ctx.root, skillRoot.relPath, slug2, "SKILL.md")));
|
|
31978
31985
|
const foreign = new Set(index2.foreignSlugs);
|
|
31979
31986
|
const publicSlugs = nestedSlugs.filter((slug2) => !(nonPublic.has(slug2) || foreign.has(slug2)));
|
|
31980
31987
|
const relReadme = `${skillRoot.relPath}/README.md`;
|
|
@@ -32007,10 +32014,10 @@ function slugsForRoot(skillRoot, index2, owned) {
|
|
|
32007
32014
|
function auditSkillRoot(input) {
|
|
32008
32015
|
const { ctx, index: index2, skillRoot, owned } = input;
|
|
32009
32016
|
const issues = [];
|
|
32010
|
-
const base = skillRoot.kind === "nested" ?
|
|
32017
|
+
const base = skillRoot.kind === "nested" ? join13(ctx.root, skillRoot.relPath) : ctx.root;
|
|
32011
32018
|
for (const slug2 of slugsForRoot(skillRoot, index2, owned)) {
|
|
32012
|
-
const skillDir =
|
|
32013
|
-
if (!
|
|
32019
|
+
const skillDir = join13(base, slug2);
|
|
32020
|
+
if (!existsSync16(skillDir))
|
|
32014
32021
|
continue;
|
|
32015
32022
|
for (const skillMd of walkSkillMarkdown(skillDir)) {
|
|
32016
32023
|
issues.push(...scanFileForSkillLinks(ctx, skillMd, index2));
|
|
@@ -32060,8 +32067,8 @@ function runSsotRule(ctx) {
|
|
|
32060
32067
|
var ssotRule = { id: "ssot", run: runSsotRule };
|
|
32061
32068
|
|
|
32062
32069
|
// src/audit/rules/ssot-summary.ts
|
|
32063
|
-
import { readFileSync as
|
|
32064
|
-
import { join as
|
|
32070
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
32071
|
+
import { join as join14 } from "node:path";
|
|
32065
32072
|
function runSsotSummaryRule(ctx) {
|
|
32066
32073
|
const overlapMin = ctx.config.docsLint?.ssotOverlapMin ?? DEFAULT_SSOT_OVERLAP_MIN;
|
|
32067
32074
|
const margin = ctx.config.docsLint?.ssotBetterMatchMargin ?? DEFAULT_BETTER_MATCH_MARGIN;
|
|
@@ -32069,7 +32076,7 @@ function runSsotSummaryRule(ctx) {
|
|
|
32069
32076
|
const files = ctx.ssotEntries.map((entry) => ({
|
|
32070
32077
|
path: entry.path,
|
|
32071
32078
|
summary: entry.summary,
|
|
32072
|
-
content:
|
|
32079
|
+
content: readFileSync16(join14(ctx.root, entry.path), "utf8")
|
|
32073
32080
|
}));
|
|
32074
32081
|
return evaluateSsotFit(files, {
|
|
32075
32082
|
overlapMin,
|
|
@@ -32099,7 +32106,6 @@ var docsRules = [
|
|
|
32099
32106
|
];
|
|
32100
32107
|
var skillsRules = [
|
|
32101
32108
|
{ ...skillIndexRule, global: true },
|
|
32102
|
-
{ ...generatedReferencesRule, global: true },
|
|
32103
32109
|
prosePolicyRule
|
|
32104
32110
|
];
|
|
32105
32111
|
var allRules = [...docsRules, ...skillsRules];
|
|
@@ -32436,20 +32442,20 @@ async function runAudit(options) {
|
|
|
32436
32442
|
}
|
|
32437
32443
|
|
|
32438
32444
|
// src/customize/resolve.ts
|
|
32439
|
-
import { existsSync as
|
|
32440
|
-
import { basename as basename3, join as
|
|
32445
|
+
import { existsSync as existsSync17, readFileSync as readFileSync17 } from "node:fs";
|
|
32446
|
+
import { basename as basename3, join as join15, relative as relative9 } from "node:path";
|
|
32441
32447
|
function customizeDir(root2) {
|
|
32442
|
-
return
|
|
32448
|
+
return join15(root2, REGISTRY_DIR_REL, "customize");
|
|
32443
32449
|
}
|
|
32444
32450
|
function customizePathForSlug(root2, slug2) {
|
|
32445
|
-
return
|
|
32451
|
+
return join15(customizeDir(root2), `${slug2}.md`);
|
|
32446
32452
|
}
|
|
32447
32453
|
function resolveSlugFile(root2, slug2) {
|
|
32448
32454
|
const direct = customizePathForSlug(root2, slug2);
|
|
32449
|
-
if (
|
|
32455
|
+
if (existsSync17(direct)) {
|
|
32450
32456
|
return {
|
|
32451
|
-
content:
|
|
32452
|
-
path: normalizeRelPath(
|
|
32457
|
+
content: readFileSync17(direct, "utf8"),
|
|
32458
|
+
path: normalizeRelPath(relative9(root2, direct))
|
|
32453
32459
|
};
|
|
32454
32460
|
}
|
|
32455
32461
|
return { content: null, path: null };
|
|
@@ -32470,11 +32476,11 @@ function readAlwaysInclude(root2, basenames, skipBasename) {
|
|
|
32470
32476
|
const file = basename3(name);
|
|
32471
32477
|
if (skipBasename && file === skipBasename)
|
|
32472
32478
|
continue;
|
|
32473
|
-
const abs =
|
|
32474
|
-
if (!
|
|
32479
|
+
const abs = join15(dir, file);
|
|
32480
|
+
if (!existsSync17(abs))
|
|
32475
32481
|
continue;
|
|
32476
|
-
parts.push(
|
|
32477
|
-
paths.push(normalizeRelPath(
|
|
32482
|
+
parts.push(readFileSync17(abs, "utf8").trimEnd());
|
|
32483
|
+
paths.push(normalizeRelPath(relative9(root2, abs)));
|
|
32478
32484
|
}
|
|
32479
32485
|
return { parts, paths };
|
|
32480
32486
|
}
|
|
@@ -32597,39 +32603,39 @@ Customize override for /${slug2} (from ${from}):
|
|
|
32597
32603
|
|
|
32598
32604
|
// src/init/init.ts
|
|
32599
32605
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
32600
|
-
import { copyFileSync, existsSync as
|
|
32601
|
-
import { join as
|
|
32606
|
+
import { copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync4, readFileSync as readFileSync19 } from "node:fs";
|
|
32607
|
+
import { join as join19 } from "node:path";
|
|
32602
32608
|
import process6 from "node:process";
|
|
32603
32609
|
|
|
32604
32610
|
// src/init/merge-hooks.ts
|
|
32605
|
-
import { existsSync as
|
|
32606
|
-
import { dirname as dirname12, join as
|
|
32611
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync3, readFileSync as readFileSync18, writeFileSync as writeFileSync4 } from "node:fs";
|
|
32612
|
+
import { dirname as dirname12, join as join18 } from "node:path";
|
|
32607
32613
|
|
|
32608
32614
|
// src/init/package-paths.ts
|
|
32609
|
-
import { existsSync as
|
|
32610
|
-
import { dirname as dirname10, join as
|
|
32615
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
32616
|
+
import { dirname as dirname10, join as join16 } from "node:path";
|
|
32611
32617
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32612
32618
|
var MODULE_DIR = dirname10(fileURLToPath4(import.meta.url));
|
|
32613
|
-
var PACKAGE_ROOT_CANDIDATES = [
|
|
32619
|
+
var PACKAGE_ROOT_CANDIDATES = [join16(MODULE_DIR, "../.."), join16(MODULE_DIR, "..")];
|
|
32614
32620
|
function resolvePackageRoot() {
|
|
32615
32621
|
for (const candidate of PACKAGE_ROOT_CANDIDATES) {
|
|
32616
|
-
if (
|
|
32622
|
+
if (existsSync18(join16(candidate, "package.json")))
|
|
32617
32623
|
return candidate;
|
|
32618
32624
|
}
|
|
32619
32625
|
throw new Error("Could not resolve @csark0812/skeleton package root");
|
|
32620
32626
|
}
|
|
32621
32627
|
function resolveTemplatesDir() {
|
|
32622
|
-
const dir =
|
|
32623
|
-
if (!
|
|
32628
|
+
const dir = join16(resolvePackageRoot(), "templates/skeleton-init");
|
|
32629
|
+
if (!existsSync18(dir)) {
|
|
32624
32630
|
throw new Error("Missing templates/skeleton-init in package");
|
|
32625
32631
|
}
|
|
32626
32632
|
return dir;
|
|
32627
32633
|
}
|
|
32628
32634
|
|
|
32629
32635
|
// src/init/resolve-hook-command.ts
|
|
32630
|
-
import { existsSync as
|
|
32636
|
+
import { existsSync as existsSync19, realpathSync as realpathSync5 } from "node:fs";
|
|
32631
32637
|
import { createRequire as createRequire3 } from "node:module";
|
|
32632
|
-
import { dirname as dirname11, join as
|
|
32638
|
+
import { dirname as dirname11, join as join17, relative as relative10, resolve as resolve6 } from "node:path";
|
|
32633
32639
|
var PACKAGE_NAME = "@csark0812/skeleton";
|
|
32634
32640
|
var CLI_DIST = "dist/cli.js";
|
|
32635
32641
|
var PACKAGE_ROOT = resolvePackageRoot();
|
|
@@ -32643,12 +32649,12 @@ function safeRealpath2(path3) {
|
|
|
32643
32649
|
}
|
|
32644
32650
|
}
|
|
32645
32651
|
function toRepoRelative(cwd, absPath) {
|
|
32646
|
-
const rel =
|
|
32652
|
+
const rel = relative10(safeRealpath2(cwd), safeRealpath2(absPath)).replace(/\\/g, "/");
|
|
32647
32653
|
return rel.startsWith("..") ? absPath.replace(/\\/g, "/") : rel;
|
|
32648
32654
|
}
|
|
32649
32655
|
function tryResolvePublishedCli(cwd) {
|
|
32650
32656
|
try {
|
|
32651
|
-
const req = createRequire3(
|
|
32657
|
+
const req = createRequire3(join17(cwd, "package.json"));
|
|
32652
32658
|
return req.resolve(`${PACKAGE_NAME}/${CLI_DIST}`);
|
|
32653
32659
|
} catch {
|
|
32654
32660
|
return null;
|
|
@@ -32657,8 +32663,8 @@ function tryResolvePublishedCli(cwd) {
|
|
|
32657
32663
|
function walkNodeModulesCli(cwd) {
|
|
32658
32664
|
let dir = cwd;
|
|
32659
32665
|
while (true) {
|
|
32660
|
-
const candidate =
|
|
32661
|
-
if (
|
|
32666
|
+
const candidate = join17(dir, "node_modules", PACKAGE_NAME, CLI_DIST);
|
|
32667
|
+
if (existsSync19(candidate))
|
|
32662
32668
|
return candidate;
|
|
32663
32669
|
const parent = dirname11(dir);
|
|
32664
32670
|
if (parent === dir)
|
|
@@ -32668,7 +32674,7 @@ function walkNodeModulesCli(cwd) {
|
|
|
32668
32674
|
return null;
|
|
32669
32675
|
}
|
|
32670
32676
|
function isInsidePackageRoot(cwd) {
|
|
32671
|
-
const rel =
|
|
32677
|
+
const rel = relative10(PACKAGE_ROOT, resolve6(cwd)).replace(/\\/g, "/");
|
|
32672
32678
|
return rel === "" || !(rel.startsWith("..") || rel.startsWith("/"));
|
|
32673
32679
|
}
|
|
32674
32680
|
function nodeCliHookCommand(cliPath) {
|
|
@@ -32699,14 +32705,14 @@ function identityKey(platform, event, matcher) {
|
|
|
32699
32705
|
return `skeleton:customize:${platform}:${event}:${matcher}`;
|
|
32700
32706
|
}
|
|
32701
32707
|
function loadFragment(name, hookCommand) {
|
|
32702
|
-
const raw =
|
|
32708
|
+
const raw = readFileSync18(join18(TEMPLATES_DIR, name), "utf8");
|
|
32703
32709
|
return JSON.parse(raw.replaceAll("{{HOOK_COMMAND}}", hookCommand));
|
|
32704
32710
|
}
|
|
32705
32711
|
function readJson(path3) {
|
|
32706
|
-
if (!
|
|
32712
|
+
if (!existsSync20(path3))
|
|
32707
32713
|
return null;
|
|
32708
32714
|
try {
|
|
32709
|
-
return JSON.parse(
|
|
32715
|
+
return JSON.parse(readFileSync18(path3, "utf8"));
|
|
32710
32716
|
} catch (error) {
|
|
32711
32717
|
throw new Error(`Invalid JSON in ${path3}: ${error}`);
|
|
32712
32718
|
}
|
|
@@ -32866,10 +32872,10 @@ function mergeNestedHooks(args) {
|
|
|
32866
32872
|
}
|
|
32867
32873
|
function mergeHookConfigs(opts) {
|
|
32868
32874
|
const results = [];
|
|
32869
|
-
const cursorPath =
|
|
32875
|
+
const cursorPath = join18(opts.cwd, ".cursor/hooks.json");
|
|
32870
32876
|
const cursorFragment = loadFragment("cursor-hooks.fragment.json", opts.hookCommand);
|
|
32871
32877
|
results.push(mergeCursorHooks(cursorPath, cursorFragment, opts));
|
|
32872
|
-
const claudePath =
|
|
32878
|
+
const claudePath = join18(opts.cwd, ".claude/settings.json");
|
|
32873
32879
|
const claudeFragment = loadFragment("claude-settings.fragment.json", opts.hookCommand);
|
|
32874
32880
|
results.push(mergeNestedHooks({
|
|
32875
32881
|
platform: "claude",
|
|
@@ -32878,8 +32884,8 @@ function mergeHookConfigs(opts) {
|
|
|
32878
32884
|
eventName: "PostToolUse",
|
|
32879
32885
|
opts
|
|
32880
32886
|
}));
|
|
32881
|
-
const codexPath =
|
|
32882
|
-
if (
|
|
32887
|
+
const codexPath = join18(opts.cwd, ".codex/hooks.json");
|
|
32888
|
+
if (existsSync20(join18(opts.cwd, ".codex"))) {
|
|
32883
32889
|
const codexFragment = loadFragment("codex-hooks.fragment.json", opts.hookCommand);
|
|
32884
32890
|
results.push(mergeNestedHooks({
|
|
32885
32891
|
platform: "codex",
|
|
@@ -32894,11 +32900,11 @@ function mergeHookConfigs(opts) {
|
|
|
32894
32900
|
return results;
|
|
32895
32901
|
}
|
|
32896
32902
|
function mergePackageJsonScripts(cwd) {
|
|
32897
|
-
const pkgPath =
|
|
32898
|
-
if (!
|
|
32903
|
+
const pkgPath = join18(cwd, "package.json");
|
|
32904
|
+
if (!existsSync20(pkgPath))
|
|
32899
32905
|
return "skipped";
|
|
32900
|
-
const fragment = JSON.parse(
|
|
32901
|
-
const pkg = JSON.parse(
|
|
32906
|
+
const fragment = JSON.parse(readFileSync18(join18(TEMPLATES_DIR, "package.json.scripts.fragment.json"), "utf8"));
|
|
32907
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
32902
32908
|
pkg.scripts ??= {};
|
|
32903
32909
|
let changed = false;
|
|
32904
32910
|
for (const [key, value] of Object.entries(fragment)) {
|
|
@@ -32954,23 +32960,23 @@ function skillsAddArgs(options = {}) {
|
|
|
32954
32960
|
// src/init/init.ts
|
|
32955
32961
|
var TEMPLATES_DIR2 = resolveTemplatesDir();
|
|
32956
32962
|
function writeScaffold(cwd) {
|
|
32957
|
-
const skeletonDir2 =
|
|
32963
|
+
const skeletonDir2 = join19(cwd, ".skeleton");
|
|
32958
32964
|
mkdirSync4(skeletonDir2, { recursive: true });
|
|
32959
32965
|
let created = false;
|
|
32960
|
-
const tomlPath =
|
|
32961
|
-
const legacyYaml =
|
|
32962
|
-
if (!(
|
|
32963
|
-
copyFileSync(
|
|
32966
|
+
const tomlPath = join19(cwd, "skeleton.toml");
|
|
32967
|
+
const legacyYaml = join19(skeletonDir2, "config.yaml");
|
|
32968
|
+
if (!(existsSync21(tomlPath) || existsSync21(legacyYaml))) {
|
|
32969
|
+
copyFileSync(join19(TEMPLATES_DIR2, "skeleton.toml"), tomlPath);
|
|
32964
32970
|
created = true;
|
|
32965
32971
|
}
|
|
32966
|
-
mkdirSync4(
|
|
32972
|
+
mkdirSync4(join19(skeletonDir2, "customize"), { recursive: true });
|
|
32967
32973
|
return created ? "created" : "skipped";
|
|
32968
32974
|
}
|
|
32969
32975
|
function assertPackageResolvable(cwd) {
|
|
32970
|
-
const pkgPath =
|
|
32971
|
-
if (!
|
|
32976
|
+
const pkgPath = join19(cwd, "package.json");
|
|
32977
|
+
if (!existsSync21(pkgPath))
|
|
32972
32978
|
return;
|
|
32973
|
-
const pkg = JSON.parse(
|
|
32979
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
32974
32980
|
const hasDep = pkg.devDependencies?.["@csark0812/skeleton"] || pkg.dependencies?.["@csark0812/skeleton"];
|
|
32975
32981
|
if (!hasDep) {
|
|
32976
32982
|
try {
|
|
@@ -33054,7 +33060,7 @@ function parseInitArgs(argv) {
|
|
|
33054
33060
|
// src/plugins/build.ts
|
|
33055
33061
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
33056
33062
|
import { createHash as createHash2 } from "node:crypto";
|
|
33057
|
-
import { existsSync as
|
|
33063
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync5 } from "node:fs";
|
|
33058
33064
|
import { basename as basename4, dirname as dirname13, resolve as resolve7 } from "node:path";
|
|
33059
33065
|
function parseBuildPluginArgs(argv) {
|
|
33060
33066
|
let check = false;
|
|
@@ -33095,7 +33101,7 @@ function localImportPaths(tsAbs, content3) {
|
|
|
33095
33101
|
candidates.push(resolve7(dir, spec), resolve7(dir, `${spec}.ts`), resolve7(dir, `${spec}.js`), resolve7(dir, spec, "index.ts"));
|
|
33096
33102
|
}
|
|
33097
33103
|
for (const candidate of candidates) {
|
|
33098
|
-
if (
|
|
33104
|
+
if (existsSync22(candidate) && candidate.endsWith(".ts")) {
|
|
33099
33105
|
deps.push(candidate);
|
|
33100
33106
|
break;
|
|
33101
33107
|
}
|
|
@@ -33112,7 +33118,7 @@ function sourceFingerprint(tsAbs, seen = new Set) {
|
|
|
33112
33118
|
if (seen.has(abs))
|
|
33113
33119
|
return;
|
|
33114
33120
|
seen.add(abs);
|
|
33115
|
-
const content3 =
|
|
33121
|
+
const content3 = readFileSync20(abs, "utf8");
|
|
33116
33122
|
hash2.update(basename4(abs));
|
|
33117
33123
|
hash2.update("\x00");
|
|
33118
33124
|
hash2.update(content3);
|
|
@@ -33130,7 +33136,7 @@ function writeStamp(tsAbs, mjsAbs) {
|
|
|
33130
33136
|
}
|
|
33131
33137
|
async function buildOne(tsAbs) {
|
|
33132
33138
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
33133
|
-
if (!
|
|
33139
|
+
if (!existsSync22(tsAbs)) {
|
|
33134
33140
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
33135
33141
|
}
|
|
33136
33142
|
const proc = spawnSync3("bun", ["build", tsAbs, "--target=node", "--format=esm", `--outfile=${mjsAbs}`, "--packages=external"], { encoding: "utf8" });
|
|
@@ -33150,17 +33156,17 @@ ${proc.stderr || proc.stdout || `exit ${proc.status}`}`);
|
|
|
33150
33156
|
}
|
|
33151
33157
|
function checkOne(tsAbs) {
|
|
33152
33158
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
33153
|
-
if (!
|
|
33159
|
+
if (!existsSync22(mjsAbs)) {
|
|
33154
33160
|
throw new Error(`Plugin not built: ${tsAbs} (missing ${mjsAbs}). Run: skeleton build-plugin`);
|
|
33155
33161
|
}
|
|
33156
|
-
if (!
|
|
33162
|
+
if (!existsSync22(tsAbs)) {
|
|
33157
33163
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
33158
33164
|
}
|
|
33159
33165
|
const stampAbs = stampPathForMjs(mjsAbs);
|
|
33160
|
-
if (!
|
|
33166
|
+
if (!existsSync22(stampAbs)) {
|
|
33161
33167
|
throw new Error(`Plugin stale: ${mjsAbs} has no fingerprint stamp. Run: skeleton build-plugin`);
|
|
33162
33168
|
}
|
|
33163
|
-
const expected =
|
|
33169
|
+
const expected = readFileSync20(stampAbs, "utf8").trim();
|
|
33164
33170
|
const actual = sourceFingerprint(tsAbs);
|
|
33165
33171
|
if (expected !== actual) {
|
|
33166
33172
|
throw new Error(`Plugin stale: ${mjsAbs} does not match ${tsAbs} (or local imports). Run: skeleton build-plugin`);
|
|
@@ -33188,178 +33194,10 @@ async function runBuildPlugin(options = {}) {
|
|
|
33188
33194
|
return { built, checked };
|
|
33189
33195
|
}
|
|
33190
33196
|
|
|
33191
|
-
// src/references/run.ts
|
|
33192
|
-
import process8 from "node:process";
|
|
33193
|
-
|
|
33194
|
-
// src/references/sync.ts
|
|
33195
|
-
import {
|
|
33196
|
-
existsSync as existsSync25,
|
|
33197
|
-
mkdirSync as mkdirSync5,
|
|
33198
|
-
readdirSync as readdirSync5,
|
|
33199
|
-
readFileSync as readFileSync23,
|
|
33200
|
-
unlinkSync as unlinkSync2,
|
|
33201
|
-
writeFileSync as writeFileSync6
|
|
33202
|
-
} from "node:fs";
|
|
33203
|
-
import { dirname as dirname14, join as join22, relative as relative13 } from "node:path";
|
|
33204
|
-
import process7 from "node:process";
|
|
33205
|
-
function resolveOwnership(root2, override) {
|
|
33206
|
-
if (override !== undefined)
|
|
33207
|
-
return override;
|
|
33208
|
-
try {
|
|
33209
|
-
return loadConfig(root2).skillOwnership;
|
|
33210
|
-
} catch {}
|
|
33211
|
-
}
|
|
33212
|
-
function walkMarkdownFiles2(dir, root2) {
|
|
33213
|
-
const files = [];
|
|
33214
|
-
if (!existsSync25(dir))
|
|
33215
|
-
return files;
|
|
33216
|
-
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
33217
|
-
if (entry.name.startsWith("."))
|
|
33218
|
-
continue;
|
|
33219
|
-
const fullPath = join22(dir, entry.name);
|
|
33220
|
-
if (entry.isDirectory()) {
|
|
33221
|
-
files.push(...walkMarkdownFiles2(fullPath, root2));
|
|
33222
|
-
continue;
|
|
33223
|
-
}
|
|
33224
|
-
if (entry.name.endsWith(".md")) {
|
|
33225
|
-
files.push(normalizeRelPath(relative13(root2, fullPath)));
|
|
33226
|
-
}
|
|
33227
|
-
}
|
|
33228
|
-
return files;
|
|
33229
|
-
}
|
|
33230
|
-
function collectGeneratedInDir(input) {
|
|
33231
|
-
const { dir, refsDir, skillDir, files } = input;
|
|
33232
|
-
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
33233
|
-
const fullPath = join22(dir, entry.name);
|
|
33234
|
-
if (entry.isDirectory()) {
|
|
33235
|
-
collectGeneratedInDir({ dir: fullPath, refsDir, skillDir, files });
|
|
33236
|
-
continue;
|
|
33237
|
-
}
|
|
33238
|
-
if (!entry.name.endsWith(".md"))
|
|
33239
|
-
continue;
|
|
33240
|
-
const content3 = readFileSync23(fullPath, "utf8");
|
|
33241
|
-
if (!isGeneratedReference(content3))
|
|
33242
|
-
continue;
|
|
33243
|
-
const refPath = normalizeRelPath(relative13(refsDir, fullPath));
|
|
33244
|
-
files.push(generatedRefPath(skillDir, refPath));
|
|
33245
|
-
}
|
|
33246
|
-
}
|
|
33247
|
-
function listGeneratedReferenceFiles(root2, skillDir) {
|
|
33248
|
-
const refsDir = join22(root2, skillDir, "references");
|
|
33249
|
-
if (!existsSync25(refsDir))
|
|
33250
|
-
return [];
|
|
33251
|
-
const files = [];
|
|
33252
|
-
collectGeneratedInDir({ dir: refsDir, refsDir, skillDir, files });
|
|
33253
|
-
return files;
|
|
33254
|
-
}
|
|
33255
|
-
function syncGeneratedCopy(ctx, refPath) {
|
|
33256
|
-
const { root: root2, plan, options, result } = ctx;
|
|
33257
|
-
const sourceRel = normalizeRelPath(join22(CANONICAL_REFS_DIR, refPath));
|
|
33258
|
-
const canonicalPath = join22(root2, sourceRel);
|
|
33259
|
-
if (!existsSync25(canonicalPath)) {
|
|
33260
|
-
throw new Error(`canonical reference missing: ${sourceRel}`);
|
|
33261
|
-
}
|
|
33262
|
-
const targetRel = generatedRefPath(plan.skillDir, refPath);
|
|
33263
|
-
const targetPath = join22(root2, targetRel);
|
|
33264
|
-
const canonicalContent = readFileSync23(canonicalPath, "utf8");
|
|
33265
|
-
const nextContent = formatGeneratedHeader(sourceRel) + canonicalContent;
|
|
33266
|
-
if (!options.dryRun)
|
|
33267
|
-
mkdirSync5(dirname14(targetPath), { recursive: true });
|
|
33268
|
-
const existing = existsSync25(targetPath) ? readFileSync23(targetPath, "utf8") : null;
|
|
33269
|
-
if (existing !== nextContent) {
|
|
33270
|
-
if (!options.dryRun)
|
|
33271
|
-
writeFileSync6(targetPath, nextContent, "utf8");
|
|
33272
|
-
result.written.push(targetRel);
|
|
33273
|
-
} else {
|
|
33274
|
-
result.skipped.push(targetRel);
|
|
33275
|
-
}
|
|
33276
|
-
}
|
|
33277
|
-
function rewritePlanLinks(ctx, skillDir) {
|
|
33278
|
-
const { root: root2, plan, options, result } = ctx;
|
|
33279
|
-
if (options.rewriteLinks === false)
|
|
33280
|
-
return;
|
|
33281
|
-
for (const relFile of walkMarkdownFiles2(skillDir, root2)) {
|
|
33282
|
-
const filePath = join22(root2, relFile);
|
|
33283
|
-
const content3 = readFileSync23(filePath, "utf8");
|
|
33284
|
-
const next = rewriteSharedRefLinks(content3, relFile, plan.skillDir);
|
|
33285
|
-
if (next === content3)
|
|
33286
|
-
continue;
|
|
33287
|
-
if (!options.dryRun)
|
|
33288
|
-
writeFileSync6(filePath, next, "utf8");
|
|
33289
|
-
result.rewritten.push(relFile);
|
|
33290
|
-
}
|
|
33291
|
-
}
|
|
33292
|
-
function removeStaleGenerated(ctx) {
|
|
33293
|
-
const { root: root2, plan, options, result } = ctx;
|
|
33294
|
-
for (const generatedRel of listGeneratedReferenceFiles(root2, plan.skillDir)) {
|
|
33295
|
-
const refPath = generatedRel.slice(`${plan.skillDir}/references/`.length);
|
|
33296
|
-
if (plan.refPaths.has(refPath))
|
|
33297
|
-
continue;
|
|
33298
|
-
if (!options.dryRun)
|
|
33299
|
-
unlinkSync2(join22(root2, generatedRel));
|
|
33300
|
-
result.removed.push(generatedRel);
|
|
33301
|
-
}
|
|
33302
|
-
}
|
|
33303
|
-
function syncPlan(ctx) {
|
|
33304
|
-
const skillDir = join22(ctx.root, ctx.plan.skillDir);
|
|
33305
|
-
for (const refPath of ctx.plan.refPaths) {
|
|
33306
|
-
syncGeneratedCopy(ctx, refPath);
|
|
33307
|
-
}
|
|
33308
|
-
rewritePlanLinks(ctx, skillDir);
|
|
33309
|
-
removeStaleGenerated(ctx);
|
|
33310
|
-
}
|
|
33311
|
-
function syncReferences(options = {}) {
|
|
33312
|
-
const root2 = options.root ?? process7.cwd();
|
|
33313
|
-
const canonicalDir = join22(root2, CANONICAL_REFS_DIR);
|
|
33314
|
-
if (!existsSync25(canonicalDir)) {
|
|
33315
|
-
throw new Error(`canonical references dir not found: ${CANONICAL_REFS_DIR}`);
|
|
33316
|
-
}
|
|
33317
|
-
const result = { written: [], rewritten: [], removed: [], skipped: [] };
|
|
33318
|
-
const plans = discoverSkillReferencePlans(root2, resolveOwnership(root2, options.ownership));
|
|
33319
|
-
for (const plan of plans)
|
|
33320
|
-
syncPlan({ root: root2, plan, options, result });
|
|
33321
|
-
return result;
|
|
33322
|
-
}
|
|
33323
|
-
|
|
33324
|
-
// src/references/run.ts
|
|
33325
|
-
function runReferencesSync(options = {}) {
|
|
33326
|
-
return syncReferences(options);
|
|
33327
|
-
}
|
|
33328
|
-
function runReferencesCheck(options = {}) {
|
|
33329
|
-
const root2 = options.root ?? process8.cwd();
|
|
33330
|
-
let ownership;
|
|
33331
|
-
try {
|
|
33332
|
-
ownership = loadConfig(root2).skillOwnership;
|
|
33333
|
-
} catch {
|
|
33334
|
-
ownership = undefined;
|
|
33335
|
-
}
|
|
33336
|
-
const issues = runGeneratedReferencesCheck(root2, ownership);
|
|
33337
|
-
return printReport(issues, {
|
|
33338
|
-
strict: options.strict,
|
|
33339
|
-
json: options.json,
|
|
33340
|
-
label: "References check"
|
|
33341
|
-
});
|
|
33342
|
-
}
|
|
33343
|
-
function printSyncSection(label, files, prefix) {
|
|
33344
|
-
if (files.length === 0)
|
|
33345
|
-
return;
|
|
33346
|
-
console.log(label);
|
|
33347
|
-
for (const file of files)
|
|
33348
|
-
console.log(` ${prefix} ${file}`);
|
|
33349
|
-
}
|
|
33350
|
-
function printSyncResult(result) {
|
|
33351
|
-
printSyncSection(`references sync: wrote ${result.written.length} file(s)`, result.written, "+");
|
|
33352
|
-
printSyncSection(`references sync: rewrote links in ${result.rewritten.length} file(s)`, result.rewritten, "~");
|
|
33353
|
-
printSyncSection(`references sync: removed ${result.removed.length} stale file(s)`, result.removed, "-");
|
|
33354
|
-
if (result.written.length === 0 && result.rewritten.length === 0 && result.removed.length === 0) {
|
|
33355
|
-
console.log(`references sync: up to date (${result.skipped.length} file(s) checked)`);
|
|
33356
|
-
}
|
|
33357
|
-
}
|
|
33358
|
-
|
|
33359
33197
|
// src/validate/changed.ts
|
|
33360
33198
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
33361
|
-
import { existsSync as
|
|
33362
|
-
import { basename as basename5, extname as extname2, join as
|
|
33199
|
+
import { existsSync as existsSync23, readFileSync as readFileSync21 } from "node:fs";
|
|
33200
|
+
import { basename as basename5, extname as extname2, join as join20 } from "node:path";
|
|
33363
33201
|
|
|
33364
33202
|
// src/validate/git-diff.ts
|
|
33365
33203
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -33477,25 +33315,25 @@ function validationIssue(code3, file, message) {
|
|
|
33477
33315
|
return issue("validate-changed", file, { code: code3, message, severity: "error" });
|
|
33478
33316
|
}
|
|
33479
33317
|
function validateJson(relPath2, root2) {
|
|
33480
|
-
const abs =
|
|
33318
|
+
const abs = join20(root2, relPath2);
|
|
33481
33319
|
try {
|
|
33482
|
-
parseJsonContent(
|
|
33320
|
+
parseJsonContent(readFileSync21(abs, "utf8"));
|
|
33483
33321
|
return null;
|
|
33484
33322
|
} catch (error) {
|
|
33485
33323
|
return validationIssue("invalid-json", relPath2, `invalid JSON: ${error}`);
|
|
33486
33324
|
}
|
|
33487
33325
|
}
|
|
33488
33326
|
function validatePolicy(relPath2, root2) {
|
|
33489
|
-
const abs =
|
|
33327
|
+
const abs = join20(root2, relPath2);
|
|
33490
33328
|
try {
|
|
33491
|
-
loadPolicyFile(abs,
|
|
33329
|
+
loadPolicyFile(abs, readFileSync21(abs, "utf8"));
|
|
33492
33330
|
return null;
|
|
33493
33331
|
} catch (error) {
|
|
33494
33332
|
return validationIssue("invalid-policy", relPath2, `invalid policy: ${error}`);
|
|
33495
33333
|
}
|
|
33496
33334
|
}
|
|
33497
33335
|
function validateShell(relPath2, root2) {
|
|
33498
|
-
const abs =
|
|
33336
|
+
const abs = join20(root2, relPath2);
|
|
33499
33337
|
const shellcheck = spawnSync5("shellcheck", [abs], { encoding: "utf8" });
|
|
33500
33338
|
if (shellcheck.status === 0)
|
|
33501
33339
|
return null;
|
|
@@ -33519,11 +33357,11 @@ function resolvePaths(options) {
|
|
|
33519
33357
|
};
|
|
33520
33358
|
}
|
|
33521
33359
|
function packageManagerFromPackageJson(root2) {
|
|
33522
|
-
const pkgPath =
|
|
33523
|
-
if (!
|
|
33360
|
+
const pkgPath = join20(root2, "package.json");
|
|
33361
|
+
if (!existsSync23(pkgPath))
|
|
33524
33362
|
return null;
|
|
33525
33363
|
try {
|
|
33526
|
-
const pkg = JSON.parse(
|
|
33364
|
+
const pkg = JSON.parse(readFileSync21(pkgPath, "utf8"));
|
|
33527
33365
|
const raw = pkg.packageManager?.split("@")[0];
|
|
33528
33366
|
if (raw === "bun" || raw === "npm" || raw === "pnpm" || raw === "yarn")
|
|
33529
33367
|
return raw;
|
|
@@ -33531,13 +33369,13 @@ function packageManagerFromPackageJson(root2) {
|
|
|
33531
33369
|
return null;
|
|
33532
33370
|
}
|
|
33533
33371
|
function packageManagerFromLockfiles(root2) {
|
|
33534
|
-
if (
|
|
33372
|
+
if (existsSync23(join20(root2, "bun.lock")) || existsSync23(join20(root2, "bun.lockb")))
|
|
33535
33373
|
return "bun";
|
|
33536
|
-
if (
|
|
33374
|
+
if (existsSync23(join20(root2, "pnpm-lock.yaml")))
|
|
33537
33375
|
return "pnpm";
|
|
33538
|
-
if (
|
|
33376
|
+
if (existsSync23(join20(root2, "yarn.lock")))
|
|
33539
33377
|
return "yarn";
|
|
33540
|
-
if (
|
|
33378
|
+
if (existsSync23(join20(root2, "package-lock.json")))
|
|
33541
33379
|
return "npm";
|
|
33542
33380
|
return null;
|
|
33543
33381
|
}
|
|
@@ -33563,8 +33401,8 @@ function emptyBuckets() {
|
|
|
33563
33401
|
function classifySinglePath(input) {
|
|
33564
33402
|
const { relPath: relPath2, ctx, state, bucketCtx } = input;
|
|
33565
33403
|
const normalized = normalizeRelPath(relPath2);
|
|
33566
|
-
const abs =
|
|
33567
|
-
if (!
|
|
33404
|
+
const abs = join20(ctx.root, normalized);
|
|
33405
|
+
if (!existsSync23(abs)) {
|
|
33568
33406
|
state.missing.push(normalized);
|
|
33569
33407
|
return;
|
|
33570
33408
|
}
|
|
@@ -33636,7 +33474,7 @@ function discoverImpactedDocuments(input) {
|
|
|
33636
33474
|
}
|
|
33637
33475
|
function impactedDocumentForPath(abs, root2, changed) {
|
|
33638
33476
|
const path3 = relPath(abs, root2);
|
|
33639
|
-
const reviewDependencies = reviewDependencyPatterns(
|
|
33477
|
+
const reviewDependencies = reviewDependencyPatterns(readFileSync21(abs, "utf8"));
|
|
33640
33478
|
const reasons = impactReasons(path3, reviewDependencies, changed);
|
|
33641
33479
|
return reasons.length > 0 ? { path: path3, reviewDependencies, reasons } : null;
|
|
33642
33480
|
}
|
|
@@ -33660,7 +33498,7 @@ function dateModeImpactDiagnostics(input) {
|
|
|
33660
33498
|
for (const impacted of input.impactedDocuments) {
|
|
33661
33499
|
if (!impacted.reasons.some((reason) => reason.kind === "changed-review-dependency"))
|
|
33662
33500
|
continue;
|
|
33663
|
-
const content3 =
|
|
33501
|
+
const content3 = readFileSync21(join20(input.root, impacted.path), "utf8");
|
|
33664
33502
|
if (changed.has(impacted.path) && docMetaLastReviewed(content3) === today)
|
|
33665
33503
|
continue;
|
|
33666
33504
|
diagnostics.push(validationIssue("impacted-document-review-required", impacted.path, "a linked review dependency changed; re-read the entire document, then attest it with --fix=doc-meta --confirm-reviewed and include the document in validation"));
|
|
@@ -33887,9 +33725,6 @@ Commands:
|
|
|
33887
33725
|
catalog [--check] [--strict] write or check .skeleton/catalog.md (gitignored)
|
|
33888
33726
|
customize resolve <slug> [--json]
|
|
33889
33727
|
hook customize (reads a host hook payload on stdin)
|
|
33890
|
-
references sync [--dry-run] [--no-rewrite-links]
|
|
33891
|
-
references check [--json] [--strict]
|
|
33892
|
-
|
|
33893
33728
|
Note: \`register\` was removed — add a source-of-truth marker to the file and run \`skeleton catalog\`.`);
|
|
33894
33729
|
}
|
|
33895
33730
|
function parseValidateChangedArgs(rest) {
|
|
@@ -33964,7 +33799,7 @@ function handleCustomizeResolve(argv) {
|
|
|
33964
33799
|
if (json) {
|
|
33965
33800
|
console.log(JSON.stringify(result, null, 2));
|
|
33966
33801
|
} else if (result.content) {
|
|
33967
|
-
|
|
33802
|
+
process7.stdout.write(result.content);
|
|
33968
33803
|
}
|
|
33969
33804
|
return 0;
|
|
33970
33805
|
}
|
|
@@ -33973,31 +33808,13 @@ function handleHook(argv) {
|
|
|
33973
33808
|
usage();
|
|
33974
33809
|
return 1;
|
|
33975
33810
|
}
|
|
33976
|
-
|
|
33811
|
+
process7.stdout.write(runCustomizeHook(readFileSync22(0, "utf8")));
|
|
33977
33812
|
return 0;
|
|
33978
33813
|
}
|
|
33979
33814
|
function handleInit(argv) {
|
|
33980
33815
|
runInit(parseInitArgs(argv));
|
|
33981
33816
|
return 0;
|
|
33982
33817
|
}
|
|
33983
|
-
function handleReferences(argv) {
|
|
33984
|
-
const sub = argv[0];
|
|
33985
|
-
if (sub === "sync") {
|
|
33986
|
-
const dryRun = argv.includes("--dry-run");
|
|
33987
|
-
const rewriteLinks = !argv.includes("--no-rewrite-links");
|
|
33988
|
-
const result = runReferencesSync({ dryRun, rewriteLinks });
|
|
33989
|
-
printSyncResult(result);
|
|
33990
|
-
return 0;
|
|
33991
|
-
}
|
|
33992
|
-
if (sub === "check") {
|
|
33993
|
-
return runReferencesCheck({
|
|
33994
|
-
json: argv.includes("--json"),
|
|
33995
|
-
strict: argv.includes("--strict")
|
|
33996
|
-
});
|
|
33997
|
-
}
|
|
33998
|
-
usage();
|
|
33999
|
-
return 1;
|
|
34000
|
-
}
|
|
34001
33818
|
async function dispatchCommand(argv) {
|
|
34002
33819
|
const command = argv[0];
|
|
34003
33820
|
const rest = argv.slice(1);
|
|
@@ -34018,29 +33835,27 @@ async function dispatchCommand(argv) {
|
|
|
34018
33835
|
return handleHook(rest);
|
|
34019
33836
|
case "init":
|
|
34020
33837
|
return handleInit(rest);
|
|
34021
|
-
case "references":
|
|
34022
|
-
return handleReferences(rest);
|
|
34023
33838
|
default:
|
|
34024
33839
|
return null;
|
|
34025
33840
|
}
|
|
34026
33841
|
}
|
|
34027
33842
|
async function main() {
|
|
34028
|
-
const argv =
|
|
33843
|
+
const argv = process7.argv.slice(2);
|
|
34029
33844
|
const command = argv[0];
|
|
34030
33845
|
if (!command || command === "--help" || command === "-h") {
|
|
34031
33846
|
usage();
|
|
34032
|
-
|
|
33847
|
+
process7.exit(command ? 0 : 1);
|
|
34033
33848
|
}
|
|
34034
33849
|
try {
|
|
34035
33850
|
const exitCode = await dispatchCommand(argv);
|
|
34036
33851
|
if (exitCode === null) {
|
|
34037
33852
|
usage();
|
|
34038
|
-
|
|
33853
|
+
process7.exit(1);
|
|
34039
33854
|
}
|
|
34040
|
-
|
|
33855
|
+
process7.exit(exitCode);
|
|
34041
33856
|
} catch (error) {
|
|
34042
33857
|
console.error(String(error));
|
|
34043
|
-
|
|
33858
|
+
process7.exit(1);
|
|
34044
33859
|
}
|
|
34045
33860
|
}
|
|
34046
33861
|
main();
|