@csark0812/skeleton 1.5.7 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -23
- package/dist/cli.js +1750 -701
- package/dist/hooks/customize-on-skill-read.js +961 -223
- package/dist/plugin-types.d.ts +19 -3
- package/package.json +3 -6
- package/schemas/config.schema.json +57 -9
- package/templates/skeleton-init/config.yaml +5 -4
- package/templates/skeleton-init/skeleton.toml +37 -0
- package/templates/skeleton-init/registry.md +0 -10
package/dist/cli.js
CHANGED
|
@@ -3037,7 +3037,6 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3037
3037
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3038
3038
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3039
3039
|
var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
|
|
3040
|
-
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/?]$/iu);
|
|
3041
3040
|
function stringArrayToHexStripped(input) {
|
|
3042
3041
|
let acc = "";
|
|
3043
3042
|
let code = 0;
|
|
@@ -3181,7 +3180,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3181
3180
|
continue;
|
|
3182
3181
|
}
|
|
3183
3182
|
} else if (input[0] === "/") {
|
|
3184
|
-
if (input[1] === ".") {
|
|
3183
|
+
if (input[1] === "." || input[1] === "/") {
|
|
3185
3184
|
output.push("/");
|
|
3186
3185
|
break;
|
|
3187
3186
|
}
|
|
@@ -3263,30 +3262,10 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3263
3262
|
}
|
|
3264
3263
|
return output;
|
|
3265
3264
|
}
|
|
3266
|
-
var BYTE_HEX = new Array(256);
|
|
3267
|
-
{
|
|
3268
|
-
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3269
|
-
for (let i = 0;i < 256; i++) {
|
|
3270
|
-
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3271
|
-
}
|
|
3272
|
-
}
|
|
3273
|
-
function isEscapeSafe(cp) {
|
|
3274
|
-
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;
|
|
3275
|
-
}
|
|
3276
|
-
function percentEncodeNonAscii(cp) {
|
|
3277
|
-
if (cp < 2048) {
|
|
3278
|
-
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3279
|
-
}
|
|
3280
|
-
if (cp < 65536) {
|
|
3281
|
-
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3282
|
-
}
|
|
3283
|
-
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3284
|
-
}
|
|
3285
3265
|
function normalizePathEncoding(input) {
|
|
3286
3266
|
let output = "";
|
|
3287
3267
|
for (let i = 0;i < input.length; i++) {
|
|
3288
|
-
|
|
3289
|
-
if (ch === "%" && i + 2 < input.length) {
|
|
3268
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
3290
3269
|
const hex = input.slice(i + 1, i + 3);
|
|
3291
3270
|
if (isHexPair(hex)) {
|
|
3292
3271
|
const normalizedHex = hex.toUpperCase();
|
|
@@ -3300,66 +3279,10 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3300
3279
|
continue;
|
|
3301
3280
|
}
|
|
3302
3281
|
}
|
|
3303
|
-
if (isPathCharacter(
|
|
3304
|
-
output +=
|
|
3305
|
-
} else {
|
|
3306
|
-
const code = input.charCodeAt(i);
|
|
3307
|
-
if (code < 128) {
|
|
3308
|
-
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3309
|
-
} else if (code < 55296 || code > 57343) {
|
|
3310
|
-
output += percentEncodeNonAscii(code);
|
|
3311
|
-
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3312
|
-
const low = input.charCodeAt(i + 1);
|
|
3313
|
-
if (low >= 56320 && low <= 57343) {
|
|
3314
|
-
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3315
|
-
i++;
|
|
3316
|
-
} else {
|
|
3317
|
-
output += percentEncodeNonAscii(65533);
|
|
3318
|
-
}
|
|
3319
|
-
} else {
|
|
3320
|
-
output += percentEncodeNonAscii(65533);
|
|
3321
|
-
}
|
|
3322
|
-
}
|
|
3323
|
-
}
|
|
3324
|
-
return output;
|
|
3325
|
-
}
|
|
3326
|
-
function normalizeQueryFragmentEncoding(input) {
|
|
3327
|
-
let output = "";
|
|
3328
|
-
for (let i = 0;i < input.length; i++) {
|
|
3329
|
-
const ch = input[i];
|
|
3330
|
-
if (ch === "%" && i + 2 < input.length) {
|
|
3331
|
-
const hex = input.slice(i + 1, i + 3);
|
|
3332
|
-
if (isHexPair(hex)) {
|
|
3333
|
-
const normalizedHex = hex.toUpperCase();
|
|
3334
|
-
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3335
|
-
if (isUnreserved(decoded)) {
|
|
3336
|
-
output += decoded;
|
|
3337
|
-
} else {
|
|
3338
|
-
output += "%" + normalizedHex;
|
|
3339
|
-
}
|
|
3340
|
-
i += 2;
|
|
3341
|
-
continue;
|
|
3342
|
-
}
|
|
3343
|
-
}
|
|
3344
|
-
if (isQueryFragmentCharacter(ch)) {
|
|
3345
|
-
output += ch;
|
|
3282
|
+
if (isPathCharacter(input[i])) {
|
|
3283
|
+
output += input[i];
|
|
3346
3284
|
} else {
|
|
3347
|
-
|
|
3348
|
-
if (code < 128) {
|
|
3349
|
-
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3350
|
-
} else if (code < 55296 || code > 57343) {
|
|
3351
|
-
output += percentEncodeNonAscii(code);
|
|
3352
|
-
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3353
|
-
const low = input.charCodeAt(i + 1);
|
|
3354
|
-
if (low >= 56320 && low <= 57343) {
|
|
3355
|
-
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3356
|
-
i++;
|
|
3357
|
-
} else {
|
|
3358
|
-
output += percentEncodeNonAscii(65533);
|
|
3359
|
-
}
|
|
3360
|
-
} else {
|
|
3361
|
-
output += percentEncodeNonAscii(65533);
|
|
3362
|
-
}
|
|
3285
|
+
output += escape(input[i]);
|
|
3363
3286
|
}
|
|
3364
3287
|
}
|
|
3365
3288
|
return output;
|
|
@@ -3367,8 +3290,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3367
3290
|
function escapePreservingEscapes(input) {
|
|
3368
3291
|
let output = "";
|
|
3369
3292
|
for (let i = 0;i < input.length; i++) {
|
|
3370
|
-
|
|
3371
|
-
if (ch === "%" && i + 2 < input.length) {
|
|
3293
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
3372
3294
|
const hex = input.slice(i + 1, i + 3);
|
|
3373
3295
|
if (isHexPair(hex)) {
|
|
3374
3296
|
output += "%" + hex.toUpperCase();
|
|
@@ -3376,22 +3298,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3376
3298
|
continue;
|
|
3377
3299
|
}
|
|
3378
3300
|
}
|
|
3379
|
-
|
|
3380
|
-
if (code < 128) {
|
|
3381
|
-
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3382
|
-
} else if (code < 55296 || code > 57343) {
|
|
3383
|
-
output += percentEncodeNonAscii(code);
|
|
3384
|
-
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3385
|
-
const low = input.charCodeAt(i + 1);
|
|
3386
|
-
if (low >= 56320 && low <= 57343) {
|
|
3387
|
-
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3388
|
-
i++;
|
|
3389
|
-
} else {
|
|
3390
|
-
output += percentEncodeNonAscii(65533);
|
|
3391
|
-
}
|
|
3392
|
-
} else {
|
|
3393
|
-
output += percentEncodeNonAscii(65533);
|
|
3394
|
-
}
|
|
3301
|
+
output += escape(input[i]);
|
|
3395
3302
|
}
|
|
3396
3303
|
return output;
|
|
3397
3304
|
}
|
|
@@ -3425,7 +3332,6 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3425
3332
|
reescapeHostDelimiters,
|
|
3426
3333
|
normalizePercentEncoding,
|
|
3427
3334
|
normalizePathEncoding,
|
|
3428
|
-
normalizeQueryFragmentEncoding,
|
|
3429
3335
|
escapePreservingEscapes,
|
|
3430
3336
|
removeDotSegments,
|
|
3431
3337
|
isIPv4,
|
|
@@ -3611,7 +3517,7 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
3611
3517
|
|
|
3612
3518
|
// node_modules/fast-uri/index.js
|
|
3613
3519
|
var require_fast_uri = __commonJS((exports, module) => {
|
|
3614
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3520
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3615
3521
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3616
3522
|
function normalize(uri, options) {
|
|
3617
3523
|
if (typeof uri === "string") {
|
|
@@ -3623,12 +3529,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3623
3529
|
}
|
|
3624
3530
|
function resolve(baseURI, relativeURI, options) {
|
|
3625
3531
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3626
|
-
const
|
|
3627
|
-
const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
|
|
3628
|
-
if (baseMalformed || relativeMalformed) {
|
|
3629
|
-
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3630
|
-
}
|
|
3631
|
-
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3532
|
+
const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3632
3533
|
schemelessOptions.skipEscape = true;
|
|
3633
3534
|
return serialize(resolved, schemelessOptions);
|
|
3634
3535
|
}
|
|
@@ -3754,8 +3655,6 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3754
3655
|
return uriTokens.join("");
|
|
3755
3656
|
}
|
|
3756
3657
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
3757
|
-
var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
3758
|
-
var AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
|
|
3759
3658
|
function getParseError(parsed, matches) {
|
|
3760
3659
|
if (matches[2] !== undefined && parsed.path && parsed.path[0] !== "/") {
|
|
3761
3660
|
return 'URI path must start with "/" when authority is present.';
|
|
@@ -3785,28 +3684,9 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3785
3684
|
uri = "//" + uri;
|
|
3786
3685
|
}
|
|
3787
3686
|
}
|
|
3788
|
-
const authorityMatch = uri.match(AUTHORITY_PREFIX);
|
|
3789
|
-
if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
|
|
3790
|
-
parsed.error = "URI authority must not contain a literal backslash.";
|
|
3791
|
-
malformedAuthorityOrPort = true;
|
|
3792
|
-
}
|
|
3793
|
-
const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
|
|
3794
|
-
if (introducerMatch !== null) {
|
|
3795
|
-
const region = introducerMatch[1];
|
|
3796
|
-
const normalizedRegion = region.replace(/[\t\n\r]/g, "");
|
|
3797
|
-
if (normalizedRegion.length >= 2) {
|
|
3798
|
-
if (normalizedRegion.slice(0, 2) !== "//") {
|
|
3799
|
-
parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
|
|
3800
|
-
malformedAuthorityOrPort = true;
|
|
3801
|
-
} else if (region.length !== normalizedRegion.length) {
|
|
3802
|
-
parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
|
|
3803
|
-
malformedAuthorityOrPort = true;
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
}
|
|
3807
3687
|
const matches = uri.match(URI_PARSE);
|
|
3808
3688
|
if (matches) {
|
|
3809
|
-
parsed.scheme = matches[1]
|
|
3689
|
+
parsed.scheme = matches[1];
|
|
3810
3690
|
parsed.userinfo = matches[3];
|
|
3811
3691
|
parsed.host = matches[4];
|
|
3812
3692
|
parsed.port = parseInt(matches[5], 10);
|
|
@@ -3865,11 +3745,12 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3865
3745
|
if (parsed.path) {
|
|
3866
3746
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3867
3747
|
}
|
|
3868
|
-
if (parsed.query) {
|
|
3869
|
-
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
3870
|
-
}
|
|
3871
3748
|
if (parsed.fragment) {
|
|
3872
|
-
|
|
3749
|
+
try {
|
|
3750
|
+
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3751
|
+
} catch {
|
|
3752
|
+
parsed.error = parsed.error || "URI malformed";
|
|
3753
|
+
}
|
|
3873
3754
|
}
|
|
3874
3755
|
}
|
|
3875
3756
|
if (schemeHandler && schemeHandler.parse) {
|
|
@@ -7821,7 +7702,7 @@ var require_stringify = __commonJS((exports) => {
|
|
|
7821
7702
|
props.push(doc.directives.tagString(tag));
|
|
7822
7703
|
return props.join(" ");
|
|
7823
7704
|
}
|
|
7824
|
-
function
|
|
7705
|
+
function stringify2(item, ctx, onComment, onChompKeep) {
|
|
7825
7706
|
if (identity.isPair(item))
|
|
7826
7707
|
return item.toString(ctx, onComment, onChompKeep);
|
|
7827
7708
|
if (identity.isAlias(item)) {
|
|
@@ -7850,14 +7731,14 @@ var require_stringify = __commonJS((exports) => {
|
|
|
7850
7731
|
${ctx.indent}${str}`;
|
|
7851
7732
|
}
|
|
7852
7733
|
exports.createStringifyContext = createStringifyContext;
|
|
7853
|
-
exports.stringify =
|
|
7734
|
+
exports.stringify = stringify2;
|
|
7854
7735
|
});
|
|
7855
7736
|
|
|
7856
7737
|
// node_modules/yaml/dist/stringify/stringifyPair.js
|
|
7857
7738
|
var require_stringifyPair = __commonJS((exports) => {
|
|
7858
7739
|
var identity = require_identity();
|
|
7859
7740
|
var Scalar = require_Scalar();
|
|
7860
|
-
var
|
|
7741
|
+
var stringify2 = require_stringify();
|
|
7861
7742
|
var stringifyComment = require_stringifyComment();
|
|
7862
7743
|
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
7863
7744
|
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
@@ -7879,7 +7760,7 @@ var require_stringifyPair = __commonJS((exports) => {
|
|
|
7879
7760
|
});
|
|
7880
7761
|
let keyCommentDone = false;
|
|
7881
7762
|
let chompKeep = false;
|
|
7882
|
-
let str =
|
|
7763
|
+
let str = stringify2.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
7883
7764
|
if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
|
7884
7765
|
if (simpleKeys)
|
|
7885
7766
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
@@ -7931,7 +7812,7 @@ ${indent}:`;
|
|
|
7931
7812
|
ctx.indent = ctx.indent.substring(2);
|
|
7932
7813
|
}
|
|
7933
7814
|
let valueCommentDone = false;
|
|
7934
|
-
const valueStr =
|
|
7815
|
+
const valueStr = stringify2.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
7935
7816
|
let ws = " ";
|
|
7936
7817
|
if (keyComment || vsb || vcb) {
|
|
7937
7818
|
ws = vsb ? `
|
|
@@ -8069,7 +7950,7 @@ var require_merge = __commonJS((exports) => {
|
|
|
8069
7950
|
var require_addPairToJSMap = __commonJS((exports) => {
|
|
8070
7951
|
var log = require_log();
|
|
8071
7952
|
var merge = require_merge();
|
|
8072
|
-
var
|
|
7953
|
+
var stringify2 = require_stringify();
|
|
8073
7954
|
var identity = require_identity();
|
|
8074
7955
|
var toJS = require_toJS();
|
|
8075
7956
|
function addPairToJSMap(ctx, map, { key, value }) {
|
|
@@ -8105,7 +7986,7 @@ var require_addPairToJSMap = __commonJS((exports) => {
|
|
|
8105
7986
|
if (typeof jsKey !== "object")
|
|
8106
7987
|
return String(jsKey);
|
|
8107
7988
|
if (identity.isNode(key) && ctx?.doc) {
|
|
8108
|
-
const strCtx =
|
|
7989
|
+
const strCtx = stringify2.createStringifyContext(ctx.doc, {});
|
|
8109
7990
|
strCtx.anchors = new Set;
|
|
8110
7991
|
for (const node of ctx.anchors.keys())
|
|
8111
7992
|
strCtx.anchors.add(node.anchor);
|
|
@@ -8167,12 +8048,12 @@ var require_Pair = __commonJS((exports) => {
|
|
|
8167
8048
|
// node_modules/yaml/dist/stringify/stringifyCollection.js
|
|
8168
8049
|
var require_stringifyCollection = __commonJS((exports) => {
|
|
8169
8050
|
var identity = require_identity();
|
|
8170
|
-
var
|
|
8051
|
+
var stringify2 = require_stringify();
|
|
8171
8052
|
var stringifyComment = require_stringifyComment();
|
|
8172
8053
|
function stringifyCollection(collection, ctx, options) {
|
|
8173
8054
|
const flow = ctx.inFlow ?? collection.flow;
|
|
8174
|
-
const
|
|
8175
|
-
return
|
|
8055
|
+
const stringify3 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
8056
|
+
return stringify3(collection, ctx, options);
|
|
8176
8057
|
}
|
|
8177
8058
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
8178
8059
|
const { indent, options: { commentString } } = ctx;
|
|
@@ -8197,7 +8078,7 @@ var require_stringifyCollection = __commonJS((exports) => {
|
|
|
8197
8078
|
}
|
|
8198
8079
|
}
|
|
8199
8080
|
chompKeep = false;
|
|
8200
|
-
let str2 =
|
|
8081
|
+
let str2 = stringify2.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
8201
8082
|
if (comment2)
|
|
8202
8083
|
str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2));
|
|
8203
8084
|
if (chompKeep && comment2)
|
|
@@ -8266,7 +8147,7 @@ ${indent}${line}` : `
|
|
|
8266
8147
|
}
|
|
8267
8148
|
if (comment)
|
|
8268
8149
|
reqNewline = true;
|
|
8269
|
-
let str =
|
|
8150
|
+
let str = stringify2.stringify(item, itemCtx, () => comment = null);
|
|
8270
8151
|
reqNewline || (reqNewline = lines.length > linesAtValue || str.includes(`
|
|
8271
8152
|
`));
|
|
8272
8153
|
if (i < items.length - 1) {
|
|
@@ -9507,7 +9388,7 @@ var require_Schema = __commonJS((exports) => {
|
|
|
9507
9388
|
// node_modules/yaml/dist/stringify/stringifyDocument.js
|
|
9508
9389
|
var require_stringifyDocument = __commonJS((exports) => {
|
|
9509
9390
|
var identity = require_identity();
|
|
9510
|
-
var
|
|
9391
|
+
var stringify2 = require_stringify();
|
|
9511
9392
|
var stringifyComment = require_stringifyComment();
|
|
9512
9393
|
function stringifyDocument(doc, options) {
|
|
9513
9394
|
const lines = [];
|
|
@@ -9522,7 +9403,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
9522
9403
|
}
|
|
9523
9404
|
if (hasDirectives)
|
|
9524
9405
|
lines.push("---");
|
|
9525
|
-
const ctx =
|
|
9406
|
+
const ctx = stringify2.createStringifyContext(doc, options);
|
|
9526
9407
|
const { commentString } = ctx.options;
|
|
9527
9408
|
if (doc.commentBefore) {
|
|
9528
9409
|
if (lines.length !== 1)
|
|
@@ -9544,7 +9425,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
9544
9425
|
contentComment = doc.contents.comment;
|
|
9545
9426
|
}
|
|
9546
9427
|
const onChompKeep = contentComment ? undefined : () => chompKeep = true;
|
|
9547
|
-
let body =
|
|
9428
|
+
let body = stringify2.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
|
|
9548
9429
|
if (contentComment)
|
|
9549
9430
|
body += stringifyComment.lineComment(body, "", commentString(contentComment));
|
|
9550
9431
|
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
|
|
@@ -9552,7 +9433,7 @@ var require_stringifyDocument = __commonJS((exports) => {
|
|
|
9552
9433
|
} else
|
|
9553
9434
|
lines.push(body);
|
|
9554
9435
|
} else {
|
|
9555
|
-
lines.push(
|
|
9436
|
+
lines.push(stringify2.stringify(doc.contents, ctx));
|
|
9556
9437
|
}
|
|
9557
9438
|
if (doc.directives?.docEnd) {
|
|
9558
9439
|
if (doc.comment) {
|
|
@@ -11571,7 +11452,7 @@ var require_cst_scalar = __commonJS((exports) => {
|
|
|
11571
11452
|
|
|
11572
11453
|
// node_modules/yaml/dist/parse/cst-stringify.js
|
|
11573
11454
|
var require_cst_stringify = __commonJS((exports) => {
|
|
11574
|
-
var
|
|
11455
|
+
var stringify2 = (cst) => ("type" in cst) ? stringifyToken(cst) : stringifyItem(cst);
|
|
11575
11456
|
function stringifyToken(token) {
|
|
11576
11457
|
switch (token.type) {
|
|
11577
11458
|
case "block-scalar": {
|
|
@@ -11624,7 +11505,7 @@ var require_cst_stringify = __commonJS((exports) => {
|
|
|
11624
11505
|
res += stringifyToken(value);
|
|
11625
11506
|
return res;
|
|
11626
11507
|
}
|
|
11627
|
-
exports.stringify =
|
|
11508
|
+
exports.stringify = stringify2;
|
|
11628
11509
|
});
|
|
11629
11510
|
|
|
11630
11511
|
// node_modules/yaml/dist/parse/cst-visit.js
|
|
@@ -13315,7 +13196,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
13315
13196
|
}
|
|
13316
13197
|
return doc;
|
|
13317
13198
|
}
|
|
13318
|
-
function
|
|
13199
|
+
function parse2(src, reviver, options) {
|
|
13319
13200
|
let _reviver = undefined;
|
|
13320
13201
|
if (typeof reviver === "function") {
|
|
13321
13202
|
_reviver = reviver;
|
|
@@ -13334,7 +13215,7 @@ var require_public_api = __commonJS((exports) => {
|
|
|
13334
13215
|
}
|
|
13335
13216
|
return doc.toJS(Object.assign({ reviver: _reviver }, options));
|
|
13336
13217
|
}
|
|
13337
|
-
function
|
|
13218
|
+
function stringify2(value, replacer, options) {
|
|
13338
13219
|
let _replacer = null;
|
|
13339
13220
|
if (typeof replacer === "function" || Array.isArray(replacer)) {
|
|
13340
13221
|
_replacer = replacer;
|
|
@@ -13356,10 +13237,10 @@ var require_public_api = __commonJS((exports) => {
|
|
|
13356
13237
|
return value.toString(options);
|
|
13357
13238
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
13358
13239
|
}
|
|
13359
|
-
exports.parse =
|
|
13240
|
+
exports.parse = parse2;
|
|
13360
13241
|
exports.parseAllDocuments = parseAllDocuments;
|
|
13361
13242
|
exports.parseDocument = parseDocument;
|
|
13362
|
-
exports.stringify =
|
|
13243
|
+
exports.stringify = stringify2;
|
|
13363
13244
|
});
|
|
13364
13245
|
|
|
13365
13246
|
// node_modules/picomatch/lib/constants.js
|
|
@@ -14136,7 +14017,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
14136
14017
|
}
|
|
14137
14018
|
return { risky: false };
|
|
14138
14019
|
};
|
|
14139
|
-
var
|
|
14020
|
+
var parse2 = (input, options) => {
|
|
14140
14021
|
if (typeof input !== "string") {
|
|
14141
14022
|
throw new TypeError("Expected a string");
|
|
14142
14023
|
}
|
|
@@ -14307,7 +14188,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
14307
14188
|
output = token.close = `)$))${extglobStar}`;
|
|
14308
14189
|
}
|
|
14309
14190
|
if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
14310
|
-
const expression =
|
|
14191
|
+
const expression = parse2(rest, { ...options, fastpaths: false }).output;
|
|
14311
14192
|
output = token.close = `)${expression})${extglobStar})`;
|
|
14312
14193
|
}
|
|
14313
14194
|
if (token.prev.type === "bos") {
|
|
@@ -14833,7 +14714,7 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
14833
14714
|
}
|
|
14834
14715
|
return state;
|
|
14835
14716
|
};
|
|
14836
|
-
|
|
14717
|
+
parse2.fastpaths = (input, options) => {
|
|
14837
14718
|
const opts = { ...options };
|
|
14838
14719
|
const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
14839
14720
|
const len = input.length;
|
|
@@ -14901,13 +14782,13 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
14901
14782
|
}
|
|
14902
14783
|
return source;
|
|
14903
14784
|
};
|
|
14904
|
-
module.exports =
|
|
14785
|
+
module.exports = parse2;
|
|
14905
14786
|
});
|
|
14906
14787
|
|
|
14907
14788
|
// node_modules/picomatch/lib/picomatch.js
|
|
14908
14789
|
var require_picomatch = __commonJS((exports, module) => {
|
|
14909
14790
|
var scan = require_scan();
|
|
14910
|
-
var
|
|
14791
|
+
var parse2 = require_parse();
|
|
14911
14792
|
var utils = require_utils2();
|
|
14912
14793
|
var constants = require_constants();
|
|
14913
14794
|
var isObject = (val) => val && typeof val === "object" && !Array.isArray(val);
|
|
@@ -14997,7 +14878,7 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
14997
14878
|
picomatch.parse = (pattern, options) => {
|
|
14998
14879
|
if (Array.isArray(pattern))
|
|
14999
14880
|
return pattern.map((p) => picomatch.parse(p, options));
|
|
15000
|
-
return
|
|
14881
|
+
return parse2(pattern, { ...options, fastpaths: false });
|
|
15001
14882
|
};
|
|
15002
14883
|
picomatch.scan = (input, options) => scan(input, options);
|
|
15003
14884
|
picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
|
@@ -15023,10 +14904,10 @@ var require_picomatch = __commonJS((exports, module) => {
|
|
|
15023
14904
|
}
|
|
15024
14905
|
let parsed = { negated: false, fastpaths: true };
|
|
15025
14906
|
if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) {
|
|
15026
|
-
parsed.output =
|
|
14907
|
+
parsed.output = parse2.fastpaths(input, options);
|
|
15027
14908
|
}
|
|
15028
14909
|
if (!parsed.output) {
|
|
15029
|
-
parsed =
|
|
14910
|
+
parsed = parse2(input, options);
|
|
15030
14911
|
}
|
|
15031
14912
|
return picomatch.compileRe(parsed, options, returnOutput, returnState);
|
|
15032
14913
|
};
|
|
@@ -15070,13 +14951,13 @@ var require_ms = __commonJS((exports, module) => {
|
|
|
15070
14951
|
options = options || {};
|
|
15071
14952
|
var type = typeof val;
|
|
15072
14953
|
if (type === "string" && val.length > 0) {
|
|
15073
|
-
return
|
|
14954
|
+
return parse2(val);
|
|
15074
14955
|
} else if (type === "number" && isFinite(val)) {
|
|
15075
14956
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
15076
14957
|
}
|
|
15077
14958
|
throw new Error("val is not a non-empty string or a valid number. val=" + JSON.stringify(val));
|
|
15078
14959
|
};
|
|
15079
|
-
function
|
|
14960
|
+
function parse2(str) {
|
|
15080
14961
|
str = String(str);
|
|
15081
14962
|
if (str.length > 100) {
|
|
15082
14963
|
return;
|
|
@@ -15771,7 +15652,7 @@ var require_extend = __commonJS((exports, module) => {
|
|
|
15771
15652
|
});
|
|
15772
15653
|
|
|
15773
15654
|
// src/cli.ts
|
|
15774
|
-
import { readFileSync as
|
|
15655
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
15775
15656
|
import process7 from "node:process";
|
|
15776
15657
|
|
|
15777
15658
|
// src/audit/config/load.ts
|
|
@@ -15781,6 +15662,883 @@ import { dirname, join } from "node:path";
|
|
|
15781
15662
|
import process2 from "node:process";
|
|
15782
15663
|
import { fileURLToPath } from "node:url";
|
|
15783
15664
|
|
|
15665
|
+
// node_modules/smol-toml/dist/date.js
|
|
15666
|
+
/*!
|
|
15667
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
15668
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
15669
|
+
*
|
|
15670
|
+
* Redistribution and use in source and binary forms, with or without
|
|
15671
|
+
* modification, are permitted provided that the following conditions are met:
|
|
15672
|
+
*
|
|
15673
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
15674
|
+
* list of conditions and the following disclaimer.
|
|
15675
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
15676
|
+
* this list of conditions and the following disclaimer in the
|
|
15677
|
+
* documentation and/or other materials provided with the distribution.
|
|
15678
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
15679
|
+
* may be used to endorse or promote products derived from this software without
|
|
15680
|
+
* specific prior written permission.
|
|
15681
|
+
*
|
|
15682
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15683
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15684
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15685
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
15686
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
15687
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
15688
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
15689
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
15690
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
15691
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
15692
|
+
*/
|
|
15693
|
+
var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
|
|
15694
|
+
|
|
15695
|
+
class TomlDate extends Date {
|
|
15696
|
+
#hasDate = false;
|
|
15697
|
+
#hasTime = false;
|
|
15698
|
+
#offset = null;
|
|
15699
|
+
constructor(date) {
|
|
15700
|
+
let hasDate = true;
|
|
15701
|
+
let hasTime = true;
|
|
15702
|
+
let offset = "Z";
|
|
15703
|
+
if (typeof date === "string") {
|
|
15704
|
+
let match = date.match(DATE_TIME_RE);
|
|
15705
|
+
if (match) {
|
|
15706
|
+
if (!match[1]) {
|
|
15707
|
+
hasDate = false;
|
|
15708
|
+
date = `0000-01-01T${date}`;
|
|
15709
|
+
}
|
|
15710
|
+
hasTime = !!match[2];
|
|
15711
|
+
hasTime && date[10] === " " && (date = date.replace(" ", "T"));
|
|
15712
|
+
if (match[2] && +match[2] > 23) {
|
|
15713
|
+
date = "";
|
|
15714
|
+
} else {
|
|
15715
|
+
offset = match[3] || null;
|
|
15716
|
+
date = date.toUpperCase();
|
|
15717
|
+
if (!offset && hasTime)
|
|
15718
|
+
date += "Z";
|
|
15719
|
+
}
|
|
15720
|
+
} else {
|
|
15721
|
+
date = "";
|
|
15722
|
+
}
|
|
15723
|
+
}
|
|
15724
|
+
super(date);
|
|
15725
|
+
if (!isNaN(this.getTime())) {
|
|
15726
|
+
this.#hasDate = hasDate;
|
|
15727
|
+
this.#hasTime = hasTime;
|
|
15728
|
+
this.#offset = offset;
|
|
15729
|
+
}
|
|
15730
|
+
}
|
|
15731
|
+
isDateTime() {
|
|
15732
|
+
return this.#hasDate && this.#hasTime;
|
|
15733
|
+
}
|
|
15734
|
+
isLocal() {
|
|
15735
|
+
return !this.#hasDate || !this.#hasTime || !this.#offset;
|
|
15736
|
+
}
|
|
15737
|
+
isDate() {
|
|
15738
|
+
return this.#hasDate && !this.#hasTime;
|
|
15739
|
+
}
|
|
15740
|
+
isTime() {
|
|
15741
|
+
return this.#hasTime && !this.#hasDate;
|
|
15742
|
+
}
|
|
15743
|
+
isValid() {
|
|
15744
|
+
return this.#hasDate || this.#hasTime;
|
|
15745
|
+
}
|
|
15746
|
+
toISOString() {
|
|
15747
|
+
let iso = super.toISOString();
|
|
15748
|
+
if (this.isDate())
|
|
15749
|
+
return iso.slice(0, 10);
|
|
15750
|
+
if (this.isTime())
|
|
15751
|
+
return iso.slice(11, 23);
|
|
15752
|
+
if (this.#offset === null)
|
|
15753
|
+
return iso.slice(0, -1);
|
|
15754
|
+
if (this.#offset === "Z")
|
|
15755
|
+
return iso;
|
|
15756
|
+
let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
|
|
15757
|
+
offset = this.#offset[0] === "-" ? offset : -offset;
|
|
15758
|
+
let offsetDate = new Date(this.getTime() - offset * 60000);
|
|
15759
|
+
return offsetDate.toISOString().slice(0, -1) + this.#offset;
|
|
15760
|
+
}
|
|
15761
|
+
static wrapAsOffsetDateTime(jsDate, offset = "Z") {
|
|
15762
|
+
let date = new TomlDate(jsDate);
|
|
15763
|
+
date.#offset = offset;
|
|
15764
|
+
return date;
|
|
15765
|
+
}
|
|
15766
|
+
static wrapAsLocalDateTime(jsDate) {
|
|
15767
|
+
let date = new TomlDate(jsDate);
|
|
15768
|
+
date.#offset = null;
|
|
15769
|
+
return date;
|
|
15770
|
+
}
|
|
15771
|
+
static wrapAsLocalDate(jsDate) {
|
|
15772
|
+
let date = new TomlDate(jsDate);
|
|
15773
|
+
date.#hasTime = false;
|
|
15774
|
+
date.#offset = null;
|
|
15775
|
+
return date;
|
|
15776
|
+
}
|
|
15777
|
+
static wrapAsLocalTime(jsDate) {
|
|
15778
|
+
let date = new TomlDate(jsDate);
|
|
15779
|
+
date.#hasDate = false;
|
|
15780
|
+
date.#offset = null;
|
|
15781
|
+
return date;
|
|
15782
|
+
}
|
|
15783
|
+
}
|
|
15784
|
+
|
|
15785
|
+
// node_modules/smol-toml/dist/error.js
|
|
15786
|
+
/*!
|
|
15787
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
15788
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
15789
|
+
*
|
|
15790
|
+
* Redistribution and use in source and binary forms, with or without
|
|
15791
|
+
* modification, are permitted provided that the following conditions are met:
|
|
15792
|
+
*
|
|
15793
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
15794
|
+
* list of conditions and the following disclaimer.
|
|
15795
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
15796
|
+
* this list of conditions and the following disclaimer in the
|
|
15797
|
+
* documentation and/or other materials provided with the distribution.
|
|
15798
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
15799
|
+
* may be used to endorse or promote products derived from this software without
|
|
15800
|
+
* specific prior written permission.
|
|
15801
|
+
*
|
|
15802
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15803
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15804
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15805
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
15806
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
15807
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
15808
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
15809
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
15810
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
15811
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
15812
|
+
*/
|
|
15813
|
+
function getLineColFromPtr(string, ptr) {
|
|
15814
|
+
let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
|
|
15815
|
+
return [lines.length, lines.pop().length + 1];
|
|
15816
|
+
}
|
|
15817
|
+
function makeCodeBlock(string, line, column) {
|
|
15818
|
+
let lines = string.split(/\r\n|\n|\r/g);
|
|
15819
|
+
let codeblock = "";
|
|
15820
|
+
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
15821
|
+
for (let i = line - 1;i <= line + 1; i++) {
|
|
15822
|
+
let l = lines[i - 1];
|
|
15823
|
+
if (!l)
|
|
15824
|
+
continue;
|
|
15825
|
+
codeblock += i.toString().padEnd(numberLen, " ");
|
|
15826
|
+
codeblock += ": ";
|
|
15827
|
+
codeblock += l;
|
|
15828
|
+
codeblock += `
|
|
15829
|
+
`;
|
|
15830
|
+
if (i === line) {
|
|
15831
|
+
codeblock += " ".repeat(numberLen + column + 2);
|
|
15832
|
+
codeblock += `^
|
|
15833
|
+
`;
|
|
15834
|
+
}
|
|
15835
|
+
}
|
|
15836
|
+
return codeblock;
|
|
15837
|
+
}
|
|
15838
|
+
|
|
15839
|
+
class TomlError extends Error {
|
|
15840
|
+
line;
|
|
15841
|
+
column;
|
|
15842
|
+
codeblock;
|
|
15843
|
+
constructor(message, options) {
|
|
15844
|
+
const [line, column] = getLineColFromPtr(options.toml, options.ptr);
|
|
15845
|
+
const codeblock = makeCodeBlock(options.toml, line, column);
|
|
15846
|
+
super(`Invalid TOML document: ${message}
|
|
15847
|
+
|
|
15848
|
+
${codeblock}`, options);
|
|
15849
|
+
this.line = line;
|
|
15850
|
+
this.column = column;
|
|
15851
|
+
this.codeblock = codeblock;
|
|
15852
|
+
}
|
|
15853
|
+
}
|
|
15854
|
+
|
|
15855
|
+
// node_modules/smol-toml/dist/util.js
|
|
15856
|
+
/*!
|
|
15857
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
15858
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
15859
|
+
*
|
|
15860
|
+
* Redistribution and use in source and binary forms, with or without
|
|
15861
|
+
* modification, are permitted provided that the following conditions are met:
|
|
15862
|
+
*
|
|
15863
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
15864
|
+
* list of conditions and the following disclaimer.
|
|
15865
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
15866
|
+
* this list of conditions and the following disclaimer in the
|
|
15867
|
+
* documentation and/or other materials provided with the distribution.
|
|
15868
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
15869
|
+
* may be used to endorse or promote products derived from this software without
|
|
15870
|
+
* specific prior written permission.
|
|
15871
|
+
*
|
|
15872
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15873
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15874
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15875
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
15876
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
15877
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
15878
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
15879
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
15880
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
15881
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
15882
|
+
*/
|
|
15883
|
+
function indexOfNewline(str, start = 0) {
|
|
15884
|
+
let idx = str.indexOf(`
|
|
15885
|
+
`, start);
|
|
15886
|
+
if (str.charCodeAt(idx - 1) === 13)
|
|
15887
|
+
idx--;
|
|
15888
|
+
return idx;
|
|
15889
|
+
}
|
|
15890
|
+
function skipComment(ctx) {
|
|
15891
|
+
for (;ctx.p < ctx.s.length; ctx.p++) {
|
|
15892
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
15893
|
+
if (c === 10)
|
|
15894
|
+
break;
|
|
15895
|
+
if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
|
|
15896
|
+
ctx.p++;
|
|
15897
|
+
break;
|
|
15898
|
+
}
|
|
15899
|
+
if (c < 32 && c !== 9 || c === 127) {
|
|
15900
|
+
throw new TomlError("control characters are not allowed in comments", {
|
|
15901
|
+
toml: ctx.s,
|
|
15902
|
+
ptr: ctx.p
|
|
15903
|
+
});
|
|
15904
|
+
}
|
|
15905
|
+
}
|
|
15906
|
+
}
|
|
15907
|
+
function skipVoid(ctx, banNewLines, banComments) {
|
|
15908
|
+
let c;
|
|
15909
|
+
while (true) {
|
|
15910
|
+
while ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10))
|
|
15911
|
+
ctx.p++;
|
|
15912
|
+
if (banComments || c !== 35)
|
|
15913
|
+
break;
|
|
15914
|
+
skipComment(ctx);
|
|
15915
|
+
}
|
|
15916
|
+
}
|
|
15917
|
+
function skipUntil(ctx, sep, end) {
|
|
15918
|
+
let ptr = ctx.p;
|
|
15919
|
+
if (!end) {
|
|
15920
|
+
ptr = indexOfNewline(ctx.s, ptr);
|
|
15921
|
+
ctx.p = ptr < 0 ? ctx.s.length : ptr;
|
|
15922
|
+
return;
|
|
15923
|
+
}
|
|
15924
|
+
for (;ctx.p < ctx.s.length; ctx.p++) {
|
|
15925
|
+
let c = ctx.s.charCodeAt(ctx.p);
|
|
15926
|
+
if (c === 35) {
|
|
15927
|
+
skipComment(ctx);
|
|
15928
|
+
} else if (c === end || c === sep) {
|
|
15929
|
+
return;
|
|
15930
|
+
}
|
|
15931
|
+
}
|
|
15932
|
+
throw new TomlError("cannot find end of structure", {
|
|
15933
|
+
toml: ctx.s,
|
|
15934
|
+
ptr
|
|
15935
|
+
});
|
|
15936
|
+
}
|
|
15937
|
+
|
|
15938
|
+
// node_modules/smol-toml/dist/primitive.js
|
|
15939
|
+
/*!
|
|
15940
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
15941
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
15942
|
+
*
|
|
15943
|
+
* Redistribution and use in source and binary forms, with or without
|
|
15944
|
+
* modification, are permitted provided that the following conditions are met:
|
|
15945
|
+
*
|
|
15946
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
15947
|
+
* list of conditions and the following disclaimer.
|
|
15948
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
15949
|
+
* this list of conditions and the following disclaimer in the
|
|
15950
|
+
* documentation and/or other materials provided with the distribution.
|
|
15951
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
15952
|
+
* may be used to endorse or promote products derived from this software without
|
|
15953
|
+
* specific prior written permission.
|
|
15954
|
+
*
|
|
15955
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
15956
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15957
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
15958
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
15959
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
15960
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
15961
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
15962
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
15963
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
15964
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
15965
|
+
*/
|
|
15966
|
+
var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
|
|
15967
|
+
var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
|
|
15968
|
+
var LEADING_ZERO = /^[+-]?0[0-9_]/;
|
|
15969
|
+
function parseString(ctx) {
|
|
15970
|
+
let start = ctx.p;
|
|
15971
|
+
let c = ctx.s.charCodeAt(ctx.p++);
|
|
15972
|
+
let first = c;
|
|
15973
|
+
let isLiteral = c === 39;
|
|
15974
|
+
let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
|
|
15975
|
+
if (isMultiline) {
|
|
15976
|
+
if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10)
|
|
15977
|
+
ctx.p++;
|
|
15978
|
+
else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)
|
|
15979
|
+
ctx.p += 2;
|
|
15980
|
+
}
|
|
15981
|
+
let parsed = "";
|
|
15982
|
+
let sliceStart = ctx.p;
|
|
15983
|
+
let state = 0;
|
|
15984
|
+
for (;ctx.p < ctx.s.length; ctx.p++) {
|
|
15985
|
+
c = ctx.s.charCodeAt(ctx.p);
|
|
15986
|
+
if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) {
|
|
15987
|
+
state = state && 3;
|
|
15988
|
+
} else if (c < 32 && c !== 9 || c === 127) {
|
|
15989
|
+
throw new TomlError("control characters are not allowed in strings", {
|
|
15990
|
+
toml: ctx.s,
|
|
15991
|
+
ptr: ctx.p
|
|
15992
|
+
});
|
|
15993
|
+
} else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
|
|
15994
|
+
if (isMultiline) {
|
|
15995
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
15996
|
+
ctx.p++;
|
|
15997
|
+
if (ctx.s.charCodeAt(ctx.p + 3) === first)
|
|
15998
|
+
ctx.p++;
|
|
15999
|
+
}
|
|
16000
|
+
if (!state)
|
|
16001
|
+
parsed += ctx.s.slice(sliceStart, ctx.p);
|
|
16002
|
+
ctx.p += isMultiline ? 3 : 1;
|
|
16003
|
+
return parsed;
|
|
16004
|
+
} else if (!state) {
|
|
16005
|
+
if (!isLiteral && c === 92) {
|
|
16006
|
+
parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
|
|
16007
|
+
state = 1;
|
|
16008
|
+
}
|
|
16009
|
+
} else if (state === 1) {
|
|
16010
|
+
if (c === 120 || c === 117 || c === 85) {
|
|
16011
|
+
let value = 0;
|
|
16012
|
+
let len = c === 120 ? 2 : c === 117 ? 4 : 8;
|
|
16013
|
+
for (let j = 0;j < len; j++, ctx.p++) {
|
|
16014
|
+
let hex = ctx.s.charCodeAt(ctx.p + 1);
|
|
16015
|
+
let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
|
|
16016
|
+
if (digit < 0)
|
|
16017
|
+
throw new TomlError("invalid non-hex character in unicode escape", { toml: ctx.s, ptr: ctx.p + 1 });
|
|
16018
|
+
value = value << 4 | digit;
|
|
16019
|
+
}
|
|
16020
|
+
if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) {
|
|
16021
|
+
throw new TomlError("invalid unicode escape", { toml: ctx.s, ptr: ctx.p });
|
|
16022
|
+
}
|
|
16023
|
+
parsed += String.fromCodePoint(value);
|
|
16024
|
+
sliceStart = ctx.p + 1;
|
|
16025
|
+
state = 0;
|
|
16026
|
+
} else if (c === 32 || c === 9) {
|
|
16027
|
+
state = 2;
|
|
16028
|
+
} else {
|
|
16029
|
+
if (c === 98)
|
|
16030
|
+
parsed += "\b";
|
|
16031
|
+
else if (c === 116)
|
|
16032
|
+
parsed += "\t";
|
|
16033
|
+
else if (c === 110)
|
|
16034
|
+
parsed += `
|
|
16035
|
+
`;
|
|
16036
|
+
else if (c === 102)
|
|
16037
|
+
parsed += "\f";
|
|
16038
|
+
else if (c === 114)
|
|
16039
|
+
parsed += "\r";
|
|
16040
|
+
else if (c === 101)
|
|
16041
|
+
parsed += "\x1B";
|
|
16042
|
+
else if (c === 34)
|
|
16043
|
+
parsed += '"';
|
|
16044
|
+
else if (c === 92)
|
|
16045
|
+
parsed += "\\";
|
|
16046
|
+
else
|
|
16047
|
+
throw new TomlError("unrecognized escape sequence", { toml: ctx.s, ptr: ctx.p });
|
|
16048
|
+
sliceStart = ctx.p + 1;
|
|
16049
|
+
state = 0;
|
|
16050
|
+
}
|
|
16051
|
+
} else if (c !== 32 && c !== 9) {
|
|
16052
|
+
if (state === 2) {
|
|
16053
|
+
throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
|
|
16054
|
+
toml: ctx.s,
|
|
16055
|
+
ptr: sliceStart
|
|
16056
|
+
});
|
|
16057
|
+
}
|
|
16058
|
+
state = !isLiteral && c === 92 ? 1 : 0;
|
|
16059
|
+
sliceStart = ctx.p;
|
|
16060
|
+
}
|
|
16061
|
+
}
|
|
16062
|
+
throw new TomlError("unfinished string", { toml: ctx.s, ptr: start });
|
|
16063
|
+
}
|
|
16064
|
+
function sliceAndTrimEndOf(ctx, start, end) {
|
|
16065
|
+
let value = ctx.s.slice(start, end);
|
|
16066
|
+
let commentIdx = value.indexOf("#");
|
|
16067
|
+
if (commentIdx > 0) {
|
|
16068
|
+
skipComment({ s: value, p: commentIdx, d: 0 });
|
|
16069
|
+
value = value.slice(0, commentIdx);
|
|
16070
|
+
}
|
|
16071
|
+
return value.trimEnd();
|
|
16072
|
+
}
|
|
16073
|
+
function parseValue(ctx, integersAsBigInt, end) {
|
|
16074
|
+
let ptr = ctx.p;
|
|
16075
|
+
let err = { toml: ctx.s, ptr };
|
|
16076
|
+
skipUntil(ctx, 44, end);
|
|
16077
|
+
let value = sliceAndTrimEndOf(ctx, ptr, ctx.p);
|
|
16078
|
+
if (!value)
|
|
16079
|
+
throw new TomlError("incomplete declaration: value expected", err);
|
|
16080
|
+
if (value === "-inf")
|
|
16081
|
+
return -Infinity;
|
|
16082
|
+
if (value === "inf" || value === "+inf")
|
|
16083
|
+
return Infinity;
|
|
16084
|
+
if (value === "nan" || value === "+nan" || value === "-nan")
|
|
16085
|
+
return NaN;
|
|
16086
|
+
if (value === "-0")
|
|
16087
|
+
return integersAsBigInt ? 0n : 0;
|
|
16088
|
+
let isInt = INT_REGEX.test(value);
|
|
16089
|
+
if (isInt || FLOAT_REGEX.test(value)) {
|
|
16090
|
+
if (LEADING_ZERO.test(value)) {
|
|
16091
|
+
throw new TomlError("leading zeroes are not allowed", err);
|
|
16092
|
+
}
|
|
16093
|
+
value = value.replace(/_/g, "");
|
|
16094
|
+
let numeric = +value;
|
|
16095
|
+
if (isNaN(numeric)) {
|
|
16096
|
+
throw new TomlError("invalid number", err);
|
|
16097
|
+
}
|
|
16098
|
+
if (isInt) {
|
|
16099
|
+
if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {
|
|
16100
|
+
throw new TomlError("integer value cannot be represented losslessly", err);
|
|
16101
|
+
}
|
|
16102
|
+
if (isInt || integersAsBigInt === true)
|
|
16103
|
+
numeric = BigInt(value);
|
|
16104
|
+
}
|
|
16105
|
+
return numeric;
|
|
16106
|
+
}
|
|
16107
|
+
const date = new TomlDate(value);
|
|
16108
|
+
if (!date.isValid())
|
|
16109
|
+
throw new TomlError("invalid value", err);
|
|
16110
|
+
return date;
|
|
16111
|
+
}
|
|
16112
|
+
|
|
16113
|
+
// node_modules/smol-toml/dist/extract.js
|
|
16114
|
+
/*!
|
|
16115
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
16116
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16117
|
+
*
|
|
16118
|
+
* Redistribution and use in source and binary forms, with or without
|
|
16119
|
+
* modification, are permitted provided that the following conditions are met:
|
|
16120
|
+
*
|
|
16121
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
16122
|
+
* list of conditions and the following disclaimer.
|
|
16123
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
16124
|
+
* this list of conditions and the following disclaimer in the
|
|
16125
|
+
* documentation and/or other materials provided with the distribution.
|
|
16126
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16127
|
+
* may be used to endorse or promote products derived from this software without
|
|
16128
|
+
* specific prior written permission.
|
|
16129
|
+
*
|
|
16130
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16131
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16132
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16133
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
16134
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
16135
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
16136
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
16137
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
16138
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
16139
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
16140
|
+
*/
|
|
16141
|
+
function extractValue(ctx, end, integersAsBigInt) {
|
|
16142
|
+
let ptr = ctx.p;
|
|
16143
|
+
let c = ctx.s.charCodeAt(ptr);
|
|
16144
|
+
if (c === 91 || c === 123) {
|
|
16145
|
+
if (!ctx.d--) {
|
|
16146
|
+
throw new TomlError("document contains excessively nested structures. aborting.", {
|
|
16147
|
+
toml: ctx.s,
|
|
16148
|
+
ptr
|
|
16149
|
+
});
|
|
16150
|
+
}
|
|
16151
|
+
let value = c === 91 ? parseArray(ctx, integersAsBigInt) : parseInlineTable(ctx, integersAsBigInt);
|
|
16152
|
+
ctx.d++;
|
|
16153
|
+
return value;
|
|
16154
|
+
}
|
|
16155
|
+
if (c === 34 || c === 39) {
|
|
16156
|
+
return parseString(ctx);
|
|
16157
|
+
}
|
|
16158
|
+
if (c === 116) {
|
|
16159
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
16160
|
+
throw new TomlError("invalid value", { toml: ctx.s, ptr });
|
|
16161
|
+
ctx.p++;
|
|
16162
|
+
return true;
|
|
16163
|
+
}
|
|
16164
|
+
if (c === 102) {
|
|
16165
|
+
if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101)
|
|
16166
|
+
throw new TomlError("invalid value", { toml: ctx.s, ptr });
|
|
16167
|
+
ctx.p++;
|
|
16168
|
+
return false;
|
|
16169
|
+
}
|
|
16170
|
+
return parseValue(ctx, integersAsBigInt, end);
|
|
16171
|
+
}
|
|
16172
|
+
|
|
16173
|
+
// node_modules/smol-toml/dist/struct.js
|
|
16174
|
+
/*!
|
|
16175
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
16176
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16177
|
+
*
|
|
16178
|
+
* Redistribution and use in source and binary forms, with or without
|
|
16179
|
+
* modification, are permitted provided that the following conditions are met:
|
|
16180
|
+
*
|
|
16181
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
16182
|
+
* list of conditions and the following disclaimer.
|
|
16183
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
16184
|
+
* this list of conditions and the following disclaimer in the
|
|
16185
|
+
* documentation and/or other materials provided with the distribution.
|
|
16186
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16187
|
+
* may be used to endorse or promote products derived from this software without
|
|
16188
|
+
* specific prior written permission.
|
|
16189
|
+
*
|
|
16190
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16191
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16192
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16193
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
16194
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
16195
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
16196
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
16197
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
16198
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
16199
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
16200
|
+
*/
|
|
16201
|
+
var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
|
|
16202
|
+
function parseKey(ctx, end = "=") {
|
|
16203
|
+
let start = ctx.p;
|
|
16204
|
+
let dot = start - 1;
|
|
16205
|
+
let parsed = [];
|
|
16206
|
+
let endPtr = ctx.s.indexOf(end, start);
|
|
16207
|
+
if (endPtr < 0) {
|
|
16208
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
16209
|
+
toml: ctx.s,
|
|
16210
|
+
ptr: start
|
|
16211
|
+
});
|
|
16212
|
+
}
|
|
16213
|
+
do {
|
|
16214
|
+
let c = ctx.s.charCodeAt(ctx.p = ++dot);
|
|
16215
|
+
if (c !== 32 && c !== 9) {
|
|
16216
|
+
if (c === 34 || c === 39) {
|
|
16217
|
+
if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) {
|
|
16218
|
+
throw new TomlError("multiline strings are not allowed in keys", {
|
|
16219
|
+
toml: ctx.s,
|
|
16220
|
+
ptr: ctx.p
|
|
16221
|
+
});
|
|
16222
|
+
}
|
|
16223
|
+
let part = parseString(ctx);
|
|
16224
|
+
dot = ctx.s.indexOf(".", ctx.p);
|
|
16225
|
+
let strEnd = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
16226
|
+
let newLine = indexOfNewline(strEnd);
|
|
16227
|
+
if (newLine > -1) {
|
|
16228
|
+
throw new TomlError("newlines are not allowed in keys", {
|
|
16229
|
+
toml: ctx.s,
|
|
16230
|
+
ptr: newLine
|
|
16231
|
+
});
|
|
16232
|
+
}
|
|
16233
|
+
if (strEnd.trimStart()) {
|
|
16234
|
+
throw new TomlError("found extra tokens after the string part", {
|
|
16235
|
+
toml: ctx.s,
|
|
16236
|
+
ptr: ctx.p
|
|
16237
|
+
});
|
|
16238
|
+
}
|
|
16239
|
+
if (endPtr < ctx.p) {
|
|
16240
|
+
endPtr = ctx.s.indexOf(end, ctx.p);
|
|
16241
|
+
if (endPtr < 0) {
|
|
16242
|
+
throw new TomlError("incomplete key-value: cannot find end of key", {
|
|
16243
|
+
toml: ctx.s,
|
|
16244
|
+
ptr: start
|
|
16245
|
+
});
|
|
16246
|
+
}
|
|
16247
|
+
}
|
|
16248
|
+
parsed.push(part);
|
|
16249
|
+
} else {
|
|
16250
|
+
dot = ctx.s.indexOf(".", ctx.p);
|
|
16251
|
+
let part = ctx.s.slice(ctx.p, dot < 0 || dot > endPtr ? endPtr : dot);
|
|
16252
|
+
if (!KEY_PART_RE.test(part)) {
|
|
16253
|
+
throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
|
|
16254
|
+
toml: ctx.s,
|
|
16255
|
+
ptr: ctx.p
|
|
16256
|
+
});
|
|
16257
|
+
}
|
|
16258
|
+
parsed.push(part.trimEnd());
|
|
16259
|
+
}
|
|
16260
|
+
}
|
|
16261
|
+
} while (dot + 1 && dot < endPtr);
|
|
16262
|
+
ctx.p = endPtr + 1;
|
|
16263
|
+
skipVoid(ctx, true, true);
|
|
16264
|
+
return parsed;
|
|
16265
|
+
}
|
|
16266
|
+
function parseInlineTable(ctx, integersAsBigInt) {
|
|
16267
|
+
let res = {};
|
|
16268
|
+
let seen = new Set;
|
|
16269
|
+
let c;
|
|
16270
|
+
ctx.p++;
|
|
16271
|
+
while (ctx.p < ctx.s.length) {
|
|
16272
|
+
skipVoid(ctx);
|
|
16273
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
|
|
16274
|
+
ctx.p++;
|
|
16275
|
+
return res;
|
|
16276
|
+
}
|
|
16277
|
+
let k;
|
|
16278
|
+
let t = res;
|
|
16279
|
+
let hasOwn = false;
|
|
16280
|
+
let p = ctx.p;
|
|
16281
|
+
let key = parseKey(ctx);
|
|
16282
|
+
for (let i = 0;i < key.length; i++) {
|
|
16283
|
+
if (i)
|
|
16284
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
16285
|
+
k = key[i];
|
|
16286
|
+
if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) {
|
|
16287
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
16288
|
+
toml: ctx.s,
|
|
16289
|
+
ptr: p
|
|
16290
|
+
});
|
|
16291
|
+
}
|
|
16292
|
+
if (!hasOwn && k === "__proto__") {
|
|
16293
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
16294
|
+
}
|
|
16295
|
+
}
|
|
16296
|
+
if (hasOwn) {
|
|
16297
|
+
throw new TomlError("trying to redefine an already defined value", {
|
|
16298
|
+
toml: ctx.s,
|
|
16299
|
+
ptr: ctx.p
|
|
16300
|
+
});
|
|
16301
|
+
}
|
|
16302
|
+
let value = extractValue(ctx, 125, integersAsBigInt);
|
|
16303
|
+
seen.add(t[k] = value);
|
|
16304
|
+
skipVoid(ctx);
|
|
16305
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) {
|
|
16306
|
+
return res;
|
|
16307
|
+
}
|
|
16308
|
+
if (c !== 44) {
|
|
16309
|
+
throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
|
|
16310
|
+
}
|
|
16311
|
+
}
|
|
16312
|
+
throw new TomlError("unfinished table encountered", {
|
|
16313
|
+
toml: ctx.s,
|
|
16314
|
+
ptr: ctx.p
|
|
16315
|
+
});
|
|
16316
|
+
}
|
|
16317
|
+
function parseArray(ctx, integersAsBigInt) {
|
|
16318
|
+
let res = [];
|
|
16319
|
+
let c;
|
|
16320
|
+
ctx.p++;
|
|
16321
|
+
while (ctx.p < ctx.s.length) {
|
|
16322
|
+
skipVoid(ctx);
|
|
16323
|
+
if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
|
|
16324
|
+
ctx.p++;
|
|
16325
|
+
return res;
|
|
16326
|
+
}
|
|
16327
|
+
res.push(extractValue(ctx, 93, integersAsBigInt));
|
|
16328
|
+
skipVoid(ctx);
|
|
16329
|
+
if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) {
|
|
16330
|
+
return res;
|
|
16331
|
+
}
|
|
16332
|
+
if (c !== 44) {
|
|
16333
|
+
throw new TomlError("expected comma or end of structure", { toml: ctx.s, ptr: ctx.p - 1 });
|
|
16334
|
+
}
|
|
16335
|
+
}
|
|
16336
|
+
throw new TomlError("unfinished array encountered", {
|
|
16337
|
+
toml: ctx.s,
|
|
16338
|
+
ptr: ctx.p
|
|
16339
|
+
});
|
|
16340
|
+
}
|
|
16341
|
+
|
|
16342
|
+
// node_modules/smol-toml/dist/parse.js
|
|
16343
|
+
/*!
|
|
16344
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
16345
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16346
|
+
*
|
|
16347
|
+
* Redistribution and use in source and binary forms, with or without
|
|
16348
|
+
* modification, are permitted provided that the following conditions are met:
|
|
16349
|
+
*
|
|
16350
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
16351
|
+
* list of conditions and the following disclaimer.
|
|
16352
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
16353
|
+
* this list of conditions and the following disclaimer in the
|
|
16354
|
+
* documentation and/or other materials provided with the distribution.
|
|
16355
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16356
|
+
* may be used to endorse or promote products derived from this software without
|
|
16357
|
+
* specific prior written permission.
|
|
16358
|
+
*
|
|
16359
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16360
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16361
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16362
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
16363
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
16364
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
16365
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
16366
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
16367
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
16368
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
16369
|
+
*/
|
|
16370
|
+
function peekTable(key, table, meta, type) {
|
|
16371
|
+
let t = table;
|
|
16372
|
+
let m = meta;
|
|
16373
|
+
let k;
|
|
16374
|
+
let hasOwn = false;
|
|
16375
|
+
let state;
|
|
16376
|
+
for (let i = 0;i < key.length; i++) {
|
|
16377
|
+
if (i) {
|
|
16378
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
16379
|
+
m = (state = m[k]).c;
|
|
16380
|
+
if (type === 0 && (state.t === 1 || state.t === 2)) {
|
|
16381
|
+
return null;
|
|
16382
|
+
}
|
|
16383
|
+
if (state.t === 2) {
|
|
16384
|
+
let l = t.length - 1;
|
|
16385
|
+
t = t[l];
|
|
16386
|
+
m = m[l].c;
|
|
16387
|
+
}
|
|
16388
|
+
}
|
|
16389
|
+
k = key[i];
|
|
16390
|
+
if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) {
|
|
16391
|
+
return null;
|
|
16392
|
+
}
|
|
16393
|
+
if (!hasOwn) {
|
|
16394
|
+
if (k === "__proto__") {
|
|
16395
|
+
Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true });
|
|
16396
|
+
Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true });
|
|
16397
|
+
}
|
|
16398
|
+
m[k] = {
|
|
16399
|
+
t: i < key.length - 1 && type === 2 ? 3 : type,
|
|
16400
|
+
d: false,
|
|
16401
|
+
i: 0,
|
|
16402
|
+
c: {}
|
|
16403
|
+
};
|
|
16404
|
+
}
|
|
16405
|
+
}
|
|
16406
|
+
state = m[k];
|
|
16407
|
+
if (state.t !== type && !(type === 1 && state.t === 3)) {
|
|
16408
|
+
return null;
|
|
16409
|
+
}
|
|
16410
|
+
if (type === 2) {
|
|
16411
|
+
if (!state.d) {
|
|
16412
|
+
state.d = true;
|
|
16413
|
+
t[k] = [];
|
|
16414
|
+
}
|
|
16415
|
+
t[k].push(t = {});
|
|
16416
|
+
state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} };
|
|
16417
|
+
}
|
|
16418
|
+
if (state.d) {
|
|
16419
|
+
return null;
|
|
16420
|
+
}
|
|
16421
|
+
state.d = true;
|
|
16422
|
+
if (type === 1) {
|
|
16423
|
+
t = hasOwn ? t[k] : t[k] = {};
|
|
16424
|
+
} else if (type === 0 && hasOwn) {
|
|
16425
|
+
return null;
|
|
16426
|
+
}
|
|
16427
|
+
return [k, t, state.c];
|
|
16428
|
+
}
|
|
16429
|
+
function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
|
|
16430
|
+
let ctx = { s: toml, p: 0, d: maxDepth };
|
|
16431
|
+
let res = {};
|
|
16432
|
+
let meta = {};
|
|
16433
|
+
let tmp;
|
|
16434
|
+
let tbl = res;
|
|
16435
|
+
let m = meta;
|
|
16436
|
+
skipVoid(ctx);
|
|
16437
|
+
while (ctx.p < toml.length) {
|
|
16438
|
+
if (toml.charCodeAt(ctx.p) === 91) {
|
|
16439
|
+
let isTableArray = toml.charCodeAt(++ctx.p) === 91;
|
|
16440
|
+
tmp = ctx.p += +isTableArray;
|
|
16441
|
+
let k = parseKey(ctx, "]");
|
|
16442
|
+
if (isTableArray) {
|
|
16443
|
+
if (toml.charCodeAt(ctx.p - 1) !== 93) {
|
|
16444
|
+
throw new TomlError("expected end of table declaration", {
|
|
16445
|
+
toml,
|
|
16446
|
+
ptr: ctx.p - 1
|
|
16447
|
+
});
|
|
16448
|
+
}
|
|
16449
|
+
ctx.p++;
|
|
16450
|
+
}
|
|
16451
|
+
let p = peekTable(k, res, meta, isTableArray ? 2 : 1);
|
|
16452
|
+
if (!p) {
|
|
16453
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
16454
|
+
toml,
|
|
16455
|
+
ptr: tmp
|
|
16456
|
+
});
|
|
16457
|
+
}
|
|
16458
|
+
m = p[2];
|
|
16459
|
+
tbl = p[1];
|
|
16460
|
+
} else {
|
|
16461
|
+
tmp = ctx.p;
|
|
16462
|
+
let k = parseKey(ctx);
|
|
16463
|
+
let p = peekTable(k, tbl, m, 0);
|
|
16464
|
+
if (!p) {
|
|
16465
|
+
throw new TomlError("trying to redefine an already defined table or value", {
|
|
16466
|
+
toml,
|
|
16467
|
+
ptr: tmp
|
|
16468
|
+
});
|
|
16469
|
+
}
|
|
16470
|
+
p[1][p[0]] = extractValue(ctx, undefined, integersAsBigInt);
|
|
16471
|
+
}
|
|
16472
|
+
skipVoid(ctx, true);
|
|
16473
|
+
if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && tmp !== 13) {
|
|
16474
|
+
throw new TomlError("each key-value declaration must be followed by an end-of-line", {
|
|
16475
|
+
toml,
|
|
16476
|
+
ptr: ctx.p
|
|
16477
|
+
});
|
|
16478
|
+
}
|
|
16479
|
+
skipVoid(ctx);
|
|
16480
|
+
}
|
|
16481
|
+
return res;
|
|
16482
|
+
}
|
|
16483
|
+
|
|
16484
|
+
// node_modules/smol-toml/dist/stringify.js
|
|
16485
|
+
/*!
|
|
16486
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
16487
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16488
|
+
*
|
|
16489
|
+
* Redistribution and use in source and binary forms, with or without
|
|
16490
|
+
* modification, are permitted provided that the following conditions are met:
|
|
16491
|
+
*
|
|
16492
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
16493
|
+
* list of conditions and the following disclaimer.
|
|
16494
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
16495
|
+
* this list of conditions and the following disclaimer in the
|
|
16496
|
+
* documentation and/or other materials provided with the distribution.
|
|
16497
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16498
|
+
* may be used to endorse or promote products derived from this software without
|
|
16499
|
+
* specific prior written permission.
|
|
16500
|
+
*
|
|
16501
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16502
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16503
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16504
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
16505
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
16506
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
16507
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
16508
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
16509
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
16510
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
16511
|
+
*/
|
|
16512
|
+
|
|
16513
|
+
// node_modules/smol-toml/dist/index.js
|
|
16514
|
+
/*!
|
|
16515
|
+
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
16516
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16517
|
+
*
|
|
16518
|
+
* Redistribution and use in source and binary forms, with or without
|
|
16519
|
+
* modification, are permitted provided that the following conditions are met:
|
|
16520
|
+
*
|
|
16521
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
16522
|
+
* list of conditions and the following disclaimer.
|
|
16523
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
16524
|
+
* this list of conditions and the following disclaimer in the
|
|
16525
|
+
* documentation and/or other materials provided with the distribution.
|
|
16526
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
16527
|
+
* may be used to endorse or promote products derived from this software without
|
|
16528
|
+
* specific prior written permission.
|
|
16529
|
+
*
|
|
16530
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16531
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
16532
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16533
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
16534
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
16535
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
16536
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
16537
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
16538
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
16539
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
16540
|
+
*/
|
|
16541
|
+
|
|
15784
16542
|
// node_modules/yaml/dist/index.js
|
|
15785
16543
|
var composer = require_composer();
|
|
15786
16544
|
var Document = require_Document();
|
|
@@ -15828,11 +16586,9 @@ var $visit = visit.visit;
|
|
|
15828
16586
|
var $visitAsync = visit.visitAsync;
|
|
15829
16587
|
|
|
15830
16588
|
// src/audit/core/shared.ts
|
|
15831
|
-
var
|
|
16589
|
+
var CATALOG_REL_PATH = ".skeleton/catalog.md";
|
|
15832
16590
|
var REGISTRY_DIR_REL = ".skeleton";
|
|
15833
16591
|
var EXTERNAL_LINK_RE = /^(https?:|mailto:|#)/;
|
|
15834
|
-
var SOURCE_OF_TRUTH_BANNER_RE = /\*\*Source of truth for\*\*/;
|
|
15835
|
-
var SOURCE_OF_TRUTH_BANNER_LINE_RE = /^\s*\*\*Source of truth for\*\*/m;
|
|
15836
16592
|
var DOC_META_RE = /<!--\s*doc-meta:\s*owner=[^|]+\|\s*last-reviewed=\d{4}-\d{2}-\d{2}\s*-->/;
|
|
15837
16593
|
var DOC_META_LAST_REVIEWED_RE = /last-reviewed=(\d{4}-\d{2}-\d{2})/;
|
|
15838
16594
|
function docMetaLastReviewed(content) {
|
|
@@ -15933,6 +16689,8 @@ var SCHEMA_CANDIDATES = [
|
|
|
15933
16689
|
join(dirname(fileURLToPath(import.meta.url)), "../schemas/config.schema.json"),
|
|
15934
16690
|
join(dirname(fileURLToPath(import.meta.url)), "../../schemas/config.schema.json")
|
|
15935
16691
|
];
|
|
16692
|
+
var ROOT_CONFIG_TOML = "skeleton.toml";
|
|
16693
|
+
var LEGACY_CONFIG_YAML = join(".skeleton", "config.yaml");
|
|
15936
16694
|
function resolveSchemaPath() {
|
|
15937
16695
|
for (const candidate of SCHEMA_CANDIDATES) {
|
|
15938
16696
|
if (existsSync(candidate))
|
|
@@ -15947,44 +16705,64 @@ var COVERAGE_BUILTIN_EXCLUDES = [
|
|
|
15947
16705
|
"**/fixtures/**",
|
|
15948
16706
|
"templates/**"
|
|
15949
16707
|
];
|
|
16708
|
+
function hasConfigMarker(dir) {
|
|
16709
|
+
return existsSync(join(dir, ROOT_CONFIG_TOML)) || existsSync(join(dir, LEGACY_CONFIG_YAML));
|
|
16710
|
+
}
|
|
15950
16711
|
function findRepoRoot(startDir = process2.cwd()) {
|
|
15951
16712
|
let dir = startDir;
|
|
15952
16713
|
while (true) {
|
|
15953
|
-
if (
|
|
16714
|
+
if (hasConfigMarker(dir))
|
|
15954
16715
|
return dir;
|
|
15955
16716
|
const parent = dirname(dir);
|
|
15956
16717
|
if (parent === dir) {
|
|
15957
|
-
throw new Error(
|
|
16718
|
+
throw new Error(`No ${ROOT_CONFIG_TOML} or ${LEGACY_CONFIG_YAML} found — run skeleton init or create config manually`);
|
|
15958
16719
|
}
|
|
15959
16720
|
dir = parent;
|
|
15960
16721
|
}
|
|
15961
16722
|
}
|
|
15962
|
-
function validateConfig(raw) {
|
|
16723
|
+
function validateConfig(raw, sourceLabel) {
|
|
15963
16724
|
const schema = JSON.parse(readFileSync(resolveSchemaPath(), "utf8"));
|
|
15964
16725
|
const ajv = new import_ajv.default({ allErrors: true, strict: false });
|
|
15965
16726
|
const validate = ajv.compile(schema);
|
|
15966
16727
|
if (!validate(raw)) {
|
|
15967
16728
|
const detail = validate.errors?.map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
|
|
15968
|
-
throw new Error(`Invalid
|
|
16729
|
+
throw new Error(`Invalid ${sourceLabel}: ${detail ?? "schema validation failed"}`);
|
|
15969
16730
|
}
|
|
15970
16731
|
const config = raw;
|
|
15971
16732
|
validateDraftPathPrefixes(config.draftPathPrefixes);
|
|
15972
16733
|
return config;
|
|
15973
16734
|
}
|
|
15974
|
-
function
|
|
15975
|
-
const
|
|
15976
|
-
|
|
15977
|
-
|
|
16735
|
+
function loadConfigDetailed(root) {
|
|
16736
|
+
const tomlPath = join(root, ROOT_CONFIG_TOML);
|
|
16737
|
+
const yamlPath = join(root, LEGACY_CONFIG_YAML);
|
|
16738
|
+
const hasToml = existsSync(tomlPath);
|
|
16739
|
+
const hasYaml = existsSync(yamlPath);
|
|
16740
|
+
if (!(hasToml || hasYaml)) {
|
|
16741
|
+
throw new Error(`Missing ${ROOT_CONFIG_TOML} (or legacy ${LEGACY_CONFIG_YAML})`);
|
|
16742
|
+
}
|
|
16743
|
+
if (hasToml && hasYaml) {
|
|
16744
|
+
console.error(`warning: both ${ROOT_CONFIG_TOML} and ${LEGACY_CONFIG_YAML} exist — using ${ROOT_CONFIG_TOML}; legacy YAML is ignored`);
|
|
15978
16745
|
}
|
|
15979
|
-
|
|
15980
|
-
|
|
16746
|
+
if (hasToml) {
|
|
16747
|
+
const raw2 = parse(readFileSync(tomlPath, "utf8"));
|
|
16748
|
+
return {
|
|
16749
|
+
config: validateConfig(raw2, ROOT_CONFIG_TOML),
|
|
16750
|
+
source: "toml",
|
|
16751
|
+
warnedDual: hasToml && hasYaml
|
|
16752
|
+
};
|
|
16753
|
+
}
|
|
16754
|
+
const raw = $parse(readFileSync(yamlPath, "utf8"));
|
|
16755
|
+
return {
|
|
16756
|
+
config: validateConfig(raw, LEGACY_CONFIG_YAML),
|
|
16757
|
+
source: "yaml"
|
|
16758
|
+
};
|
|
16759
|
+
}
|
|
16760
|
+
function loadConfig(root) {
|
|
16761
|
+
return loadConfigDetailed(root).config;
|
|
15981
16762
|
}
|
|
15982
16763
|
function mergedExcludes(config) {
|
|
15983
16764
|
return [...new Set([...BUILTIN_EXCLUDES, ...config.scan.exclude])];
|
|
15984
16765
|
}
|
|
15985
|
-
function retiredSkills(config) {
|
|
15986
|
-
return config.scan.retiredSkills ?? [];
|
|
15987
|
-
}
|
|
15988
16766
|
function nonPublicSkills(config) {
|
|
15989
16767
|
return config.scan.nonPublicSkills ?? [];
|
|
15990
16768
|
}
|
|
@@ -17523,11 +18301,12 @@ function collectScanFiles(config, root, skillIndex) {
|
|
|
17523
18301
|
});
|
|
17524
18302
|
}
|
|
17525
18303
|
function collectBannedFiles(config, root) {
|
|
17526
|
-
|
|
18304
|
+
const patterns = config.deny?.paths ?? [];
|
|
18305
|
+
if (patterns.length === 0)
|
|
17527
18306
|
return [];
|
|
17528
18307
|
const exclude = mergedExcludes(config);
|
|
17529
18308
|
const files = new Set;
|
|
17530
|
-
for (const pattern of
|
|
18309
|
+
for (const pattern of patterns) {
|
|
17531
18310
|
for (const abs of globSync(pattern, {
|
|
17532
18311
|
cwd: root,
|
|
17533
18312
|
absolute: true,
|
|
@@ -17592,7 +18371,7 @@ function collectDocMetaPaths(ctx) {
|
|
|
17592
18371
|
for (const abs of expandPatterns(ctx.root, ["docs/*/README.md"], mergedExcludes(ctx.config))) {
|
|
17593
18372
|
paths.push(normalizeRelPath(relative4(ctx.root, abs)));
|
|
17594
18373
|
}
|
|
17595
|
-
const extras = ["docs/README.md"
|
|
18374
|
+
const extras = ["docs/README.md"];
|
|
17596
18375
|
for (const file of extras) {
|
|
17597
18376
|
const abs = join6(ctx.root, file);
|
|
17598
18377
|
if (existsSync7(abs))
|
|
@@ -17661,31 +18440,108 @@ function relPath(absPath, root) {
|
|
|
17661
18440
|
return normalizeRelPath(relative4(root, absPath));
|
|
17662
18441
|
}
|
|
17663
18442
|
|
|
17664
|
-
// src/audit/core/
|
|
17665
|
-
import {
|
|
17666
|
-
import {
|
|
17667
|
-
|
|
17668
|
-
|
|
17669
|
-
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
18443
|
+
// src/audit/core/ssot-collect.ts
|
|
18444
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
18445
|
+
import { relative as relative5 } from "node:path";
|
|
18446
|
+
|
|
18447
|
+
// src/audit/core/ssot.ts
|
|
18448
|
+
var SSOT_COMMENT_RE = /<!--\s*source-of-truth:\s*([\s\S]*?)\s*-->/gi;
|
|
18449
|
+
var HWS = "[ \\t]*";
|
|
18450
|
+
var SSOT_VISIBLE_LINE_RE = new RegExp(`^${HWS}source-of-truth:${HWS}(.+?)${HWS}$`, "gim");
|
|
18451
|
+
var LEGACY_BANNER_LINE_RE = new RegExp(`^${HWS}\\*\\*Source of truth for\\*\\*${HWS}(.+?)${HWS}$`, "gim");
|
|
18452
|
+
function cleanSummary(raw) {
|
|
18453
|
+
return raw.replace(/\s+/g, " ").trim().replace(/\.$/, "").trim();
|
|
18454
|
+
}
|
|
18455
|
+
function stripCode(content) {
|
|
18456
|
+
return content.replace(/```[\s\S]*?```/g, `
|
|
18457
|
+
`).replace(/`[^`\n]+`/g, " ");
|
|
18458
|
+
}
|
|
18459
|
+
function collectMatches(re, content) {
|
|
18460
|
+
const out = [];
|
|
18461
|
+
re.lastIndex = 0;
|
|
18462
|
+
let match = re.exec(content);
|
|
18463
|
+
while (match) {
|
|
18464
|
+
const summary = cleanSummary(match[1] ?? "");
|
|
18465
|
+
if (summary)
|
|
18466
|
+
out.push(summary);
|
|
18467
|
+
match = re.exec(content);
|
|
17673
18468
|
}
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17678
|
-
|
|
17679
|
-
|
|
17680
|
-
|
|
18469
|
+
return out;
|
|
18470
|
+
}
|
|
18471
|
+
function parseSsot(content) {
|
|
18472
|
+
const prose = stripCode(content);
|
|
18473
|
+
const comments = collectMatches(SSOT_COMMENT_RE, prose);
|
|
18474
|
+
const visibles = collectMatches(SSOT_VISIBLE_LINE_RE, prose);
|
|
18475
|
+
const legacies = collectMatches(LEGACY_BANNER_LINE_RE, prose);
|
|
18476
|
+
const forms = [];
|
|
18477
|
+
if (comments.length)
|
|
18478
|
+
forms.push("comment");
|
|
18479
|
+
if (visibles.length)
|
|
18480
|
+
forms.push("visible");
|
|
18481
|
+
if (legacies.length)
|
|
18482
|
+
forms.push("legacy");
|
|
18483
|
+
if (forms.length === 0)
|
|
18484
|
+
return { status: "none" };
|
|
18485
|
+
if (forms.length > 1)
|
|
18486
|
+
return { status: "dual", forms };
|
|
18487
|
+
if (comments.length > 1 || visibles.length > 1 || legacies.length > 1) {
|
|
18488
|
+
return { status: "malformed", detail: "multiple source-of-truth markers of the same form" };
|
|
18489
|
+
}
|
|
18490
|
+
if (comments.length === 1) {
|
|
18491
|
+
const summary2 = comments[0];
|
|
18492
|
+
if (!summary2)
|
|
18493
|
+
return { status: "malformed", detail: "empty source-of-truth comment" };
|
|
18494
|
+
return { status: "ok", entry: { summary: summary2, form: "comment" } };
|
|
18495
|
+
}
|
|
18496
|
+
if (visibles.length === 1) {
|
|
18497
|
+
const summary2 = visibles[0];
|
|
18498
|
+
if (!summary2)
|
|
18499
|
+
return { status: "malformed", detail: "empty source-of-truth line" };
|
|
18500
|
+
return { status: "ok", entry: { summary: summary2, form: "visible" } };
|
|
18501
|
+
}
|
|
18502
|
+
const summary = legacies[0];
|
|
18503
|
+
if (!summary)
|
|
18504
|
+
return { status: "malformed", detail: "empty legacy Source of truth banner" };
|
|
18505
|
+
return { status: "ok", entry: { summary, form: "legacy" } };
|
|
18506
|
+
}
|
|
18507
|
+
function rewriteLegacySsotToComment(content) {
|
|
18508
|
+
const parsed = parseSsot(content);
|
|
18509
|
+
if (parsed.status !== "ok" || parsed.entry.form !== "legacy")
|
|
18510
|
+
return null;
|
|
18511
|
+
const comment = `<!-- source-of-truth: ${parsed.entry.summary} -->`;
|
|
18512
|
+
const next = content.replace(LEGACY_BANNER_LINE_RE, comment);
|
|
18513
|
+
return next === content ? null : next;
|
|
18514
|
+
}
|
|
18515
|
+
|
|
18516
|
+
// src/audit/core/ssot-collect.ts
|
|
18517
|
+
function collectSsotEntries(files, root) {
|
|
18518
|
+
const entries = [];
|
|
18519
|
+
const errors2 = [];
|
|
18520
|
+
for (const abs of files) {
|
|
18521
|
+
const rel = normalizeRelPath(relative5(root, abs));
|
|
18522
|
+
if (!(rel.endsWith(".md") || rel.endsWith(".mdc")))
|
|
17681
18523
|
continue;
|
|
17682
|
-
const
|
|
17683
|
-
|
|
18524
|
+
const content = readFileSync6(abs, "utf8");
|
|
18525
|
+
const parsed = parseSsot(content);
|
|
18526
|
+
if (parsed.status === "none")
|
|
18527
|
+
continue;
|
|
18528
|
+
if (parsed.status === "dual") {
|
|
18529
|
+
errors2.push({
|
|
18530
|
+
path: rel,
|
|
18531
|
+
kind: "dual",
|
|
18532
|
+
detail: `multiple source-of-truth forms: ${parsed.forms.join(", ")}`,
|
|
18533
|
+
forms: parsed.forms
|
|
18534
|
+
});
|
|
17684
18535
|
continue;
|
|
17685
|
-
|
|
17686
|
-
|
|
18536
|
+
}
|
|
18537
|
+
if (parsed.status === "malformed") {
|
|
18538
|
+
errors2.push({ path: rel, kind: "malformed", detail: parsed.detail });
|
|
18539
|
+
continue;
|
|
18540
|
+
}
|
|
18541
|
+
entries.push({ path: rel, summary: parsed.entry.summary, form: parsed.entry.form });
|
|
17687
18542
|
}
|
|
17688
|
-
|
|
18543
|
+
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
18544
|
+
return { entries, errors: errors2 };
|
|
17689
18545
|
}
|
|
17690
18546
|
|
|
17691
18547
|
// src/audit/core/context.ts
|
|
@@ -17701,11 +18557,12 @@ function createContext(options = {}) {
|
|
|
17701
18557
|
files = includeExplicitMarkdownPaths(files, options.paths, root);
|
|
17702
18558
|
files = filterToPaths(files, options.paths, root);
|
|
17703
18559
|
}
|
|
17704
|
-
const
|
|
18560
|
+
const ssot = collectSsotEntries(files, root);
|
|
18561
|
+
const ssotPaths = ssot.entries.map((e) => e.path);
|
|
17705
18562
|
const allDocMetaPaths = collectDocMetaPaths({
|
|
17706
18563
|
config,
|
|
17707
18564
|
root,
|
|
17708
|
-
registryPaths:
|
|
18565
|
+
registryPaths: ssotPaths,
|
|
17709
18566
|
skillIndex
|
|
17710
18567
|
});
|
|
17711
18568
|
return {
|
|
@@ -17713,9 +18570,10 @@ function createContext(options = {}) {
|
|
|
17713
18570
|
config,
|
|
17714
18571
|
files,
|
|
17715
18572
|
docMetaPaths: options.paths && options.paths.length > 0 ? filterDocMetaPaths(allDocMetaPaths, options.paths, skillIndex) : allDocMetaPaths,
|
|
17716
|
-
|
|
17717
|
-
|
|
17718
|
-
|
|
18573
|
+
ssotEntries: ssot.entries,
|
|
18574
|
+
ssotErrors: ssot.errors,
|
|
18575
|
+
registryPaths: [],
|
|
18576
|
+
registryHasTableHeader: false,
|
|
17719
18577
|
skillIndex,
|
|
17720
18578
|
lockedSkillSlugs: new Set(skillIndex.foreignSlugs),
|
|
17721
18579
|
policies: options.policies ?? []
|
|
@@ -17723,12 +18581,12 @@ function createContext(options = {}) {
|
|
|
17723
18581
|
}
|
|
17724
18582
|
|
|
17725
18583
|
// src/audit/core/fix.ts
|
|
17726
|
-
import { existsSync as
|
|
17727
|
-
import { dirname as dirname6, resolve as
|
|
18584
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5, writeFileSync } from "node:fs";
|
|
18585
|
+
import { dirname as dirname6, resolve as resolve5, sep as sep3 } from "node:path";
|
|
17728
18586
|
|
|
17729
18587
|
// src/audit/fix/anchors.ts
|
|
17730
|
-
import { existsSync as
|
|
17731
|
-
import { dirname as dirname5, resolve as
|
|
18588
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
18589
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
17732
18590
|
|
|
17733
18591
|
// node_modules/github-slugger/regex.js
|
|
17734
18592
|
var regex = /[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g;
|
|
@@ -20731,10 +21589,10 @@ function resolveAll(constructs2, events, context) {
|
|
|
20731
21589
|
const called = [];
|
|
20732
21590
|
let index = -1;
|
|
20733
21591
|
while (++index < constructs2.length) {
|
|
20734
|
-
const
|
|
20735
|
-
if (
|
|
20736
|
-
events =
|
|
20737
|
-
called.push(
|
|
21592
|
+
const resolve4 = constructs2[index].resolveAll;
|
|
21593
|
+
if (resolve4 && !called.includes(resolve4)) {
|
|
21594
|
+
events = resolve4(events, context);
|
|
21595
|
+
called.push(resolve4);
|
|
20738
21596
|
}
|
|
20739
21597
|
}
|
|
20740
21598
|
return events;
|
|
@@ -21979,9 +22837,9 @@ function factoryTitle(effects, ok2, nok, type, markerType, stringType) {
|
|
|
21979
22837
|
return atBreak(code);
|
|
21980
22838
|
}
|
|
21981
22839
|
effects.consume(code);
|
|
21982
|
-
return code === codes.backslash ?
|
|
22840
|
+
return code === codes.backslash ? escape2 : inside;
|
|
21983
22841
|
}
|
|
21984
|
-
function
|
|
22842
|
+
function escape2(code) {
|
|
21985
22843
|
if (code === marker || code === codes.backslash) {
|
|
21986
22844
|
effects.consume(code);
|
|
21987
22845
|
return inside;
|
|
@@ -24042,7 +24900,7 @@ function serializeChunks(chunks, expandTabs) {
|
|
|
24042
24900
|
}
|
|
24043
24901
|
|
|
24044
24902
|
// node_modules/micromark/dev/lib/parse.js
|
|
24045
|
-
function
|
|
24903
|
+
function parse2(options) {
|
|
24046
24904
|
const settings = options || {};
|
|
24047
24905
|
const constructs2 = combineExtensions([exports_constructs, ...settings.extensions || []]);
|
|
24048
24906
|
const parser2 = {
|
|
@@ -24201,7 +25059,7 @@ function fromMarkdown(value, encoding, options) {
|
|
|
24201
25059
|
options = encoding;
|
|
24202
25060
|
encoding = undefined;
|
|
24203
25061
|
}
|
|
24204
|
-
return compiler(options)(postprocess(
|
|
25062
|
+
return compiler(options)(postprocess(parse2(options).document().write(preprocess()(value, encoding, true))));
|
|
24205
25063
|
}
|
|
24206
25064
|
function compiler(options) {
|
|
24207
25065
|
const config = {
|
|
@@ -25908,7 +26766,7 @@ var handle = {
|
|
|
25908
26766
|
};
|
|
25909
26767
|
|
|
25910
26768
|
// node_modules/mdast-util-to-markdown/lib/join.js
|
|
25911
|
-
var
|
|
26769
|
+
var join7 = [joinDefaults];
|
|
25912
26770
|
function joinDefaults(left, right, parent, state) {
|
|
25913
26771
|
if (right.type === "code" && formatCodeAsIndented(right, state) && (left.type === "list" || left.type === right.type && formatCodeAsIndented(left, state))) {
|
|
25914
26772
|
return false;
|
|
@@ -26291,7 +27149,7 @@ function toMarkdown(tree, options) {
|
|
|
26291
27149
|
handle: undefined,
|
|
26292
27150
|
indentLines,
|
|
26293
27151
|
indexStack: [],
|
|
26294
|
-
join: [...
|
|
27152
|
+
join: [...join7],
|
|
26295
27153
|
options: {},
|
|
26296
27154
|
safe: safeBound,
|
|
26297
27155
|
stack: [],
|
|
@@ -26784,7 +27642,7 @@ class Processor extends CallableInstance {
|
|
|
26784
27642
|
assertParser("process", this.parser || this.Parser);
|
|
26785
27643
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
26786
27644
|
return done ? executor(undefined, done) : new Promise(executor);
|
|
26787
|
-
function executor(
|
|
27645
|
+
function executor(resolve4, reject) {
|
|
26788
27646
|
const realFile = vfile(file);
|
|
26789
27647
|
const parseTree = self.parse(realFile);
|
|
26790
27648
|
self.run(parseTree, realFile, function(error, tree, file2) {
|
|
@@ -26803,8 +27661,8 @@ class Processor extends CallableInstance {
|
|
|
26803
27661
|
function realDone(error, file2) {
|
|
26804
27662
|
if (error || !file2) {
|
|
26805
27663
|
reject(error);
|
|
26806
|
-
} else if (
|
|
26807
|
-
|
|
27664
|
+
} else if (resolve4) {
|
|
27665
|
+
resolve4(file2);
|
|
26808
27666
|
} else {
|
|
26809
27667
|
ok(done, "`done` is defined if `resolve` is not");
|
|
26810
27668
|
done(undefined, file2);
|
|
@@ -26837,7 +27695,7 @@ class Processor extends CallableInstance {
|
|
|
26837
27695
|
file = undefined;
|
|
26838
27696
|
}
|
|
26839
27697
|
return done ? executor(undefined, done) : new Promise(executor);
|
|
26840
|
-
function executor(
|
|
27698
|
+
function executor(resolve4, reject) {
|
|
26841
27699
|
ok(typeof file !== "function", "`file` can’t be a `done` anymore, we checked");
|
|
26842
27700
|
const realFile = vfile(file);
|
|
26843
27701
|
transformers.run(tree, realFile, realDone);
|
|
@@ -26845,8 +27703,8 @@ class Processor extends CallableInstance {
|
|
|
26845
27703
|
const resultingTree = outputTree || tree;
|
|
26846
27704
|
if (error) {
|
|
26847
27705
|
reject(error);
|
|
26848
|
-
} else if (
|
|
26849
|
-
|
|
27706
|
+
} else if (resolve4) {
|
|
27707
|
+
resolve4(resultingTree);
|
|
26850
27708
|
} else {
|
|
26851
27709
|
ok(done, "`done` is defined if `resolve` is not");
|
|
26852
27710
|
done(undefined, resultingTree, file2);
|
|
@@ -29289,7 +30147,7 @@ function resolveLink(sourceFile, target) {
|
|
|
29289
30147
|
const withoutAnchor = target.split("#")[0]?.split("?")[0] ?? "";
|
|
29290
30148
|
if (!withoutAnchor)
|
|
29291
30149
|
return sourceFile;
|
|
29292
|
-
return
|
|
30150
|
+
return resolve4(dirname5(sourceFile), withoutAnchor);
|
|
29293
30151
|
}
|
|
29294
30152
|
function replaceAnchorInTarget(target, oldAnchor, newAnchor) {
|
|
29295
30153
|
const hashIndex = target.indexOf("#");
|
|
@@ -29313,7 +30171,7 @@ function anchorTargetReplacement(filePath, target) {
|
|
|
29313
30171
|
if (!anchor)
|
|
29314
30172
|
return null;
|
|
29315
30173
|
const resolved = resolveLink(filePath, target);
|
|
29316
|
-
if (!
|
|
30174
|
+
if (!existsSync8(resolved))
|
|
29317
30175
|
return null;
|
|
29318
30176
|
const targetContent = readFileSync7(resolved, "utf8");
|
|
29319
30177
|
const slugs = extractHeadingSlugs(targetContent, resolved);
|
|
@@ -29397,8 +30255,8 @@ function collectAnchorFixes(ctx) {
|
|
|
29397
30255
|
}
|
|
29398
30256
|
|
|
29399
30257
|
// src/audit/fix/doc-meta.ts
|
|
29400
|
-
import { existsSync as
|
|
29401
|
-
import { join as
|
|
30258
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
|
|
30259
|
+
import { join as join8 } from "node:path";
|
|
29402
30260
|
|
|
29403
30261
|
// src/audit/core/git-meta.ts
|
|
29404
30262
|
import { spawnSync } from "node:child_process";
|
|
@@ -29427,8 +30285,8 @@ function bumpDocMetaLastReviewed(content3, gitDate) {
|
|
|
29427
30285
|
return replaceDocMetaLastReviewed(content3, gitDate);
|
|
29428
30286
|
}
|
|
29429
30287
|
function docMetaFixForPath(ctx, relPath2) {
|
|
29430
|
-
const abs =
|
|
29431
|
-
if (!
|
|
30288
|
+
const abs = join8(ctx.root, relPath2);
|
|
30289
|
+
if (!existsSync9(abs))
|
|
29432
30290
|
return null;
|
|
29433
30291
|
const content3 = readFileSync8(abs, "utf8");
|
|
29434
30292
|
if (!DOC_META_RE.test(content3))
|
|
@@ -29461,34 +30319,74 @@ function collectDocMetaFixes(ctx) {
|
|
|
29461
30319
|
return edits;
|
|
29462
30320
|
}
|
|
29463
30321
|
|
|
30322
|
+
// src/audit/fix/ssot.ts
|
|
30323
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
30324
|
+
import { join as join9 } from "node:path";
|
|
30325
|
+
function collectSsotFixes(ctx) {
|
|
30326
|
+
const edits = [];
|
|
30327
|
+
for (const entry of ctx.ssotEntries) {
|
|
30328
|
+
if (entry.form !== "legacy")
|
|
30329
|
+
continue;
|
|
30330
|
+
const abs = join9(ctx.root, entry.path);
|
|
30331
|
+
const content3 = readFileSync9(abs, "utf8");
|
|
30332
|
+
const next = rewriteLegacySsotToComment(content3);
|
|
30333
|
+
if (!next)
|
|
30334
|
+
continue;
|
|
30335
|
+
edits.push({
|
|
30336
|
+
file: entry.path,
|
|
30337
|
+
description: "rewrite legacy **Source of truth for** banner to <!-- source-of-truth: … -->",
|
|
30338
|
+
content: next
|
|
30339
|
+
});
|
|
30340
|
+
}
|
|
30341
|
+
return edits;
|
|
30342
|
+
}
|
|
30343
|
+
|
|
29464
30344
|
// src/audit/core/fix.ts
|
|
29465
30345
|
function collectFixes(ctx, kinds) {
|
|
29466
30346
|
const meta = kinds.has("doc-meta") ? collectDocMetaFixes(ctx) : [];
|
|
29467
30347
|
const anchors = kinds.has("anchors") ? collectAnchorFixes(ctx) : [];
|
|
29468
|
-
|
|
30348
|
+
const ssot = kinds.has("ssot") ? collectSsotFixes(ctx) : [];
|
|
30349
|
+
return coalesceFixEdits(meta, anchors, ssot);
|
|
29469
30350
|
}
|
|
29470
|
-
function coalesceFixEdits(metaEdits, anchorEdits) {
|
|
30351
|
+
function coalesceFixEdits(metaEdits, anchorEdits, ssotEdits = []) {
|
|
29471
30352
|
const metaByFile = new Map(metaEdits.map((e) => [e.file, e]));
|
|
29472
30353
|
const anchorByFile = new Map(anchorEdits.map((e) => [e.file, e]));
|
|
29473
|
-
const
|
|
30354
|
+
const ssotByFile = new Map(ssotEdits.map((e) => [e.file, e]));
|
|
30355
|
+
const files = new Set([...metaByFile.keys(), ...anchorByFile.keys(), ...ssotByFile.keys()]);
|
|
29474
30356
|
const out = [];
|
|
29475
30357
|
for (const file of [...files].sort()) {
|
|
29476
|
-
|
|
29477
|
-
|
|
29478
|
-
|
|
29479
|
-
|
|
29480
|
-
|
|
29481
|
-
|
|
29482
|
-
content: overlayLastReviewed(anchors.content, meta.content)
|
|
29483
|
-
});
|
|
29484
|
-
} else if (meta) {
|
|
29485
|
-
out.push(meta);
|
|
29486
|
-
} else if (anchors) {
|
|
29487
|
-
out.push(anchors);
|
|
29488
|
-
}
|
|
30358
|
+
out.push(coalesceOneFile({
|
|
30359
|
+
file,
|
|
30360
|
+
meta: metaByFile.get(file),
|
|
30361
|
+
anchors: anchorByFile.get(file),
|
|
30362
|
+
ssot: ssotByFile.get(file)
|
|
30363
|
+
}));
|
|
29489
30364
|
}
|
|
29490
30365
|
return out;
|
|
29491
30366
|
}
|
|
30367
|
+
function coalesceOneFile(input) {
|
|
30368
|
+
const { file, meta, anchors, ssot } = input;
|
|
30369
|
+
const descriptions = [];
|
|
30370
|
+
let content3 = anchors?.content ?? meta?.content ?? ssot?.content ?? "";
|
|
30371
|
+
if (meta)
|
|
30372
|
+
descriptions.push(meta.description);
|
|
30373
|
+
if (anchors) {
|
|
30374
|
+
descriptions.push(anchors.description);
|
|
30375
|
+
content3 = anchors.content;
|
|
30376
|
+
if (meta)
|
|
30377
|
+
content3 = overlayLastReviewed(content3, meta.content);
|
|
30378
|
+
} else if (meta) {
|
|
30379
|
+
content3 = meta.content;
|
|
30380
|
+
}
|
|
30381
|
+
if (ssot) {
|
|
30382
|
+
descriptions.push(ssot.description);
|
|
30383
|
+
content3 = rewriteSsotOnto(content3, ssot.content);
|
|
30384
|
+
}
|
|
30385
|
+
return { file, description: descriptions.join("; "), content: content3 };
|
|
30386
|
+
}
|
|
30387
|
+
function rewriteSsotOnto(base, ssotContent) {
|
|
30388
|
+
return ssotContent || base;
|
|
30389
|
+
}
|
|
29492
30390
|
function overlayLastReviewed(targetContent, metaContent) {
|
|
29493
30391
|
const date = docMetaLastReviewed(metaContent);
|
|
29494
30392
|
if (!date)
|
|
@@ -29502,9 +30400,9 @@ function shouldStopPathWalk(rootResolved, parent, cursor) {
|
|
|
29502
30400
|
return parent === cursor || !underRoot(rootResolved, parent) && parent !== rootResolved;
|
|
29503
30401
|
}
|
|
29504
30402
|
function resolveExistingRealPath(rootResolved, abs, relFile) {
|
|
29505
|
-
const rootReal =
|
|
30403
|
+
const rootReal = existsSync10(rootResolved) ? realpathSync5(rootResolved) : rootResolved;
|
|
29506
30404
|
let cursor = abs;
|
|
29507
|
-
while (!
|
|
30405
|
+
while (!existsSync10(cursor)) {
|
|
29508
30406
|
const parent = dirname6(cursor);
|
|
29509
30407
|
if (shouldStopPathWalk(rootResolved, parent, cursor))
|
|
29510
30408
|
return abs;
|
|
@@ -29517,8 +30415,8 @@ function resolveExistingRealPath(rootResolved, abs, relFile) {
|
|
|
29517
30415
|
return abs;
|
|
29518
30416
|
}
|
|
29519
30417
|
function resolveWritePath(root2, relFile) {
|
|
29520
|
-
const rootResolved =
|
|
29521
|
-
const abs =
|
|
30418
|
+
const rootResolved = resolve5(root2);
|
|
30419
|
+
const abs = resolve5(rootResolved, relFile);
|
|
29522
30420
|
if (!underRoot(rootResolved, abs)) {
|
|
29523
30421
|
throw new Error(`Refusing autofix outside repo root: ${relFile}`);
|
|
29524
30422
|
}
|
|
@@ -29545,19 +30443,22 @@ function applyFixes(ctx, options) {
|
|
|
29545
30443
|
}
|
|
29546
30444
|
function parseFixKinds(raw) {
|
|
29547
30445
|
if (raw === true)
|
|
29548
|
-
return ["doc-meta", "anchors"];
|
|
30446
|
+
return ["doc-meta", "anchors", "ssot"];
|
|
29549
30447
|
switch (raw) {
|
|
29550
30448
|
case "doc-meta":
|
|
29551
30449
|
return ["doc-meta"];
|
|
29552
30450
|
case "anchors":
|
|
29553
30451
|
return ["anchors"];
|
|
30452
|
+
case "ssot":
|
|
30453
|
+
return ["ssot"];
|
|
29554
30454
|
default:
|
|
29555
|
-
throw new Error(`Unknown --fix kind: ${raw}. Use doc-meta or
|
|
30455
|
+
throw new Error(`Unknown --fix kind: ${raw}. Use doc-meta, anchors, or ssot.`);
|
|
29556
30456
|
}
|
|
29557
30457
|
}
|
|
29558
30458
|
var FIX_KIND_RULE = {
|
|
29559
30459
|
"doc-meta": "doc-meta",
|
|
29560
|
-
anchors: "links"
|
|
30460
|
+
anchors: "links",
|
|
30461
|
+
ssot: "ssot"
|
|
29561
30462
|
};
|
|
29562
30463
|
function fixKindsForOnly(kinds, only) {
|
|
29563
30464
|
if (!only)
|
|
@@ -29636,7 +30537,7 @@ function printTextReport(ctx) {
|
|
|
29636
30537
|
}
|
|
29637
30538
|
|
|
29638
30539
|
// src/references/check.ts
|
|
29639
|
-
import { existsSync as
|
|
30540
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
|
|
29640
30541
|
import { join as join11, relative as relative7 } from "node:path";
|
|
29641
30542
|
|
|
29642
30543
|
// src/references/constants.ts
|
|
@@ -29660,11 +30561,11 @@ function isGeneratedReference(content3) {
|
|
|
29660
30561
|
}
|
|
29661
30562
|
|
|
29662
30563
|
// src/references/discover.ts
|
|
29663
|
-
import { existsSync as
|
|
30564
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
29664
30565
|
import { join as join10, relative as relative6 } from "node:path";
|
|
29665
30566
|
function walkMarkdownFiles(dir, root2) {
|
|
29666
30567
|
const files = [];
|
|
29667
|
-
if (!
|
|
30568
|
+
if (!existsSync11(dir))
|
|
29668
30569
|
return files;
|
|
29669
30570
|
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
29670
30571
|
if (entry.name.startsWith("."))
|
|
@@ -29681,7 +30582,7 @@ function walkMarkdownFiles(dir, root2) {
|
|
|
29681
30582
|
return files;
|
|
29682
30583
|
}
|
|
29683
30584
|
function canonicalExists(root2, refPath) {
|
|
29684
|
-
return
|
|
30585
|
+
return existsSync11(join10(root2, CANONICAL_REFS_DIR, refPath));
|
|
29685
30586
|
}
|
|
29686
30587
|
function findSharedRefLinks(content3, sourceFile) {
|
|
29687
30588
|
const links = [];
|
|
@@ -29725,7 +30626,7 @@ function findLocalCanonicalLinks(root2, content3, sourceFile) {
|
|
|
29725
30626
|
return links;
|
|
29726
30627
|
}
|
|
29727
30628
|
function collectLinksForFile(root2, relFile) {
|
|
29728
|
-
const content3 =
|
|
30629
|
+
const content3 = readFileSync10(join10(root2, relFile), "utf8");
|
|
29729
30630
|
if (isGeneratedReference(content3))
|
|
29730
30631
|
return [];
|
|
29731
30632
|
return [
|
|
@@ -29740,7 +30641,7 @@ function expandTransitiveRefs(input) {
|
|
|
29740
30641
|
const refPath = queue.pop();
|
|
29741
30642
|
if (!(refPath && canonicalExists(root2, refPath)))
|
|
29742
30643
|
continue;
|
|
29743
|
-
const canonicalContent =
|
|
30644
|
+
const canonicalContent = readFileSync10(join10(root2, CANONICAL_REFS_DIR, refPath), "utf8");
|
|
29744
30645
|
const syntheticSource = generatedRefPath(slug2, refPath);
|
|
29745
30646
|
for (const link2 of findLocalCanonicalLinks(root2, canonicalContent, syntheticSource)) {
|
|
29746
30647
|
if (refPaths.has(link2.refPath))
|
|
@@ -29753,7 +30654,7 @@ function expandTransitiveRefs(input) {
|
|
|
29753
30654
|
}
|
|
29754
30655
|
function planForSkill(root2, slug2) {
|
|
29755
30656
|
const skillDir = join10(root2, slug2);
|
|
29756
|
-
if (!
|
|
30657
|
+
if (!existsSync11(join10(skillDir, "SKILL.md")))
|
|
29757
30658
|
return null;
|
|
29758
30659
|
const refPaths = new Set;
|
|
29759
30660
|
const links = [];
|
|
@@ -29804,7 +30705,7 @@ function rewriteSharedRefLinks(content3, sourceFile, skill) {
|
|
|
29804
30705
|
|
|
29805
30706
|
// src/references/check.ts
|
|
29806
30707
|
function walkMarkdown(dir, onFile) {
|
|
29807
|
-
if (!
|
|
30708
|
+
if (!existsSync12(dir))
|
|
29808
30709
|
return;
|
|
29809
30710
|
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
29810
30711
|
if (entry.name.startsWith("."))
|
|
@@ -29822,7 +30723,7 @@ function walkMarkdown(dir, onFile) {
|
|
|
29822
30723
|
function listAllGeneratedFiles(root2) {
|
|
29823
30724
|
const files = [];
|
|
29824
30725
|
walkMarkdown(root2, (fullPath) => {
|
|
29825
|
-
const content3 =
|
|
30726
|
+
const content3 = readFileSync11(fullPath, "utf8");
|
|
29826
30727
|
if (isGeneratedReference(content3)) {
|
|
29827
30728
|
files.push(normalizeRelPath(relative7(root2, fullPath)));
|
|
29828
30729
|
}
|
|
@@ -29831,20 +30732,20 @@ function listAllGeneratedFiles(root2) {
|
|
|
29831
30732
|
}
|
|
29832
30733
|
function checkNeededCopy(root2, targetRel) {
|
|
29833
30734
|
const targetPath = join11(root2, targetRel);
|
|
29834
|
-
if (!
|
|
30735
|
+
if (!existsSync12(targetPath)) {
|
|
29835
30736
|
return issue("generated-references", targetRel, "missing generated copy — run skeleton references sync");
|
|
29836
30737
|
}
|
|
29837
|
-
const generated =
|
|
30738
|
+
const generated = readFileSync11(targetPath, "utf8");
|
|
29838
30739
|
if (!isGeneratedReference(generated)) {
|
|
29839
30740
|
return issue("generated-references", targetRel, "expected generated-reference provenance header");
|
|
29840
30741
|
}
|
|
29841
30742
|
const body = stripGeneratedHeader(generated);
|
|
29842
30743
|
const sourceRel = normalizeRelPath(generated.match(/source: ([^\n]+)/)?.[1] ?? join11(CANONICAL_REFS_DIR, targetRel.split("/references/")[1] ?? ""));
|
|
29843
30744
|
const canonicalPath = join11(root2, sourceRel);
|
|
29844
|
-
if (!
|
|
30745
|
+
if (!existsSync12(canonicalPath)) {
|
|
29845
30746
|
return issue("generated-references", targetRel, `canonical source missing: ${sourceRel}`);
|
|
29846
30747
|
}
|
|
29847
|
-
const canonical =
|
|
30748
|
+
const canonical = readFileSync11(canonicalPath, "utf8");
|
|
29848
30749
|
if (body !== canonical) {
|
|
29849
30750
|
return issue("generated-references", targetRel, "stale generated copy — run skeleton references sync");
|
|
29850
30751
|
}
|
|
@@ -29865,7 +30766,7 @@ function checkStaleSharedLinks(root2, skillDir) {
|
|
|
29865
30766
|
const issues = [];
|
|
29866
30767
|
walkMarkdown(skillDir, (fullPath) => {
|
|
29867
30768
|
const relFile = normalizeRelPath(relative7(root2, fullPath));
|
|
29868
|
-
const content3 =
|
|
30769
|
+
const content3 = readFileSync11(fullPath, "utf8");
|
|
29869
30770
|
if (!content3.match(SHARED_REF_LINK_RE))
|
|
29870
30771
|
return;
|
|
29871
30772
|
issues.push(issue("generated-references", relFile, "still links to shared root references/ — run skeleton references sync"));
|
|
@@ -29875,7 +30776,7 @@ function checkStaleSharedLinks(root2, skillDir) {
|
|
|
29875
30776
|
function runGeneratedReferencesCheck(root2, ownership) {
|
|
29876
30777
|
const issues = [];
|
|
29877
30778
|
const canonicalDir = join11(root2, CANONICAL_REFS_DIR);
|
|
29878
|
-
if (!
|
|
30779
|
+
if (!existsSync12(canonicalDir))
|
|
29879
30780
|
return issues;
|
|
29880
30781
|
const skillIndex = buildSkillIndex(root2, ownership);
|
|
29881
30782
|
const plans = discoverSkillReferencePlans(root2, ownership);
|
|
@@ -29910,14 +30811,14 @@ function runBannedRule(ctx) {
|
|
|
29910
30811
|
const issues = [];
|
|
29911
30812
|
for (const abs of collectBannedFiles(ctx.config, ctx.root)) {
|
|
29912
30813
|
const rel = relPath(abs, ctx.root);
|
|
29913
|
-
issues.push(issue("banned", rel, "file matches
|
|
30814
|
+
issues.push(issue("banned", rel, "file matches deny.paths — must not exist in repo"));
|
|
29914
30815
|
}
|
|
29915
30816
|
return issues;
|
|
29916
30817
|
}
|
|
29917
30818
|
var bannedRule = { id: "banned", run: runBannedRule };
|
|
29918
30819
|
|
|
29919
30820
|
// src/audit/rules/doc-meta.ts
|
|
29920
|
-
import { existsSync as
|
|
30821
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12 } from "node:fs";
|
|
29921
30822
|
import { join as join12 } from "node:path";
|
|
29922
30823
|
function checkDocMetaBanner(relPath2, content3) {
|
|
29923
30824
|
if (DOC_META_RE.test(content3))
|
|
@@ -29969,9 +30870,9 @@ function runDocMetaRule(ctx) {
|
|
|
29969
30870
|
const today = new Date;
|
|
29970
30871
|
for (const relPath2 of ctx.docMetaPaths) {
|
|
29971
30872
|
const abs = join12(ctx.root, relPath2);
|
|
29972
|
-
if (!
|
|
30873
|
+
if (!existsSync13(abs))
|
|
29973
30874
|
continue;
|
|
29974
|
-
const content3 =
|
|
30875
|
+
const content3 = readFileSync12(abs, "utf8");
|
|
29975
30876
|
const banner = checkDocMetaBanner(relPath2, content3);
|
|
29976
30877
|
if (banner) {
|
|
29977
30878
|
issues.push(banner);
|
|
@@ -29999,23 +30900,13 @@ function runDocMetaRule(ctx) {
|
|
|
29999
30900
|
var docMetaRule = { id: "doc-meta", run: runDocMetaRule };
|
|
30000
30901
|
|
|
30001
30902
|
// src/audit/rules/links.ts
|
|
30002
|
-
import { existsSync as
|
|
30003
|
-
import { dirname as dirname7, resolve as
|
|
30903
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
|
|
30904
|
+
import { dirname as dirname7, resolve as resolve6 } from "node:path";
|
|
30004
30905
|
function resolveLink2(sourceFile, target) {
|
|
30005
30906
|
const withoutAnchor = target.split("#")[0]?.split("?")[0] ?? "";
|
|
30006
30907
|
if (!withoutAnchor)
|
|
30007
30908
|
return sourceFile;
|
|
30008
|
-
return
|
|
30009
|
-
}
|
|
30010
|
-
function checkRetiredSkill(input) {
|
|
30011
|
-
const skillMatch = SKILL_LINK_IN_TARGET_RE.exec(input.target);
|
|
30012
|
-
const slug2 = skillMatch?.[1];
|
|
30013
|
-
if (!(slug2 && input.ctx.retiredSkills.has(slug2)))
|
|
30014
|
-
return null;
|
|
30015
|
-
return issue("links", relPath(input.sourceFile, input.ctx.root), {
|
|
30016
|
-
message: `references retired skill "${slug2}/SKILL.md"`,
|
|
30017
|
-
link: input.linkLabel
|
|
30018
|
-
});
|
|
30909
|
+
return resolve6(dirname7(sourceFile), withoutAnchor);
|
|
30019
30910
|
}
|
|
30020
30911
|
function checkMissingSkill(input, relSource) {
|
|
30021
30912
|
if (!input.target.includes("/SKILL.md"))
|
|
@@ -30033,13 +30924,13 @@ function checkAgentFile(input, resolved, relSource) {
|
|
|
30033
30924
|
return null;
|
|
30034
30925
|
}
|
|
30035
30926
|
const agentPath = resolved.endsWith(".md") ? resolved : `${resolved}.md`;
|
|
30036
|
-
if (
|
|
30927
|
+
if (existsSync14(agentPath))
|
|
30037
30928
|
return null;
|
|
30038
30929
|
return issue("links", relSource, { message: "missing agent file", link: input.linkLabel });
|
|
30039
30930
|
}
|
|
30040
30931
|
function checkBrokenPath(ctx) {
|
|
30041
30932
|
const { input, pathPart, resolved, relSource, relTarget } = ctx;
|
|
30042
|
-
if (!(pathPart && !
|
|
30933
|
+
if (!(pathPart && !existsSync14(resolved)))
|
|
30043
30934
|
return null;
|
|
30044
30935
|
return issue("links", relSource, {
|
|
30045
30936
|
message: `broken link → ${relTarget}`,
|
|
@@ -30048,9 +30939,9 @@ function checkBrokenPath(ctx) {
|
|
|
30048
30939
|
}
|
|
30049
30940
|
function checkBrokenAnchor(ctx) {
|
|
30050
30941
|
const { input, anchor, resolved, relSource, relTarget } = ctx;
|
|
30051
|
-
if (!(anchor &&
|
|
30942
|
+
if (!(anchor && existsSync14(resolved)))
|
|
30052
30943
|
return null;
|
|
30053
|
-
const targetContent =
|
|
30944
|
+
const targetContent = readFileSync13(resolved, "utf8");
|
|
30054
30945
|
const slugs = extractHeadingSlugs(targetContent, resolved);
|
|
30055
30946
|
const anchorSlug = slugifyAnchor(anchor);
|
|
30056
30947
|
if (slugs.has(anchorSlug))
|
|
@@ -30075,9 +30966,6 @@ function validateTarget(input) {
|
|
|
30075
30966
|
if (isPlaceholderLink(target))
|
|
30076
30967
|
return [];
|
|
30077
30968
|
const parts = resolveTargetParts(sourceFile, target, ctx.root);
|
|
30078
|
-
const retired = checkRetiredSkill(input);
|
|
30079
|
-
if (retired)
|
|
30080
|
-
return [retired];
|
|
30081
30969
|
const missingSkill = checkMissingSkill(input, parts.relSource);
|
|
30082
30970
|
if (missingSkill)
|
|
30083
30971
|
return [missingSkill];
|
|
@@ -30104,6 +30992,331 @@ function runLinksRule(ctx) {
|
|
|
30104
30992
|
}
|
|
30105
30993
|
var linksRule = { id: "links", run: runLinksRule };
|
|
30106
30994
|
|
|
30995
|
+
// src/audit/rules/near-duplicate.ts
|
|
30996
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
30997
|
+
import { join as join13 } from "node:path";
|
|
30998
|
+
|
|
30999
|
+
// src/audit/core/ssot-fit.ts
|
|
31000
|
+
var DEFAULT_SSOT_OVERLAP_MIN = 0.35;
|
|
31001
|
+
var DEFAULT_BETTER_MATCH_MARGIN = 0.15;
|
|
31002
|
+
var STOP = new Set([
|
|
31003
|
+
"a",
|
|
31004
|
+
"an",
|
|
31005
|
+
"the",
|
|
31006
|
+
"and",
|
|
31007
|
+
"or",
|
|
31008
|
+
"of",
|
|
31009
|
+
"for",
|
|
31010
|
+
"to",
|
|
31011
|
+
"in",
|
|
31012
|
+
"on",
|
|
31013
|
+
"with",
|
|
31014
|
+
"this",
|
|
31015
|
+
"that",
|
|
31016
|
+
"is",
|
|
31017
|
+
"are",
|
|
31018
|
+
"be",
|
|
31019
|
+
"as",
|
|
31020
|
+
"by",
|
|
31021
|
+
"from",
|
|
31022
|
+
"at",
|
|
31023
|
+
"it",
|
|
31024
|
+
"its"
|
|
31025
|
+
]);
|
|
31026
|
+
var STEM_BLOCKLIST = new Set([
|
|
31027
|
+
"business",
|
|
31028
|
+
"analysis",
|
|
31029
|
+
"status",
|
|
31030
|
+
"process",
|
|
31031
|
+
"access",
|
|
31032
|
+
"address",
|
|
31033
|
+
"series",
|
|
31034
|
+
"species",
|
|
31035
|
+
"news",
|
|
31036
|
+
"means",
|
|
31037
|
+
"cross",
|
|
31038
|
+
"class",
|
|
31039
|
+
"glass",
|
|
31040
|
+
"less",
|
|
31041
|
+
"success",
|
|
31042
|
+
"progress",
|
|
31043
|
+
"express",
|
|
31044
|
+
"discuss",
|
|
31045
|
+
"focus",
|
|
31046
|
+
"bonus",
|
|
31047
|
+
"basis",
|
|
31048
|
+
"crisis",
|
|
31049
|
+
"thesis",
|
|
31050
|
+
"atlas",
|
|
31051
|
+
"canvas",
|
|
31052
|
+
"campus",
|
|
31053
|
+
"virus",
|
|
31054
|
+
"bus",
|
|
31055
|
+
"gas",
|
|
31056
|
+
"plus",
|
|
31057
|
+
"alias",
|
|
31058
|
+
"bias",
|
|
31059
|
+
"circus",
|
|
31060
|
+
"consensus",
|
|
31061
|
+
"census"
|
|
31062
|
+
]);
|
|
31063
|
+
function lightStem(token) {
|
|
31064
|
+
if (token.length < 4)
|
|
31065
|
+
return token;
|
|
31066
|
+
if (STEM_BLOCKLIST.has(token))
|
|
31067
|
+
return token;
|
|
31068
|
+
if (token.endsWith("ies") && token.length > 4) {
|
|
31069
|
+
return `${token.slice(0, -3)}y`;
|
|
31070
|
+
}
|
|
31071
|
+
if (token.endsWith("sses") || token.endsWith("ches") || token.endsWith("shes") || token.endsWith("xes")) {
|
|
31072
|
+
return token.slice(0, -2);
|
|
31073
|
+
}
|
|
31074
|
+
if (token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
31075
|
+
return token.slice(0, -1);
|
|
31076
|
+
}
|
|
31077
|
+
return token;
|
|
31078
|
+
}
|
|
31079
|
+
function contentTokens(text5) {
|
|
31080
|
+
return text5.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length > 1 && !STOP.has(t)).map(lightStem);
|
|
31081
|
+
}
|
|
31082
|
+
function uniqueContentTokens(text5) {
|
|
31083
|
+
return [...new Set(contentTokens(text5))];
|
|
31084
|
+
}
|
|
31085
|
+
function stripCode2(content3) {
|
|
31086
|
+
return content3.replace(/```[\s\S]*?```/g, `
|
|
31087
|
+
`).replace(/`[^`\n]+`/g, " ");
|
|
31088
|
+
}
|
|
31089
|
+
function stripSsotAndMeta(content3) {
|
|
31090
|
+
return content3.replace(/<!--\s*source-of-truth:[\s\S]*?-->/gi, `
|
|
31091
|
+
`).replace(/^\s*source-of-truth:\s*.+$/gim, `
|
|
31092
|
+
`).replace(/^\s*\*\*Source of truth for\*\*\s*.+$/gim, `
|
|
31093
|
+
`).replace(/<!--\s*doc-meta:[\s\S]*?-->/gi, `
|
|
31094
|
+
`);
|
|
31095
|
+
}
|
|
31096
|
+
function extractH1(content3) {
|
|
31097
|
+
const prose = stripCode2(content3);
|
|
31098
|
+
const m = /^#\s+(.+)$/m.exec(prose);
|
|
31099
|
+
return m?.[1]?.trim() ?? "";
|
|
31100
|
+
}
|
|
31101
|
+
function extractLeadParagraph(content3) {
|
|
31102
|
+
const prose = stripSsotAndMeta(stripCode2(content3));
|
|
31103
|
+
const lines = prose.split(/\n/);
|
|
31104
|
+
const chunks = [];
|
|
31105
|
+
let buf = [];
|
|
31106
|
+
const flush = () => {
|
|
31107
|
+
const t = buf.join(" ").trim();
|
|
31108
|
+
if (t)
|
|
31109
|
+
chunks.push(t);
|
|
31110
|
+
buf = [];
|
|
31111
|
+
};
|
|
31112
|
+
for (const line of lines) {
|
|
31113
|
+
const trimmed = line.trim();
|
|
31114
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
31115
|
+
flush();
|
|
31116
|
+
continue;
|
|
31117
|
+
}
|
|
31118
|
+
if (/^[-*|]/.test(trimmed) && chunks.length === 0 && buf.length === 0) {
|
|
31119
|
+
buf.push(trimmed.replace(/^[-*|]+\s*/, ""));
|
|
31120
|
+
continue;
|
|
31121
|
+
}
|
|
31122
|
+
buf.push(trimmed);
|
|
31123
|
+
}
|
|
31124
|
+
flush();
|
|
31125
|
+
return chunks[0] ?? "";
|
|
31126
|
+
}
|
|
31127
|
+
function buildEvidenceText(content3) {
|
|
31128
|
+
const h1 = extractH1(content3);
|
|
31129
|
+
const lead = extractLeadParagraph(content3);
|
|
31130
|
+
const body = stripSsotAndMeta(stripCode2(content3));
|
|
31131
|
+
return [h1, lead, body].filter(Boolean).join(`
|
|
31132
|
+
|
|
31133
|
+
`);
|
|
31134
|
+
}
|
|
31135
|
+
function ssotEvidenceOverlap(summary, evidence) {
|
|
31136
|
+
const st = uniqueContentTokens(summary);
|
|
31137
|
+
if (st.length === 0)
|
|
31138
|
+
return 0;
|
|
31139
|
+
const ev = new Set(contentTokens(evidence));
|
|
31140
|
+
let hit = 0;
|
|
31141
|
+
for (const t of st) {
|
|
31142
|
+
if (ev.has(t))
|
|
31143
|
+
hit++;
|
|
31144
|
+
}
|
|
31145
|
+
return hit / st.length;
|
|
31146
|
+
}
|
|
31147
|
+
function longestSummaryPhrase(summary) {
|
|
31148
|
+
const toks = contentTokens(summary);
|
|
31149
|
+
if (toks.length >= 3)
|
|
31150
|
+
return toks.slice(0, 3);
|
|
31151
|
+
if (toks.length >= 2)
|
|
31152
|
+
return toks.slice(0, 2);
|
|
31153
|
+
return null;
|
|
31154
|
+
}
|
|
31155
|
+
function evidenceHasPhrase(evidence, phrase) {
|
|
31156
|
+
if (phrase.length === 0)
|
|
31157
|
+
return true;
|
|
31158
|
+
const ev = contentTokens(evidence);
|
|
31159
|
+
const needle = phrase.join(" ");
|
|
31160
|
+
for (let i = 0;i <= ev.length - phrase.length; i++) {
|
|
31161
|
+
if (ev.slice(i, i + phrase.length).join(" ") === needle)
|
|
31162
|
+
return true;
|
|
31163
|
+
}
|
|
31164
|
+
return false;
|
|
31165
|
+
}
|
|
31166
|
+
function evaluateSsotFit(files, options = {}) {
|
|
31167
|
+
const overlapMin = options.overlapMin ?? DEFAULT_SSOT_OVERLAP_MIN;
|
|
31168
|
+
const margin = options.betterMatchMargin ?? DEFAULT_BETTER_MATCH_MARGIN;
|
|
31169
|
+
const phraseCheck = options.phraseCheck !== false;
|
|
31170
|
+
const prepared = files.map((f) => {
|
|
31171
|
+
const evidence = buildEvidenceText(f.content);
|
|
31172
|
+
const overlap = ssotEvidenceOverlap(f.summary, evidence);
|
|
31173
|
+
const summaryToks = uniqueContentTokens(f.summary);
|
|
31174
|
+
return { ...f, evidence, overlap, summaryToks };
|
|
31175
|
+
});
|
|
31176
|
+
const issues = [];
|
|
31177
|
+
for (const row of prepared) {
|
|
31178
|
+
if (row.summaryToks.length < 2) {
|
|
31179
|
+
issues.push({
|
|
31180
|
+
kind: "short",
|
|
31181
|
+
path: row.path,
|
|
31182
|
+
message: `source-of-truth summary too short to verify against body ("${row.summary}")`
|
|
31183
|
+
});
|
|
31184
|
+
continue;
|
|
31185
|
+
}
|
|
31186
|
+
if (row.overlap < overlapMin) {
|
|
31187
|
+
let message = `source-of-truth summary weakly matches this paper (token overlap ${row.overlap.toFixed(2)} < ${overlapMin})`;
|
|
31188
|
+
if (phraseCheck) {
|
|
31189
|
+
const phrase = longestSummaryPhrase(row.summary);
|
|
31190
|
+
if (phrase && !evidenceHasPhrase(row.evidence, phrase)) {
|
|
31191
|
+
message += ` — key phrase "${phrase.join(" ")}" not found in H1/lead/body`;
|
|
31192
|
+
}
|
|
31193
|
+
}
|
|
31194
|
+
issues.push({ kind: "weak", path: row.path, message });
|
|
31195
|
+
let best = null;
|
|
31196
|
+
for (const other of prepared) {
|
|
31197
|
+
if (other.path === row.path)
|
|
31198
|
+
continue;
|
|
31199
|
+
const cross = ssotEvidenceOverlap(row.summary, other.evidence);
|
|
31200
|
+
if (cross < overlapMin)
|
|
31201
|
+
continue;
|
|
31202
|
+
if (cross < row.overlap + margin)
|
|
31203
|
+
continue;
|
|
31204
|
+
if (!best || cross > best.overlap)
|
|
31205
|
+
best = { path: other.path, overlap: cross };
|
|
31206
|
+
}
|
|
31207
|
+
if (best) {
|
|
31208
|
+
issues.push({
|
|
31209
|
+
kind: "better-match",
|
|
31210
|
+
path: row.path,
|
|
31211
|
+
otherPath: best.path,
|
|
31212
|
+
message: `source-of-truth fits ${best.path} better (overlap ${best.overlap.toFixed(2)} vs own ${row.overlap.toFixed(2)}). ` + `Try: (1) rewrite this SSOT to match this paper, (2) move/fix the marker onto ${best.path}, ` + `or (3) if these pages are really one topic, consider combining them`
|
|
31213
|
+
});
|
|
31214
|
+
}
|
|
31215
|
+
}
|
|
31216
|
+
}
|
|
31217
|
+
return issues;
|
|
31218
|
+
}
|
|
31219
|
+
|
|
31220
|
+
// src/audit/rules/near-duplicate.ts
|
|
31221
|
+
var DEFAULT_THRESHOLD = 0.72;
|
|
31222
|
+
var SHINGLE_N = 3;
|
|
31223
|
+
function tokenize2(text5) {
|
|
31224
|
+
return contentTokens(text5);
|
|
31225
|
+
}
|
|
31226
|
+
function normalizeSummary(summary) {
|
|
31227
|
+
return contentTokens(summary).join(" ");
|
|
31228
|
+
}
|
|
31229
|
+
function shingles(tokens, n) {
|
|
31230
|
+
const out = new Set;
|
|
31231
|
+
if (tokens.length < n) {
|
|
31232
|
+
if (tokens.length > 0)
|
|
31233
|
+
out.add(tokens.join(" "));
|
|
31234
|
+
return out;
|
|
31235
|
+
}
|
|
31236
|
+
for (let i = 0;i <= tokens.length - n; i++) {
|
|
31237
|
+
out.add(tokens.slice(i, i + n).join(" "));
|
|
31238
|
+
}
|
|
31239
|
+
return out;
|
|
31240
|
+
}
|
|
31241
|
+
function jaccard2(a, b) {
|
|
31242
|
+
if (a.size === 0 && b.size === 0)
|
|
31243
|
+
return 1;
|
|
31244
|
+
if (a.size === 0 || b.size === 0)
|
|
31245
|
+
return 0;
|
|
31246
|
+
let inter = 0;
|
|
31247
|
+
for (const x of a) {
|
|
31248
|
+
if (b.has(x))
|
|
31249
|
+
inter++;
|
|
31250
|
+
}
|
|
31251
|
+
return inter / (a.size + b.size - inter);
|
|
31252
|
+
}
|
|
31253
|
+
function pairKey(a, b) {
|
|
31254
|
+
return a < b ? `${a}::${b}` : `${b}::${a}`;
|
|
31255
|
+
}
|
|
31256
|
+
function ignoredPairSet(ctx) {
|
|
31257
|
+
const pairs = ctx.config.docsLint?.ignorePairs ?? [];
|
|
31258
|
+
const set = new Set;
|
|
31259
|
+
for (const pair of pairs) {
|
|
31260
|
+
if (!pair || pair.length < 2)
|
|
31261
|
+
continue;
|
|
31262
|
+
const a = normalizeRelPath(pair[0] ?? "");
|
|
31263
|
+
const b = normalizeRelPath(pair[1] ?? "");
|
|
31264
|
+
if (a && b)
|
|
31265
|
+
set.add(pairKey(a, b));
|
|
31266
|
+
}
|
|
31267
|
+
return set;
|
|
31268
|
+
}
|
|
31269
|
+
function isIgnoredGlob(rel, globs) {
|
|
31270
|
+
return globs.some((g) => matchesGlobScope(rel, g));
|
|
31271
|
+
}
|
|
31272
|
+
function bodyWithoutSsotNoise(content3) {
|
|
31273
|
+
return content3.replace(/<!--\s*source-of-truth:[\s\S]*?-->/gi, " ").replace(/^\s*source-of-truth:\s*.+$/gim, " ").replace(/^\s*\*\*Source of truth for\*\*\s*.+$/gim, " ");
|
|
31274
|
+
}
|
|
31275
|
+
function eligibleEntries(ctx) {
|
|
31276
|
+
const globs = ctx.config.docsLint?.ignoreGlobs ?? [];
|
|
31277
|
+
return ctx.ssotEntries.filter((e) => !isIgnoredGlob(e.path, globs));
|
|
31278
|
+
}
|
|
31279
|
+
function runNearDuplicateRule(ctx) {
|
|
31280
|
+
const issues = [];
|
|
31281
|
+
const threshold = ctx.config.docsLint?.nearDuplicateThreshold ?? DEFAULT_THRESHOLD;
|
|
31282
|
+
const ignored = ignoredPairSet(ctx);
|
|
31283
|
+
const entries = eligibleEntries(ctx);
|
|
31284
|
+
const fingerprints = entries.map((e) => {
|
|
31285
|
+
const content3 = readFileSync14(join13(ctx.root, e.path), "utf8");
|
|
31286
|
+
const tokens = tokenize2(bodyWithoutSsotNoise(content3));
|
|
31287
|
+
return {
|
|
31288
|
+
path: e.path,
|
|
31289
|
+
summaryKey: normalizeSummary(e.summary),
|
|
31290
|
+
set: shingles(tokens, SHINGLE_N)
|
|
31291
|
+
};
|
|
31292
|
+
});
|
|
31293
|
+
for (let i = 0;i < fingerprints.length; i++) {
|
|
31294
|
+
for (let j = i + 1;j < fingerprints.length; j++) {
|
|
31295
|
+
const a = fingerprints[i];
|
|
31296
|
+
const b = fingerprints[j];
|
|
31297
|
+
if (!(a && b))
|
|
31298
|
+
continue;
|
|
31299
|
+
if (ignored.has(pairKey(a.path, b.path)))
|
|
31300
|
+
continue;
|
|
31301
|
+
const score = jaccard2(a.set, b.set);
|
|
31302
|
+
if (score >= threshold) {
|
|
31303
|
+
issues.push(issue("near-duplicate", a.path, {
|
|
31304
|
+
message: `near-duplicate of ${b.path} (shingle Jaccard ${score.toFixed(2)} ≥ ${threshold})`,
|
|
31305
|
+
severity: "warning"
|
|
31306
|
+
}));
|
|
31307
|
+
}
|
|
31308
|
+
if (a.summaryKey && a.summaryKey === b.summaryKey) {
|
|
31309
|
+
issues.push(issue("near-duplicate", a.path, {
|
|
31310
|
+
message: `duplicate source-of-truth summary also used by ${b.path}`,
|
|
31311
|
+
severity: "warning"
|
|
31312
|
+
}));
|
|
31313
|
+
}
|
|
31314
|
+
}
|
|
31315
|
+
}
|
|
31316
|
+
return issues;
|
|
31317
|
+
}
|
|
31318
|
+
var nearDuplicateRule = { id: "near-duplicate", run: runNearDuplicateRule };
|
|
31319
|
+
|
|
30107
31320
|
// src/audit/rules/prose-policy.ts
|
|
30108
31321
|
function checkDraftEntry(input) {
|
|
30109
31322
|
const { rel, lines, entry, draftPrefixes } = input;
|
|
@@ -30164,53 +31377,6 @@ function runProsePolicyRule(ctx) {
|
|
|
30164
31377
|
}
|
|
30165
31378
|
var prosePolicyRule = { id: "prose-policy", run: runProsePolicyRule };
|
|
30166
31379
|
|
|
30167
|
-
// src/audit/rules/registry.ts
|
|
30168
|
-
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "node:fs";
|
|
30169
|
-
import { join as join13 } from "node:path";
|
|
30170
|
-
function checkRegistryEntries(ctx) {
|
|
30171
|
-
const issues = [];
|
|
30172
|
-
for (const rel of ctx.registryPaths) {
|
|
30173
|
-
const abs = join13(ctx.root, rel);
|
|
30174
|
-
if (!existsSync16(abs)) {
|
|
30175
|
-
issues.push(issue("registry", rel, "registry entry file missing"));
|
|
30176
|
-
continue;
|
|
30177
|
-
}
|
|
30178
|
-
const content3 = readFileSync13(abs, "utf8");
|
|
30179
|
-
if (!SOURCE_OF_TRUTH_BANNER_RE.test(content3)) {
|
|
30180
|
-
issues.push(issue("registry", rel, "missing **Source of truth for** banner (required for registry entry)"));
|
|
30181
|
-
}
|
|
30182
|
-
}
|
|
30183
|
-
return issues;
|
|
30184
|
-
}
|
|
30185
|
-
function checkUnregisteredBanners(ctx, registry) {
|
|
30186
|
-
const issues = [];
|
|
30187
|
-
for (const filePath of ctx.files) {
|
|
30188
|
-
const rel = relPath(filePath, ctx.root);
|
|
30189
|
-
if (rel === REGISTRY_REL_PATH)
|
|
30190
|
-
continue;
|
|
30191
|
-
if (!(rel.endsWith(".md") || rel.endsWith(".mdc")))
|
|
30192
|
-
continue;
|
|
30193
|
-
const content3 = readFileSync13(filePath, "utf8");
|
|
30194
|
-
if (!SOURCE_OF_TRUTH_BANNER_LINE_RE.test(content3))
|
|
30195
|
-
continue;
|
|
30196
|
-
if (!registry.has(rel)) {
|
|
30197
|
-
issues.push(issue("registry", rel, "has **Source of truth for** banner but is not in .skeleton/registry.md — add registry row or remove banner"));
|
|
30198
|
-
}
|
|
30199
|
-
}
|
|
30200
|
-
return issues;
|
|
30201
|
-
}
|
|
30202
|
-
function runRegistryRule(ctx) {
|
|
30203
|
-
const issues = [];
|
|
30204
|
-
const registry = new Set(ctx.registryPaths);
|
|
30205
|
-
if (ctx.registryHasTableHeader && ctx.registryPaths.length === 0) {
|
|
30206
|
-
issues.push(issue("registry", REGISTRY_REL_PATH, "registry table header found but 0 rows parsed — check | Topic | Canonical file | format and link syntax"));
|
|
30207
|
-
}
|
|
30208
|
-
issues.push(...checkRegistryEntries(ctx));
|
|
30209
|
-
issues.push(...checkUnregisteredBanners(ctx, registry));
|
|
30210
|
-
return issues;
|
|
30211
|
-
}
|
|
30212
|
-
var registryRule = { id: "registry", run: runRegistryRule };
|
|
30213
|
-
|
|
30214
31380
|
// src/audit/rules/scan-gaps.ts
|
|
30215
31381
|
function runCoverageGapsRule(ctx) {
|
|
30216
31382
|
const exclude = [...COVERAGE_BUILTIN_EXCLUDES, ...ctx.config.scan.exclude];
|
|
@@ -30221,7 +31387,7 @@ function runCoverageGapsRule(ctx) {
|
|
|
30221
31387
|
if (scanned.has(rel))
|
|
30222
31388
|
continue;
|
|
30223
31389
|
issues.push(issue("coverage-gaps", rel, {
|
|
30224
|
-
message: "markdown outside audit scan perimeter — extend .skeleton/config.yaml scan.include",
|
|
31390
|
+
message: "markdown outside audit scan perimeter — extend skeleton.toml (or legacy .skeleton/config.yaml) scan.include",
|
|
30225
31391
|
severity: "warning"
|
|
30226
31392
|
}));
|
|
30227
31393
|
}
|
|
@@ -30240,11 +31406,11 @@ function runScanRootsRule(ctx) {
|
|
|
30240
31406
|
var scanRootsRule = { id: "scan-roots", run: runScanRootsRule };
|
|
30241
31407
|
|
|
30242
31408
|
// src/audit/rules/skill-index.ts
|
|
30243
|
-
import { existsSync as
|
|
31409
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync15 } from "node:fs";
|
|
30244
31410
|
import { join as join14, relative as relative8 } from "node:path";
|
|
30245
31411
|
function walkSkillMarkdown(dir) {
|
|
30246
31412
|
const files = [];
|
|
30247
|
-
if (!
|
|
31413
|
+
if (!existsSync15(dir))
|
|
30248
31414
|
return files;
|
|
30249
31415
|
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
30250
31416
|
if (entry.name.startsWith("."))
|
|
@@ -30276,17 +31442,13 @@ function parseReadmeTaxonomySlugs(content3) {
|
|
|
30276
31442
|
function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
30277
31443
|
const issues = [];
|
|
30278
31444
|
const rel = relative8(ctx.root, filePath).replace(/\\/g, "/");
|
|
30279
|
-
const content3 =
|
|
31445
|
+
const content3 = readFileSync15(filePath, "utf8");
|
|
30280
31446
|
if (isGeneratedReference(content3))
|
|
30281
31447
|
return issues;
|
|
30282
31448
|
for (const match of content3.matchAll(SKILL_LINK_RE)) {
|
|
30283
31449
|
const slug2 = match[1];
|
|
30284
31450
|
if (!slug2)
|
|
30285
31451
|
continue;
|
|
30286
|
-
if (ctx.retiredSkills.has(slug2)) {
|
|
30287
|
-
issues.push(issue("skill-index", rel, `references retired skill "${slug2}/SKILL.md"`));
|
|
30288
|
-
continue;
|
|
30289
|
-
}
|
|
30290
31452
|
if (!resolveSkillPath(index2, ctx.root, slug2)) {
|
|
30291
31453
|
issues.push(issue("skill-index", rel, `links missing skill "${slug2}/SKILL.md"`));
|
|
30292
31454
|
}
|
|
@@ -30296,13 +31458,13 @@ function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
|
30296
31458
|
function taxonomyIssuesForReadme(input) {
|
|
30297
31459
|
const { ctx, index: index2, skillRoot, diskSlugs, nonPublic } = input;
|
|
30298
31460
|
const readmePath = join14(ctx.root, skillRoot.relPath, "README.md");
|
|
30299
|
-
if (!
|
|
31461
|
+
if (!existsSync15(readmePath))
|
|
30300
31462
|
return [];
|
|
30301
|
-
const readme =
|
|
31463
|
+
const readme = readFileSync15(readmePath, "utf8");
|
|
30302
31464
|
if (!readme.includes("## Taxonomy"))
|
|
30303
31465
|
return [];
|
|
30304
31466
|
const taxonomySlugs = parseReadmeTaxonomySlugs(readme);
|
|
30305
|
-
const nestedSlugs = diskSlugs.filter((slug2) =>
|
|
31467
|
+
const nestedSlugs = diskSlugs.filter((slug2) => existsSync15(join14(ctx.root, skillRoot.relPath, slug2, "SKILL.md")));
|
|
30306
31468
|
const foreign = new Set(index2.foreignSlugs);
|
|
30307
31469
|
const publicSlugs = nestedSlugs.filter((slug2) => !(nonPublic.has(slug2) || foreign.has(slug2)));
|
|
30308
31470
|
const relReadme = `${skillRoot.relPath}/README.md`;
|
|
@@ -30338,7 +31500,7 @@ function auditSkillRoot(input) {
|
|
|
30338
31500
|
const base = skillRoot.kind === "nested" ? join14(ctx.root, skillRoot.relPath) : ctx.root;
|
|
30339
31501
|
for (const slug2 of slugsForRoot(skillRoot, index2, owned)) {
|
|
30340
31502
|
const skillDir = join14(base, slug2);
|
|
30341
|
-
if (!
|
|
31503
|
+
if (!existsSync15(skillDir))
|
|
30342
31504
|
continue;
|
|
30343
31505
|
for (const skillMd of walkSkillMarkdown(skillDir)) {
|
|
30344
31506
|
issues.push(...scanFileForSkillLinks(ctx, skillMd, index2));
|
|
@@ -30377,10 +31539,46 @@ function skillAuditSuffix(ctx) {
|
|
|
30377
31539
|
return ` (${owned} owned skills audited, ${foreign} foreign ignored)`;
|
|
30378
31540
|
}
|
|
30379
31541
|
|
|
31542
|
+
// src/audit/rules/ssot.ts
|
|
31543
|
+
function runSsotRule(ctx) {
|
|
31544
|
+
const issues = [];
|
|
31545
|
+
for (const err of ctx.ssotErrors) {
|
|
31546
|
+
issues.push(issue("ssot", err.path, err.detail));
|
|
31547
|
+
}
|
|
31548
|
+
return issues;
|
|
31549
|
+
}
|
|
31550
|
+
var ssotRule = { id: "ssot", run: runSsotRule };
|
|
31551
|
+
|
|
31552
|
+
// src/audit/rules/ssot-summary.ts
|
|
31553
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
31554
|
+
import { join as join15 } from "node:path";
|
|
31555
|
+
function runSsotSummaryRule(ctx) {
|
|
31556
|
+
const overlapMin = ctx.config.docsLint?.ssotOverlapMin ?? DEFAULT_SSOT_OVERLAP_MIN;
|
|
31557
|
+
const margin = ctx.config.docsLint?.ssotBetterMatchMargin ?? DEFAULT_BETTER_MATCH_MARGIN;
|
|
31558
|
+
const phraseCheck = ctx.config.docsLint?.ssotPhraseCheck !== false;
|
|
31559
|
+
const files = ctx.ssotEntries.map((entry) => ({
|
|
31560
|
+
path: entry.path,
|
|
31561
|
+
summary: entry.summary,
|
|
31562
|
+
content: readFileSync16(join15(ctx.root, entry.path), "utf8")
|
|
31563
|
+
}));
|
|
31564
|
+
return evaluateSsotFit(files, {
|
|
31565
|
+
overlapMin,
|
|
31566
|
+
betterMatchMargin: margin,
|
|
31567
|
+
phraseCheck
|
|
31568
|
+
}).map((fit) => issue("ssot-summary", fit.path, {
|
|
31569
|
+
message: fit.message,
|
|
31570
|
+
severity: "warning",
|
|
31571
|
+
link: fit.otherPath
|
|
31572
|
+
}));
|
|
31573
|
+
}
|
|
31574
|
+
var ssotSummaryRule = { id: "ssot-summary", run: runSsotSummaryRule };
|
|
31575
|
+
|
|
30380
31576
|
// src/audit/rules/index.ts
|
|
30381
31577
|
var docsRules = [
|
|
30382
31578
|
{ ...scanRootsRule, global: true },
|
|
30383
|
-
{ ...
|
|
31579
|
+
{ ...ssotRule, global: true },
|
|
31580
|
+
{ ...nearDuplicateRule, global: true },
|
|
31581
|
+
{ ...ssotSummaryRule, global: true },
|
|
30384
31582
|
{ ...coverageGapsRule, global: true },
|
|
30385
31583
|
linksRule,
|
|
30386
31584
|
docMetaRule,
|
|
@@ -30444,8 +31642,8 @@ function rulesForSuite(suite, pluginRules = []) {
|
|
|
30444
31642
|
function parseFixArg(argv, index2) {
|
|
30445
31643
|
const next = argv[index2 + 1];
|
|
30446
31644
|
if (next && !next.startsWith("-")) {
|
|
30447
|
-
if (next !== "doc-meta" && next !== "anchors") {
|
|
30448
|
-
throw new Error(`Unknown --fix kind: ${next}. Use --fix, --fix=doc-meta, or --fix=
|
|
31645
|
+
if (next !== "doc-meta" && next !== "anchors" && next !== "ssot") {
|
|
31646
|
+
throw new Error(`Unknown --fix kind: ${next}. Use --fix, --fix=doc-meta, --fix=anchors, or --fix=ssot.`);
|
|
30449
31647
|
}
|
|
30450
31648
|
return { fix: next, nextIndex: index2 + 1 };
|
|
30451
31649
|
}
|
|
@@ -30536,7 +31734,7 @@ async function runAuditFixes(options, ctx, loaded) {
|
|
|
30536
31734
|
}
|
|
30537
31735
|
const kinds = fixKindsForOnly(parseFixKinds(options.fix), options.only);
|
|
30538
31736
|
if (kinds.length === 0) {
|
|
30539
|
-
console.error("--fix has no overlapping rules with --only (doc-meta → doc-meta, anchors → links).");
|
|
31737
|
+
console.error("--fix has no overlapping rules with --only (doc-meta → doc-meta, anchors → links, ssot → ssot).");
|
|
30540
31738
|
return 1;
|
|
30541
31739
|
}
|
|
30542
31740
|
applyFixes(ctx, { kinds, dryRun: options.dryRun });
|
|
@@ -30580,41 +31778,89 @@ async function runAudit(options) {
|
|
|
30580
31778
|
});
|
|
30581
31779
|
}
|
|
30582
31780
|
|
|
31781
|
+
// src/catalog.ts
|
|
31782
|
+
import { existsSync as existsSync16, mkdirSync, readFileSync as readFileSync17, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31783
|
+
import { dirname as dirname8, join as join16 } from "node:path";
|
|
31784
|
+
function renderCatalog(entries) {
|
|
31785
|
+
const lines = [
|
|
31786
|
+
"# Skeleton catalog",
|
|
31787
|
+
"",
|
|
31788
|
+
"Generated by `skeleton catalog`. Gitignored — regenerate locally; do not commit.",
|
|
31789
|
+
"",
|
|
31790
|
+
"Agents: skim this list, then read only the SSOT line / first ~20 lines of a candidate before opening the full paper.",
|
|
31791
|
+
"",
|
|
31792
|
+
"| Summary | Path |",
|
|
31793
|
+
"| ------- | ---- |"
|
|
31794
|
+
];
|
|
31795
|
+
for (const e of entries) {
|
|
31796
|
+
const summary = e.summary.replace(/\|/g, "\\|");
|
|
31797
|
+
lines.push(`| ${summary} | [${e.path}](../${e.path}) |`);
|
|
31798
|
+
}
|
|
31799
|
+
lines.push("");
|
|
31800
|
+
return lines.join(`
|
|
31801
|
+
`);
|
|
31802
|
+
}
|
|
31803
|
+
function buildCatalogContent(root2) {
|
|
31804
|
+
const config = loadConfig(root2);
|
|
31805
|
+
const skillIndex = buildSkillIndex(root2, config.skillOwnership);
|
|
31806
|
+
const files = collectScanFiles(config, root2, skillIndex);
|
|
31807
|
+
const { entries } = collectSsotEntries(files, root2);
|
|
31808
|
+
return { content: renderCatalog(entries), entries };
|
|
31809
|
+
}
|
|
31810
|
+
function checkCatalog(root2) {
|
|
31811
|
+
const { content: expected, entries } = buildCatalogContent(root2);
|
|
31812
|
+
const abs = join16(root2, CATALOG_REL_PATH);
|
|
31813
|
+
if (!existsSync16(abs)) {
|
|
31814
|
+
return { ok: false, missing: true, stale: false, expected, actual: null, entries };
|
|
31815
|
+
}
|
|
31816
|
+
const actual = readFileSync17(abs, "utf8");
|
|
31817
|
+
const stale = actual !== expected;
|
|
31818
|
+
return { ok: !stale, missing: false, stale, expected, actual, entries };
|
|
31819
|
+
}
|
|
31820
|
+
function writeCatalog(root2) {
|
|
31821
|
+
const { content: content3, entries } = buildCatalogContent(root2);
|
|
31822
|
+
const abs = join16(root2, CATALOG_REL_PATH);
|
|
31823
|
+
mkdirSync(dirname8(abs), { recursive: true });
|
|
31824
|
+
writeFileSync2(abs, content3, "utf8");
|
|
31825
|
+
return { path: normalizeRelPath(CATALOG_REL_PATH), entries };
|
|
31826
|
+
}
|
|
31827
|
+
function runCatalogCli(options = {}) {
|
|
31828
|
+
const root2 = options.root ?? findRepoRoot();
|
|
31829
|
+
if (options.check) {
|
|
31830
|
+
const result = checkCatalog(root2);
|
|
31831
|
+
if (result.missing) {
|
|
31832
|
+
console.error(`catalog: missing ${CATALOG_REL_PATH} — run \`skeleton catalog\``);
|
|
31833
|
+
return 0;
|
|
31834
|
+
}
|
|
31835
|
+
if (result.stale) {
|
|
31836
|
+
console.error(`catalog: ${CATALOG_REL_PATH} is outdated — run \`skeleton catalog\``);
|
|
31837
|
+
return 0;
|
|
31838
|
+
}
|
|
31839
|
+
console.log(`catalog: ${CATALOG_REL_PATH} up to date (${result.entries.length} entries)`);
|
|
31840
|
+
return 0;
|
|
31841
|
+
}
|
|
31842
|
+
const written = writeCatalog(root2);
|
|
31843
|
+
console.log(`catalog: wrote ${written.path} (${written.entries.length} entries)`);
|
|
31844
|
+
return 0;
|
|
31845
|
+
}
|
|
31846
|
+
|
|
30583
31847
|
// src/customize/resolve.ts
|
|
30584
|
-
import { existsSync as
|
|
30585
|
-
import { basename as basename3, join as
|
|
30586
|
-
var CUSTOMIZE_PREFIX = "Customize: ";
|
|
31848
|
+
import { existsSync as existsSync17, readFileSync as readFileSync18 } from "node:fs";
|
|
31849
|
+
import { basename as basename3, join as join17, relative as relative9 } from "node:path";
|
|
30587
31850
|
function customizeDir(root2) {
|
|
30588
|
-
return
|
|
31851
|
+
return join17(root2, REGISTRY_DIR_REL, "customize");
|
|
30589
31852
|
}
|
|
30590
31853
|
function customizePathForSlug(root2, slug2) {
|
|
30591
|
-
return
|
|
30592
|
-
}
|
|
30593
|
-
function findCustomizeViaRegistry(root2, slug2) {
|
|
30594
|
-
for (const rel of parseRegistry(root2).paths) {
|
|
30595
|
-
const expected = `${REGISTRY_DIR_REL}/customize/${slug2}.md`;
|
|
30596
|
-
if (normalizeRelPath(rel) === expected && existsSync18(join15(root2, rel))) {
|
|
30597
|
-
return rel;
|
|
30598
|
-
}
|
|
30599
|
-
}
|
|
30600
|
-
return null;
|
|
31854
|
+
return join17(customizeDir(root2), `${slug2}.md`);
|
|
30601
31855
|
}
|
|
30602
31856
|
function resolveSlugFile(root2, slug2) {
|
|
30603
31857
|
const direct = customizePathForSlug(root2, slug2);
|
|
30604
|
-
if (
|
|
31858
|
+
if (existsSync17(direct)) {
|
|
30605
31859
|
return {
|
|
30606
|
-
content:
|
|
31860
|
+
content: readFileSync18(direct, "utf8"),
|
|
30607
31861
|
path: normalizeRelPath(relative9(root2, direct))
|
|
30608
31862
|
};
|
|
30609
31863
|
}
|
|
30610
|
-
const registryPath = findCustomizeViaRegistry(root2, slug2);
|
|
30611
|
-
if (registryPath) {
|
|
30612
|
-
const abs = join15(root2, registryPath);
|
|
30613
|
-
return {
|
|
30614
|
-
content: readFileSync15(abs, "utf8"),
|
|
30615
|
-
path: registryPath
|
|
30616
|
-
};
|
|
30617
|
-
}
|
|
30618
31864
|
return { content: null, path: null };
|
|
30619
31865
|
}
|
|
30620
31866
|
function alwaysIncludeBasenames(root2) {
|
|
@@ -30633,10 +31879,10 @@ function readAlwaysInclude(root2, basenames, skipBasename) {
|
|
|
30633
31879
|
const file = basename3(name);
|
|
30634
31880
|
if (skipBasename && file === skipBasename)
|
|
30635
31881
|
continue;
|
|
30636
|
-
const abs =
|
|
30637
|
-
if (!
|
|
31882
|
+
const abs = join17(dir, file);
|
|
31883
|
+
if (!existsSync17(abs))
|
|
30638
31884
|
continue;
|
|
30639
|
-
parts.push(
|
|
31885
|
+
parts.push(readFileSync18(abs, "utf8").trimEnd());
|
|
30640
31886
|
paths.push(normalizeRelPath(relative9(root2, abs)));
|
|
30641
31887
|
}
|
|
30642
31888
|
return { parts, paths };
|
|
@@ -30760,39 +32006,39 @@ Customize override for /${slug2} (from ${from}):
|
|
|
30760
32006
|
|
|
30761
32007
|
// src/init/init.ts
|
|
30762
32008
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
30763
|
-
import { copyFileSync, existsSync as
|
|
30764
|
-
import { join as
|
|
32009
|
+
import { copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync3, readFileSync as readFileSync20 } from "node:fs";
|
|
32010
|
+
import { join as join21 } from "node:path";
|
|
30765
32011
|
import process4 from "node:process";
|
|
30766
32012
|
|
|
30767
32013
|
// src/init/merge-hooks.ts
|
|
30768
|
-
import { existsSync as
|
|
30769
|
-
import { dirname as
|
|
32014
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync2, readFileSync as readFileSync19, writeFileSync as writeFileSync3 } from "node:fs";
|
|
32015
|
+
import { dirname as dirname11, join as join20 } from "node:path";
|
|
30770
32016
|
|
|
30771
32017
|
// src/init/package-paths.ts
|
|
30772
|
-
import { existsSync as
|
|
30773
|
-
import { dirname as
|
|
32018
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
32019
|
+
import { dirname as dirname9, join as join18 } from "node:path";
|
|
30774
32020
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
30775
|
-
var MODULE_DIR =
|
|
30776
|
-
var PACKAGE_ROOT_CANDIDATES = [
|
|
32021
|
+
var MODULE_DIR = dirname9(fileURLToPath5(import.meta.url));
|
|
32022
|
+
var PACKAGE_ROOT_CANDIDATES = [join18(MODULE_DIR, "../.."), join18(MODULE_DIR, "..")];
|
|
30777
32023
|
function resolvePackageRoot() {
|
|
30778
32024
|
for (const candidate of PACKAGE_ROOT_CANDIDATES) {
|
|
30779
|
-
if (
|
|
32025
|
+
if (existsSync18(join18(candidate, "package.json")))
|
|
30780
32026
|
return candidate;
|
|
30781
32027
|
}
|
|
30782
32028
|
throw new Error("Could not resolve @csark0812/skeleton package root");
|
|
30783
32029
|
}
|
|
30784
32030
|
function resolveTemplatesDir() {
|
|
30785
|
-
const dir =
|
|
30786
|
-
if (!
|
|
32031
|
+
const dir = join18(resolvePackageRoot(), "templates/skeleton-init");
|
|
32032
|
+
if (!existsSync18(dir)) {
|
|
30787
32033
|
throw new Error("Missing templates/skeleton-init in package");
|
|
30788
32034
|
}
|
|
30789
32035
|
return dir;
|
|
30790
32036
|
}
|
|
30791
32037
|
|
|
30792
32038
|
// src/init/resolve-hook-command.ts
|
|
30793
|
-
import { existsSync as
|
|
32039
|
+
import { existsSync as existsSync19, realpathSync as realpathSync6 } from "node:fs";
|
|
30794
32040
|
import { createRequire as createRequire3 } from "node:module";
|
|
30795
|
-
import { dirname as
|
|
32041
|
+
import { dirname as dirname10, join as join19, relative as relative10, resolve as resolve7 } from "node:path";
|
|
30796
32042
|
var PACKAGE_NAME = "@csark0812/skeleton";
|
|
30797
32043
|
var CLI_DIST = "dist/cli.js";
|
|
30798
32044
|
var PACKAGE_ROOT = resolvePackageRoot();
|
|
@@ -30811,7 +32057,7 @@ function toRepoRelative(cwd, absPath) {
|
|
|
30811
32057
|
}
|
|
30812
32058
|
function tryResolvePublishedCli(cwd) {
|
|
30813
32059
|
try {
|
|
30814
|
-
const req = createRequire3(
|
|
32060
|
+
const req = createRequire3(join19(cwd, "package.json"));
|
|
30815
32061
|
return req.resolve(`${PACKAGE_NAME}/${CLI_DIST}`);
|
|
30816
32062
|
} catch {
|
|
30817
32063
|
return null;
|
|
@@ -30820,10 +32066,10 @@ function tryResolvePublishedCli(cwd) {
|
|
|
30820
32066
|
function walkNodeModulesCli(cwd) {
|
|
30821
32067
|
let dir = cwd;
|
|
30822
32068
|
while (true) {
|
|
30823
|
-
const candidate =
|
|
30824
|
-
if (
|
|
32069
|
+
const candidate = join19(dir, "node_modules", PACKAGE_NAME, CLI_DIST);
|
|
32070
|
+
if (existsSync19(candidate))
|
|
30825
32071
|
return candidate;
|
|
30826
|
-
const parent =
|
|
32072
|
+
const parent = dirname10(dir);
|
|
30827
32073
|
if (parent === dir)
|
|
30828
32074
|
break;
|
|
30829
32075
|
dir = parent;
|
|
@@ -30831,7 +32077,7 @@ function walkNodeModulesCli(cwd) {
|
|
|
30831
32077
|
return null;
|
|
30832
32078
|
}
|
|
30833
32079
|
function isInsidePackageRoot(cwd) {
|
|
30834
|
-
const rel = relative10(PACKAGE_ROOT,
|
|
32080
|
+
const rel = relative10(PACKAGE_ROOT, resolve7(cwd)).replace(/\\/g, "/");
|
|
30835
32081
|
return rel === "" || !(rel.startsWith("..") || rel.startsWith("/"));
|
|
30836
32082
|
}
|
|
30837
32083
|
function nodeCliHookCommand(cliPath) {
|
|
@@ -30862,21 +32108,21 @@ function identityKey(platform, event, matcher) {
|
|
|
30862
32108
|
return `skeleton:customize:${platform}:${event}:${matcher}`;
|
|
30863
32109
|
}
|
|
30864
32110
|
function loadFragment(name, hookCommand) {
|
|
30865
|
-
const raw =
|
|
32111
|
+
const raw = readFileSync19(join20(TEMPLATES_DIR, name), "utf8");
|
|
30866
32112
|
return JSON.parse(raw.replaceAll("{{HOOK_COMMAND}}", hookCommand));
|
|
30867
32113
|
}
|
|
30868
32114
|
function readJson(path2) {
|
|
30869
|
-
if (!
|
|
32115
|
+
if (!existsSync20(path2))
|
|
30870
32116
|
return null;
|
|
30871
32117
|
try {
|
|
30872
|
-
return JSON.parse(
|
|
32118
|
+
return JSON.parse(readFileSync19(path2, "utf8"));
|
|
30873
32119
|
} catch (error) {
|
|
30874
32120
|
throw new Error(`Invalid JSON in ${path2}: ${error}`);
|
|
30875
32121
|
}
|
|
30876
32122
|
}
|
|
30877
32123
|
function writeJson(path2, value) {
|
|
30878
|
-
|
|
30879
|
-
|
|
32124
|
+
mkdirSync2(dirname11(path2), { recursive: true });
|
|
32125
|
+
writeFileSync3(path2, `${JSON.stringify(value, null, 2)}
|
|
30880
32126
|
`, "utf8");
|
|
30881
32127
|
}
|
|
30882
32128
|
function deepEqual(a, b) {
|
|
@@ -31029,10 +32275,10 @@ function mergeNestedHooks(args) {
|
|
|
31029
32275
|
}
|
|
31030
32276
|
function mergeHookConfigs(opts) {
|
|
31031
32277
|
const results = [];
|
|
31032
|
-
const cursorPath =
|
|
32278
|
+
const cursorPath = join20(opts.cwd, ".cursor/hooks.json");
|
|
31033
32279
|
const cursorFragment = loadFragment("cursor-hooks.fragment.json", opts.hookCommand);
|
|
31034
32280
|
results.push(mergeCursorHooks(cursorPath, cursorFragment, opts));
|
|
31035
|
-
const claudePath =
|
|
32281
|
+
const claudePath = join20(opts.cwd, ".claude/settings.json");
|
|
31036
32282
|
const claudeFragment = loadFragment("claude-settings.fragment.json", opts.hookCommand);
|
|
31037
32283
|
results.push(mergeNestedHooks({
|
|
31038
32284
|
platform: "claude",
|
|
@@ -31041,8 +32287,8 @@ function mergeHookConfigs(opts) {
|
|
|
31041
32287
|
eventName: "PostToolUse",
|
|
31042
32288
|
opts
|
|
31043
32289
|
}));
|
|
31044
|
-
const codexPath =
|
|
31045
|
-
if (
|
|
32290
|
+
const codexPath = join20(opts.cwd, ".codex/hooks.json");
|
|
32291
|
+
if (existsSync20(join20(opts.cwd, ".codex"))) {
|
|
31046
32292
|
const codexFragment = loadFragment("codex-hooks.fragment.json", opts.hookCommand);
|
|
31047
32293
|
results.push(mergeNestedHooks({
|
|
31048
32294
|
platform: "codex",
|
|
@@ -31057,11 +32303,11 @@ function mergeHookConfigs(opts) {
|
|
|
31057
32303
|
return results;
|
|
31058
32304
|
}
|
|
31059
32305
|
function mergePackageJsonScripts(cwd) {
|
|
31060
|
-
const pkgPath =
|
|
31061
|
-
if (!
|
|
32306
|
+
const pkgPath = join20(cwd, "package.json");
|
|
32307
|
+
if (!existsSync20(pkgPath))
|
|
31062
32308
|
return "skipped";
|
|
31063
|
-
const fragment = JSON.parse(
|
|
31064
|
-
const pkg = JSON.parse(
|
|
32309
|
+
const fragment = JSON.parse(readFileSync19(join20(TEMPLATES_DIR, "package.json.scripts.fragment.json"), "utf8"));
|
|
32310
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
31065
32311
|
pkg.scripts ??= {};
|
|
31066
32312
|
let changed = false;
|
|
31067
32313
|
for (const [key, value] of Object.entries(fragment)) {
|
|
@@ -31072,7 +32318,7 @@ function mergePackageJsonScripts(cwd) {
|
|
|
31072
32318
|
}
|
|
31073
32319
|
if (!changed)
|
|
31074
32320
|
return "skipped";
|
|
31075
|
-
|
|
32321
|
+
writeFileSync3(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
31076
32322
|
`, "utf8");
|
|
31077
32323
|
return "updated";
|
|
31078
32324
|
}
|
|
@@ -31117,27 +32363,23 @@ function skillsAddArgs(options = {}) {
|
|
|
31117
32363
|
// src/init/init.ts
|
|
31118
32364
|
var TEMPLATES_DIR2 = resolveTemplatesDir();
|
|
31119
32365
|
function writeScaffold(cwd) {
|
|
31120
|
-
const skeletonDir2 =
|
|
31121
|
-
|
|
32366
|
+
const skeletonDir2 = join21(cwd, ".skeleton");
|
|
32367
|
+
mkdirSync3(skeletonDir2, { recursive: true });
|
|
31122
32368
|
let created = false;
|
|
31123
|
-
const
|
|
31124
|
-
|
|
31125
|
-
|
|
31126
|
-
|
|
31127
|
-
}
|
|
31128
|
-
const registryPath = join19(skeletonDir2, "registry.md");
|
|
31129
|
-
if (!existsSync22(registryPath)) {
|
|
31130
|
-
copyFileSync(join19(TEMPLATES_DIR2, "registry.md"), registryPath);
|
|
32369
|
+
const tomlPath = join21(cwd, "skeleton.toml");
|
|
32370
|
+
const legacyYaml = join21(skeletonDir2, "config.yaml");
|
|
32371
|
+
if (!(existsSync21(tomlPath) || existsSync21(legacyYaml))) {
|
|
32372
|
+
copyFileSync(join21(TEMPLATES_DIR2, "skeleton.toml"), tomlPath);
|
|
31131
32373
|
created = true;
|
|
31132
32374
|
}
|
|
31133
|
-
|
|
32375
|
+
mkdirSync3(join21(skeletonDir2, "customize"), { recursive: true });
|
|
31134
32376
|
return created ? "created" : "skipped";
|
|
31135
32377
|
}
|
|
31136
32378
|
function assertPackageResolvable(cwd) {
|
|
31137
|
-
const pkgPath =
|
|
31138
|
-
if (!
|
|
32379
|
+
const pkgPath = join21(cwd, "package.json");
|
|
32380
|
+
if (!existsSync21(pkgPath))
|
|
31139
32381
|
return;
|
|
31140
|
-
const pkg = JSON.parse(
|
|
32382
|
+
const pkg = JSON.parse(readFileSync20(pkgPath, "utf8"));
|
|
31141
32383
|
const hasDep = pkg.devDependencies?.["@csark0812/skeleton"] || pkg.dependencies?.["@csark0812/skeleton"];
|
|
31142
32384
|
if (!hasDep) {
|
|
31143
32385
|
try {
|
|
@@ -31186,9 +32428,9 @@ function runInit(options = {}) {
|
|
|
31186
32428
|
for (const result of hooks)
|
|
31187
32429
|
logHookMergeResult(result);
|
|
31188
32430
|
if (scaffold === "created") {
|
|
31189
|
-
console.log("init: wrote
|
|
32431
|
+
console.log("init: wrote skeleton.toml (hooks optional — see docs)");
|
|
31190
32432
|
} else {
|
|
31191
|
-
console.log("init: .skeleton/ already present — skipped scaffold write");
|
|
32433
|
+
console.log("init: skeleton.toml or .skeleton/ already present — skipped scaffold write");
|
|
31192
32434
|
}
|
|
31193
32435
|
if (scripts === "updated") {
|
|
31194
32436
|
console.log("init: merged validate/audit scripts into package.json");
|
|
@@ -31221,8 +32463,8 @@ function parseInitArgs(argv) {
|
|
|
31221
32463
|
// src/plugins/build.ts
|
|
31222
32464
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
31223
32465
|
import { createHash } from "node:crypto";
|
|
31224
|
-
import { existsSync as
|
|
31225
|
-
import { basename as basename4, dirname as
|
|
32466
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "node:fs";
|
|
32467
|
+
import { basename as basename4, dirname as dirname12, resolve as resolve8 } from "node:path";
|
|
31226
32468
|
function parseBuildPluginArgs(argv) {
|
|
31227
32469
|
let check = false;
|
|
31228
32470
|
let entry;
|
|
@@ -31247,7 +32489,7 @@ function collectPluginEntries(root2, config, entry) {
|
|
|
31247
32489
|
return (config.plugins ?? []).map((e) => resolvePluginTsPath(root2, e));
|
|
31248
32490
|
}
|
|
31249
32491
|
function localImportPaths(tsAbs, content3) {
|
|
31250
|
-
const dir =
|
|
32492
|
+
const dir = dirname12(tsAbs);
|
|
31251
32493
|
const deps = [];
|
|
31252
32494
|
const re = /(?:from\s+|import\s*\(\s*|import\s+)["'](\.[^"']+)["']/g;
|
|
31253
32495
|
for (const match of content3.matchAll(re)) {
|
|
@@ -31257,12 +32499,12 @@ function localImportPaths(tsAbs, content3) {
|
|
|
31257
32499
|
const candidates = [];
|
|
31258
32500
|
if (spec.endsWith(".js")) {
|
|
31259
32501
|
const withoutJs = spec.slice(0, -".js".length);
|
|
31260
|
-
candidates.push(
|
|
32502
|
+
candidates.push(resolve8(dir, `${withoutJs}.ts`), resolve8(dir, spec), resolve8(dir, withoutJs, "index.ts"));
|
|
31261
32503
|
} else {
|
|
31262
|
-
candidates.push(
|
|
32504
|
+
candidates.push(resolve8(dir, spec), resolve8(dir, `${spec}.ts`), resolve8(dir, `${spec}.js`), resolve8(dir, spec, "index.ts"));
|
|
31263
32505
|
}
|
|
31264
32506
|
for (const candidate of candidates) {
|
|
31265
|
-
if (
|
|
32507
|
+
if (existsSync22(candidate) && candidate.endsWith(".ts")) {
|
|
31266
32508
|
deps.push(candidate);
|
|
31267
32509
|
break;
|
|
31268
32510
|
}
|
|
@@ -31279,7 +32521,7 @@ function sourceFingerprint(tsAbs, seen = new Set) {
|
|
|
31279
32521
|
if (seen.has(abs))
|
|
31280
32522
|
return;
|
|
31281
32523
|
seen.add(abs);
|
|
31282
|
-
const content3 =
|
|
32524
|
+
const content3 = readFileSync21(abs, "utf8");
|
|
31283
32525
|
hash.update(basename4(abs));
|
|
31284
32526
|
hash.update("\x00");
|
|
31285
32527
|
hash.update(content3);
|
|
@@ -31292,12 +32534,12 @@ function sourceFingerprint(tsAbs, seen = new Set) {
|
|
|
31292
32534
|
return hash.digest("hex");
|
|
31293
32535
|
}
|
|
31294
32536
|
function writeStamp(tsAbs, mjsAbs) {
|
|
31295
|
-
|
|
32537
|
+
writeFileSync4(stampPathForMjs(mjsAbs), `${sourceFingerprint(tsAbs)}
|
|
31296
32538
|
`, "utf8");
|
|
31297
32539
|
}
|
|
31298
32540
|
async function buildOne(tsAbs) {
|
|
31299
32541
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
31300
|
-
if (!
|
|
32542
|
+
if (!existsSync22(tsAbs)) {
|
|
31301
32543
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
31302
32544
|
}
|
|
31303
32545
|
const proc = spawnSync3("bun", ["build", tsAbs, "--target=node", "--format=esm", `--outfile=${mjsAbs}`, "--packages=external"], { encoding: "utf8" });
|
|
@@ -31317,17 +32559,17 @@ ${proc.stderr || proc.stdout || `exit ${proc.status}`}`);
|
|
|
31317
32559
|
}
|
|
31318
32560
|
function checkOne(tsAbs) {
|
|
31319
32561
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
31320
|
-
if (!
|
|
32562
|
+
if (!existsSync22(mjsAbs)) {
|
|
31321
32563
|
throw new Error(`Plugin not built: ${tsAbs} (missing ${mjsAbs}). Run: skeleton build-plugin`);
|
|
31322
32564
|
}
|
|
31323
|
-
if (!
|
|
32565
|
+
if (!existsSync22(tsAbs)) {
|
|
31324
32566
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
31325
32567
|
}
|
|
31326
32568
|
const stampAbs = stampPathForMjs(mjsAbs);
|
|
31327
|
-
if (!
|
|
32569
|
+
if (!existsSync22(stampAbs)) {
|
|
31328
32570
|
throw new Error(`Plugin stale: ${mjsAbs} has no fingerprint stamp. Run: skeleton build-plugin`);
|
|
31329
32571
|
}
|
|
31330
|
-
const expected =
|
|
32572
|
+
const expected = readFileSync21(stampAbs, "utf8").trim();
|
|
31331
32573
|
const actual = sourceFingerprint(tsAbs);
|
|
31332
32574
|
if (expected !== actual) {
|
|
31333
32575
|
throw new Error(`Plugin stale: ${mjsAbs} does not match ${tsAbs} (or local imports). Run: skeleton build-plugin`);
|
|
@@ -31360,14 +32602,14 @@ import process6 from "node:process";
|
|
|
31360
32602
|
|
|
31361
32603
|
// src/references/sync.ts
|
|
31362
32604
|
import {
|
|
31363
|
-
existsSync as
|
|
31364
|
-
mkdirSync as
|
|
32605
|
+
existsSync as existsSync23,
|
|
32606
|
+
mkdirSync as mkdirSync4,
|
|
31365
32607
|
readdirSync as readdirSync6,
|
|
31366
|
-
readFileSync as
|
|
32608
|
+
readFileSync as readFileSync22,
|
|
31367
32609
|
unlinkSync,
|
|
31368
|
-
writeFileSync as
|
|
32610
|
+
writeFileSync as writeFileSync5
|
|
31369
32611
|
} from "node:fs";
|
|
31370
|
-
import { dirname as
|
|
32612
|
+
import { dirname as dirname13, join as join22, relative as relative11 } from "node:path";
|
|
31371
32613
|
import process5 from "node:process";
|
|
31372
32614
|
function resolveOwnership(root2, override) {
|
|
31373
32615
|
if (override !== undefined)
|
|
@@ -31378,12 +32620,12 @@ function resolveOwnership(root2, override) {
|
|
|
31378
32620
|
}
|
|
31379
32621
|
function walkMarkdownFiles2(dir, root2) {
|
|
31380
32622
|
const files = [];
|
|
31381
|
-
if (!
|
|
32623
|
+
if (!existsSync23(dir))
|
|
31382
32624
|
return files;
|
|
31383
32625
|
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
31384
32626
|
if (entry.name.startsWith("."))
|
|
31385
32627
|
continue;
|
|
31386
|
-
const fullPath =
|
|
32628
|
+
const fullPath = join22(dir, entry.name);
|
|
31387
32629
|
if (entry.isDirectory()) {
|
|
31388
32630
|
files.push(...walkMarkdownFiles2(fullPath, root2));
|
|
31389
32631
|
continue;
|
|
@@ -31397,14 +32639,14 @@ function walkMarkdownFiles2(dir, root2) {
|
|
|
31397
32639
|
function collectGeneratedInDir(input) {
|
|
31398
32640
|
const { dir, refsDir, skill, files } = input;
|
|
31399
32641
|
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
31400
|
-
const fullPath =
|
|
32642
|
+
const fullPath = join22(dir, entry.name);
|
|
31401
32643
|
if (entry.isDirectory()) {
|
|
31402
32644
|
collectGeneratedInDir({ dir: fullPath, refsDir, skill, files });
|
|
31403
32645
|
continue;
|
|
31404
32646
|
}
|
|
31405
32647
|
if (!entry.name.endsWith(".md"))
|
|
31406
32648
|
continue;
|
|
31407
|
-
const content3 =
|
|
32649
|
+
const content3 = readFileSync22(fullPath, "utf8");
|
|
31408
32650
|
if (!isGeneratedReference(content3))
|
|
31409
32651
|
continue;
|
|
31410
32652
|
const refPath = normalizeRelPath(relative11(refsDir, fullPath));
|
|
@@ -31412,8 +32654,8 @@ function collectGeneratedInDir(input) {
|
|
|
31412
32654
|
}
|
|
31413
32655
|
}
|
|
31414
32656
|
function listGeneratedReferenceFiles(skillDir, skill) {
|
|
31415
|
-
const refsDir =
|
|
31416
|
-
if (!
|
|
32657
|
+
const refsDir = join22(skillDir, "references");
|
|
32658
|
+
if (!existsSync23(refsDir))
|
|
31417
32659
|
return [];
|
|
31418
32660
|
const files = [];
|
|
31419
32661
|
collectGeneratedInDir({ dir: refsDir, refsDir, skill, files });
|
|
@@ -31421,21 +32663,21 @@ function listGeneratedReferenceFiles(skillDir, skill) {
|
|
|
31421
32663
|
}
|
|
31422
32664
|
function syncGeneratedCopy(ctx, refPath) {
|
|
31423
32665
|
const { root: root2, plan, options, result } = ctx;
|
|
31424
|
-
const sourceRel = normalizeRelPath(
|
|
31425
|
-
const canonicalPath =
|
|
31426
|
-
if (!
|
|
32666
|
+
const sourceRel = normalizeRelPath(join22(CANONICAL_REFS_DIR, refPath));
|
|
32667
|
+
const canonicalPath = join22(root2, sourceRel);
|
|
32668
|
+
if (!existsSync23(canonicalPath)) {
|
|
31427
32669
|
throw new Error(`canonical reference missing: ${sourceRel}`);
|
|
31428
32670
|
}
|
|
31429
32671
|
const targetRel = generatedRefPath(plan.skill, refPath);
|
|
31430
|
-
const targetPath =
|
|
31431
|
-
const canonicalContent =
|
|
32672
|
+
const targetPath = join22(root2, targetRel);
|
|
32673
|
+
const canonicalContent = readFileSync22(canonicalPath, "utf8");
|
|
31432
32674
|
const nextContent = formatGeneratedHeader(sourceRel) + canonicalContent;
|
|
31433
32675
|
if (!options.dryRun)
|
|
31434
|
-
|
|
31435
|
-
const existing =
|
|
32676
|
+
mkdirSync4(dirname13(targetPath), { recursive: true });
|
|
32677
|
+
const existing = existsSync23(targetPath) ? readFileSync22(targetPath, "utf8") : null;
|
|
31436
32678
|
if (existing !== nextContent) {
|
|
31437
32679
|
if (!options.dryRun)
|
|
31438
|
-
|
|
32680
|
+
writeFileSync5(targetPath, nextContent, "utf8");
|
|
31439
32681
|
result.written.push(targetRel);
|
|
31440
32682
|
} else {
|
|
31441
32683
|
result.skipped.push(targetRel);
|
|
@@ -31446,13 +32688,13 @@ function rewritePlanLinks(ctx, skillDir) {
|
|
|
31446
32688
|
if (options.rewriteLinks === false)
|
|
31447
32689
|
return;
|
|
31448
32690
|
for (const relFile of walkMarkdownFiles2(skillDir, root2)) {
|
|
31449
|
-
const filePath =
|
|
31450
|
-
const content3 =
|
|
32691
|
+
const filePath = join22(root2, relFile);
|
|
32692
|
+
const content3 = readFileSync22(filePath, "utf8");
|
|
31451
32693
|
const next = rewriteSharedRefLinks(content3, relFile, plan.skill);
|
|
31452
32694
|
if (next === content3)
|
|
31453
32695
|
continue;
|
|
31454
32696
|
if (!options.dryRun)
|
|
31455
|
-
|
|
32697
|
+
writeFileSync5(filePath, next, "utf8");
|
|
31456
32698
|
result.rewritten.push(relFile);
|
|
31457
32699
|
}
|
|
31458
32700
|
}
|
|
@@ -31463,12 +32705,12 @@ function removeStaleGenerated(ctx, skillDir) {
|
|
|
31463
32705
|
if (plan.refPaths.has(refPath))
|
|
31464
32706
|
continue;
|
|
31465
32707
|
if (!options.dryRun)
|
|
31466
|
-
unlinkSync(
|
|
32708
|
+
unlinkSync(join22(root2, generatedRel));
|
|
31467
32709
|
result.removed.push(generatedRel);
|
|
31468
32710
|
}
|
|
31469
32711
|
}
|
|
31470
32712
|
function syncPlan(ctx) {
|
|
31471
|
-
const skillDir =
|
|
32713
|
+
const skillDir = join22(ctx.root, ctx.plan.skill);
|
|
31472
32714
|
for (const refPath of ctx.plan.refPaths) {
|
|
31473
32715
|
syncGeneratedCopy(ctx, refPath);
|
|
31474
32716
|
}
|
|
@@ -31477,8 +32719,8 @@ function syncPlan(ctx) {
|
|
|
31477
32719
|
}
|
|
31478
32720
|
function syncReferences(options = {}) {
|
|
31479
32721
|
const root2 = options.root ?? process5.cwd();
|
|
31480
|
-
const canonicalDir =
|
|
31481
|
-
if (!
|
|
32722
|
+
const canonicalDir = join22(root2, CANONICAL_REFS_DIR);
|
|
32723
|
+
if (!existsSync23(canonicalDir)) {
|
|
31482
32724
|
throw new Error(`canonical references dir not found: ${CANONICAL_REFS_DIR}`);
|
|
31483
32725
|
}
|
|
31484
32726
|
const result = { written: [], rewritten: [], removed: [], skipped: [] };
|
|
@@ -31523,183 +32765,10 @@ function printSyncResult(result) {
|
|
|
31523
32765
|
}
|
|
31524
32766
|
}
|
|
31525
32767
|
|
|
31526
|
-
// src/register.ts
|
|
31527
|
-
import { existsSync as existsSync25, readFileSync as readFileSync20, writeFileSync as writeFileSync5 } from "node:fs";
|
|
31528
|
-
import { dirname as dirname13, join as join21, relative as relative12 } from "node:path";
|
|
31529
|
-
var REGISTRY_TABLE_ROW_RE2 = /^\|\s*([^|]+)\|\s*\[[^\]]*\]\(([^)]+)\)\s*\|/;
|
|
31530
|
-
var REGISTRY_TABLE_HEADER = "| Topic | Canonical file |";
|
|
31531
|
-
function extractTopic(content3) {
|
|
31532
|
-
const match = content3.match(/\*\*Source of truth for\*\*\s*(.+)/);
|
|
31533
|
-
return match?.[1]?.trim().replace(/\s+$/, "") ?? null;
|
|
31534
|
-
}
|
|
31535
|
-
function toRegistryLink(root2, absPath) {
|
|
31536
|
-
const fromRegistry = join21(root2, REGISTRY_DIR_REL);
|
|
31537
|
-
return normalizeRelPath(relative12(fromRegistry, absPath));
|
|
31538
|
-
}
|
|
31539
|
-
function inferSection(registryLink) {
|
|
31540
|
-
return registryLink.startsWith("customize/") ? "Customizations" : "Documentation";
|
|
31541
|
-
}
|
|
31542
|
-
function ensureCustomizeTopic(topic, registryLink) {
|
|
31543
|
-
if (!registryLink.startsWith("customize/"))
|
|
31544
|
-
return topic;
|
|
31545
|
-
if (topic.startsWith(CUSTOMIZE_PREFIX))
|
|
31546
|
-
return topic;
|
|
31547
|
-
return `${CUSTOMIZE_PREFIX}${topic}`;
|
|
31548
|
-
}
|
|
31549
|
-
function parseRegistryRows(content3) {
|
|
31550
|
-
const rows = [];
|
|
31551
|
-
for (const line of content3.split(`
|
|
31552
|
-
`)) {
|
|
31553
|
-
const match = REGISTRY_TABLE_ROW_RE2.exec(line);
|
|
31554
|
-
if (!(match?.[1] && match[2]))
|
|
31555
|
-
continue;
|
|
31556
|
-
rows.push({ topic: match[1].trim(), link: match[2].trim(), line });
|
|
31557
|
-
}
|
|
31558
|
-
return rows;
|
|
31559
|
-
}
|
|
31560
|
-
function pathFromRegistryLink(root2, link2) {
|
|
31561
|
-
return normalizeRelPath(relative12(root2, join21(root2, REGISTRY_DIR_REL, link2)));
|
|
31562
|
-
}
|
|
31563
|
-
function isOutsideScan(root2, relPath2) {
|
|
31564
|
-
const config = loadConfig(root2);
|
|
31565
|
-
const skillIndex = buildSkillIndex(root2, config.skillOwnership);
|
|
31566
|
-
const scanned = collectScanFiles(config, root2, skillIndex).map((abs) => normalizeRelPath(relative12(root2, abs)));
|
|
31567
|
-
if (scanned.includes(relPath2))
|
|
31568
|
-
return false;
|
|
31569
|
-
return !config.scan.include.some((pattern) => matchesGlobScope(relPath2, pattern));
|
|
31570
|
-
}
|
|
31571
|
-
function defaultRegistryContent() {
|
|
31572
|
-
return `# Registry
|
|
31573
|
-
|
|
31574
|
-
<!-- doc-meta: owner=eng | last-reviewed=${new Date().toISOString().slice(0, 10)} -->
|
|
31575
|
-
|
|
31576
|
-
**Source of truth for** topic routing in this repo. Edit rows here; edit content in canonical files only.
|
|
31577
|
-
|
|
31578
|
-
## Documentation
|
|
31579
|
-
|
|
31580
|
-
${REGISTRY_TABLE_HEADER}
|
|
31581
|
-
|-------|------------------|
|
|
31582
|
-
|
|
31583
|
-
`;
|
|
31584
|
-
}
|
|
31585
|
-
function upsertRow(opts) {
|
|
31586
|
-
const { content: content3, topic, link: link2, section, root: root2 } = opts;
|
|
31587
|
-
const rows = parseRegistryRows(content3);
|
|
31588
|
-
const targetPath = link2;
|
|
31589
|
-
const existingByLink = rows.find((row) => row.link === targetPath);
|
|
31590
|
-
if (existingByLink && existingByLink.topic === topic) {
|
|
31591
|
-
return { content: content3, action: "noop" };
|
|
31592
|
-
}
|
|
31593
|
-
const duplicateTopic = rows.find((row) => row.topic === topic && row.link !== targetPath);
|
|
31594
|
-
if (duplicateTopic) {
|
|
31595
|
-
throw new Error(`topic "${topic}" already registered for ${pathFromRegistryLink(root2, duplicateTopic.link)} — hand-edit registry or use different topic`);
|
|
31596
|
-
}
|
|
31597
|
-
const newLine = `| ${topic} | [${link2.split("/").pop()}](${link2}) |`;
|
|
31598
|
-
if (existingByLink) {
|
|
31599
|
-
const updated = content3.replace(existingByLink.line, newLine);
|
|
31600
|
-
return { content: updated, action: "updated" };
|
|
31601
|
-
}
|
|
31602
|
-
const sectionHeader = `## ${section}`;
|
|
31603
|
-
const sectionIdx = content3.indexOf(sectionHeader);
|
|
31604
|
-
if (sectionIdx >= 0) {
|
|
31605
|
-
const afterSection = content3.indexOf(REGISTRY_TABLE_HEADER, sectionIdx);
|
|
31606
|
-
if (afterSection >= 0) {
|
|
31607
|
-
const insertAt = content3.indexOf(`
|
|
31608
|
-
`, afterSection + REGISTRY_TABLE_HEADER.length);
|
|
31609
|
-
if (insertAt >= 0) {
|
|
31610
|
-
const updated = `${content3.slice(0, insertAt + 1) + newLine}
|
|
31611
|
-
${content3.slice(insertAt + 1)}`;
|
|
31612
|
-
return { content: updated, action: "added" };
|
|
31613
|
-
}
|
|
31614
|
-
}
|
|
31615
|
-
}
|
|
31616
|
-
const appended = `${content3.trimEnd()}
|
|
31617
|
-
|
|
31618
|
-
## ${section}
|
|
31619
|
-
|
|
31620
|
-
${REGISTRY_TABLE_HEADER}
|
|
31621
|
-
|-------|------------------|
|
|
31622
|
-
${newLine}
|
|
31623
|
-
`;
|
|
31624
|
-
return { content: appended, action: "added" };
|
|
31625
|
-
}
|
|
31626
|
-
function printRegisterResult(options, result, relPath2) {
|
|
31627
|
-
if (options.json) {
|
|
31628
|
-
console.log(JSON.stringify(result, null, 2));
|
|
31629
|
-
} else if (options.dryRun) {
|
|
31630
|
-
console.log(`dry-run: would ${result.action} registry row for ${relPath2} → ${result.topic}`);
|
|
31631
|
-
} else if (result.action === "noop") {
|
|
31632
|
-
console.log(`register: ${relPath2} already registered (${result.topic})`);
|
|
31633
|
-
} else {
|
|
31634
|
-
console.log(`register: ${result.action} ${relPath2} → ${result.topic}`);
|
|
31635
|
-
}
|
|
31636
|
-
}
|
|
31637
|
-
function resolveRegistrationTopic(input) {
|
|
31638
|
-
const { options, root: root2, relPath: relPath2, absPath } = input;
|
|
31639
|
-
const content3 = readFileSync20(absPath, "utf8");
|
|
31640
|
-
let topic = options.topic ?? extractTopic(content3);
|
|
31641
|
-
if (!topic) {
|
|
31642
|
-
throw new Error(`No **Source of truth for** banner in ${relPath2} — add banner or pass --topic`);
|
|
31643
|
-
}
|
|
31644
|
-
const registryLink = toRegistryLink(root2, absPath);
|
|
31645
|
-
topic = ensureCustomizeTopic(topic, registryLink);
|
|
31646
|
-
return { topic, registryLink, section: inferSection(registryLink) };
|
|
31647
|
-
}
|
|
31648
|
-
function loadRegistryContent(root2) {
|
|
31649
|
-
const registryAbs = join21(root2, REGISTRY_REL_PATH);
|
|
31650
|
-
if (!(existsSync25(registryAbs) || existsSync25(join21(root2, ".skeleton/config.yaml")))) {
|
|
31651
|
-
throw new Error("Missing .skeleton/config.yaml — run skeleton init first");
|
|
31652
|
-
}
|
|
31653
|
-
return existsSync25(registryAbs) ? readFileSync20(registryAbs, "utf8") : defaultRegistryContent();
|
|
31654
|
-
}
|
|
31655
|
-
function registerPath(options) {
|
|
31656
|
-
const root2 = options.root ?? findRepoRoot();
|
|
31657
|
-
const relPath2 = normalizeRelPath(options.path);
|
|
31658
|
-
const absPath = join21(root2, relPath2);
|
|
31659
|
-
if (!existsSync25(absPath)) {
|
|
31660
|
-
throw new Error(`File not found: ${relPath2}`);
|
|
31661
|
-
}
|
|
31662
|
-
const { topic, registryLink, section } = resolveRegistrationTopic({
|
|
31663
|
-
options,
|
|
31664
|
-
root: root2,
|
|
31665
|
-
relPath: relPath2,
|
|
31666
|
-
absPath
|
|
31667
|
-
});
|
|
31668
|
-
let registryContent = loadRegistryContent(root2);
|
|
31669
|
-
const { content: updated, action } = upsertRow({
|
|
31670
|
-
content: registryContent,
|
|
31671
|
-
topic,
|
|
31672
|
-
link: registryLink,
|
|
31673
|
-
section,
|
|
31674
|
-
root: root2
|
|
31675
|
-
});
|
|
31676
|
-
registryContent = updated;
|
|
31677
|
-
const result = {
|
|
31678
|
-
topic,
|
|
31679
|
-
registryLink,
|
|
31680
|
-
section,
|
|
31681
|
-
action,
|
|
31682
|
-
warnOutsideScan: isOutsideScan(root2, relPath2)
|
|
31683
|
-
};
|
|
31684
|
-
const registryAbs = join21(root2, REGISTRY_REL_PATH);
|
|
31685
|
-
if (!options.dryRun && action !== "noop") {
|
|
31686
|
-
const dir = dirname13(registryAbs);
|
|
31687
|
-
if (!existsSync25(dir)) {
|
|
31688
|
-
throw new Error(`Missing ${REGISTRY_DIR_REL}/ directory`);
|
|
31689
|
-
}
|
|
31690
|
-
writeFileSync5(registryAbs, registryContent, "utf8");
|
|
31691
|
-
}
|
|
31692
|
-
if (result.warnOutsideScan) {
|
|
31693
|
-
console.error(`warning: ${relPath2} is outside scan.include — register succeeded but audit will not scan it`);
|
|
31694
|
-
}
|
|
31695
|
-
printRegisterResult(options, result, relPath2);
|
|
31696
|
-
return result;
|
|
31697
|
-
}
|
|
31698
|
-
|
|
31699
32768
|
// src/validate/changed.ts
|
|
31700
32769
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
31701
|
-
import { existsSync as
|
|
31702
|
-
import { basename as basename5, extname as extname2, join as
|
|
32770
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
|
|
32771
|
+
import { basename as basename5, extname as extname2, join as join23 } from "node:path";
|
|
31703
32772
|
|
|
31704
32773
|
// src/validate/git-diff.ts
|
|
31705
32774
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -31792,9 +32861,9 @@ function parseJsonContent(content3) {
|
|
|
31792
32861
|
}
|
|
31793
32862
|
}
|
|
31794
32863
|
function validateJson(relPath2, root2) {
|
|
31795
|
-
const abs =
|
|
32864
|
+
const abs = join23(root2, relPath2);
|
|
31796
32865
|
try {
|
|
31797
|
-
parseJsonContent(
|
|
32866
|
+
parseJsonContent(readFileSync23(abs, "utf8"));
|
|
31798
32867
|
return 0;
|
|
31799
32868
|
} catch (error) {
|
|
31800
32869
|
console.error(`validate changed: invalid JSON in ${relPath2}: ${error}`);
|
|
@@ -31802,9 +32871,9 @@ function validateJson(relPath2, root2) {
|
|
|
31802
32871
|
}
|
|
31803
32872
|
}
|
|
31804
32873
|
function validatePolicy(relPath2, root2) {
|
|
31805
|
-
const abs =
|
|
32874
|
+
const abs = join23(root2, relPath2);
|
|
31806
32875
|
try {
|
|
31807
|
-
loadPolicyFile(abs,
|
|
32876
|
+
loadPolicyFile(abs, readFileSync23(abs, "utf8"));
|
|
31808
32877
|
return 0;
|
|
31809
32878
|
} catch (error) {
|
|
31810
32879
|
console.error(`validate changed: invalid policy ${relPath2}: ${error}`);
|
|
@@ -31812,7 +32881,7 @@ function validatePolicy(relPath2, root2) {
|
|
|
31812
32881
|
}
|
|
31813
32882
|
}
|
|
31814
32883
|
function validateShell(relPath2, root2) {
|
|
31815
|
-
const abs =
|
|
32884
|
+
const abs = join23(root2, relPath2);
|
|
31816
32885
|
const shellcheck = spawnSync5("shellcheck", [abs], { encoding: "utf8" });
|
|
31817
32886
|
if (shellcheck.status === 0)
|
|
31818
32887
|
return 0;
|
|
@@ -31833,11 +32902,11 @@ function resolvePaths(options) {
|
|
|
31833
32902
|
});
|
|
31834
32903
|
}
|
|
31835
32904
|
function packageManagerFromPackageJson(root2) {
|
|
31836
|
-
const pkgPath =
|
|
31837
|
-
if (!
|
|
32905
|
+
const pkgPath = join23(root2, "package.json");
|
|
32906
|
+
if (!existsSync24(pkgPath))
|
|
31838
32907
|
return null;
|
|
31839
32908
|
try {
|
|
31840
|
-
const pkg = JSON.parse(
|
|
32909
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf8"));
|
|
31841
32910
|
const raw = pkg.packageManager?.split("@")[0];
|
|
31842
32911
|
if (raw === "bun" || raw === "npm" || raw === "pnpm" || raw === "yarn")
|
|
31843
32912
|
return raw;
|
|
@@ -31845,13 +32914,13 @@ function packageManagerFromPackageJson(root2) {
|
|
|
31845
32914
|
return null;
|
|
31846
32915
|
}
|
|
31847
32916
|
function packageManagerFromLockfiles(root2) {
|
|
31848
|
-
if (
|
|
32917
|
+
if (existsSync24(join23(root2, "bun.lock")) || existsSync24(join23(root2, "bun.lockb")))
|
|
31849
32918
|
return "bun";
|
|
31850
|
-
if (
|
|
32919
|
+
if (existsSync24(join23(root2, "pnpm-lock.yaml")))
|
|
31851
32920
|
return "pnpm";
|
|
31852
|
-
if (
|
|
32921
|
+
if (existsSync24(join23(root2, "yarn.lock")))
|
|
31853
32922
|
return "yarn";
|
|
31854
|
-
if (
|
|
32923
|
+
if (existsSync24(join23(root2, "package-lock.json")))
|
|
31855
32924
|
return "npm";
|
|
31856
32925
|
return null;
|
|
31857
32926
|
}
|
|
@@ -31877,8 +32946,8 @@ function emptyBuckets() {
|
|
|
31877
32946
|
function classifySinglePath(input) {
|
|
31878
32947
|
const { relPath: relPath2, ctx, state, bucketCtx } = input;
|
|
31879
32948
|
const normalized = normalizeRelPath(relPath2);
|
|
31880
|
-
const abs =
|
|
31881
|
-
if (!
|
|
32949
|
+
const abs = join23(ctx.root, normalized);
|
|
32950
|
+
if (!existsSync24(abs)) {
|
|
31882
32951
|
state.missing++;
|
|
31883
32952
|
console.error(`validate changed: path not found: ${relPath2}`);
|
|
31884
32953
|
return;
|
|
@@ -32112,31 +33181,16 @@ function usage() {
|
|
|
32112
33181
|
Commands:
|
|
32113
33182
|
init [--force-hooks] [--skills] [--no-skills] [skills add flags…]
|
|
32114
33183
|
audit docs|self|skills [--strict] [--json] [--paths=a,b] [--only=rule]
|
|
32115
|
-
[--fix[=doc-meta|anchors]] [--dry-run]
|
|
33184
|
+
[--fix[=doc-meta|anchors|ssot]] [--dry-run]
|
|
32116
33185
|
build-plugin [path] [--check]
|
|
32117
33186
|
validate changed [paths…] [--staged] [--base <ref>]
|
|
32118
|
-
|
|
33187
|
+
catalog [--check] write or check .skeleton/catalog.md (gitignored)
|
|
32119
33188
|
customize resolve <slug> [--json]
|
|
32120
33189
|
hook customize (reads a host hook payload on stdin)
|
|
32121
33190
|
references sync [--dry-run] [--no-rewrite-links]
|
|
32122
|
-
references check [--json] [--strict]
|
|
32123
|
-
|
|
32124
|
-
|
|
32125
|
-
let path2 = null;
|
|
32126
|
-
let topic;
|
|
32127
|
-
let dryRun = false;
|
|
32128
|
-
let json = false;
|
|
32129
|
-
for (const arg of argv) {
|
|
32130
|
-
if (arg === "--dry-run")
|
|
32131
|
-
dryRun = true;
|
|
32132
|
-
else if (arg === "--json")
|
|
32133
|
-
json = true;
|
|
32134
|
-
else if (arg.startsWith("--topic="))
|
|
32135
|
-
topic = arg.slice("--topic=".length);
|
|
32136
|
-
else if (!(arg.startsWith("-") || path2))
|
|
32137
|
-
path2 = arg;
|
|
32138
|
-
}
|
|
32139
|
-
return { path: path2, topic, dryRun, json };
|
|
33191
|
+
references check [--json] [--strict]
|
|
33192
|
+
|
|
33193
|
+
Note: \`register\` was removed — add a source-of-truth marker to the file and run \`skeleton catalog\`.`);
|
|
32140
33194
|
}
|
|
32141
33195
|
function parseValidateChangedArgs(rest) {
|
|
32142
33196
|
const paths = [];
|
|
@@ -32180,19 +33234,12 @@ async function handleValidateChanged(argv) {
|
|
|
32180
33234
|
const { paths, staged, base } = parseValidateChangedArgs(argv);
|
|
32181
33235
|
return runValidateChanged({ paths, staged, base });
|
|
32182
33236
|
}
|
|
32183
|
-
function handleRegister(
|
|
32184
|
-
|
|
32185
|
-
|
|
32186
|
-
|
|
32187
|
-
|
|
32188
|
-
}
|
|
32189
|
-
registerPath({
|
|
32190
|
-
path: opts.path,
|
|
32191
|
-
topic: opts.topic,
|
|
32192
|
-
dryRun: opts.dryRun,
|
|
32193
|
-
json: opts.json
|
|
32194
|
-
});
|
|
32195
|
-
return 0;
|
|
33237
|
+
function handleRegister() {
|
|
33238
|
+
console.error("register: removed — add `<!-- source-of-truth: … -->` (or visible `source-of-truth:`) to the file, then run `skeleton catalog`.");
|
|
33239
|
+
return 1;
|
|
33240
|
+
}
|
|
33241
|
+
function handleCatalog(argv) {
|
|
33242
|
+
return runCatalogCli({ check: argv.includes("--check") });
|
|
32196
33243
|
}
|
|
32197
33244
|
function handleCustomizeResolve(argv) {
|
|
32198
33245
|
const slug2 = argv[0];
|
|
@@ -32214,7 +33261,7 @@ function handleHook(argv) {
|
|
|
32214
33261
|
usage();
|
|
32215
33262
|
return 1;
|
|
32216
33263
|
}
|
|
32217
|
-
process7.stdout.write(runCustomizeHook(
|
|
33264
|
+
process7.stdout.write(runCustomizeHook(readFileSync24(0, "utf8")));
|
|
32218
33265
|
return 0;
|
|
32219
33266
|
}
|
|
32220
33267
|
function handleInit(argv) {
|
|
@@ -32250,7 +33297,9 @@ async function dispatchCommand(argv) {
|
|
|
32250
33297
|
case "validate":
|
|
32251
33298
|
return rest[0] === "changed" ? handleValidateChanged(rest.slice(1)) : null;
|
|
32252
33299
|
case "register":
|
|
32253
|
-
return handleRegister(
|
|
33300
|
+
return handleRegister();
|
|
33301
|
+
case "catalog":
|
|
33302
|
+
return handleCatalog(rest);
|
|
32254
33303
|
case "customize":
|
|
32255
33304
|
return rest[0] === "resolve" ? handleCustomizeResolve(rest.slice(1)) : null;
|
|
32256
33305
|
case "hook":
|