@csark0812/skeleton 1.1.1 → 1.1.3

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.
@@ -3524,49 +3524,49 @@ var require_fast_uri = __commonJS((exports, module) => {
3524
3524
  schemelessOptions.skipEscape = true;
3525
3525
  return serialize(resolved, schemelessOptions);
3526
3526
  }
3527
- function resolveComponent(base, relative, options, skipNormalization) {
3527
+ function resolveComponent(base, relative2, options, skipNormalization) {
3528
3528
  const target = {};
3529
3529
  if (!skipNormalization) {
3530
3530
  base = parse(serialize(base, options), options);
3531
- relative = parse(serialize(relative, options), options);
3531
+ relative2 = parse(serialize(relative2, options), options);
3532
3532
  }
3533
3533
  options = options || {};
3534
- if (!options.tolerant && relative.scheme) {
3535
- target.scheme = relative.scheme;
3536
- target.userinfo = relative.userinfo;
3537
- target.host = relative.host;
3538
- target.port = relative.port;
3539
- target.path = removeDotSegments(relative.path || "");
3540
- target.query = relative.query;
3534
+ if (!options.tolerant && relative2.scheme) {
3535
+ target.scheme = relative2.scheme;
3536
+ target.userinfo = relative2.userinfo;
3537
+ target.host = relative2.host;
3538
+ target.port = relative2.port;
3539
+ target.path = removeDotSegments(relative2.path || "");
3540
+ target.query = relative2.query;
3541
3541
  } else {
3542
- if (relative.userinfo !== undefined || relative.host !== undefined || relative.port !== undefined) {
3543
- target.userinfo = relative.userinfo;
3544
- target.host = relative.host;
3545
- target.port = relative.port;
3546
- target.path = removeDotSegments(relative.path || "");
3547
- target.query = relative.query;
3542
+ if (relative2.userinfo !== undefined || relative2.host !== undefined || relative2.port !== undefined) {
3543
+ target.userinfo = relative2.userinfo;
3544
+ target.host = relative2.host;
3545
+ target.port = relative2.port;
3546
+ target.path = removeDotSegments(relative2.path || "");
3547
+ target.query = relative2.query;
3548
3548
  } else {
3549
- if (!relative.path) {
3549
+ if (!relative2.path) {
3550
3550
  target.path = base.path;
3551
- if (relative.query !== undefined) {
3552
- target.query = relative.query;
3551
+ if (relative2.query !== undefined) {
3552
+ target.query = relative2.query;
3553
3553
  } else {
3554
3554
  target.query = base.query;
3555
3555
  }
3556
3556
  } else {
3557
- if (relative.path[0] === "/") {
3558
- target.path = removeDotSegments(relative.path);
3557
+ if (relative2.path[0] === "/") {
3558
+ target.path = removeDotSegments(relative2.path);
3559
3559
  } else {
3560
3560
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
3561
- target.path = "/" + relative.path;
3561
+ target.path = "/" + relative2.path;
3562
3562
  } else if (!base.path) {
3563
- target.path = relative.path;
3563
+ target.path = relative2.path;
3564
3564
  } else {
3565
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
3565
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
3566
3566
  }
3567
3567
  target.path = removeDotSegments(target.path);
3568
3568
  }
3569
- target.query = relative.query;
3569
+ target.query = relative2.query;
3570
3570
  }
3571
3571
  target.userinfo = base.userinfo;
3572
3572
  target.host = base.host;
@@ -3574,7 +3574,7 @@ var require_fast_uri = __commonJS((exports, module) => {
3574
3574
  }
3575
3575
  target.scheme = base.scheme;
3576
3576
  }
3577
- target.fragment = relative.fragment;
3577
+ target.fragment = relative2.fragment;
3578
3578
  return target;
3579
3579
  }
3580
3580
  function equal(uriA, uriB, options) {
@@ -13237,14 +13237,75 @@ var require_public_api = __commonJS((exports) => {
13237
13237
  // src/hooks/customize-on-skill-read.ts
13238
13238
  import { readFileSync as readFileSync4 } from "node:fs";
13239
13239
 
13240
+ // src/audit/core/shared.ts
13241
+ var REGISTRY_REL_PATH = ".skeleton/registry.md";
13242
+ var REGISTRY_DIR_REL = ".skeleton";
13243
+ function normalizeRelPath(p) {
13244
+ return p.replace(/\\/g, "/");
13245
+ }
13246
+
13247
+ // src/audit/core/skill-roots.ts
13248
+ import { existsSync, readdirSync, readlinkSync, realpathSync } from "node:fs";
13249
+ import { join, relative } from "node:path";
13250
+ var FLAT_SKILL_DENYLIST = new Set([
13251
+ ".git",
13252
+ ".github",
13253
+ ".skeleton",
13254
+ ".cursor",
13255
+ ".claude",
13256
+ ".agents",
13257
+ ".codex",
13258
+ "docs",
13259
+ "refs",
13260
+ "scripts",
13261
+ "src",
13262
+ "dist",
13263
+ "node_modules",
13264
+ "templates",
13265
+ "fixtures",
13266
+ "schemas"
13267
+ ]);
13268
+ var NESTED_EXCLUDED_DIRS = new Set(["references", "_shared"]);
13269
+ var NESTED_SKILL_SLUG_RE = /(?:^|\/)\.(?:claude|agents)\/skills\/([a-z0-9-]+)\//;
13270
+ var FLAT_SKILL_REFERENCES_RE = /(?:^|\/)([a-z0-9-]+)\/references(?:\/|$)/;
13271
+ function slugFromSkillPath(relPath) {
13272
+ const normalized = normalizeRelPath(relPath);
13273
+ const nested = normalized.match(NESTED_SKILL_SLUG_RE);
13274
+ if (nested?.[1])
13275
+ return nested[1];
13276
+ if (normalized.endsWith("/SKILL.md")) {
13277
+ const parts = normalized.split("/");
13278
+ return parts.at(-2) ?? null;
13279
+ }
13280
+ return null;
13281
+ }
13282
+ function slugFromPath(filePath, workspaceRoot) {
13283
+ const normalized = normalizeRelPath(filePath);
13284
+ const nested = normalized.match(NESTED_SKILL_SLUG_RE);
13285
+ if (nested?.[1])
13286
+ return nested[1];
13287
+ if (normalized.endsWith("/SKILL.md")) {
13288
+ return slugFromSkillPath(normalized);
13289
+ }
13290
+ const flatRef = normalized.match(FLAT_SKILL_REFERENCES_RE);
13291
+ const flatSlug = flatRef?.[1];
13292
+ if (!flatSlug || FLAT_SKILL_DENYLIST.has(flatSlug))
13293
+ return null;
13294
+ if (workspaceRoot) {
13295
+ if (!existsSync(join(workspaceRoot, flatSlug, "SKILL.md")))
13296
+ return null;
13297
+ }
13298
+ return flatSlug;
13299
+ }
13300
+
13240
13301
  // src/customize/resolve.ts
13241
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
13242
- import { basename, join as join3, relative as relative2 } from "node:path";
13302
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
13303
+ import { basename, join as join4, relative as relative3 } from "node:path";
13243
13304
 
13244
13305
  // src/audit/config/load.ts
13245
13306
  var import_ajv = __toESM(require_ajv(), 1);
13246
- import { existsSync, readFileSync } from "node:fs";
13247
- import { dirname, join } from "node:path";
13307
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
13308
+ import { dirname, join as join2 } from "node:path";
13248
13309
  import { fileURLToPath } from "node:url";
13249
13310
 
13250
13311
  // node_modules/yaml/dist/index.js
@@ -13295,24 +13356,18 @@ var $visitAsync = visit.visitAsync;
13295
13356
 
13296
13357
  // src/audit/config/load.ts
13297
13358
  var SCHEMA_CANDIDATES = [
13298
- join(dirname(fileURLToPath(import.meta.url)), "../../../schemas/config.schema.json"),
13299
- join(dirname(fileURLToPath(import.meta.url)), "../schemas/config.schema.json"),
13300
- join(dirname(fileURLToPath(import.meta.url)), "../../schemas/config.schema.json")
13359
+ join2(dirname(fileURLToPath(import.meta.url)), "../../../schemas/config.schema.json"),
13360
+ join2(dirname(fileURLToPath(import.meta.url)), "../schemas/config.schema.json"),
13361
+ join2(dirname(fileURLToPath(import.meta.url)), "../../schemas/config.schema.json")
13301
13362
  ];
13302
13363
  function resolveSchemaPath() {
13303
13364
  for (const candidate of SCHEMA_CANDIDATES) {
13304
- if (existsSync(candidate))
13365
+ if (existsSync2(candidate))
13305
13366
  return candidate;
13306
13367
  }
13307
13368
  throw new Error("Missing schemas/config.schema.json in package");
13308
13369
  }
13309
- var BUILTIN_EXCLUDES = [
13310
- "node_modules/**",
13311
- ".git/**",
13312
- "dist/**",
13313
- "refs/**",
13314
- "_agent/**"
13315
- ];
13370
+ var BUILTIN_EXCLUDES = ["node_modules/**", ".git/**", "dist/**", "refs/**", "_agent/**"];
13316
13371
  var COVERAGE_BUILTIN_EXCLUDES = [
13317
13372
  ...BUILTIN_EXCLUDES,
13318
13373
  "**/__tests__/**",
@@ -13322,7 +13377,7 @@ var COVERAGE_BUILTIN_EXCLUDES = [
13322
13377
  function findRepoRoot(startDir = process.cwd()) {
13323
13378
  let dir = startDir;
13324
13379
  while (true) {
13325
- if (existsSync(join(dir, ".skeleton", "config.yaml")))
13380
+ if (existsSync2(join2(dir, ".skeleton", "config.yaml")))
13326
13381
  return dir;
13327
13382
  const parent = dirname(dir);
13328
13383
  if (parent === dir) {
@@ -13342,31 +13397,22 @@ function validateConfig(raw) {
13342
13397
  return raw;
13343
13398
  }
13344
13399
  function loadConfig(root) {
13345
- const configPath = join(root, ".skeleton", "config.yaml");
13346
- if (!existsSync(configPath)) {
13347
- throw new Error(`Missing ${join(".skeleton", "config.yaml")}`);
13400
+ const configPath = join2(root, ".skeleton", "config.yaml");
13401
+ if (!existsSync2(configPath)) {
13402
+ throw new Error(`Missing ${join2(".skeleton", "config.yaml")}`);
13348
13403
  }
13349
13404
  const raw = $parse(readFileSync(configPath, "utf8"));
13350
13405
  return validateConfig(raw);
13351
13406
  }
13352
13407
 
13353
13408
  // src/audit/core/registry.ts
13354
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
13355
- import { join as join2, relative, resolve } from "node:path";
13356
-
13357
- // src/audit/core/shared.ts
13358
- var REGISTRY_REL_PATH = ".skeleton/registry.md";
13359
- var REGISTRY_DIR_REL = ".skeleton";
13360
- function normalizeRelPath(p) {
13361
- return p.replace(/\\/g, "/");
13362
- }
13363
-
13364
- // src/audit/core/registry.ts
13409
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
13410
+ import { join as join3, relative as relative2, resolve } from "node:path";
13365
13411
  var REGISTRY_TABLE_ROW_RE = /^\|\s*[^|]+\|\s*\[[^\]]*\]\(([^)]+)\)\s*\|/;
13366
13412
  var REGISTRY_TABLE_HEADER_RE = /\|\s*Topic\s*\|\s*Canonical file\s*\|/i;
13367
13413
  function parseRegistry(root) {
13368
- const abs = join2(root, REGISTRY_REL_PATH);
13369
- if (!existsSync2(abs)) {
13414
+ const abs = join3(root, REGISTRY_REL_PATH);
13415
+ if (!existsSync3(abs)) {
13370
13416
  return { paths: [], hasTableHeader: false };
13371
13417
  }
13372
13418
  const content = readFileSync2(abs, "utf8");
@@ -13380,8 +13426,8 @@ function parseRegistry(root) {
13380
13426
  const linkTarget = match[1].trim();
13381
13427
  if (linkTarget.startsWith("#"))
13382
13428
  continue;
13383
- const resolved = resolve(join2(root, REGISTRY_DIR_REL), linkTarget);
13384
- paths.push(normalizeRelPath(relative(root, resolved)));
13429
+ const resolved = resolve(join3(root, REGISTRY_DIR_REL), linkTarget);
13430
+ paths.push(normalizeRelPath(relative2(root, resolved)));
13385
13431
  }
13386
13432
  return { paths: [...new Set(paths)], hasTableHeader };
13387
13433
  }
@@ -13391,15 +13437,15 @@ function parseRegistryPaths(root) {
13391
13437
 
13392
13438
  // src/customize/resolve.ts
13393
13439
  function customizeDir(root) {
13394
- return join3(root, REGISTRY_DIR_REL, "customize");
13440
+ return join4(root, REGISTRY_DIR_REL, "customize");
13395
13441
  }
13396
13442
  function customizePathForSlug(root, slug) {
13397
- return join3(customizeDir(root), `${slug}.md`);
13443
+ return join4(customizeDir(root), `${slug}.md`);
13398
13444
  }
13399
13445
  function findCustomizeViaRegistry(root, slug) {
13400
13446
  for (const rel of parseRegistryPaths(root)) {
13401
13447
  const expected = `${REGISTRY_DIR_REL}/customize/${slug}.md`;
13402
- if (normalizeRelPath(rel) === expected && existsSync3(join3(root, rel))) {
13448
+ if (normalizeRelPath(rel) === expected && existsSync4(join4(root, rel))) {
13403
13449
  return rel;
13404
13450
  }
13405
13451
  }
@@ -13407,15 +13453,15 @@ function findCustomizeViaRegistry(root, slug) {
13407
13453
  }
13408
13454
  function resolveSlugFile(root, slug) {
13409
13455
  const direct = customizePathForSlug(root, slug);
13410
- if (existsSync3(direct)) {
13456
+ if (existsSync4(direct)) {
13411
13457
  return {
13412
13458
  content: readFileSync3(direct, "utf8"),
13413
- path: normalizeRelPath(relative2(root, direct))
13459
+ path: normalizeRelPath(relative3(root, direct))
13414
13460
  };
13415
13461
  }
13416
13462
  const registryPath = findCustomizeViaRegistry(root, slug);
13417
13463
  if (registryPath) {
13418
- const abs = join3(root, registryPath);
13464
+ const abs = join4(root, registryPath);
13419
13465
  return {
13420
13466
  content: readFileSync3(abs, "utf8"),
13421
13467
  path: registryPath
@@ -13439,11 +13485,11 @@ function readAlwaysInclude(root, basenames, skipBasename) {
13439
13485
  const file = basename(name);
13440
13486
  if (skipBasename && file === skipBasename)
13441
13487
  continue;
13442
- const abs = join3(dir, file);
13443
- if (!existsSync3(abs))
13488
+ const abs = join4(dir, file);
13489
+ if (!existsSync4(abs))
13444
13490
  continue;
13445
13491
  parts.push(readFileSync3(abs, "utf8").trimEnd());
13446
- paths.push(normalizeRelPath(relative2(root, abs)));
13492
+ paths.push(normalizeRelPath(relative3(root, abs)));
13447
13493
  }
13448
13494
  return { parts, paths };
13449
13495
  }
@@ -13466,11 +13512,11 @@ function resolveCustomize(root, slug) {
13466
13512
  }
13467
13513
  return {
13468
13514
  slug,
13469
- content: parts.join(`
13515
+ content: `${parts.join(`
13470
13516
 
13471
13517
  ---
13472
13518
 
13473
- `) + `
13519
+ `)}
13474
13520
  `,
13475
13521
  path: slugFile.path ?? always.paths[0] ?? null,
13476
13522
  included
@@ -13481,41 +13527,6 @@ function resolveCustomizeFromRoot(slug, startDir) {
13481
13527
  return resolveCustomize(root, slug);
13482
13528
  }
13483
13529
 
13484
- // src/audit/core/skill-roots.ts
13485
- var FLAT_SKILL_DENYLIST = new Set([
13486
- ".git",
13487
- ".github",
13488
- ".skeleton",
13489
- ".cursor",
13490
- ".claude",
13491
- ".agents",
13492
- ".codex",
13493
- "docs",
13494
- "refs",
13495
- "scripts",
13496
- "src",
13497
- "dist",
13498
- "node_modules",
13499
- "templates",
13500
- "fixtures",
13501
- "schemas"
13502
- ]);
13503
- var NESTED_EXCLUDED_DIRS = new Set(["references", "_shared"]);
13504
- function slugFromSkillPath(relPath) {
13505
- const normalized = normalizeRelPath(relPath);
13506
- if (normalized.endsWith("/SKILL.md")) {
13507
- const parts = normalized.split("/");
13508
- return parts.at(-2) ?? null;
13509
- }
13510
- return null;
13511
- }
13512
- function slugFromPath(filePath) {
13513
- const normalized = normalizeRelPath(filePath);
13514
- if (!normalized.endsWith("/SKILL.md"))
13515
- return null;
13516
- return slugFromSkillPath(normalized);
13517
- }
13518
-
13519
13530
  // src/hooks/customize-on-skill-read.ts
13520
13531
  function parsePayload(raw) {
13521
13532
  if (!raw.trim())
@@ -13547,7 +13558,7 @@ function extractSkillSlug(payload) {
13547
13558
  }
13548
13559
  const path = extractPath(payload);
13549
13560
  if (path)
13550
- return slugFromPath(path);
13561
+ return slugFromPath(path, process.cwd());
13551
13562
  return null;
13552
13563
  }
13553
13564
  function cursorResponse(content) {
@@ -13579,11 +13590,6 @@ function main() {
13579
13590
  try {
13580
13591
  const raw = readFileSync4(0, "utf8");
13581
13592
  const payload = parsePayload(raw);
13582
- const path = extractPath(payload);
13583
- if (path && !path.endsWith("/SKILL.md")) {
13584
- process.stdout.write("{}");
13585
- return;
13586
- }
13587
13593
  const slug = extractSkillSlug(payload);
13588
13594
  if (!slug) {
13589
13595
  process.stdout.write("{}");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@csark0812/skeleton",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "SSOT audit CLI for agent harness repos",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  "templates",
12
12
  "schemas"
13
13
  ],
14
+ "license": "MIT",
14
15
  "engines": {
15
16
  "node": ">=22"
16
17
  },
@@ -20,12 +21,21 @@
20
21
  "test": "bun test",
21
22
  "test:audit": "bun test src/audit/__tests__",
22
23
  "test:cli": "bun test src/__tests__/cli",
24
+ "test:coverage": "bun test --coverage",
25
+ "typecheck": "tsc -p tsconfig.json --noEmit",
26
+ "lint": "biome check .",
27
+ "format": "biome format --write .",
28
+ "format:check": "biome check --formatter-enabled=true --linter-enabled=false .",
29
+ "audit:deps": "bun audit",
23
30
  "validate:changed": "bun src/cli.ts validate changed",
24
31
  "validate:ci": "bun src/cli.ts validate changed --base origin/main",
25
32
  "audit:docs": "bun src/cli.ts audit docs",
26
33
  "audit:skills": "bun src/cli.ts audit skills",
27
34
  "audit:self": "bun src/cli.ts audit self",
28
- "prepack": "bun test && bun run build"
35
+ "check": "bun run lint && bun test && bun run typecheck && bun run build && bun run audit:self",
36
+ "start": "bun src/cli.ts --help",
37
+ "dev": "bun src/cli.ts --help",
38
+ "prepack": "bun test && bun run typecheck && bun run build"
29
39
  },
30
40
  "dependencies": {
31
41
  "ajv": "^8.17.1",
@@ -37,6 +47,7 @@
37
47
  "yaml": "^2.8.0"
38
48
  },
39
49
  "devDependencies": {
50
+ "@biomejs/biome": "^2.5.3",
40
51
  "@types/bun": "^1.3.8",
41
52
  "@types/github-slugger": "^2.0.0",
42
53
  "typescript": "~5.8.3"
@@ -24,9 +24,14 @@
24
24
  "type": "array",
25
25
  "items": { "type": "string" }
26
26
  },
27
- "retiredSkills": {
27
+ "retiredSkills": {
28
28
  "type": "array",
29
29
  "items": { "type": "string", "pattern": "^[a-z0-9-]+$" }
30
+ },
31
+ "nonPublicSkills": {
32
+ "type": "array",
33
+ "items": { "type": "string", "pattern": "^[a-z0-9-]+$" },
34
+ "description": "Skill slugs that exist on disk but must not appear in README Taxonomy (consumer-internal skills)"
30
35
  }
31
36
  }
32
37
  },