@promptscript/cli 1.0.0-alpha.2 → 1.0.0-alpha.4

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
@@ -1,7 +1,7 @@
1
1
  // packages/cli/src/cli.ts
2
2
  import { Command } from "commander";
3
3
  import { fileURLToPath as fileURLToPath2 } from "url";
4
- import { dirname as dirname5 } from "path";
4
+ import { dirname as dirname7 } from "path";
5
5
 
6
6
  // packages/core/src/types/constants.ts
7
7
  var BLOCK_TYPES = [
@@ -86,6 +86,13 @@ function isBuiltInConvention(name) {
86
86
  return name in BUILT_IN_CONVENTIONS;
87
87
  }
88
88
 
89
+ // packages/core/src/types/prettier.ts
90
+ var DEFAULT_PRETTIER_OPTIONS = {
91
+ proseWrap: "preserve",
92
+ tabWidth: 2,
93
+ printWidth: 80
94
+ };
95
+
89
96
  // packages/core/src/errors/base.ts
90
97
  var PSError = class extends Error {
91
98
  /** Error code */
@@ -291,7 +298,7 @@ function getPackageVersion(baseDir, relativePath = "../package.json") {
291
298
 
292
299
  // packages/cli/src/commands/init.ts
293
300
  import { fileURLToPath } from "url";
294
- import { dirname } from "path";
301
+ import { dirname as dirname2 } from "path";
295
302
 
296
303
  // packages/cli/src/services.ts
297
304
  import { writeFile, mkdir, readFile, readdir } from "fs/promises";
@@ -308,7 +315,8 @@ var defaultFileSystem = {
308
315
  var defaultPrompts = {
309
316
  input: prompts.input,
310
317
  confirm: prompts.confirm,
311
- checkbox: prompts.checkbox
318
+ checkbox: prompts.checkbox,
319
+ select: prompts.select
312
320
  };
313
321
  var createDefaultServices = () => ({
314
322
  fs: defaultFileSystem,
@@ -378,6 +386,13 @@ var ConsoleOutput = {
378
386
  if (isQuiet()) return;
379
387
  console.log(chalk.yellow(` \u26A0 ${message}`));
380
388
  },
389
+ /**
390
+ * Print a skipped file message.
391
+ */
392
+ skipped(message) {
393
+ if (isQuiet()) return;
394
+ console.log(chalk.yellow(` \u2298 ${message}`));
395
+ },
381
396
  /**
382
397
  * Print an info message.
383
398
  */
@@ -680,9 +695,114 @@ function formatDetectionResults(detection) {
680
695
  return lines;
681
696
  }
682
697
 
698
+ // packages/cli/src/prettier/loader.ts
699
+ import { existsSync as existsSync2 } from "fs";
700
+ import { readFile as readFile2 } from "fs/promises";
701
+ import { join as join2, dirname, resolve } from "path";
702
+ import { parse as parseYaml } from "yaml";
703
+ var PRETTIER_CONFIG_FILES = [
704
+ ".prettierrc",
705
+ ".prettierrc.json",
706
+ ".prettierrc.yaml",
707
+ ".prettierrc.yml"
708
+ ];
709
+ function findPrettierConfig(startDir = process.cwd()) {
710
+ let currentDir = resolve(startDir);
711
+ const root2 = dirname(currentDir);
712
+ while (currentDir !== root2) {
713
+ for (const configFile of PRETTIER_CONFIG_FILES) {
714
+ const configPath = join2(currentDir, configFile);
715
+ if (existsSync2(configPath)) {
716
+ return configPath;
717
+ }
718
+ }
719
+ currentDir = dirname(currentDir);
720
+ }
721
+ for (const configFile of PRETTIER_CONFIG_FILES) {
722
+ const configPath = join2(currentDir, configFile);
723
+ if (existsSync2(configPath)) {
724
+ return configPath;
725
+ }
726
+ }
727
+ return null;
728
+ }
729
+ async function loadPrettierConfig(configPath) {
730
+ try {
731
+ const content = await readFile2(configPath, "utf-8");
732
+ const isYaml = configPath.endsWith(".yaml") || configPath.endsWith(".yml");
733
+ let parsed;
734
+ if (isYaml || configPath.endsWith(".prettierrc")) {
735
+ try {
736
+ parsed = parseYaml(content);
737
+ } catch {
738
+ parsed = JSON.parse(content);
739
+ }
740
+ } else {
741
+ parsed = JSON.parse(content);
742
+ }
743
+ if (!parsed || typeof parsed !== "object") {
744
+ return null;
745
+ }
746
+ const config = parsed;
747
+ const result = {};
748
+ if (typeof config["proseWrap"] === "string") {
749
+ const proseWrap = config["proseWrap"];
750
+ if (proseWrap === "always" || proseWrap === "never" || proseWrap === "preserve") {
751
+ result.proseWrap = proseWrap;
752
+ }
753
+ }
754
+ if (typeof config["tabWidth"] === "number") {
755
+ result.tabWidth = config["tabWidth"];
756
+ }
757
+ if (typeof config["printWidth"] === "number") {
758
+ result.printWidth = config["printWidth"];
759
+ }
760
+ return result;
761
+ } catch {
762
+ return null;
763
+ }
764
+ }
765
+ async function resolvePrettierOptions(config, basePath = process.cwd()) {
766
+ const formatting = config?.formatting;
767
+ if (!formatting) {
768
+ return { ...DEFAULT_PRETTIER_OPTIONS };
769
+ }
770
+ const result = { ...DEFAULT_PRETTIER_OPTIONS };
771
+ const prettier = formatting.prettier;
772
+ if (prettier === true) {
773
+ const configPath = findPrettierConfig(basePath);
774
+ if (configPath) {
775
+ const loadedOptions = await loadPrettierConfig(configPath);
776
+ if (loadedOptions) {
777
+ Object.assign(result, loadedOptions);
778
+ }
779
+ }
780
+ } else if (typeof prettier === "string") {
781
+ const configPath = resolve(basePath, prettier);
782
+ if (existsSync2(configPath)) {
783
+ const loadedOptions = await loadPrettierConfig(configPath);
784
+ if (loadedOptions) {
785
+ Object.assign(result, loadedOptions);
786
+ }
787
+ }
788
+ } else if (prettier && typeof prettier === "object") {
789
+ Object.assign(result, prettier);
790
+ }
791
+ if (formatting.proseWrap !== void 0) {
792
+ result.proseWrap = formatting.proseWrap;
793
+ }
794
+ if (formatting.tabWidth !== void 0) {
795
+ result.tabWidth = formatting.tabWidth;
796
+ }
797
+ if (formatting.printWidth !== void 0) {
798
+ result.printWidth = formatting.printWidth;
799
+ }
800
+ return result;
801
+ }
802
+
683
803
  // packages/cli/src/commands/init.ts
684
804
  var __filename = fileURLToPath(import.meta.url);
685
- var __dirname = dirname(__filename);
805
+ var __dirname = dirname2(__filename);
686
806
  async function initCommand(options, services = createDefaultServices()) {
687
807
  const { fs: fs4 } = services;
688
808
  if (fs4.existsSync("promptscript.yaml") && !options.force) {
@@ -693,7 +813,14 @@ async function initCommand(options, services = createDefaultServices()) {
693
813
  try {
694
814
  const projectInfo = await detectProject(services);
695
815
  const aiToolsDetection = await detectAITools(services);
696
- const config = await resolveConfig(options, projectInfo, aiToolsDetection, services);
816
+ const prettierConfigPath = findPrettierConfig(process.cwd());
817
+ const config = await resolveConfig(
818
+ options,
819
+ projectInfo,
820
+ aiToolsDetection,
821
+ prettierConfigPath,
822
+ services
823
+ );
697
824
  const spinner = createSpinner("Creating PromptScript configuration...").start();
698
825
  await fs4.mkdir(".promptscript", { recursive: true });
699
826
  const configContent = generateConfig(config);
@@ -716,6 +843,14 @@ async function initCommand(options, services = createDefaultServices()) {
716
843
  ConsoleOutput.muted(` Registry: ${config.registry}`);
717
844
  }
718
845
  ConsoleOutput.newline();
846
+ if (config.prettierConfigPath) {
847
+ ConsoleOutput.info(`Prettier config detected: ${config.prettierConfigPath}`);
848
+ ConsoleOutput.muted(" Output formatting will respect your Prettier settings");
849
+ } else {
850
+ ConsoleOutput.muted("No Prettier config found");
851
+ ConsoleOutput.muted(" Default formatting options added to config (tabWidth: 2)");
852
+ }
853
+ ConsoleOutput.newline();
719
854
  console.log("Next steps:");
720
855
  ConsoleOutput.muted("1. Edit .promptscript/project.prs to customize your AI instructions");
721
856
  ConsoleOutput.muted("2. Run: prs compile");
@@ -729,14 +864,15 @@ async function initCommand(options, services = createDefaultServices()) {
729
864
  process.exit(1);
730
865
  }
731
866
  }
732
- async function resolveConfig(options, projectInfo, aiToolsDetection, services) {
867
+ async function resolveConfig(options, projectInfo, aiToolsDetection, prettierConfigPath, services) {
733
868
  if (options.yes) {
734
869
  return {
735
870
  projectId: options.name ?? projectInfo.name,
736
871
  team: options.team,
737
872
  inherit: options.inherit,
738
873
  registry: options.registry ?? "./registry",
739
- targets: options.targets ?? getSuggestedTargets(aiToolsDetection)
874
+ targets: options.targets ?? getSuggestedTargets(aiToolsDetection),
875
+ prettierConfigPath
740
876
  };
741
877
  }
742
878
  if (!options.interactive && options.name && options.targets) {
@@ -745,12 +881,19 @@ async function resolveConfig(options, projectInfo, aiToolsDetection, services) {
745
881
  team: options.team,
746
882
  inherit: options.inherit,
747
883
  registry: options.registry,
748
- targets: options.targets
884
+ targets: options.targets,
885
+ prettierConfigPath
749
886
  };
750
887
  }
751
- return await runInteractivePrompts(options, projectInfo, aiToolsDetection, services);
888
+ return await runInteractivePrompts(
889
+ options,
890
+ projectInfo,
891
+ aiToolsDetection,
892
+ prettierConfigPath,
893
+ services
894
+ );
752
895
  }
753
- async function runInteractivePrompts(options, projectInfo, aiToolsDetection, services) {
896
+ async function runInteractivePrompts(options, projectInfo, aiToolsDetection, prettierConfigPath, services) {
754
897
  const { prompts: prompts2 } = services;
755
898
  ConsoleOutput.newline();
756
899
  console.log("\u{1F680} PromptScript Setup");
@@ -768,6 +911,9 @@ async function runInteractivePrompts(options, projectInfo, aiToolsDetection, ser
768
911
  for (const line of detectionLines) {
769
912
  ConsoleOutput.muted(line);
770
913
  }
914
+ if (prettierConfigPath) {
915
+ ConsoleOutput.muted(`Prettier: ${prettierConfigPath}`);
916
+ }
771
917
  ConsoleOutput.newline();
772
918
  const projectId = await prompts2.input({
773
919
  message: "Project name:",
@@ -829,7 +975,8 @@ async function runInteractivePrompts(options, projectInfo, aiToolsDetection, ser
829
975
  team,
830
976
  inherit,
831
977
  registry,
832
- targets
978
+ targets,
979
+ prettierConfigPath
833
980
  };
834
981
  }
835
982
  function formatTargetName(target) {
@@ -862,7 +1009,18 @@ function generateConfig(config) {
862
1009
  for (const target of config.targets) {
863
1010
  lines.push(` - ${target}`);
864
1011
  }
865
- lines.push("", "validation:", " rules:", " empty-block: warn", "");
1012
+ lines.push("", "validation:", " rules:", " empty-block: warn");
1013
+ lines.push("");
1014
+ if (config.prettierConfigPath) {
1015
+ lines.push("formatting:", " prettier: true # Auto-detected from project");
1016
+ } else {
1017
+ lines.push(
1018
+ "formatting:",
1019
+ " tabWidth: 2",
1020
+ " proseWrap: preserve # 'always' | 'never' | 'preserve'"
1021
+ );
1022
+ }
1023
+ lines.push("");
866
1024
  return lines.join("\n");
867
1025
  }
868
1026
  function generateProjectPs(config, projectInfo) {
@@ -912,15 +1070,15 @@ ${frameworksLine}
912
1070
  }
913
1071
 
914
1072
  // packages/cli/src/commands/compile.ts
915
- import { resolve as resolve2, dirname as dirname3 } from "path";
916
- import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
917
- import { existsSync as existsSync6 } from "fs";
1073
+ import { resolve as resolve4, dirname as dirname5 } from "path";
1074
+ import { writeFile as writeFile2, mkdir as mkdir2, readFile as readFile6 } from "fs/promises";
1075
+ import { existsSync as existsSync7 } from "fs";
918
1076
  import chokidar from "chokidar";
919
1077
 
920
1078
  // packages/cli/src/config/loader.ts
921
- import { readFile as readFile2 } from "fs/promises";
922
- import { existsSync as existsSync2 } from "fs";
923
- import { parse as parseYaml } from "yaml";
1079
+ import { readFile as readFile3 } from "fs/promises";
1080
+ import { existsSync as existsSync3 } from "fs";
1081
+ import { parse as parseYaml2 } from "yaml";
924
1082
  var CONFIG_FILES = [
925
1083
  "promptscript.yaml",
926
1084
  "promptscript.yml",
@@ -943,14 +1101,14 @@ function interpolateEnvVars(text) {
943
1101
  }
944
1102
  function findConfigFile(customPath) {
945
1103
  if (customPath) {
946
- return existsSync2(customPath) ? customPath : null;
1104
+ return existsSync3(customPath) ? customPath : null;
947
1105
  }
948
1106
  const envConfig = process.env["PROMPTSCRIPT_CONFIG"];
949
- if (envConfig && existsSync2(envConfig)) {
1107
+ if (envConfig && existsSync3(envConfig)) {
950
1108
  return envConfig;
951
1109
  }
952
1110
  for (const file of CONFIG_FILES) {
953
- if (existsSync2(file)) {
1111
+ if (existsSync3(file)) {
954
1112
  return file;
955
1113
  }
956
1114
  }
@@ -964,10 +1122,10 @@ async function loadConfig(customPath) {
964
1122
  }
965
1123
  throw new Error("No PromptScript configuration found. Run: prs init");
966
1124
  }
967
- let content = await readFile2(configFile, "utf-8");
1125
+ let content = await readFile3(configFile, "utf-8");
968
1126
  content = interpolateEnvVars(content);
969
1127
  try {
970
- return parseYaml(content);
1128
+ return parseYaml2(content);
971
1129
  } catch (error) {
972
1130
  const message = error instanceof Error ? error.message : "Unknown parse error";
973
1131
  throw new Error(`Failed to parse ${configFile}: ${message}`);
@@ -977,7 +1135,17 @@ async function loadConfig(customPath) {
977
1135
  // packages/formatters/src/convention-renderer.ts
978
1136
  var ConventionRenderer = class {
979
1137
  convention;
980
- constructor(convention = "xml") {
1138
+ prettierOptions;
1139
+ constructor(conventionOrOptions = "xml") {
1140
+ let convention;
1141
+ let prettier;
1142
+ if (typeof conventionOrOptions === "object" && ("convention" in conventionOrOptions || "prettier" in conventionOrOptions)) {
1143
+ const opts = conventionOrOptions;
1144
+ convention = opts.convention ?? "xml";
1145
+ prettier = opts.prettier;
1146
+ } else {
1147
+ convention = conventionOrOptions;
1148
+ }
981
1149
  if (typeof convention === "string") {
982
1150
  if (isBuiltInConvention(convention)) {
983
1151
  this.convention = BUILT_IN_CONVENTIONS[convention];
@@ -989,6 +1157,16 @@ var ConventionRenderer = class {
989
1157
  } else {
990
1158
  this.convention = convention;
991
1159
  }
1160
+ this.prettierOptions = {
1161
+ ...DEFAULT_PRETTIER_OPTIONS,
1162
+ ...prettier
1163
+ };
1164
+ }
1165
+ /**
1166
+ * Get the current Prettier options.
1167
+ */
1168
+ getPrettierOptions() {
1169
+ return this.prettierOptions;
992
1170
  }
993
1171
  /**
994
1172
  * Get the current convention.
@@ -1008,16 +1186,24 @@ var ConventionRenderer = class {
1008
1186
  const transformedName = this.transformName(name, renderer.nameTransform);
1009
1187
  const start = this.applyTemplate(renderer.start, { name: transformedName, level });
1010
1188
  const end = renderer.end ? this.applyTemplate(renderer.end, { name: transformedName, level }) : "";
1011
- const trimmedContent = content.trim();
1189
+ let trimmedContent = content.trim();
1012
1190
  if (!trimmedContent) {
1013
1191
  return end ? `${start}
1014
1192
  ${end}` : start;
1015
1193
  }
1194
+ if (this.convention.name === "markdown") {
1195
+ trimmedContent = this.escapeMarkdownSpecialChars(trimmedContent);
1196
+ }
1016
1197
  const indentedContent = this.indentContent(trimmedContent, renderer, level);
1017
1198
  if (end) {
1018
1199
  return `${start}
1019
1200
  ${indentedContent}
1020
1201
  ${end}`;
1202
+ }
1203
+ if (this.convention.name === "markdown") {
1204
+ return `${start}
1205
+
1206
+ ${indentedContent}`;
1021
1207
  }
1022
1208
  return `${start}
1023
1209
  ${indentedContent}`;
@@ -1105,13 +1291,22 @@ ${this.convention.rootWrapper.end}`;
1105
1291
  }
1106
1292
  return result;
1107
1293
  }
1294
+ /**
1295
+ * Escape markdown special characters for Prettier compatibility.
1296
+ * - Escapes __ to \_\_ (to avoid emphasis)
1297
+ * - Escapes /* to /\* (to avoid glob patterns being interpreted)
1298
+ */
1299
+ escapeMarkdownSpecialChars(content) {
1300
+ return content.replace(/__/g, "\\_\\_").replace(/\/\*/g, "/\\*");
1301
+ }
1108
1302
  indentContent(content, renderer, level) {
1109
1303
  const indent = renderer.indent ?? "";
1110
1304
  if (!indent) {
1111
1305
  return content;
1112
1306
  }
1113
1307
  if (this.convention.name === "xml") {
1114
- const baseIndent = indent.repeat(level);
1308
+ const indentStr = " ".repeat(this.prettierOptions.tabWidth);
1309
+ const baseIndent = indentStr.repeat(level);
1115
1310
  return content.split("\n").map((line) => line.trim() ? `${baseIndent}${line}` : line).join("\n");
1116
1311
  }
1117
1312
  return content;
@@ -1130,7 +1325,19 @@ var BaseFormatter = class {
1130
1325
  */
1131
1326
  createRenderer(options) {
1132
1327
  const convention = options?.convention ?? this.defaultConvention;
1133
- return new ConventionRenderer(convention);
1328
+ return new ConventionRenderer({
1329
+ convention,
1330
+ prettier: options?.prettier
1331
+ });
1332
+ }
1333
+ /**
1334
+ * Get resolved Prettier options, merging provided options with defaults.
1335
+ */
1336
+ getPrettierOptions(options) {
1337
+ return {
1338
+ ...DEFAULT_PRETTIER_OPTIONS,
1339
+ ...options?.prettier
1340
+ };
1134
1341
  }
1135
1342
  /**
1136
1343
  * Get the output path, respecting options override.
@@ -1183,6 +1390,14 @@ var BaseFormatter = class {
1183
1390
  return {};
1184
1391
  }
1185
1392
  }
1393
+ /**
1394
+ * Format standards list from array of values (pass-through).
1395
+ * Returns array of strings for rendering as bullet list.
1396
+ */
1397
+ formatStandardsList(items) {
1398
+ if (!Array.isArray(items)) return [];
1399
+ return items.map((item) => this.valueToString(item)).filter((s) => s.length > 0);
1400
+ }
1186
1401
  /**
1187
1402
  * Format an array as comma-separated string.
1188
1403
  */
@@ -1248,6 +1463,136 @@ var BaseFormatter = class {
1248
1463
  const endPos = endCodeBlock + 3;
1249
1464
  return text.substring(headerIndex, endPos);
1250
1465
  }
1466
+ /**
1467
+ * Normalize markdown content to match Prettier formatting.
1468
+ * - Strips common leading indentation from lines
1469
+ * - Trims trailing whitespace from lines
1470
+ * - Normalizes markdown table formatting
1471
+ * - Adds blank lines before lists when preceded by text
1472
+ * - Escapes markdown special characters in paths
1473
+ */
1474
+ normalizeMarkdownForPrettier(content) {
1475
+ const lines = content.split("\n");
1476
+ let minIndent = Infinity;
1477
+ let inCodeBlock = false;
1478
+ for (const line of lines) {
1479
+ const trimmed = line.trimEnd();
1480
+ if (trimmed.startsWith("```")) {
1481
+ inCodeBlock = !inCodeBlock;
1482
+ continue;
1483
+ }
1484
+ if (inCodeBlock) continue;
1485
+ if (trimmed.length === 0) continue;
1486
+ const match = line.match(/^(\s*)/);
1487
+ const leadingSpaces = match?.[1]?.length ?? 0;
1488
+ minIndent = Math.min(minIndent, leadingSpaces);
1489
+ }
1490
+ if (minIndent === Infinity) minIndent = 0;
1491
+ const result = [];
1492
+ let inTable = false;
1493
+ let tableLines = [];
1494
+ inCodeBlock = false;
1495
+ for (const line of lines) {
1496
+ const trimmedLine = line.trimEnd();
1497
+ if (trimmedLine.trimStart().startsWith("```")) {
1498
+ inCodeBlock = !inCodeBlock;
1499
+ }
1500
+ const unindentedLine = minIndent > 0 ? trimmedLine.slice(minIndent) : trimmedLine;
1501
+ if (inCodeBlock || unindentedLine.startsWith("```")) {
1502
+ result.push(unindentedLine);
1503
+ continue;
1504
+ }
1505
+ let processedLine = unindentedLine;
1506
+ processedLine = processedLine.replace(/__([^_]+)__/g, "\\_\\_$1\\_\\_");
1507
+ processedLine = processedLine.replace(/\/\*/g, "/\\*");
1508
+ if (processedLine.trimStart().startsWith("|") && processedLine.trimEnd().endsWith("|")) {
1509
+ inTable = true;
1510
+ tableLines.push(processedLine.trim());
1511
+ } else {
1512
+ if (inTable && tableLines.length > 0) {
1513
+ result.push(...this.formatMarkdownTable(tableLines));
1514
+ tableLines = [];
1515
+ inTable = false;
1516
+ }
1517
+ const prevLine = result.length > 0 ? result[result.length - 1] : "";
1518
+ const isListItem = processedLine.trimStart().startsWith("- ");
1519
+ if (isListItem && prevLine && !prevLine.trimStart().startsWith("- ")) {
1520
+ result.push("");
1521
+ }
1522
+ result.push(processedLine);
1523
+ }
1524
+ }
1525
+ if (tableLines.length > 0) {
1526
+ result.push(...this.formatMarkdownTable(tableLines));
1527
+ }
1528
+ return result.join("\n");
1529
+ }
1530
+ /**
1531
+ * Strip all leading indentation from markdown content.
1532
+ * Used for AGENTS.md where content from multiple sources has inconsistent indentation.
1533
+ * Preserves indentation inside code blocks.
1534
+ */
1535
+ stripAllIndent(content) {
1536
+ const lines = content.split("\n");
1537
+ const result = [];
1538
+ let inCodeBlock = false;
1539
+ for (const line of lines) {
1540
+ const trimmedEnd = line.trimEnd();
1541
+ if (trimmedEnd.trimStart().startsWith("```")) {
1542
+ if (!inCodeBlock) {
1543
+ const prevLine2 = result.length > 0 ? result[result.length - 1] : "";
1544
+ if (prevLine2 && prevLine2.trim()) {
1545
+ result.push("");
1546
+ }
1547
+ }
1548
+ inCodeBlock = !inCodeBlock;
1549
+ result.push(trimmedEnd.trimStart());
1550
+ continue;
1551
+ }
1552
+ if (inCodeBlock) {
1553
+ result.push(trimmedEnd);
1554
+ continue;
1555
+ }
1556
+ let stripped = trimmedEnd.trimStart();
1557
+ stripped = stripped.replace(/__/g, "\\_\\_");
1558
+ stripped = stripped.replace(/\/\*/g, "/\\*");
1559
+ const prevLine = result.length > 0 ? result[result.length - 1] : "";
1560
+ if (stripped.startsWith("- ") && prevLine && !prevLine.startsWith("- ")) {
1561
+ result.push("");
1562
+ }
1563
+ result.push(stripped);
1564
+ }
1565
+ return result.join("\n");
1566
+ }
1567
+ /**
1568
+ * Format a markdown table to match Prettier output.
1569
+ * Prettier removes trailing whitespace from cells.
1570
+ */
1571
+ formatMarkdownTable(tableLines) {
1572
+ if (tableLines.length === 0) return [];
1573
+ const rows = tableLines.map(
1574
+ (line) => line.split("|").slice(1, -1).map((cell) => cell.trim())
1575
+ );
1576
+ const colCount = rows[0]?.length ?? 0;
1577
+ const colWidths = new Array(colCount).fill(0);
1578
+ for (const row of rows) {
1579
+ for (let i = 0; i < row.length; i++) {
1580
+ const cell = row[i] ?? "";
1581
+ const width = cell.match(/^-+$/) ? 3 : cell.length;
1582
+ colWidths[i] = Math.max(colWidths[i] ?? 0, width);
1583
+ }
1584
+ }
1585
+ return rows.map((row) => {
1586
+ const cells = row.map((cell, colIndex) => {
1587
+ const width = colWidths[colIndex] ?? 0;
1588
+ if (cell.match(/^-+$/)) {
1589
+ return "-".repeat(width);
1590
+ }
1591
+ return cell.padEnd(width);
1592
+ });
1593
+ return "| " + cells.join(" | ") + " |";
1594
+ });
1595
+ }
1251
1596
  };
1252
1597
 
1253
1598
  // packages/formatters/src/registry.ts
@@ -1327,6 +1672,51 @@ var GITHUB_VERSIONS = {
1327
1672
  outputPath: ".github/copilot-instructions.md"
1328
1673
  }
1329
1674
  };
1675
+ var TOOL_NAME_MAPPING = {
1676
+ // Read tools
1677
+ Read: "read",
1678
+ NotebookRead: "read",
1679
+ // Edit tools
1680
+ Edit: "edit",
1681
+ MultiEdit: "edit",
1682
+ Write: "edit",
1683
+ NotebookEdit: "edit",
1684
+ // Search tools
1685
+ Grep: "search",
1686
+ Glob: "search",
1687
+ // Execute tools
1688
+ Bash: "execute",
1689
+ // Web tools
1690
+ WebFetch: "web",
1691
+ WebSearch: "web",
1692
+ // Agent tools
1693
+ Task: "agent",
1694
+ // Todo tools
1695
+ TodoWrite: "todo",
1696
+ TodoRead: "todo"
1697
+ };
1698
+ var MODEL_NAME_MAPPING = {
1699
+ // Claude models - default aliases map to latest versions (4.5)
1700
+ sonnet: "Claude Sonnet 4.5",
1701
+ opus: "Claude Opus 4.5",
1702
+ haiku: "Claude Haiku 4.5",
1703
+ // Explicit version mappings
1704
+ "sonnet-4": "Claude Sonnet 4",
1705
+ "sonnet-4.5": "Claude Sonnet 4.5",
1706
+ "opus-4": "Claude Opus 4",
1707
+ "opus-4.5": "Claude Opus 4.5",
1708
+ "haiku-4": "Claude Haiku 4",
1709
+ "haiku-4.5": "Claude Haiku 4.5",
1710
+ // OpenAI models (pass through if already in correct format)
1711
+ "gpt-4o": "GPT-4o",
1712
+ "gpt-4.1": "GPT-4.1",
1713
+ "gpt-5": "GPT-5",
1714
+ "gpt-5-mini": "GPT-5 mini",
1715
+ // Special values
1716
+ inherit: "",
1717
+ // Empty string means omit the model property
1718
+ auto: "Auto"
1719
+ };
1330
1720
  var GitHubFormatter = class extends BaseFormatter {
1331
1721
  name = "github";
1332
1722
  outputPath = ".github/copilot-instructions.md";
@@ -1368,7 +1758,7 @@ var GitHubFormatter = class extends BaseFormatter {
1368
1758
  this.addCommonSections(ast, renderer, sections);
1369
1759
  return {
1370
1760
  path: this.getOutputPath(options),
1371
- content: sections.join("\n\n")
1761
+ content: sections.join("\n\n") + "\n"
1372
1762
  };
1373
1763
  }
1374
1764
  // ============================================================
@@ -1392,7 +1782,7 @@ var GitHubFormatter = class extends BaseFormatter {
1392
1782
  this.addCommonSections(ast, renderer, sections);
1393
1783
  return {
1394
1784
  path: this.getOutputPath(options),
1395
- content: sections.join("\n\n"),
1785
+ content: sections.join("\n\n") + "\n",
1396
1786
  additionalFiles: additionalFiles.length > 0 ? additionalFiles : void 0
1397
1787
  };
1398
1788
  }
@@ -1429,7 +1819,7 @@ var GitHubFormatter = class extends BaseFormatter {
1429
1819
  this.addCommonSections(ast, renderer, sections);
1430
1820
  return {
1431
1821
  path: this.getOutputPath(options),
1432
- content: sections.join("\n\n"),
1822
+ content: sections.join("\n\n") + "\n",
1433
1823
  additionalFiles: additionalFiles.length > 0 ? additionalFiles : void 0
1434
1824
  };
1435
1825
  }
@@ -1600,10 +1990,9 @@ var GitHubFormatter = class extends BaseFormatter {
1600
1990
  if (config.mode === "agent") {
1601
1991
  lines.push("mode: agent");
1602
1992
  if (config.tools && config.tools.length > 0) {
1603
- lines.push("tools:");
1604
- for (const tool of config.tools) {
1605
- lines.push(` - ${tool}`);
1606
- }
1993
+ const mappedTools = config.tools.map((tool) => TOOL_NAME_MAPPING[tool] ?? tool.toLowerCase()).filter((t, i, arr) => arr.indexOf(t) === i);
1994
+ const toolsArray = mappedTools.map((t) => `'${t}'`).join(", ");
1995
+ lines.push(`tools: [${toolsArray}]`);
1607
1996
  }
1608
1997
  }
1609
1998
  lines.push("---");
@@ -1646,19 +2035,21 @@ var GitHubFormatter = class extends BaseFormatter {
1646
2035
  generateSkillFile(config) {
1647
2036
  const lines = [];
1648
2037
  lines.push("---");
1649
- lines.push(`name: "${config.name}"`);
1650
- lines.push(`description: "${config.description}"`);
2038
+ lines.push(`name: '${config.name}'`);
2039
+ const descQuote = config.description.includes("'") ? '"' : "'";
2040
+ lines.push(`description: ${descQuote}${config.description}${descQuote}`);
1651
2041
  if (config.disableModelInvocation) {
1652
2042
  lines.push("disable-model-invocation: true");
1653
2043
  }
1654
2044
  lines.push("---");
1655
2045
  lines.push("");
1656
2046
  if (config.content) {
1657
- lines.push(config.content);
2047
+ const normalizedContent = this.normalizeMarkdownForPrettier(config.content);
2048
+ lines.push(normalizedContent);
1658
2049
  }
1659
2050
  return {
1660
2051
  path: `.github/skills/${config.name}/SKILL.md`,
1661
- content: lines.join("\n")
2052
+ content: lines.join("\n") + "\n"
1662
2053
  };
1663
2054
  }
1664
2055
  // ============================================================
@@ -1673,13 +2064,11 @@ var GitHubFormatter = class extends BaseFormatter {
1673
2064
  const lines = [];
1674
2065
  lines.push("# Agent Instructions");
1675
2066
  lines.push("");
1676
- lines.push("> Auto-generated by PromptScript");
1677
- lines.push("");
1678
2067
  const identityText = this.extractText(identity2.content);
1679
2068
  if (identityText) {
1680
2069
  lines.push("## Identity");
1681
2070
  lines.push("");
1682
- lines.push(identityText);
2071
+ lines.push(this.stripAllIndent(identityText));
1683
2072
  lines.push("");
1684
2073
  }
1685
2074
  const context = this.findBlock(ast, "context");
@@ -1688,7 +2077,7 @@ var GitHubFormatter = class extends BaseFormatter {
1688
2077
  if (contextText) {
1689
2078
  lines.push("## Context");
1690
2079
  lines.push("");
1691
- lines.push(contextText);
2080
+ lines.push(this.stripAllIndent(contextText));
1692
2081
  lines.push("");
1693
2082
  }
1694
2083
  }
@@ -1701,12 +2090,11 @@ var GitHubFormatter = class extends BaseFormatter {
1701
2090
  for (const item of items) {
1702
2091
  lines.push(`- ${item}`);
1703
2092
  }
1704
- lines.push("");
1705
2093
  }
1706
2094
  }
1707
2095
  return {
1708
2096
  path: "AGENTS.md",
1709
- content: lines.join("\n")
2097
+ content: lines.join("\n") + "\n"
1710
2098
  };
1711
2099
  }
1712
2100
  /**
@@ -1757,12 +2145,26 @@ var GitHubFormatter = class extends BaseFormatter {
1757
2145
  return agents;
1758
2146
  }
1759
2147
  /**
1760
- * Parse tools array from a Value.
2148
+ * Parse tools array from a Value and map to GitHub Copilot canonical names.
2149
+ *
2150
+ * @see https://docs.github.com/en/copilot/reference/custom-agents-configuration
1761
2151
  */
1762
2152
  parseToolsArray(value) {
1763
2153
  if (!value || !Array.isArray(value)) return void 0;
1764
- const arr = value.map((v) => this.valueToString(v)).filter((s) => s.length > 0);
1765
- return arr.length > 0 ? arr : void 0;
2154
+ const mapped = value.map((v) => this.valueToString(v)).filter((s) => s.length > 0).map((tool) => TOOL_NAME_MAPPING[tool] ?? tool.toLowerCase());
2155
+ const unique = [...new Set(mapped)];
2156
+ return unique.length > 0 ? unique : void 0;
2157
+ }
2158
+ /**
2159
+ * Map a model name from PromptScript/Claude Code format to GitHub Copilot format.
2160
+ *
2161
+ * @returns The mapped model name, or undefined if the model should be omitted (e.g., "inherit")
2162
+ */
2163
+ mapModelName(model) {
2164
+ if (!model) return void 0;
2165
+ const mapped = MODEL_NAME_MAPPING[model.toLowerCase()];
2166
+ if (mapped === "") return void 0;
2167
+ return mapped ?? model;
1766
2168
  }
1767
2169
  /**
1768
2170
  * Generate a .github/agents/<name>.md file.
@@ -1775,13 +2177,12 @@ var GitHubFormatter = class extends BaseFormatter {
1775
2177
  lines.push(`name: ${config.name}`);
1776
2178
  lines.push(`description: ${config.description}`);
1777
2179
  if (config.tools && config.tools.length > 0) {
1778
- lines.push("tools:");
1779
- for (const tool of config.tools) {
1780
- lines.push(` - ${tool}`);
1781
- }
2180
+ const toolsArray = config.tools.map((t) => `'${t}'`).join(", ");
2181
+ lines.push(`tools: [${toolsArray}]`);
1782
2182
  }
1783
- if (config.model) {
1784
- lines.push(`model: ${config.model}`);
2183
+ const mappedModel = this.mapModelName(config.model);
2184
+ if (mappedModel) {
2185
+ lines.push(`model: ${mappedModel}`);
1785
2186
  }
1786
2187
  lines.push("---");
1787
2188
  lines.push("");
@@ -1790,7 +2191,7 @@ var GitHubFormatter = class extends BaseFormatter {
1790
2191
  }
1791
2192
  return {
1792
2193
  path: `.github/agents/${config.name}.md`,
1793
- content: lines.join("\n")
2194
+ content: lines.join("\n") + "\n"
1794
2195
  };
1795
2196
  }
1796
2197
  // ============================================================
@@ -1822,22 +2223,14 @@ var GitHubFormatter = class extends BaseFormatter {
1822
2223
  const knowledge = this.knowledge(ast, renderer);
1823
2224
  if (knowledge) sections.push(knowledge);
1824
2225
  }
1825
- header(ast) {
1826
- const id = this.getMetaField(ast, "id") ?? "unknown";
1827
- const syntax = this.getMetaField(ast, "syntax") ?? "0.0.0";
1828
- return `# GitHub Copilot Instructions
1829
-
1830
- > Auto-generated by PromptScript
1831
- > Source: ${id} (syntax ${syntax})
1832
- > Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
1833
- >
1834
- > **Do not edit manually**`;
2226
+ header(_ast) {
2227
+ return `# GitHub Copilot Instructions`;
1835
2228
  }
1836
2229
  project(ast, renderer) {
1837
2230
  const identity2 = this.findBlock(ast, "identity");
1838
2231
  if (!identity2) return null;
1839
2232
  const content = this.extractText(identity2.content);
1840
- return renderer.renderSection("project", content);
2233
+ return renderer.renderSection("project", this.stripAllIndent(content));
1841
2234
  }
1842
2235
  techStack(ast, renderer) {
1843
2236
  const context = this.findBlock(ast, "context");
@@ -1875,50 +2268,30 @@ var GitHubFormatter = class extends BaseFormatter {
1875
2268
  const archMatch = this.extractSectionWithCodeBlock(text, "## Architecture");
1876
2269
  if (!archMatch) return null;
1877
2270
  const content = archMatch.replace("## Architecture", "").trim();
1878
- return renderer.renderSection("architecture", content);
2271
+ return renderer.renderSection("architecture", this.stripAllIndent(content));
1879
2272
  }
1880
2273
  codeStandards(ast, renderer) {
1881
2274
  const standards = this.findBlock(ast, "standards");
1882
2275
  if (!standards) return null;
1883
2276
  const props = this.getProps(standards.content);
1884
2277
  const subsections = [];
1885
- this.addStandardsSubsection(
1886
- subsections,
1887
- renderer,
1888
- props["typescript"],
1889
- "typescript",
1890
- this.formatStandardsObject.bind(this)
1891
- );
1892
- this.addStandardsSubsection(
1893
- subsections,
1894
- renderer,
1895
- props["naming"],
1896
- "naming",
1897
- this.formatNamingStandards.bind(this)
1898
- );
1899
- this.addStandardsSubsection(
1900
- subsections,
1901
- renderer,
1902
- props["errors"],
1903
- "error-handling",
1904
- this.formatErrorStandards.bind(this)
1905
- );
1906
- this.addStandardsSubsection(
1907
- subsections,
1908
- renderer,
1909
- props["testing"],
1910
- "testing",
1911
- this.formatTestingStandards.bind(this)
1912
- );
1913
- if (subsections.length === 0) return null;
1914
- return renderer.renderSection("code-standards", subsections.join("\n"));
1915
- }
1916
- addStandardsSubsection(subsections, renderer, value, name, formatter) {
1917
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
1918
- const items = formatter(value);
1919
- if (items.length > 0) {
1920
- subsections.push(renderer.renderSection(name, renderer.renderList(items), 2));
2278
+ const sectionMap = {
2279
+ typescript: "typescript",
2280
+ naming: "naming",
2281
+ errors: "error-handling",
2282
+ testing: "testing"
2283
+ };
2284
+ for (const [key, sectionName] of Object.entries(sectionMap)) {
2285
+ const value = props[key];
2286
+ if (Array.isArray(value)) {
2287
+ const items = this.formatStandardsList(value);
2288
+ if (items.length > 0) {
2289
+ subsections.push(renderer.renderSection(sectionName, renderer.renderList(items), 2));
2290
+ }
2291
+ }
1921
2292
  }
2293
+ if (subsections.length === 0) return null;
2294
+ return renderer.renderSection("code-standards", subsections.join("\n\n"));
1922
2295
  }
1923
2296
  commands(ast, renderer) {
1924
2297
  const knowledge = this.findBlock(ast, "knowledge");
@@ -1927,7 +2300,7 @@ var GitHubFormatter = class extends BaseFormatter {
1927
2300
  const commandsMatch = this.extractSectionWithCodeBlock(text, "## Development Commands");
1928
2301
  if (!commandsMatch) return null;
1929
2302
  const content = commandsMatch.replace("## Development Commands", "").trim();
1930
- return renderer.renderSection("commands", content);
2303
+ return renderer.renderSection("commands", this.stripAllIndent(content));
1931
2304
  }
1932
2305
  gitCommits(ast, renderer) {
1933
2306
  const standards = this.findBlock(ast, "standards");
@@ -1978,7 +2351,7 @@ var GitHubFormatter = class extends BaseFormatter {
1978
2351
  subsections.push(renderer.renderSection("vite-vitest", `Vite root: ${value}`, 2));
1979
2352
  }
1980
2353
  if (subsections.length === 0) return null;
1981
- return renderer.renderSection("configuration-files", subsections.join("\n"));
2354
+ return renderer.renderSection("configuration-files", subsections.join("\n\n"));
1982
2355
  }
1983
2356
  documentation(ast, renderer) {
1984
2357
  const standards = this.findBlock(ast, "standards");
@@ -2014,8 +2387,11 @@ var GitHubFormatter = class extends BaseFormatter {
2014
2387
  if (!postMatch) return null;
2015
2388
  const intro = "After completing any code changes, run the following commands to ensure code quality:";
2016
2389
  const content = postMatch.replace("## Post-Work Verification", "").trim();
2017
- return renderer.renderSection("post-work-verification", `${intro}
2018
- ${content}`);
2390
+ return renderer.renderSection(
2391
+ "post-work-verification",
2392
+ `${intro}
2393
+ ${this.stripAllIndent(content)}`
2394
+ );
2019
2395
  }
2020
2396
  restrictions(ast, renderer) {
2021
2397
  const block = this.findBlock(ast, "restrictions");
@@ -2070,47 +2446,6 @@ ${content}`);
2070
2446
  formatTechItem(arr) {
2071
2447
  return arr.map(String).join(", ");
2072
2448
  }
2073
- formatStandardsObject(obj) {
2074
- const items = [];
2075
- if (obj["strictMode"]) items.push("Strict mode enabled, no `any` types");
2076
- if (obj["useUnknown"]) items.push(`Use \`unknown\` ${this.valueToString(obj["useUnknown"])}`);
2077
- if (obj["interfaces"])
2078
- items.push(`Prefer \`interface\` ${this.valueToString(obj["interfaces"])}`);
2079
- if (obj["types"]) items.push(`Use \`type\` ${this.valueToString(obj["types"])}`);
2080
- if (obj["exports"]) items.push(`${this.capitalize(this.valueToString(obj["exports"]))}`);
2081
- if (obj["returnTypes"])
2082
- items.push(`Explicit return types ${this.valueToString(obj["returnTypes"])}`);
2083
- return items;
2084
- }
2085
- formatNamingStandards(obj) {
2086
- const items = [];
2087
- if (obj["files"]) items.push(`Files: \`${this.valueToString(obj["files"])}\``);
2088
- if (obj["classes"]) items.push(`Classes/Interfaces: \`${this.valueToString(obj["classes"])}\``);
2089
- if (obj["functions"])
2090
- items.push(`Functions/Variables: \`${this.valueToString(obj["functions"])}\``);
2091
- if (obj["constants"]) items.push(`Constants: \`${this.valueToString(obj["constants"])}\``);
2092
- return items;
2093
- }
2094
- formatErrorStandards(obj) {
2095
- const items = [];
2096
- if (obj["customClasses"])
2097
- items.push(
2098
- `Use custom error classes extending \`${this.valueToString(obj["customClasses"])}\``
2099
- );
2100
- if (obj["locationInfo"]) items.push("Always include location information");
2101
- if (obj["messages"])
2102
- items.push(`Provide ${this.valueToString(obj["messages"])} error messages`);
2103
- return items;
2104
- }
2105
- formatTestingStandards(obj) {
2106
- const items = [];
2107
- if (obj["filePattern"]) items.push(`Test files: \`${this.valueToString(obj["filePattern"])}\``);
2108
- if (obj["pattern"]) items.push(`Follow ${this.valueToString(obj["pattern"])} pattern`);
2109
- if (obj["coverage"])
2110
- items.push(`Target >${this.valueToString(obj["coverage"])}% coverage for libraries`);
2111
- if (obj["fixtures"]) items.push(`Use fixtures ${this.valueToString(obj["fixtures"])}`);
2112
- return items;
2113
- }
2114
2449
  formatRestriction(text) {
2115
2450
  const formatted = text.replace(/^-\s*/, "").replace(/^"/, "").replace(/"$/, "").replace(/^Never\s+/i, "Don't ");
2116
2451
  return formatted;
@@ -2385,8 +2720,9 @@ var ClaudeFormatter = class extends BaseFormatter {
2385
2720
  generateSkillFile(config) {
2386
2721
  const lines = [];
2387
2722
  lines.push("---");
2388
- lines.push(`name: "${config.name}"`);
2389
- lines.push(`description: "${config.description}"`);
2723
+ lines.push(`name: '${config.name}'`);
2724
+ const descQuote = config.description.includes("'") ? '"' : "'";
2725
+ lines.push(`description: ${descQuote}${config.description}${descQuote}`);
2390
2726
  if (config.context) {
2391
2727
  lines.push(`context: ${config.context}`);
2392
2728
  }
@@ -2405,11 +2741,12 @@ var ClaudeFormatter = class extends BaseFormatter {
2405
2741
  lines.push("---");
2406
2742
  lines.push("");
2407
2743
  if (config.content) {
2408
- lines.push(config.content);
2744
+ const normalizedContent = this.normalizeMarkdownForPrettier(config.content);
2745
+ lines.push(normalizedContent);
2409
2746
  }
2410
2747
  return {
2411
2748
  path: `.claude/skills/${config.name}/SKILL.md`,
2412
- content: lines.join("\n")
2749
+ content: lines.join("\n") + "\n"
2413
2750
  };
2414
2751
  }
2415
2752
  // ============================================================
@@ -2518,7 +2855,7 @@ var ClaudeFormatter = class extends BaseFormatter {
2518
2855
  }
2519
2856
  return {
2520
2857
  path: `.claude/agents/${config.name}.md`,
2521
- content: lines.join("\n")
2858
+ content: lines.join("\n") + "\n"
2522
2859
  };
2523
2860
  }
2524
2861
  // ============================================================
@@ -3567,7 +3904,7 @@ var AntigravityFormatter = class extends BaseFormatter {
3567
3904
  if (diagrams) sections.push(diagrams);
3568
3905
  const restrictions = this.restrictions(ast, renderer);
3569
3906
  if (restrictions) sections.push(restrictions);
3570
- const content = sections.join("\n\n");
3907
+ const content = sections.join("\n\n") + "\n";
3571
3908
  this.validateContentLength(content);
3572
3909
  const mainOutput = {
3573
3910
  path: this.getOutputPath(options),
@@ -3721,17 +4058,8 @@ var AntigravityFormatter = class extends BaseFormatter {
3721
4058
  formatWorkflowTitle(name) {
3722
4059
  return name.replace(/^\//, "").split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3723
4060
  }
3724
- header(ast) {
3725
- const id = this.getMetaField(ast, "id") ?? "unknown";
3726
- const syntax = this.getMetaField(ast, "syntax") ?? "0.0.0";
3727
- return `# Project Rules
3728
-
3729
- > Auto-generated by PromptScript
3730
- > Source: ${id} (syntax ${syntax})
3731
- > Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
3732
- >
3733
- > **Do not edit manually** - these rules are generated from PromptScript.
3734
- > To modify, update the source .prs file and recompile.`;
4061
+ header(_ast) {
4062
+ return `# Project Rules`;
3735
4063
  }
3736
4064
  identity(ast, _renderer) {
3737
4065
  const identity2 = this.findBlock(ast, "identity");
@@ -3740,7 +4068,7 @@ var AntigravityFormatter = class extends BaseFormatter {
3740
4068
  if (!content) return null;
3741
4069
  return `## Project Identity
3742
4070
 
3743
- ${content}`;
4071
+ ${this.stripAllIndent(content)}`;
3744
4072
  }
3745
4073
  /**
3746
4074
  * Extract tech stack from @context block (same as GitHub/Cursor).
@@ -3794,7 +4122,7 @@ ${items.join("\n")}`;
3794
4122
  const content = archMatch.replace("## Architecture", "").trim();
3795
4123
  return `## Architecture
3796
4124
 
3797
- ${content}`;
4125
+ ${this.stripAllIndent(content)}`;
3798
4126
  }
3799
4127
  const props = this.getProps(context.content);
3800
4128
  const arch = props["architecture"];
@@ -3803,7 +4131,7 @@ ${content}`;
3803
4131
  if (archText.trim()) {
3804
4132
  return `## Architecture
3805
4133
 
3806
- ${archText.trim()}`;
4134
+ ${this.stripAllIndent(archText.trim())}`;
3807
4135
  }
3808
4136
  }
3809
4137
  }
@@ -3813,53 +4141,35 @@ ${archText.trim()}`;
3813
4141
  if (content) {
3814
4142
  return `## Architecture
3815
4143
 
3816
- ${content}`;
4144
+ ${this.stripAllIndent(content)}`;
3817
4145
  }
3818
4146
  }
3819
4147
  return null;
3820
4148
  }
3821
4149
  /**
3822
- * Extract code standards from @standards block (same as GitHub/Cursor).
4150
+ * Extract code standards from @standards block.
4151
+ * Expects arrays of strings (pass-through format).
3823
4152
  */
3824
4153
  codeStandards(ast, _renderer) {
3825
4154
  const standards = this.findBlock(ast, "standards");
3826
4155
  if (!standards) return null;
3827
4156
  const props = this.getProps(standards.content);
3828
4157
  const subsections = [];
3829
- const typescript = props["typescript"];
3830
- if (typescript && typeof typescript === "object" && !Array.isArray(typescript)) {
3831
- const items = this.formatTypeScriptStandards(typescript);
3832
- if (items.length > 0) {
3833
- subsections.push(`### TypeScript
3834
-
3835
- ${items.map((i) => "- " + i).join("\n")}`);
3836
- }
3837
- }
3838
- const naming = props["naming"];
3839
- if (naming && typeof naming === "object" && !Array.isArray(naming)) {
3840
- const items = this.formatNamingStandards(naming);
3841
- if (items.length > 0) {
3842
- subsections.push(`### Naming Conventions
3843
-
3844
- ${items.map((i) => "- " + i).join("\n")}`);
3845
- }
3846
- }
3847
- const errors = props["errors"];
3848
- if (errors && typeof errors === "object" && !Array.isArray(errors)) {
3849
- const items = this.formatErrorStandards(errors);
3850
- if (items.length > 0) {
3851
- subsections.push(`### Error Handling
3852
-
3853
- ${items.map((i) => "- " + i).join("\n")}`);
3854
- }
3855
- }
3856
- const testing = props["testing"];
3857
- if (testing && typeof testing === "object" && !Array.isArray(testing)) {
3858
- const items = this.formatTestingStandards(testing);
3859
- if (items.length > 0) {
3860
- subsections.push(`### Testing
4158
+ const sectionMap = {
4159
+ typescript: "TypeScript",
4160
+ naming: "Naming Conventions",
4161
+ errors: "Error Handling",
4162
+ testing: "Testing"
4163
+ };
4164
+ for (const [key, title] of Object.entries(sectionMap)) {
4165
+ const value = props[key];
4166
+ if (Array.isArray(value)) {
4167
+ const items = this.formatStandardsList(value);
4168
+ if (items.length > 0) {
4169
+ subsections.push(`### ${title}
3861
4170
 
3862
4171
  ${items.map((i) => "- " + i).join("\n")}`);
4172
+ }
3863
4173
  }
3864
4174
  }
3865
4175
  if (subsections.length === 0) return null;
@@ -3922,7 +4232,7 @@ ${items.map((i) => "- " + i).join("\n")}`;
3922
4232
  }
3923
4233
  const vite = configObj["viteRoot"];
3924
4234
  if (vite) {
3925
- const value = this.valueToString(vite);
4235
+ const value = this.valueToString(vite).replace(/__/g, "\\_\\_").replace(/\/\*/g, "/\\*");
3926
4236
  subsections.push(`### Vite/Vitest
3927
4237
 
3928
4238
  - Vite root: ${value}`);
@@ -3944,7 +4254,11 @@ ${subsections.join("\n\n")}`;
3944
4254
  for (const [key, value] of Object.entries(props)) {
3945
4255
  if (this.isWorkflow(value)) continue;
3946
4256
  const valueStr = this.valueToString(value);
3947
- lines.push(`- **${key}**: ${valueStr}`);
4257
+ if (valueStr) {
4258
+ lines.push(`- **${key}**: ${valueStr}`);
4259
+ } else {
4260
+ lines.push(`- **${key}**:`);
4261
+ }
3948
4262
  }
3949
4263
  if (lines.length === 0) return null;
3950
4264
  return `## Commands
@@ -3963,7 +4277,7 @@ ${lines.join("\n")}`;
3963
4277
  const content = commandsMatch.replace("## Development Commands", "").trim();
3964
4278
  return `## Development Commands
3965
4279
 
3966
- ${content}`;
4280
+ ${this.stripAllIndent(content)}`;
3967
4281
  }
3968
4282
  /**
3969
4283
  * Extract post-work verification from @knowledge block (same as GitHub/Cursor).
@@ -3979,7 +4293,7 @@ ${content}`;
3979
4293
  return `## Post-Work Verification
3980
4294
 
3981
4295
  ${intro}
3982
- ${content}`;
4296
+ ${this.stripAllIndent(content)}`;
3983
4297
  }
3984
4298
  /**
3985
4299
  * Extract documentation standards from @standards.documentation (same as GitHub/Cursor).
@@ -4025,9 +4339,8 @@ ${items.map((i) => "- " + i).join("\n")}`;
4025
4339
  const items = [];
4026
4340
  const format2 = diagObj["format"];
4027
4341
  if (format2) {
4028
- items.push(
4029
- `Always use **${this.valueToString(format2)}** syntax for diagrams in documentation`
4030
- );
4342
+ const formatValue = this.valueToString(format2).replace(/__/g, "\\_\\_").replace(/\/\*/g, "/\\*");
4343
+ items.push(`Always use **${formatValue}** syntax for diagrams in documentation`);
4031
4344
  }
4032
4345
  const types = diagObj["types"];
4033
4346
  if (types && Array.isArray(types)) {
@@ -4072,55 +4385,6 @@ ${items.map((i) => "- " + i).join("\n")}`;
4072
4385
  formatRestriction(text) {
4073
4386
  return text.replace(/^-\s*/, "").replace(/^"/, "").replace(/"$/, "").replace(/^Never\s+/i, "Don't ");
4074
4387
  }
4075
- // Helper methods for formatting standards
4076
- formatTypeScriptStandards(obj) {
4077
- const items = [];
4078
- if (obj["strictMode"]) items.push("Strict mode enabled, no `any` types");
4079
- if (obj["noAny"]) items.push("Never use `any` type - use `unknown` with type guards");
4080
- if (obj["useUnknown"]) items.push(`Use \`unknown\` ${this.valueToString(obj["useUnknown"])}`);
4081
- if (obj["interfaces"])
4082
- items.push(`Prefer \`interface\` ${this.valueToString(obj["interfaces"])}`);
4083
- if (obj["types"]) items.push(`Use \`type\` ${this.valueToString(obj["types"])}`);
4084
- if (obj["exports"]) items.push(`${this.capitalize(this.valueToString(obj["exports"]))}`);
4085
- if (obj["returnTypes"])
4086
- items.push(`Explicit return types ${this.valueToString(obj["returnTypes"])}`);
4087
- return items;
4088
- }
4089
- formatNamingStandards(obj) {
4090
- const items = [];
4091
- if (obj["files"]) items.push(`Files: \`${this.valueToString(obj["files"])}\``);
4092
- if (obj["classes"]) items.push(`Classes/Interfaces: \`${this.valueToString(obj["classes"])}\``);
4093
- if (obj["interfaces"]) items.push(`Interfaces: \`${this.valueToString(obj["interfaces"])}\``);
4094
- if (obj["functions"])
4095
- items.push(`Functions/Variables: \`${this.valueToString(obj["functions"])}\``);
4096
- if (obj["variables"]) items.push(`Variables: \`${this.valueToString(obj["variables"])}\``);
4097
- if (obj["constants"]) items.push(`Constants: \`${this.valueToString(obj["constants"])}\``);
4098
- return items;
4099
- }
4100
- formatErrorStandards(obj) {
4101
- const items = [];
4102
- if (obj["customClasses"])
4103
- items.push(
4104
- `Use custom error classes extending \`${this.valueToString(obj["customClasses"])}\``
4105
- );
4106
- if (obj["locationInfo"]) items.push("Always include location information");
4107
- if (obj["messages"])
4108
- items.push(`Provide ${this.valueToString(obj["messages"])} error messages`);
4109
- return items;
4110
- }
4111
- formatTestingStandards(obj) {
4112
- const items = [];
4113
- if (obj["filePattern"]) items.push(`Test files: \`${this.valueToString(obj["filePattern"])}\``);
4114
- if (obj["pattern"]) items.push(`Follow ${this.valueToString(obj["pattern"])} pattern`);
4115
- if (obj["framework"]) items.push(`Framework: ${this.valueToString(obj["framework"])}`);
4116
- if (obj["coverage"])
4117
- items.push(`Target >${this.valueToString(obj["coverage"])}% coverage for libraries`);
4118
- if (obj["fixtures"]) items.push(`Use fixtures ${this.valueToString(obj["fixtures"])}`);
4119
- return items;
4120
- }
4121
- capitalize(str) {
4122
- return str.charAt(0).toUpperCase() + str.slice(1);
4123
- }
4124
4388
  };
4125
4389
 
4126
4390
  // packages/formatters/src/index.ts
@@ -14277,8 +14541,8 @@ function parse(source, options = {}) {
14277
14541
  }
14278
14542
 
14279
14543
  // packages/resolver/src/loader.ts
14280
- import { readFile as readFile3 } from "fs/promises";
14281
- import { resolve, dirname as dirname2, isAbsolute, join as join2 } from "path";
14544
+ import { readFile as readFile4 } from "fs/promises";
14545
+ import { resolve as resolve2, dirname as dirname3, isAbsolute } from "path";
14282
14546
  var FileLoader = class {
14283
14547
  registryPath;
14284
14548
  localPath;
@@ -14295,7 +14559,7 @@ var FileLoader = class {
14295
14559
  */
14296
14560
  async load(path) {
14297
14561
  try {
14298
- return await readFile3(path, "utf-8");
14562
+ return await readFile4(path, "utf-8");
14299
14563
  } catch (err) {
14300
14564
  if (err.code === "ENOENT") {
14301
14565
  throw new FileNotFoundError(path);
@@ -14324,11 +14588,11 @@ var FileLoader = class {
14324
14588
  const namespace = match[1];
14325
14589
  const segments = match[2];
14326
14590
  const fileName2 = segments.endsWith(".prs") ? segments : `${segments}.prs`;
14327
- return resolve(this.registryPath, `@${namespace}`, fileName2);
14591
+ return resolve2(this.registryPath, `@${namespace}`, fileName2);
14328
14592
  }
14329
14593
  }
14330
14594
  const fileName = path.endsWith(".prs") ? path : `${path}.prs`;
14331
- return resolve(this.localPath, fileName);
14595
+ return resolve2(this.localPath, fileName);
14332
14596
  }
14333
14597
  /**
14334
14598
  * Resolve a PathReference to an absolute path.
@@ -14339,9 +14603,9 @@ var FileLoader = class {
14339
14603
  */
14340
14604
  resolveRef(ref, fromFile) {
14341
14605
  if (ref.isRelative) {
14342
- const dir = dirname2(fromFile);
14343
- const fileName = join2(...ref.segments) + ".prs";
14344
- return resolve(dir, fileName);
14606
+ const dir = dirname3(fromFile);
14607
+ const rawPath = ref.raw.endsWith(".prs") ? ref.raw : `${ref.raw}.prs`;
14608
+ return resolve2(dir, rawPath);
14345
14609
  }
14346
14610
  return this.toAbsolutePath(ref.raw);
14347
14611
  }
@@ -14665,9 +14929,7 @@ function mergeProperties2(source, target) {
14665
14929
  sourceVal,
14666
14930
  targetVal
14667
14931
  );
14668
- } else if (typeof sourceVal === typeof targetVal) {
14669
14932
  } else {
14670
- result[key] = deepCloneValue2(targetVal);
14671
14933
  }
14672
14934
  }
14673
14935
  return result;
@@ -15001,6 +15263,115 @@ function uniqueConcat3(parent, child) {
15001
15263
  return result;
15002
15264
  }
15003
15265
 
15266
+ // packages/resolver/src/skills.ts
15267
+ import { readFile as readFile5, access } from "fs/promises";
15268
+ import { resolve as resolve3, dirname as dirname4 } from "path";
15269
+ function parseSkillMd(content) {
15270
+ const lines = content.split("\n");
15271
+ let inFrontmatter = false;
15272
+ let frontmatterStart = -1;
15273
+ let frontmatterEnd = -1;
15274
+ for (let i = 0; i < lines.length; i++) {
15275
+ const line = lines[i]?.trim() ?? "";
15276
+ if (line === "---") {
15277
+ if (!inFrontmatter) {
15278
+ inFrontmatter = true;
15279
+ frontmatterStart = i;
15280
+ } else {
15281
+ frontmatterEnd = i;
15282
+ break;
15283
+ }
15284
+ }
15285
+ }
15286
+ let name;
15287
+ let description;
15288
+ let bodyContent;
15289
+ if (frontmatterStart >= 0 && frontmatterEnd > frontmatterStart) {
15290
+ const frontmatterLines = lines.slice(frontmatterStart + 1, frontmatterEnd);
15291
+ for (const line of frontmatterLines) {
15292
+ const nameMatch = line.match(/^name:\s*(?:"([^"]+)"|'([^']+)'|(.+))\s*$/);
15293
+ if (nameMatch) {
15294
+ name = (nameMatch[1] ?? nameMatch[2] ?? nameMatch[3])?.trim();
15295
+ }
15296
+ const descMatch = line.match(/^description:\s*(?:"([^"]+)"|'([^']+)'|(.+))\s*$/);
15297
+ if (descMatch) {
15298
+ description = (descMatch[1] ?? descMatch[2] ?? descMatch[3])?.trim();
15299
+ }
15300
+ }
15301
+ bodyContent = lines.slice(frontmatterEnd + 1).join("\n").trim();
15302
+ } else {
15303
+ bodyContent = content.trim();
15304
+ }
15305
+ return { name, description, content: bodyContent };
15306
+ }
15307
+ async function fileExists(path) {
15308
+ try {
15309
+ await access(path);
15310
+ return true;
15311
+ } catch {
15312
+ return false;
15313
+ }
15314
+ }
15315
+ async function resolveNativeSkills(ast, registryPath, sourceFile) {
15316
+ const skillsBlock = ast.blocks.find((b) => b.name === "skills");
15317
+ if (!skillsBlock || skillsBlock.content.type !== "ObjectContent") {
15318
+ return ast;
15319
+ }
15320
+ const skillsContent = skillsBlock.content;
15321
+ const updatedProperties = { ...skillsContent.properties };
15322
+ let hasUpdates = false;
15323
+ const sourceDir = dirname4(sourceFile);
15324
+ const isSkillsDir = sourceDir.includes("@skills");
15325
+ for (const [skillName, skillValue] of Object.entries(skillsContent.properties)) {
15326
+ if (typeof skillValue !== "object" || skillValue === null || Array.isArray(skillValue)) {
15327
+ continue;
15328
+ }
15329
+ const skillObj = skillValue;
15330
+ let skillMdPath = null;
15331
+ if (isSkillsDir) {
15332
+ const basePath = sourceDir;
15333
+ skillMdPath = resolve3(basePath, skillName, "SKILL.md");
15334
+ } else {
15335
+ skillMdPath = resolve3(registryPath, "@skills", skillName, "SKILL.md");
15336
+ }
15337
+ if (skillMdPath && await fileExists(skillMdPath)) {
15338
+ try {
15339
+ const rawContent = await readFile5(skillMdPath, "utf-8");
15340
+ const parsed = parseSkillMd(rawContent);
15341
+ const updatedSkill = { ...skillObj };
15342
+ if (parsed.content) {
15343
+ updatedSkill["content"] = {
15344
+ type: "TextContent",
15345
+ value: parsed.content,
15346
+ loc: { file: skillMdPath, line: 1, column: 1, offset: 0 }
15347
+ };
15348
+ }
15349
+ if (parsed.description && (!skillObj["description"] || typeof skillObj["description"] === "string" && parsed.description.length > skillObj["description"].length)) {
15350
+ updatedSkill["description"] = parsed.description;
15351
+ }
15352
+ updatedProperties[skillName] = updatedSkill;
15353
+ hasUpdates = true;
15354
+ } catch {
15355
+ }
15356
+ }
15357
+ }
15358
+ if (!hasUpdates) {
15359
+ return ast;
15360
+ }
15361
+ const updatedSkillsBlock = {
15362
+ ...skillsBlock,
15363
+ content: {
15364
+ ...skillsContent,
15365
+ properties: updatedProperties
15366
+ }
15367
+ };
15368
+ const updatedBlocks = ast.blocks.map((b) => b.name === "skills" ? updatedSkillsBlock : b);
15369
+ return {
15370
+ ...ast,
15371
+ blocks: updatedBlocks
15372
+ };
15373
+ }
15374
+
15004
15375
  // packages/resolver/src/resolver.ts
15005
15376
  var Resolver = class {
15006
15377
  loader;
@@ -15053,6 +15424,7 @@ var Resolver = class {
15053
15424
  ast = await this.resolveInherit(ast, absPath, sources, errors);
15054
15425
  ast = await this.resolveImports(ast, absPath, sources, errors);
15055
15426
  ast = applyExtends(ast);
15427
+ ast = await resolveNativeSkills(ast, this.loader.getRegistryPath(), absPath);
15056
15428
  return {
15057
15429
  ast,
15058
15430
  sources: [...new Set(sources)],
@@ -15146,7 +15518,7 @@ var Resolver = class {
15146
15518
  };
15147
15519
 
15148
15520
  // packages/resolver/src/registry.ts
15149
- import { existsSync as existsSync3, promises as fs } from "fs";
15521
+ import { existsSync as existsSync4, promises as fs } from "fs";
15150
15522
  import { join as join3 } from "path";
15151
15523
  var FileSystemRegistry = class {
15152
15524
  rootPath;
@@ -15173,7 +15545,7 @@ var FileSystemRegistry = class {
15173
15545
  }
15174
15546
  async exists(path) {
15175
15547
  const fullPath = this.resolvePath(path);
15176
- return existsSync3(fullPath);
15548
+ return existsSync4(fullPath);
15177
15549
  }
15178
15550
  async list(path) {
15179
15551
  const fullPath = this.resolvePath(path);
@@ -15229,7 +15601,7 @@ var HttpRegistry = class {
15229
15601
  * Sleep for specified milliseconds.
15230
15602
  */
15231
15603
  sleep(ms) {
15232
- return new Promise((resolve7) => setTimeout(resolve7, ms));
15604
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
15233
15605
  }
15234
15606
  /**
15235
15607
  * Fetch with timeout.
@@ -15371,12 +15743,12 @@ function createHttpRegistry(options) {
15371
15743
  }
15372
15744
 
15373
15745
  // packages/resolver/src/git-registry.ts
15374
- import { existsSync as existsSync5, promises as fs3 } from "fs";
15746
+ import { existsSync as existsSync6, promises as fs3 } from "fs";
15375
15747
  import { join as join5 } from "path";
15376
15748
  import { simpleGit } from "simple-git";
15377
15749
 
15378
15750
  // packages/resolver/src/git-cache-manager.ts
15379
- import { existsSync as existsSync4, promises as fs2 } from "fs";
15751
+ import { existsSync as existsSync5, promises as fs2 } from "fs";
15380
15752
  import { join as join4 } from "path";
15381
15753
  import { homedir } from "os";
15382
15754
 
@@ -15526,7 +15898,7 @@ var GitCacheManager = class {
15526
15898
  */
15527
15899
  async get(url, ref) {
15528
15900
  const cachePath = this.getCachePath(url, ref);
15529
- if (!existsSync4(cachePath)) {
15901
+ if (!existsSync5(cachePath)) {
15530
15902
  return null;
15531
15903
  }
15532
15904
  const metadata = await this.readMetadata(cachePath);
@@ -15591,7 +15963,7 @@ var GitCacheManager = class {
15591
15963
  */
15592
15964
  async remove(url, ref) {
15593
15965
  const cachePath = this.getCachePath(url, ref);
15594
- if (existsSync4(cachePath)) {
15966
+ if (existsSync5(cachePath)) {
15595
15967
  await fs2.rm(cachePath, { recursive: true, force: true });
15596
15968
  }
15597
15969
  }
@@ -15601,7 +15973,7 @@ var GitCacheManager = class {
15601
15973
  * @returns Array of cache entries
15602
15974
  */
15603
15975
  async list() {
15604
- if (!existsSync4(this.cacheDir)) {
15976
+ if (!existsSync5(this.cacheDir)) {
15605
15977
  return [];
15606
15978
  }
15607
15979
  const entries = [];
@@ -15636,7 +16008,7 @@ var GitCacheManager = class {
15636
16008
  * Remove all cache entries.
15637
16009
  */
15638
16010
  async clear() {
15639
- if (existsSync4(this.cacheDir)) {
16011
+ if (existsSync5(this.cacheDir)) {
15640
16012
  await fs2.rm(this.cacheDir, { recursive: true, force: true });
15641
16013
  }
15642
16014
  }
@@ -15646,7 +16018,7 @@ var GitCacheManager = class {
15646
16018
  * @returns Total cache size in bytes
15647
16019
  */
15648
16020
  async getSize() {
15649
- if (!existsSync4(this.cacheDir)) {
16021
+ if (!existsSync5(this.cacheDir)) {
15650
16022
  return 0;
15651
16023
  }
15652
16024
  return this.calculateDirSize(this.cacheDir);
@@ -15673,7 +16045,7 @@ var GitCacheManager = class {
15673
16045
  */
15674
16046
  async readMetadata(cachePath) {
15675
16047
  const metadataPath = join4(cachePath, METADATA_FILE);
15676
- if (!existsSync4(metadataPath)) {
16048
+ if (!existsSync5(metadataPath)) {
15677
16049
  return null;
15678
16050
  }
15679
16051
  try {
@@ -15756,7 +16128,7 @@ var GitRegistry = class {
15756
16128
  const ref = version ?? this.defaultRef;
15757
16129
  const repoPath = await this.ensureCloned(ref);
15758
16130
  const filePath = this.resolveFilePath(repoPath, basePath);
15759
- if (!existsSync5(filePath)) {
16131
+ if (!existsSync6(filePath)) {
15760
16132
  throw new FileNotFoundError(path);
15761
16133
  }
15762
16134
  return fs3.readFile(filePath, "utf-8");
@@ -15773,7 +16145,7 @@ var GitRegistry = class {
15773
16145
  const ref = version ?? this.defaultRef;
15774
16146
  const repoPath = await this.ensureCloned(ref);
15775
16147
  const filePath = this.resolveFilePath(repoPath, basePath);
15776
- return existsSync5(filePath);
16148
+ return existsSync6(filePath);
15777
16149
  } catch {
15778
16150
  return false;
15779
16151
  }
@@ -15790,7 +16162,7 @@ var GitRegistry = class {
15790
16162
  const ref = version ?? this.defaultRef;
15791
16163
  const repoPath = await this.ensureCloned(ref);
15792
16164
  const dirPath = this.resolveDirectoryPath(repoPath, basePath);
15793
- if (!existsSync5(dirPath)) {
16165
+ if (!existsSync6(dirPath)) {
15794
16166
  return [];
15795
16167
  }
15796
16168
  const entries = await fs3.readdir(dirPath, { withFileTypes: true });
@@ -15852,7 +16224,7 @@ var GitRegistry = class {
15852
16224
  * Clone the repository to the specified path.
15853
16225
  */
15854
16226
  async clone(targetPath, ref) {
15855
- if (existsSync5(targetPath)) {
16227
+ if (existsSync6(targetPath)) {
15856
16228
  await fs3.rm(targetPath, { recursive: true, force: true });
15857
16229
  }
15858
16230
  await fs3.mkdir(targetPath, { recursive: true });
@@ -16487,6 +16859,39 @@ var Validator = class {
16487
16859
  };
16488
16860
 
16489
16861
  // packages/compiler/src/compiler.ts
16862
+ function generateMarker() {
16863
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
16864
+ return `<!-- PromptScript ${timestamp} - do not edit -->`;
16865
+ }
16866
+ function addMarkerToOutput(output) {
16867
+ const { content, path } = output;
16868
+ if (content.includes("<!-- PromptScript")) {
16869
+ return output;
16870
+ }
16871
+ const marker = generateMarker();
16872
+ if (!path.endsWith(".md") && !path.endsWith(".mdc")) {
16873
+ return output;
16874
+ }
16875
+ if (content.startsWith("---")) {
16876
+ const closingIndex = content.indexOf("---", 3);
16877
+ if (closingIndex !== -1) {
16878
+ const beforeMarker = content.slice(0, closingIndex + 3);
16879
+ const afterMarker = content.slice(closingIndex + 3);
16880
+ const newContent = `${beforeMarker}
16881
+
16882
+ ${marker}
16883
+ ${afterMarker.replace(/^\n+/, "\n")}`;
16884
+ return { ...output, content: newContent };
16885
+ }
16886
+ }
16887
+ const lines = content.split("\n");
16888
+ if (lines[0]?.startsWith("# ")) {
16889
+ lines.splice(1, 0, "", marker);
16890
+ } else {
16891
+ lines.unshift(marker, "");
16892
+ }
16893
+ return { ...output, content: lines.join("\n") };
16894
+ }
16490
16895
  var Compiler = class _Compiler {
16491
16896
  constructor(options) {
16492
16897
  this.options = options;
@@ -16557,10 +16962,10 @@ var Compiler = class _Compiler {
16557
16962
  try {
16558
16963
  const formatOptions = this.getFormatOptionsForTarget(formatter.name, config);
16559
16964
  const output = formatter.format(resolved.ast, formatOptions);
16560
- outputs.set(output.path, output);
16965
+ outputs.set(output.path, addMarkerToOutput(output));
16561
16966
  if (output.additionalFiles) {
16562
16967
  for (const additionalFile of output.additionalFiles) {
16563
- outputs.set(additionalFile.path, additionalFile);
16968
+ outputs.set(additionalFile.path, addMarkerToOutput(additionalFile));
16564
16969
  }
16565
16970
  }
16566
16971
  } catch (err) {
@@ -16644,12 +17049,12 @@ var Compiler = class _Compiler {
16644
17049
  */
16645
17050
  async watch(entryPath, options = {}) {
16646
17051
  const { default: chokidar2 } = await import("chokidar");
16647
- const { dirname: dirname6, resolve: resolve7 } = await import("path");
16648
- const baseDir = dirname6(resolve7(entryPath));
17052
+ const { dirname: dirname8, resolve: resolve9 } = await import("path");
17053
+ const baseDir = dirname8(resolve9(entryPath));
16649
17054
  const includePatterns = options.include ?? ["**/*.prs"];
16650
17055
  const excludePatterns = options.exclude ?? ["**/node_modules/**"];
16651
17056
  const debounceMs = options.debounce ?? 300;
16652
- const watchPatterns = includePatterns.map((p) => resolve7(baseDir, p));
17057
+ const watchPatterns = includePatterns.map((p) => resolve9(baseDir, p));
16653
17058
  let debounceTimer = null;
16654
17059
  let pendingChanges = [];
16655
17060
  const handleChange = async (changedFiles) => {
@@ -16704,14 +17109,13 @@ var Compiler = class _Compiler {
16704
17109
  */
16705
17110
  getFormatOptionsForTarget(_targetName, config) {
16706
17111
  const customConventions = this.options.customConventions;
16707
- if (!config?.convention && !config?.version && !config?.output) {
16708
- return {};
16709
- }
16710
- const conventionName = config?.convention;
17112
+ const prettierOptions = this.options.prettier;
16711
17113
  const options = {
16712
17114
  outputPath: config?.output,
16713
- version: config?.version
17115
+ version: config?.version,
17116
+ prettier: prettierOptions
16714
17117
  };
17118
+ const conventionName = config?.convention;
16715
17119
  if (conventionName && customConventions?.[conventionName]) {
16716
17120
  options.convention = customConventions[conventionName];
16717
17121
  } else if (conventionName) {
@@ -16788,7 +17192,91 @@ var Compiler = class _Compiler {
16788
17192
  }
16789
17193
  };
16790
17194
 
17195
+ // packages/cli/src/output/pager.ts
17196
+ import { spawn } from "child_process";
17197
+ function isTTY() {
17198
+ return process.stdout.isTTY === true;
17199
+ }
17200
+ function getPagerCommand() {
17201
+ return process.env["PAGER"] ?? "less";
17202
+ }
17203
+ var Pager = class {
17204
+ lines = [];
17205
+ enabled;
17206
+ constructor(enabled = true) {
17207
+ this.enabled = enabled && isTTY();
17208
+ }
17209
+ /**
17210
+ * Write a line to the pager buffer.
17211
+ */
17212
+ write(line) {
17213
+ this.lines.push(line);
17214
+ }
17215
+ /**
17216
+ * Write multiple lines to the pager buffer.
17217
+ */
17218
+ writeLines(lines) {
17219
+ this.lines.push(...lines);
17220
+ }
17221
+ /**
17222
+ * Flush all buffered content through the pager.
17223
+ * If pager is disabled or not a TTY, just prints to stdout.
17224
+ */
17225
+ async flush() {
17226
+ const content = this.lines.join("\n");
17227
+ if (!this.enabled || this.lines.length === 0) {
17228
+ if (content) {
17229
+ console.log(content);
17230
+ }
17231
+ return;
17232
+ }
17233
+ return new Promise((resolve9) => {
17234
+ const pagerCmd = getPagerCommand();
17235
+ const [cmd, ...args] = pagerCmd.split(" ");
17236
+ if (cmd === "less" && !args.includes("-R")) {
17237
+ args.push("-R");
17238
+ }
17239
+ if (!cmd) {
17240
+ console.log(content);
17241
+ resolve9();
17242
+ return;
17243
+ }
17244
+ const pager = spawn(cmd, args, {
17245
+ stdio: ["pipe", "inherit", "inherit"],
17246
+ env: {
17247
+ ...process.env,
17248
+ // Ensure less handles colors properly
17249
+ LESS: process.env["LESS"] ?? "-R"
17250
+ }
17251
+ });
17252
+ pager.on("error", (_err) => {
17253
+ console.log(content);
17254
+ resolve9();
17255
+ });
17256
+ pager.on("close", () => {
17257
+ resolve9();
17258
+ });
17259
+ if (pager.stdin) {
17260
+ pager.stdin.write(content);
17261
+ pager.stdin.end();
17262
+ } else {
17263
+ console.log(content);
17264
+ resolve9();
17265
+ }
17266
+ });
17267
+ }
17268
+ };
17269
+ function createPager(enabled = true) {
17270
+ return new Pager(enabled);
17271
+ }
17272
+
16791
17273
  // packages/cli/src/commands/compile.ts
17274
+ var PROMPTSCRIPT_MARKERS = [
17275
+ "<!-- PromptScript",
17276
+ // Current marker (HTML comment with date)
17277
+ "> Auto-generated by PromptScript"
17278
+ // Legacy - for backwards compatibility
17279
+ ];
16792
17280
  function parseTargets(targets) {
16793
17281
  return targets.map((entry) => {
16794
17282
  if (typeof entry === "string") {
@@ -16802,6 +17290,28 @@ function parseTargets(targets) {
16802
17290
  return { name, config };
16803
17291
  }).filter((target) => target.config?.enabled !== false);
16804
17292
  }
17293
+ async function isPromptScriptGenerated(filePath) {
17294
+ try {
17295
+ const content = await readFile6(filePath, "utf-8");
17296
+ const lines = content.split("\n").slice(0, 10);
17297
+ return lines.some((line) => PROMPTSCRIPT_MARKERS.some((marker) => line.includes(marker)));
17298
+ } catch {
17299
+ return false;
17300
+ }
17301
+ }
17302
+ async function promptForOverwrite(filePath, services) {
17303
+ const response = await services.prompts.select({
17304
+ message: `File exists and was not generated by PromptScript: ${filePath}
17305
+ Overwrite?`,
17306
+ choices: [
17307
+ { name: "No (skip this file)", value: "no" },
17308
+ { name: "Yes (overwrite this file)", value: "yes" },
17309
+ { name: "All (overwrite all remaining files)", value: "all" }
17310
+ ],
17311
+ default: "no"
17312
+ });
17313
+ return response;
17314
+ }
16805
17315
  function printErrors(errors) {
16806
17316
  for (const err of errors) {
16807
17317
  ConsoleOutput.error(err.message);
@@ -16810,17 +17320,84 @@ function printErrors(errors) {
16810
17320
  }
16811
17321
  }
16812
17322
  }
16813
- async function writeOutputs(outputs, options, _config) {
17323
+ async function writeOutputs(outputs, options, _config, services) {
17324
+ const result = { written: [], skipped: [] };
17325
+ let overwriteAll = false;
17326
+ const conflicts = [];
16814
17327
  for (const output of outputs.values()) {
16815
- const outputPath = options.output ? resolve2(options.output, output.path) : resolve2(output.path);
17328
+ const outputPath = options.output ? resolve4(options.output, output.path) : resolve4(output.path);
17329
+ const fileExists2 = existsSync7(outputPath);
16816
17330
  if (options.dryRun) {
16817
- ConsoleOutput.dryRun(`Would write: ${outputPath}`);
16818
- } else {
16819
- await mkdir2(dirname3(outputPath), { recursive: true });
17331
+ if (fileExists2) {
17332
+ const isGenerated2 = await isPromptScriptGenerated(outputPath);
17333
+ if (isGenerated2) {
17334
+ ConsoleOutput.dryRun(`Would overwrite: ${outputPath}`);
17335
+ } else {
17336
+ ConsoleOutput.warning(`Would conflict: ${outputPath} (not generated by PromptScript)`);
17337
+ }
17338
+ } else {
17339
+ ConsoleOutput.dryRun(`Would write: ${outputPath}`);
17340
+ }
17341
+ result.written.push(outputPath);
17342
+ continue;
17343
+ }
17344
+ if (!fileExists2) {
17345
+ await mkdir2(dirname5(outputPath), { recursive: true });
17346
+ await writeFile2(outputPath, output.content, "utf-8");
17347
+ ConsoleOutput.success(outputPath);
17348
+ result.written.push(outputPath);
17349
+ continue;
17350
+ }
17351
+ const isGenerated = await isPromptScriptGenerated(outputPath);
17352
+ if (isGenerated) {
17353
+ await mkdir2(dirname5(outputPath), { recursive: true });
17354
+ await writeFile2(outputPath, output.content, "utf-8");
17355
+ ConsoleOutput.success(outputPath);
17356
+ result.written.push(outputPath);
17357
+ continue;
17358
+ }
17359
+ if (options.force || overwriteAll) {
17360
+ await mkdir2(dirname5(outputPath), { recursive: true });
16820
17361
  await writeFile2(outputPath, output.content, "utf-8");
16821
17362
  ConsoleOutput.success(outputPath);
17363
+ result.written.push(outputPath);
17364
+ continue;
17365
+ }
17366
+ if (!isTTY()) {
17367
+ conflicts.push(outputPath);
17368
+ continue;
16822
17369
  }
17370
+ const response = await promptForOverwrite(outputPath, services);
17371
+ switch (response) {
17372
+ case "yes":
17373
+ await mkdir2(dirname5(outputPath), { recursive: true });
17374
+ await writeFile2(outputPath, output.content, "utf-8");
17375
+ ConsoleOutput.success(outputPath);
17376
+ result.written.push(outputPath);
17377
+ break;
17378
+ case "no":
17379
+ ConsoleOutput.skipped(outputPath);
17380
+ result.skipped.push(outputPath);
17381
+ break;
17382
+ case "all":
17383
+ overwriteAll = true;
17384
+ await mkdir2(dirname5(outputPath), { recursive: true });
17385
+ await writeFile2(outputPath, output.content, "utf-8");
17386
+ ConsoleOutput.success(outputPath);
17387
+ result.written.push(outputPath);
17388
+ break;
17389
+ }
17390
+ }
17391
+ if (conflicts.length > 0) {
17392
+ const fileList = conflicts.map((f) => ` - ${f}`).join("\n");
17393
+ throw new Error(
17394
+ `Cannot overwrite files not generated by PromptScript in non-interactive mode:
17395
+ ${fileList}
17396
+
17397
+ Use --force to overwrite these files.`
17398
+ );
16823
17399
  }
17400
+ return result;
16824
17401
  }
16825
17402
  function printStats(stats) {
16826
17403
  ConsoleOutput.newline();
@@ -16837,7 +17414,7 @@ function printWarnings(warnings) {
16837
17414
  }
16838
17415
  }
16839
17416
  }
16840
- async function compileCommand(options) {
17417
+ async function compileCommand(options, services = createDefaultServices()) {
16841
17418
  const spinner = createSpinner("Loading configuration...").start();
16842
17419
  try {
16843
17420
  const config = await loadConfig(options.config);
@@ -16845,6 +17422,7 @@ async function compileCommand(options) {
16845
17422
  const selectedTarget = options.target ?? options.format;
16846
17423
  const targets = selectedTarget ? [{ name: selectedTarget }] : parseTargets(config.targets);
16847
17424
  const registryPath = options.registry ?? config.registry?.path ?? "./registry";
17425
+ const prettierOptions = await resolvePrettierOptions(config, process.cwd());
16848
17426
  const compiler = new Compiler({
16849
17427
  resolver: {
16850
17428
  registryPath,
@@ -16852,10 +17430,11 @@ async function compileCommand(options) {
16852
17430
  },
16853
17431
  validator: config.validation,
16854
17432
  formatters: targets,
16855
- customConventions: config.customConventions
17433
+ customConventions: config.customConventions,
17434
+ prettier: prettierOptions
16856
17435
  });
16857
- const entryPath = resolve2("./.promptscript/project.prs");
16858
- if (!existsSync6(entryPath)) {
17436
+ const entryPath = resolve4("./.promptscript/project.prs");
17437
+ if (!existsSync7(entryPath)) {
16859
17438
  spinner.fail("Entry file not found");
16860
17439
  ConsoleOutput.error(`File not found: ${entryPath}`);
16861
17440
  ConsoleOutput.muted("Run: prs init");
@@ -16870,15 +17449,27 @@ async function compileCommand(options) {
16870
17449
  }
16871
17450
  spinner.succeed("Compilation successful");
16872
17451
  ConsoleOutput.newline();
16873
- await writeOutputs(result.outputs, options, config);
17452
+ const writeResult = await writeOutputs(result.outputs, options, config, services);
17453
+ if (writeResult.skipped.length > 0) {
17454
+ ConsoleOutput.muted(`Skipped ${writeResult.skipped.length} file(s)`);
17455
+ }
16874
17456
  printStats(result.stats);
16875
17457
  printWarnings(result.warnings);
16876
17458
  if (options.watch) {
16877
17459
  ConsoleOutput.newline();
16878
17460
  ConsoleOutput.info("Watching for changes... (Ctrl+C to stop)");
16879
- watchForChanges("./.promptscript", () => compileCommand({ ...options, watch: false }));
17461
+ watchForChanges(
17462
+ "./.promptscript",
17463
+ () => compileCommand({ ...options, watch: false }, services)
17464
+ );
16880
17465
  }
16881
17466
  } catch (error) {
17467
+ if (error.name === "ExitPromptError") {
17468
+ spinner.stop();
17469
+ ConsoleOutput.newline();
17470
+ ConsoleOutput.muted("Compilation cancelled");
17471
+ return;
17472
+ }
16882
17473
  spinner.fail("Error");
16883
17474
  ConsoleOutput.error(error.message);
16884
17475
  process.exit(1);
@@ -16919,8 +17510,8 @@ function watchForChanges(dir, callback) {
16919
17510
  }
16920
17511
 
16921
17512
  // packages/cli/src/commands/validate.ts
16922
- import { resolve as resolve3 } from "path";
16923
- import { existsSync as existsSync7 } from "fs";
17513
+ import { resolve as resolve5 } from "path";
17514
+ import { existsSync as existsSync8 } from "fs";
16924
17515
  function printValidationErrors(errors) {
16925
17516
  if (errors.length === 0) return;
16926
17517
  console.log(`Errors (${errors.length}):`);
@@ -17010,8 +17601,8 @@ async function validateCommand(options) {
17010
17601
  formatters: []
17011
17602
  // No formatters needed for validation only
17012
17603
  });
17013
- const entryPath = resolve3("./.promptscript/project.prs");
17014
- if (!existsSync7(entryPath)) {
17604
+ const entryPath = resolve5("./.promptscript/project.prs");
17605
+ if (!existsSync8(entryPath)) {
17015
17606
  handleEntryNotFound(entryPath, isJsonFormat, spinner);
17016
17607
  }
17017
17608
  const result = await compiler.compile(entryPath);
@@ -17051,8 +17642,8 @@ function outputJsonResult(result) {
17051
17642
 
17052
17643
  // packages/cli/src/commands/pull.ts
17053
17644
  import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
17054
- import { existsSync as existsSync8 } from "fs";
17055
- import { resolve as resolve4, dirname as dirname4 } from "path";
17645
+ import { existsSync as existsSync9 } from "fs";
17646
+ import { resolve as resolve6, dirname as dirname6 } from "path";
17056
17647
  async function pullCommand(options) {
17057
17648
  const spinner = createSpinner("Loading configuration...").start();
17058
17649
  try {
@@ -17075,8 +17666,8 @@ async function pullCommand(options) {
17075
17666
  }
17076
17667
  spinner.text = `Fetching ${inheritPath}...`;
17077
17668
  const content = await registry.fetch(inheritPath);
17078
- const destPath = resolve4("./.promptscript/.inherited", inheritPath);
17079
- if (existsSync8(destPath) && !options.force && !options.dryRun) {
17669
+ const destPath = resolve6("./.promptscript/.inherited", inheritPath);
17670
+ if (existsSync9(destPath) && !options.force && !options.dryRun) {
17080
17671
  spinner.warn("File already exists (use --force to overwrite)");
17081
17672
  ConsoleOutput.muted(destPath);
17082
17673
  return;
@@ -17086,12 +17677,12 @@ async function pullCommand(options) {
17086
17677
  ConsoleOutput.newline();
17087
17678
  ConsoleOutput.dryRun(`Would fetch: ${config.inherit}`);
17088
17679
  ConsoleOutput.dryRun(` to: ${destPath}`);
17089
- if (existsSync8(destPath)) {
17680
+ if (existsSync9(destPath)) {
17090
17681
  ConsoleOutput.dryRun("(would overwrite existing file)");
17091
17682
  }
17092
17683
  return;
17093
17684
  }
17094
- await mkdir3(dirname4(destPath), { recursive: true });
17685
+ await mkdir3(dirname6(destPath), { recursive: true });
17095
17686
  await writeFile3(destPath, content, "utf-8");
17096
17687
  spinner.succeed("Pulled from registry");
17097
17688
  ConsoleOutput.success(destPath);
@@ -17134,10 +17725,10 @@ async function createRegistry(config, options, spinner) {
17134
17725
  }
17135
17726
  const registryPath = config.registry?.path ?? "./registry";
17136
17727
  spinner.text = `Using local registry: ${registryPath}...`;
17137
- if (!existsSync8(registryPath)) {
17728
+ if (!existsSync9(registryPath)) {
17138
17729
  throw new Error(`Local registry path not found: ${registryPath}`);
17139
17730
  }
17140
- return createFileSystemRegistry(resolve4(registryPath));
17731
+ return createFileSystemRegistry(resolve6(registryPath));
17141
17732
  }
17142
17733
  function parseInheritPath(inheritPath) {
17143
17734
  const versionIndex = inheritPath.lastIndexOf("@");
@@ -17184,89 +17775,9 @@ function handlePullError(error, spinner) {
17184
17775
  }
17185
17776
 
17186
17777
  // packages/cli/src/commands/diff.ts
17187
- import { resolve as resolve5 } from "path";
17188
- import { readFile as readFile4 } from "fs/promises";
17189
- import { existsSync as existsSync9 } from "fs";
17190
-
17191
- // packages/cli/src/output/pager.ts
17192
- import { spawn } from "child_process";
17193
- function isTTY() {
17194
- return process.stdout.isTTY === true;
17195
- }
17196
- function getPagerCommand() {
17197
- return process.env["PAGER"] ?? "less";
17198
- }
17199
- var Pager = class {
17200
- lines = [];
17201
- enabled;
17202
- constructor(enabled = true) {
17203
- this.enabled = enabled && isTTY();
17204
- }
17205
- /**
17206
- * Write a line to the pager buffer.
17207
- */
17208
- write(line) {
17209
- this.lines.push(line);
17210
- }
17211
- /**
17212
- * Write multiple lines to the pager buffer.
17213
- */
17214
- writeLines(lines) {
17215
- this.lines.push(...lines);
17216
- }
17217
- /**
17218
- * Flush all buffered content through the pager.
17219
- * If pager is disabled or not a TTY, just prints to stdout.
17220
- */
17221
- async flush() {
17222
- const content = this.lines.join("\n");
17223
- if (!this.enabled || this.lines.length === 0) {
17224
- if (content) {
17225
- console.log(content);
17226
- }
17227
- return;
17228
- }
17229
- return new Promise((resolve7) => {
17230
- const pagerCmd = getPagerCommand();
17231
- const [cmd, ...args] = pagerCmd.split(" ");
17232
- if (cmd === "less" && !args.includes("-R")) {
17233
- args.push("-R");
17234
- }
17235
- if (!cmd) {
17236
- console.log(content);
17237
- resolve7();
17238
- return;
17239
- }
17240
- const pager = spawn(cmd, args, {
17241
- stdio: ["pipe", "inherit", "inherit"],
17242
- env: {
17243
- ...process.env,
17244
- // Ensure less handles colors properly
17245
- LESS: process.env["LESS"] ?? "-R"
17246
- }
17247
- });
17248
- pager.on("error", (_err) => {
17249
- console.log(content);
17250
- resolve7();
17251
- });
17252
- pager.on("close", () => {
17253
- resolve7();
17254
- });
17255
- if (pager.stdin) {
17256
- pager.stdin.write(content);
17257
- pager.stdin.end();
17258
- } else {
17259
- console.log(content);
17260
- resolve7();
17261
- }
17262
- });
17263
- }
17264
- };
17265
- function createPager(enabled = true) {
17266
- return new Pager(enabled);
17267
- }
17268
-
17269
- // packages/cli/src/commands/diff.ts
17778
+ import { resolve as resolve7 } from "path";
17779
+ import { readFile as readFile7 } from "fs/promises";
17780
+ import { existsSync as existsSync10 } from "fs";
17270
17781
  import chalk2 from "chalk";
17271
17782
  function configureColors(options) {
17272
17783
  if (options.color === false) {
@@ -17300,16 +17811,16 @@ function printNewFilePreview(content, showFull, pager) {
17300
17811
  }
17301
17812
  }
17302
17813
  async function compareOutput(_name, output, _config, showFull, pager) {
17303
- const outputPath = resolve5(output.path);
17814
+ const outputPath = resolve7(output.path);
17304
17815
  const newContent = output.content;
17305
- if (!existsSync9(outputPath)) {
17816
+ if (!existsSync10(outputPath)) {
17306
17817
  pager.write(chalk2.green(`+ ${outputPath} (new file)`));
17307
17818
  pager.write("");
17308
17819
  printNewFilePreview(newContent, showFull, pager);
17309
17820
  pager.write("");
17310
17821
  return true;
17311
17822
  }
17312
- const existingContent = await readFile4(outputPath, "utf-8");
17823
+ const existingContent = await readFile7(outputPath, "utf-8");
17313
17824
  if (existingContent === newContent) {
17314
17825
  pager.write(chalk2.gray(` ${outputPath} (no changes)`));
17315
17826
  return false;
@@ -17338,8 +17849,8 @@ async function diffCommand(options) {
17338
17849
  formatters: targets,
17339
17850
  customConventions: config.customConventions
17340
17851
  });
17341
- const entryPath = resolve5("./.promptscript/project.prs");
17342
- if (!existsSync9(entryPath)) {
17852
+ const entryPath = resolve7("./.promptscript/project.prs");
17853
+ if (!existsSync10(entryPath)) {
17343
17854
  spinner.fail("Entry file not found");
17344
17855
  ConsoleOutput.error(`File not found: ${entryPath}`);
17345
17856
  ConsoleOutput.muted("Run: prs init");
@@ -17405,8 +17916,8 @@ function printSimpleDiff(existingLines, newLines, showFull, pager) {
17405
17916
  }
17406
17917
 
17407
17918
  // packages/cli/src/commands/check.ts
17408
- import { existsSync as existsSync10 } from "fs";
17409
- import { resolve as resolve6 } from "path";
17919
+ import { existsSync as existsSync11 } from "fs";
17920
+ import { resolve as resolve8 } from "path";
17410
17921
  async function checkCommand(_options) {
17411
17922
  const spinner = createSpinner("Checking project health...").start();
17412
17923
  const results = [];
@@ -17468,7 +17979,7 @@ async function checkCommand(_options) {
17468
17979
  });
17469
17980
  }
17470
17981
  const entryPath = config.input?.entry ?? ".promptscript/project.prs";
17471
- if (existsSync10(entryPath)) {
17982
+ if (existsSync11(entryPath)) {
17472
17983
  results.push({
17473
17984
  name: "Entry file",
17474
17985
  status: "ok",
@@ -17483,8 +17994,8 @@ async function checkCommand(_options) {
17483
17994
  hasErrors = true;
17484
17995
  }
17485
17996
  if (config.registry?.path) {
17486
- const registryPath = resolve6(config.registry.path);
17487
- if (existsSync10(registryPath)) {
17997
+ const registryPath = resolve8(config.registry.path);
17998
+ if (existsSync11(registryPath)) {
17488
17999
  results.push({
17489
18000
  name: "Registry path",
17490
18001
  status: "ok",
@@ -17567,7 +18078,7 @@ function printResults(results) {
17567
18078
 
17568
18079
  // packages/cli/src/cli.ts
17569
18080
  var __filename2 = fileURLToPath2(import.meta.url);
17570
- var __dirname2 = dirname5(__filename2);
18081
+ var __dirname2 = dirname7(__filename2);
17571
18082
  var program = new Command();
17572
18083
  program.name("prs").description("PromptScript CLI - Standardize AI instructions").version(getPackageVersion(__dirname2, "./package.json")).option("--verbose", "Enable verbose output").option("--quiet", "Suppress non-error output").hook("preAction", (thisCommand) => {
17573
18084
  const opts = thisCommand.opts();
@@ -17581,7 +18092,7 @@ program.name("prs").description("PromptScript CLI - Standardize AI instructions"
17581
18092
  }
17582
18093
  });
17583
18094
  program.command("init").description("Initialize PromptScript in current directory").option("-n, --name <name>", "Project name (auto-detected from package.json, etc.)").option("-t, --team <team>", "Team namespace").option("--inherit <path>", "Inheritance path (e.g., @company/team)").option("--registry <path>", "Registry path").option("--targets <targets...>", "Target AI tools (github, claude, cursor)").option("-i, --interactive", "Force interactive mode").option("-y, --yes", "Skip prompts, use defaults").option("-f, --force", "Force reinitialize even if already initialized").action((opts) => initCommand(opts));
17584
- program.command("compile").description("Compile PromptScript to target formats").option("-t, --target <target>", "Specific target (github, claude, cursor)").option("-f, --format <format>", "Output format (alias for --target)").option("-a, --all", "All configured targets", true).option("-w, --watch", "Watch mode").option("-o, --output <dir>", "Output directory").option("--dry-run", "Preview changes").option("--registry <path>", "Registry path (overrides config)").option("-c, --config <path>", "Path to custom config file").action(compileCommand);
18095
+ program.command("compile").description("Compile PromptScript to target formats").option("-t, --target <target>", "Specific target (github, claude, cursor)").option("-f, --format <format>", "Output format (alias for --target)").option("-a, --all", "All configured targets", true).option("-w, --watch", "Watch mode").option("-o, --output <dir>", "Output directory").option("--dry-run", "Preview changes").option("--registry <path>", "Registry path (overrides config)").option("-c, --config <path>", "Path to custom config file").option("--force", "Force overwrite existing files without prompts").action((opts) => compileCommand(opts));
17585
18096
  program.command("validate").description("Validate PromptScript files").option("--strict", "Treat warnings as errors").option("--format <format>", "Output format (text, json)", "text").action(validateCommand);
17586
18097
  program.command("pull").description("Pull updates from registry").option("-f, --force", "Force overwrite").option("--dry-run", "Preview changes without pulling").option("-b, --branch <name>", "Git branch to pull from").option("--tag <name>", "Git tag to pull from").option("--commit <hash>", "Git commit to pull from").option("--refresh", "Force re-fetch from remote (ignore cache)").action(pullCommand);
17587
18098
  program.command("diff").description("Show diff for compiled output").option("-t, --target <target>", "Specific target").option("-a, --all", "Show diff for all targets at once").option("--full", "Show full diff without truncation").option("--no-pager", "Disable pager output").option("--color", "Force colored output").option("--no-color", "Disable colored output").action(diffCommand);