@csark0812/skeleton 1.5.7 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/cli.js +1749 -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,107 @@ 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 SSOT_VISIBLE_LINE_RE = /^\s*source-of-truth:\s*(.+?)\s*$/gim;
|
|
18450
|
+
var LEGACY_BANNER_LINE_RE = /^\s*\*\*Source of truth for\*\*\s*(.+?)\s*$/gim;
|
|
18451
|
+
function cleanSummary(raw) {
|
|
18452
|
+
return raw.replace(/\s+/g, " ").trim().replace(/\.$/, "").trim();
|
|
18453
|
+
}
|
|
18454
|
+
function stripCode(content) {
|
|
18455
|
+
return content.replace(/```[\s\S]*?```/g, `
|
|
18456
|
+
`).replace(/`[^`\n]+`/g, " ");
|
|
18457
|
+
}
|
|
18458
|
+
function collectMatches(re, content) {
|
|
18459
|
+
const out = [];
|
|
18460
|
+
re.lastIndex = 0;
|
|
18461
|
+
let match = re.exec(content);
|
|
18462
|
+
while (match) {
|
|
18463
|
+
const summary = cleanSummary(match[1] ?? "");
|
|
18464
|
+
if (summary)
|
|
18465
|
+
out.push(summary);
|
|
18466
|
+
match = re.exec(content);
|
|
17673
18467
|
}
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17678
|
-
|
|
17679
|
-
|
|
17680
|
-
|
|
18468
|
+
return out;
|
|
18469
|
+
}
|
|
18470
|
+
function parseSsot(content) {
|
|
18471
|
+
const prose = stripCode(content);
|
|
18472
|
+
const comments = collectMatches(SSOT_COMMENT_RE, prose);
|
|
18473
|
+
const visibles = collectMatches(SSOT_VISIBLE_LINE_RE, prose);
|
|
18474
|
+
const legacies = collectMatches(LEGACY_BANNER_LINE_RE, prose);
|
|
18475
|
+
const forms = [];
|
|
18476
|
+
if (comments.length)
|
|
18477
|
+
forms.push("comment");
|
|
18478
|
+
if (visibles.length)
|
|
18479
|
+
forms.push("visible");
|
|
18480
|
+
if (legacies.length)
|
|
18481
|
+
forms.push("legacy");
|
|
18482
|
+
if (forms.length === 0)
|
|
18483
|
+
return { status: "none" };
|
|
18484
|
+
if (forms.length > 1)
|
|
18485
|
+
return { status: "dual", forms };
|
|
18486
|
+
if (comments.length > 1 || visibles.length > 1 || legacies.length > 1) {
|
|
18487
|
+
return { status: "malformed", detail: "multiple source-of-truth markers of the same form" };
|
|
18488
|
+
}
|
|
18489
|
+
if (comments.length === 1) {
|
|
18490
|
+
const summary2 = comments[0];
|
|
18491
|
+
if (!summary2)
|
|
18492
|
+
return { status: "malformed", detail: "empty source-of-truth comment" };
|
|
18493
|
+
return { status: "ok", entry: { summary: summary2, form: "comment" } };
|
|
18494
|
+
}
|
|
18495
|
+
if (visibles.length === 1) {
|
|
18496
|
+
const summary2 = visibles[0];
|
|
18497
|
+
if (!summary2)
|
|
18498
|
+
return { status: "malformed", detail: "empty source-of-truth line" };
|
|
18499
|
+
return { status: "ok", entry: { summary: summary2, form: "visible" } };
|
|
18500
|
+
}
|
|
18501
|
+
const summary = legacies[0];
|
|
18502
|
+
if (!summary)
|
|
18503
|
+
return { status: "malformed", detail: "empty legacy Source of truth banner" };
|
|
18504
|
+
return { status: "ok", entry: { summary, form: "legacy" } };
|
|
18505
|
+
}
|
|
18506
|
+
function rewriteLegacySsotToComment(content) {
|
|
18507
|
+
const parsed = parseSsot(content);
|
|
18508
|
+
if (parsed.status !== "ok" || parsed.entry.form !== "legacy")
|
|
18509
|
+
return null;
|
|
18510
|
+
const comment = `<!-- source-of-truth: ${parsed.entry.summary} -->`;
|
|
18511
|
+
const next = content.replace(LEGACY_BANNER_LINE_RE, comment);
|
|
18512
|
+
return next === content ? null : next;
|
|
18513
|
+
}
|
|
18514
|
+
|
|
18515
|
+
// src/audit/core/ssot-collect.ts
|
|
18516
|
+
function collectSsotEntries(files, root) {
|
|
18517
|
+
const entries = [];
|
|
18518
|
+
const errors2 = [];
|
|
18519
|
+
for (const abs of files) {
|
|
18520
|
+
const rel = normalizeRelPath(relative5(root, abs));
|
|
18521
|
+
if (!(rel.endsWith(".md") || rel.endsWith(".mdc")))
|
|
17681
18522
|
continue;
|
|
17682
|
-
const
|
|
17683
|
-
|
|
18523
|
+
const content = readFileSync6(abs, "utf8");
|
|
18524
|
+
const parsed = parseSsot(content);
|
|
18525
|
+
if (parsed.status === "none")
|
|
18526
|
+
continue;
|
|
18527
|
+
if (parsed.status === "dual") {
|
|
18528
|
+
errors2.push({
|
|
18529
|
+
path: rel,
|
|
18530
|
+
kind: "dual",
|
|
18531
|
+
detail: `multiple source-of-truth forms: ${parsed.forms.join(", ")}`,
|
|
18532
|
+
forms: parsed.forms
|
|
18533
|
+
});
|
|
17684
18534
|
continue;
|
|
17685
|
-
|
|
17686
|
-
|
|
18535
|
+
}
|
|
18536
|
+
if (parsed.status === "malformed") {
|
|
18537
|
+
errors2.push({ path: rel, kind: "malformed", detail: parsed.detail });
|
|
18538
|
+
continue;
|
|
18539
|
+
}
|
|
18540
|
+
entries.push({ path: rel, summary: parsed.entry.summary, form: parsed.entry.form });
|
|
17687
18541
|
}
|
|
17688
|
-
|
|
18542
|
+
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
18543
|
+
return { entries, errors: errors2 };
|
|
17689
18544
|
}
|
|
17690
18545
|
|
|
17691
18546
|
// src/audit/core/context.ts
|
|
@@ -17701,11 +18556,12 @@ function createContext(options = {}) {
|
|
|
17701
18556
|
files = includeExplicitMarkdownPaths(files, options.paths, root);
|
|
17702
18557
|
files = filterToPaths(files, options.paths, root);
|
|
17703
18558
|
}
|
|
17704
|
-
const
|
|
18559
|
+
const ssot = collectSsotEntries(files, root);
|
|
18560
|
+
const ssotPaths = ssot.entries.map((e) => e.path);
|
|
17705
18561
|
const allDocMetaPaths = collectDocMetaPaths({
|
|
17706
18562
|
config,
|
|
17707
18563
|
root,
|
|
17708
|
-
registryPaths:
|
|
18564
|
+
registryPaths: ssotPaths,
|
|
17709
18565
|
skillIndex
|
|
17710
18566
|
});
|
|
17711
18567
|
return {
|
|
@@ -17713,9 +18569,10 @@ function createContext(options = {}) {
|
|
|
17713
18569
|
config,
|
|
17714
18570
|
files,
|
|
17715
18571
|
docMetaPaths: options.paths && options.paths.length > 0 ? filterDocMetaPaths(allDocMetaPaths, options.paths, skillIndex) : allDocMetaPaths,
|
|
17716
|
-
|
|
17717
|
-
|
|
17718
|
-
|
|
18572
|
+
ssotEntries: ssot.entries,
|
|
18573
|
+
ssotErrors: ssot.errors,
|
|
18574
|
+
registryPaths: [],
|
|
18575
|
+
registryHasTableHeader: false,
|
|
17719
18576
|
skillIndex,
|
|
17720
18577
|
lockedSkillSlugs: new Set(skillIndex.foreignSlugs),
|
|
17721
18578
|
policies: options.policies ?? []
|
|
@@ -17723,12 +18580,12 @@ function createContext(options = {}) {
|
|
|
17723
18580
|
}
|
|
17724
18581
|
|
|
17725
18582
|
// src/audit/core/fix.ts
|
|
17726
|
-
import { existsSync as
|
|
17727
|
-
import { dirname as dirname6, resolve as
|
|
18583
|
+
import { existsSync as existsSync10, realpathSync as realpathSync5, writeFileSync } from "node:fs";
|
|
18584
|
+
import { dirname as dirname6, resolve as resolve5, sep as sep3 } from "node:path";
|
|
17728
18585
|
|
|
17729
18586
|
// src/audit/fix/anchors.ts
|
|
17730
|
-
import { existsSync as
|
|
17731
|
-
import { dirname as dirname5, resolve as
|
|
18587
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
|
|
18588
|
+
import { dirname as dirname5, resolve as resolve4 } from "node:path";
|
|
17732
18589
|
|
|
17733
18590
|
// node_modules/github-slugger/regex.js
|
|
17734
18591
|
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 +21588,10 @@ function resolveAll(constructs2, events, context) {
|
|
|
20731
21588
|
const called = [];
|
|
20732
21589
|
let index = -1;
|
|
20733
21590
|
while (++index < constructs2.length) {
|
|
20734
|
-
const
|
|
20735
|
-
if (
|
|
20736
|
-
events =
|
|
20737
|
-
called.push(
|
|
21591
|
+
const resolve4 = constructs2[index].resolveAll;
|
|
21592
|
+
if (resolve4 && !called.includes(resolve4)) {
|
|
21593
|
+
events = resolve4(events, context);
|
|
21594
|
+
called.push(resolve4);
|
|
20738
21595
|
}
|
|
20739
21596
|
}
|
|
20740
21597
|
return events;
|
|
@@ -21979,9 +22836,9 @@ function factoryTitle(effects, ok2, nok, type, markerType, stringType) {
|
|
|
21979
22836
|
return atBreak(code);
|
|
21980
22837
|
}
|
|
21981
22838
|
effects.consume(code);
|
|
21982
|
-
return code === codes.backslash ?
|
|
22839
|
+
return code === codes.backslash ? escape2 : inside;
|
|
21983
22840
|
}
|
|
21984
|
-
function
|
|
22841
|
+
function escape2(code) {
|
|
21985
22842
|
if (code === marker || code === codes.backslash) {
|
|
21986
22843
|
effects.consume(code);
|
|
21987
22844
|
return inside;
|
|
@@ -24042,7 +24899,7 @@ function serializeChunks(chunks, expandTabs) {
|
|
|
24042
24899
|
}
|
|
24043
24900
|
|
|
24044
24901
|
// node_modules/micromark/dev/lib/parse.js
|
|
24045
|
-
function
|
|
24902
|
+
function parse2(options) {
|
|
24046
24903
|
const settings = options || {};
|
|
24047
24904
|
const constructs2 = combineExtensions([exports_constructs, ...settings.extensions || []]);
|
|
24048
24905
|
const parser2 = {
|
|
@@ -24201,7 +25058,7 @@ function fromMarkdown(value, encoding, options) {
|
|
|
24201
25058
|
options = encoding;
|
|
24202
25059
|
encoding = undefined;
|
|
24203
25060
|
}
|
|
24204
|
-
return compiler(options)(postprocess(
|
|
25061
|
+
return compiler(options)(postprocess(parse2(options).document().write(preprocess()(value, encoding, true))));
|
|
24205
25062
|
}
|
|
24206
25063
|
function compiler(options) {
|
|
24207
25064
|
const config = {
|
|
@@ -25908,7 +26765,7 @@ var handle = {
|
|
|
25908
26765
|
};
|
|
25909
26766
|
|
|
25910
26767
|
// node_modules/mdast-util-to-markdown/lib/join.js
|
|
25911
|
-
var
|
|
26768
|
+
var join7 = [joinDefaults];
|
|
25912
26769
|
function joinDefaults(left, right, parent, state) {
|
|
25913
26770
|
if (right.type === "code" && formatCodeAsIndented(right, state) && (left.type === "list" || left.type === right.type && formatCodeAsIndented(left, state))) {
|
|
25914
26771
|
return false;
|
|
@@ -26291,7 +27148,7 @@ function toMarkdown(tree, options) {
|
|
|
26291
27148
|
handle: undefined,
|
|
26292
27149
|
indentLines,
|
|
26293
27150
|
indexStack: [],
|
|
26294
|
-
join: [...
|
|
27151
|
+
join: [...join7],
|
|
26295
27152
|
options: {},
|
|
26296
27153
|
safe: safeBound,
|
|
26297
27154
|
stack: [],
|
|
@@ -26784,7 +27641,7 @@ class Processor extends CallableInstance {
|
|
|
26784
27641
|
assertParser("process", this.parser || this.Parser);
|
|
26785
27642
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
26786
27643
|
return done ? executor(undefined, done) : new Promise(executor);
|
|
26787
|
-
function executor(
|
|
27644
|
+
function executor(resolve4, reject) {
|
|
26788
27645
|
const realFile = vfile(file);
|
|
26789
27646
|
const parseTree = self.parse(realFile);
|
|
26790
27647
|
self.run(parseTree, realFile, function(error, tree, file2) {
|
|
@@ -26803,8 +27660,8 @@ class Processor extends CallableInstance {
|
|
|
26803
27660
|
function realDone(error, file2) {
|
|
26804
27661
|
if (error || !file2) {
|
|
26805
27662
|
reject(error);
|
|
26806
|
-
} else if (
|
|
26807
|
-
|
|
27663
|
+
} else if (resolve4) {
|
|
27664
|
+
resolve4(file2);
|
|
26808
27665
|
} else {
|
|
26809
27666
|
ok(done, "`done` is defined if `resolve` is not");
|
|
26810
27667
|
done(undefined, file2);
|
|
@@ -26837,7 +27694,7 @@ class Processor extends CallableInstance {
|
|
|
26837
27694
|
file = undefined;
|
|
26838
27695
|
}
|
|
26839
27696
|
return done ? executor(undefined, done) : new Promise(executor);
|
|
26840
|
-
function executor(
|
|
27697
|
+
function executor(resolve4, reject) {
|
|
26841
27698
|
ok(typeof file !== "function", "`file` can’t be a `done` anymore, we checked");
|
|
26842
27699
|
const realFile = vfile(file);
|
|
26843
27700
|
transformers.run(tree, realFile, realDone);
|
|
@@ -26845,8 +27702,8 @@ class Processor extends CallableInstance {
|
|
|
26845
27702
|
const resultingTree = outputTree || tree;
|
|
26846
27703
|
if (error) {
|
|
26847
27704
|
reject(error);
|
|
26848
|
-
} else if (
|
|
26849
|
-
|
|
27705
|
+
} else if (resolve4) {
|
|
27706
|
+
resolve4(resultingTree);
|
|
26850
27707
|
} else {
|
|
26851
27708
|
ok(done, "`done` is defined if `resolve` is not");
|
|
26852
27709
|
done(undefined, resultingTree, file2);
|
|
@@ -29289,7 +30146,7 @@ function resolveLink(sourceFile, target) {
|
|
|
29289
30146
|
const withoutAnchor = target.split("#")[0]?.split("?")[0] ?? "";
|
|
29290
30147
|
if (!withoutAnchor)
|
|
29291
30148
|
return sourceFile;
|
|
29292
|
-
return
|
|
30149
|
+
return resolve4(dirname5(sourceFile), withoutAnchor);
|
|
29293
30150
|
}
|
|
29294
30151
|
function replaceAnchorInTarget(target, oldAnchor, newAnchor) {
|
|
29295
30152
|
const hashIndex = target.indexOf("#");
|
|
@@ -29313,7 +30170,7 @@ function anchorTargetReplacement(filePath, target) {
|
|
|
29313
30170
|
if (!anchor)
|
|
29314
30171
|
return null;
|
|
29315
30172
|
const resolved = resolveLink(filePath, target);
|
|
29316
|
-
if (!
|
|
30173
|
+
if (!existsSync8(resolved))
|
|
29317
30174
|
return null;
|
|
29318
30175
|
const targetContent = readFileSync7(resolved, "utf8");
|
|
29319
30176
|
const slugs = extractHeadingSlugs(targetContent, resolved);
|
|
@@ -29397,8 +30254,8 @@ function collectAnchorFixes(ctx) {
|
|
|
29397
30254
|
}
|
|
29398
30255
|
|
|
29399
30256
|
// src/audit/fix/doc-meta.ts
|
|
29400
|
-
import { existsSync as
|
|
29401
|
-
import { join as
|
|
30257
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "node:fs";
|
|
30258
|
+
import { join as join8 } from "node:path";
|
|
29402
30259
|
|
|
29403
30260
|
// src/audit/core/git-meta.ts
|
|
29404
30261
|
import { spawnSync } from "node:child_process";
|
|
@@ -29427,8 +30284,8 @@ function bumpDocMetaLastReviewed(content3, gitDate) {
|
|
|
29427
30284
|
return replaceDocMetaLastReviewed(content3, gitDate);
|
|
29428
30285
|
}
|
|
29429
30286
|
function docMetaFixForPath(ctx, relPath2) {
|
|
29430
|
-
const abs =
|
|
29431
|
-
if (!
|
|
30287
|
+
const abs = join8(ctx.root, relPath2);
|
|
30288
|
+
if (!existsSync9(abs))
|
|
29432
30289
|
return null;
|
|
29433
30290
|
const content3 = readFileSync8(abs, "utf8");
|
|
29434
30291
|
if (!DOC_META_RE.test(content3))
|
|
@@ -29461,34 +30318,74 @@ function collectDocMetaFixes(ctx) {
|
|
|
29461
30318
|
return edits;
|
|
29462
30319
|
}
|
|
29463
30320
|
|
|
30321
|
+
// src/audit/fix/ssot.ts
|
|
30322
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
30323
|
+
import { join as join9 } from "node:path";
|
|
30324
|
+
function collectSsotFixes(ctx) {
|
|
30325
|
+
const edits = [];
|
|
30326
|
+
for (const entry of ctx.ssotEntries) {
|
|
30327
|
+
if (entry.form !== "legacy")
|
|
30328
|
+
continue;
|
|
30329
|
+
const abs = join9(ctx.root, entry.path);
|
|
30330
|
+
const content3 = readFileSync9(abs, "utf8");
|
|
30331
|
+
const next = rewriteLegacySsotToComment(content3);
|
|
30332
|
+
if (!next)
|
|
30333
|
+
continue;
|
|
30334
|
+
edits.push({
|
|
30335
|
+
file: entry.path,
|
|
30336
|
+
description: "rewrite legacy **Source of truth for** banner to <!-- source-of-truth: … -->",
|
|
30337
|
+
content: next
|
|
30338
|
+
});
|
|
30339
|
+
}
|
|
30340
|
+
return edits;
|
|
30341
|
+
}
|
|
30342
|
+
|
|
29464
30343
|
// src/audit/core/fix.ts
|
|
29465
30344
|
function collectFixes(ctx, kinds) {
|
|
29466
30345
|
const meta = kinds.has("doc-meta") ? collectDocMetaFixes(ctx) : [];
|
|
29467
30346
|
const anchors = kinds.has("anchors") ? collectAnchorFixes(ctx) : [];
|
|
29468
|
-
|
|
30347
|
+
const ssot = kinds.has("ssot") ? collectSsotFixes(ctx) : [];
|
|
30348
|
+
return coalesceFixEdits(meta, anchors, ssot);
|
|
29469
30349
|
}
|
|
29470
|
-
function coalesceFixEdits(metaEdits, anchorEdits) {
|
|
30350
|
+
function coalesceFixEdits(metaEdits, anchorEdits, ssotEdits = []) {
|
|
29471
30351
|
const metaByFile = new Map(metaEdits.map((e) => [e.file, e]));
|
|
29472
30352
|
const anchorByFile = new Map(anchorEdits.map((e) => [e.file, e]));
|
|
29473
|
-
const
|
|
30353
|
+
const ssotByFile = new Map(ssotEdits.map((e) => [e.file, e]));
|
|
30354
|
+
const files = new Set([...metaByFile.keys(), ...anchorByFile.keys(), ...ssotByFile.keys()]);
|
|
29474
30355
|
const out = [];
|
|
29475
30356
|
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
|
-
}
|
|
30357
|
+
out.push(coalesceOneFile({
|
|
30358
|
+
file,
|
|
30359
|
+
meta: metaByFile.get(file),
|
|
30360
|
+
anchors: anchorByFile.get(file),
|
|
30361
|
+
ssot: ssotByFile.get(file)
|
|
30362
|
+
}));
|
|
29489
30363
|
}
|
|
29490
30364
|
return out;
|
|
29491
30365
|
}
|
|
30366
|
+
function coalesceOneFile(input) {
|
|
30367
|
+
const { file, meta, anchors, ssot } = input;
|
|
30368
|
+
const descriptions = [];
|
|
30369
|
+
let content3 = anchors?.content ?? meta?.content ?? ssot?.content ?? "";
|
|
30370
|
+
if (meta)
|
|
30371
|
+
descriptions.push(meta.description);
|
|
30372
|
+
if (anchors) {
|
|
30373
|
+
descriptions.push(anchors.description);
|
|
30374
|
+
content3 = anchors.content;
|
|
30375
|
+
if (meta)
|
|
30376
|
+
content3 = overlayLastReviewed(content3, meta.content);
|
|
30377
|
+
} else if (meta) {
|
|
30378
|
+
content3 = meta.content;
|
|
30379
|
+
}
|
|
30380
|
+
if (ssot) {
|
|
30381
|
+
descriptions.push(ssot.description);
|
|
30382
|
+
content3 = rewriteSsotOnto(content3, ssot.content);
|
|
30383
|
+
}
|
|
30384
|
+
return { file, description: descriptions.join("; "), content: content3 };
|
|
30385
|
+
}
|
|
30386
|
+
function rewriteSsotOnto(base, ssotContent) {
|
|
30387
|
+
return ssotContent || base;
|
|
30388
|
+
}
|
|
29492
30389
|
function overlayLastReviewed(targetContent, metaContent) {
|
|
29493
30390
|
const date = docMetaLastReviewed(metaContent);
|
|
29494
30391
|
if (!date)
|
|
@@ -29502,9 +30399,9 @@ function shouldStopPathWalk(rootResolved, parent, cursor) {
|
|
|
29502
30399
|
return parent === cursor || !underRoot(rootResolved, parent) && parent !== rootResolved;
|
|
29503
30400
|
}
|
|
29504
30401
|
function resolveExistingRealPath(rootResolved, abs, relFile) {
|
|
29505
|
-
const rootReal =
|
|
30402
|
+
const rootReal = existsSync10(rootResolved) ? realpathSync5(rootResolved) : rootResolved;
|
|
29506
30403
|
let cursor = abs;
|
|
29507
|
-
while (!
|
|
30404
|
+
while (!existsSync10(cursor)) {
|
|
29508
30405
|
const parent = dirname6(cursor);
|
|
29509
30406
|
if (shouldStopPathWalk(rootResolved, parent, cursor))
|
|
29510
30407
|
return abs;
|
|
@@ -29517,8 +30414,8 @@ function resolveExistingRealPath(rootResolved, abs, relFile) {
|
|
|
29517
30414
|
return abs;
|
|
29518
30415
|
}
|
|
29519
30416
|
function resolveWritePath(root2, relFile) {
|
|
29520
|
-
const rootResolved =
|
|
29521
|
-
const abs =
|
|
30417
|
+
const rootResolved = resolve5(root2);
|
|
30418
|
+
const abs = resolve5(rootResolved, relFile);
|
|
29522
30419
|
if (!underRoot(rootResolved, abs)) {
|
|
29523
30420
|
throw new Error(`Refusing autofix outside repo root: ${relFile}`);
|
|
29524
30421
|
}
|
|
@@ -29545,19 +30442,22 @@ function applyFixes(ctx, options) {
|
|
|
29545
30442
|
}
|
|
29546
30443
|
function parseFixKinds(raw) {
|
|
29547
30444
|
if (raw === true)
|
|
29548
|
-
return ["doc-meta", "anchors"];
|
|
30445
|
+
return ["doc-meta", "anchors", "ssot"];
|
|
29549
30446
|
switch (raw) {
|
|
29550
30447
|
case "doc-meta":
|
|
29551
30448
|
return ["doc-meta"];
|
|
29552
30449
|
case "anchors":
|
|
29553
30450
|
return ["anchors"];
|
|
30451
|
+
case "ssot":
|
|
30452
|
+
return ["ssot"];
|
|
29554
30453
|
default:
|
|
29555
|
-
throw new Error(`Unknown --fix kind: ${raw}. Use doc-meta or
|
|
30454
|
+
throw new Error(`Unknown --fix kind: ${raw}. Use doc-meta, anchors, or ssot.`);
|
|
29556
30455
|
}
|
|
29557
30456
|
}
|
|
29558
30457
|
var FIX_KIND_RULE = {
|
|
29559
30458
|
"doc-meta": "doc-meta",
|
|
29560
|
-
anchors: "links"
|
|
30459
|
+
anchors: "links",
|
|
30460
|
+
ssot: "ssot"
|
|
29561
30461
|
};
|
|
29562
30462
|
function fixKindsForOnly(kinds, only) {
|
|
29563
30463
|
if (!only)
|
|
@@ -29636,7 +30536,7 @@ function printTextReport(ctx) {
|
|
|
29636
30536
|
}
|
|
29637
30537
|
|
|
29638
30538
|
// src/references/check.ts
|
|
29639
|
-
import { existsSync as
|
|
30539
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
|
|
29640
30540
|
import { join as join11, relative as relative7 } from "node:path";
|
|
29641
30541
|
|
|
29642
30542
|
// src/references/constants.ts
|
|
@@ -29660,11 +30560,11 @@ function isGeneratedReference(content3) {
|
|
|
29660
30560
|
}
|
|
29661
30561
|
|
|
29662
30562
|
// src/references/discover.ts
|
|
29663
|
-
import { existsSync as
|
|
30563
|
+
import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
29664
30564
|
import { join as join10, relative as relative6 } from "node:path";
|
|
29665
30565
|
function walkMarkdownFiles(dir, root2) {
|
|
29666
30566
|
const files = [];
|
|
29667
|
-
if (!
|
|
30567
|
+
if (!existsSync11(dir))
|
|
29668
30568
|
return files;
|
|
29669
30569
|
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
29670
30570
|
if (entry.name.startsWith("."))
|
|
@@ -29681,7 +30581,7 @@ function walkMarkdownFiles(dir, root2) {
|
|
|
29681
30581
|
return files;
|
|
29682
30582
|
}
|
|
29683
30583
|
function canonicalExists(root2, refPath) {
|
|
29684
|
-
return
|
|
30584
|
+
return existsSync11(join10(root2, CANONICAL_REFS_DIR, refPath));
|
|
29685
30585
|
}
|
|
29686
30586
|
function findSharedRefLinks(content3, sourceFile) {
|
|
29687
30587
|
const links = [];
|
|
@@ -29725,7 +30625,7 @@ function findLocalCanonicalLinks(root2, content3, sourceFile) {
|
|
|
29725
30625
|
return links;
|
|
29726
30626
|
}
|
|
29727
30627
|
function collectLinksForFile(root2, relFile) {
|
|
29728
|
-
const content3 =
|
|
30628
|
+
const content3 = readFileSync10(join10(root2, relFile), "utf8");
|
|
29729
30629
|
if (isGeneratedReference(content3))
|
|
29730
30630
|
return [];
|
|
29731
30631
|
return [
|
|
@@ -29740,7 +30640,7 @@ function expandTransitiveRefs(input) {
|
|
|
29740
30640
|
const refPath = queue.pop();
|
|
29741
30641
|
if (!(refPath && canonicalExists(root2, refPath)))
|
|
29742
30642
|
continue;
|
|
29743
|
-
const canonicalContent =
|
|
30643
|
+
const canonicalContent = readFileSync10(join10(root2, CANONICAL_REFS_DIR, refPath), "utf8");
|
|
29744
30644
|
const syntheticSource = generatedRefPath(slug2, refPath);
|
|
29745
30645
|
for (const link2 of findLocalCanonicalLinks(root2, canonicalContent, syntheticSource)) {
|
|
29746
30646
|
if (refPaths.has(link2.refPath))
|
|
@@ -29753,7 +30653,7 @@ function expandTransitiveRefs(input) {
|
|
|
29753
30653
|
}
|
|
29754
30654
|
function planForSkill(root2, slug2) {
|
|
29755
30655
|
const skillDir = join10(root2, slug2);
|
|
29756
|
-
if (!
|
|
30656
|
+
if (!existsSync11(join10(skillDir, "SKILL.md")))
|
|
29757
30657
|
return null;
|
|
29758
30658
|
const refPaths = new Set;
|
|
29759
30659
|
const links = [];
|
|
@@ -29804,7 +30704,7 @@ function rewriteSharedRefLinks(content3, sourceFile, skill) {
|
|
|
29804
30704
|
|
|
29805
30705
|
// src/references/check.ts
|
|
29806
30706
|
function walkMarkdown(dir, onFile) {
|
|
29807
|
-
if (!
|
|
30707
|
+
if (!existsSync12(dir))
|
|
29808
30708
|
return;
|
|
29809
30709
|
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
29810
30710
|
if (entry.name.startsWith("."))
|
|
@@ -29822,7 +30722,7 @@ function walkMarkdown(dir, onFile) {
|
|
|
29822
30722
|
function listAllGeneratedFiles(root2) {
|
|
29823
30723
|
const files = [];
|
|
29824
30724
|
walkMarkdown(root2, (fullPath) => {
|
|
29825
|
-
const content3 =
|
|
30725
|
+
const content3 = readFileSync11(fullPath, "utf8");
|
|
29826
30726
|
if (isGeneratedReference(content3)) {
|
|
29827
30727
|
files.push(normalizeRelPath(relative7(root2, fullPath)));
|
|
29828
30728
|
}
|
|
@@ -29831,20 +30731,20 @@ function listAllGeneratedFiles(root2) {
|
|
|
29831
30731
|
}
|
|
29832
30732
|
function checkNeededCopy(root2, targetRel) {
|
|
29833
30733
|
const targetPath = join11(root2, targetRel);
|
|
29834
|
-
if (!
|
|
30734
|
+
if (!existsSync12(targetPath)) {
|
|
29835
30735
|
return issue("generated-references", targetRel, "missing generated copy — run skeleton references sync");
|
|
29836
30736
|
}
|
|
29837
|
-
const generated =
|
|
30737
|
+
const generated = readFileSync11(targetPath, "utf8");
|
|
29838
30738
|
if (!isGeneratedReference(generated)) {
|
|
29839
30739
|
return issue("generated-references", targetRel, "expected generated-reference provenance header");
|
|
29840
30740
|
}
|
|
29841
30741
|
const body = stripGeneratedHeader(generated);
|
|
29842
30742
|
const sourceRel = normalizeRelPath(generated.match(/source: ([^\n]+)/)?.[1] ?? join11(CANONICAL_REFS_DIR, targetRel.split("/references/")[1] ?? ""));
|
|
29843
30743
|
const canonicalPath = join11(root2, sourceRel);
|
|
29844
|
-
if (!
|
|
30744
|
+
if (!existsSync12(canonicalPath)) {
|
|
29845
30745
|
return issue("generated-references", targetRel, `canonical source missing: ${sourceRel}`);
|
|
29846
30746
|
}
|
|
29847
|
-
const canonical =
|
|
30747
|
+
const canonical = readFileSync11(canonicalPath, "utf8");
|
|
29848
30748
|
if (body !== canonical) {
|
|
29849
30749
|
return issue("generated-references", targetRel, "stale generated copy — run skeleton references sync");
|
|
29850
30750
|
}
|
|
@@ -29865,7 +30765,7 @@ function checkStaleSharedLinks(root2, skillDir) {
|
|
|
29865
30765
|
const issues = [];
|
|
29866
30766
|
walkMarkdown(skillDir, (fullPath) => {
|
|
29867
30767
|
const relFile = normalizeRelPath(relative7(root2, fullPath));
|
|
29868
|
-
const content3 =
|
|
30768
|
+
const content3 = readFileSync11(fullPath, "utf8");
|
|
29869
30769
|
if (!content3.match(SHARED_REF_LINK_RE))
|
|
29870
30770
|
return;
|
|
29871
30771
|
issues.push(issue("generated-references", relFile, "still links to shared root references/ — run skeleton references sync"));
|
|
@@ -29875,7 +30775,7 @@ function checkStaleSharedLinks(root2, skillDir) {
|
|
|
29875
30775
|
function runGeneratedReferencesCheck(root2, ownership) {
|
|
29876
30776
|
const issues = [];
|
|
29877
30777
|
const canonicalDir = join11(root2, CANONICAL_REFS_DIR);
|
|
29878
|
-
if (!
|
|
30778
|
+
if (!existsSync12(canonicalDir))
|
|
29879
30779
|
return issues;
|
|
29880
30780
|
const skillIndex = buildSkillIndex(root2, ownership);
|
|
29881
30781
|
const plans = discoverSkillReferencePlans(root2, ownership);
|
|
@@ -29910,14 +30810,14 @@ function runBannedRule(ctx) {
|
|
|
29910
30810
|
const issues = [];
|
|
29911
30811
|
for (const abs of collectBannedFiles(ctx.config, ctx.root)) {
|
|
29912
30812
|
const rel = relPath(abs, ctx.root);
|
|
29913
|
-
issues.push(issue("banned", rel, "file matches
|
|
30813
|
+
issues.push(issue("banned", rel, "file matches deny.paths — must not exist in repo"));
|
|
29914
30814
|
}
|
|
29915
30815
|
return issues;
|
|
29916
30816
|
}
|
|
29917
30817
|
var bannedRule = { id: "banned", run: runBannedRule };
|
|
29918
30818
|
|
|
29919
30819
|
// src/audit/rules/doc-meta.ts
|
|
29920
|
-
import { existsSync as
|
|
30820
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12 } from "node:fs";
|
|
29921
30821
|
import { join as join12 } from "node:path";
|
|
29922
30822
|
function checkDocMetaBanner(relPath2, content3) {
|
|
29923
30823
|
if (DOC_META_RE.test(content3))
|
|
@@ -29969,9 +30869,9 @@ function runDocMetaRule(ctx) {
|
|
|
29969
30869
|
const today = new Date;
|
|
29970
30870
|
for (const relPath2 of ctx.docMetaPaths) {
|
|
29971
30871
|
const abs = join12(ctx.root, relPath2);
|
|
29972
|
-
if (!
|
|
30872
|
+
if (!existsSync13(abs))
|
|
29973
30873
|
continue;
|
|
29974
|
-
const content3 =
|
|
30874
|
+
const content3 = readFileSync12(abs, "utf8");
|
|
29975
30875
|
const banner = checkDocMetaBanner(relPath2, content3);
|
|
29976
30876
|
if (banner) {
|
|
29977
30877
|
issues.push(banner);
|
|
@@ -29999,23 +30899,13 @@ function runDocMetaRule(ctx) {
|
|
|
29999
30899
|
var docMetaRule = { id: "doc-meta", run: runDocMetaRule };
|
|
30000
30900
|
|
|
30001
30901
|
// src/audit/rules/links.ts
|
|
30002
|
-
import { existsSync as
|
|
30003
|
-
import { dirname as dirname7, resolve as
|
|
30902
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13 } from "node:fs";
|
|
30903
|
+
import { dirname as dirname7, resolve as resolve6 } from "node:path";
|
|
30004
30904
|
function resolveLink2(sourceFile, target) {
|
|
30005
30905
|
const withoutAnchor = target.split("#")[0]?.split("?")[0] ?? "";
|
|
30006
30906
|
if (!withoutAnchor)
|
|
30007
30907
|
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
|
-
});
|
|
30908
|
+
return resolve6(dirname7(sourceFile), withoutAnchor);
|
|
30019
30909
|
}
|
|
30020
30910
|
function checkMissingSkill(input, relSource) {
|
|
30021
30911
|
if (!input.target.includes("/SKILL.md"))
|
|
@@ -30033,13 +30923,13 @@ function checkAgentFile(input, resolved, relSource) {
|
|
|
30033
30923
|
return null;
|
|
30034
30924
|
}
|
|
30035
30925
|
const agentPath = resolved.endsWith(".md") ? resolved : `${resolved}.md`;
|
|
30036
|
-
if (
|
|
30926
|
+
if (existsSync14(agentPath))
|
|
30037
30927
|
return null;
|
|
30038
30928
|
return issue("links", relSource, { message: "missing agent file", link: input.linkLabel });
|
|
30039
30929
|
}
|
|
30040
30930
|
function checkBrokenPath(ctx) {
|
|
30041
30931
|
const { input, pathPart, resolved, relSource, relTarget } = ctx;
|
|
30042
|
-
if (!(pathPart && !
|
|
30932
|
+
if (!(pathPart && !existsSync14(resolved)))
|
|
30043
30933
|
return null;
|
|
30044
30934
|
return issue("links", relSource, {
|
|
30045
30935
|
message: `broken link → ${relTarget}`,
|
|
@@ -30048,9 +30938,9 @@ function checkBrokenPath(ctx) {
|
|
|
30048
30938
|
}
|
|
30049
30939
|
function checkBrokenAnchor(ctx) {
|
|
30050
30940
|
const { input, anchor, resolved, relSource, relTarget } = ctx;
|
|
30051
|
-
if (!(anchor &&
|
|
30941
|
+
if (!(anchor && existsSync14(resolved)))
|
|
30052
30942
|
return null;
|
|
30053
|
-
const targetContent =
|
|
30943
|
+
const targetContent = readFileSync13(resolved, "utf8");
|
|
30054
30944
|
const slugs = extractHeadingSlugs(targetContent, resolved);
|
|
30055
30945
|
const anchorSlug = slugifyAnchor(anchor);
|
|
30056
30946
|
if (slugs.has(anchorSlug))
|
|
@@ -30075,9 +30965,6 @@ function validateTarget(input) {
|
|
|
30075
30965
|
if (isPlaceholderLink(target))
|
|
30076
30966
|
return [];
|
|
30077
30967
|
const parts = resolveTargetParts(sourceFile, target, ctx.root);
|
|
30078
|
-
const retired = checkRetiredSkill(input);
|
|
30079
|
-
if (retired)
|
|
30080
|
-
return [retired];
|
|
30081
30968
|
const missingSkill = checkMissingSkill(input, parts.relSource);
|
|
30082
30969
|
if (missingSkill)
|
|
30083
30970
|
return [missingSkill];
|
|
@@ -30104,6 +30991,331 @@ function runLinksRule(ctx) {
|
|
|
30104
30991
|
}
|
|
30105
30992
|
var linksRule = { id: "links", run: runLinksRule };
|
|
30106
30993
|
|
|
30994
|
+
// src/audit/rules/near-duplicate.ts
|
|
30995
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
30996
|
+
import { join as join13 } from "node:path";
|
|
30997
|
+
|
|
30998
|
+
// src/audit/core/ssot-fit.ts
|
|
30999
|
+
var DEFAULT_SSOT_OVERLAP_MIN = 0.35;
|
|
31000
|
+
var DEFAULT_BETTER_MATCH_MARGIN = 0.15;
|
|
31001
|
+
var STOP = new Set([
|
|
31002
|
+
"a",
|
|
31003
|
+
"an",
|
|
31004
|
+
"the",
|
|
31005
|
+
"and",
|
|
31006
|
+
"or",
|
|
31007
|
+
"of",
|
|
31008
|
+
"for",
|
|
31009
|
+
"to",
|
|
31010
|
+
"in",
|
|
31011
|
+
"on",
|
|
31012
|
+
"with",
|
|
31013
|
+
"this",
|
|
31014
|
+
"that",
|
|
31015
|
+
"is",
|
|
31016
|
+
"are",
|
|
31017
|
+
"be",
|
|
31018
|
+
"as",
|
|
31019
|
+
"by",
|
|
31020
|
+
"from",
|
|
31021
|
+
"at",
|
|
31022
|
+
"it",
|
|
31023
|
+
"its"
|
|
31024
|
+
]);
|
|
31025
|
+
var STEM_BLOCKLIST = new Set([
|
|
31026
|
+
"business",
|
|
31027
|
+
"analysis",
|
|
31028
|
+
"status",
|
|
31029
|
+
"process",
|
|
31030
|
+
"access",
|
|
31031
|
+
"address",
|
|
31032
|
+
"series",
|
|
31033
|
+
"species",
|
|
31034
|
+
"news",
|
|
31035
|
+
"means",
|
|
31036
|
+
"cross",
|
|
31037
|
+
"class",
|
|
31038
|
+
"glass",
|
|
31039
|
+
"less",
|
|
31040
|
+
"success",
|
|
31041
|
+
"progress",
|
|
31042
|
+
"express",
|
|
31043
|
+
"discuss",
|
|
31044
|
+
"focus",
|
|
31045
|
+
"bonus",
|
|
31046
|
+
"basis",
|
|
31047
|
+
"crisis",
|
|
31048
|
+
"thesis",
|
|
31049
|
+
"atlas",
|
|
31050
|
+
"canvas",
|
|
31051
|
+
"campus",
|
|
31052
|
+
"virus",
|
|
31053
|
+
"bus",
|
|
31054
|
+
"gas",
|
|
31055
|
+
"plus",
|
|
31056
|
+
"alias",
|
|
31057
|
+
"bias",
|
|
31058
|
+
"circus",
|
|
31059
|
+
"consensus",
|
|
31060
|
+
"census"
|
|
31061
|
+
]);
|
|
31062
|
+
function lightStem(token) {
|
|
31063
|
+
if (token.length < 4)
|
|
31064
|
+
return token;
|
|
31065
|
+
if (STEM_BLOCKLIST.has(token))
|
|
31066
|
+
return token;
|
|
31067
|
+
if (token.endsWith("ies") && token.length > 4) {
|
|
31068
|
+
return `${token.slice(0, -3)}y`;
|
|
31069
|
+
}
|
|
31070
|
+
if (token.endsWith("sses") || token.endsWith("ches") || token.endsWith("shes") || token.endsWith("xes")) {
|
|
31071
|
+
return token.slice(0, -2);
|
|
31072
|
+
}
|
|
31073
|
+
if (token.endsWith("s") && !token.endsWith("ss") && !token.endsWith("us") && !token.endsWith("is")) {
|
|
31074
|
+
return token.slice(0, -1);
|
|
31075
|
+
}
|
|
31076
|
+
return token;
|
|
31077
|
+
}
|
|
31078
|
+
function contentTokens(text5) {
|
|
31079
|
+
return text5.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length > 1 && !STOP.has(t)).map(lightStem);
|
|
31080
|
+
}
|
|
31081
|
+
function uniqueContentTokens(text5) {
|
|
31082
|
+
return [...new Set(contentTokens(text5))];
|
|
31083
|
+
}
|
|
31084
|
+
function stripCode2(content3) {
|
|
31085
|
+
return content3.replace(/```[\s\S]*?```/g, `
|
|
31086
|
+
`).replace(/`[^`\n]+`/g, " ");
|
|
31087
|
+
}
|
|
31088
|
+
function stripSsotAndMeta(content3) {
|
|
31089
|
+
return content3.replace(/<!--\s*source-of-truth:[\s\S]*?-->/gi, `
|
|
31090
|
+
`).replace(/^\s*source-of-truth:\s*.+$/gim, `
|
|
31091
|
+
`).replace(/^\s*\*\*Source of truth for\*\*\s*.+$/gim, `
|
|
31092
|
+
`).replace(/<!--\s*doc-meta:[\s\S]*?-->/gi, `
|
|
31093
|
+
`);
|
|
31094
|
+
}
|
|
31095
|
+
function extractH1(content3) {
|
|
31096
|
+
const prose = stripCode2(content3);
|
|
31097
|
+
const m = /^#\s+(.+)$/m.exec(prose);
|
|
31098
|
+
return m?.[1]?.trim() ?? "";
|
|
31099
|
+
}
|
|
31100
|
+
function extractLeadParagraph(content3) {
|
|
31101
|
+
const prose = stripSsotAndMeta(stripCode2(content3));
|
|
31102
|
+
const lines = prose.split(/\n/);
|
|
31103
|
+
const chunks = [];
|
|
31104
|
+
let buf = [];
|
|
31105
|
+
const flush = () => {
|
|
31106
|
+
const t = buf.join(" ").trim();
|
|
31107
|
+
if (t)
|
|
31108
|
+
chunks.push(t);
|
|
31109
|
+
buf = [];
|
|
31110
|
+
};
|
|
31111
|
+
for (const line of lines) {
|
|
31112
|
+
const trimmed = line.trim();
|
|
31113
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
31114
|
+
flush();
|
|
31115
|
+
continue;
|
|
31116
|
+
}
|
|
31117
|
+
if (/^[-*|]/.test(trimmed) && chunks.length === 0 && buf.length === 0) {
|
|
31118
|
+
buf.push(trimmed.replace(/^[-*|]+\s*/, ""));
|
|
31119
|
+
continue;
|
|
31120
|
+
}
|
|
31121
|
+
buf.push(trimmed);
|
|
31122
|
+
}
|
|
31123
|
+
flush();
|
|
31124
|
+
return chunks[0] ?? "";
|
|
31125
|
+
}
|
|
31126
|
+
function buildEvidenceText(content3) {
|
|
31127
|
+
const h1 = extractH1(content3);
|
|
31128
|
+
const lead = extractLeadParagraph(content3);
|
|
31129
|
+
const body = stripSsotAndMeta(stripCode2(content3));
|
|
31130
|
+
return [h1, lead, body].filter(Boolean).join(`
|
|
31131
|
+
|
|
31132
|
+
`);
|
|
31133
|
+
}
|
|
31134
|
+
function ssotEvidenceOverlap(summary, evidence) {
|
|
31135
|
+
const st = uniqueContentTokens(summary);
|
|
31136
|
+
if (st.length === 0)
|
|
31137
|
+
return 0;
|
|
31138
|
+
const ev = new Set(contentTokens(evidence));
|
|
31139
|
+
let hit = 0;
|
|
31140
|
+
for (const t of st) {
|
|
31141
|
+
if (ev.has(t))
|
|
31142
|
+
hit++;
|
|
31143
|
+
}
|
|
31144
|
+
return hit / st.length;
|
|
31145
|
+
}
|
|
31146
|
+
function longestSummaryPhrase(summary) {
|
|
31147
|
+
const toks = contentTokens(summary);
|
|
31148
|
+
if (toks.length >= 3)
|
|
31149
|
+
return toks.slice(0, 3);
|
|
31150
|
+
if (toks.length >= 2)
|
|
31151
|
+
return toks.slice(0, 2);
|
|
31152
|
+
return null;
|
|
31153
|
+
}
|
|
31154
|
+
function evidenceHasPhrase(evidence, phrase) {
|
|
31155
|
+
if (phrase.length === 0)
|
|
31156
|
+
return true;
|
|
31157
|
+
const ev = contentTokens(evidence);
|
|
31158
|
+
const needle = phrase.join(" ");
|
|
31159
|
+
for (let i = 0;i <= ev.length - phrase.length; i++) {
|
|
31160
|
+
if (ev.slice(i, i + phrase.length).join(" ") === needle)
|
|
31161
|
+
return true;
|
|
31162
|
+
}
|
|
31163
|
+
return false;
|
|
31164
|
+
}
|
|
31165
|
+
function evaluateSsotFit(files, options = {}) {
|
|
31166
|
+
const overlapMin = options.overlapMin ?? DEFAULT_SSOT_OVERLAP_MIN;
|
|
31167
|
+
const margin = options.betterMatchMargin ?? DEFAULT_BETTER_MATCH_MARGIN;
|
|
31168
|
+
const phraseCheck = options.phraseCheck !== false;
|
|
31169
|
+
const prepared = files.map((f) => {
|
|
31170
|
+
const evidence = buildEvidenceText(f.content);
|
|
31171
|
+
const overlap = ssotEvidenceOverlap(f.summary, evidence);
|
|
31172
|
+
const summaryToks = uniqueContentTokens(f.summary);
|
|
31173
|
+
return { ...f, evidence, overlap, summaryToks };
|
|
31174
|
+
});
|
|
31175
|
+
const issues = [];
|
|
31176
|
+
for (const row of prepared) {
|
|
31177
|
+
if (row.summaryToks.length < 2) {
|
|
31178
|
+
issues.push({
|
|
31179
|
+
kind: "short",
|
|
31180
|
+
path: row.path,
|
|
31181
|
+
message: `source-of-truth summary too short to verify against body ("${row.summary}")`
|
|
31182
|
+
});
|
|
31183
|
+
continue;
|
|
31184
|
+
}
|
|
31185
|
+
if (row.overlap < overlapMin) {
|
|
31186
|
+
let message = `source-of-truth summary weakly matches this paper (token overlap ${row.overlap.toFixed(2)} < ${overlapMin})`;
|
|
31187
|
+
if (phraseCheck) {
|
|
31188
|
+
const phrase = longestSummaryPhrase(row.summary);
|
|
31189
|
+
if (phrase && !evidenceHasPhrase(row.evidence, phrase)) {
|
|
31190
|
+
message += ` — key phrase "${phrase.join(" ")}" not found in H1/lead/body`;
|
|
31191
|
+
}
|
|
31192
|
+
}
|
|
31193
|
+
issues.push({ kind: "weak", path: row.path, message });
|
|
31194
|
+
let best = null;
|
|
31195
|
+
for (const other of prepared) {
|
|
31196
|
+
if (other.path === row.path)
|
|
31197
|
+
continue;
|
|
31198
|
+
const cross = ssotEvidenceOverlap(row.summary, other.evidence);
|
|
31199
|
+
if (cross < overlapMin)
|
|
31200
|
+
continue;
|
|
31201
|
+
if (cross < row.overlap + margin)
|
|
31202
|
+
continue;
|
|
31203
|
+
if (!best || cross > best.overlap)
|
|
31204
|
+
best = { path: other.path, overlap: cross };
|
|
31205
|
+
}
|
|
31206
|
+
if (best) {
|
|
31207
|
+
issues.push({
|
|
31208
|
+
kind: "better-match",
|
|
31209
|
+
path: row.path,
|
|
31210
|
+
otherPath: best.path,
|
|
31211
|
+
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`
|
|
31212
|
+
});
|
|
31213
|
+
}
|
|
31214
|
+
}
|
|
31215
|
+
}
|
|
31216
|
+
return issues;
|
|
31217
|
+
}
|
|
31218
|
+
|
|
31219
|
+
// src/audit/rules/near-duplicate.ts
|
|
31220
|
+
var DEFAULT_THRESHOLD = 0.72;
|
|
31221
|
+
var SHINGLE_N = 3;
|
|
31222
|
+
function tokenize2(text5) {
|
|
31223
|
+
return contentTokens(text5);
|
|
31224
|
+
}
|
|
31225
|
+
function normalizeSummary(summary) {
|
|
31226
|
+
return contentTokens(summary).join(" ");
|
|
31227
|
+
}
|
|
31228
|
+
function shingles(tokens, n) {
|
|
31229
|
+
const out = new Set;
|
|
31230
|
+
if (tokens.length < n) {
|
|
31231
|
+
if (tokens.length > 0)
|
|
31232
|
+
out.add(tokens.join(" "));
|
|
31233
|
+
return out;
|
|
31234
|
+
}
|
|
31235
|
+
for (let i = 0;i <= tokens.length - n; i++) {
|
|
31236
|
+
out.add(tokens.slice(i, i + n).join(" "));
|
|
31237
|
+
}
|
|
31238
|
+
return out;
|
|
31239
|
+
}
|
|
31240
|
+
function jaccard2(a, b) {
|
|
31241
|
+
if (a.size === 0 && b.size === 0)
|
|
31242
|
+
return 1;
|
|
31243
|
+
if (a.size === 0 || b.size === 0)
|
|
31244
|
+
return 0;
|
|
31245
|
+
let inter = 0;
|
|
31246
|
+
for (const x of a) {
|
|
31247
|
+
if (b.has(x))
|
|
31248
|
+
inter++;
|
|
31249
|
+
}
|
|
31250
|
+
return inter / (a.size + b.size - inter);
|
|
31251
|
+
}
|
|
31252
|
+
function pairKey(a, b) {
|
|
31253
|
+
return a < b ? `${a}::${b}` : `${b}::${a}`;
|
|
31254
|
+
}
|
|
31255
|
+
function ignoredPairSet(ctx) {
|
|
31256
|
+
const pairs = ctx.config.docsLint?.ignorePairs ?? [];
|
|
31257
|
+
const set = new Set;
|
|
31258
|
+
for (const pair of pairs) {
|
|
31259
|
+
if (!pair || pair.length < 2)
|
|
31260
|
+
continue;
|
|
31261
|
+
const a = normalizeRelPath(pair[0] ?? "");
|
|
31262
|
+
const b = normalizeRelPath(pair[1] ?? "");
|
|
31263
|
+
if (a && b)
|
|
31264
|
+
set.add(pairKey(a, b));
|
|
31265
|
+
}
|
|
31266
|
+
return set;
|
|
31267
|
+
}
|
|
31268
|
+
function isIgnoredGlob(rel, globs) {
|
|
31269
|
+
return globs.some((g) => matchesGlobScope(rel, g));
|
|
31270
|
+
}
|
|
31271
|
+
function bodyWithoutSsotNoise(content3) {
|
|
31272
|
+
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, " ");
|
|
31273
|
+
}
|
|
31274
|
+
function eligibleEntries(ctx) {
|
|
31275
|
+
const globs = ctx.config.docsLint?.ignoreGlobs ?? [];
|
|
31276
|
+
return ctx.ssotEntries.filter((e) => !isIgnoredGlob(e.path, globs));
|
|
31277
|
+
}
|
|
31278
|
+
function runNearDuplicateRule(ctx) {
|
|
31279
|
+
const issues = [];
|
|
31280
|
+
const threshold = ctx.config.docsLint?.nearDuplicateThreshold ?? DEFAULT_THRESHOLD;
|
|
31281
|
+
const ignored = ignoredPairSet(ctx);
|
|
31282
|
+
const entries = eligibleEntries(ctx);
|
|
31283
|
+
const fingerprints = entries.map((e) => {
|
|
31284
|
+
const content3 = readFileSync14(join13(ctx.root, e.path), "utf8");
|
|
31285
|
+
const tokens = tokenize2(bodyWithoutSsotNoise(content3));
|
|
31286
|
+
return {
|
|
31287
|
+
path: e.path,
|
|
31288
|
+
summaryKey: normalizeSummary(e.summary),
|
|
31289
|
+
set: shingles(tokens, SHINGLE_N)
|
|
31290
|
+
};
|
|
31291
|
+
});
|
|
31292
|
+
for (let i = 0;i < fingerprints.length; i++) {
|
|
31293
|
+
for (let j = i + 1;j < fingerprints.length; j++) {
|
|
31294
|
+
const a = fingerprints[i];
|
|
31295
|
+
const b = fingerprints[j];
|
|
31296
|
+
if (!(a && b))
|
|
31297
|
+
continue;
|
|
31298
|
+
if (ignored.has(pairKey(a.path, b.path)))
|
|
31299
|
+
continue;
|
|
31300
|
+
const score = jaccard2(a.set, b.set);
|
|
31301
|
+
if (score >= threshold) {
|
|
31302
|
+
issues.push(issue("near-duplicate", a.path, {
|
|
31303
|
+
message: `near-duplicate of ${b.path} (shingle Jaccard ${score.toFixed(2)} ≥ ${threshold})`,
|
|
31304
|
+
severity: "warning"
|
|
31305
|
+
}));
|
|
31306
|
+
}
|
|
31307
|
+
if (a.summaryKey && a.summaryKey === b.summaryKey) {
|
|
31308
|
+
issues.push(issue("near-duplicate", a.path, {
|
|
31309
|
+
message: `duplicate source-of-truth summary also used by ${b.path}`,
|
|
31310
|
+
severity: "warning"
|
|
31311
|
+
}));
|
|
31312
|
+
}
|
|
31313
|
+
}
|
|
31314
|
+
}
|
|
31315
|
+
return issues;
|
|
31316
|
+
}
|
|
31317
|
+
var nearDuplicateRule = { id: "near-duplicate", run: runNearDuplicateRule };
|
|
31318
|
+
|
|
30107
31319
|
// src/audit/rules/prose-policy.ts
|
|
30108
31320
|
function checkDraftEntry(input) {
|
|
30109
31321
|
const { rel, lines, entry, draftPrefixes } = input;
|
|
@@ -30164,53 +31376,6 @@ function runProsePolicyRule(ctx) {
|
|
|
30164
31376
|
}
|
|
30165
31377
|
var prosePolicyRule = { id: "prose-policy", run: runProsePolicyRule };
|
|
30166
31378
|
|
|
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
31379
|
// src/audit/rules/scan-gaps.ts
|
|
30215
31380
|
function runCoverageGapsRule(ctx) {
|
|
30216
31381
|
const exclude = [...COVERAGE_BUILTIN_EXCLUDES, ...ctx.config.scan.exclude];
|
|
@@ -30221,7 +31386,7 @@ function runCoverageGapsRule(ctx) {
|
|
|
30221
31386
|
if (scanned.has(rel))
|
|
30222
31387
|
continue;
|
|
30223
31388
|
issues.push(issue("coverage-gaps", rel, {
|
|
30224
|
-
message: "markdown outside audit scan perimeter — extend .skeleton/config.yaml scan.include",
|
|
31389
|
+
message: "markdown outside audit scan perimeter — extend skeleton.toml (or legacy .skeleton/config.yaml) scan.include",
|
|
30225
31390
|
severity: "warning"
|
|
30226
31391
|
}));
|
|
30227
31392
|
}
|
|
@@ -30240,11 +31405,11 @@ function runScanRootsRule(ctx) {
|
|
|
30240
31405
|
var scanRootsRule = { id: "scan-roots", run: runScanRootsRule };
|
|
30241
31406
|
|
|
30242
31407
|
// src/audit/rules/skill-index.ts
|
|
30243
|
-
import { existsSync as
|
|
31408
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync15 } from "node:fs";
|
|
30244
31409
|
import { join as join14, relative as relative8 } from "node:path";
|
|
30245
31410
|
function walkSkillMarkdown(dir) {
|
|
30246
31411
|
const files = [];
|
|
30247
|
-
if (!
|
|
31412
|
+
if (!existsSync15(dir))
|
|
30248
31413
|
return files;
|
|
30249
31414
|
for (const entry of readdirSync5(dir, { withFileTypes: true })) {
|
|
30250
31415
|
if (entry.name.startsWith("."))
|
|
@@ -30276,17 +31441,13 @@ function parseReadmeTaxonomySlugs(content3) {
|
|
|
30276
31441
|
function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
30277
31442
|
const issues = [];
|
|
30278
31443
|
const rel = relative8(ctx.root, filePath).replace(/\\/g, "/");
|
|
30279
|
-
const content3 =
|
|
31444
|
+
const content3 = readFileSync15(filePath, "utf8");
|
|
30280
31445
|
if (isGeneratedReference(content3))
|
|
30281
31446
|
return issues;
|
|
30282
31447
|
for (const match of content3.matchAll(SKILL_LINK_RE)) {
|
|
30283
31448
|
const slug2 = match[1];
|
|
30284
31449
|
if (!slug2)
|
|
30285
31450
|
continue;
|
|
30286
|
-
if (ctx.retiredSkills.has(slug2)) {
|
|
30287
|
-
issues.push(issue("skill-index", rel, `references retired skill "${slug2}/SKILL.md"`));
|
|
30288
|
-
continue;
|
|
30289
|
-
}
|
|
30290
31451
|
if (!resolveSkillPath(index2, ctx.root, slug2)) {
|
|
30291
31452
|
issues.push(issue("skill-index", rel, `links missing skill "${slug2}/SKILL.md"`));
|
|
30292
31453
|
}
|
|
@@ -30296,13 +31457,13 @@ function scanFileForSkillLinks(ctx, filePath, index2) {
|
|
|
30296
31457
|
function taxonomyIssuesForReadme(input) {
|
|
30297
31458
|
const { ctx, index: index2, skillRoot, diskSlugs, nonPublic } = input;
|
|
30298
31459
|
const readmePath = join14(ctx.root, skillRoot.relPath, "README.md");
|
|
30299
|
-
if (!
|
|
31460
|
+
if (!existsSync15(readmePath))
|
|
30300
31461
|
return [];
|
|
30301
|
-
const readme =
|
|
31462
|
+
const readme = readFileSync15(readmePath, "utf8");
|
|
30302
31463
|
if (!readme.includes("## Taxonomy"))
|
|
30303
31464
|
return [];
|
|
30304
31465
|
const taxonomySlugs = parseReadmeTaxonomySlugs(readme);
|
|
30305
|
-
const nestedSlugs = diskSlugs.filter((slug2) =>
|
|
31466
|
+
const nestedSlugs = diskSlugs.filter((slug2) => existsSync15(join14(ctx.root, skillRoot.relPath, slug2, "SKILL.md")));
|
|
30306
31467
|
const foreign = new Set(index2.foreignSlugs);
|
|
30307
31468
|
const publicSlugs = nestedSlugs.filter((slug2) => !(nonPublic.has(slug2) || foreign.has(slug2)));
|
|
30308
31469
|
const relReadme = `${skillRoot.relPath}/README.md`;
|
|
@@ -30338,7 +31499,7 @@ function auditSkillRoot(input) {
|
|
|
30338
31499
|
const base = skillRoot.kind === "nested" ? join14(ctx.root, skillRoot.relPath) : ctx.root;
|
|
30339
31500
|
for (const slug2 of slugsForRoot(skillRoot, index2, owned)) {
|
|
30340
31501
|
const skillDir = join14(base, slug2);
|
|
30341
|
-
if (!
|
|
31502
|
+
if (!existsSync15(skillDir))
|
|
30342
31503
|
continue;
|
|
30343
31504
|
for (const skillMd of walkSkillMarkdown(skillDir)) {
|
|
30344
31505
|
issues.push(...scanFileForSkillLinks(ctx, skillMd, index2));
|
|
@@ -30377,10 +31538,46 @@ function skillAuditSuffix(ctx) {
|
|
|
30377
31538
|
return ` (${owned} owned skills audited, ${foreign} foreign ignored)`;
|
|
30378
31539
|
}
|
|
30379
31540
|
|
|
31541
|
+
// src/audit/rules/ssot.ts
|
|
31542
|
+
function runSsotRule(ctx) {
|
|
31543
|
+
const issues = [];
|
|
31544
|
+
for (const err of ctx.ssotErrors) {
|
|
31545
|
+
issues.push(issue("ssot", err.path, err.detail));
|
|
31546
|
+
}
|
|
31547
|
+
return issues;
|
|
31548
|
+
}
|
|
31549
|
+
var ssotRule = { id: "ssot", run: runSsotRule };
|
|
31550
|
+
|
|
31551
|
+
// src/audit/rules/ssot-summary.ts
|
|
31552
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
31553
|
+
import { join as join15 } from "node:path";
|
|
31554
|
+
function runSsotSummaryRule(ctx) {
|
|
31555
|
+
const overlapMin = ctx.config.docsLint?.ssotOverlapMin ?? DEFAULT_SSOT_OVERLAP_MIN;
|
|
31556
|
+
const margin = ctx.config.docsLint?.ssotBetterMatchMargin ?? DEFAULT_BETTER_MATCH_MARGIN;
|
|
31557
|
+
const phraseCheck = ctx.config.docsLint?.ssotPhraseCheck !== false;
|
|
31558
|
+
const files = ctx.ssotEntries.map((entry) => ({
|
|
31559
|
+
path: entry.path,
|
|
31560
|
+
summary: entry.summary,
|
|
31561
|
+
content: readFileSync16(join15(ctx.root, entry.path), "utf8")
|
|
31562
|
+
}));
|
|
31563
|
+
return evaluateSsotFit(files, {
|
|
31564
|
+
overlapMin,
|
|
31565
|
+
betterMatchMargin: margin,
|
|
31566
|
+
phraseCheck
|
|
31567
|
+
}).map((fit) => issue("ssot-summary", fit.path, {
|
|
31568
|
+
message: fit.message,
|
|
31569
|
+
severity: "warning",
|
|
31570
|
+
link: fit.otherPath
|
|
31571
|
+
}));
|
|
31572
|
+
}
|
|
31573
|
+
var ssotSummaryRule = { id: "ssot-summary", run: runSsotSummaryRule };
|
|
31574
|
+
|
|
30380
31575
|
// src/audit/rules/index.ts
|
|
30381
31576
|
var docsRules = [
|
|
30382
31577
|
{ ...scanRootsRule, global: true },
|
|
30383
|
-
{ ...
|
|
31578
|
+
{ ...ssotRule, global: true },
|
|
31579
|
+
{ ...nearDuplicateRule, global: true },
|
|
31580
|
+
{ ...ssotSummaryRule, global: true },
|
|
30384
31581
|
{ ...coverageGapsRule, global: true },
|
|
30385
31582
|
linksRule,
|
|
30386
31583
|
docMetaRule,
|
|
@@ -30444,8 +31641,8 @@ function rulesForSuite(suite, pluginRules = []) {
|
|
|
30444
31641
|
function parseFixArg(argv, index2) {
|
|
30445
31642
|
const next = argv[index2 + 1];
|
|
30446
31643
|
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=
|
|
31644
|
+
if (next !== "doc-meta" && next !== "anchors" && next !== "ssot") {
|
|
31645
|
+
throw new Error(`Unknown --fix kind: ${next}. Use --fix, --fix=doc-meta, --fix=anchors, or --fix=ssot.`);
|
|
30449
31646
|
}
|
|
30450
31647
|
return { fix: next, nextIndex: index2 + 1 };
|
|
30451
31648
|
}
|
|
@@ -30536,7 +31733,7 @@ async function runAuditFixes(options, ctx, loaded) {
|
|
|
30536
31733
|
}
|
|
30537
31734
|
const kinds = fixKindsForOnly(parseFixKinds(options.fix), options.only);
|
|
30538
31735
|
if (kinds.length === 0) {
|
|
30539
|
-
console.error("--fix has no overlapping rules with --only (doc-meta → doc-meta, anchors → links).");
|
|
31736
|
+
console.error("--fix has no overlapping rules with --only (doc-meta → doc-meta, anchors → links, ssot → ssot).");
|
|
30540
31737
|
return 1;
|
|
30541
31738
|
}
|
|
30542
31739
|
applyFixes(ctx, { kinds, dryRun: options.dryRun });
|
|
@@ -30580,41 +31777,89 @@ async function runAudit(options) {
|
|
|
30580
31777
|
});
|
|
30581
31778
|
}
|
|
30582
31779
|
|
|
31780
|
+
// src/catalog.ts
|
|
31781
|
+
import { existsSync as existsSync16, mkdirSync, readFileSync as readFileSync17, writeFileSync as writeFileSync2 } from "node:fs";
|
|
31782
|
+
import { dirname as dirname8, join as join16 } from "node:path";
|
|
31783
|
+
function renderCatalog(entries) {
|
|
31784
|
+
const lines = [
|
|
31785
|
+
"# Skeleton catalog",
|
|
31786
|
+
"",
|
|
31787
|
+
"Generated by `skeleton catalog`. Gitignored — regenerate locally; do not commit.",
|
|
31788
|
+
"",
|
|
31789
|
+
"Agents: skim this list, then read only the SSOT line / first ~20 lines of a candidate before opening the full paper.",
|
|
31790
|
+
"",
|
|
31791
|
+
"| Summary | Path |",
|
|
31792
|
+
"| ------- | ---- |"
|
|
31793
|
+
];
|
|
31794
|
+
for (const e of entries) {
|
|
31795
|
+
const summary = e.summary.replace(/\|/g, "\\|");
|
|
31796
|
+
lines.push(`| ${summary} | [${e.path}](../${e.path}) |`);
|
|
31797
|
+
}
|
|
31798
|
+
lines.push("");
|
|
31799
|
+
return lines.join(`
|
|
31800
|
+
`);
|
|
31801
|
+
}
|
|
31802
|
+
function buildCatalogContent(root2) {
|
|
31803
|
+
const config = loadConfig(root2);
|
|
31804
|
+
const skillIndex = buildSkillIndex(root2, config.skillOwnership);
|
|
31805
|
+
const files = collectScanFiles(config, root2, skillIndex);
|
|
31806
|
+
const { entries } = collectSsotEntries(files, root2);
|
|
31807
|
+
return { content: renderCatalog(entries), entries };
|
|
31808
|
+
}
|
|
31809
|
+
function checkCatalog(root2) {
|
|
31810
|
+
const { content: expected, entries } = buildCatalogContent(root2);
|
|
31811
|
+
const abs = join16(root2, CATALOG_REL_PATH);
|
|
31812
|
+
if (!existsSync16(abs)) {
|
|
31813
|
+
return { ok: false, missing: true, stale: false, expected, actual: null, entries };
|
|
31814
|
+
}
|
|
31815
|
+
const actual = readFileSync17(abs, "utf8");
|
|
31816
|
+
const stale = actual !== expected;
|
|
31817
|
+
return { ok: !stale, missing: false, stale, expected, actual, entries };
|
|
31818
|
+
}
|
|
31819
|
+
function writeCatalog(root2) {
|
|
31820
|
+
const { content: content3, entries } = buildCatalogContent(root2);
|
|
31821
|
+
const abs = join16(root2, CATALOG_REL_PATH);
|
|
31822
|
+
mkdirSync(dirname8(abs), { recursive: true });
|
|
31823
|
+
writeFileSync2(abs, content3, "utf8");
|
|
31824
|
+
return { path: normalizeRelPath(CATALOG_REL_PATH), entries };
|
|
31825
|
+
}
|
|
31826
|
+
function runCatalogCli(options = {}) {
|
|
31827
|
+
const root2 = options.root ?? findRepoRoot();
|
|
31828
|
+
if (options.check) {
|
|
31829
|
+
const result = checkCatalog(root2);
|
|
31830
|
+
if (result.missing) {
|
|
31831
|
+
console.error(`catalog: missing ${CATALOG_REL_PATH} — run \`skeleton catalog\``);
|
|
31832
|
+
return 0;
|
|
31833
|
+
}
|
|
31834
|
+
if (result.stale) {
|
|
31835
|
+
console.error(`catalog: ${CATALOG_REL_PATH} is outdated — run \`skeleton catalog\``);
|
|
31836
|
+
return 0;
|
|
31837
|
+
}
|
|
31838
|
+
console.log(`catalog: ${CATALOG_REL_PATH} up to date (${result.entries.length} entries)`);
|
|
31839
|
+
return 0;
|
|
31840
|
+
}
|
|
31841
|
+
const written = writeCatalog(root2);
|
|
31842
|
+
console.log(`catalog: wrote ${written.path} (${written.entries.length} entries)`);
|
|
31843
|
+
return 0;
|
|
31844
|
+
}
|
|
31845
|
+
|
|
30583
31846
|
// src/customize/resolve.ts
|
|
30584
|
-
import { existsSync as
|
|
30585
|
-
import { basename as basename3, join as
|
|
30586
|
-
var CUSTOMIZE_PREFIX = "Customize: ";
|
|
31847
|
+
import { existsSync as existsSync17, readFileSync as readFileSync18 } from "node:fs";
|
|
31848
|
+
import { basename as basename3, join as join17, relative as relative9 } from "node:path";
|
|
30587
31849
|
function customizeDir(root2) {
|
|
30588
|
-
return
|
|
31850
|
+
return join17(root2, REGISTRY_DIR_REL, "customize");
|
|
30589
31851
|
}
|
|
30590
31852
|
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;
|
|
31853
|
+
return join17(customizeDir(root2), `${slug2}.md`);
|
|
30601
31854
|
}
|
|
30602
31855
|
function resolveSlugFile(root2, slug2) {
|
|
30603
31856
|
const direct = customizePathForSlug(root2, slug2);
|
|
30604
|
-
if (
|
|
31857
|
+
if (existsSync17(direct)) {
|
|
30605
31858
|
return {
|
|
30606
|
-
content:
|
|
31859
|
+
content: readFileSync18(direct, "utf8"),
|
|
30607
31860
|
path: normalizeRelPath(relative9(root2, direct))
|
|
30608
31861
|
};
|
|
30609
31862
|
}
|
|
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
31863
|
return { content: null, path: null };
|
|
30619
31864
|
}
|
|
30620
31865
|
function alwaysIncludeBasenames(root2) {
|
|
@@ -30633,10 +31878,10 @@ function readAlwaysInclude(root2, basenames, skipBasename) {
|
|
|
30633
31878
|
const file = basename3(name);
|
|
30634
31879
|
if (skipBasename && file === skipBasename)
|
|
30635
31880
|
continue;
|
|
30636
|
-
const abs =
|
|
30637
|
-
if (!
|
|
31881
|
+
const abs = join17(dir, file);
|
|
31882
|
+
if (!existsSync17(abs))
|
|
30638
31883
|
continue;
|
|
30639
|
-
parts.push(
|
|
31884
|
+
parts.push(readFileSync18(abs, "utf8").trimEnd());
|
|
30640
31885
|
paths.push(normalizeRelPath(relative9(root2, abs)));
|
|
30641
31886
|
}
|
|
30642
31887
|
return { parts, paths };
|
|
@@ -30760,39 +32005,39 @@ Customize override for /${slug2} (from ${from}):
|
|
|
30760
32005
|
|
|
30761
32006
|
// src/init/init.ts
|
|
30762
32007
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
30763
|
-
import { copyFileSync, existsSync as
|
|
30764
|
-
import { join as
|
|
32008
|
+
import { copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync3, readFileSync as readFileSync20 } from "node:fs";
|
|
32009
|
+
import { join as join21 } from "node:path";
|
|
30765
32010
|
import process4 from "node:process";
|
|
30766
32011
|
|
|
30767
32012
|
// src/init/merge-hooks.ts
|
|
30768
|
-
import { existsSync as
|
|
30769
|
-
import { dirname as
|
|
32013
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync2, readFileSync as readFileSync19, writeFileSync as writeFileSync3 } from "node:fs";
|
|
32014
|
+
import { dirname as dirname11, join as join20 } from "node:path";
|
|
30770
32015
|
|
|
30771
32016
|
// src/init/package-paths.ts
|
|
30772
|
-
import { existsSync as
|
|
30773
|
-
import { dirname as
|
|
32017
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
32018
|
+
import { dirname as dirname9, join as join18 } from "node:path";
|
|
30774
32019
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
30775
|
-
var MODULE_DIR =
|
|
30776
|
-
var PACKAGE_ROOT_CANDIDATES = [
|
|
32020
|
+
var MODULE_DIR = dirname9(fileURLToPath5(import.meta.url));
|
|
32021
|
+
var PACKAGE_ROOT_CANDIDATES = [join18(MODULE_DIR, "../.."), join18(MODULE_DIR, "..")];
|
|
30777
32022
|
function resolvePackageRoot() {
|
|
30778
32023
|
for (const candidate of PACKAGE_ROOT_CANDIDATES) {
|
|
30779
|
-
if (
|
|
32024
|
+
if (existsSync18(join18(candidate, "package.json")))
|
|
30780
32025
|
return candidate;
|
|
30781
32026
|
}
|
|
30782
32027
|
throw new Error("Could not resolve @csark0812/skeleton package root");
|
|
30783
32028
|
}
|
|
30784
32029
|
function resolveTemplatesDir() {
|
|
30785
|
-
const dir =
|
|
30786
|
-
if (!
|
|
32030
|
+
const dir = join18(resolvePackageRoot(), "templates/skeleton-init");
|
|
32031
|
+
if (!existsSync18(dir)) {
|
|
30787
32032
|
throw new Error("Missing templates/skeleton-init in package");
|
|
30788
32033
|
}
|
|
30789
32034
|
return dir;
|
|
30790
32035
|
}
|
|
30791
32036
|
|
|
30792
32037
|
// src/init/resolve-hook-command.ts
|
|
30793
|
-
import { existsSync as
|
|
32038
|
+
import { existsSync as existsSync19, realpathSync as realpathSync6 } from "node:fs";
|
|
30794
32039
|
import { createRequire as createRequire3 } from "node:module";
|
|
30795
|
-
import { dirname as
|
|
32040
|
+
import { dirname as dirname10, join as join19, relative as relative10, resolve as resolve7 } from "node:path";
|
|
30796
32041
|
var PACKAGE_NAME = "@csark0812/skeleton";
|
|
30797
32042
|
var CLI_DIST = "dist/cli.js";
|
|
30798
32043
|
var PACKAGE_ROOT = resolvePackageRoot();
|
|
@@ -30811,7 +32056,7 @@ function toRepoRelative(cwd, absPath) {
|
|
|
30811
32056
|
}
|
|
30812
32057
|
function tryResolvePublishedCli(cwd) {
|
|
30813
32058
|
try {
|
|
30814
|
-
const req = createRequire3(
|
|
32059
|
+
const req = createRequire3(join19(cwd, "package.json"));
|
|
30815
32060
|
return req.resolve(`${PACKAGE_NAME}/${CLI_DIST}`);
|
|
30816
32061
|
} catch {
|
|
30817
32062
|
return null;
|
|
@@ -30820,10 +32065,10 @@ function tryResolvePublishedCli(cwd) {
|
|
|
30820
32065
|
function walkNodeModulesCli(cwd) {
|
|
30821
32066
|
let dir = cwd;
|
|
30822
32067
|
while (true) {
|
|
30823
|
-
const candidate =
|
|
30824
|
-
if (
|
|
32068
|
+
const candidate = join19(dir, "node_modules", PACKAGE_NAME, CLI_DIST);
|
|
32069
|
+
if (existsSync19(candidate))
|
|
30825
32070
|
return candidate;
|
|
30826
|
-
const parent =
|
|
32071
|
+
const parent = dirname10(dir);
|
|
30827
32072
|
if (parent === dir)
|
|
30828
32073
|
break;
|
|
30829
32074
|
dir = parent;
|
|
@@ -30831,7 +32076,7 @@ function walkNodeModulesCli(cwd) {
|
|
|
30831
32076
|
return null;
|
|
30832
32077
|
}
|
|
30833
32078
|
function isInsidePackageRoot(cwd) {
|
|
30834
|
-
const rel = relative10(PACKAGE_ROOT,
|
|
32079
|
+
const rel = relative10(PACKAGE_ROOT, resolve7(cwd)).replace(/\\/g, "/");
|
|
30835
32080
|
return rel === "" || !(rel.startsWith("..") || rel.startsWith("/"));
|
|
30836
32081
|
}
|
|
30837
32082
|
function nodeCliHookCommand(cliPath) {
|
|
@@ -30862,21 +32107,21 @@ function identityKey(platform, event, matcher) {
|
|
|
30862
32107
|
return `skeleton:customize:${platform}:${event}:${matcher}`;
|
|
30863
32108
|
}
|
|
30864
32109
|
function loadFragment(name, hookCommand) {
|
|
30865
|
-
const raw =
|
|
32110
|
+
const raw = readFileSync19(join20(TEMPLATES_DIR, name), "utf8");
|
|
30866
32111
|
return JSON.parse(raw.replaceAll("{{HOOK_COMMAND}}", hookCommand));
|
|
30867
32112
|
}
|
|
30868
32113
|
function readJson(path2) {
|
|
30869
|
-
if (!
|
|
32114
|
+
if (!existsSync20(path2))
|
|
30870
32115
|
return null;
|
|
30871
32116
|
try {
|
|
30872
|
-
return JSON.parse(
|
|
32117
|
+
return JSON.parse(readFileSync19(path2, "utf8"));
|
|
30873
32118
|
} catch (error) {
|
|
30874
32119
|
throw new Error(`Invalid JSON in ${path2}: ${error}`);
|
|
30875
32120
|
}
|
|
30876
32121
|
}
|
|
30877
32122
|
function writeJson(path2, value) {
|
|
30878
|
-
|
|
30879
|
-
|
|
32123
|
+
mkdirSync2(dirname11(path2), { recursive: true });
|
|
32124
|
+
writeFileSync3(path2, `${JSON.stringify(value, null, 2)}
|
|
30880
32125
|
`, "utf8");
|
|
30881
32126
|
}
|
|
30882
32127
|
function deepEqual(a, b) {
|
|
@@ -31029,10 +32274,10 @@ function mergeNestedHooks(args) {
|
|
|
31029
32274
|
}
|
|
31030
32275
|
function mergeHookConfigs(opts) {
|
|
31031
32276
|
const results = [];
|
|
31032
|
-
const cursorPath =
|
|
32277
|
+
const cursorPath = join20(opts.cwd, ".cursor/hooks.json");
|
|
31033
32278
|
const cursorFragment = loadFragment("cursor-hooks.fragment.json", opts.hookCommand);
|
|
31034
32279
|
results.push(mergeCursorHooks(cursorPath, cursorFragment, opts));
|
|
31035
|
-
const claudePath =
|
|
32280
|
+
const claudePath = join20(opts.cwd, ".claude/settings.json");
|
|
31036
32281
|
const claudeFragment = loadFragment("claude-settings.fragment.json", opts.hookCommand);
|
|
31037
32282
|
results.push(mergeNestedHooks({
|
|
31038
32283
|
platform: "claude",
|
|
@@ -31041,8 +32286,8 @@ function mergeHookConfigs(opts) {
|
|
|
31041
32286
|
eventName: "PostToolUse",
|
|
31042
32287
|
opts
|
|
31043
32288
|
}));
|
|
31044
|
-
const codexPath =
|
|
31045
|
-
if (
|
|
32289
|
+
const codexPath = join20(opts.cwd, ".codex/hooks.json");
|
|
32290
|
+
if (existsSync20(join20(opts.cwd, ".codex"))) {
|
|
31046
32291
|
const codexFragment = loadFragment("codex-hooks.fragment.json", opts.hookCommand);
|
|
31047
32292
|
results.push(mergeNestedHooks({
|
|
31048
32293
|
platform: "codex",
|
|
@@ -31057,11 +32302,11 @@ function mergeHookConfigs(opts) {
|
|
|
31057
32302
|
return results;
|
|
31058
32303
|
}
|
|
31059
32304
|
function mergePackageJsonScripts(cwd) {
|
|
31060
|
-
const pkgPath =
|
|
31061
|
-
if (!
|
|
32305
|
+
const pkgPath = join20(cwd, "package.json");
|
|
32306
|
+
if (!existsSync20(pkgPath))
|
|
31062
32307
|
return "skipped";
|
|
31063
|
-
const fragment = JSON.parse(
|
|
31064
|
-
const pkg = JSON.parse(
|
|
32308
|
+
const fragment = JSON.parse(readFileSync19(join20(TEMPLATES_DIR, "package.json.scripts.fragment.json"), "utf8"));
|
|
32309
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
|
|
31065
32310
|
pkg.scripts ??= {};
|
|
31066
32311
|
let changed = false;
|
|
31067
32312
|
for (const [key, value] of Object.entries(fragment)) {
|
|
@@ -31072,7 +32317,7 @@ function mergePackageJsonScripts(cwd) {
|
|
|
31072
32317
|
}
|
|
31073
32318
|
if (!changed)
|
|
31074
32319
|
return "skipped";
|
|
31075
|
-
|
|
32320
|
+
writeFileSync3(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
31076
32321
|
`, "utf8");
|
|
31077
32322
|
return "updated";
|
|
31078
32323
|
}
|
|
@@ -31117,27 +32362,23 @@ function skillsAddArgs(options = {}) {
|
|
|
31117
32362
|
// src/init/init.ts
|
|
31118
32363
|
var TEMPLATES_DIR2 = resolveTemplatesDir();
|
|
31119
32364
|
function writeScaffold(cwd) {
|
|
31120
|
-
const skeletonDir2 =
|
|
31121
|
-
|
|
32365
|
+
const skeletonDir2 = join21(cwd, ".skeleton");
|
|
32366
|
+
mkdirSync3(skeletonDir2, { recursive: true });
|
|
31122
32367
|
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);
|
|
32368
|
+
const tomlPath = join21(cwd, "skeleton.toml");
|
|
32369
|
+
const legacyYaml = join21(skeletonDir2, "config.yaml");
|
|
32370
|
+
if (!(existsSync21(tomlPath) || existsSync21(legacyYaml))) {
|
|
32371
|
+
copyFileSync(join21(TEMPLATES_DIR2, "skeleton.toml"), tomlPath);
|
|
31131
32372
|
created = true;
|
|
31132
32373
|
}
|
|
31133
|
-
|
|
32374
|
+
mkdirSync3(join21(skeletonDir2, "customize"), { recursive: true });
|
|
31134
32375
|
return created ? "created" : "skipped";
|
|
31135
32376
|
}
|
|
31136
32377
|
function assertPackageResolvable(cwd) {
|
|
31137
|
-
const pkgPath =
|
|
31138
|
-
if (!
|
|
32378
|
+
const pkgPath = join21(cwd, "package.json");
|
|
32379
|
+
if (!existsSync21(pkgPath))
|
|
31139
32380
|
return;
|
|
31140
|
-
const pkg = JSON.parse(
|
|
32381
|
+
const pkg = JSON.parse(readFileSync20(pkgPath, "utf8"));
|
|
31141
32382
|
const hasDep = pkg.devDependencies?.["@csark0812/skeleton"] || pkg.dependencies?.["@csark0812/skeleton"];
|
|
31142
32383
|
if (!hasDep) {
|
|
31143
32384
|
try {
|
|
@@ -31186,9 +32427,9 @@ function runInit(options = {}) {
|
|
|
31186
32427
|
for (const result of hooks)
|
|
31187
32428
|
logHookMergeResult(result);
|
|
31188
32429
|
if (scaffold === "created") {
|
|
31189
|
-
console.log("init: wrote
|
|
32430
|
+
console.log("init: wrote skeleton.toml (hooks optional — see docs)");
|
|
31190
32431
|
} else {
|
|
31191
|
-
console.log("init: .skeleton/ already present — skipped scaffold write");
|
|
32432
|
+
console.log("init: skeleton.toml or .skeleton/ already present — skipped scaffold write");
|
|
31192
32433
|
}
|
|
31193
32434
|
if (scripts === "updated") {
|
|
31194
32435
|
console.log("init: merged validate/audit scripts into package.json");
|
|
@@ -31221,8 +32462,8 @@ function parseInitArgs(argv) {
|
|
|
31221
32462
|
// src/plugins/build.ts
|
|
31222
32463
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
31223
32464
|
import { createHash } from "node:crypto";
|
|
31224
|
-
import { existsSync as
|
|
31225
|
-
import { basename as basename4, dirname as
|
|
32465
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "node:fs";
|
|
32466
|
+
import { basename as basename4, dirname as dirname12, resolve as resolve8 } from "node:path";
|
|
31226
32467
|
function parseBuildPluginArgs(argv) {
|
|
31227
32468
|
let check = false;
|
|
31228
32469
|
let entry;
|
|
@@ -31247,7 +32488,7 @@ function collectPluginEntries(root2, config, entry) {
|
|
|
31247
32488
|
return (config.plugins ?? []).map((e) => resolvePluginTsPath(root2, e));
|
|
31248
32489
|
}
|
|
31249
32490
|
function localImportPaths(tsAbs, content3) {
|
|
31250
|
-
const dir =
|
|
32491
|
+
const dir = dirname12(tsAbs);
|
|
31251
32492
|
const deps = [];
|
|
31252
32493
|
const re = /(?:from\s+|import\s*\(\s*|import\s+)["'](\.[^"']+)["']/g;
|
|
31253
32494
|
for (const match of content3.matchAll(re)) {
|
|
@@ -31257,12 +32498,12 @@ function localImportPaths(tsAbs, content3) {
|
|
|
31257
32498
|
const candidates = [];
|
|
31258
32499
|
if (spec.endsWith(".js")) {
|
|
31259
32500
|
const withoutJs = spec.slice(0, -".js".length);
|
|
31260
|
-
candidates.push(
|
|
32501
|
+
candidates.push(resolve8(dir, `${withoutJs}.ts`), resolve8(dir, spec), resolve8(dir, withoutJs, "index.ts"));
|
|
31261
32502
|
} else {
|
|
31262
|
-
candidates.push(
|
|
32503
|
+
candidates.push(resolve8(dir, spec), resolve8(dir, `${spec}.ts`), resolve8(dir, `${spec}.js`), resolve8(dir, spec, "index.ts"));
|
|
31263
32504
|
}
|
|
31264
32505
|
for (const candidate of candidates) {
|
|
31265
|
-
if (
|
|
32506
|
+
if (existsSync22(candidate) && candidate.endsWith(".ts")) {
|
|
31266
32507
|
deps.push(candidate);
|
|
31267
32508
|
break;
|
|
31268
32509
|
}
|
|
@@ -31279,7 +32520,7 @@ function sourceFingerprint(tsAbs, seen = new Set) {
|
|
|
31279
32520
|
if (seen.has(abs))
|
|
31280
32521
|
return;
|
|
31281
32522
|
seen.add(abs);
|
|
31282
|
-
const content3 =
|
|
32523
|
+
const content3 = readFileSync21(abs, "utf8");
|
|
31283
32524
|
hash.update(basename4(abs));
|
|
31284
32525
|
hash.update("\x00");
|
|
31285
32526
|
hash.update(content3);
|
|
@@ -31292,12 +32533,12 @@ function sourceFingerprint(tsAbs, seen = new Set) {
|
|
|
31292
32533
|
return hash.digest("hex");
|
|
31293
32534
|
}
|
|
31294
32535
|
function writeStamp(tsAbs, mjsAbs) {
|
|
31295
|
-
|
|
32536
|
+
writeFileSync4(stampPathForMjs(mjsAbs), `${sourceFingerprint(tsAbs)}
|
|
31296
32537
|
`, "utf8");
|
|
31297
32538
|
}
|
|
31298
32539
|
async function buildOne(tsAbs) {
|
|
31299
32540
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
31300
|
-
if (!
|
|
32541
|
+
if (!existsSync22(tsAbs)) {
|
|
31301
32542
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
31302
32543
|
}
|
|
31303
32544
|
const proc = spawnSync3("bun", ["build", tsAbs, "--target=node", "--format=esm", `--outfile=${mjsAbs}`, "--packages=external"], { encoding: "utf8" });
|
|
@@ -31317,17 +32558,17 @@ ${proc.stderr || proc.stdout || `exit ${proc.status}`}`);
|
|
|
31317
32558
|
}
|
|
31318
32559
|
function checkOne(tsAbs) {
|
|
31319
32560
|
const mjsAbs = mjsPathForTs(tsAbs);
|
|
31320
|
-
if (!
|
|
32561
|
+
if (!existsSync22(mjsAbs)) {
|
|
31321
32562
|
throw new Error(`Plugin not built: ${tsAbs} (missing ${mjsAbs}). Run: skeleton build-plugin`);
|
|
31322
32563
|
}
|
|
31323
|
-
if (!
|
|
32564
|
+
if (!existsSync22(tsAbs)) {
|
|
31324
32565
|
throw new Error(`Plugin source not found: ${tsAbs}`);
|
|
31325
32566
|
}
|
|
31326
32567
|
const stampAbs = stampPathForMjs(mjsAbs);
|
|
31327
|
-
if (!
|
|
32568
|
+
if (!existsSync22(stampAbs)) {
|
|
31328
32569
|
throw new Error(`Plugin stale: ${mjsAbs} has no fingerprint stamp. Run: skeleton build-plugin`);
|
|
31329
32570
|
}
|
|
31330
|
-
const expected =
|
|
32571
|
+
const expected = readFileSync21(stampAbs, "utf8").trim();
|
|
31331
32572
|
const actual = sourceFingerprint(tsAbs);
|
|
31332
32573
|
if (expected !== actual) {
|
|
31333
32574
|
throw new Error(`Plugin stale: ${mjsAbs} does not match ${tsAbs} (or local imports). Run: skeleton build-plugin`);
|
|
@@ -31360,14 +32601,14 @@ import process6 from "node:process";
|
|
|
31360
32601
|
|
|
31361
32602
|
// src/references/sync.ts
|
|
31362
32603
|
import {
|
|
31363
|
-
existsSync as
|
|
31364
|
-
mkdirSync as
|
|
32604
|
+
existsSync as existsSync23,
|
|
32605
|
+
mkdirSync as mkdirSync4,
|
|
31365
32606
|
readdirSync as readdirSync6,
|
|
31366
|
-
readFileSync as
|
|
32607
|
+
readFileSync as readFileSync22,
|
|
31367
32608
|
unlinkSync,
|
|
31368
|
-
writeFileSync as
|
|
32609
|
+
writeFileSync as writeFileSync5
|
|
31369
32610
|
} from "node:fs";
|
|
31370
|
-
import { dirname as
|
|
32611
|
+
import { dirname as dirname13, join as join22, relative as relative11 } from "node:path";
|
|
31371
32612
|
import process5 from "node:process";
|
|
31372
32613
|
function resolveOwnership(root2, override) {
|
|
31373
32614
|
if (override !== undefined)
|
|
@@ -31378,12 +32619,12 @@ function resolveOwnership(root2, override) {
|
|
|
31378
32619
|
}
|
|
31379
32620
|
function walkMarkdownFiles2(dir, root2) {
|
|
31380
32621
|
const files = [];
|
|
31381
|
-
if (!
|
|
32622
|
+
if (!existsSync23(dir))
|
|
31382
32623
|
return files;
|
|
31383
32624
|
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
31384
32625
|
if (entry.name.startsWith("."))
|
|
31385
32626
|
continue;
|
|
31386
|
-
const fullPath =
|
|
32627
|
+
const fullPath = join22(dir, entry.name);
|
|
31387
32628
|
if (entry.isDirectory()) {
|
|
31388
32629
|
files.push(...walkMarkdownFiles2(fullPath, root2));
|
|
31389
32630
|
continue;
|
|
@@ -31397,14 +32638,14 @@ function walkMarkdownFiles2(dir, root2) {
|
|
|
31397
32638
|
function collectGeneratedInDir(input) {
|
|
31398
32639
|
const { dir, refsDir, skill, files } = input;
|
|
31399
32640
|
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
31400
|
-
const fullPath =
|
|
32641
|
+
const fullPath = join22(dir, entry.name);
|
|
31401
32642
|
if (entry.isDirectory()) {
|
|
31402
32643
|
collectGeneratedInDir({ dir: fullPath, refsDir, skill, files });
|
|
31403
32644
|
continue;
|
|
31404
32645
|
}
|
|
31405
32646
|
if (!entry.name.endsWith(".md"))
|
|
31406
32647
|
continue;
|
|
31407
|
-
const content3 =
|
|
32648
|
+
const content3 = readFileSync22(fullPath, "utf8");
|
|
31408
32649
|
if (!isGeneratedReference(content3))
|
|
31409
32650
|
continue;
|
|
31410
32651
|
const refPath = normalizeRelPath(relative11(refsDir, fullPath));
|
|
@@ -31412,8 +32653,8 @@ function collectGeneratedInDir(input) {
|
|
|
31412
32653
|
}
|
|
31413
32654
|
}
|
|
31414
32655
|
function listGeneratedReferenceFiles(skillDir, skill) {
|
|
31415
|
-
const refsDir =
|
|
31416
|
-
if (!
|
|
32656
|
+
const refsDir = join22(skillDir, "references");
|
|
32657
|
+
if (!existsSync23(refsDir))
|
|
31417
32658
|
return [];
|
|
31418
32659
|
const files = [];
|
|
31419
32660
|
collectGeneratedInDir({ dir: refsDir, refsDir, skill, files });
|
|
@@ -31421,21 +32662,21 @@ function listGeneratedReferenceFiles(skillDir, skill) {
|
|
|
31421
32662
|
}
|
|
31422
32663
|
function syncGeneratedCopy(ctx, refPath) {
|
|
31423
32664
|
const { root: root2, plan, options, result } = ctx;
|
|
31424
|
-
const sourceRel = normalizeRelPath(
|
|
31425
|
-
const canonicalPath =
|
|
31426
|
-
if (!
|
|
32665
|
+
const sourceRel = normalizeRelPath(join22(CANONICAL_REFS_DIR, refPath));
|
|
32666
|
+
const canonicalPath = join22(root2, sourceRel);
|
|
32667
|
+
if (!existsSync23(canonicalPath)) {
|
|
31427
32668
|
throw new Error(`canonical reference missing: ${sourceRel}`);
|
|
31428
32669
|
}
|
|
31429
32670
|
const targetRel = generatedRefPath(plan.skill, refPath);
|
|
31430
|
-
const targetPath =
|
|
31431
|
-
const canonicalContent =
|
|
32671
|
+
const targetPath = join22(root2, targetRel);
|
|
32672
|
+
const canonicalContent = readFileSync22(canonicalPath, "utf8");
|
|
31432
32673
|
const nextContent = formatGeneratedHeader(sourceRel) + canonicalContent;
|
|
31433
32674
|
if (!options.dryRun)
|
|
31434
|
-
|
|
31435
|
-
const existing =
|
|
32675
|
+
mkdirSync4(dirname13(targetPath), { recursive: true });
|
|
32676
|
+
const existing = existsSync23(targetPath) ? readFileSync22(targetPath, "utf8") : null;
|
|
31436
32677
|
if (existing !== nextContent) {
|
|
31437
32678
|
if (!options.dryRun)
|
|
31438
|
-
|
|
32679
|
+
writeFileSync5(targetPath, nextContent, "utf8");
|
|
31439
32680
|
result.written.push(targetRel);
|
|
31440
32681
|
} else {
|
|
31441
32682
|
result.skipped.push(targetRel);
|
|
@@ -31446,13 +32687,13 @@ function rewritePlanLinks(ctx, skillDir) {
|
|
|
31446
32687
|
if (options.rewriteLinks === false)
|
|
31447
32688
|
return;
|
|
31448
32689
|
for (const relFile of walkMarkdownFiles2(skillDir, root2)) {
|
|
31449
|
-
const filePath =
|
|
31450
|
-
const content3 =
|
|
32690
|
+
const filePath = join22(root2, relFile);
|
|
32691
|
+
const content3 = readFileSync22(filePath, "utf8");
|
|
31451
32692
|
const next = rewriteSharedRefLinks(content3, relFile, plan.skill);
|
|
31452
32693
|
if (next === content3)
|
|
31453
32694
|
continue;
|
|
31454
32695
|
if (!options.dryRun)
|
|
31455
|
-
|
|
32696
|
+
writeFileSync5(filePath, next, "utf8");
|
|
31456
32697
|
result.rewritten.push(relFile);
|
|
31457
32698
|
}
|
|
31458
32699
|
}
|
|
@@ -31463,12 +32704,12 @@ function removeStaleGenerated(ctx, skillDir) {
|
|
|
31463
32704
|
if (plan.refPaths.has(refPath))
|
|
31464
32705
|
continue;
|
|
31465
32706
|
if (!options.dryRun)
|
|
31466
|
-
unlinkSync(
|
|
32707
|
+
unlinkSync(join22(root2, generatedRel));
|
|
31467
32708
|
result.removed.push(generatedRel);
|
|
31468
32709
|
}
|
|
31469
32710
|
}
|
|
31470
32711
|
function syncPlan(ctx) {
|
|
31471
|
-
const skillDir =
|
|
32712
|
+
const skillDir = join22(ctx.root, ctx.plan.skill);
|
|
31472
32713
|
for (const refPath of ctx.plan.refPaths) {
|
|
31473
32714
|
syncGeneratedCopy(ctx, refPath);
|
|
31474
32715
|
}
|
|
@@ -31477,8 +32718,8 @@ function syncPlan(ctx) {
|
|
|
31477
32718
|
}
|
|
31478
32719
|
function syncReferences(options = {}) {
|
|
31479
32720
|
const root2 = options.root ?? process5.cwd();
|
|
31480
|
-
const canonicalDir =
|
|
31481
|
-
if (!
|
|
32721
|
+
const canonicalDir = join22(root2, CANONICAL_REFS_DIR);
|
|
32722
|
+
if (!existsSync23(canonicalDir)) {
|
|
31482
32723
|
throw new Error(`canonical references dir not found: ${CANONICAL_REFS_DIR}`);
|
|
31483
32724
|
}
|
|
31484
32725
|
const result = { written: [], rewritten: [], removed: [], skipped: [] };
|
|
@@ -31523,183 +32764,10 @@ function printSyncResult(result) {
|
|
|
31523
32764
|
}
|
|
31524
32765
|
}
|
|
31525
32766
|
|
|
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
32767
|
// src/validate/changed.ts
|
|
31700
32768
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
31701
|
-
import { existsSync as
|
|
31702
|
-
import { basename as basename5, extname as extname2, join as
|
|
32769
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
|
|
32770
|
+
import { basename as basename5, extname as extname2, join as join23 } from "node:path";
|
|
31703
32771
|
|
|
31704
32772
|
// src/validate/git-diff.ts
|
|
31705
32773
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -31792,9 +32860,9 @@ function parseJsonContent(content3) {
|
|
|
31792
32860
|
}
|
|
31793
32861
|
}
|
|
31794
32862
|
function validateJson(relPath2, root2) {
|
|
31795
|
-
const abs =
|
|
32863
|
+
const abs = join23(root2, relPath2);
|
|
31796
32864
|
try {
|
|
31797
|
-
parseJsonContent(
|
|
32865
|
+
parseJsonContent(readFileSync23(abs, "utf8"));
|
|
31798
32866
|
return 0;
|
|
31799
32867
|
} catch (error) {
|
|
31800
32868
|
console.error(`validate changed: invalid JSON in ${relPath2}: ${error}`);
|
|
@@ -31802,9 +32870,9 @@ function validateJson(relPath2, root2) {
|
|
|
31802
32870
|
}
|
|
31803
32871
|
}
|
|
31804
32872
|
function validatePolicy(relPath2, root2) {
|
|
31805
|
-
const abs =
|
|
32873
|
+
const abs = join23(root2, relPath2);
|
|
31806
32874
|
try {
|
|
31807
|
-
loadPolicyFile(abs,
|
|
32875
|
+
loadPolicyFile(abs, readFileSync23(abs, "utf8"));
|
|
31808
32876
|
return 0;
|
|
31809
32877
|
} catch (error) {
|
|
31810
32878
|
console.error(`validate changed: invalid policy ${relPath2}: ${error}`);
|
|
@@ -31812,7 +32880,7 @@ function validatePolicy(relPath2, root2) {
|
|
|
31812
32880
|
}
|
|
31813
32881
|
}
|
|
31814
32882
|
function validateShell(relPath2, root2) {
|
|
31815
|
-
const abs =
|
|
32883
|
+
const abs = join23(root2, relPath2);
|
|
31816
32884
|
const shellcheck = spawnSync5("shellcheck", [abs], { encoding: "utf8" });
|
|
31817
32885
|
if (shellcheck.status === 0)
|
|
31818
32886
|
return 0;
|
|
@@ -31833,11 +32901,11 @@ function resolvePaths(options) {
|
|
|
31833
32901
|
});
|
|
31834
32902
|
}
|
|
31835
32903
|
function packageManagerFromPackageJson(root2) {
|
|
31836
|
-
const pkgPath =
|
|
31837
|
-
if (!
|
|
32904
|
+
const pkgPath = join23(root2, "package.json");
|
|
32905
|
+
if (!existsSync24(pkgPath))
|
|
31838
32906
|
return null;
|
|
31839
32907
|
try {
|
|
31840
|
-
const pkg = JSON.parse(
|
|
32908
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf8"));
|
|
31841
32909
|
const raw = pkg.packageManager?.split("@")[0];
|
|
31842
32910
|
if (raw === "bun" || raw === "npm" || raw === "pnpm" || raw === "yarn")
|
|
31843
32911
|
return raw;
|
|
@@ -31845,13 +32913,13 @@ function packageManagerFromPackageJson(root2) {
|
|
|
31845
32913
|
return null;
|
|
31846
32914
|
}
|
|
31847
32915
|
function packageManagerFromLockfiles(root2) {
|
|
31848
|
-
if (
|
|
32916
|
+
if (existsSync24(join23(root2, "bun.lock")) || existsSync24(join23(root2, "bun.lockb")))
|
|
31849
32917
|
return "bun";
|
|
31850
|
-
if (
|
|
32918
|
+
if (existsSync24(join23(root2, "pnpm-lock.yaml")))
|
|
31851
32919
|
return "pnpm";
|
|
31852
|
-
if (
|
|
32920
|
+
if (existsSync24(join23(root2, "yarn.lock")))
|
|
31853
32921
|
return "yarn";
|
|
31854
|
-
if (
|
|
32922
|
+
if (existsSync24(join23(root2, "package-lock.json")))
|
|
31855
32923
|
return "npm";
|
|
31856
32924
|
return null;
|
|
31857
32925
|
}
|
|
@@ -31877,8 +32945,8 @@ function emptyBuckets() {
|
|
|
31877
32945
|
function classifySinglePath(input) {
|
|
31878
32946
|
const { relPath: relPath2, ctx, state, bucketCtx } = input;
|
|
31879
32947
|
const normalized = normalizeRelPath(relPath2);
|
|
31880
|
-
const abs =
|
|
31881
|
-
if (!
|
|
32948
|
+
const abs = join23(ctx.root, normalized);
|
|
32949
|
+
if (!existsSync24(abs)) {
|
|
31882
32950
|
state.missing++;
|
|
31883
32951
|
console.error(`validate changed: path not found: ${relPath2}`);
|
|
31884
32952
|
return;
|
|
@@ -32112,31 +33180,16 @@ function usage() {
|
|
|
32112
33180
|
Commands:
|
|
32113
33181
|
init [--force-hooks] [--skills] [--no-skills] [skills add flags…]
|
|
32114
33182
|
audit docs|self|skills [--strict] [--json] [--paths=a,b] [--only=rule]
|
|
32115
|
-
[--fix[=doc-meta|anchors]] [--dry-run]
|
|
33183
|
+
[--fix[=doc-meta|anchors|ssot]] [--dry-run]
|
|
32116
33184
|
build-plugin [path] [--check]
|
|
32117
33185
|
validate changed [paths…] [--staged] [--base <ref>]
|
|
32118
|
-
|
|
33186
|
+
catalog [--check] write or check .skeleton/catalog.md (gitignored)
|
|
32119
33187
|
customize resolve <slug> [--json]
|
|
32120
33188
|
hook customize (reads a host hook payload on stdin)
|
|
32121
33189
|
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 };
|
|
33190
|
+
references check [--json] [--strict]
|
|
33191
|
+
|
|
33192
|
+
Note: \`register\` was removed — add a source-of-truth marker to the file and run \`skeleton catalog\`.`);
|
|
32140
33193
|
}
|
|
32141
33194
|
function parseValidateChangedArgs(rest) {
|
|
32142
33195
|
const paths = [];
|
|
@@ -32180,19 +33233,12 @@ async function handleValidateChanged(argv) {
|
|
|
32180
33233
|
const { paths, staged, base } = parseValidateChangedArgs(argv);
|
|
32181
33234
|
return runValidateChanged({ paths, staged, base });
|
|
32182
33235
|
}
|
|
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;
|
|
33236
|
+
function handleRegister() {
|
|
33237
|
+
console.error("register: removed — add `<!-- source-of-truth: … -->` (or visible `source-of-truth:`) to the file, then run `skeleton catalog`.");
|
|
33238
|
+
return 1;
|
|
33239
|
+
}
|
|
33240
|
+
function handleCatalog(argv) {
|
|
33241
|
+
return runCatalogCli({ check: argv.includes("--check") });
|
|
32196
33242
|
}
|
|
32197
33243
|
function handleCustomizeResolve(argv) {
|
|
32198
33244
|
const slug2 = argv[0];
|
|
@@ -32214,7 +33260,7 @@ function handleHook(argv) {
|
|
|
32214
33260
|
usage();
|
|
32215
33261
|
return 1;
|
|
32216
33262
|
}
|
|
32217
|
-
process7.stdout.write(runCustomizeHook(
|
|
33263
|
+
process7.stdout.write(runCustomizeHook(readFileSync24(0, "utf8")));
|
|
32218
33264
|
return 0;
|
|
32219
33265
|
}
|
|
32220
33266
|
function handleInit(argv) {
|
|
@@ -32250,7 +33296,9 @@ async function dispatchCommand(argv) {
|
|
|
32250
33296
|
case "validate":
|
|
32251
33297
|
return rest[0] === "changed" ? handleValidateChanged(rest.slice(1)) : null;
|
|
32252
33298
|
case "register":
|
|
32253
|
-
return handleRegister(
|
|
33299
|
+
return handleRegister();
|
|
33300
|
+
case "catalog":
|
|
33301
|
+
return handleCatalog(rest);
|
|
32254
33302
|
case "customize":
|
|
32255
33303
|
return rest[0] === "resolve" ? handleCustomizeResolve(rest.slice(1)) : null;
|
|
32256
33304
|
case "hook":
|