@promptscript/cli 1.12.1 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -4,11 +4,20 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __esm = (fn, res) => function __init() {
8
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ var __esm = (fn, res, err) => function __init() {
8
+ if (err) throw err[0];
9
+ try {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ } catch (e) {
12
+ throw err = [e], e;
13
+ }
9
14
  };
10
15
  var __commonJS = (cb, mod) => function __require() {
11
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
+ try {
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18
+ } catch (e) {
19
+ throw mod = 0, e;
20
+ }
12
21
  };
13
22
  var __export = (target, all) => {
14
23
  for (var name in all)
@@ -11760,6 +11769,14 @@ var init_base_formatter = __esm({
11760
11769
  referencesMode() {
11761
11770
  return "none";
11762
11771
  }
11772
+ /**
11773
+ * Default pass-through for injected skill content. Formatters whose target
11774
+ * tools restrict skill frontmatter (e.g. Factory AI) override this hook to
11775
+ * filter unsupported fields before the compiler writes the file.
11776
+ */
11777
+ transformInjectedSkillContent(content) {
11778
+ return content;
11779
+ }
11763
11780
  /**
11764
11781
  * Generate a provenance comment for a reference file.
11765
11782
  */
@@ -16365,6 +16382,24 @@ ${lines.join("\n")}
16365
16382
  }
16366
16383
  return filtered;
16367
16384
  }
16385
+ /**
16386
+ * Filter the frontmatter of an externally-supplied SKILL.md file (such as
16387
+ * the bundled PromptScript skill injected by the compiler) so it only
16388
+ * contains fields Factory AI recognises. The body is preserved verbatim.
16389
+ * Files without a YAML frontmatter block are returned unchanged.
16390
+ */
16391
+ transformInjectedSkillContent(content) {
16392
+ if (!content.startsWith("---")) return content;
16393
+ const closing = content.indexOf("\n---", 3);
16394
+ if (closing === -1) return content;
16395
+ const rawFrontmatter = content.slice(4, closing);
16396
+ const body = content.slice(closing + 4);
16397
+ const filteredLines = this.filterFactoryFrontmatter(rawFrontmatter);
16398
+ const filteredFrontmatter = filteredLines.join("\n");
16399
+ return `---
16400
+ ${filteredFrontmatter}
16401
+ ---${body}`;
16402
+ }
16368
16403
  };
16369
16404
  }
16370
16405
  });
@@ -19863,9 +19898,9 @@ var require_dist = __commonJS({
19863
19898
  }
19864
19899
  });
19865
19900
 
19866
- // node_modules/.pnpm/toad-cache@3.7.0/node_modules/toad-cache/dist/toad-cache.cjs
19901
+ // node_modules/.pnpm/toad-cache@3.7.1/node_modules/toad-cache/dist/toad-cache.cjs
19867
19902
  var require_toad_cache = __commonJS({
19868
- "node_modules/.pnpm/toad-cache@3.7.0/node_modules/toad-cache/dist/toad-cache.cjs"(exports) {
19903
+ "node_modules/.pnpm/toad-cache@3.7.1/node_modules/toad-cache/dist/toad-cache.cjs"(exports) {
19869
19904
  "use strict";
19870
19905
  var FifoMap = class {
19871
19906
  constructor(max = 1e3, ttlInMsecs = 0) {
@@ -19976,6 +20011,155 @@ var require_toad_cache = __commonJS({
19976
20011
  this.last = item;
19977
20012
  }
19978
20013
  };
20014
+ var FifoObject = class {
20015
+ constructor(max = 1e3, ttlInMsecs = 0) {
20016
+ if (isNaN(max) || max < 0) {
20017
+ throw new Error("Invalid max value");
20018
+ }
20019
+ if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
20020
+ throw new Error("Invalid ttl value");
20021
+ }
20022
+ this.first = null;
20023
+ this.items = /* @__PURE__ */ Object.create(null);
20024
+ this.last = null;
20025
+ this.size = 0;
20026
+ this.max = max;
20027
+ this.ttl = ttlInMsecs;
20028
+ }
20029
+ clear() {
20030
+ this.items = /* @__PURE__ */ Object.create(null);
20031
+ this.first = null;
20032
+ this.last = null;
20033
+ this.size = 0;
20034
+ }
20035
+ delete(key) {
20036
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20037
+ const deletedItem = this.items[key];
20038
+ delete this.items[key];
20039
+ this.size--;
20040
+ if (deletedItem.prev !== null) {
20041
+ deletedItem.prev.next = deletedItem.next;
20042
+ }
20043
+ if (deletedItem.next !== null) {
20044
+ deletedItem.next.prev = deletedItem.prev;
20045
+ }
20046
+ if (this.first === deletedItem) {
20047
+ this.first = deletedItem.next;
20048
+ }
20049
+ if (this.last === deletedItem) {
20050
+ this.last = deletedItem.prev;
20051
+ }
20052
+ }
20053
+ }
20054
+ deleteMany(keys) {
20055
+ for (var i = 0; i < keys.length; i++) {
20056
+ this.delete(keys[i]);
20057
+ }
20058
+ }
20059
+ evict() {
20060
+ if (this.size > 0) {
20061
+ const item = this.first;
20062
+ delete this.items[item.key];
20063
+ if (--this.size === 0) {
20064
+ this.first = null;
20065
+ this.last = null;
20066
+ } else {
20067
+ this.first = item.next;
20068
+ this.first.prev = null;
20069
+ }
20070
+ }
20071
+ }
20072
+ expiresAt(key) {
20073
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20074
+ return this.items[key].expiry;
20075
+ }
20076
+ }
20077
+ get(key) {
20078
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20079
+ const item = this.items[key];
20080
+ if (this.ttl > 0 && item.expiry <= Date.now()) {
20081
+ this.delete(key);
20082
+ return;
20083
+ }
20084
+ return item.value;
20085
+ }
20086
+ }
20087
+ getMany(keys) {
20088
+ const result = [];
20089
+ for (var i = 0; i < keys.length; i++) {
20090
+ result.push(this.get(keys[i]));
20091
+ }
20092
+ return result;
20093
+ }
20094
+ keys() {
20095
+ return Object.keys(this.items);
20096
+ }
20097
+ set(key, value) {
20098
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20099
+ const item2 = this.items[key];
20100
+ item2.value = value;
20101
+ item2.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
20102
+ return;
20103
+ }
20104
+ if (this.max > 0 && this.size === this.max) {
20105
+ this.evict();
20106
+ }
20107
+ const item = {
20108
+ expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
20109
+ key,
20110
+ prev: this.last,
20111
+ next: null,
20112
+ value
20113
+ };
20114
+ this.items[key] = item;
20115
+ if (++this.size === 1) {
20116
+ this.first = item;
20117
+ } else {
20118
+ this.last.next = item;
20119
+ }
20120
+ this.last = item;
20121
+ }
20122
+ };
20123
+ var HitStatisticsRecord = class {
20124
+ constructor() {
20125
+ this.records = {};
20126
+ }
20127
+ initForCache(cacheId, currentTimeStamp) {
20128
+ this.records[cacheId] = {
20129
+ [currentTimeStamp]: {
20130
+ cacheSize: 0,
20131
+ hits: 0,
20132
+ falsyHits: 0,
20133
+ emptyHits: 0,
20134
+ misses: 0,
20135
+ expirations: 0,
20136
+ evictions: 0,
20137
+ invalidateOne: 0,
20138
+ invalidateAll: 0,
20139
+ sets: 0
20140
+ }
20141
+ };
20142
+ }
20143
+ resetForCache(cacheId) {
20144
+ for (let key of Object.keys(this.records[cacheId])) {
20145
+ this.records[cacheId][key] = {
20146
+ cacheSize: 0,
20147
+ hits: 0,
20148
+ falsyHits: 0,
20149
+ emptyHits: 0,
20150
+ misses: 0,
20151
+ expirations: 0,
20152
+ evictions: 0,
20153
+ invalidateOne: 0,
20154
+ invalidateAll: 0,
20155
+ sets: 0
20156
+ };
20157
+ }
20158
+ }
20159
+ getStatistics() {
20160
+ return this.records;
20161
+ }
20162
+ };
19979
20163
  var LruMap = class {
19980
20164
  constructor(max = 1e3, ttlInMsecs = 0) {
19981
20165
  if (isNaN(max) || max < 0) {
@@ -20244,46 +20428,6 @@ var require_toad_cache = __commonJS({
20244
20428
  this.last = item;
20245
20429
  }
20246
20430
  };
20247
- var HitStatisticsRecord = class {
20248
- constructor() {
20249
- this.records = {};
20250
- }
20251
- initForCache(cacheId, currentTimeStamp) {
20252
- this.records[cacheId] = {
20253
- [currentTimeStamp]: {
20254
- cacheSize: 0,
20255
- hits: 0,
20256
- falsyHits: 0,
20257
- emptyHits: 0,
20258
- misses: 0,
20259
- expirations: 0,
20260
- evictions: 0,
20261
- invalidateOne: 0,
20262
- invalidateAll: 0,
20263
- sets: 0
20264
- }
20265
- };
20266
- }
20267
- resetForCache(cacheId) {
20268
- for (let key of Object.keys(this.records[cacheId])) {
20269
- this.records[cacheId][key] = {
20270
- cacheSize: 0,
20271
- hits: 0,
20272
- falsyHits: 0,
20273
- emptyHits: 0,
20274
- misses: 0,
20275
- expirations: 0,
20276
- evictions: 0,
20277
- invalidateOne: 0,
20278
- invalidateAll: 0,
20279
- sets: 0
20280
- };
20281
- }
20282
- }
20283
- getStatistics() {
20284
- return this.records;
20285
- }
20286
- };
20287
20431
  function getTimestamp(date) {
20288
20432
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
20289
20433
  }
@@ -20425,115 +20569,6 @@ var require_toad_cache = __commonJS({
20425
20569
  this.hitStatistics.addMiss();
20426
20570
  }
20427
20571
  };
20428
- var FifoObject = class {
20429
- constructor(max = 1e3, ttlInMsecs = 0) {
20430
- if (isNaN(max) || max < 0) {
20431
- throw new Error("Invalid max value");
20432
- }
20433
- if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
20434
- throw new Error("Invalid ttl value");
20435
- }
20436
- this.first = null;
20437
- this.items = /* @__PURE__ */ Object.create(null);
20438
- this.last = null;
20439
- this.size = 0;
20440
- this.max = max;
20441
- this.ttl = ttlInMsecs;
20442
- }
20443
- clear() {
20444
- this.items = /* @__PURE__ */ Object.create(null);
20445
- this.first = null;
20446
- this.last = null;
20447
- this.size = 0;
20448
- }
20449
- delete(key) {
20450
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20451
- const deletedItem = this.items[key];
20452
- delete this.items[key];
20453
- this.size--;
20454
- if (deletedItem.prev !== null) {
20455
- deletedItem.prev.next = deletedItem.next;
20456
- }
20457
- if (deletedItem.next !== null) {
20458
- deletedItem.next.prev = deletedItem.prev;
20459
- }
20460
- if (this.first === deletedItem) {
20461
- this.first = deletedItem.next;
20462
- }
20463
- if (this.last === deletedItem) {
20464
- this.last = deletedItem.prev;
20465
- }
20466
- }
20467
- }
20468
- deleteMany(keys) {
20469
- for (var i = 0; i < keys.length; i++) {
20470
- this.delete(keys[i]);
20471
- }
20472
- }
20473
- evict() {
20474
- if (this.size > 0) {
20475
- const item = this.first;
20476
- delete this.items[item.key];
20477
- if (--this.size === 0) {
20478
- this.first = null;
20479
- this.last = null;
20480
- } else {
20481
- this.first = item.next;
20482
- this.first.prev = null;
20483
- }
20484
- }
20485
- }
20486
- expiresAt(key) {
20487
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20488
- return this.items[key].expiry;
20489
- }
20490
- }
20491
- get(key) {
20492
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20493
- const item = this.items[key];
20494
- if (this.ttl > 0 && item.expiry <= Date.now()) {
20495
- this.delete(key);
20496
- return;
20497
- }
20498
- return item.value;
20499
- }
20500
- }
20501
- getMany(keys) {
20502
- const result = [];
20503
- for (var i = 0; i < keys.length; i++) {
20504
- result.push(this.get(keys[i]));
20505
- }
20506
- return result;
20507
- }
20508
- keys() {
20509
- return Object.keys(this.items);
20510
- }
20511
- set(key, value) {
20512
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20513
- const item2 = this.items[key];
20514
- item2.value = value;
20515
- item2.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
20516
- return;
20517
- }
20518
- if (this.max > 0 && this.size === this.max) {
20519
- this.evict();
20520
- }
20521
- const item = {
20522
- expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
20523
- key,
20524
- prev: this.last,
20525
- next: null,
20526
- value
20527
- };
20528
- this.items[key] = item;
20529
- if (++this.size === 1) {
20530
- this.first = item;
20531
- } else {
20532
- this.last.next = item;
20533
- }
20534
- this.last = item;
20535
- }
20536
- };
20537
20572
  exports.Fifo = FifoObject;
20538
20573
  exports.FifoMap = FifoMap;
20539
20574
  exports.FifoObject = FifoObject;
@@ -20546,9 +20581,9 @@ var require_toad_cache = __commonJS({
20546
20581
  }
20547
20582
  });
20548
20583
 
