@promptscript/cli 1.13.0 → 1.13.2

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)
@@ -1406,6 +1415,12 @@ var init_mapper = __esm({
1406
1415
  });
1407
1416
 
1408
1417
  // packages/importer/src/emitter.ts
1418
+ function resolveQuoteDelimiter(content) {
1419
+ const matches = content.match(/"+/g);
1420
+ if (!matches) return '"""';
1421
+ const maxRun = matches.reduce((max, m) => Math.max(max, m.length), 0);
1422
+ return '"'.repeat(Math.max(3, maxRun + 1));
1423
+ }
1409
1424
  function emitPrs(sections, options) {
1410
1425
  const lines = [];
1411
1426
  lines.push("@meta {");
@@ -1431,11 +1446,12 @@ function emitPrs(sections, options) {
1431
1446
  lines.push(` ${entryName}: {`);
1432
1447
  lines.push(` applyTo: [${applyToStr}]`);
1433
1448
  lines.push(` description: "${description}"`);
1434
- lines.push(` content: """`);
1449
+ const contentDelimiter2 = resolveQuoteDelimiter(section.content);
1450
+ lines.push(` content: ${contentDelimiter2}`);
1435
1451
  for (const contentLine of section.content.split("\n")) {
1436
1452
  lines.push(` ${contentLine}`);
1437
1453
  }
1438
- lines.push(` """`);
1454
+ lines.push(` ${contentDelimiter2}`);
1439
1455
  lines.push(` }`);
1440
1456
  }
1441
1457
  lines.push(`}`);
@@ -1444,11 +1460,12 @@ function emitPrs(sections, options) {
1444
1460
  }
1445
1461
  lines.push(`@${block} {`);
1446
1462
  const mergedContent = blockSections.map((s) => s.content).join("\n\n");
1447
- lines.push(` """`);
1463
+ const contentDelimiter = resolveQuoteDelimiter(mergedContent);
1464
+ lines.push(` ${contentDelimiter}`);
1448
1465
  for (const contentLine of mergedContent.split("\n")) {
1449
1466
  lines.push(` ${contentLine}`);
1450
1467
  }
1451
- lines.push(` """`);
1468
+ lines.push(` ${contentDelimiter}`);
1452
1469
  lines.push("}");
1453
1470
  }
1454
1471
  lines.push("");
@@ -1488,11 +1505,12 @@ function emitModularFiles(blocks, options) {
1488
1505
  lines.push("# REVIEW: low confidence -- verify this mapping");
1489
1506
  }
1490
1507
  lines.push(`@${block.targetBlock} {`);
1491
- lines.push(' """');
1508
+ const blockDelimiter = resolveQuoteDelimiter(block.content);
1509
+ lines.push(` ${blockDelimiter}`);
1492
1510
  for (const contentLine of block.content.split("\n")) {
1493
1511
  lines.push(` ${contentLine}`);
1494
1512
  }
1495
- lines.push(' """');
1513
+ lines.push(` ${blockDelimiter}`);
1496
1514
  lines.push("}");
1497
1515
  lines.push("");
1498
1516
  }
@@ -1516,11 +1534,12 @@ function emitModularFiles(blocks, options) {
1516
1534
  projectLines.push(comment);
1517
1535
  }
1518
1536
  projectLines.push("@identity {");
1519
- projectLines.push(' """');
1537
+ const identityDelimiter = resolveQuoteDelimiter(identity.content);
1538
+ projectLines.push(` ${identityDelimiter}`);
1520
1539
  for (const line of identity.content.split("\n")) {
1521
1540
  projectLines.push(` ${line}`);
1522
1541
  }
1523
- projectLines.push(' """');
1542
+ projectLines.push(` ${identityDelimiter}`);
1524
1543
  projectLines.push("}");
1525
1544
  }
1526
1545
  projectLines.push("");
@@ -8913,6 +8932,7 @@ var init_parser2 = __esm({
8913
8932
  { ALT: () => this.SUBRULE(this.block) }
8914
8933
  ])
8915
8934
  );
8935
+ this.CONSUME(EOF);
8916
8936
  });
8917
8937
  /**
8918
8938
  * metaBlock
@@ -10084,6 +10104,12 @@ ${s.content}`);
10084
10104
  reviewComments: []
10085
10105
  };
10086
10106
  }
10107
+ function isStructuralMarker(line) {
10108
+ const trimmed = line.trim();
10109
+ if (/^```[^\s`]*$/.test(trimmed)) return true;
10110
+ if (/^(---|\*\*\*|___)$/.test(trimmed)) return true;
10111
+ return false;
10112
+ }
10087
10113
  function mergeUnion(sections) {
10088
10114
  const seenLines = /* @__PURE__ */ new Set();
10089
10115
  const uniqueLines = [];