20549
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/LocalStore.js
20584
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/LocalStore.js
20550
20585
  var require_LocalStore = __commonJS({
20551
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/LocalStore.js"(exports, module) {
20586
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/LocalStore.js"(exports, module) {
20552
20587
  "use strict";
20553
20588
  var { LruMap: Lru } = require_toad_cache();
20554
20589
  function LocalStore(continueExceeding, exponentialBackoff, cache = 5e3) {
@@ -20589,9 +20624,9 @@ var require_LocalStore = __commonJS({
20589
20624
  }
20590
20625
  });
20591
20626
 
20592
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/RedisStore.js
20627
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/RedisStore.js
20593
20628
  var require_RedisStore = __commonJS({
20594
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/RedisStore.js"(exports, module) {
20629
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/RedisStore.js"(exports, module) {
20595
20630
  "use strict";
20596
20631
  var lua = `
20597
20632
  -- Key to operate on
@@ -20647,9 +20682,9 @@ var require_RedisStore = __commonJS({
20647
20682
  }
20648
20683
  });
20649
20684
 
20650
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/index.js
20685
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/index.js
20651
20686
  var require_rate_limit = __commonJS({
20652
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/index.js"(exports, module) {
20687
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/index.js"(exports, module) {
20653
20688
  "use strict";
20654
20689
  var fp = require_plugin();
20655
20690
  var { parse: parse2, format: format2 } = require_dist();
@@ -20717,7 +20752,7 @@ var require_rate_limit = __commonJS({
20717
20752
  globalParams.timeWindow = defaultTimeWindow;
20718
20753
  }
20719
20754
  globalParams.hook = settings.hook || defaultHook;
20720
- globalParams.allowList = settings.allowList || settings.whitelist || null;
20755
+ globalParams.allowList = settings.allowList || null;
20721
20756
  globalParams.ban = Number.isFinite(settings.ban) && settings.ban >= 0 ? Math.trunc(settings.ban) : -1;
20722
20757
  globalParams.onBanReach = typeof settings.onBanReach === "function" ? settings.onBanReach : defaultOnFn;
20723
20758
  globalParams.onExceeding = typeof settings.onExceeding === "function" ? settings.onExceeding : defaultOnFn;
@@ -20847,9 +20882,9 @@ var require_rate_limit = __commonJS({
20847
20882
  let ttl = 0;
20848
20883
  let ttlInSeconds = 0;
20849
20884
  try {
20850
- const res = await new Promise((resolve21, reject) => {
20885
+ const res = await new Promise((resolve22, reject) => {
20851
20886
  store.incr(key, (err, res2) => {
20852
- err ? reject(err) : resolve21(res2);
20887
+ err ? reject(err) : resolve22(res2);
20853
20888
  }, timeWindow, max);
20854
20889
  });
20855
20890
  current = res.current;
@@ -20956,12 +20991,12 @@ var init_health = __esm({
20956
20991
 
20957
20992
  // packages/server/src/source-dirs.ts
20958
20993
  import { readFile as readFile24 } from "fs/promises";
20959
- import { join as join21, dirname as dirname12 } from "path";
20994
+ import { join as join23, dirname as dirname14 } from "path";
20960
20995
  import { parse as parseYaml13 } from "yaml";
20961
20996
  async function readProjectConfig(workspace) {
20962
20997
  for (const filename of CONFIG_FILENAMES) {
20963
20998
  try {
20964
- const raw = await readFile24(join21(workspace, filename), "utf-8");
20999
+ const raw = await readFile24(join23(workspace, filename), "utf-8");
20965
21000
  const config = parseYaml13(raw);
20966
21001
  if (config) return config;
20967
21002
  } catch {
@@ -20972,10 +21007,10 @@ async function readProjectConfig(workspace) {
20972
21007
  async function resolveSourceDir(workspace) {
20973
21008
  for (const filename of CONFIG_FILENAMES) {
20974
21009
  try {
20975
- const raw = await readFile24(join21(workspace, filename), "utf-8");
21010
+ const raw = await readFile24(join23(workspace, filename), "utf-8");
20976
21011
  const config = parseYaml13(raw);
20977
21012
  if (config?.input?.entry) {
20978
- return dirname12(config.input.entry);
21013
+ return dirname14(config.input.entry);
20979
21014
  }
20980
21015
  } catch {
20981
21016
  }
@@ -20989,9 +21024,9 @@ async function resolveFileGlobs(workspace) {
20989
21024
  async function resolveWatchPaths(workspace) {
20990
21025
  const sourceDir = await resolveSourceDir(workspace);
20991
21026
  return [
20992
- join21(workspace, sourceDir),
20993
- join21(workspace, "promptscript.yaml"),
20994
- join21(workspace, "promptscript.yml")
21027
+ join23(workspace, sourceDir),
21028
+ join23(workspace, "promptscript.yaml"),
21029
+ join23(workspace, "promptscript.yml")
20995
21030
  ];
20996
21031
  }
20997
21032
  var DEFAULT_SOURCE_DIR, CONFIG_FILENAMES;
@@ -21018,13 +21053,13 @@ var init_config2 = __esm({
21018
21053
  });
21019
21054
 
21020
21055
  // packages/server/src/path-guard.ts
21021
- import { resolve as resolve20, relative as relative4, isAbsolute as isAbsolute6 } from "path";
21056
+ import { resolve as resolve21, relative as relative4, isAbsolute as isAbsolute6 } from "path";
21022
21057
  function resolveSafePath(workspace, requestedPath) {
21023
21058
  const decoded = decodeURIComponent(requestedPath);
21024
21059
  if (isAbsolute6(decoded)) {
21025
21060
  throw new PathTraversalError(requestedPath);
21026
21061
  }
21027
- const resolved = resolve20(workspace, decoded);
21062
+ const resolved = resolve21(workspace, decoded);
21028
21063
  const rel = relative4(workspace, resolved);
21029
21064
  if (rel.startsWith("..") || isAbsolute6(rel)) {
21030
21065
  throw new PathTraversalError(requestedPath);
@@ -21046,7 +21081,7 @@ var init_path_guard = __esm({
21046
21081
 
21047
21082
  // packages/server/src/routes/files.ts
21048
21083
  import { readFile as readFile25, writeFile as writeFile13, unlink as unlink2, stat as stat3, mkdir as mkdir10 } from "fs/promises";
21049
- import { dirname as dirname13 } from "path";
21084
+ import { dirname as dirname15 } from "path";
21050
21085
  import fg from "fast-glob";
21051
21086
  function registerRoutes(app, workspace, readOnly) {
21052
21087
  app.get("/api/files", async () => {
@@ -21106,7 +21141,7 @@ function registerRoutes(app, workspace, readOnly) {
21106
21141
  return reply.status(409).send({ error: "File already exists" });
21107
21142
  } catch {
21108
21143
  }
21109
- await mkdir10(dirname13(resolved), { recursive: true });
21144
+ await mkdir10(dirname15(resolved), { recursive: true });
21110
21145
  await writeFile13(resolved, request.body.content, "utf-8");
21111
21146
  return reply.status(201).send({ path: filePath, status: "created" });
21112
21147
  } catch (err) {
@@ -21332,14 +21367,14 @@ init_src();
21332
21367
  init_init();
21333
21368
  import { Command } from "commander";
21334
21369
  import { fileURLToPath as fileURLToPath4 } from "url";
21335
- import { dirname as dirname14 } from "path";
21370
+ import { dirname as dirname16 } from "path";
21336
21371
 
21337
21372
  // packages/cli/src/commands/compile.ts
21338
21373
  init_src();
21339
- import { resolve as resolve7, dirname as dirname8, isAbsolute as isAbsolute5 } from "path";
21374
+ import { resolve as resolve8, dirname as dirname9, isAbsolute as isAbsolute5 } from "path";
21340
21375
  import { fileURLToPath as fileURLToPath2 } from "url";
21341
21376
  import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile12 } from "fs/promises";
21342
- import { existsSync as existsSync11 } from "fs";
21377
+ import { existsSync as existsSync12 } from "fs";
21343
21378
  import chokidar from "chokidar";
21344
21379
 
21345
21380
  // packages/cli/src/config/loader.ts
@@ -21403,6 +21438,56 @@ async function loadConfig(customPath) {
21403
21438
 
21404
21439
  // packages/cli/src/commands/compile.ts
21405
21440
  init_loader();
21441
+
21442
+ // packages/cli/src/prettier/post-format.ts
21443
+ import { resolve as resolve4 } from "path";
21444
+ var MARKDOWN_RE = /\.(md|mdx|markdown)$/i;
21445
+ async function postFormatWithPrettier(outputs, projectRoot, logger) {
21446
+ let prettier;
21447
+ try {
21448
+ prettier = await import("prettier");
21449
+ } catch {
21450
+ logger.verbose("Prettier not available; skipping markdown post-format.");
21451
+ return;
21452
+ }
21453
+ const queue = [];
21454
+ for (const output of outputs.values()) {
21455
+ collectOutputs(output, queue);
21456
+ }
21457
+ for (const output of queue) {
21458
+ if (!MARKDOWN_RE.test(output.path)) continue;
21459
+ const absPath = resolve4(projectRoot, output.path);
21460
+ let config = null;
21461
+ try {
21462
+ config = await prettier.resolveConfig(absPath);
21463
+ } catch (err) {
21464
+ logger.verbose(
21465
+ `Could not resolve Prettier config for ${output.path}: ${err instanceof Error ? err.message : String(err)}`
21466
+ );
21467
+ }
21468
+ try {
21469
+ output.content = await prettier.format(output.content, {
21470
+ ...config ?? {},
21471
+ filepath: absPath,
21472
+ parser: "markdown"
21473
+ });
21474
+ } catch (err) {
21475
+ logger.verbose(
21476
+ `Prettier rejected ${output.path}: ${err instanceof Error ? err.message : String(err)}`
21477
+ );
21478
+ }
21479
+ }
21480
+ }
21481
+ function collectOutputs(output, into) {
21482
+ into.push(output);
21483
+ if (output.additionalFiles) {
21484
+ for (const child of output.additionalFiles) {
21485
+ collectOutputs(child, into);
21486
+ }
21487
+ }
21488
+ }
21489
+
21490
+ // packages/cli/src/commands/compile.ts
21406
21491
  init_console();
21407
21492
 
21408
21493
  // packages/compiler/src/compiler.ts
@@ -21419,7 +21504,7 @@ import { basename as basename11, dirname as dirname7, join as join8 } from "path
21419
21504
  // packages/resolver/src/loader.ts
21420
21505
  init_src();
21421
21506
  import { readFile as readFile7 } from "fs/promises";
21422
- import { resolve as resolve4, dirname as dirname5, basename as basename7, isAbsolute as isAbsolute2, relative } from "path";
21507
+ import { resolve as resolve5, dirname as dirname5, basename as basename7, isAbsolute as isAbsolute2, relative } from "path";
21423
21508
 
21424
21509
  // packages/resolver/src/alias-resolver.ts
21425
21510
  init_src();
@@ -21509,8 +21594,8 @@ var FileLoader = class {
21509
21594
  options;
21510
21595
  constructor(options) {
21511
21596
  this.registryPath = options.registryPath;
21512
- this.localPath = resolve4(options.localPath ?? process.cwd());
21513
- this.projectRoot = resolve4(
21597
+ this.localPath = resolve5(options.localPath ?? process.cwd());
21598
+ this.projectRoot = resolve5(
21514
21599
  options.projectRoot ?? (basename7(this.localPath) === ".promptscript" ? dirname5(this.localPath) : this.localPath)
21515
21600
  );
21516
21601
  this.options = options;
@@ -21553,11 +21638,11 @@ var FileLoader = class {
21553
21638
  const namespace = match[1];
21554
21639
  const segments = match[2];
21555
21640
  const fileName2 = segments.endsWith(".prs") || segments.endsWith(".md") ? segments : `${segments}.prs`;
21556
- return resolve4(this.registryPath, `@${namespace}`, fileName2);
21641
+ return resolve5(this.registryPath, `@${namespace}`, fileName2);
21557
21642
  }
21558
21643
  }
21559
21644
  const fileName = path.endsWith(".prs") || path.endsWith(".md") ? path : `${path}.prs`;
21560
- return resolve4(this.localPath, fileName);
21645
+ return resolve5(this.localPath, fileName);
21561
21646
  }
21562
21647
  /**
21563
21648
  * Resolve a PathReference to an absolute path.
@@ -21570,7 +21655,7 @@ var FileLoader = class {
21570
21655
  if (ref.isRelative) {
21571
21656
  const dir = dirname5(fromFile);
21572
21657
  const rawPath = ref.raw.endsWith(".prs") || ref.raw.endsWith(".md") ? ref.raw : `${ref.raw}.prs`;
21573
- const resolved = resolve4(dir, rawPath);
21658
+ const resolved = resolve5(dir, rawPath);
21574
21659
  const rel = relative(this.projectRoot, resolved);
21575
21660
  if (rel.startsWith("..") || isAbsolute2(rel)) {
21576
21661
  throw new Error(`Path traversal outside project root is not allowed: ${ref.raw}`);
@@ -22511,7 +22596,7 @@ function uniqueConcat3(parent, child) {
22511
22596
  // packages/resolver/src/skills.ts
22512
22597
  init_src();
22513
22598
  import { readFile as readFile8, readdir as readdir2, access, lstat, realpath } from "fs/promises";
22514
- import { basename as basename8, resolve as resolve5, dirname as dirname6, relative as relative2, normalize as normalize2, isAbsolute as isAbsolute3, sep as sep2 } from "path";
22599
+ import { basename as basename8, resolve as resolve6, dirname as dirname6, relative as relative2, normalize as normalize2, isAbsolute as isAbsolute3, sep as sep2 } from "path";
22515
22600
  function parseSkillMd(content) {
22516
22601
  const lines = content.split("\n");
22517
22602
  let inFrontmatter = false;
@@ -22957,10 +23042,10 @@ function parseSkillIgnore(content) {
22957
23042
  return { patterns };
22958
23043
  }
22959
23044
  function isIgnoredByRules(relPath, rules) {
22960
- const basename14 = relPath.split("/").pop() ?? relPath;
23045
+ const basename16 = relPath.split("/").pop() ?? relPath;
22961
23046
  let ignored = false;
22962
23047
  for (const { regex, matchPath, negated } of rules.patterns) {
22963
- const target = matchPath ? relPath : basename14;
23048
+ const target = matchPath ? relPath : basename16;
22964
23049
  if (regex.test(target)) {
22965
23050
  ignored = !negated;
22966
23051
  }
@@ -22968,7 +23053,7 @@ function isIgnoredByRules(relPath, rules) {
22968
23053
  return ignored;
22969
23054
  }
22970
23055
  async function loadSkillIgnore(skillDir) {
22971
- const ignorePath = resolve5(skillDir, ".skillignore");
23056
+ const ignorePath = resolve6(skillDir, ".skillignore");
22972
23057
  try {
22973
23058
  const content = await readFile8(ignorePath, "utf-8");
22974
23059
  return parseSkillIgnore(content);
@@ -23014,7 +23099,7 @@ async function discoverSkillResources(skillDir, logger = noopLogger2) {
23014
23099
  }
23015
23100
  if (entry.isSymbolicLink()) continue;
23016
23101
  if (SKIP_FILES.has(entry.name)) continue;
23017
- const fullPath = resolve5(entry.parentPath, entry.name);
23102
+ const fullPath = resolve6(entry.parentPath, entry.name);
23018
23103
  const relPath = relative2(skillDir, fullPath);
23019
23104
  const relPathNormalized = relPath.split(sep2).join("/");
23020
23105
  const pathSegments = relPath.split(sep2);
@@ -23073,7 +23158,7 @@ async function resolveSkillReferences(references, basePath, logger) {
23073
23158
  column: 0
23074
23159
  });
23075
23160
  }
23076
- const fullPath = resolve5(basePath, ref);
23161
+ const fullPath = resolve6(basePath, ref);
23077
23162
  let content;
23078
23163
  try {
23079
23164
  content = await readFile8(fullPath, "utf-8");
@@ -23145,8 +23230,8 @@ async function discoverSkillDirs(basePath) {
23145
23230
  if (!entry.isDirectory()) continue;
23146
23231
  if (SKIP_DIRS.has(entry.name)) continue;
23147
23232
  if (!isSafeSkillName(entry.name)) continue;
23148
- const subDir = resolve5(dir, entry.name);
23149
- const skillMd = resolve5(subDir, "SKILL.md");
23233
+ const subDir = resolve6(dir, entry.name);
23234
+ const skillMd = resolve6(subDir, "SKILL.md");
23150
23235
  if (await fileExists(skillMd)) {
23151
23236
  if (!result.has(entry.name)) {
23152
23237
  result.set(entry.name, subDir);
@@ -23173,9 +23258,9 @@ async function resolveNativeSkills(ast, registryPath, sourceFile, localPath, opt
23173
23258
  const isSkillsDir = sourceDir.includes("@skills") || sourceDir.endsWith("/skills");
23174
23259
  const discoveredSkillPaths = /* @__PURE__ */ new Map();
23175
23260
  if (!isSkillsDir && localPath) {
23176
- const discoveryDirs = [resolve5(localPath, "skills")];
23261
+ const discoveryDirs = [resolve6(localPath, "skills")];
23177
23262
  if (options?.universalDir && localPath) {
23178
- discoveryDirs.push(resolve5(localPath, "..", options.universalDir, "skills"));
23263
+ discoveryDirs.push(resolve6(localPath, "..", options.universalDir, "skills"));
23179
23264
  }
23180
23265
  for (const dir of discoveryDirs) {
23181
23266
  const discovered = await discoverSkillDirs(dir);
@@ -23196,7 +23281,7 @@ async function resolveNativeSkills(ast, registryPath, sourceFile, localPath, opt
23196
23281
  }
23197
23282
  let sharedResources = [];
23198
23283
  if (localPath) {
23199
- const sharedDir = resolve5(localPath, "shared");
23284
+ const sharedDir = resolve6(localPath, "shared");
23200
23285
  if (await fileExists(sharedDir)) {
23201
23286
  try {
23202
23287
  sharedResources = await discoverSkillResources(sharedDir, logger);
@@ -23217,12 +23302,12 @@ async function resolveNativeSkills(ast, registryPath, sourceFile, localPath, opt
23217
23302
  continue;
23218
23303
  }
23219
23304
  const skillObj = skillValue;
23220
- const skillMdPath = isSkillsDir ? resolve5(sourceDir, skillName, "SKILL.md") : await (async () => {
23305
+ const skillMdPath = isSkillsDir ? resolve6(sourceDir, skillName, "SKILL.md") : await (async () => {
23221
23306
  const discoveredDir = discoveredSkillPaths.get(skillName);
23222
- if (discoveredDir) return resolve5(discoveredDir, "SKILL.md");
23223
- const localCandidate = localPath ? resolve5(localPath, "skills", skillName, "SKILL.md") : null;
23224
- const universalCandidate = options?.universalDir && localPath ? resolve5(localPath, "..", options.universalDir, "skills", skillName, "SKILL.md") : null;
23225
- const registryCandidate = resolve5(registryPath, "@skills", skillName, "SKILL.md");
23307
+ if (discoveredDir) return resolve6(discoveredDir, "SKILL.md");
23308
+ const localCandidate = localPath ? resolve6(localPath, "skills", skillName, "SKILL.md") : null;
23309
+ const universalCandidate = options?.universalDir && localPath ? resolve6(localPath, "..", options.universalDir, "skills", skillName, "SKILL.md") : null;
23310
+ const registryCandidate = resolve6(registryPath, "@skills", skillName, "SKILL.md");
23226
23311
  if (localCandidate && await fileExists(localCandidate)) return localCandidate;
23227
23312
  if (universalCandidate && await fileExists(universalCandidate))
23228
23313
  return universalCandidate;
@@ -23312,7 +23397,7 @@ async function discoverCommandFiles(dir, logger = noopLogger2) {
23312
23397
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
23313
23398
  if (entry.isSymbolicLink()) continue;
23314
23399
  const cmdName = "/" + entry.name.replace(/\.md$/, "");
23315
- const fullPath = resolve5(dir, entry.name);
23400
+ const fullPath = resolve6(dir, entry.name);
23316
23401
  try {
23317
23402
  const fileStat = await lstat(fullPath);
23318
23403
  if (fileStat.isSymbolicLink()) continue;
@@ -23343,11 +23428,11 @@ async function resolveNativeCommands(ast, sourceFile, localPath, options) {
23343
23428
  if (!localPath) return ast;
23344
23429
  const logger = options?.logger ?? noopLogger2;
23345
23430
  const allCommands = {};
23346
- const localCommands = await discoverCommandFiles(resolve5(localPath, "commands"), logger);
23431
+ const localCommands = await discoverCommandFiles(resolve6(localPath, "commands"), logger);
23347
23432
  Object.assign(allCommands, localCommands);
23348
23433
  if (options?.universalDir) {
23349
23434
  const universalCommands = await discoverCommandFiles(
23350
- resolve5(localPath, "..", options.universalDir, "commands"),
23435
+ resolve6(localPath, "..", options.universalDir, "commands"),
23351
23436
  logger
23352
23437
  );
23353
23438
  for (const [name, value] of Object.entries(universalCommands)) {
@@ -23428,7 +23513,7 @@ async function discoverAgentFiles(dir, logger = noopLogger2) {
23428
23513
  for (const entry of entries) {
23429
23514
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
23430
23515
  if (entry.isSymbolicLink()) continue;
23431
- const fullPath = resolve5(dir, entry.name);
23516
+ const fullPath = resolve6(dir, entry.name);
23432
23517
  try {
23433
23518
  const fileStat = await lstat(fullPath);
23434
23519
  if (fileStat.isSymbolicLink()) continue;
@@ -23492,11 +23577,11 @@ async function resolveNativeAgents(ast, sourceFile, localPath, options) {
23492
23577
  if (!localPath) return ast;
23493
23578
  const logger = options?.logger ?? noopLogger2;
23494
23579
  const allAgents = {};
23495
- const localAgents = await discoverAgentFiles(resolve5(localPath, "agents"), logger);
23580
+ const localAgents = await discoverAgentFiles(resolve6(localPath, "agents"), logger);
23496
23581
  Object.assign(allAgents, localAgents);
23497
23582
  if (options?.universalDir) {
23498
23583
  const universalAgents = await discoverAgentFiles(
23499
- resolve5(localPath, "..", options.universalDir, "agents"),
23584
+ resolve6(localPath, "..", options.universalDir, "agents"),
23500
23585
  logger
23501
23586
  );
23502
23587
  for (const [name, value] of Object.entries(universalAgents)) {
@@ -25124,7 +25209,7 @@ var RegistryCache = class {
25124
25209
 
25125
25210
  // packages/resolver/src/auto-discovery.ts
25126
25211
  import { readFile as readFile10, readdir as readdir3, access as access2, lstat as lstat2 } from "fs/promises";
25127
- import { resolve as resolve6, basename as basename10 } from "path";
25212
+ import { resolve as resolve7, basename as basename10 } from "path";
25128
25213
  var CONTEXT_FILES = ["CLAUDE.md", ".clinerules", ".cursorrules"];
25129
25214
  async function fileExists2(path) {
25130
25215
  try {
@@ -25160,9 +25245,9 @@ async function discoverSkills(dir) {
25160
25245
  const properties = {};
25161
25246
  for (const entry of entries) {
25162
25247
  if (!entry.isDirectory()) continue;
25163
- let skillMdPath = resolve6(dir, entry.name, "SKILL.md");
25248
+ let skillMdPath = resolve7(dir, entry.name, "SKILL.md");
25164
25249
  if (!await fileExists2(skillMdPath)) {
25165
- const dirnameMdPath = resolve6(dir, entry.name, `${entry.name}.md`);
25250
+ const dirnameMdPath = resolve7(dir, entry.name, `${entry.name}.md`);
25166
25251
  if (await fileExists2(dirnameMdPath)) {
25167
25252
  skillMdPath = dirnameMdPath;
25168
25253
  } else {
@@ -25189,7 +25274,7 @@ async function discoverSkills(dir) {
25189
25274
  return Object.keys(properties).length > 0 ? properties : null;
25190
25275
  }
25191
25276
  async function discoverRootSkill(dir) {
25192
- const skillMdPath = resolve6(dir, "SKILL.md");
25277
+ const skillMdPath = resolve7(dir, "SKILL.md");
25193
25278
  if (!await fileExists2(skillMdPath)) return null;
25194
25279
  try {
25195
25280
  const raw = await readFile10(skillMdPath, "utf-8");
@@ -25220,7 +25305,7 @@ async function discoverAgents(dir) {
25220
25305
  const properties = {};
25221
25306
  for (const entry of entries) {
25222
25307
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
25223
- const fullPath = resolve6(dir, entry.name);
25308
+ const fullPath = resolve7(dir, entry.name);
25224
25309
  try {
25225
25310
  const stat4 = await lstat2(fullPath);
25226
25311
  if (stat4.isSymbolicLink()) continue;
@@ -25256,7 +25341,7 @@ async function discoverCommands(dir) {
25256
25341
  for (const entry of entries) {
25257
25342
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
25258
25343
  if (entry.name === "SKILL.md") continue;
25259
- const fullPath = resolve6(dir, entry.name);
25344
+ const fullPath = resolve7(dir, entry.name);
25260
25345
  try {
25261
25346
  const stat4 = await lstat2(fullPath);
25262
25347
  if (stat4.isSymbolicLink()) continue;
@@ -25273,7 +25358,7 @@ async function discoverCommands(dir) {
25273
25358
  }
25274
25359
  async function discoverContext(dir) {
25275
25360
  for (const fileName of CONTEXT_FILES) {
25276
- const fullPath = resolve6(dir, fileName);
25361
+ const fullPath = resolve7(dir, fileName);
25277
25362
  if (!await fileExists2(fullPath)) continue;
25278
25363
  try {
25279
25364
  const content = await readFile10(fullPath, "utf-8");
@@ -25303,7 +25388,7 @@ async function discoverNativeContent(dir) {
25303
25388
  const subSkills = await discoverSkills(dir);
25304
25389
  const wrappedSkillResults = await Promise.all(
25305
25390
  SKILL_WRAPPER_DIRS.map(async (name) => {
25306
- const candidate = resolve6(dir, name);
25391
+ const candidate = resolve7(dir, name);
25307
25392
  if (!await safeIsDirectory(candidate)) return null;
25308
25393
  return discoverSkills(candidate);
25309
25394
  })
@@ -25324,7 +25409,7 @@ async function discoverNativeContent(dir) {
25324
25409
  const rootAgents = await discoverAgents(dir) ?? {};
25325
25410
  const wrappedAgents = {};
25326
25411
  for (const name of AGENT_WRAPPER_DIRS) {
25327
- const candidate = resolve6(dir, name);
25412
+ const candidate = resolve7(dir, name);
25328
25413
  if (await safeIsDirectory(candidate)) {
25329
25414
  const found = await discoverAgents(candidate);
25330
25415
  if (found) Object.assign(wrappedAgents, found);
@@ -25337,7 +25422,7 @@ async function discoverNativeContent(dir) {
25337
25422
  const rootCommands = await discoverCommands(dir) ?? {};
25338
25423
  const wrappedCommands = {};
25339
25424
  for (const name of COMMAND_WRAPPER_DIRS) {
25340
- const candidate = resolve6(dir, name);
25425
+ const candidate = resolve7(dir, name);
25341
25426
  if (await safeIsDirectory(candidate)) {
25342
25427
  const found = await discoverCommands(candidate);
25343
25428
  if (found) Object.assign(wrappedCommands, found);
@@ -25838,18 +25923,39 @@ var Resolver = class {
25838
25923
  errors.push(new ResolveError(e.message, e.location));
25839
25924
  }
25840
25925
  }
25926
+ } else if (isMdPath) {
25927
+ errors.push(
25928
+ new ResolveError(
25929
+ `Cannot resolve registry import: file '${subPath}' not found in ${repoUrl} (looked for ${resolvedFullPath}). Verify the path inside the repository.`
25930
+ )
25931
+ );
25841
25932
  } else {
25842
25933
  const discoverDir = isRoot ? cachePath : join8(cachePath, subPath);
25843
- this.logger.debug(`No .prs found, trying auto-discovery: ${discoverDir}`);
25844
- resolvedAST = await discoverNativeContent(discoverDir);
25845
- if (!resolvedAST) {
25846
- const where = isRoot ? "<repository root>" : `'${subPath}'`;
25847
- const hint = isRoot ? ` Specify a sub-path (e.g. ${repoUrl}/skills/<name>).` : "";
25934
+ if (!isRoot && !existsSync9(discoverDir)) {
25848
25935
  errors.push(
25849
25936
  new ResolveError(
25850
- `Cannot resolve registry import: no .prs file or native content at ${where} in ${repoUrl}.${hint}`
25937
+ `Cannot resolve registry import: path '${subPath}' does not exist in repository ${repoUrl}.`
25851
25938
  )
25852
25939
  );
25940
+ } else {
25941
+ this.logger.debug(
25942
+ `No .prs found, trying directory scan and auto-discovery: ${discoverDir}`
25943
+ );
25944
+ const dirResult = await this.tryDirectoryScan(discoverDir, [marker], []);
25945
+ if (dirResult?.ast) {
25946
+ resolvedAST = dirResult.ast;
25947
+ } else {
25948
+ resolvedAST = await discoverNativeContent(discoverDir);
25949
+ if (!resolvedAST) {
25950
+ const where = isRoot ? "<repository root>" : `'${subPath}'`;
25951
+ const hint = isRoot ? ` Specify a sub-path (e.g. ${repoUrl}/skills/<name>).` : "";
25952
+ errors.push(
25953
+ new ResolveError(
25954
+ `Cannot resolve registry import: no .prs file, .md file, or native content at ${where} in ${repoUrl}.${hint}`
25955
+ )
25956
+ );
25957
+ }
25958
+ }
25853
25959
  }
25854
25960
  }
25855
25961
  const result = {
@@ -26080,7 +26186,7 @@ var HttpRegistry = class {
26080
26186
  * Sleep for specified milliseconds.
26081
26187
  */
26082
26188
  sleep(ms) {
26083
- return new Promise((resolve21) => setTimeout(resolve21, ms));
26189
+ return new Promise((resolve22) => setTimeout(resolve22, ms));
26084
26190
  }
26085
26191
  /**
26086
26192
  * Fetch with timeout.
@@ -26224,9 +26330,251 @@ function createHttpRegistry(options) {
26224
26330
  // packages/resolver/src/vendor-registry.ts
26225
26331
  init_src();
26226
26332
 
26333
+ // packages/resolver/src/skill-validation.ts
26334
+ import { basename as basename12, dirname as dirname8, join as join10 } from "path";
26335
+ import { existsSync as existsSync11 } from "fs";
26336
+ function validateSkillFrontmatter(rawContent, options = {}) {
26337
+ const issues = [];
26338
+ if (!hasFrontmatterDelimiters(rawContent)) {
26339
+ issues.push({
26340
+ severity: "error",
26341
+ code: "SK001",
26342
+ message: "SKILL.md must start with a YAML frontmatter block delimited by `---` lines."
26343
+ });
26344
+ return { valid: false, issues };
26345
+ }
26346
+ const parsed = parseSkillMd(rawContent);
26347
+ validateName(parsed, options, issues);
26348
+ validateDescription(parsed, issues);
26349
+ validateCompatibility(parsed.rawFrontmatter, issues);
26350
+ validateLicense(parsed.rawFrontmatter, issues);
26351
+ validateBody(parsed.content, issues);
26352
+ validateReferences(parsed.references, options.filePath, issues);
26353
+ validateAllowedTools(parsed.rawFrontmatter, issues);
26354
+ const hasErrors = issues.some((i) => i.severity === "error");
26355
+ return { valid: !hasErrors, issues };
26356
+ }
26357
+ var NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
26358
+ var MAX_NAME_LEN = 64;
26359
+ var MIN_DESC_LEN = 1;
26360
+ var MAX_DESC_LEN = 1024;
26361
+ var MAX_COMPATIBILITY_LEN = 500;
26362
+ var SHORT_DESC_WARN_LEN = 40;
26363
+ var MAX_BODY_LINES = 500;
26364
+ function validateName(parsed, options, issues) {
26365
+ const name = parsed.name;
26366
+ if (!name || name.length === 0) {
26367
+ issues.push({
26368
+ severity: "error",
26369
+ code: "SK002",
26370
+ field: "name",
26371
+ message: "`name` is required in SKILL.md frontmatter."
26372
+ });
26373
+ return;
26374
+ }
26375
+ if (name.length > MAX_NAME_LEN) {
26376
+ issues.push({
26377
+ severity: "error",
26378
+ code: "SK003",
26379
+ field: "name",
26380
+ message: `\`name\` must be at most ${MAX_NAME_LEN} characters (got ${name.length}).`
26381
+ });
26382
+ }
26383
+ if (!NAME_PATTERN.test(name)) {
26384
+ issues.push({
26385
+ severity: "error",
26386
+ code: "SK004",
26387
+ field: "name",
26388
+ message: `\`name\` "${name}" is invalid. Use lowercase letters, digits, and single hyphens only. Cannot start or end with a hyphen or contain consecutive hyphens.`
26389
+ });
26390
+ }
26391
+ if (options.filePath) {
26392
+ const parentDir = basename12(dirname8(options.filePath));
26393
+ if (parentDir && parentDir !== name) {
26394
+ issues.push({
26395
+ severity: "error",
26396
+ code: "SK005",
26397
+ field: "name",
26398
+ message: `\`name\` "${name}" must match the parent directory name "${parentDir}".`
26399
+ });
26400
+ }
26401
+ }
26402
+ if (options.existingNames?.has(name)) {
26403
+ issues.push({
26404
+ severity: "error",
26405
+ code: "SK006",
26406
+ field: "name",
26407
+ message: `Skill name "${name}" collides with an already-installed skill. Two skills cannot share the same name (they would be written to the same output folder).`
26408
+ });
26409
+ }
26410
+ }
26411
+ function validateDescription(parsed, issues) {
26412
+ const fromRaw = parsed.rawFrontmatter ? extractScalarField(parsed.rawFrontmatter, "description") : void 0;
26413
+ const description = fromRaw !== void 0 ? fromRaw : parsed.description;
26414
+ if (!description || description.trim().length < MIN_DESC_LEN) {
26415
+ issues.push({
26416
+ severity: "error",
26417
+ code: "SK010",
26418
+ field: "description",
26419
+ message: "`description` is required and must be non-empty."
26420
+ });
26421
+ return;
26422
+ }
26423
+ if (description.length > MAX_DESC_LEN) {
26424
+ issues.push({
26425
+ severity: "error",
26426
+ code: "SK011",
26427
+ field: "description",
26428
+ message: `\`description\` must be at most ${MAX_DESC_LEN} characters (got ${description.length}).`
26429
+ });
26430
+ }
26431
+ if (description.length < SHORT_DESC_WARN_LEN) {
26432
+ issues.push({
26433
+ severity: "warning",
26434
+ code: "SK012",
26435
+ field: "description",
26436
+ message: `\`description\` is very short (${description.length} chars). The spec recommends describing both what the skill does AND when to use it so agents can match it to tasks.`
26437
+ });
26438
+ } else if (!/\bwhen\b|\buse\b/i.test(description)) {
26439
+ issues.push({
26440
+ severity: "warning",
26441
+ code: "SK013",
26442
+ field: "description",
26443
+ message: '`description` should mention WHEN to use the skill (e.g. "Use when \u2026"). This improves agent trigger accuracy.'
26444
+ });
26445
+ }
26446
+ }
26447
+ function validateCompatibility(rawFrontmatter, issues) {
26448
+ if (!rawFrontmatter) return;
26449
+ const value = extractScalarField(rawFrontmatter, "compatibility");
26450
+ if (value === void 0) return;
26451
+ if (value.length > MAX_COMPATIBILITY_LEN) {
26452
+ issues.push({
26453
+ severity: "error",
26454
+ code: "SK020",
26455
+ field: "compatibility",
26456
+ message: `\`compatibility\` must be at most ${MAX_COMPATIBILITY_LEN} characters (got ${value.length}).`
26457
+ });
26458
+ }
26459
+ }
26460
+ function validateLicense(rawFrontmatter, issues) {
26461
+ if (!rawFrontmatter) {
26462
+ issues.push({
26463
+ severity: "warning",
26464
+ code: "SK030",
26465
+ field: "license",
26466
+ message: "`license` is missing. Enterprises typically require an explicit license declaration before adopting a third-party skill."
26467
+ });
26468
+ return;
26469
+ }
26470
+ const value = extractScalarField(rawFrontmatter, "license");
26471
+ if (value === void 0 || value.length === 0) {
26472
+ issues.push({
26473
+ severity: "warning",
26474
+ code: "SK030",
26475
+ field: "license",
26476
+ message: "`license` is missing. Enterprises typically require an explicit license declaration before adopting a third-party skill."
26477
+ });
26478
+ }
26479
+ }
26480
+ function validateBody(body, issues) {
26481
+ const lines = body.split("\n").length;
26482
+ if (lines > MAX_BODY_LINES) {
26483
+ issues.push({
26484
+ severity: "warning",
26485
+ code: "SK040",
26486
+ message: `SKILL.md body has ${lines} lines (>${MAX_BODY_LINES}). The spec recommends splitting long content into separate files under references/ for progressive disclosure.`
26487
+ });
26488
+ }
26489
+ }
26490
+ function validateReferences(references, filePath, issues) {
26491
+ if (!references || references.length === 0) return;
26492
+ if (!filePath) return;
26493
+ const skillDir = dirname8(filePath);
26494
+ for (const ref of references) {
26495
+ if (ref.startsWith("/") || ref.startsWith("..")) {
26496
+ issues.push({
26497
+ severity: "error",
26498
+ code: "SK050",
26499
+ field: "references",
26500
+ message: `Reference "${ref}" must be a relative path inside the skill directory (no leading "/" or "..").`
26501
+ });
26502
+ continue;
26503
+ }
26504
+ const target = join10(skillDir, ref);
26505
+ if (!existsSync11(target)) {
26506
+ issues.push({
26507
+ severity: "error",
26508
+ code: "SK051",
26509
+ field: "references",
26510
+ message: `Reference "${ref}" listed in frontmatter does not exist (looked for ${target}).`
26511
+ });
26512
+ }
26513
+ }
26514
+ }
26515
+ function validateAllowedTools(rawFrontmatter, issues) {
26516
+ if (!rawFrontmatter) return;
26517
+ const value = extractScalarField(rawFrontmatter, "allowed-tools");
26518
+ if (value === void 0) return;
26519
+ const tokens = value.split(/\s+/).filter((t) => t.length > 0);
26520
+ for (const token of tokens) {
26521
+ if (!/^[A-Za-z][A-Za-z0-9_-]*(\([^)]*\))?$/.test(token)) {
26522
+ issues.push({
26523
+ severity: "warning",
26524
+ code: "SK060",
26525
+ field: "allowed-tools",
26526
+ message: `\`allowed-tools\` entry "${token}" does not match the expected \`Tool\` or \`Tool(scope:pattern)\` shape.`
26527
+ });
26528
+ }
26529
+ }
26530
+ }
26531
+ function hasFrontmatterDelimiters(content) {
26532
+ const lines = content.split("\n");
26533
+ let first2 = -1;
26534
+ for (let i = 0; i < lines.length; i++) {
26535
+ if ((lines[i] ?? "").trim() === "---") {
26536
+ first2 = i;
26537
+ break;
26538
+ }
26539
+ }
26540
+ if (first2 === -1) return false;
26541
+ for (let i = first2 + 1; i < lines.length; i++) {
26542
+ if ((lines[i] ?? "").trim() === "---") return true;
26543
+ }
26544
+ return false;
26545
+ }
26546
+ function extractScalarField(rawFrontmatter, field) {
26547
+ const lines = rawFrontmatter.split("\n");
26548
+ const pattern = new RegExp(`^${escapeRegex(field)}:\\s*(?:"([^"]*)"|'([^']*)'|(.*))\\s*$`);
26549
+ for (const line of lines) {
26550
+ const match = line.match(pattern);
26551
+ if (match) {
26552
+ return (match[1] ?? match[2] ?? match[3] ?? "").trim();
26553
+ }
26554
+ }
26555
+ return void 0;
26556
+ }
26557
+ function escapeRegex(input2) {
26558
+ return input2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26559
+ }
26560
+ function formatSkillValidationIssues(issues) {
26561
+ return issues.map((i) => {
26562
+ const tag = i.severity === "error" ? "\u2717" : "\u26A0";
26563
+ const field = i.field ? ` [${i.field}]` : "";
26564
+ return ` ${tag} ${i.code}${field}: ${i.message}`;
26565
+ }).join("\n");
26566
+ }
26567
+
26227
26568
  // packages/resolver/src/index.ts