@@ -10093,6 +10119,10 @@ function mergeUnion(sections) {
10093
10119
  for (const line of lines) {
10094
10120
  const normalized = line.trim().replace(/\s+/g, " ");
10095
10121
  if (normalized.length === 0) continue;
10122
+ if (isStructuralMarker(line)) {
10123
+ uniqueLines.push(line);
10124
+ continue;
10125
+ }
10096
10126
  if (seenLines.has(normalized)) {
10097
10127
  deduped++;
10098
10128
  continue;
@@ -11774,11 +11804,18 @@ var init_base_formatter = __esm({
11774
11804
  referenceProvenance(sourcePath) {
11775
11805
  return `<!-- from: ${sourcePath} -->`;
11776
11806
  }
11807
+ /**
11808
+ * Check if a name is safe for use in file paths.
11809
+ * Rejects path traversal sequences and path separators.
11810
+ */
11811
+ isSafeName(name) {
11812
+ return !name.includes("..") && !name.includes("/") && !name.includes("\\");
11813
+ }
11777
11814
  /**
11778
11815
  * Check if a skill name is safe for use in file paths.
11779
11816
  */
11780
11817
  isSafeSkillName(name) {
11781
- return !name.includes("..") && !name.includes("/") && !name.includes("\\");
11818
+ return this.isSafeName(name);
11782
11819
  }
11783
11820
  /**
11784
11821
  * Render content inside a code fence, using a longer fence if the content
@@ -11952,9 +11989,11 @@ var init_markdown_instruction_formatter = __esm({
11952
11989
  if ("type" in value && value["type"] === "TextContent") {
11953
11990
  const content = this.valueToString(value);
11954
11991
  if (content.includes("\n")) {
11992
+ const cmdName = name.replace(/^\/+/, "");
11993
+ if (!this.isSafeName(cmdName)) continue;
11955
11994
  commands.push({
11956
- name: name.replace(/^\/+/, ""),
11957
- description: name.replace(/^\/+/, ""),
11995
+ name: cmdName,
11996
+ description: cmdName,
11958
11997
  content
11959
11998
  });
11960
11999
  }
@@ -11962,8 +12001,10 @@ var init_markdown_instruction_formatter = __esm({
11962
12001
  }
11963
12002
  const obj = value;
11964
12003
  if (obj["prompt"] === true || obj["content"]) {
12004
+ const cmdName = name.replace(/^\/+/, "");
12005
+ if (!this.isSafeName(cmdName)) continue;
11965
12006
  commands.push({
11966
- name: name.replace(/^\/+/, ""),
12007
+ name: cmdName,
11967
12008
  description: obj["description"] ? this.valueToString(obj["description"]) : name,
11968
12009
  argumentHint: obj["argumentHint"] ? this.valueToString(obj["argumentHint"]) : void 0,
11969
12010
  content: obj["content"] ? this.valueToString(obj["content"]) : ""
@@ -18392,11 +18433,21 @@ function detectTools() {
18392
18433
  );
18393
18434
  }
18394
18435
  async function readSettingsFile(path) {
18436
+ let content;
18437
+ try {
18438
+ content = await readFile4(path, "utf-8");
18439
+ } catch (err) {
18440
+ const nodeErr = err;
18441
+ if (nodeErr.code === "ENOENT") {
18442
+ return {};
18443
+ }
18444
+ throw err;
18445
+ }
18395
18446
  try {
18396
- const content = await readFile4(path, "utf-8");
18397
18447
  return JSON.parse(content);
18398
- } catch {
18399
- return {};
18448
+ } catch (err) {
18449
+ const message = err instanceof Error ? err.message : String(err);
18450
+ throw new Error(`Failed to parse settings file ${path}: ${message}`, { cause: err });
18400
18451
  }
18401
18452
  }
18402
18453
  async function writeSettingsFile(path, data) {
@@ -19889,9 +19940,9 @@ var require_dist = __commonJS({
19889
19940
  }
19890
19941
  });
19891
19942
 
19892
- // node_modules/.pnpm/toad-cache@3.7.0/node_modules/toad-cache/dist/toad-cache.cjs
19943
+ // node_modules/.pnpm/toad-cache@3.7.1/node_modules/toad-cache/dist/toad-cache.cjs
19893
19944
  var require_toad_cache = __commonJS({
19894
- "node_modules/.pnpm/toad-cache@3.7.0/node_modules/toad-cache/dist/toad-cache.cjs"(exports) {
19945
+ "node_modules/.pnpm/toad-cache@3.7.1/node_modules/toad-cache/dist/toad-cache.cjs"(exports) {
19895
19946
  "use strict";
19896
19947
  var FifoMap = class {
19897
19948
  constructor(max = 1e3, ttlInMsecs = 0) {
@@ -20002,6 +20053,155 @@ var require_toad_cache = __commonJS({
20002
20053
  this.last = item;
20003
20054
  }
20004
20055
  };
20056
+ var FifoObject = class {
20057
+ constructor(max = 1e3, ttlInMsecs = 0) {
20058
+ if (isNaN(max) || max < 0) {
20059
+ throw new Error("Invalid max value");
20060
+ }
20061
+ if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
20062
+ throw new Error("Invalid ttl value");
20063
+ }
20064
+ this.first = null;
20065
+ this.items = /* @__PURE__ */ Object.create(null);
20066
+ this.last = null;
20067
+ this.size = 0;
20068
+ this.max = max;
20069
+ this.ttl = ttlInMsecs;
20070
+ }
20071
+ clear() {
20072
+ this.items = /* @__PURE__ */ Object.create(null);
20073
+ this.first = null;
20074
+ this.last = null;
20075
+ this.size = 0;
20076
+ }
20077
+ delete(key) {
20078
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20079
+ const deletedItem = this.items[key];
20080
+ delete this.items[key];
20081
+ this.size--;
20082
+ if (deletedItem.prev !== null) {
20083
+ deletedItem.prev.next = deletedItem.next;
20084
+ }
20085
+ if (deletedItem.next !== null) {
20086
+ deletedItem.next.prev = deletedItem.prev;
20087
+ }
20088
+ if (this.first === deletedItem) {
20089
+ this.first = deletedItem.next;
20090
+ }
20091
+ if (this.last === deletedItem) {
20092
+ this.last = deletedItem.prev;
20093
+ }
20094
+ }
20095
+ }
20096
+ deleteMany(keys) {
20097
+ for (var i = 0; i < keys.length; i++) {
20098
+ this.delete(keys[i]);
20099
+ }
20100
+ }
20101
+ evict() {
20102
+ if (this.size > 0) {
20103
+ const item = this.first;
20104
+ delete this.items[item.key];
20105
+ if (--this.size === 0) {
20106
+ this.first = null;
20107
+ this.last = null;
20108
+ } else {
20109
+ this.first = item.next;
20110
+ this.first.prev = null;
20111
+ }
20112
+ }
20113
+ }
20114
+ expiresAt(key) {
20115
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20116
+ return this.items[key].expiry;
20117
+ }
20118
+ }
20119
+ get(key) {
20120
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20121
+ const item = this.items[key];
20122
+ if (this.ttl > 0 && item.expiry <= Date.now()) {
20123
+ this.delete(key);
20124
+ return;
20125
+ }
20126
+ return item.value;
20127
+ }
20128
+ }
20129
+ getMany(keys) {
20130
+ const result = [];
20131
+ for (var i = 0; i < keys.length; i++) {
20132
+ result.push(this.get(keys[i]));
20133
+ }
20134
+ return result;
20135
+ }
20136
+ keys() {
20137
+ return Object.keys(this.items);
20138
+ }
20139
+ set(key, value) {
20140
+ if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20141
+ const item2 = this.items[key];
20142
+ item2.value = value;
20143
+ item2.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
20144
+ return;
20145
+ }
20146
+ if (this.max > 0 && this.size === this.max) {
20147
+ this.evict();
20148
+ }
20149
+ const item = {
20150
+ expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
20151
+ key,
20152
+ prev: this.last,
20153
+ next: null,
20154
+ value
20155
+ };
20156
+ this.items[key] = item;
20157
+ if (++this.size === 1) {
20158
+ this.first = item;
20159
+ } else {
20160
+ this.last.next = item;
20161
+ }
20162
+ this.last = item;
20163
+ }
20164
+ };
20165
+ var HitStatisticsRecord = class {
20166
+ constructor() {
20167
+ this.records = {};
20168
+ }
20169
+ initForCache(cacheId, currentTimeStamp) {
20170
+ this.records[cacheId] = {
20171
+ [currentTimeStamp]: {
20172
+ cacheSize: 0,
20173
+ hits: 0,
20174
+ falsyHits: 0,
20175
+ emptyHits: 0,
20176
+ misses: 0,
20177
+ expirations: 0,
20178
+ evictions: 0,
20179
+ invalidateOne: 0,
20180
+ invalidateAll: 0,
20181
+ sets: 0
20182
+ }
20183
+ };
20184
+ }
20185
+ resetForCache(cacheId) {
20186
+ for (let key of Object.keys(this.records[cacheId])) {
20187
+ this.records[cacheId][key] = {
20188
+ cacheSize: 0,
20189
+ hits: 0,
20190
+ falsyHits: 0,
20191
+ emptyHits: 0,
20192
+ misses: 0,
20193
+ expirations: 0,
20194
+ evictions: 0,
20195
+ invalidateOne: 0,
20196
+ invalidateAll: 0,
20197
+ sets: 0
20198
+ };
20199
+ }
20200
+ }
20201
+ getStatistics() {
20202
+ return this.records;
20203
+ }
20204
+ };
20005
20205
  var LruMap = class {
20006
20206
  constructor(max = 1e3, ttlInMsecs = 0) {
20007
20207
  if (isNaN(max) || max < 0) {
@@ -20270,46 +20470,6 @@ var require_toad_cache = __commonJS({
20270
20470
  this.last = item;
20271
20471
  }
20272
20472
  };
20273
- var HitStatisticsRecord = class {
20274
- constructor() {
20275
- this.records = {};
20276
- }
20277
- initForCache(cacheId, currentTimeStamp) {
20278
- this.records[cacheId] = {
20279
- [currentTimeStamp]: {
20280
- cacheSize: 0,
20281
- hits: 0,
20282
- falsyHits: 0,
20283
- emptyHits: 0,
20284
- misses: 0,
20285
- expirations: 0,
20286
- evictions: 0,
20287
- invalidateOne: 0,
20288
- invalidateAll: 0,
20289
- sets: 0
20290
- }
20291
- };
20292
- }
20293
- resetForCache(cacheId) {
20294
- for (let key of Object.keys(this.records[cacheId])) {
20295
- this.records[cacheId][key] = {
20296
- cacheSize: 0,
20297
- hits: 0,
20298
- falsyHits: 0,
20299
- emptyHits: 0,
20300
- misses: 0,
20301
- expirations: 0,
20302
- evictions: 0,
20303
- invalidateOne: 0,
20304
- invalidateAll: 0,
20305
- sets: 0
20306
- };
20307
- }
20308
- }
20309
- getStatistics() {
20310
- return this.records;
20311
- }
20312
- };
20313
20473
  function getTimestamp(date) {
20314
20474
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`;
20315
20475
  }
@@ -20451,115 +20611,6 @@ var require_toad_cache = __commonJS({
20451
20611
  this.hitStatistics.addMiss();
20452
20612
  }
20453
20613
  };
20454
- var FifoObject = class {
20455
- constructor(max = 1e3, ttlInMsecs = 0) {
20456
- if (isNaN(max) || max < 0) {
20457
- throw new Error("Invalid max value");
20458
- }
20459
- if (isNaN(ttlInMsecs) || ttlInMsecs < 0) {
20460
- throw new Error("Invalid ttl value");
20461
- }
20462
- this.first = null;
20463
- this.items = /* @__PURE__ */ Object.create(null);
20464
- this.last = null;
20465
- this.size = 0;
20466
- this.max = max;
20467
- this.ttl = ttlInMsecs;
20468
- }
20469
- clear() {
20470
- this.items = /* @__PURE__ */ Object.create(null);
20471
- this.first = null;
20472
- this.last = null;
20473
- this.size = 0;
20474
- }
20475
- delete(key) {
20476
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20477
- const deletedItem = this.items[key];
20478
- delete this.items[key];
20479
- this.size--;
20480
- if (deletedItem.prev !== null) {
20481
- deletedItem.prev.next = deletedItem.next;
20482
- }
20483
- if (deletedItem.next !== null) {
20484
- deletedItem.next.prev = deletedItem.prev;
20485
- }
20486
- if (this.first === deletedItem) {
20487
- this.first = deletedItem.next;
20488
- }
20489
- if (this.last === deletedItem) {
20490
- this.last = deletedItem.prev;
20491
- }
20492
- }
20493
- }
20494
- deleteMany(keys) {
20495
- for (var i = 0; i < keys.length; i++) {
20496
- this.delete(keys[i]);
20497
- }
20498
- }
20499
- evict() {
20500
- if (this.size > 0) {
20501
- const item = this.first;
20502
- delete this.items[item.key];
20503
- if (--this.size === 0) {
20504
- this.first = null;
20505
- this.last = null;
20506
- } else {
20507
- this.first = item.next;
20508
- this.first.prev = null;
20509
- }
20510
- }
20511
- }
20512
- expiresAt(key) {
20513
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20514
- return this.items[key].expiry;
20515
- }
20516
- }
20517
- get(key) {
20518
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20519
- const item = this.items[key];
20520
- if (this.ttl > 0 && item.expiry <= Date.now()) {
20521
- this.delete(key);
20522
- return;
20523
- }
20524
- return item.value;
20525
- }
20526
- }
20527
- getMany(keys) {
20528
- const result = [];
20529
- for (var i = 0; i < keys.length; i++) {
20530
- result.push(this.get(keys[i]));
20531
- }
20532
- return result;
20533
- }
20534
- keys() {
20535
- return Object.keys(this.items);
20536
- }
20537
- set(key, value) {
20538
- if (Object.prototype.hasOwnProperty.call(this.items, key)) {
20539
- const item2 = this.items[key];
20540
- item2.value = value;
20541
- item2.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
20542
- return;
20543
- }
20544
- if (this.max > 0 && this.size === this.max) {
20545
- this.evict();
20546
- }
20547
- const item = {
20548
- expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
20549
- key,
20550
- prev: this.last,
20551
- next: null,
20552
- value
20553
- };
20554
- this.items[key] = item;
20555
- if (++this.size === 1) {
20556
- this.first = item;
20557
- } else {
20558
- this.last.next = item;
20559
- }
20560
- this.last = item;
20561
- }
20562
- };
20563
20614
  exports.Fifo = FifoObject;
20564
20615
  exports.FifoMap = FifoMap;
20565
20616
  exports.FifoObject = FifoObject;
@@ -20572,9 +20623,9 @@ var require_toad_cache = __commonJS({
20572
20623
  }
20573
20624
  });
20574
20625
 
20575
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/LocalStore.js
20626
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/LocalStore.js
20576
20627
  var require_LocalStore = __commonJS({
20577
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/LocalStore.js"(exports, module) {
20628
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/LocalStore.js"(exports, module) {
20578
20629
  "use strict";
20579
20630
  var { LruMap: Lru } = require_toad_cache();
20580
20631
  function LocalStore(continueExceeding, exponentialBackoff, cache = 5e3) {
@@ -20615,9 +20666,9 @@ var require_LocalStore = __commonJS({
20615
20666
  }
20616
20667
  });
20617
20668
 
20618
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/RedisStore.js
20669
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/RedisStore.js
20619
20670
  var require_RedisStore = __commonJS({
20620
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/store/RedisStore.js"(exports, module) {
20671
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/store/RedisStore.js"(exports, module) {
20621
20672
  "use strict";
20622
20673
  var lua = `
20623
20674
  -- Key to operate on
@@ -20673,9 +20724,9 @@ var require_RedisStore = __commonJS({
20673
20724
  }
20674
20725
  });
20675
20726
 
20676
- // node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/index.js
20727
+ // node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/index.js
20677
20728
  var require_rate_limit = __commonJS({
20678
- "node_modules/.pnpm/@fastify+rate-limit@10.3.0/node_modules/@fastify/rate-limit/index.js"(exports, module) {
20729
+ "node_modules/.pnpm/@fastify+rate-limit@11.0.0/node_modules/@fastify/rate-limit/index.js"(exports, module) {
20679
20730
  "use strict";
20680
20731
  var fp = require_plugin();
20681
20732
  var { parse: parse2, format: format2 } = require_dist();
@@ -20743,7 +20794,7 @@ var require_rate_limit = __commonJS({
20743
20794
  globalParams.timeWindow = defaultTimeWindow;
20744
20795
  }
20745
20796
  globalParams.hook = settings.hook || defaultHook;
20746
- globalParams.allowList = settings.allowList || settings.whitelist || null;
20797
+ globalParams.allowList = settings.allowList || null;
20747
20798
  globalParams.ban = Number.isFinite(settings.ban) && settings.ban >= 0 ? Math.trunc(settings.ban) : -1;
20748
20799
  globalParams.onBanReach = typeof settings.onBanReach === "function" ? settings.onBanReach : defaultOnFn;
20749
20800
  globalParams.onExceeding = typeof settings.onExceeding === "function" ? settings.onExceeding : defaultOnFn;
@@ -20873,9 +20924,9 @@ var require_rate_limit = __commonJS({
20873
20924
  let ttl = 0;
20874
20925
  let ttlInSeconds = 0;
20875
20926
  try {
20876
- const res = await new Promise((resolve22, reject) => {
20927
+ const res = await new Promise((resolve24, reject) => {
20877
20928
  store.incr(key, (err, res2) => {
20878
- err ? reject(err) : resolve22(res2);
20929
+ err ? reject(err) : resolve24(res2);
20879
20930
  }, timeWindow, max);
20880
20931
  });
20881
20932
  current = res.current;
@@ -21044,17 +21095,43 @@ var init_config2 = __esm({
21044
21095
  });
21045
21096
 
21046
21097
  // packages/server/src/path-guard.ts
21047
- import { resolve as resolve21, relative as relative4, isAbsolute as isAbsolute6 } from "path";
21048
- function resolveSafePath(workspace, requestedPath) {
21098
+ import { resolve as resolve23, relative as relative6, isAbsolute as isAbsolute6, dirname as dirname15, basename as basename16 } from "path";
21099
+ import { realpath as realpath2 } from "fs/promises";
21100
+ async function resolveSafePath(workspace, requestedPath) {
21049
21101
  const decoded = decodeURIComponent(requestedPath);
21050
21102
  if (isAbsolute6(decoded)) {
21051
21103
  throw new PathTraversalError(requestedPath);
21052
21104
  }
21053
- const resolved = resolve21(workspace, decoded);
21054
- const rel = relative4(workspace, resolved);
21105
+ const resolved = resolve23(workspace, decoded);
21106
+ const rel = relative6(workspace, resolved);
21055
21107
  if (rel.startsWith("..") || isAbsolute6(rel)) {
21056
21108
  throw new PathTraversalError(requestedPath);
21057
21109
  }
21110
+ let realWorkspace;
21111
+ try {
21112
+ realWorkspace = await realpath2(workspace);
21113
+ } catch {
21114
+ realWorkspace = workspace;
21115
+ }
21116
+ let real;
21117
+ try {
21118
+ real = await realpath2(resolved);
21119
+ } catch (err) {
21120
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
21121
+ try {
21122
+ const realParent = await realpath2(dirname15(resolved));
21123
+ real = resolve23(realParent, basename16(resolved));
21124
+ } catch {
21125
+ return resolved;
21126
+ }
21127
+ } else {
21128
+ throw err;
21129
+ }
21130
+ }
21131
+ const realRel = relative6(realWorkspace, real);
21132
+ if (realRel.startsWith("..") || isAbsolute6(realRel)) {
21133
+ throw new PathTraversalError(requestedPath);
21134
+ }
21058
21135
  return resolved;
21059
21136
  }
21060
21137
  var PathTraversalError;
@@ -21072,7 +21149,7 @@ var init_path_guard = __esm({
21072
21149
 
21073
21150
  // packages/server/src/routes/files.ts
21074
21151
  import { readFile as readFile25, writeFile as writeFile13, unlink as unlink2, stat as stat3, mkdir as mkdir10 } from "fs/promises";
21075
- import { dirname as dirname15 } from "path";
21152
+ import { dirname as dirname16 } from "path";
21076
21153
  import fg from "fast-glob";
21077
21154
  function registerRoutes(app, workspace, readOnly) {
21078
21155
  app.get("/api/files", async () => {
@@ -21091,7 +21168,7 @@ function registerRoutes(app, workspace, readOnly) {
21091
21168
  app.get("/api/files/*", async (request, reply) => {
21092
21169
  const filePath = request.params["*"];
21093
21170
  try {
21094
- const resolved = resolveSafePath(workspace, filePath);
21171
+ const resolved = await resolveSafePath(workspace, filePath);
21095
21172
  const content = await readFile25(resolved, "utf-8");
21096
21173
  return { path: filePath, content };
21097
21174
  } catch (err) {
@@ -21108,7 +21185,7 @@ function registerRoutes(app, workspace, readOnly) {
21108
21185
  if (readOnly) return reply.status(403).send({ error: "Read-only mode" });
21109
21186
  const filePath = request.params["*"];
21110
21187
  try {
21111
- const resolved = resolveSafePath(workspace, filePath);
21188
+ const resolved = await resolveSafePath(workspace, filePath);
21112
21189
  await writeFile13(resolved, request.body.content, "utf-8");
21113
21190
  return { path: filePath, status: "updated" };
21114
21191
  } catch (err) {
@@ -21126,13 +21203,13 @@ function registerRoutes(app, workspace, readOnly) {
21126
21203
  if (readOnly) return reply.status(403).send({ error: "Read-only mode" });
21127
21204
  const filePath = request.params["*"];
21128
21205
  try {
21129
- const resolved = resolveSafePath(workspace, filePath);
21206
+ const resolved = await resolveSafePath(workspace, filePath);
21130
21207
  try {
21131
21208
  await stat3(resolved);
21132
21209
  return reply.status(409).send({ error: "File already exists" });
21133
21210
  } catch {
21134
21211
  }
21135
- await mkdir10(dirname15(resolved), { recursive: true });
21212
+ await mkdir10(dirname16(resolved), { recursive: true });
21136
21213
  await writeFile13(resolved, request.body.content, "utf-8");
21137
21214
  return reply.status(201).send({ path: filePath, status: "created" });
21138
21215
  } catch (err) {
@@ -21147,7 +21224,7 @@ function registerRoutes(app, workspace, readOnly) {
21147
21224
  if (readOnly) return reply.status(403).send({ error: "Read-only mode" });
21148
21225
  const filePath = request.params["*"];
21149
21226
  try {
21150
- const resolved = resolveSafePath(workspace, filePath);
21227
+ const resolved = await resolveSafePath(workspace, filePath);
21151
21228
  await unlink2(resolved);
21152
21229
  return { path: filePath, status: "deleted" };
21153
21230
  } catch (err) {
@@ -21170,7 +21247,7 @@ var init_files = __esm({
21170
21247
 
21171
21248
  // packages/server/src/watcher.ts
21172
21249
  import { watch } from "chokidar";
21173
- import { relative as relative5 } from "path";
21250
+ import { relative as relative7 } from "path";
21174
21251
  function isWatchedFile(filePath) {
21175
21252
  const base = filePath.split("/").pop() ?? "";
21176
21253
  if (CONFIG_FILENAMES2.has(base)) return true;
@@ -21186,15 +21263,15 @@ function createFileWatcher(workspace, watchPaths, onEvent) {
21186
21263
  });
21187
21264
  watcher.on("add", (filePath) => {
21188
21265
  if (!ready || !isWatchedFile(filePath)) return;
21189
- onEvent({ type: "file:created", path: relative5(workspace, filePath) });
21266
+ onEvent({ type: "file:created", path: relative7(workspace, filePath) });
21190
21267
  });
21191
21268
  watcher.on("change", (filePath) => {
21192
21269
  if (!ready || !isWatchedFile(filePath)) return;
21193
- onEvent({ type: "file:changed", path: relative5(workspace, filePath) });
21270
+ onEvent({ type: "file:changed", path: relative7(workspace, filePath) });
21194
21271
  });
21195
21272
  watcher.on("unlink", (filePath) => {
21196
21273
  if (!ready || !isWatchedFile(filePath)) return;
21197
- onEvent({ type: "file:deleted", path: relative5(workspace, filePath) });
21274
+ onEvent({ type: "file:deleted", path: relative7(workspace, filePath) });
21198
21275
  });
21199
21276
  return watcher;
21200
21277
  }
@@ -21216,7 +21293,20 @@ async function createServer(options) {
21216
21293
  origin: options.corsOrigin
21217
21294
  });
21218
21295
  await app.register(import_rate_limit.default, { max: 1e3, timeWindow: "1 minute" });
21219
- await app.register(fastifyWebsocket);
21296
+ await app.register(fastifyWebsocket, {
21297
+ options: {
21298
+ // Validate Origin header to prevent cross-origin WebSocket connections.
21299
+ // Browser WebSockets don't enforce CORS, so we must check server-side.
21300
+ verifyClient: (info, callback) => {
21301
+ const origin = info.req.headers.origin;
21302
+ if (origin && origin !== options.corsOrigin && options.corsOrigin !== "*") {
21303
+ callback(false, 403, "Origin not allowed");
21304
+ return;
21305
+ }
21306
+ callback(true);
21307
+ }
21308
+ }
21309
+ });
21220
21310
  registerHealthRoute(app);
21221
21311
  registerConfigRoute(
21222
21312
  app,
@@ -21357,12 +21447,12 @@ var init_migrate = __esm({
21357
21447
  init_src();
21358
21448
  init_init();
21359
21449
  import { Command } from "commander";
21360
- import { fileURLToPath as fileURLToPath4 } from "url";
21361
- import { dirname as dirname16 } from "path";
21450
+ import { fileURLToPath as fileURLToPath4, pathToFileURL } from "url";
21451
+ import { dirname as dirname17 } from "path";
21362
21452
 
21363
21453
  // packages/cli/src/commands/compile.ts
21364
21454
  init_src();
21365
- import { resolve as resolve8, dirname as dirname9, isAbsolute as isAbsolute5 } from "path";
21455
+ import { resolve as resolve10, dirname as dirname9, isAbsolute as isAbsolute5 } from "path";
21366
21456
  import { fileURLToPath as fileURLToPath2 } from "url";
21367
21457
  import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile12 } from "fs/promises";
21368
21458
  import { existsSync as existsSync12 } from "fs";
@@ -21374,6 +21464,68 @@ init_env_config();
21374
21464
  import { readFile as readFile6 } from "fs/promises";
21375
21465
  import { existsSync as existsSync6 } from "fs";
21376
21466
  import { parse as parseYaml4 } from "yaml";
21467
+
21468
+ // packages/cli/src/config/merge-config.ts
21469
+ function deepMergeRegistry(target, source) {
21470
+ if (!source) return target;
21471
+ if (!target) return source;
21472
+ const merged = { ...target };
21473
+ if (source.path !== void 0) merged.path = source.path;
21474
+ if (source.url !== void 0) merged.url = source.url;
21475
+ if (source.git) {
21476
+ const mergedAuth = source.git.auth ?? merged.git?.auth;
21477
+ merged.git = {
21478
+ ...merged.git,
21479
+ ...source.git,
21480
+ ...mergedAuth ? { auth: mergedAuth } : {}
21481
+ };
21482
+ }
21483
+ if (source.cache) {
21484
+ merged.cache = { ...merged.cache, ...source.cache };
21485
+ }
21486
+ if (source.auth) {
21487
+ merged.auth = { ...merged.auth, ...source.auth };
21488
+ }
21489
+ return merged;
21490
+ }
21491
+ function userConfigToProjectRegistry(userRegistry) {
21492
+ const registry2 = {};
21493
+ if (userRegistry.git) {
21494
+ registry2.git = {
21495
+ url: userRegistry.git.url,
21496
+ ...userRegistry.git.fallbackUrl ? { fallbackUrl: userRegistry.git.fallbackUrl } : {},
21497
+ ...userRegistry.git.ref ? { ref: userRegistry.git.ref } : {},
21498
+ ...userRegistry.git.path ? { path: userRegistry.git.path } : {},
21499
+ ...userRegistry.git.auth ? { auth: userRegistry.git.auth } : {}
21500
+ };
21501
+ }
21502
+ if (userRegistry.url) {
21503
+ registry2.url = userRegistry.url;
21504
+ }
21505
+ if (userRegistry.cache) {
21506
+ registry2.cache = { ...userRegistry.cache };
21507
+ }
21508
+ return registry2;
21509
+ }
21510
+ function mergeConfigs(userConfig, projectConfig, envOverrides, cliFlags) {
21511
+ const merged = { ...projectConfig };
21512
+ if (userConfig.registry) {
21513
+ const userRegistry = userConfigToProjectRegistry(userConfig.registry);
21514
+ merged.registry = deepMergeRegistry(userRegistry, merged.registry);
21515
+ }
21516
+ if (envOverrides.registry) {
21517
+ merged.registry = deepMergeRegistry(merged.registry, envOverrides.registry);
21518
+ }
21519
+ if (cliFlags?.registry) {
21520
+ merged.registry = deepMergeRegistry(merged.registry, cliFlags.registry);
21521
+ }
21522
+ if (cliFlags?.targets) {
21523
+ merged.targets = cliFlags.targets;
21524
+ }
21525
+ return merged;
21526
+ }
21527
+
21528
+ // packages/cli/src/config/loader.ts
21377
21529
  var CONFIG_FILES = [
21378
21530
  "promptscript.yaml",
21379
21531
  "promptscript.yml",
@@ -21426,6 +21578,12 @@ async function loadConfig(customPath) {
21426
21578
  throw new Error(`Failed to parse ${configFile}: ${message}`, { cause: error });
21427
21579
  }
21428
21580
  }
21581
+ async function loadEffectiveConfig(customPath, cliFlags) {
21582
+ const userConfig = await loadUserConfig();
21583
+ const projectConfig = await loadConfig(customPath);
21584
+ const envOverrides = loadEnvOverrides();
21585
+ return mergeConfigs(userConfig, projectConfig, envOverrides, cliFlags);
21586
+ }
21429
21587
 
21430
21588
  // packages/cli/src/commands/compile.ts
21431
21589
  init_loader();
@@ -21489,8 +21647,8 @@ init_src4();
21489
21647
  init_src2();
21490
21648
  init_src();
21491
21649
  import { existsSync as existsSync9 } from "fs";
21492
- import { lstat as lstat3, readdir as readdir4, readFile as readFile11 } from "fs/promises";
21493
- import { basename as basename11, dirname as dirname7, join as join8 } from "path";
21650
+ import { lstat as lstat4, readdir as readdir4, readFile as readFile11 } from "fs/promises";
21651
+ import { basename as basename11, dirname as dirname7, join as join8, relative as relative4, resolve as resolve9 } from "path";
21494
21652
 
21495
21653
  // packages/resolver/src/loader.ts
21496
21654
  init_src();
@@ -23033,10 +23191,10 @@ function parseSkillIgnore(content) {
23033
23191
  return { patterns };
23034
23192
  }
23035
23193
  function isIgnoredByRules(relPath, rules) {
23036
- const basename16 = relPath.split("/").pop() ?? relPath;
23194
+ const basename17 = relPath.split("/").pop() ?? relPath;
23037
23195
  let ignored = false;
23038
23196
  for (const { regex, matchPath, negated } of rules.patterns) {
23039
- const target = matchPath ? relPath : basename16;
23197
+ const target = matchPath ? relPath : basename17;
23040
23198
  if (regex.test(target)) {
23041
23199
  ignored = !negated;
23042
23200
  }
@@ -24596,6 +24754,27 @@ var GitRegistry = class {
24596
24754
  await this.cacheManager.remove(this.url, targetRef);
24597
24755
  await this.ensureCloned(targetRef);
24598
24756
  }
24757
+ /**
24758
+ * Checkout a specific commit in an already-cloned repository.
24759
+ * Used to enforce lockfile pinning: after cloning at a tag/branch,
24760
+ * checkout the exact commit recorded in the lockfile.
24761
+ *
24762
+ * @param targetDir - Path to the cloned repository
24763
+ * @param commit - Commit hash to checkout
24764
+ */
24765
+ async checkoutCommit(targetDir, commit) {
24766
+ const git = this.createGit(targetDir);
24767
+ try {
24768
+ await git.fetch(["origin", commit, "--depth=1"]);
24769
+ } catch {
24770
+ try {
24771
+ await git.fetch(["--unshallow"]);
24772
+ } catch {
24773
+ await git.fetch(["origin"]);
24774
+ }
24775
+ }
24776
+ await git.checkout(commit);
24777
+ }
24599
24778
  /**
24600
24779
  * Get the current commit hash for a ref.
24601
24780
  *
@@ -25125,8 +25304,16 @@ async function validateRemoteAccess(repoUrl) {
25125
25304
  }
25126
25305
 
25127
25306
  // packages/resolver/src/registry-cache.ts
25128
- import { mkdir as mkdir3, stat, writeFile as writeFile3, readFile as readFile9 } from "fs/promises";
25129
- import { join as join7 } from "path";
25307
+ import { mkdir as mkdir3, stat, writeFile as writeFile3, readFile as readFile9, lstat as lstat2 } from "fs/promises";
25308
+ import { join as join7, resolve as resolve7, relative as relative3 } from "path";
25309
+ function validatePathComponent(component, label) {
25310
+ if (component.includes("..")) {
25311
+ throw new Error(`Invalid ${label}: contains parent directory traversal (..)`);
25312
+ }
25313
+ if (component.startsWith("/")) {
25314
+ throw new Error(`Invalid ${label}: absolute paths are not allowed`);
25315
+ }
25316
+ }
25130
25317
  var RegistryCache = class {
25131
25318
  constructor(baseDir) {
25132
25319
  this.baseDir = baseDir;
@@ -25134,7 +25321,13 @@ var RegistryCache = class {
25134
25321
  baseDir;
25135
25322
  getCachePath(repoUrl, version) {
25136
25323
  const normalized = repoUrl.replace(/^(https?:\/\/|git@|git:\/\/)/, "").replace(":", "/");
25137
- return join7(this.baseDir, "registries", normalized, version);
25324
+ validatePathComponent(version, "version");
25325
+ const result = join7(this.baseDir, "registries", normalized, version);
25326
+ const rel = relative3(resolve7(this.baseDir), resolve7(result));
25327
+ if (rel.startsWith("..")) {
25328
+ throw new Error(`Path traversal detected: version "${version}" escapes cache root`);
25329
+ }
25330
+ return result;
25138
25331
  }
25139
25332
  async has(repoUrl, version) {
25140
25333
  try {
@@ -25148,8 +25341,19 @@ var RegistryCache = class {
25148
25341
  async set(repoUrl, version, commit) {
25149
25342
  const cachePath = this.getCachePath(repoUrl, version);
25150
25343
  await mkdir3(cachePath, { recursive: true });
25344
+ const metaPath = join7(cachePath, ".prs-registry-meta.json");
25345
+ try {
25346
+ const statResult = await lstat2(metaPath);
25347
+ if (statResult.isSymbolicLink()) {
25348
+ throw new Error(
25349
+ `Refusing to write metadata: ${metaPath} is a symlink (possible supply-chain attack)`
25350
+ );
25351
+ }
25352
+ } catch (err) {
25353
+ if (err.code !== "ENOENT") throw err;
25354
+ }
25151
25355
  const meta = { commit, cachedAt: Date.now() };
25152
- await writeFile3(join7(cachePath, ".prs-registry-meta.json"), JSON.stringify(meta, null, 2));
25356
+ await writeFile3(metaPath, JSON.stringify(meta, null, 2));
25153
25357
  return cachePath;
25154
25358
  }
25155
25359
  async isStale(repoUrl, version, ttlMs) {
@@ -25198,9 +25402,16 @@ var RegistryCache = class {
25198
25402
  }
25199
25403
  };
25200
25404
 
25405
+ // packages/resolver/src/reference-hasher.ts
25406
+ import { createHash as createHash2 } from "crypto";
25407
+ function hashContent(content) {
25408
+ const hex = createHash2("sha256").update(content).digest("hex");
25409
+ return `sha256-${hex}`;
25410
+ }
25411
+
25201
25412
  // packages/resolver/src/auto-discovery.ts
25202
- import { readFile as readFile10, readdir as readdir3, access as access2, lstat as lstat2 } from "fs/promises";
25203
- import { resolve as resolve7, basename as basename10 } from "path";
25413
+ import { readFile as readFile10, readdir as readdir3, access as access2, lstat as lstat3 } from "fs/promises";
25414
+ import { resolve as resolve8, basename as basename10 } from "path";
25204
25415
  var CONTEXT_FILES = ["CLAUDE.md", ".clinerules", ".cursorrules"];
25205
25416
  async function fileExists2(path) {
25206
25417
  try {
@@ -25236,9 +25447,9 @@ async function discoverSkills(dir) {
25236
25447
  const properties = {};
25237
25448
  for (const entry of entries) {
25238
25449
  if (!entry.isDirectory()) continue;
25239
- let skillMdPath = resolve7(dir, entry.name, "SKILL.md");
25450
+ let skillMdPath = resolve8(dir, entry.name, "SKILL.md");
25240
25451
  if (!await fileExists2(skillMdPath)) {
25241
- const dirnameMdPath = resolve7(dir, entry.name, `${entry.name}.md`);
25452
+ const dirnameMdPath = resolve8(dir, entry.name, `${entry.name}.md`);
25242
25453
  if (await fileExists2(dirnameMdPath)) {
25243
25454
  skillMdPath = dirnameMdPath;
25244
25455
  } else {
@@ -25265,7 +25476,7 @@ async function discoverSkills(dir) {
25265
25476
  return Object.keys(properties).length > 0 ? properties : null;
25266
25477
  }
25267
25478
  async function discoverRootSkill(dir) {
25268
- const skillMdPath = resolve7(dir, "SKILL.md");
25479
+ const skillMdPath = resolve8(dir, "SKILL.md");
25269
25480
  if (!await fileExists2(skillMdPath)) return null;
25270
25481
  try {
25271
25482
  const raw = await readFile10(skillMdPath, "utf-8");
@@ -25296,9 +25507,9 @@ async function discoverAgents(dir) {
25296
25507
  const properties = {};
25297
25508
  for (const entry of entries) {
25298
25509
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
25299
- const fullPath = resolve7(dir, entry.name);
25510
+ const fullPath = resolve8(dir, entry.name);
25300
25511
  try {
25301
- const stat4 = await lstat2(fullPath);
25512
+ const stat4 = await lstat3(fullPath);
25302
25513
  if (stat4.isSymbolicLink()) continue;
25303
25514
  const raw = await readFile10(fullPath, "utf-8");
25304
25515
  const fm = parseFrontmatter(raw);
@@ -25332,9 +25543,9 @@ async function discoverCommands(dir) {
25332
25543
  for (const entry of entries) {
25333
25544
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
25334
25545
  if (entry.name === "SKILL.md") continue;
25335
- const fullPath = resolve7(dir, entry.name);
25546
+ const fullPath = resolve8(dir, entry.name);
25336
25547
  try {
25337
- const stat4 = await lstat2(fullPath);
25548
+ const stat4 = await lstat3(fullPath);
25338
25549
  if (stat4.isSymbolicLink()) continue;
25339
25550
  const raw = await readFile10(fullPath, "utf-8");
25340
25551
  const fm = parseFrontmatter(raw);
@@ -25349,7 +25560,7 @@ async function discoverCommands(dir) {
25349
25560
  }
25350
25561
  async function discoverContext(dir) {
25351
25562
  for (const fileName of CONTEXT_FILES) {
25352
- const fullPath = resolve7(dir, fileName);
25563
+ const fullPath = resolve8(dir, fileName);
25353
25564
  if (!await fileExists2(fullPath)) continue;
25354
25565
  try {
25355
25566
  const content = await readFile10(fullPath, "utf-8");
@@ -25366,7 +25577,7 @@ var AGENT_WRAPPER_DIRS = ["agents"];
25366
25577
  var COMMAND_WRAPPER_DIRS = ["commands"];
25367
25578
  async function safeIsDirectory(dir) {
25368
25579
  try {
25369
- const stat4 = await lstat2(dir);
25580
+ const stat4 = await lstat3(dir);
25370
25581
  return stat4.isDirectory();
25371
25582
  } catch {
25372
25583
  return false;
@@ -25379,7 +25590,7 @@ async function discoverNativeContent(dir) {
25379
25590
  const subSkills = await discoverSkills(dir);
25380
25591
  const wrappedSkillResults = await Promise.all(
25381
25592
  SKILL_WRAPPER_DIRS.map(async (name) => {
25382
- const candidate = resolve7(dir, name);
25593
+ const candidate = resolve8(dir, name);
25383
25594
  if (!await safeIsDirectory(candidate)) return null;
25384
25595
  return discoverSkills(candidate);
25385
25596
  })
@@ -25400,7 +25611,7 @@ async function discoverNativeContent(dir) {
25400
25611
  const rootAgents = await discoverAgents(dir) ?? {};
25401
25612
  const wrappedAgents = {};
25402
25613
  for (const name of AGENT_WRAPPER_DIRS) {
25403
- const candidate = resolve7(dir, name);
25614
+ const candidate = resolve8(dir, name);
25404
25615
  if (await safeIsDirectory(candidate)) {
25405
25616
  const found = await discoverAgents(candidate);
25406
25617
  if (found) Object.assign(wrappedAgents, found);
@@ -25413,7 +25624,7 @@ async function discoverNativeContent(dir) {
25413
25624
  const rootCommands = await discoverCommands(dir) ?? {};
25414
25625
  const wrappedCommands = {};
25415
25626
  for (const name of COMMAND_WRAPPER_DIRS) {
25416
- const candidate = resolve7(dir, name);
25627
+ const candidate = resolve8(dir, name);
25417
25628
  if (await safeIsDirectory(candidate)) {
25418
25629
  const found = await discoverCommands(candidate);
25419
25630
  if (found) Object.assign(wrappedCommands, found);
@@ -25880,23 +26091,56 @@ var Resolver = class {
25880
26091
  const lockEntry = this.options.lockfile?.dependencies[repoUrl];
25881
26092
  const pinnedTag = lockEntry?.version ?? (version || void 0);
25882
26093
  const tag = pinnedTag ?? "main";
26094
+ const lockedCommit = lockEntry?.commit && /^[0-9a-f]{40}$/.test(lockEntry.commit) && !/^0{40}$/.test(lockEntry.commit) ? lockEntry.commit : null;
25883
26095
  const hasCached = await this.registryCache.has(repoUrl, effectiveVersion);
25884
26096
  let cachePath;
25885
26097
  if (hasCached) {
25886
26098
  this.logger.debug(`Registry cache hit: ${repoUrl}@${effectiveVersion}`);
25887
26099
  cachePath = this.registryCache.getCachePath(repoUrl, effectiveVersion);
26100
+ if (lockedCommit) {
26101
+ try {
26102
+ const cachedMeta = await this.registryCache.getMeta(repoUrl, effectiveVersion);
26103
+ if (cachedMeta && cachedMeta.commit !== lockedCommit) {
26104
+ this.logger.verbose(
26105
+ `Lockfile commit mismatch for ${repoUrl}: cached=${cachedMeta.commit}, locked=${lockedCommit}. Re-cloning.`
26106
+ );
26107
+ const fallbackRepoUrl = this.options.registries ? findFallbackUrl(repoUrl, this.options.registries) : void 0;
26108
+ await this.gitRegistry.cloneAtTag(repoUrl, tag, cachePath, fallbackRepoUrl);
26109
+ await this.gitRegistry.checkoutCommit(cachePath, lockedCommit);
26110
+ await this.registryCache.set(repoUrl, effectiveVersion, lockedCommit);
26111
+ }
26112
+ } catch (err) {
26113
+ this.logger.debug(`Lockfile commit verification failed: ${err}`);
26114
+ }
26115
+ }
25888
26116
  } else {
25889
26117
  this.logger.verbose(`Registry cache miss, cloning: ${repoUrl}@${tag}`);
25890
26118
  cachePath = this.registryCache.getCachePath(repoUrl, effectiveVersion);
25891
26119
  const fallbackRepoUrl = this.options.registries ? findFallbackUrl(repoUrl, this.options.registries) : void 0;
25892
26120
  await this.gitRegistry.cloneAtTag(repoUrl, tag, cachePath, fallbackRepoUrl);
25893
- const commitHash = lockEntry?.commit ?? "unknown";
26121
+ if (lockedCommit) {
26122
+ this.logger.verbose(`Checking out locked commit: ${lockedCommit}`);
26123
+ await this.gitRegistry.checkoutCommit(cachePath, lockedCommit);
26124
+ }
26125
+ const commitHash = lockedCommit ?? lockEntry?.commit ?? "unknown";
25894
26126
  await this.registryCache.set(repoUrl, effectiveVersion, commitHash);
25895
26127
  }
25896
26128
  const isRoot = subPath === "";
25897
26129
  const isMdPath = !isRoot && subPath.endsWith(".md");
25898
26130
  const resolvedFileName = isRoot ? "" : isMdPath ? subPath : subPath.endsWith(".prs") ? subPath : `${subPath}.prs`;
25899
26131
  const resolvedFullPath = isRoot ? "" : join8(cachePath, resolvedFileName);
26132
+ if (!isRoot) {
26133
+ const rel = relative4(resolve9(cachePath), resolve9(resolvedFullPath));
26134
+ if (rel.startsWith("..") || resolve9(resolvedFullPath) === resolve9(cachePath)) {
26135
+ errors.push(
26136
+ new ResolveError(
26137
+ `Path traversal detected: subpath '${subPath}' escapes repository cache boundary.`
26138
+ )
26139
+ );
26140
+ this.resolving.delete(marker);
26141
+ return { ast: null, sources: [marker], errors };
26142
+ }
26143
+ }
25900
26144
  let resolvedAST = null;
25901
26145
  if (!isRoot && existsSync9(resolvedFullPath) && isMdPath) {
25902
26146
  this.logger.debug(`Found .md file: ${resolvedFullPath}`);
@@ -25922,16 +26166,43 @@ var Resolver = class {
25922
26166
  );
25923
26167
  } else {
25924
26168
  const discoverDir = isRoot ? cachePath : join8(cachePath, subPath);
25925
- this.logger.debug(`No .prs found, trying auto-discovery: ${discoverDir}`);
25926
- resolvedAST = await discoverNativeContent(discoverDir);
25927
- if (!resolvedAST) {
25928
- const where = isRoot ? "<repository root>" : `'${subPath}'`;
25929
- const hint = isRoot ? ` Specify a sub-path (e.g. ${repoUrl}/skills/<name>).` : "";
26169
+ if (!isRoot) {
26170
+ const dirRel = relative4(resolve9(cachePath), resolve9(discoverDir));
26171
+ if (dirRel.startsWith("..")) {
26172
+ errors.push(
26173
+ new ResolveError(
26174
+ `Path traversal detected: subpath '${subPath}' escapes repository cache boundary.`
26175
+ )
26176
+ );
26177
+ this.resolving.delete(marker);
26178
+ return { ast: null, sources: [marker], errors };
26179
+ }
26180
+ }
26181
+ if (!isRoot && !existsSync9(discoverDir)) {
25930
26182
  errors.push(
25931
26183
  new ResolveError(
25932
- `Cannot resolve registry import: no .prs file or native content at ${where} in ${repoUrl}.${hint}`
26184
+ `Cannot resolve registry import: path '${subPath}' does not exist in repository ${repoUrl}.`
25933
26185
  )
25934
26186
  );
26187
+ } else {
26188
+ this.logger.debug(
26189
+ `No .prs found, trying directory scan and auto-discovery: ${discoverDir}`
26190
+ );
26191
+ const dirResult = await this.tryDirectoryScan(discoverDir, [marker], []);
26192
+ if (dirResult?.ast) {
26193
+ resolvedAST = dirResult.ast;
26194
+ } else {
26195
+ resolvedAST = await discoverNativeContent(discoverDir);
26196
+ if (!resolvedAST) {
26197
+ const where = isRoot ? "<repository root>" : `'${subPath}'`;
26198
+ const hint = isRoot ? ` Specify a sub-path (e.g. ${repoUrl}/skills/<name>).` : "";
26199
+ errors.push(
26200
+ new ResolveError(
26201
+ `Cannot resolve registry import: no .prs file, .md file, or native content at ${where} in ${repoUrl}.${hint}`
26202
+ )
26203
+ );
26204
+ }
26205
+ }
25935
26206
  }
25936
26207
  }
25937
26208
  const result = {
@@ -25961,7 +26232,7 @@ var Resolver = class {
25961
26232
  async tryDirectoryScan(dirPath, sources, errors) {
25962
26233
  let stat4;
25963
26234
  try {
25964
- stat4 = await lstat3(dirPath);
26235
+ stat4 = await lstat4(dirPath);
25965
26236
  } catch {
25966
26237
  return null;
25967
26238
  }
@@ -26014,7 +26285,7 @@ var Resolver = class {
26014
26285
  const subDir = join8(currentDir, entry.name);
26015
26286
  let subStat;
26016
26287
  try {
26017
- subStat = await lstat3(subDir);
26288
+ subStat = await lstat4(subDir);
26018
26289
  } catch {
26019
26290
  continue;
26020
26291
  }
@@ -26069,6 +26340,41 @@ var Resolver = class {
26069
26340
  clearCache() {
26070
26341
  this.cache.clear();
26071
26342
  }
26343
+ /**
26344
+ * Verify integrity hashes for registry reference files.
26345
+ * Reads each referenced file from the registry cache and compares its
26346
+ * hash against the lockfile entry.
26347
+ *
26348
+ * @param lockfile - Lockfile with reference hashes
26349
+ * @returns Array of errors for mismatched references
26350
+ */
26351
+ async verifyReferenceHashes(lockfile) {
26352
+ if (!lockfile.references) return [];
26353
+ const errors = [];
26354
+ for (const [key, entry] of Object.entries(lockfile.references)) {
26355
+ const parts = key.split("\0");
26356
+ if (parts.length !== 3) continue;
26357
+ const [repoUrl, relativePath, version] = parts;
26358
+ try {
26359
+ const cachePath = this.registryCache.getCachePath(repoUrl, version);
26360
+ const fullPath = join8(cachePath, relativePath);
26361
+ if (!existsSync9(fullPath)) continue;
26362
+ const content = await readFile11(fullPath);
26363
+ const actualHash = hashContent(content);
26364
+ if (actualHash !== entry.hash) {
26365
+ errors.push(
26366
+ new ResolveError(
26367
+ `Reference file hash mismatch: ${relativePath} has changed since last lock. Run \`prs lock --update\` to accept changes.`,
26368
+ void 0,
26369
+ "PS2023" /* LOCKFILE_INTEGRITY */
26370
+ )
26371
+ );
26372
+ }
26373
+ } catch {
26374
+ }
26375
+ }
26376
+ return errors;
26377
+ }
26072
26378
  /**
26073
26379
  * Get the file loader.
26074
26380
  */
@@ -26162,7 +26468,7 @@ var HttpRegistry = class {
26162
26468
  * Sleep for specified milliseconds.
26163
26469
  */
26164
26470
  sleep(ms) {
26165
- return new Promise((resolve22) => setTimeout(resolve22, ms));
26471
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
26166
26472
  }
26167
26473
  /**
26168
26474
  * Fetch with timeout.
@@ -26544,13 +26850,6 @@ function formatSkillValidationIssues(issues) {
26544
26850
  // packages/resolver/src/index.ts
26545
26851
  init_src();
26546
26852
 
26547
- // packages/resolver/src/reference-hasher.ts
26548
- import { createHash as createHash2 } from "crypto";
26549
- function hashContent(content) {
26550
- const hex = createHash2("sha256").update(content).digest("hex");
26551
- return `sha256-${hex}`;
26552
- }
26553
-
26554
26853
  // packages/validator/src/validator.ts
26555
26854
  init_src();
26556
26855
 
@@ -26767,10 +27066,10 @@ function walkValue(value, loc, callback, exclude) {
26767
27066
  const typed = value;
26768
27067
  if (typed.type === "TextContent" && typeof typed.value === "string") {
26769
27068
  callback(typed.value, typed.loc ?? loc);
27069
+ return;
26770
27070
  }
26771
- } else {
26772
- walkObjectProperties(value, loc, callback, exclude);
26773
27071
  }
27072
+ walkObjectProperties(value, loc, callback, exclude);
26774
27073
  }
26775
27074
  }
26776
27075
  function offsetLocation(baseLoc, text, charIndex) {
@@ -27715,7 +28014,8 @@ var AUTHORITY_PATTERNS = [
27715
28014
  /\[?\s{0,10}PRIORITY\s{0,10}(?:OVERRIDE|ONE|ALPHA)\s{0,10}\]?/i,
27716
28015
  /\[?\s{0,10}EMERGENCY\s{0,10}(?:PROTOCOL|OVERRIDE|MODE)\s{0,10}\]?/i,
27717
28016
  // Warning suppression patterns
27718
- /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:WARN|ALERT|NOTIFY|FLAG|REPORT)/i,
28017
+ // Removed because it triggers false positives on valid agent instructions (e.g., "do not notify user")
28018
+ // /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:WARN|ALERT|NOTIFY|FLAG|REPORT)/i,
27719
28019
  /(?:DO\s{1,10}NOT|NEVER|DON'?T)\s{1,10}(?:PROVIDE|SHOW|DISPLAY|INCLUDE)\s{1,10}(?:SECURITY\s{1,10})?WARNINGS?/i,
27720
28020
  /(?:SUPPRESS|HIDE|DISABLE|REMOVE|SILENCE)\s{1,10}(?:ALL\s{1,10})?WARNINGS?/i,
27721
28021
  /(?:SUPPRESS|HIDE|DISABLE|REMOVE|SILENCE)\s{1,10}(?:ALL\s{1,10})?(?:SECURITY\s{1,10})?(?:ALERTS?|NOTIFICATIONS?)/i,
@@ -27858,7 +28158,10 @@ function decodeRawHex(hex) {
27858
28158
  if (isNaN(byte)) return null;
27859
28159
  bytes.push(byte);
27860
28160
  }
27861
- const decoded = String.fromCharCode(...bytes);
28161
+ let decoded = "";
28162
+ for (const byte of bytes) {
28163
+ decoded += String.fromCharCode(byte);
28164
+ }
27862
28165
  if (/[\x00-\x08\x0E-\x1F]/.test(decoded)) {
27863
28166
  return null;
27864
28167
  }
@@ -29356,10 +29659,14 @@ function getComposedFrom(skill) {
29356
29659
  return raw.filter(isComposedFromEntry);
29357
29660
  }
29358
29661
  function extractRegistry(source) {
29359
- if (!source.startsWith("@")) return null;
29360
- const slash = source.indexOf("/");
29361
- if (slash === -1) return source;
29362
- return source.slice(0, slash);
29662
+ if (source.startsWith("@")) {
29663
+ const slash = source.indexOf("/");
29664
+ if (slash === -1) return source;
29665
+ return source.slice(0, slash);
29666
+ }
29667
+ const match = /\/(@[a-zA-Z_][a-zA-Z0-9_-]*)\//.exec(source);
29668
+ if (match) return match[1] ?? null;
29669
+ return null;
29363
29670
  }
29364
29671
  function matchesTargetPattern(composedFrom, targetPattern) {
29365
29672
  const registry2 = extractRegistry(targetPattern);
@@ -29621,6 +29928,17 @@ var Validator = class {
29621
29928
  }
29622
29929
  this.logger.debug(`Validator initialized with ${this.rules.length} rules`);
29623
29930
  }
29931
+ /**
29932
+ * Update validator configuration after construction.
29933
+ * Allows the compiler to inject runtime data (registry references, lockfile, etc.)
29934
+ * that becomes available only after resolution.
29935
+ */
29936
+ updateConfig(partial) {
29937
+ this.config = { ...this.config, ...partial };
29938
+ if (partial.disableRules) {
29939
+ this.disabledRules = new Set(partial.disableRules);
29940
+ }
29941
+ }
29624
29942
  /**
29625
29943
  * Validate an AST.
29626
29944
  *
@@ -29751,7 +30069,7 @@ var SECURITY_STRICT_MULTILINGUAL = {
29751
30069
  };
29752
30070
 
29753
30071
  // packages/compiler/src/compiler.ts
29754
- import { relative as relative3, isAbsolute as isAbsolute4 } from "path";
30072
+ import { relative as relative5, isAbsolute as isAbsolute4 } from "path";
29755
30073
  function generateHtmlMarker(source, target) {
29756
30074
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
29757
30075
  return `<!-- PromptScript ${timestamp} | source: ${source} | target: ${target} - do not edit -->`;
@@ -29827,7 +30145,7 @@ var Compiler = class _Compiler {
29827
30145
  formatTime: 0,
29828
30146
  totalTime: 0
29829
30147
  };
29830
- const sourceLabel = isAbsolute4(entryPath) ? relative3(process.cwd(), entryPath) : entryPath;
30148
+ const sourceLabel = isAbsolute4(entryPath) ? relative5(process.cwd(), entryPath) : entryPath;
29831
30149
  this.logger.verbose("=== Stage 1: Resolve ===");
29832
30150
  const startResolve = Date.now();
29833
30151
  let resolved;
@@ -29861,6 +30179,7 @@ var Compiler = class _Compiler {
29861
30179
  stats
29862
30180
  };
29863
30181
  }
30182
+ const compileErrors = [];
29864
30183
  if (!this.options.ignoreHashes && this.options.resolver.lockfile?.references) {
29865
30184
  this.logger.verbose("=== Stage 1.5: Reference Integrity ===");
29866
30185
  const registryReferences = /* @__PURE__ */ new Set();
@@ -29877,17 +30196,29 @@ var Compiler = class _Compiler {
29877
30196
  }
29878
30197
  }
29879
30198
  }
29880
- if (this.options.validator) {
29881
- this.options.validator.registryReferences = registryReferences;
29882
- this.options.validator.lockfile = this.options.resolver.lockfile;
29883
- this.options.validator.ignoreHashes = this.options.ignoreHashes;
30199
+ const hashErrors = await this.resolver.verifyReferenceHashes(this.options.resolver.lockfile);
30200
+ for (const err of hashErrors) {
30201
+ compileErrors.push(this.toCompileError(err));
29884
30202
  }
30203
+ this.validator.updateConfig({
30204
+ registryReferences,
30205
+ lockfile: this.options.resolver.lockfile,
30206
+ ignoreHashes: this.options.ignoreHashes
30207
+ });
29885
30208
  } else if (this.options.ignoreHashes) {
29886
30209
  this.logger.verbose("--ignore-hashes is set: reference integrity verification is disabled");
29887
30210
  console.error("\u26A0 --ignore-hashes is set: reference integrity verification is disabled");
29888
- if (this.options.validator) {
29889
- this.options.validator.ignoreHashes = true;
29890
- }
30211
+ this.validator.updateConfig({ ignoreHashes: true });
30212
+ }
30213
+ if (compileErrors.length > 0) {
30214
+ stats.totalTime = Date.now() - startTotal;
30215
+ return {
30216
+ success: false,
30217
+ outputs: /* @__PURE__ */ new Map(),
30218
+ errors: compileErrors,
30219
+ warnings: [],
30220
+ stats
30221
+ };
29891
30222
  }
29892
30223
  this.logger.verbose("=== Stage 2: Validate ===");
29893
30224
  const startValidate = Date.now();
@@ -30084,12 +30415,12 @@ var Compiler = class _Compiler {
30084
30415
  */
30085
30416
  async watch(entryPath, options = {}) {
30086
30417
  const { default: chokidar2 } = await import("chokidar");
30087
- const { dirname: dirname17, resolve: resolve22 } = await import("path");
30088
- const baseDir = dirname17(resolve22(entryPath));
30418
+ const { dirname: dirname18, resolve: resolve24 } = await import("path");
30419
+ const baseDir = dirname18(resolve24(entryPath));
30089
30420
  const includePatterns = options.include ?? ["**/*.prs"];
30090
30421
  const excludePatterns = options.exclude ?? ["**/node_modules/**"];
30091
30422
  const debounceMs = options.debounce ?? 300;
30092
- const watchPatterns = includePatterns.map((p) => resolve22(baseDir, p));
30423
+ const watchPatterns = includePatterns.map((p) => resolve24(baseDir, p));
30093
30424
  let debounceTimer = null;
30094
30425
  let pendingChanges = [];
30095
30426
  const handleChange = async (changedFiles) => {
@@ -30264,7 +30595,7 @@ var Pager = class {
30264
30595
  }
30265
30596
  return;
30266
30597
  }
30267
- return new Promise((resolve22) => {
30598
+ return new Promise((resolve24) => {
30268
30599
  const pagerCmd = getPagerCommand();
30269
30600
  const [cmd, ...args] = pagerCmd.split(" ");
30270
30601
  if (cmd === "less" && !args.includes("-R")) {
@@ -30272,7 +30603,7 @@ var Pager = class {
30272
30603
  }
30273
30604
  if (!cmd) {
30274
30605
  console.log(content);
30275
- resolve22();
30606
+ resolve24();
30276
30607
  return;
30277
30608
  }
30278
30609
  const pager = spawn(cmd, args, {
@@ -30285,17 +30616,17 @@ var Pager = class {
30285
30616
  });
30286
30617
  pager.on("error", (_err) => {
30287
30618
  console.log(content);
30288
- resolve22();
30619
+ resolve24();
30289
30620
  });
30290
30621
  pager.on("close", () => {
30291
- resolve22();
30622
+ resolve24();
30292
30623
  });
30293
30624
  if (pager.stdin) {
30294
30625
  pager.stdin.write(content);
30295
30626
  pager.stdin.end();
30296
30627
  } else {
30297
30628
  console.log(content);
30298
- resolve22();
30629
+ resolve24();
30299
30630
  }
30300
30631
  });
30301
30632
  }
@@ -30405,9 +30736,9 @@ var __dirname2 = dirname9(__filename2);
30405
30736
  async function loadBundledSkillContent(logger) {
30406
30737
  const skillRelPath = "skills/promptscript/SKILL.md";
30407
30738
  const candidates = [
30408
- resolve8(__dirname2, skillRelPath),
30739
+ resolve10(__dirname2, skillRelPath),
30409
30740
  // bundled: dist/packages/cli/skills/...
30410
- resolve8(__dirname2, "..", "..", skillRelPath)
30741
+ resolve10(__dirname2, "..", "..", skillRelPath)
30411
30742
  // dev: packages/cli/skills/...
30412
30743
  ];
30413
30744
  for (const candidate of candidates) {
@@ -30428,7 +30759,7 @@ async function loadBundledSkillContent(logger) {
30428
30759
  }
30429
30760
  function findConfigInDir(dir) {
30430
30761
  for (const file of CONFIG_FILES) {
30431
- const fullPath = resolve8(dir, file);
30762
+ const fullPath = resolve10(dir, file);
30432
30763
  if (existsSync12(fullPath)) {
30433
30764
  return fullPath;
30434
30765
  }
@@ -30485,7 +30816,7 @@ function getBuildProfile(config, buildName) {
30485
30816
  }
30486
30817
  function resolveOutputBase(projectRoot, output) {
30487
30818
  if (!output) return projectRoot;
30488
- return isAbsolute5(output) ? output : resolve8(projectRoot, output);
30819
+ return isAbsolute5(output) ? output : resolve10(projectRoot, output);
30489
30820
  }
30490
30821
  async function isPromptScriptGenerated2(filePath) {
30491
30822
  try {
@@ -30551,7 +30882,7 @@ async function writeOutputs(outputs, options, _config, services) {
30551
30882
  }
30552
30883
  }
30553
30884
  for (const output of outputs.values()) {
30554
- const outputPath = options.output ? resolve8(options.output, output.path) : resolve8(output.path);
30885
+ const outputPath = options.output ? resolve10(options.output, output.path) : resolve10(output.path);
30555
30886
  const fileExists3 = existsSync12(outputPath);
30556
30887
  if (options.dryRun) {
30557
30888
  if (fileExists3) {
@@ -30685,14 +31016,21 @@ async function compileCommand(options, services = createDefaultServices()) {
30685
31016
  const spinner = createSpinner("Loading configuration...").start();
30686
31017
  const logger = createCliLogger();
30687
31018
  try {
30688
- const projectRoot = options.cwd ? resolve8(options.cwd) : process.cwd();
31019
+ const projectRoot = options.cwd ? resolve10(options.cwd) : process.cwd();
30689
31020
  logger.verbose("Loading configuration...");
30690
31021
  const configPath = options.config ? options.config : options.cwd ? findConfigInDir(projectRoot) : void 0;
30691
- const config = await loadConfig(configPath);
31022
+ const config = await loadEffectiveConfig(configPath);
30692
31023
  const buildProfile = getBuildProfile(config, options.build);
30693
31024
  const selectedTarget = options.target ?? options.format;
30694
31025
  const targetEntries = buildProfile?.targets ?? config.targets;
30695
- const targets = selectedTarget ? [{ name: selectedTarget }] : parseTargets(targetEntries);
31026
+ const parsedTargets = parseTargets(targetEntries);
31027
+ let targets;
31028
+ if (selectedTarget) {
31029
+ const matched = parsedTargets.find((t) => t.name === selectedTarget);
31030
+ targets = matched ? [matched] : [{ name: selectedTarget }];
31031
+ } else {
31032
+ targets = parsedTargets;
31033
+ }
30696
31034
  const conflicts = detectOutputConflicts(targets);
30697
31035
  if (conflicts.size > 0) {
30698
31036
  const lines = [...conflicts.entries()].map(
@@ -30725,7 +31063,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30725
31063
  }
30726
31064
  }
30727
31065
  let lockfile;
30728
- const lockfilePath = resolve8(projectRoot, "promptscript.lock");
31066
+ const lockfilePath = resolve10(projectRoot, "promptscript.lock");
30729
31067
  try {
30730
31068
  const lockfileContent = await readFile12(lockfilePath, "utf-8");
30731
31069
  const parsed = parseYaml5(lockfileContent, { maxAliasCount: 100 });
@@ -30745,7 +31083,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30745
31083
  if (config.includePromptScriptSkill !== false) {
30746
31084
  skillContent = await loadBundledSkillContent(logger);
30747
31085
  }
30748
- const localPath = resolve8(projectRoot, ".promptscript");
31086
+ const localPath = resolve10(projectRoot, ".promptscript");
30749
31087
  const compiler = new Compiler({
30750
31088
  resolver: {
30751
31089
  registryPath,
@@ -30765,7 +31103,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30765
31103
  ignoreHashes: options.ignoreHashes
30766
31104
  });
30767
31105
  const entry = buildProfile?.entry ?? config.input?.entry;
30768
- const entryPath = entry ? resolve8(projectRoot, entry) : resolve8(localPath, "project.prs");
31106
+ const entryPath = entry ? resolve10(projectRoot, entry) : resolve10(localPath, "project.prs");
30769
31107
  if (!existsSync12(entryPath)) {
30770
31108
  spinner.fail("Entry file not found");
30771
31109
  ConsoleOutput.error(`File not found: ${entryPath}`);
@@ -30805,7 +31143,7 @@ Disable one of the conflicting targets or assign a custom output path.`
30805
31143
  ConsoleOutput.newline();
30806
31144
  ConsoleOutput.info("Watching for changes... (Ctrl+C to stop)");
30807
31145
  watchForChanges(
30808
- resolve8(projectRoot, ".promptscript"),
31146
+ resolve10(projectRoot, ".promptscript"),
30809
31147
  () => compileCommand({ ...options, watch: false }, services)
30810
31148
  );
30811
31149
  }
@@ -30856,7 +31194,7 @@ function watchForChanges(dir, callback) {
30856
31194
  }
30857
31195
 
30858
31196
  // packages/cli/src/commands/validate.ts
30859
- import { resolve as resolve9, join as join12 } from "path";
31197
+ import { resolve as resolve11, join as join12 } from "path";
30860
31198
  import { existsSync as existsSync13, readFileSync as readFileSync4, writeFileSync, readdirSync } from "fs";
30861
31199
  init_console();
30862
31200
  init_src();
@@ -31006,7 +31344,7 @@ async function validateCommand(options) {
31006
31344
  formatters: []
31007
31345
  // No formatters needed for validation only
31008
31346
  });
31009
- const entryPath = resolve9("./.promptscript/project.prs");
31347
+ const entryPath = resolve11("./.promptscript/project.prs");
31010
31348
  if (!existsSync13(entryPath)) {
31011
31349
  handleEntryNotFound(entryPath, isJsonFormat, spinner);
31012
31350
  return;
@@ -31090,7 +31428,7 @@ ${fixedCount} file(s) fixed.`);
31090
31428
  // packages/cli/src/commands/pull.ts
31091
31429
  import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
31092
31430
  import { existsSync as existsSync14 } from "fs";
31093
- import { resolve as resolve10, dirname as dirname10 } from "path";
31431
+ import { resolve as resolve12, dirname as dirname10 } from "path";
31094
31432
  init_console();
31095
31433
  async function pullCommand(options) {
31096
31434
  const spinner = createSpinner("Loading configuration...").start();
@@ -31115,7 +31453,7 @@ async function pullCommand(options) {
31115
31453
  }
31116
31454
  spinner.text = `Fetching ${inheritPath}...`;
31117
31455
  const content = await registry2.fetch(inheritPath);
31118
- const destPath = resolve10("./.promptscript/.inherited", inheritPath);
31456
+ const destPath = resolve12("./.promptscript/.inherited", inheritPath);
31119
31457
  if (existsSync14(destPath) && !options.force && !options.dryRun) {
31120
31458
  spinner.warn("File already exists (use --force to overwrite)");
31121
31459
  ConsoleOutput.muted(destPath);
@@ -31177,7 +31515,7 @@ async function createRegistry(config, options, spinner) {
31177
31515
  if (!existsSync14(registryPath)) {
31178
31516
  throw new Error(`Local registry path not found: ${registryPath}`);
31179
31517
  }
31180
- return createFileSystemRegistry(resolve10(registryPath));
31518
+ return createFileSystemRegistry(resolve12(registryPath));
31181
31519
  }
31182
31520
  function parseInheritPath(inheritPath) {
31183
31521
  const versionIndex = inheritPath.lastIndexOf("@");
@@ -31224,7 +31562,7 @@ function handlePullError(error, spinner) {
31224
31562
  }
31225
31563
 
31226
31564
  // packages/cli/src/commands/diff.ts
31227
- import { resolve as resolve11 } from "path";
31565
+ import { resolve as resolve13 } from "path";
31228
31566
  import { readFile as readFile13 } from "fs/promises";
31229
31567
  import { existsSync as existsSync15 } from "fs";
31230
31568
  init_console();
@@ -31261,7 +31599,7 @@ function printNewFilePreview(content, showFull, pager) {
31261
31599
  }
31262
31600
  }
31263
31601
  async function compareOutput(_name, output, _config, showFull, pager) {
31264
- const outputPath = resolve11(output.path);
31602
+ const outputPath = resolve13(output.path);
31265
31603
  const newContent = output.content;
31266
31604
  if (!existsSync15(outputPath)) {
31267
31605
  pager.write(chalk2.green(`+ ${outputPath} (new file)`));
@@ -31303,7 +31641,7 @@ async function diffCommand(options) {
31303
31641
  formatters: targets,
31304
31642
  customConventions: config.customConventions
31305
31643
  });
31306
- const entryPath = resolve11("./.promptscript/project.prs");
31644
+ const entryPath = resolve13("./.promptscript/project.prs");
31307
31645
  if (!existsSync15(entryPath)) {
31308
31646
  spinner.fail("Entry file not found");
31309
31647
  ConsoleOutput.error(`File not found: ${entryPath}`);
@@ -31373,7 +31711,7 @@ function printSimpleDiff(existingLines, newLines, showFull, pager) {
31373
31711
 
31374
31712
  // packages/cli/src/commands/check.ts
31375
31713
  import { existsSync as existsSync16 } from "fs";
31376
- import { resolve as resolve12 } from "path";
31714
+ import { resolve as resolve14 } from "path";
31377
31715
  init_console();
31378
31716
  async function checkCommand(_options) {
31379
31717
  const spinner = createSpinner("Checking project health...").start();
@@ -31451,7 +31789,7 @@ async function checkCommand(_options) {
31451
31789
  hasErrors = true;
31452
31790
  }
31453
31791
  if (config.registry?.path) {
31454
- const registryPath = resolve12(config.registry.path);
31792
+ const registryPath = resolve14(config.registry.path);
31455
31793
  if (existsSync16(registryPath)) {
31456
31794
  results.push({
31457
31795
  name: "Registry path",
@@ -31815,8 +32153,32 @@ var SEED_SECURITY = `@meta {
31815
32153
  `;
31816
32154
  async function scaffoldRegistry(options, services) {
31817
32155
  const { fs: fs4 } = services;
31818
- const { directory, name, description, namespaces, seed } = options;
32156
+ const { directory, name, description, namespaces, seed, force } = options;
31819
32157
  const createdFiles = [];
32158
+ const existingManifestPath = join14(directory, "registry-manifest.yaml");
32159
+ if (fs4.existsSync(existingManifestPath) && !force) {
32160
+ throw new Error(
32161
+ `Directory already contains a registry-manifest.yaml. Use --force to overwrite.`
32162
+ );
32163
+ }
32164
+ if (!force) {
32165
+ let entries;
32166
+ try {
32167
+ entries = await fs4.readdir(directory);
32168
+ } catch (err) {
32169
+ const nodeErr = err;
32170
+ if (nodeErr.code !== "ENOENT") {
32171
+ throw err;
32172
+ }
32173
+ entries = [];
32174
+ }
32175
+ const visibleEntries = entries.filter((e) => !e.startsWith("."));
32176
+ if (visibleEntries.length > 0) {
32177
+ throw new Error(
32178
+ `Directory "${directory}" is not empty. Use --force to overwrite existing files.`
32179
+ );
32180
+ }
32181
+ }
31820
32182
  await fs4.mkdir(directory, { recursive: true });
31821
32183
  const manifest = generateManifest(name, description, namespaces, seed);
31822
32184
  const manifestPath = join14(directory, "registry-manifest.yaml");
@@ -31956,7 +32318,7 @@ Then reference configs with \`@inherit\` or \`@use\`:
31956
32318
  }
31957
32319
 
31958
32320
  // packages/cli/src/utils/resolve-target-directory.ts
31959
- import { join as join15, resolve as resolve13 } from "path";
32321
+ import { join as join15, resolve as resolve15 } from "path";
31960
32322
 
31961
32323
  // packages/cli/src/utils/slugify.ts
31962
32324
  function slugify(name) {
@@ -31967,7 +32329,7 @@ function slugify(name) {
31967
32329
  async function resolveTargetDirectory(options, services) {
31968
32330
  const { cwd, directoryArg, registryName, nonInteractive } = options;
31969
32331
  if (directoryArg) {
31970
- return resolve13(directoryArg);
32332
+ return resolve15(directoryArg);
31971
32333
  }
31972
32334
  const empty = await isDirectoryEmpty(cwd, services.fs);
31973
32335
  if (empty && nonInteractive) {
@@ -32043,7 +32405,7 @@ async function registryInitCommand(directory, options, services = createDefaultS
32043
32405
  );
32044
32406
  const spinner = createSpinner("Creating registry...").start();
32045
32407
  const createdFiles = await scaffoldRegistry(
32046
- { directory: targetDir, name, description, namespaces, seed },
32408
+ { directory: targetDir, name, description, namespaces, seed, force: options.force },
32047
32409
  services
32048
32410
  );
32049
32411
  spinner.succeed("Registry created");
@@ -32074,7 +32436,7 @@ async function registryInitCommand(directory, options, services = createDefaultS
32074
32436
  // packages/cli/src/commands/registry/validate.ts
32075
32437
  init_services();
32076
32438
  init_console();
32077
- import { resolve as resolve14 } from "path";
32439
+ import { resolve as resolve16 } from "path";
32078
32440
 
32079
32441
  // packages/cli/src/utils/registry-validator.ts
32080
32442
  import { join as join16 } from "path";
@@ -32274,7 +32636,7 @@ function detectCircularDependencies(catalog) {
32274
32636
 
32275
32637
  // packages/cli/src/commands/registry/validate.ts
32276
32638
  async function registryValidateCommand(path, options, services = createDefaultServices()) {
32277
- const registryPath = resolve14(path ?? ".");
32639
+ const registryPath = resolve16(path ?? ".");
32278
32640
  const spinner = createSpinner("Validating registry...").start();
32279
32641
  try {
32280
32642
  const result = await validateRegistry(registryPath, services);
@@ -32326,10 +32688,10 @@ async function registryValidateCommand(path, options, services = createDefaultSe
32326
32688
  // packages/cli/src/commands/registry/publish.ts
32327
32689
  init_services();
32328
32690
  init_console();
32329
- import { resolve as resolve15, join as join17 } from "path";
32691
+ import { resolve as resolve17, join as join17 } from "path";
32330
32692
  import { execFileSync as execFileSync2 } from "child_process";
32331
32693
  async function registryPublishCommand(path, options, services = createDefaultServices()) {
32332
- const registryPath = resolve15(path ?? ".");
32694
+ const registryPath = resolve17(path ?? ".");
32333
32695
  try {
32334
32696
  if (!options.force) {
32335
32697
  const spinner2 = createSpinner("Validating registry...").start();
@@ -32554,7 +32916,7 @@ async function addToProjectConfig(alias, url) {
32554
32916
 
32555
32917
  // packages/cli/src/commands/registry/index.ts
32556
32918
  function registerRegistryCommands(registry2) {
32557
- registry2.command("init [directory]").description("Create a new PromptScript registry").option("-n, --name <name>", "Registry name").option("-d, --description <desc>", "Registry description").option("--namespaces <ns...>", "Namespace names (e.g., @core @stacks)").option("-y, --yes", "Non-interactive mode with defaults").option("-o, --output <dir>", "Output directory").option("--no-seed", "Skip seed configurations").action((directory, opts) => registryInitCommand(directory, opts));
32919
+ registry2.command("init [directory]").description("Create a new PromptScript registry").option("-n, --name <name>", "Registry name").option("-d, --description <desc>", "Registry description").option("--namespaces <ns...>", "Namespace names (e.g., @core @stacks)").option("-y, --yes", "Non-interactive mode with defaults").option("-o, --output <dir>", "Output directory").option("--no-seed", "Skip seed configurations").option("-f, --force", "Force overwrite existing files").action((directory, opts) => registryInitCommand(directory, opts));
32558
32920
  registry2.command("validate [path]").description("Validate registry structure and manifest").option("--strict", "Treat warnings as errors").option("--format <format>", "Output format (text, json)", "text").action((path, opts) => registryValidateCommand(path, opts));
32559
32921
  registry2.command("publish [path]").description("Publish registry to remote").option("--dry-run", "Preview what would be published").option("-f, --force", "Skip validation").option("-m, --message <msg>", "Git commit message").option("--tag <tag>", "Git tag for release").action((path, opts) => registryPublishCommand(path, opts));
32560
32922
  registry2.command("list").description("Show merged registry alias mappings from all config levels").action(() => registryListCommand());
@@ -32564,7 +32926,7 @@ function registerRegistryCommands(registry2) {
32564
32926
  // packages/cli/src/commands/lock.ts
32565
32927
  import { writeFile as writeFile8, readFile as readFile18 } from "fs/promises";
32566
32928
  import { existsSync as existsSync19 } from "fs";
32567
- import { resolve as resolve16 } from "path";
32929
+ import { resolve as resolve18 } from "path";
32568
32930
  import { parse as parseYaml9, stringify as stringifyYaml2 } from "yaml";
32569
32931
  init_console();
32570
32932
  init_src();
@@ -32637,8 +32999,8 @@ async function lockCommand(options) {
32637
32999
  const aliases = config.registries ?? {};
32638
33000
  const aliasEntries = Object.entries(aliases);
32639
33001
  const projectRoot = process.cwd();
32640
- const localPath = resolve16(projectRoot, ".promptscript");
32641
- const entryPath = config.input?.entry ? resolve16(projectRoot, config.input.entry) : resolve16(localPath, "project.prs");
33002
+ const localPath = resolve18(projectRoot, ".promptscript");
33003
+ const entryPath = config.input?.entry ? resolve18(projectRoot, config.input.entry) : resolve18(localPath, "project.prs");
32642
33004
  const scannedImports = await collectRemoteImports(entryPath, {
32643
33005
  localPath,
32644
33006
  registries: config.registries
@@ -32765,10 +33127,12 @@ async function updateCommand(packageArg, options) {
32765
33127
  const dependencies = { ...existing.dependencies };
32766
33128
  for (const repoUrl of toUpdate) {
32767
33129
  const before = existing.dependencies[repoUrl]?.version ?? "(none)";
33130
+ const existingDep = existing.dependencies[repoUrl];
33131
+ const validation = await validateRemoteAccess(repoUrl);
32768
33132
  const updated = {
32769
33133
  version: "latest",
32770
- commit: "0000000000000000000000000000000000000000",
32771
- integrity: "sha256-pending"
33134
+ commit: validation.headCommit ?? existingDep?.commit ?? "0000000000000000000000000000000000000000",
33135
+ integrity: existingDep?.integrity ?? "sha256-pending"
32772
33136
  };
32773
33137
  dependencies[repoUrl] = updated;
32774
33138
  updates.push({ repoUrl, before, after: updated.version });
@@ -32806,7 +33170,7 @@ init_console();
32806
33170
  init_src();
32807
33171
  import { readFile as readFile20, writeFile as writeFile10, mkdir as mkdir8, readdir as readdir5 } from "fs/promises";
32808
33172
  import { existsSync as existsSync21 } from "fs";
32809
- import { join as join18, resolve as resolve17 } from "path";
33173
+ import { join as join18, resolve as resolve19 } from "path";
32810
33174
  import { homedir as homedir4 } from "os";
32811
33175
  import { parse as parseYaml11 } from "yaml";
32812
33176
  var VENDOR_DIR = ".promptscript/vendor";
@@ -32834,7 +33198,7 @@ async function vendorSyncCommand(options) {
32834
33198
  continue;
32835
33199
  }
32836
33200
  if (!options.dryRun) {
32837
- const vendorTarget = resolve17(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
33201
+ const vendorTarget = resolve19(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32838
33202
  await mkdir8(vendorTarget, { recursive: true });
32839
33203
  await copyDirectory(cacheDir, vendorTarget);
32840
33204
  }
@@ -32888,7 +33252,7 @@ async function vendorCheckCommand(_options) {
32888
33252
  }
32889
33253
  const issues = [];
32890
33254
  for (const [repoUrl] of deps) {
32891
- const vendorTarget = resolve17(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
33255
+ const vendorTarget = resolve19(VENDOR_DIR, repoUrl.replace(/[/:]/g, "_"));
32892
33256
  if (!existsSync21(vendorTarget)) {
32893
33257
  issues.push({ repoUrl, issue: "missing from vendor directory" });
32894
33258
  }
@@ -33025,7 +33389,7 @@ async function resolveCommand(importPath, _options) {
33025
33389
 
33026
33390
  // packages/cli/src/commands/inspect.ts
33027
33391
  import { existsSync as existsSync23 } from "fs";
33028
- import { resolve as resolve18, basename as basename13 } from "path";
33392
+ import { resolve as resolve20, basename as basename13 } from "path";
33029
33393
  init_console();
33030
33394
  async function inspectCommand(skillName, options) {
33031
33395
  const isJson = options.format === "json";
@@ -33038,7 +33402,7 @@ async function inspectCommand(skillName, options) {
33038
33402
  localPath: "./.promptscript",
33039
33403
  registries: config.registries
33040
33404
  });
33041
- const entryPath = resolve18("./.promptscript/project.prs");
33405
+ const entryPath = resolve20("./.promptscript/project.prs");
33042
33406
  if (!existsSync23(entryPath)) {
33043
33407
  spinner.stop();
33044
33408
  ConsoleOutput.error(`Entry file not found: ${entryPath}`);
@@ -33219,7 +33583,7 @@ init_console();
33219
33583
  // packages/cli/src/commands/import.ts
33220
33584
  init_src3();
33221
33585
  init_console();
33222
- import { resolve as resolve19, join as join20, basename as basename14 } from "path";
33586
+ import { resolve as resolve21, join as join20, basename as basename14 } from "path";
33223
33587
  import { writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync24 } from "fs";
33224
33588
  import { stat as stat2, readdir as readdir6, readFile as readFile21, writeFile as writeFile11, mkdir as mkdir9 } from "fs/promises";
33225
33589
  function parseInstructionFrontmatter(content) {
@@ -33274,7 +33638,7 @@ async function importDirectory(dirPath) {
33274
33638
  return lines.join("\n");
33275
33639
  }
33276
33640
  async function importCommand(file, options) {
33277
- const filepath = resolve19(file);
33641
+ const filepath = resolve21(file);
33278
33642
  const inputStat = await stat2(filepath).catch(() => null);
33279
33643
  if (inputStat?.isDirectory()) {
33280
33644
  const prsContent = await importDirectory(filepath);
@@ -33306,11 +33670,11 @@ async function importCommand(file, options) {
33306
33670
  console.log(result.prsContent);
33307
33671
  return;
33308
33672
  }
33309
- const outputDir = resolve19(options.output ?? ".promptscript");
33673
+ const outputDir = resolve21(options.output ?? ".promptscript");
33310
33674
  if (!existsSync24(outputDir)) {
33311
33675
  mkdirSync(outputDir, { recursive: true });
33312
33676
  }
33313
- const outputPath = resolve19(outputDir, "imported.prs");
33677
+ const outputPath = resolve21(outputDir, "imported.prs");
33314
33678
  writeFileSync2(outputPath, result.prsContent, "utf-8");
33315
33679
  ConsoleOutput.success(`Written to ${outputPath}`);
33316
33680
  if (options.validate) {
@@ -33545,7 +33909,7 @@ init_hooks();
33545
33909
 
33546
33910
  // packages/cli/src/commands/skills.ts
33547
33911
  import { writeFile as writeFile12, readFile as readFile23, readdir as readdir7, mkdtemp, rm } from "fs/promises";
33548
- import { resolve as resolve20, join as join22, basename as basename15, dirname as dirname13 } from "path";
33912
+ import { resolve as resolve22, join as join22, basename as basename15, dirname as dirname13 } from "path";
33549
33913
  import { existsSync as existsSync26 } from "fs";
33550
33914
  import { tmpdir as tmpdir2 } from "os";
33551
33915
  import { parse as parseYaml12, stringify as stringifyYaml4 } from "yaml";
@@ -33665,7 +34029,7 @@ function validateRemoteSource(source) {
33665
34029
  }
33666
34030
  async function resolveEntryFile(fileFlag) {
33667
34031
  if (fileFlag) {
33668
- const resolved = resolve20(fileFlag);
34032
+ const resolved = resolve22(fileFlag);
33669
34033
  if (!existsSync26(resolved)) {
33670
34034
  throw new Error(`File not found: ${resolved}`);
33671
34035
  }
@@ -33676,7 +34040,7 @@ async function resolveEntryFile(fileFlag) {
33676
34040
  try {
33677
34041
  const config = await loadConfig();
33678
34042
  if (config.input?.entry) {
33679
- const entryPath = resolve20(config.input.entry);
34043
+ const entryPath = resolve22(config.input.entry);
33680
34044
  if (existsSync26(entryPath)) {
33681
34045
  return entryPath;
33682
34046
  }
@@ -33684,16 +34048,16 @@ async function resolveEntryFile(fileFlag) {
33684
34048
  } catch {
33685
34049
  }
33686
34050
  }
33687
- const promptscriptDir = resolve20(".promptscript");
34051
+ const promptscriptDir = resolve22(".promptscript");
33688
34052
  if (existsSync26(promptscriptDir)) {
33689
34053
  const entries = await readdir7(promptscriptDir);
33690
34054
  const prsFiles = entries.filter((f) => f.endsWith(".prs"));
33691
34055
  if (prsFiles.length === 1) {
33692
- return resolve20(promptscriptDir, prsFiles[0]);
34056
+ return resolve22(promptscriptDir, prsFiles[0]);
33693
34057
  }
33694
34058
  if (prsFiles.length > 1) {
33695
34059
  if (prsFiles.includes("project.prs")) {
33696
- return resolve20(promptscriptDir, "project.prs");
34060
+ return resolve22(promptscriptDir, "project.prs");
33697
34061
  }
33698
34062
  throw new Error(
33699
34063
  `Multiple .prs files found in .promptscript/. Use --file to specify which one.`
@@ -34044,7 +34408,7 @@ async function skillsUpdateCommand(name, options) {
34044
34408
 
34045
34409
  // packages/cli/src/cli.ts
34046
34410
  var __filename4 = fileURLToPath4(import.meta.url);
34047
- var __dirname4 = dirname16(__filename4);
34411
+ var __dirname4 = dirname17(__filename4);
34048
34412
  var program = new Command();
34049
34413
  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) => {
34050
34414
  const opts = thisCommand.opts();
@@ -34112,7 +34476,9 @@ registerRegistryCommands(registry);
34112
34476
  function run(args = process.argv) {
34113
34477
  program.parse(args);
34114
34478
  }
34115
- run();
34479
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
34480
+ run();
34481
+ }
34116
34482
 
34117
34483
  // packages/cli/src/index.ts
34118
34484
  init_init();
@@ -34150,7 +34516,7 @@ toad-cache/dist/toad-cache.cjs:
34150
34516
  (**
34151
34517
  * toad-cache
34152
34518
  *
34153
- * @copyright 2024 Igor Savin <kibertoad@gmail.com>
34519
+ * @copyright 2026 Igor Savin <kibertoad@gmail.com>
34154
34520
  * @license MIT
34155
34521
  * @version 3.7.0
34156
34522
  *)