26228
26569
  init_src();
26229
26570
 
26571
+ // packages/resolver/src/reference-hasher.ts
26572
+ import { createHash as createHash2 } from "crypto";
26573
+ function hashContent(content) {
26574
+ const hex = createHash2("sha256").update(content).digest("hex");
26575
+ return `sha256-${hex}`;
26576
+ }
26577
+
26230
26578
  // packages/validator/src/validator.ts
26231
26579
  init_src();
26232
26580
 
@@ -27391,7 +27739,8 @@ var AUTHORITY_PATTERNS = [
27391
27739
  /\[?\s{0,10}PRIORITY\s{0,10}(?:OVERRIDE|ONE|ALPHA)\s{0,10}\]?/i,
27392
27740
  /\[?\s{0,10}EMERGENCY\s{0,10}(?:PROTOCOL|OVERRIDE|MODE)\s{0,10}\]?/i,
27393
27741
  // Warning suppression patterns
27394
- /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:WARN|ALERT|NOTIFY|FLAG|REPORT)/i,
27742
+ // Removed because it triggers false positives on valid agent instructions (e.g., "do not notify user")
27743
+ // /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:WARN|ALERT|NOTIFY|FLAG|REPORT)/i,
27395
27744
  /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:PROVIDE|SHOW|DISPLAY|INCLUDE)\s{1,10}(?:SECURITY\s{1,10})?WARNINGS?/i,
27396
27745
  /(?:SUPPRESS|HIDE|DISABLE|REMOVE|SILENCE)\s{1,10}(?:ALL\s{1,10})?WARNINGS?/i,
27397
27746
  /(?:SUPPRESS|HIDE|DISABLE|REMOVE|SILENCE)\s{1,10}(?:ALL\s{1,10})?(?:SECURITY\s{1,10})?(?:ALERTS?|NOTIFICATIONS?)/i,
@@ -29679,7 +30028,7 @@ var Compiler = class _Compiler {
29679
30028
  outputPathOwners.set(skillPath, `${formatter.name}:promptscript-skill`);
29680
30029
  const skillOutput = {
29681
30030
  path: skillPath,
29682
- content: this.options.skillContent
30031
+ content: formatter.transformInjectedSkillContent ? formatter.transformInjectedSkillContent(this.options.skillContent) : this.options.skillContent
29683
30032
  };
29684
30033
  outputs.set(skillPath, addMarkerToOutput(skillOutput, sourceLabel, "promptscript"));
29685
30034
  this.logger.verbose(` \u2192 ${skillPath} (auto-injected promptscript skill)`);
@@ -29760,12 +30109,12 @@ var Compiler = class _Compiler {
29760
30109
  */
29761
30110
  async watch(entryPath, options = {}) {
29762
30111
  const { default: chokidar2 } = await import("chokidar");
29763
- const { dirname: dirname15, resolve: resolve21 } = await import("path");
29764
- const baseDir = dirname15(resolve21(entryPath));
30112
+ const { dirname: dirname17, resolve: resolve22 } = await import("path");
30113
+ const baseDir = dirname17(resolve22(entryPath));
29765
30114
  const includePatterns = options.include ?? ["**/*.prs"];
29766
30115
  const excludePatterns = options.exclude ?? ["**/node_modules/**"];
29767
30116
  const debounceMs = options.debounce ?? 300;
29768
- const watchPatterns = includePatterns.map((p) => resolve21(baseDir, p));
30117
+ const watchPatterns = includePatterns.map((p) => resolve22(baseDir, p));
29769
30118
  let debounceTimer = null;
29770
30119
  let pendingChanges = [];
29771
30120
  const handleChange = async (changedFiles) => {
@@ -29940,7 +30289,7 @@ var Pager = class {
29940
30289
  }
29941
30290
  return;
29942
30291
  }
29943
- return new Promise((resolve21) => {
30292
+ return new Promise((resolve22) => {
29944
30293
  const pagerCmd = getPagerCommand();
29945
30294
  const [cmd, ...args] = pagerCmd.split(" ");
29946
30295
  if (cmd === "less" && !args.includes("-R")) {
@@ -29948,7 +30297,7 @@ var Pager = class {
29948
30297
  }
29949
30298
  if (!cmd) {
29950
30299
  console.log(content);
29951
- resolve21();
30300
+ resolve22();
29952
30301
  return;
29953
30302
  }
29954
30303
  const pager = spawn(cmd, args, {
@@ -29961,17 +30310,17 @@ var Pager = class {
29961
30310
  });
29962
30311
  pager.on("error", (_err) => {
29963
30312
  console.log(content);
29964
- resolve21();
30313
+ resolve22();
29965
30314
  });
29966
30315
  pager.on("close", () => {
29967
- resolve21();
30316
+ resolve22();
29968
30317
  });
29969
30318
  if (pager.stdin) {
29970
30319
  pager.stdin.write(content);
29971
30320
  pager.stdin.end();
29972
30321
  } else {
29973
30322
  console.log(content);
29974
- resolve21();
30323
+ resolve22();
29975
30324
  }
29976
30325
  });
29977
30326
  }
@@ -29984,7 +30333,7 @@ function createPager(enabled = true) {
29984
30333
  init_services();
29985
30334
 
29986
30335
  // packages/cli/src/utils/registry-resolver.ts
29987
- import { join as join10 } from "path";
30336
+ import { join as join11 } from "path";
29988
30337
  async function resolveRegistryPath(config) {
29989
30338
  if (config.registry?.git) {
29990
30339
  const gitConfig = config.registry.git;
@@ -29998,7 +30347,7 @@ async function resolveRegistryPath(config) {
29998
30347
  if (isValid) {
29999
30348
  const subPath2 = gitConfig.path ?? "";
30000
30349
  return {
30001
- path: subPath2 ? join10(cachePath, subPath2) : cachePath,
30350
+ path: subPath2 ? join11(cachePath, subPath2) : cachePath,
30002
30351
  isRemote: true,
30003
30352
  source: "git"
30004
30353
  };
@@ -30027,7 +30376,7 @@ async function resolveRegistryPath(config) {
30027
30376
  }
30028
30377
  const subPath = gitConfig.path ?? "";
30029
30378
  return {
30030
- path: subPath ? join10(cachePath, subPath) : cachePath,
30379
+ path: subPath ? join11(cachePath, subPath) : cachePath,
30031
30380
  isRemote: true,
30032
30381
  source: "git"
30033
30382
  };
@@ -30077,17 +30426,17 @@ function detectOutputConflicts(targets) {
30077
30426
 
30078
30427
  // packages/cli/src/commands/compile.ts
30079
30428
  var __filename2 = fileURLToPath2(import.meta.url);
30080
- var __dirname2 = dirname8(__filename2);
30429
+ var __dirname2 = dirname9(__filename2);
30081
30430
  async function loadBundledSkillContent(logger) {
30082
30431
  const skillRelPath = "skills/promptscript/SKILL.md";
30083
30432
  const candidates = [
30084
- resolve7(__dirname2, skillRelPath),
30433
+ resolve8(__dirname2, skillRelPath),
30085
30434
  // bundled: dist/packages/cli/skills/...
30086
- resolve7(__dirname2, "..", "..", skillRelPath)
30435
+ resolve8(__dirname2, "..", "..", skillRelPath)
30087
30436
  // dev: packages/cli/skills/...
30088
30437
  ];
30089
30438
  for (const candidate of candidates) {
30090
- if (existsSync11(candidate)) {
30439
+ if (existsSync12(candidate)) {
30091
30440
  try {
30092
30441
  const content = await readFile12(candidate, "utf-8");
30093
30442
  logger.debug(
@@ -30104,8 +30453,8 @@ async function loadBundledSkillContent(logger) {
30104
30453
  }
30105
30454
  function findConfigInDir(dir) {
30106
30455
  for (const file of CONFIG_FILES) {
30107
- const fullPath = resolve7(dir, file);
30108
- if (existsSync11(fullPath)) {
30456
+ const fullPath = resolve8(dir, file);
30457
+ if (existsSync12(fullPath)) {
30109
30458
  return fullPath;
30110
30459
  }
30111
30460
  }
@@ -30161,7 +30510,7 @@ function getBuildProfile(config, buildName) {
30161
30510
  }
30162
30511
  function resolveOutputBase(projectRoot, output) {
30163
30512
  if (!output) return projectRoot;
30164
- return isAbsolute5(output) ? output : resolve7(projectRoot, output);
30513
+ return isAbsolute5(output) ? output : resolve8(projectRoot, output);
30165
30514
  }
30166
30515
  async function isPromptScriptGenerated2(filePath) {
30167
30516
  try {
@@ -30205,13 +30554,13 @@ async function writeOutputs(outputs, options, _config, services) {
30205
30554
  const targetErrors = [];
30206
30555
  async function safeWrite(path, content) {
30207
30556
  try {
30208
- await mkdir4(dirname8(path), { recursive: true });
30557
+ await mkdir4(dirname9(path), { recursive: true });
30209
30558
  await writeFile4(path, content, "utf-8");
30210
30559
  return true;
30211
30560
  } catch (err) {
30212
30561
  const nodeErr = err;
30213
30562
  if (nodeErr.code === "ENOTDIR") {
30214
- const conflictPath = nodeErr.path ?? dirname8(path);
30563
+ const conflictPath = nodeErr.path ?? dirname9(path);
30215
30564
  const msg = `Cannot create directory because '${conflictPath}' already exists as a file. Remove it or disable this target.`;
30216
30565
  targetErrors.push(msg);
30217
30566
  ConsoleOutput.error(msg);
@@ -30227,8 +30576,8 @@ async function writeOutputs(outputs, options, _config, services) {
30227
30576
  }
30228
30577
  }
30229
30578
  for (const output of outputs.values()) {
30230
- const outputPath = options.output ? resolve7(options.output, output.path) : resolve7(output.path);
30231
- const fileExists3 = existsSync11(outputPath);
30579
+ const outputPath = options.output ? resolve8(options.output, output.path) : resolve8(output.path);
30580
+ const fileExists3 = existsSync12(outputPath);
30232
30581
  if (options.dryRun) {
30233
30582
  if (fileExists3) {
30234
30583
  const isGenerated2 = await isPromptScriptGenerated2(outputPath);
@@ -30361,7 +30710,7 @@ async function compileCommand(options, services = createDefaultServices()) {
30361
30710
  const spinner = createSpinner("Loading configuration...").start();
30362
30711
  const logger = createCliLogger();
30363
30712
  try {
30364
- const projectRoot = options.cwd ? resolve7(options.cwd) : process.cwd();
30713
+ const projectRoot = options.cwd ? resolve8(options.cwd) : process.cwd();
30365
30714
  logger.verbose("Loading configuration...");
30366
30715
  const configPath = options.config ? options.config : options.cwd ? findConfigInDir(projectRoot) : void 0;
30367
30716
  const config = await loadConfig(configPath);
@@ -30401,7 +30750,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30401
30750
  }
30402
30751
  }
30403
30752
  let lockfile;
30404
- const lockfilePath = resolve7(projectRoot, "promptscript.lock");
30753
+ const lockfilePath = resolve8(projectRoot, "promptscript.lock");
30405
30754
  try {
30406
30755
  const lockfileContent = await readFile12(lockfilePath, "utf-8");
30407
30756
  const parsed = parseYaml5(lockfileContent, { maxAliasCount: 100 });
@@ -30421,7 +30770,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30421
30770
  if (config.includePromptScriptSkill !== false) {
30422
30771
  skillContent = await loadBundledSkillContent(logger);
30423
30772
  }
30424
- const localPath = resolve7(projectRoot, ".promptscript");
30773
+ const localPath = resolve8(projectRoot, ".promptscript");
30425
30774
  const compiler = new Compiler({
30426
30775
  resolver: {
30427
30776
  registryPath,
@@ -30441,8 +30790,8 @@ Disable one of the conflicting targets or assign a custom output path.`
30441
30790
  ignoreHashes: options.ignoreHashes
30442
30791
  });
30443
30792
  const entry = buildProfile?.entry ?? config.input?.entry;
30444
- const entryPath = entry ? resolve7(projectRoot, entry) : resolve7(localPath, "project.prs");
30445
- if (!existsSync11(entryPath)) {
30793
+ const entryPath = entry ? resolve8(projectRoot, entry) : resolve8(localPath, "project.prs");
30794
+ if (!existsSync12(entryPath)) {
30446
30795
  spinner.fail("Entry file not found");
30447
30796
  ConsoleOutput.error(`File not found: ${entryPath}`);
30448
30797
  ConsoleOutput.muted("Run: prs init");
@@ -30467,6 +30816,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30467
30816
  ...options,
30468
30817
  output: resolveOutputBase(projectRoot, configuredOutput)
30469
30818
  };
30819
+ await postFormatWithPrettier(result.outputs, projectRoot, logger);
30470
30820
  const writeResult = await writeOutputs(result.outputs, effectiveOptions, config, services);
30471
30821
  if (writeResult.unchanged.length > 0) {
30472
30822
  ConsoleOutput.muted(`Unchanged ${writeResult.unchanged.length} file(s)`);
@@ -30480,7 +30830,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30480
30830
  ConsoleOutput.newline();
30481
30831
  ConsoleOutput.info("Watching for changes... (Ctrl+C to stop)");
30482
30832
  watchForChanges(
30483
- resolve7(projectRoot, ".promptscript"),
30833
+ resolve8(projectRoot, ".promptscript"),
30484
30834
  () => compileCommand({ ...options, watch: false }, services)
30485
30835
  );
30486
30836
  }
@@ -30531,8 +30881,8 @@ function watchForChanges(dir, callback) {
30531
30881
  }
30532
30882
 
30533
30883
  // packages/cli/src/commands/validate.ts
30534
- import { resolve as resolve8, join as join11 } from "path";
30535
- import { existsSync as existsSync12, readFileSync as readFileSync4, writeFileSync, readdirSync } from "fs";
30884
+ import { resolve as resolve9, join as join12 } from "path";
30885
+ import { existsSync as existsSync13, readFileSync as readFileSync4, writeFileSync, readdirSync } from "fs";
30536
30886
  init_console();
30537
30887
  init_src();
30538
30888
  init_src2();
@@ -30641,7 +30991,7 @@ function discoverPrsFiles(dir) {
30641
30991
  try {
30642
30992
  const entries = readdirSync(dir, { withFileTypes: true });
30643
30993
  for (const entry of entries) {
30644
- const fullPath = join11(dir, entry.name);
30994
+ const fullPath = join12(dir, entry.name);
30645
30995
  if (entry.isDirectory()) {
30646
30996
  results.push(...discoverPrsFiles(fullPath));
30647
30997
  } else if (entry.name.endsWith(".prs")) {
@@ -30681,8 +31031,8 @@ async function validateCommand(options) {
30681
31031
  formatters: []
30682
31032
  // No formatters needed for validation only
30683
31033
  });
30684
- const entryPath = resolve8("./.promptscript/project.prs");
30685
- if (!existsSync12(entryPath)) {
31034
+ const entryPath = resolve9("./.promptscript/project.prs");
31035
+ if (!existsSync13(entryPath)) {
30686
31036
  handleEntryNotFound(entryPath, isJsonFormat, spinner);
30687
31037
  return;
30688
31038
  }
@@ -30764,8 +31114,8 @@ ${fixedCount} file(s) fixed.`);
30764
31114
 
30765
31115
  // packages/cli/src/commands/pull.ts
30766
31116
  import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
30767
- import { existsSync as existsSync13 } from "fs";
30768
- import { resolve as resolve9, dirname as dirname9 } from "path";
31117
+ import { existsSync as existsSync14 } from "fs";
31118
+ import { resolve as resolve10, dirname as dirname10 } from "path";
30769
31119
  init_console();
30770
31120
  async function pullCommand(options) {
30771
31121
  const spinner = createSpinner("Loading configuration...").start();
@@ -30790,8 +31140,8 @@ async function pullCommand(options) {
30790
31140
  }
30791
31141
  spinner.text = `Fetching ${inheritPath}...`;
30792
31142
  const content = await registry2.fetch(inheritPath);
30793
- const destPath = resolve9("./.promptscript/.inherited", inheritPath);
30794
- if (existsSync13(destPath) && !options.force && !options.dryRun) {
31143
+ const destPath = resolve10("./.promptscript/.inherited", inheritPath);
31144
+ if (existsSync14(destPath) && !options.force && !options.dryRun) {
30795
31145
  spinner.warn("File already exists (use --force to overwrite)");
30796
31146
  ConsoleOutput.muted(destPath);
30797
31147
  return;
@@ -30801,12 +31151,12 @@ async function pullCommand(options) {
30801
31151
  ConsoleOutput.newline();
30802
31152
  ConsoleOutput.dryRun(`Would fetch: ${config.inherit}`);
30803
31153
  ConsoleOutput.dryRun(` to: ${destPath}`);
30804
- if (existsSync13(destPath)) {
31154
+ if (existsSync14(destPath)) {
30805
31155
  ConsoleOutput.dryRun("(would overwrite existing file)");
30806
31156
  }
30807
31157
  return;
30808
31158
  }
30809
- await mkdir5(dirname9(destPath), { recursive: true });
31159
+ await mkdir5(dirname10(destPath), { recursive: true });
30810
31160
  await writeFile5(destPath, content, "utf-8");
30811
31161
  spinner.succeed("Pulled from registry");
30812
31162
  ConsoleOutput.success(destPath);
@@ -30849,10 +31199,10 @@ async function createRegistry(config, options, spinner) {
30849
31199
  }
30850
31200
  const registryPath = config.registry?.path ?? "./registry";
30851
31201
  spinner.text = `Using local registry: ${registryPath}...`;
30852
- if (!existsSync13(registryPath)) {
31202
+ if (!existsSync14(registryPath)) {
30853
31203
  throw new Error(`Local registry path not found: ${registryPath}`);
30854
31204
  }
30855
- return createFileSystemRegistry(resolve9(registryPath));
31205
+ return createFileSystemRegistry(resolve10(registryPath));
30856
31206
  }
30857
31207
  function parseInheritPath(inheritPath) {
30858
31208
  const versionIndex = inheritPath.lastIndexOf("@");
@@ -30899,9 +31249,9 @@ function handlePullError(error, spinner) {
30899
31249
  }
30900
31250
 
30901
31251
  // packages/cli/src/commands/diff.ts
30902
- import { resolve as resolve10 } from "path";
31252
+ import { resolve as resolve11 } from "path";
30903
31253
  import { readFile as readFile13 } from "fs/promises";
30904
- import { existsSync as existsSync14 } from "fs";
31254
+ import { existsSync as existsSync15 } from "fs";
30905
31255
  init_console();
30906
31256
  import chalk2 from "chalk";
30907
31257
  function configureColors(options) {
@@ -30936,9 +31286,9 @@ function printNewFilePreview(content, showFull, pager) {
30936
31286
  }
30937
31287
  }
30938
31288
  async function compareOutput(_name, output, _config, showFull, pager) {
30939
- const outputPath = resolve10(output.path);
31289
+ const outputPath = resolve11(output.path);
30940
31290
  const newContent = output.content;
30941
- if (!existsSync14(outputPath)) {
31291
+ if (!existsSync15(outputPath)) {
30942
31292
  pager.write(chalk2.green(`+ ${outputPath} (new file)`));
30943
31293
  pager.write("");
30944
31294
  printNewFilePreview(newContent, showFull, pager);
@@ -30978,8 +31328,8 @@ async function diffCommand(options) {
30978
31328
  formatters: targets,
30979
31329
  customConventions: config.customConventions
30980
31330
  });
30981
- const entryPath = resolve10("./.promptscript/project.prs");
30982
- if (!existsSync14(entryPath)) {
31331
+ const entryPath = resolve11("./.promptscript/project.prs");
31332
+ if (!existsSync15(entryPath)) {
30983
31333
  spinner.fail("Entry file not found");
30984
31334
  ConsoleOutput.error(`File not found: ${entryPath}`);
30985
31335
  ConsoleOutput.muted("Run: prs init");
@@ -31047,8 +31397,8 @@ function printSimpleDiff(existingLines, newLines, showFull, pager) {
31047
31397
  }
31048
31398
 
31049
31399
  // packages/cli/src/commands/check.ts
31050
- import { existsSync as existsSync15 } from "fs";
31051
- import { resolve as resolve11 } from "path";
31400
+ import { existsSync as existsSync16 } from "fs";
31401
+ import { resolve as resolve12 } from "path";
31052
31402
  init_console();
31053
31403
  async function checkCommand(_options) {
31054
31404
  const spinner = createSpinner("Checking project health...").start();
@@ -31111,7 +31461,7 @@ async function checkCommand(_options) {
31111
31461
  });
31112
31462
  }
31113
31463
  const entryPath = config.input?.entry ?? ".promptscript/project.prs";
31114
- if (existsSync15(entryPath)) {
31464
+ if (existsSync16(entryPath)) {
31115
31465
  results.push({
31116
31466
  name: "Entry file",
31117
31467
  status: "ok",
@@ -31126,8 +31476,8 @@ async function checkCommand(_options) {
31126
31476
  hasErrors = true;
31127
31477
  }
31128
31478
  if (config.registry?.path) {
31129
- const registryPath = resolve11(config.registry.path);
31130
- if (existsSync15(registryPath)) {
31479
+ const registryPath = resolve12(config.registry.path);
31480
+ if (existsSync16(registryPath)) {
31131
31481
  results.push({
31132
31482
  name: "Registry path",
31133
31483
  status: "ok",
@@ -31212,21 +31562,21 @@ function printResults(results) {
31212
31562
  init_src();
31213
31563
  init_console();
31214
31564
  import { fileURLToPath as fileURLToPath3 } from "url";
31215
- import { dirname as dirname10 } from "path";
31565
+ import { dirname as dirname11 } from "path";
31216
31566
 
31217
31567
  // packages/cli/src/utils/version-check.ts
31218
31568
  init_console();
31219
31569
  import { homedir as homedir3 } from "os";
31220
- import { join as join12 } from "path";
31570
+ import { join as join13 } from "path";
31221
31571
  import { readFile as readFile14, writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
31222
31572
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/@promptscript/cli/latest";
31223
31573
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
31224
31574
  var FETCH_TIMEOUT_MS = 3e3;
31225
31575
  function getCacheDir() {
31226
- return join12(homedir3(), ".promptscript", ".cache");
31576
+ return join13(homedir3(), ".promptscript", ".cache");
31227
31577
  }
31228
31578
  function getCachePath() {
31229
- return join12(getCacheDir(), "version.json");
31579
+ return join13(getCacheDir(), "version.json");
31230
31580
  }
31231
31581
  async function readCache() {
31232
31582
  try {
@@ -31365,7 +31715,7 @@ function printUpdateNotification(info) {
31365
31715
 
31366
31716
  // packages/cli/src/commands/update-check.ts
31367
31717
  var __filename3 = fileURLToPath3(import.meta.url);
31368
- var __dirname3 = dirname10(__filename3);
31718
+ var __dirname3 = dirname11(__filename3);
31369
31719
  async function updateCheckCommand() {
31370
31720
  const currentVersion = getPackageVersion(__dirname3, "./package.json");
31371
31721
  console.log(`@promptscript/cli v${currentVersion}`);
@@ -31393,7 +31743,7 @@ init_services();
31393
31743
  init_console();
31394
31744
 
31395
31745
  // packages/cli/src/utils/registry-scaffolder.ts
31396
- import { join as join13 } from "path";
31746
+ import { join as join14 } from "path";
31397
31747
  var SEED_BASE = `@meta {
31398
31748
  id: "@core/base"
31399
31749
  syntax: "1.0.0"
@@ -31494,14 +31844,14 @@ async function scaffoldRegistry(options, services) {
31494
31844
  const createdFiles = [];
31495
31845
  await fs4.mkdir(directory, { recursive: true });
31496
31846
  const manifest = generateManifest(name, description, namespaces, seed);
31497
- const manifestPath = join13(directory, "registry-manifest.yaml");
31847
+ const manifestPath = join14(directory, "registry-manifest.yaml");
31498
31848
  await fs4.writeFile(manifestPath, manifest, "utf-8");
31499
31849
  createdFiles.push(manifestPath);
31500
31850
  const readme = generateReadme(name, description, namespaces);
31501
- const readmePath = join13(directory, "README.md");
31851
+ const readmePath = join14(directory, "README.md");
31502
31852
  await fs4.writeFile(readmePath, readme, "utf-8");
31503
31853
  createdFiles.push(readmePath);
31504
- const gitignorePath = join13(directory, ".gitignore");
31854
+ const gitignorePath = join14(directory, ".gitignore");
31505
31855
  await fs4.writeFile(
31506
31856
  gitignorePath,
31507
31857
  ".DS_Store\nnode_modules/\n*.log\n*.swp\n*.bak\n.env*\n",
@@ -31509,20 +31859,20 @@ async function scaffoldRegistry(options, services) {
31509
31859
  );
31510
31860
  createdFiles.push(gitignorePath);
31511
31861
  for (const ns of namespaces) {
31512
- const nsDir = join13(directory, ns);
31862
+ const nsDir = join14(directory, ns);
31513
31863
  await fs4.mkdir(nsDir, { recursive: true });
31514
31864
  if (seed && ns === "@core") {
31515
- const basePath = join13(nsDir, "base.prs");
31865
+ const basePath = join14(nsDir, "base.prs");
31516
31866
  await fs4.writeFile(basePath, SEED_BASE, "utf-8");
31517
31867
  createdFiles.push(basePath);
31518
- const qualityPath = join13(nsDir, "quality.prs");
31868
+ const qualityPath = join14(nsDir, "quality.prs");
31519
31869
  await fs4.writeFile(qualityPath, SEED_QUALITY, "utf-8");
31520
31870
  createdFiles.push(qualityPath);
31521
- const securityPath = join13(nsDir, "security.prs");
31871
+ const securityPath = join14(nsDir, "security.prs");
31522
31872
  await fs4.writeFile(securityPath, SEED_SECURITY, "utf-8");
31523
31873
  createdFiles.push(securityPath);
31524
31874
  } else {
31525
- const gitkeepPath = join13(nsDir, ".gitkeep");
31875
+ const gitkeepPath = join14(nsDir, ".gitkeep");
31526
31876
  await fs4.writeFile(gitkeepPath, "", "utf-8");
31527
31877
  createdFiles.push(gitkeepPath);
31528
31878
  }
@@ -31631,7 +31981,7 @@ Then reference configs with \`@inherit\` or \`@use\`:
31631
31981
  }
31632
31982
 
31633
31983
  // packages/cli/src/utils/resolve-target-directory.ts
31634
- import { join as join14, resolve as resolve12 } from "path";
31984
+ import { join as join15, resolve as resolve13 } from "path";
31635
31985
 
31636
31986
  // packages/cli/src/utils/slugify.ts
31637
31987
  function slugify(name) {
@@ -31642,7 +31992,7 @@ function slugify(name) {
31642
31992
  async function resolveTargetDirectory(options, services) {
31643
31993
  const { cwd, directoryArg, registryName, nonInteractive } = options;
31644
31994
  if (directoryArg) {
31645
- return resolve12(directoryArg);
31995
+ return resolve13(directoryArg);
31646
31996
  }
31647
31997
  const empty = await isDirectoryEmpty(cwd, services.fs);
31648
31998
  if (empty && nonInteractive) {
@@ -31656,9 +32006,9 @@ async function resolveTargetDirectory(options, services) {
31656
32006
  { name: `Subdirectory (./${slugify(registryName)})`, value: "subdirectory" }
31657
32007
  ]
31658
32008
  });
31659
- return choice === "here" ? cwd : join14(cwd, slugify(registryName));
32009
+ return choice === "here" ? cwd : join15(cwd, slugify(registryName));
31660
32010
  }
31661
- return join14(cwd, slugify(registryName));
32011
+ return join15(cwd, slugify(registryName));
31662
32012
  }
31663
32013
  async function isDirectoryEmpty(dir, fs4) {
31664
32014
  const entries = await fs4.readdir(dir);
@@ -31749,15 +32099,15 @@ async function registryInitCommand(directory, options, services = createDefaultS
31749
32099
  // packages/cli/src/commands/registry/validate.ts
31750
32100
  init_services();
31751
32101
  init_console();
31752
- import { resolve as resolve13 } from "path";
32102
+ import { resolve as resolve14 } from "path";
31753
32103
 
31754
32104
  // packages/cli/src/utils/registry-validator.ts
31755
- import { join as join15 } from "path";
32105
+ import { join as join16 } from "path";
31756
32106
  import { parse as parseYaml6 } from "yaml";
31757
32107
  async function validateRegistry(registryPath, services) {
31758
32108
  const { fs: fs4 } = services;
31759
32109
  const issues = [];
31760
- const manifestPath = join15(registryPath, "registry-manifest.yaml");
32110
+ const manifestPath = join16(registryPath, "registry-manifest.yaml");
31761
32111
  if (!fs4.existsSync(manifestPath)) {
31762
32112
  return {
31763
32113
  valid: false,
@@ -31849,7 +32199,7 @@ async function validateRegistry(registryPath, services) {
31849
32199
  });
31850
32200
  }
31851
32201
  if (entry.path) {
31852
- const prsPath = join15(registryPath, entry.path);
32202
+ const prsPath = join16(registryPath, entry.path);
31853
32203
  if (!fs4.existsSync(prsPath)) {
31854
32204
  issues.push({
31855
32205
  severity: "error",
@@ -31884,7 +32234,7 @@ async function validateRegistry(registryPath, services) {
31884
32234
  });
31885
32235
  }
31886
32236
  for (const ns of namespaceNames) {
31887
- const nsDir = join15(registryPath, ns);
32237
+ const nsDir = join16(registryPath, ns);
31888
32238
  if (fs4.existsSync(nsDir)) {
31889
32239
  try {
31890
32240
  const files = await fs4.readdir(nsDir);
@@ -31898,7 +32248,7 @@ async function validateRegistry(registryPath, services) {
31898
32248
  issues.push({
31899
32249
  severity: "warning",
31900
32250
  message: `Orphaned .prs file not in catalog: ${relativePath}`,
31901
- path: join15(nsDir, file)
32251
+ path: join16(nsDir, file)
31902
32252
  });
31903
32253
  }
31904
32254
  }
@@ -31949,7 +32299,7 @@ function detectCircularDependencies(catalog) {
31949
32299
 
31950
32300
  // packages/cli/src/commands/registry/validate.ts
31951
32301
  async function registryValidateCommand(path, options, services = createDefaultServices()) {
31952
- const registryPath = resolve13(path ?? ".");
32302
+ const registryPath = resolve14(path ?? ".");
31953
32303
  const spinner = createSpinner("Validating registry...").start();
31954
32304
  try {
31955
32305
  const result = await validateRegistry(registryPath, services);
@@ -32001,10 +32351,10 @@ async function registryValidateCommand(path, options, services = createDefaultSe
32001
32351
  // packages/cli/src/commands/registry/publish.ts
32002
32352
  init_services();
32003
32353
  init_console();
32004
- import { resolve as resolve14, join as join16 } from "path";
32354
+ import { resolve as resolve15, join as join17 } from "path";
32005
32355
  import { execFileSync as execFileSync2 } from "child_process";
32006
32356
  async function registryPublishCommand(path, options, services = createDefaultServices()) {
32007
- const registryPath = resolve14(path ?? ".");
32357
+ const registryPath = resolve15(path ?? ".");
32008
32358
  try {
32009
32359
  if (!options.force) {
32010
32360
  const spinner2 = createSpinner("Validating registry...").start();
@@ -32024,7 +32374,7 @@ async function registryPublishCommand(path, options, services = createDefaultSer
32024
32374
  `Registry valid (${result.stats.catalogEntries} entries, ${result.stats.prsFiles} files)`
32025
32375
  );
32026
32376
  }
32027
- const manifestPath = join16(registryPath, "registry-manifest.yaml");
32377
+ const manifestPath = join17(registryPath, "registry-manifest.yaml");
32028
32378
  if (services.fs.existsSync(manifestPath)) {
32029
32379
  const content = await services.fs.readFile(manifestPath, "utf-8");
32030
32380
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
@@ -32152,8 +32502,8 @@ async function registryListCommand() {
32152
32502
  // packages/cli/src/commands/registry/add.ts
32153
32503
  init_console();
32154
32504
  import { readFile as readFile16, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
32155
- import { existsSync as existsSync16 } from "fs";
32156
- import { dirname as dirname11 } from "path";
32505
+ import { existsSync as existsSync17 } from "fs";
32506
+ import { dirname as dirname12 } from "path";
32157
32507
  import { parse as parseYaml8, stringify as stringifyYaml } from "yaml";
32158
32508
  init_user_config();
32159
32509
  async function registryAddCommand(alias, url, options) {
@@ -32183,12 +32533,12 @@ async function registryAddCommand(alias, url, options) {
32183
32533
  }
32184
32534
  }
32185
32535
  async function addToGlobalConfig(alias, url) {
32186
- const configDir = dirname11(USER_CONFIG_PATH);
32187
- if (!existsSync16(configDir)) {
32536
+ const configDir = dirname12(USER_CONFIG_PATH);
32537
+ if (!existsSync17(configDir)) {
32188
32538
  await mkdir7(configDir, { recursive: true });
32189
32539
  }
32190
32540
  let config = { version: "1" };
32191
- if (existsSync16(USER_CONFIG_PATH)) {
32541
+ if (existsSync17(USER_CONFIG_PATH)) {
32192
32542
  const content = await readFile16(USER_CONFIG_PATH, "utf-8");
32193
32543
  const parsed = parseYaml8(content);
32194
32544
  if (parsed && typeof parsed === "object") {
@@ -32238,8 +32588,8 @@ function registerRegistryCommands(registry2) {
32238
32588
 
32239
32589
  // packages/cli/src/commands/lock.ts
32240
32590
  import { writeFile as writeFile8, readFile as readFile18 } from "fs/promises";
32241
- import { existsSync as existsSync18 } from "fs";
32242
- import { resolve as resolve15 } from "path";
32591
+ import { existsSync as existsSync19 } from "fs";
32592
+ import { resolve as resolve16 } from "path";
32243
32593
  import { parse as parseYaml9, stringify as stringifyYaml2 } from "yaml";
32244
32594
  init_console();
32245
32595
  init_src();
@@ -32247,9 +32597,9 @@ init_src();
32247
32597
  // packages/cli/src/commands/lock-scanner.ts
32248
32598
  init_src2();
32249
32599
  import { readFile as readFile17 } from "fs/promises";
32250
- import { existsSync as existsSync17 } from "fs";
32600
+ import { existsSync as existsSync18 } from "fs";
32251
32601
  async function collectRemoteImports(entryPath, options) {
32252
- if (!existsSync17(entryPath)) {
32602
+ if (!existsSync18(entryPath)) {
32253
32603
  return [];
32254
32604
  }
32255
32605
  const loader = new FileLoader({
@@ -32286,7 +32636,7 @@ async function collectRemoteImports(entryPath, options) {
32286
32636
  results.push(marker);
32287
32637
  }
32288
32638
  } else {
32289
- if (existsSync17(resolved)) {
32639
+ if (existsSync18(resolved)) {
32290
32640
  await scan(resolved);
32291
32641
  }
32292
32642
  }
@@ -32312,8 +32662,8 @@ async function lockCommand(options) {
32312
32662
  const aliases = config.registries ?? {};
32313
32663
  const aliasEntries = Object.entries(aliases);
32314
32664
  const projectRoot = process.cwd();
32315
- const localPath = resolve15(projectRoot, ".promptscript");
32316
- const entryPath = config.input?.entry ? resolve15(projectRoot, config.input.entry) : resolve15(localPath, "project.prs");
32665
+ const localPath = resolve16(projectRoot, ".promptscript");
32666
+ const entryPath = config.input?.entry ? resolve16(projectRoot, config.input.entry) : resolve16(localPath, "project.prs");
32317
32667
  const scannedImports = await collectRemoteImports(entryPath, {
32318
32668
  localPath,
32319
32669
  registries: config.registries
@@ -32324,7 +32674,7 @@ async function lockCommand(options) {
32324
32674
  return;
32325
32675
  }
32326
32676
  let existing = { version: LOCKFILE_VERSION, dependencies: {} };
32327
- if (existsSync18(LOCKFILE_PATH)) {
32677
+ if (existsSync19(LOCKFILE_PATH)) {
32328
32678
  try {
32329
32679
  const raw = await readFile18(LOCKFILE_PATH, "utf-8");
32330
32680
  const parsed = parseYaml9(raw, { maxAliasCount: 100 });
@@ -32393,7 +32743,7 @@ async function lockCommand(options) {
32393
32743
 
32394
32744
  // packages/cli/src/commands/update.ts
32395
32745
  import { writeFile as writeFile9, readFile as readFile19 } from "fs/promises";
32396
- import { existsSync as existsSync19 } from "fs";
32746
+ import { existsSync as existsSync20 } from "fs";
32397
32747
  import { parse as parseYaml10, stringify as stringifyYaml3 } from "yaml";
32398
32748
  init_console();
32399
32749
  init_src();
@@ -32416,7 +32766,7 @@ async function updateCommand(packageArg, options) {
32416
32766
  return;
32417
32767
  }
32418
32768
  let existing = { version: LOCKFILE_VERSION, dependencies: {} };
32419
- if (existsSync19(LOCKFILE_PATH)) {
32769
+ if (existsSync20(LOCKFILE_PATH)) {
32420
32770
  try {
32421
32771
  const raw = await readFile19(LOCKFILE_PATH, "utf-8");
32422
32772
  const parsed = parseYaml10(raw, { maxAliasCount: 100 });
@@ -32480,12 +32830,12 @@ async function updateCommand(packageArg, options) {
32480
32830
  init_console();
32481
32831
  init_src();
32482
32832
  import { readFile as readFile20, writeFile as writeFile10, mkdir as mkdir8, readdir as readdir5 } from "fs/promises";
32483
- import { existsSync as existsSync20 } from "fs";
32484
- import { join as join17, resolve as resolve16 } from "path";
32833
+ import { existsSync as existsSync21 } from "fs";
32834
+ import { join as join18, resolve as resolve17 } from "path";
32485
32835
  import { homedir as homedir4 } from "os";
32486
32836
  import { parse as parseYaml11 } from "yaml";
32487
32837
  var VENDOR_DIR = ".promptscript/vendor";
32488
- var CACHE_BASE = join17(homedir4(), ".promptscript", "cache", "registries");
32838
+ var CACHE_BASE = join18(homedir4(), ".promptscript", "cache", "registries");
32489
32839
  async function vendorSyncCommand(options) {
32490
32840
  const spinner = createSpinner("Syncing vendor directory...").start();
32491
32841
  try {
@@ -32503,13 +32853,13 @@ async function vendorSyncCommand(options) {
32503
32853
  }
32504
32854
  const results = [];
32505
32855
  for (const [repoUrl, dep] of deps) {
32506
- const cacheDir = join17(CACHE_BASE, repoUrl.replace(/[/:]/g, "_"), dep.version);
32507
- if (!existsSync20(cacheDir)) {
32856
+ const cacheDir = join18(CACHE_BASE, repoUrl.replace(/[/:]/g, "_"), dep.version);
32857
+ if (!existsSync21(cacheDir)) {
32508
32858
  results.push({ repoUrl, status: "missing" });
32509
32859
  continue;
32510
32860
  }
32511
32861
  if (!options.dryRun) {
32512
- const vendorTarget = resolve16(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32862
+ const vendorTarget = resolve17(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32513
32863
  await mkdir8(vendorTarget, { recursive: true });
32514
32864
  await copyDirectory(cacheDir, vendorTarget);
32515
32865
  }
@@ -32555,7 +32905,7 @@ async function vendorCheckCommand(_options) {
32555
32905
  spinner.warn("No dependencies in lockfile");
32556
32906
  return;
32557
32907
  }
32558
- if (!existsSync20(VENDOR_DIR)) {
32908
+ if (!existsSync21(VENDOR_DIR)) {
32559
32909
  spinner.fail("Vendor directory does not exist");
32560
32910
  ConsoleOutput.muted("Run: prs vendor sync");
32561
32911
  process.exitCode = 1;
@@ -32563,8 +32913,8 @@ async function vendorCheckCommand(_options) {
32563
32913
  }
32564
32914
  const issues = [];
32565
32915
  for (const [repoUrl] of deps) {
32566
- const vendorTarget = resolve16(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32567
- if (!existsSync20(vendorTarget)) {
32916
+ const vendorTarget = resolve17(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32917
+ if (!existsSync21(vendorTarget)) {
32568
32918
  issues.push({ repoUrl, issue: "missing from vendor directory" });
32569
32919
  }
32570
32920
  }
@@ -32587,7 +32937,7 @@ async function vendorCheckCommand(_options) {
32587
32937
  }
32588
32938
  }
32589
32939
  async function loadLockfile() {
32590
- if (!existsSync20(LOCKFILE_PATH)) {
32940
+ if (!existsSync21(LOCKFILE_PATH)) {
32591
32941
  return null;
32592
32942
  }
32593
32943
  try {
@@ -32601,8 +32951,8 @@ async function loadLockfile() {
32601
32951
  async function copyDirectory(src, dest) {
32602
32952
  const entries = await readdir5(src, { withFileTypes: true });
32603
32953
  for (const entry of entries) {
32604
- const srcPath = join17(src, entry.name);
32605
- const destPath = join17(dest, entry.name);
32954
+ const srcPath = join18(src, entry.name);
32955
+ const destPath = join18(dest, entry.name);
32606
32956
  if (entry.isDirectory()) {
32607
32957
  await mkdir8(destPath, { recursive: true });
32608
32958
  await copyDirectory(srcPath, destPath);
@@ -32614,12 +32964,12 @@ async function copyDirectory(src, dest) {
32614
32964
  }
32615
32965
 
32616
32966
  // packages/cli/src/commands/resolve-cmd.ts
32617
- import { existsSync as existsSync21 } from "fs";
32618
- import { join as join18 } from "path";
32967
+ import { existsSync as existsSync22 } from "fs";
32968
+ import { join as join19 } from "path";
32619
32969
  import { homedir as homedir5 } from "os";
32620
32970
  init_user_config();
32621
32971
  init_console();
32622
- var CACHE_BASE2 = join18(homedir5(), ".promptscript", "cache", "registries");
32972
+ var CACHE_BASE2 = join19(homedir5(), ".promptscript", "cache", "registries");
32623
32973
  async function resolveCommand(importPath, _options) {
32624
32974
  try {
32625
32975
  const configFile = findConfigFile();
@@ -32661,11 +33011,11 @@ async function resolveCommand(importPath, _options) {
32661
33011
  }
32662
33012
  const { repoUrl, path, version } = expanded;
32663
33013
  const cacheVersion = version ?? "latest";
32664
- const cacheDir = join18(CACHE_BASE2, repoUrl.replace(/[/:]/g, "_"), cacheVersion);
32665
- const cacheExists = existsSync21(cacheDir);
33014
+ const cacheDir = join19(CACHE_BASE2, repoUrl.replace(/[/:]/g, "_"), cacheVersion);
33015
+ const cacheExists = existsSync22(cacheDir);
32666
33016
  const filePath = path.endsWith(".prs") ? path : `${path}.prs`;
32667
- const cachedFile = join18(cacheDir, filePath);
32668
- const fileExists3 = cacheExists && existsSync21(cachedFile);
33017
+ const cachedFile = join19(cacheDir, filePath);
33018
+ const fileExists3 = cacheExists && existsSync22(cachedFile);
32669
33019
  ConsoleOutput.newline();
32670
33020
  console.log(` Alias: ${aliasName} \u2192 ${repoUrl}`);
32671
33021
  console.log(` Repo: ${repoUrl}`);
@@ -32682,7 +33032,7 @@ async function resolveCommand(importPath, _options) {
32682
33032
  ConsoleOutput.newline();
32683
33033
  } else {
32684
33034
  const resolvedPath = importPath.endsWith(".prs") ? importPath : `${importPath}.prs`;
32685
- const exists = existsSync21(resolvedPath);
33035
+ const exists = existsSync22(resolvedPath);
32686
33036
  ConsoleOutput.newline();
32687
33037
  console.log(` Import: ${importPath}`);
32688
33038
  console.log(` Type: local file`);
@@ -32699,8 +33049,8 @@ async function resolveCommand(importPath, _options) {
32699
33049
  }
32700
33050
 
32701
33051
  // packages/cli/src/commands/inspect.ts
32702
- import { existsSync as existsSync22 } from "fs";
32703
- import { resolve as resolve17, basename as basename12 } from "path";
33052
+ import { existsSync as existsSync23 } from "fs";
33053
+ import { resolve as resolve18, basename as basename13 } from "path";
32704
33054
  init_console();
32705
33055
  async function inspectCommand(skillName, options) {
32706
33056
  const isJson = options.format === "json";
@@ -32713,8 +33063,8 @@ async function inspectCommand(skillName, options) {
32713
33063
  localPath: "./.promptscript",
32714
33064
  registries: config.registries
32715
33065
  });
32716
- const entryPath = resolve17("./.promptscript/project.prs");
32717
- if (!existsSync22(entryPath)) {
33066
+ const entryPath = resolve18("./.promptscript/project.prs");
33067
+ if (!existsSync23(entryPath)) {
32718
33068
  spinner.stop();
32719
33069
  ConsoleOutput.error(`Entry file not found: ${entryPath}`);
32720
33070
  process.exitCode = 1;
@@ -32786,7 +33136,7 @@ function summarizeValue(val) {
32786
33136
  return String(val);
32787
33137
  }
32788
33138
  function shortPath(source) {
32789
- return basename12(source);
33139
+ return basename13(source);
32790
33140
  }
32791
33141
  function getPropertySource(propName, trace, baseSource) {
32792
33142
  for (let i = trace.length - 1; i >= 0; i--) {
@@ -32894,8 +33244,8 @@ init_console();
32894
33244
  // packages/cli/src/commands/import.ts
32895
33245
  init_src3();
32896
33246
  init_console();
32897
- import { resolve as resolve18, join as join19, basename as basename13 } from "path";
32898
- import { writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync23 } from "fs";
33247
+ import { resolve as resolve19, join as join20, basename as basename14 } from "path";
33248
+ import { writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync24 } from "fs";
32899
33249
  import { stat as stat2, readdir as readdir6, readFile as readFile21, writeFile as writeFile11, mkdir as mkdir9 } from "fs/promises";
32900
33250
  function parseInstructionFrontmatter(content) {
32901
33251
  const match = /^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/.exec(content);
@@ -32923,10 +33273,10 @@ async function importDirectory(dirPath) {
32923
33273
  }
32924
33274
  const lines = ["@meta {", ' version: "1.0"', "}", "", "@guards {"];
32925
33275
  for (const filename of instructionFiles) {
32926
- const filePath = join19(dirPath, filename);
33276
+ const filePath = join20(dirPath, filename);
32927
33277
  const content = await readFile21(filePath, "utf-8");
32928
33278
  const frontmatter = parseInstructionFrontmatter(content);
32929
- const entryName = basename13(filename).replace(/\.instructions\.md$/i, "");
33279
+ const entryName = basename14(filename).replace(/\.instructions\.md$/i, "");
32930
33280
  if (frontmatter) {
32931
33281
  const globPatterns = frontmatter.applyTo.map((p) => `"${p}"`).join(", ");
32932
33282
  lines.push(` ${entryName}(${globPatterns}) {`);
@@ -32949,7 +33299,7 @@ async function importDirectory(dirPath) {
32949
33299
  return lines.join("\n");
32950
33300
  }
32951
33301
  async function importCommand(file, options) {
32952
- const filepath = resolve18(file);
33302
+ const filepath = resolve19(file);
32953
33303
  const inputStat = await stat2(filepath).catch(() => null);
32954
33304
  if (inputStat?.isDirectory()) {
32955
33305
  const prsContent = await importDirectory(filepath);
@@ -32959,7 +33309,7 @@ async function importCommand(file, options) {
32959
33309
  }
32960
33310
  const outputDir = options.output ?? ".promptscript";
32961
33311
  await mkdir9(outputDir, { recursive: true });
32962
- const outputPath = join19(outputDir, "imported.prs");
33312
+ const outputPath = join20(outputDir, "imported.prs");
32963
33313
  await writeFile11(outputPath, prsContent);
32964
33314
  console.log(`\u2714 Imported directory to ${outputPath}`);
32965
33315
  return;
@@ -32981,11 +33331,11 @@ async function importCommand(file, options) {
32981
33331
  console.log(result.prsContent);
32982
33332
  return;
32983
33333
  }
32984
- const outputDir = resolve18(options.output ?? ".promptscript");
32985
- if (!existsSync23(outputDir)) {
33334
+ const outputDir = resolve19(options.output ?? ".promptscript");
33335
+ if (!existsSync24(outputDir)) {
32986
33336
  mkdirSync(outputDir, { recursive: true });
32987
33337
  }
32988
- const outputPath = resolve18(outputDir, "imported.prs");
33338
+ const outputPath = resolve19(outputDir, "imported.prs");
32989
33339
  writeFileSync2(outputPath, result.prsContent, "utf-8");
32990
33340
  ConsoleOutput.success(`Written to ${outputPath}`);
32991
33341
  if (options.validate) {
@@ -33100,18 +33450,18 @@ async function detectMarker(filePath) {
33100
33450
  }
33101
33451
 
33102
33452
  // packages/cli/src/hooks/debounce-lock.ts
33103
- import { createHash as createHash2 } from "node:crypto";
33104
- import { existsSync as existsSync24, writeFileSync as writeFileSync4, unlinkSync, statSync } from "node:fs";
33453
+ import { createHash as createHash3 } from "node:crypto";
33454
+ import { existsSync as existsSync25, writeFileSync as writeFileSync4, unlinkSync, statSync } from "node:fs";
33105
33455
  import { tmpdir } from "node:os";
33106
- import { join as join20 } from "node:path";
33456
+ import { join as join21 } from "node:path";
33107
33457
  var STALE_THRESHOLD_MS = 3e4;
33108
33458
  function getLockPath(projectDir) {
33109
- const hash = createHash2("md5").update(projectDir).digest("hex").slice(0, 12);
33110
- return join20(tmpdir(), `prs-compile-${hash}.lock`);
33459
+ const hash = createHash3("md5").update(projectDir).digest("hex").slice(0, 12);
33460
+ return join21(tmpdir(), `prs-compile-${hash}.lock`);
33111
33461
  }
33112
33462
  function acquireLock(projectDir) {
33113
33463
  const lockPath = getLockPath(projectDir);
33114
- if (existsSync24(lockPath)) {
33464
+ if (existsSync25(lockPath)) {
33115
33465
  try {
33116
33466
  const stat4 = statSync(lockPath);
33117
33467
  const age = Date.now() - stat4.mtimeMs;
@@ -33219,9 +33569,10 @@ Usage: echo '{"file_path":"..."}' | prs hook ${action}
33219
33569
  init_hooks();
33220
33570
 
33221
33571
  // packages/cli/src/commands/skills.ts
33222
- import { writeFile as writeFile12, readFile as readFile23, readdir as readdir7 } from "fs/promises";
33223
- import { resolve as resolve19 } from "path";
33224
- import { existsSync as existsSync25 } from "fs";
33572
+ import { writeFile as writeFile12, readFile as readFile23, readdir as readdir7, mkdtemp, rm } from "fs/promises";
33573
+ import { resolve as resolve20, join as join22, basename as basename15, dirname as dirname13 } from "path";
33574
+ import { existsSync as existsSync26 } from "fs";
33575
+ import { tmpdir as tmpdir2 } from "os";
33225
33576
  import { parse as parseYaml12, stringify as stringifyYaml4 } from "yaml";
33226
33577
  init_console();
33227
33578
  init_src();
@@ -33241,6 +33592,77 @@ function normalizeSkillSource(input2) {
33241
33592
  }
33242
33593
  return source;
33243
33594
  }
33595
+ function extractSubPath(source) {
33596
+ const parts = source.replace(/^https?:\/\//, "").split("/");
33597
+ return parts.length > 3 ? parts.slice(3).join("/") : "";
33598
+ }
33599
+ function deriveSkillFolderName(source) {
33600
+ const subPath = extractSubPath(source);
33601
+ if (!subPath) return void 0;
33602
+ if (!subPath.toLowerCase().endsWith(".md")) return void 0;
33603
+ const parent = dirname13(subPath);
33604
+ if (parent === "." || parent === "") return void 0;
33605
+ return basename15(parent);
33606
+ }
33607
+ function collectExistingSkillNames(lockfile, exclude) {
33608
+ const names = /* @__PURE__ */ new Set();
33609
+ for (const [key, dep] of Object.entries(lockfile.dependencies)) {
33610
+ if (dep.source !== "md") continue;
33611
+ if (exclude && key === exclude) continue;
33612
+ const name = deriveSkillFolderName(key);
33613
+ if (name) names.add(name);
33614
+ }
33615
+ return names;
33616
+ }
33617
+ async function fetchAndValidateRemoteSkill(source, options) {
33618
+ const subPath = extractSubPath(source);
33619
+ if (!subPath || !subPath.toLowerCase().endsWith(".md")) {
33620
+ return void 0;
33621
+ }
33622
+ const repoUrl = extractRepoUrl(source);
33623
+ const tmp = await mkdtemp(join22(tmpdir2(), "prs-skill-validate-"));
33624
+ try {
33625
+ const gitRegistry = createGitRegistry({ url: repoUrl });
33626
+ await gitRegistry.cloneAtTag(repoUrl, options.version, tmp);
33627
+ const filePath = join22(tmp, subPath);
33628
+ if (!existsSync26(filePath)) {
33629
+ return {
33630
+ content: "",
33631
+ integrity: "",
33632
+ valid: false,
33633
+ issues: [
33634
+ {
33635
+ severity: "error",
33636
+ code: "SK000",
33637
+ message: `File '${subPath}' does not exist in ${repoUrl} at ${options.version}.`
33638
+ }
33639
+ ]
33640
+ };
33641
+ }
33642
+ const content = await readFile23(filePath, "utf-8");
33643
+ const integrity = hashContent(Buffer.from(content, "utf-8"));
33644
+ const result = validateSkillFrontmatter(content, {
33645
+ filePath,
33646
+ existingNames: options.existingNames
33647
+ });
33648
+ return { content, integrity, valid: result.valid, issues: result.issues };
33649
+ } finally {
33650
+ await rm(tmp, { recursive: true, force: true }).catch(() => {
33651
+ });
33652
+ }
33653
+ }
33654
+ function printValidationIssues(issues) {
33655
+ if (issues.length === 0) return;
33656
+ ConsoleOutput.newline();
33657
+ const formatted = formatSkillValidationIssues(issues);
33658
+ for (const line of formatted.split("\n")) {
33659
+ if (line.includes("\u2717")) {
33660
+ ConsoleOutput.error(line);
33661
+ } else {
33662
+ ConsoleOutput.warn(line);
33663
+ }
33664
+ }
33665
+ }
33244
33666
  var HEADER_DIRECTIVES = ["@use ", "@inherit ", "@meta "];
33245
33667
  function extractRepoUrl(source) {
33246
33668
  const parts = source.replace(/^https?:\/\//, "").split("/");
@@ -33268,8 +33690,8 @@ function validateRemoteSource(source) {
33268
33690
  }
33269
33691
  async function resolveEntryFile(fileFlag) {
33270
33692
  if (fileFlag) {
33271
- const resolved = resolve19(fileFlag);
33272
- if (!existsSync25(resolved)) {
33693
+ const resolved = resolve20(fileFlag);
33694
+ if (!existsSync26(resolved)) {
33273
33695
  throw new Error(`File not found: ${resolved}`);
33274
33696
  }
33275
33697
  return resolved;
@@ -33279,24 +33701,24 @@ async function resolveEntryFile(fileFlag) {
33279
33701
  try {
33280
33702
  const config = await loadConfig();
33281
33703
  if (config.input?.entry) {
33282
- const entryPath = resolve19(config.input.entry);
33283
- if (existsSync25(entryPath)) {
33704
+ const entryPath = resolve20(config.input.entry);
33705
+ if (existsSync26(entryPath)) {
33284
33706
  return entryPath;
33285
33707
  }
33286
33708
  }
33287
33709
  } catch {
33288
33710
  }
33289
33711
  }
33290
- const promptscriptDir = resolve19(".promptscript");
33291
- if (existsSync25(promptscriptDir)) {
33712
+ const promptscriptDir = resolve20(".promptscript");
33713
+ if (existsSync26(promptscriptDir)) {
33292
33714
  const entries = await readdir7(promptscriptDir);
33293
33715
  const prsFiles = entries.filter((f) => f.endsWith(".prs"));
33294
33716
  if (prsFiles.length === 1) {
33295
- return resolve19(promptscriptDir, prsFiles[0]);
33717
+ return resolve20(promptscriptDir, prsFiles[0]);
33296
33718
  }
33297
33719
  if (prsFiles.length > 1) {
33298
33720
  if (prsFiles.includes("project.prs")) {
33299
- return resolve19(promptscriptDir, "project.prs");
33721
+ return resolve20(promptscriptDir, "project.prs");
33300
33722
  }
33301
33723
  throw new Error(
33302
33724
  `Multiple .prs files found in .promptscript/. Use --file to specify which one.`
@@ -33340,7 +33762,7 @@ function extractUsePath(line) {
33340
33762
  }
33341
33763
  async function loadLockfile2() {
33342
33764
  const defaultLockfile = { version: LOCKFILE_VERSION, dependencies: {} };
33343
- if (!existsSync25(LOCKFILE_PATH)) {
33765
+ if (!existsSync26(LOCKFILE_PATH)) {
33344
33766
  return defaultLockfile;
33345
33767
  }
33346
33768
  try {
@@ -33359,6 +33781,14 @@ async function saveLockfile(lockfile) {
33359
33781
  async function skillsAddCommand(rawSource, options) {
33360
33782
  const spinner = createSpinner("Adding skill...").start();
33361
33783
  try {
33784
+ if (/^http:\/\//i.test(rawSource.trim())) {
33785
+ spinner.fail("Plain HTTP sources are not allowed (security)");
33786
+ ConsoleOutput.error(
33787
+ "Use https:// or git@host:owner/repo. Cleartext git transport is rejected to prevent man-in-the-middle attacks."
33788
+ );
33789
+ process.exitCode = 1;
33790
+ return;
33791
+ }
33362
33792
  const source = normalizeSkillSource(rawSource);
33363
33793
  const sourceError = validateRemoteSource(source);
33364
33794
  if (sourceError) {
@@ -33387,15 +33817,52 @@ async function skillsAddCommand(rawSource, options) {
33387
33817
  process.exitCode = 1;
33388
33818
  return;
33389
33819
  }
33820
+ const lockfile = await loadLockfile2();
33821
+ let integrity = "sha256-pending";
33822
+ let validationFailed = false;
33823
+ if (!options.skipValidation) {
33824
+ spinner.text = "Validating SKILL.md frontmatter...";
33825
+ try {
33826
+ const fetched = await fetchAndValidateRemoteSkill(source, {
33827
+ existingNames: collectExistingSkillNames(lockfile),
33828
+ version: "main"
33829
+ });
33830
+ if (fetched) {
33831
+ integrity = fetched.integrity || integrity;
33832
+ const hasErrors = !fetched.valid;
33833
+ const hasWarnings = fetched.issues.some((i) => i.severity === "warning");
33834
+ if (hasErrors || options.strict && hasWarnings) {
33835
+ spinner.fail("SKILL.md failed validation");
33836
+ printValidationIssues(fetched.issues);
33837
+ ConsoleOutput.newline();
33838
+ ConsoleOutput.muted(
33839
+ "Re-run with --skip-validation to bypass (not recommended) or fix the upstream SKILL.md."
33840
+ );
33841
+ process.exitCode = 1;
33842
+ validationFailed = true;
33843
+ } else if (fetched.issues.length > 0) {
33844
+ spinner.warn("SKILL.md has validation warnings");
33845
+ printValidationIssues(fetched.issues);
33846
+ spinner.start("Adding skill...");
33847
+ }
33848
+ }
33849
+ } catch (err) {
33850
+ spinner.warn("Could not validate SKILL.md ahead of time");
33851
+ ConsoleOutput.muted(
33852
+ `Reason: ${err instanceof Error ? err.message : String(err)}. Proceeding without frontmatter check.`
33853
+ );
33854
+ spinner.start("Adding skill...");
33855
+ }
33856
+ }
33857
+ if (validationFailed) return;
33390
33858
  const insertionPoint = findInsertionPoint(lines);
33391
33859
  const newLine = `@use ${source}`;
33392
33860
  lines.splice(insertionPoint, 0, newLine);
33393
33861
  const updatedContent = lines.join("\n");
33394
- const lockfile = await loadLockfile2();
33395
33862
  const lockEntry = {
33396
33863
  version: "latest",
33397
33864
  commit: validation.headCommit ?? "0000000000000000000000000000000000000000",
33398
- integrity: "sha256-pending",
33865
+ integrity,
33399
33866
  source: "md"
33400
33867
  };
33401
33868
  lockfile.dependencies[source] = lockEntry;
@@ -33523,10 +33990,39 @@ async function skillsUpdateCommand(name, options) {
33523
33990
  });
33524
33991
  continue;
33525
33992
  }
33993
+ let integrity = dep.integrity ?? "sha256-pending";
33994
+ if (!options.skipValidation) {
33995
+ try {
33996
+ const fetched = await fetchAndValidateRemoteSkill(key, {
33997
+ existingNames: collectExistingSkillNames(lockfile, key),
33998
+ version: dep.version === "latest" ? "main" : dep.version
33999
+ });
34000
+ if (fetched) {
34001
+ integrity = fetched.integrity || integrity;
34002
+ const hasErrors = !fetched.valid;
34003
+ const hasWarnings = fetched.issues.some((i) => i.severity === "warning");
34004
+ if (hasErrors || options.strict && hasWarnings) {
34005
+ skipped.push({
34006
+ key,
34007
+ reason: "SKILL.md failed validation after update"
34008
+ });
34009
+ printValidationIssues(fetched.issues);
34010
+ continue;
34011
+ } else if (hasWarnings) {
34012
+ ConsoleOutput.warn(`${key}: validation warnings`);
34013
+ printValidationIssues(fetched.issues);
34014
+ }
34015
+ }
34016
+ } catch (err) {
34017
+ ConsoleOutput.warn(
34018
+ `${key}: could not re-validate (${err instanceof Error ? err.message : String(err)})`
34019
+ );
34020
+ }
34021
+ }
33526
34022
  lockfile.dependencies[key] = {
33527
34023
  version: dep.version ?? "latest",
33528
34024
  commit: validation.headCommit,
33529
- integrity: dep.integrity ?? "sha256-pending",
34025
+ integrity,
33530
34026
  source: "md",
33531
34027
  fetchedAt
33532
34028
  };
@@ -33573,7 +34069,7 @@ async function skillsUpdateCommand(name, options) {
33573
34069
 
33574
34070
  // packages/cli/src/cli.ts
33575
34071
  var __filename4 = fileURLToPath4(import.meta.url);
33576
- var __dirname4 = dirname14(__filename4);
34072
+ var __dirname4 = dirname16(__filename4);
33577
34073
  var program = new Command();
33578
34074
  program.name("prs").description("PromptScript CLI - Standardize AI instructions").version(getPackageVersion(__dirname3, "./package.json")).option("--verbose", "Enable verbose output").option("--debug", "Enable debug output (includes verbose)").option("--quiet", "Suppress non-error output").hook("preAction", async (thisCommand, actionCommand) => {
33579
34075
  const opts = thisCommand.opts();
@@ -33632,10 +34128,10 @@ program.command("resolve <import>").description("Show full resolution chain for
33632
34128
  program.command("hook").argument("<action>", "Hook action: pre-edit or post-edit").description("Hook handler invoked by AI tools (not for direct use)").action(hookCommand);
33633
34129
  program.command("hooks").argument("<action>", "Action: install or uninstall").argument("[tool]", "Tool: claude, gemini, copilot, cursor, windsurf, factory, cline").option("--all", "Install/uninstall for all detected tools").description("Manage PromptScript hooks for AI tools").action(hooksCommand);
33634
34130
  var skills = program.command("skills").description("Manage PromptScript skills");
33635
- skills.command("add <source>").description("Add a remote skill to the project").option("-f, --file <file>", "Target .prs file to modify").option("--dry-run", "Preview changes without writing").action((source, opts) => skillsAddCommand(source, opts));
34131
+ skills.command("add <source>").description("Add a remote skill to the project").option("-f, --file <file>", "Target .prs file to modify").option("--dry-run", "Preview changes without writing").option("--skip-validation", "Skip SKILL.md frontmatter validation (not recommended)").option("--strict", "Treat validation warnings as errors").action((source, opts) => skillsAddCommand(source, opts));
33636
34132
  skills.command("remove <name>").description("Remove a skill from the project").option("--dry-run", "Preview changes without writing").action((name, opts) => skillsRemoveCommand(name, opts));
33637
34133
  skills.command("list").description("List skills imported in the current project").action(() => skillsListCommand());
33638
- skills.command("update [name]").description("Update lock entries for markdown-sourced skills").option("--dry-run", "Preview changes without writing").action((name, opts) => skillsUpdateCommand(name, opts));
34134
+ skills.command("update [name]").description("Update lock entries for markdown-sourced skills").option("--dry-run", "Preview changes without writing").option("--skip-validation", "Skip SKILL.md frontmatter validation (not recommended)").option("--strict", "Treat validation warnings as errors").action((name, opts) => skillsUpdateCommand(name, opts));
33639
34135
  var registry = program.command("registry").description("Manage PromptScript registries");
33640
34136
  registerRegistryCommands(registry);
33641
34137
  function run(args = process.argv) {
@@ -33679,7 +34175,7 @@ toad-cache/dist/toad-cache.cjs:
33679
34175
  (**
33680
34176
  * toad-cache
33681
34177
  *
33682
- * @copyright 2024 Igor Savin <kibertoad@gmail.com>
34178
+ * @copyright 2026 Igor Savin <kibertoad@gmail.com>
33683
34179
  * @license MIT
33684
34180
  * @version 3.7.0
33685
34181
  *)