gitifact 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/dist/THIRD_PARTY_NOTICES.txt +3495 -191
  2. package/dist/browser/assets/BottomSheet-BFoM6syr.js +1 -0
  3. package/dist/browser/assets/Grid-BgyoU_D4.js +1 -0
  4. package/dist/browser/assets/Icon-DPaLmsmh.js +4 -0
  5. package/dist/browser/assets/IconButton-Br-4XhQr.js +1 -0
  6. package/dist/browser/assets/Markdown-d1SaIOZk.js +68 -0
  7. package/dist/browser/assets/{MenuBottomSheet-CQA7HL9k.js → MenuBottomSheet-Dgz4h1S7.js} +1 -1
  8. package/dist/browser/assets/MetadataListItem-BTW_ggUY.js +1 -0
  9. package/dist/browser/assets/ProgressBarMarkTooltip-BxGSd9KS.js +1 -0
  10. package/dist/browser/assets/Section-Z2PuhE6c.js +1 -0
  11. package/dist/browser/assets/Table-7eL9Hctc.js +3 -0
  12. package/dist/browser/assets/TimestampHoverCard-BJShn6bb.js +1 -0
  13. package/dist/browser/assets/Tooltip-MoU3alsv.js +1 -0
  14. package/dist/browser/assets/abnfDiagram-VCTEODGH-DmAlk-TR.js +1 -0
  15. package/dist/browser/assets/about-Dyn0BeO0.js +3 -0
  16. package/dist/browser/assets/activity-Cgw5nLJm.js +1 -0
  17. package/dist/browser/assets/appearance-DgDbwXAm.js +1 -0
  18. package/dist/browser/assets/arc-Pry-7G1_.js +1 -0
  19. package/dist/browser/assets/architecture-7GRP2DOG-BuddTnfb.js +1 -0
  20. package/dist/browser/assets/architectureDiagram-5GKGNRK7-VwuVv8aO.js +36 -0
  21. package/dist/browser/assets/array-BifhSqXX.js +1 -0
  22. package/dist/browser/assets/blockDiagram-I7D4REHJ-BY92gQgN.js +129 -0
  23. package/dist/browser/assets/c4Diagram-7LVT6UL2-D5TNBYXh.js +38 -0
  24. package/dist/browser/assets/changelog-DjXt1_80.js +2 -0
  25. package/dist/browser/assets/channel-NEbtzeVB.js +1 -0
  26. package/dist/browser/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  27. package/dist/browser/assets/chunk-4HAMMTFA-DBbX-wzu.js +62 -0
  28. package/dist/browser/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  29. package/dist/browser/assets/chunk-75Z2AOVW-962-yyBD.js +2 -0
  30. package/dist/browser/assets/chunk-DU6HZSFF-CHHMX1CR.js +127 -0
  31. package/dist/browser/assets/chunk-F27PBJKO-BOnYAGjZ.js +1 -0
  32. package/dist/browser/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
  33. package/dist/browser/assets/chunk-GMAD6QVW-DQF31PdR.js +72 -0
  34. package/dist/browser/assets/chunk-GVQU2GXP-rruJzn36.js +1 -0
  35. package/dist/browser/assets/chunk-IMKFNOWR-CZ8ptS4j.js +231 -0
  36. package/dist/browser/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  37. package/dist/browser/assets/chunk-L3NEJ4N5-USlKRxmU.js +1 -0
  38. package/dist/browser/assets/chunk-OSK3NFVY-DYQeYWNP.js +10 -0
  39. package/dist/browser/assets/chunk-P2QGCYS3-SDkZ9hQX.js +1 -0
  40. package/dist/browser/assets/chunk-POPQ4Y6H-bdnFdIMc.js +1 -0
  41. package/dist/browser/assets/chunk-PWAF6VOD-DuKrEmQw.js +1 -0
  42. package/dist/browser/assets/chunk-SHT3W25Y-IggbHeog.js +168 -0
  43. package/dist/browser/assets/chunk-SVP7TREG-BxYPjkqU.js +88 -0
  44. package/dist/browser/assets/chunk-TICWLB2K-DMrY9ez0.js +206 -0
  45. package/dist/browser/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  46. package/dist/browser/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  47. package/dist/browser/assets/classDiagram-ZZMXUADV-BwE_Hs5R.js +1 -0
  48. package/dist/browser/assets/classDiagram-v2-VYDZK3BY-BwE_Hs5R.js +1 -0
  49. package/dist/browser/assets/{container.stylex-oPimSCGl.js → container.stylex-rwI38dw9.js} +1 -1
  50. package/dist/browser/assets/{contributors._email-CINLTSX2.js → contributors._email-BNMR_dTN.js} +1 -1
  51. package/dist/browser/assets/contributors.index-G5f2IyP0.js +1 -0
  52. package/dist/browser/assets/cose-bilkent-JH36ORCC-BEpcWcmK.js +1 -0
  53. package/dist/browser/assets/cynefin-OW5HDTMX-C4N2LLi1.js +1 -0
  54. package/dist/browser/assets/cynefinDiagram-5FMLGOSQ-C3KE8asf.js +62 -0
  55. package/dist/browser/assets/cytoscape.esm-Yq6u8L66.js +321 -0
  56. package/dist/browser/assets/dagre-C-rnJpZF.js +1 -0
  57. package/dist/browser/assets/dagre-GXQ25YYZ-C20xAaTE.js +4 -0
  58. package/dist/browser/assets/defaultLocale-BFoDCU3G.js +1 -0
  59. package/dist/browser/assets/diagram-S7CK7UJ4-6wtbgLIX.js +30 -0
  60. package/dist/browser/assets/diagram-UQ7AKVKN-BA02zKbd.js +41 -0
  61. package/dist/browser/assets/diagram-VSXAHHWV-Bl0Bun2O.js +3 -0
  62. package/dist/browser/assets/diagram-VX7I27RA-ChsRTsfS.js +24 -0
  63. package/dist/browser/assets/diagram-Z3DM3KII-B3Mxficd.js +24 -0
  64. package/dist/browser/assets/dist-v5Q1xZ2K.js +1 -0
  65. package/dist/browser/assets/document-CaUvlKcm.css +1 -0
  66. package/dist/browser/assets/document-Dx4gYX9t.js +11 -0
  67. package/dist/browser/assets/ebnfDiagram-PWID7BFC-Cs_89QgY.js +1 -0
  68. package/dist/browser/assets/erDiagram-RLTQ6QDP-BefkilYT.js +99 -0
  69. package/dist/browser/assets/eventmodeling-NTZA5JFV-OyiymXqZ.js +1 -0
  70. package/dist/browser/assets/{features._featureId-FySsJ2tl.js → features._featureId-BazwZKuA.js} +1 -1
  71. package/dist/browser/assets/features.index-BJB0VCMw.js +1 -0
  72. package/dist/browser/assets/flowDiagram-HODETNUW-BGkl5kD6.js +1 -0
  73. package/dist/browser/assets/ganttDiagram-EL5Y4UJY-B_Y3HJTL.js +292 -0
  74. package/dist/browser/assets/git-CuSufflq.js +1 -0
  75. package/dist/browser/assets/gitGraph-4MIJSDKK-CPDeR11I.js +1 -0
  76. package/dist/browser/assets/gitGraphDiagram-WWUBYQGX-B89zUhQY.js +106 -0
  77. package/dist/browser/assets/graphlib-DS17s2tU.js +1 -0
  78. package/dist/browser/assets/{index-CiEgP5lo.css → index-BSZEm1y4.css} +1 -1
  79. package/dist/browser/assets/index-Cgka-Zmz.js +48 -0
  80. package/dist/browser/assets/info-A6RAGUB7-DlEdyaYJ.js +1 -0
  81. package/dist/browser/assets/infoDiagram-27XIBGKW-T8vu4pEW.js +2 -0
  82. package/dist/browser/assets/init-C-OQMol4.js +1 -0
  83. package/dist/browser/assets/ishikawaDiagram-5VMMS53U-B4C53CII.js +70 -0
  84. package/dist/browser/assets/journeyDiagram-3NMN7TZE-DemWKqD6.js +139 -0
  85. package/dist/browser/assets/kanban-definition-UXKFOSKX-xMvrIZPT.js +89 -0
  86. package/dist/browser/assets/katex-ZlcWpGUi.js +257 -0
  87. package/dist/browser/assets/line-CfCBYCoS.js +1 -0
  88. package/dist/browser/assets/linear-SzVmGSw4.js +1 -0
  89. package/dist/browser/assets/mermaid-parser.core-DCp4gVZn.js +7 -0
  90. package/dist/browser/assets/mermaid.core-ny8BaDSG.js +44 -0
  91. package/dist/browser/assets/mindmap-definition-YA3MSWOX-CNWF3H17.js +96 -0
  92. package/dist/browser/assets/ordinal-BDEzSJ7C.js +1 -0
  93. package/dist/browser/assets/packet-AYTQ26CC-DgNRIjqj.js +1 -0
  94. package/dist/browser/assets/page-header-BxP70prH.js +124 -0
  95. package/dist/browser/assets/page-header-ClRsIf4A.css +1 -0
  96. package/dist/browser/assets/path-fybaL0A-.js +1 -0
  97. package/dist/browser/assets/pegDiagram-XKGWAZYB-BPEzoUlc.js +1 -0
  98. package/dist/browser/assets/pie-WAS4IAKB-D85SGg9H.js +1 -0
  99. package/dist/browser/assets/pieDiagram-E7YTZNPT-L5HtHPrJ.js +39 -0
  100. package/dist/browser/assets/preload-helper-BZ1Pz5am.js +1 -0
  101. package/dist/browser/assets/product-DLraSF3D.css +1 -0
  102. package/dist/browser/assets/product-Df-TRcl5.js +8 -0
  103. package/dist/browser/assets/product.index-68tq-tnH.js +1 -0
  104. package/dist/browser/assets/quadrantDiagram-AXDQQJYC-BFek-axl.js +7 -0
  105. package/dist/browser/assets/radar-RG4KPBEZ-BwPngHhh.js +1 -0
  106. package/dist/browser/assets/railroad-74A4TZTK-Bf5cESw-.js +1 -0
  107. package/dist/browser/assets/railroad-abnf-HS5TGJTU-QtVzwDRk.js +1 -0
  108. package/dist/browser/assets/railroad-ebnf-LZEXJU2U-CCcgn2jt.js +1 -0
  109. package/dist/browser/assets/railroad-peg-WCYAUIDC-DWRNBkSL.js +1 -0
  110. package/dist/browser/assets/railroadDiagram-O6MQD6OU-0D-Z1mj1.js +1 -0
  111. package/dist/browser/assets/request-state-BR8vtOZQ.js +1 -0
  112. package/dist/browser/assets/requirementDiagram-BXWQKSXE-8pNButqN.js +84 -0
  113. package/dist/browser/assets/requirements-C6bYGbsR.js +1 -0
  114. package/dist/browser/assets/rolldown-runtime-hePW80VL.js +1 -0
  115. package/dist/browser/assets/rough.esm-Dy-Kn_BL.js +1 -0
  116. package/dist/browser/assets/sankeyDiagram-P5KCCOFB-BOWaOPXp.js +40 -0
  117. package/dist/browser/assets/sequenceDiagram-WJ2MYXX4-BA3_JPLh.js +162 -0
  118. package/dist/browser/assets/settings-DHKMQuFF.js +1 -0
  119. package/dist/browser/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  120. package/dist/browser/assets/src-B6xuSHsQ.js +1 -0
  121. package/dist/browser/assets/stateDiagram-D77RDMKH-YYcbi5Z-.js +1 -0
  122. package/dist/browser/assets/stateDiagram-v2-MP3YSRHH-BEg6dLDA.js +1 -0
  123. package/dist/browser/assets/swimlanes-42K2YHIH-B_Eh1oqP.js +1 -0
  124. package/dist/browser/assets/swimlanesDiagram-VR7AAH4N-Bckt0ZyW.js +8 -0
  125. package/dist/browser/assets/themeProps-CkLe5zXY.js +1 -0
  126. package/dist/browser/assets/timeline-definition-24CTP7MA-DfFHHbdC.js +120 -0
  127. package/dist/browser/assets/treeView-Q6P3EWNA-CaZRyAuW.js +1 -0
  128. package/dist/browser/assets/treemap-WGGIJYW6-DI2-Ryxd.js +1 -0
  129. package/dist/browser/assets/useClipboard-Cqx6Upy7.js +1 -0
  130. package/dist/browser/assets/useDevWarning-Dudfg3qF.js +1 -0
  131. package/dist/browser/assets/useIsomorphicLayoutEffect-BiEJxDg_.js +1 -0
  132. package/dist/browser/assets/useMediaQuery-twbHF0pO.js +1 -0
  133. package/dist/browser/assets/useScrollLock-D-Y-zHSV.js +1 -0
  134. package/dist/browser/assets/vennDiagram-4TSXK5OY-QXok2k3u.js +34 -0
  135. package/dist/browser/assets/wardley-WFR3VGLG-BiXQYqiJ.js +1 -0
  136. package/dist/browser/assets/wardleyDiagram-VM6X3IG4-BZBhm2Zm.js +78 -0
  137. package/dist/browser/assets/{wiki-DYxjYiPl.js → wiki-C-iMsNey.js} +1 -1
  138. package/dist/browser/assets/xychartDiagram-S5SC5T6Z-qrzzwM55.js +7 -0
  139. package/dist/browser/index.html +27 -26
  140. package/dist/i18n/ko/block.md +1 -0
  141. package/dist/i18n/ko/changelog.md +32 -0
  142. package/dist/i18n/ko/docs/commit.md +0 -1
  143. package/dist/i18n/ko/docs/design.md +2 -0
  144. package/dist/i18n/ko/docs/spec.md +2 -0
  145. package/dist/i18n/ko/docs/wiki.md +2 -0
  146. package/dist/i18n/ko/docs/writing.md +54 -0
  147. package/dist/main.js +1358 -944
  148. package/package.json +1 -1
  149. package/dist/browser/assets/BottomSheet-F2BUQwSi.js +0 -1
  150. package/dist/browser/assets/Grid-kXvDaAvk.js +0 -1
  151. package/dist/browser/assets/IconButton-CkA9oftf.js +0 -1
  152. package/dist/browser/assets/Markdown-CqZ4w2H_.js +0 -68
  153. package/dist/browser/assets/MetadataListItem-B6xUZEC3.js +0 -1
  154. package/dist/browser/assets/ProgressBarMarkTooltip-BVcVKVq9.js +0 -1
  155. package/dist/browser/assets/Section-zmL2D3WL.js +0 -1
  156. package/dist/browser/assets/Table-DDKWqCdD.js +0 -3
  157. package/dist/browser/assets/TimestampHoverCard-DOWpOAzA.js +0 -1
  158. package/dist/browser/assets/Tooltip-a2AGdnkC.js +0 -1
  159. package/dist/browser/assets/about-Chl-XBQg.js +0 -3
  160. package/dist/browser/assets/activity-F2_AhgBS.js +0 -1
  161. package/dist/browser/assets/changelog-DrJfyXDZ.js +0 -2
  162. package/dist/browser/assets/composeEventHandlers-CHIontwB.js +0 -1
  163. package/dist/browser/assets/contributors.index-ChB89wcL.js +0 -1
  164. package/dist/browser/assets/devWarning-BZMSgwyk.js +0 -1
  165. package/dist/browser/assets/document-Jy6Buepz.js +0 -9
  166. package/dist/browser/assets/document-QMuypGH5.css +0 -1
  167. package/dist/browser/assets/features.index-DWfPG8WV.js +0 -1
  168. package/dist/browser/assets/git-AnH-8SBT.js +0 -1
  169. package/dist/browser/assets/index-DXK4gUTr.js +0 -48
  170. package/dist/browser/assets/page-header-9-i3H9WR.css +0 -1
  171. package/dist/browser/assets/page-header-N7A_M6-B.js +0 -124
  172. package/dist/browser/assets/product-BKOKDrzZ.js +0 -8
  173. package/dist/browser/assets/product-DNlxFjU7.css +0 -1
  174. package/dist/browser/assets/product.index-BohDJK9z.js +0 -1
  175. package/dist/browser/assets/request-state-CO3OLoay.js +0 -1
  176. package/dist/browser/assets/requirements-Dh2NEqNw.js +0 -1
  177. package/dist/browser/assets/settings-DylPhHVJ.js +0 -1
  178. package/dist/browser/assets/themeProps-MQSlTycI.js +0 -1
  179. package/dist/browser/assets/useClipboard-B8Or2k0a.js +0 -1
  180. package/dist/browser/assets/useDevWarning-Xg7kPMHJ.js +0 -1
  181. package/dist/browser/assets/useIsomorphicLayoutEffect-f8dYmyS2.js +0 -1
  182. package/dist/browser/assets/useMediaQuery-DFlnKIlp.js +0 -1
  183. package/dist/browser/assets/useScrollLock-CrQ0xkil.js +0 -1
  184. package/dist/browser/assets/useTranslator-DY2HN18N.js +0 -4
package/dist/main.js CHANGED
@@ -1537,16 +1537,16 @@ var Command = class _Command extends EventEmitter {
1537
1537
  * @param {Function} listener
1538
1538
  * @return {Command} `this` command for chaining
1539
1539
  */
1540
- hook(event, listener) {
1540
+ hook(event2, listener) {
1541
1541
  const allowedValues = ["preSubcommand", "preAction", "postAction"];
1542
- if (!allowedValues.includes(event)) {
1543
- throw new Error(`Unexpected value for event passed to hook : '${event}'.
1542
+ if (!allowedValues.includes(event2)) {
1543
+ throw new Error(`Unexpected value for event passed to hook : '${event2}'.
1544
1544
  Expecting one of '${allowedValues.join("', '")}'`);
1545
1545
  }
1546
- if (this._lifeCycleHooks[event]) {
1547
- this._lifeCycleHooks[event].push(listener);
1546
+ if (this._lifeCycleHooks[event2]) {
1547
+ this._lifeCycleHooks[event2].push(listener);
1548
1548
  } else {
1549
- this._lifeCycleHooks[event] = [listener];
1549
+ this._lifeCycleHooks[event2] = [listener];
1550
1550
  }
1551
1551
  return this;
1552
1552
  }
@@ -2383,15 +2383,15 @@ Expecting one of '${allowedValues.join("', '")}'`);
2383
2383
  * @return {(Promise|undefined)}
2384
2384
  * @private
2385
2385
  */
2386
- _chainOrCallHooks(promise2, event) {
2386
+ _chainOrCallHooks(promise2, event2) {
2387
2387
  let result = promise2;
2388
2388
  const hooks = [];
2389
- this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event] !== void 0).forEach((hookedCommand) => {
2390
- hookedCommand._lifeCycleHooks[event].forEach((callback) => {
2389
+ this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event2] !== void 0).forEach((hookedCommand) => {
2390
+ hookedCommand._lifeCycleHooks[event2].forEach((callback) => {
2391
2391
  hooks.push({ hookedCommand, callback });
2392
2392
  });
2393
2393
  });
2394
- if (event === "postAction") {
2394
+ if (event2 === "postAction") {
2395
2395
  hooks.reverse();
2396
2396
  }
2397
2397
  hooks.forEach((hookDetail) => {
@@ -2409,10 +2409,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2409
2409
  * @return {(Promise|undefined)}
2410
2410
  * @private
2411
2411
  */
2412
- _chainOrCallSubCommandHook(promise2, subCommand, event) {
2412
+ _chainOrCallSubCommandHook(promise2, subCommand, event2) {
2413
2413
  let result = promise2;
2414
- if (this._lifeCycleHooks[event] !== void 0) {
2415
- this._lifeCycleHooks[event].forEach((hook) => {
2414
+ if (this._lifeCycleHooks[event2] !== void 0) {
2415
+ this._lifeCycleHooks[event2].forEach((hook) => {
2416
2416
  result = this._chainOrCall(result, () => {
2417
2417
  return hook(this, subCommand);
2418
2418
  });
@@ -3779,9 +3779,9 @@ function parseDesignPreview(source2, specId) {
3779
3779
  fence = void 0;
3780
3780
  return line;
3781
3781
  }
3782
- const open6 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
3783
- if (open6) {
3784
- fence = { char: open6[1][0], size: open6[1].length };
3782
+ const open5 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
3783
+ if (open5) {
3784
+ fence = { char: open5[1][0], size: open5[1].length };
3785
3785
  return line;
3786
3786
  }
3787
3787
  if (/^#\s/.test(line))
@@ -3832,9 +3832,9 @@ function parseDocument(path3, source2) {
3832
3832
  fence = void 0;
3833
3833
  continue;
3834
3834
  }
3835
- const open6 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
3836
- if (open6) {
3837
- fence = { char: open6[1][0], size: open6[1].length };
3835
+ const open5 = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
3836
+ if (open5) {
3837
+ fence = { char: open5[1][0], size: open5[1].length };
3838
3838
  continue;
3839
3839
  }
3840
3840
  if (/^#\s/.test(line))
@@ -3932,9 +3932,9 @@ function extractLinks(body) {
3932
3932
  fence = void 0;
3933
3933
  continue;
3934
3934
  }
3935
- const open6 = /^ {0,3}(`{3,}|~{3,})/.exec(line);
3936
- if (open6) {
3937
- fence = { char: open6[1][0], size: open6[1].length };
3935
+ const open5 = /^ {0,3}(`{3,}|~{3,})/.exec(line);
3936
+ if (open5) {
3937
+ fence = { char: open5[1][0], size: open5[1].length };
3938
3938
  continue;
3939
3939
  }
3940
3940
  for (const m of line.replace(/`[^`]*`/g, "").matchAll(/!?\[[^\]]*\]\((?:<([^>]+)>|([^)\s]+))(?:\s+"[^"]*")?\)/g))
@@ -4205,11 +4205,11 @@ function parseChangelog(text2) {
4205
4205
  let previous;
4206
4206
  let entry2;
4207
4207
  let section;
4208
- const fail8 = (line, key, values = {}) => new InitError("INVALID_CHANGELOG", t("changelog.atLine", { line, reason: t(key, values) }));
4208
+ const fail9 = (line, key, values = {}) => new InitError("INVALID_CHANGELOG", t("changelog.atLine", { line, reason: t(key, values) }));
4209
4209
  const lines = text2.replace(/\r\n/g, "\n").split("\n");
4210
4210
  const close = (line) => {
4211
4211
  if (entry2 && changelogSections.every((name) => entry2[name].length === 0))
4212
- throw fail8(line, "changelog.emptyVersion", { version: entry2.version });
4212
+ throw fail9(line, "changelog.emptyVersion", { version: entry2.version });
4213
4213
  };
4214
4214
  lines.forEach((raw, index) => {
4215
4215
  const line = index + 1;
@@ -4220,9 +4220,9 @@ function parseChangelog(text2) {
4220
4220
  close(line);
4221
4221
  const core = [Number(version2[1]), Number(version2[2]), Number(version2[3])];
4222
4222
  if (!realDate(Number(version2[4]), Number(version2[5]), Number(version2[6])))
4223
- throw fail8(line, "changelog.invalidDate", { text: raw });
4223
+ throw fail9(line, "changelog.invalidDate", { text: raw });
4224
4224
  if (previous && !(core[0] < previous[0] || core[0] === previous[0] && (core[1] < previous[1] || core[1] === previous[1] && core[2] < previous[2]))) {
4225
- throw fail8(line, "changelog.order", { version: core.join(".") });
4225
+ throw fail9(line, "changelog.order", { version: core.join(".") });
4226
4226
  }
4227
4227
  previous = core;
4228
4228
  section = void 0;
@@ -4233,25 +4233,25 @@ function parseChangelog(text2) {
4233
4233
  const heading = sectionLine.exec(raw);
4234
4234
  if (heading) {
4235
4235
  if (!entry2)
4236
- throw fail8(line, "changelog.sectionBeforeVersion");
4236
+ throw fail9(line, "changelog.sectionBeforeVersion");
4237
4237
  const name = heading[1].toLowerCase();
4238
4238
  if (entry2[name].length > 0)
4239
- throw fail8(line, "changelog.duplicateSection", { section: heading[1] });
4239
+ throw fail9(line, "changelog.duplicateSection", { section: heading[1] });
4240
4240
  section = name;
4241
4241
  return;
4242
4242
  }
4243
4243
  const item = itemLine.exec(raw);
4244
4244
  if (item) {
4245
4245
  if (!entry2 || !section)
4246
- throw fail8(line, "changelog.itemOutsideSection");
4246
+ throw fail9(line, "changelog.itemOutsideSection");
4247
4247
  entry2[section].push(item[1].trimEnd());
4248
4248
  return;
4249
4249
  }
4250
- throw fail8(line, "changelog.unknownLine", { text: raw });
4250
+ throw fail9(line, "changelog.unknownLine", { text: raw });
4251
4251
  });
4252
4252
  close(lines.length);
4253
4253
  if (entries.length === 0)
4254
- throw fail8(1, "changelog.noVersions");
4254
+ throw fail9(1, "changelog.noVersions");
4255
4255
  return entries;
4256
4256
  }
4257
4257
 
@@ -4591,10 +4591,10 @@ function decodeGitLine(buffer) {
4591
4591
  if (!value || value.includes("\0")) return invalid();
4592
4592
  return value;
4593
4593
  }
4594
- function fieldsAndPath(record3, count) {
4594
+ function fieldsAndPath(record3, count2) {
4595
4595
  const fields2 = [];
4596
4596
  let start = 0;
4597
- for (let index = 0; index < count; index++) {
4597
+ for (let index = 0; index < count2; index++) {
4598
4598
  const end = record3.indexOf(" ", start);
4599
4599
  if (end <= start) return invalid();
4600
4600
  fields2.push(record3.slice(start, end));
@@ -4645,7 +4645,7 @@ function parsePorcelain(buffer, format) {
4645
4645
  const modes = fields2.slice(3, conflict ? 7 : 6);
4646
4646
  if (modes.some((mode) => !/^(000000|100644|100755|120000|160000)$/.test(mode))) return invalid();
4647
4647
  const oids = fields2.slice(conflict ? 7 : 6);
4648
- if (oids.some((oid2) => !oidPattern.test(oid2))) return invalid();
4648
+ if (oids.some((oid3) => !oidPattern.test(oid3))) return invalid();
4649
4649
  change2 = { kind: conflict ? "unmerged" : "tracked", path: path3, xy, submodule: submodule(fields2[2]) };
4650
4650
  } else return invalid();
4651
4651
  if (seen.has(change2.path)) return invalid();
@@ -6023,14 +6023,14 @@ function codePointLength(str) {
6023
6023
  const units = str.length;
6024
6024
  if (!highSurrogate.test(str))
6025
6025
  return units;
6026
- let count = units;
6026
+ let count2 = units;
6027
6027
  for (let i = 0; i < units - 1; i++) {
6028
6028
  if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
6029
- count--;
6029
+ count2--;
6030
6030
  i++;
6031
6031
  }
6032
6032
  }
6033
- return count;
6033
+ return count2;
6034
6034
  }
6035
6035
  function getLengthableOrigin(input2) {
6036
6036
  if (Array.isArray(input2))
@@ -8571,16 +8571,16 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
8571
8571
  };
8572
8572
  });
8573
8573
  function handleExclusiveUnionResults(results, final, inst, ctx) {
8574
- const matches = [];
8574
+ const matches2 = [];
8575
8575
  for (let i = 0; i < results.length; i++) {
8576
8576
  if (results[i].issues.length === 0)
8577
- matches.push(i);
8577
+ matches2.push(i);
8578
8578
  }
8579
- if (matches.length === 1) {
8580
- final.value = results[matches[0]].value;
8579
+ if (matches2.length === 1) {
8580
+ final.value = results[matches2[0]].value;
8581
8581
  return final;
8582
8582
  }
8583
- if (matches.length === 0) {
8583
+ if (matches2.length === 0) {
8584
8584
  final.issues.push({
8585
8585
  code: "invalid_union",
8586
8586
  input: final.value,
@@ -8594,7 +8594,7 @@ function handleExclusiveUnionResults(results, final, inst, ctx) {
8594
8594
  inst,
8595
8595
  errors: [],
8596
8596
  inclusive: false,
8597
- matches
8597
+ matches: matches2
8598
8598
  });
8599
8599
  }
8600
8600
  return final;
@@ -10385,8 +10385,8 @@ function az_default() {
10385
10385
  }
10386
10386
 
10387
10387
  // ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/be.js
10388
- function getBelarusianPlural(count, one, few, many) {
10389
- const absCount = Math.abs(count);
10388
+ function getBelarusianPlural(count2, one, few, many) {
10389
+ const absCount = Math.abs(count2);
10390
10390
  const lastDigit = absCount % 10;
10391
10391
  const lastTwoDigits = absCount % 100;
10392
10392
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -13033,8 +13033,8 @@ function hu_default() {
13033
13033
  }
13034
13034
 
13035
13035
  // ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/hy.js
13036
- function getArmenianPlural(count, one, many) {
13037
- return Math.abs(count) === 1 ? one : many;
13036
+ function getArmenianPlural(count2, one, many) {
13037
+ return Math.abs(count2) === 1 ? one : many;
13038
13038
  }
13039
13039
  function withDefiniteArticle(word) {
13040
13040
  if (!word)
@@ -15772,8 +15772,8 @@ function ro_default() {
15772
15772
  }
15773
15773
 
15774
15774
  // ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/ru.js
15775
- function getRussianPlural(count, one, few, many) {
15776
- const absCount = Math.abs(count);
15775
+ function getRussianPlural(count2, one, few, many) {
15776
+ const absCount = Math.abs(count2);
15777
15777
  const lastDigit = absCount % 10;
15778
15778
  const lastTwoDigits = absCount % 100;
15779
15779
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -20407,13 +20407,13 @@ function initializeContext(params) {
20407
20407
  external: params?.external ?? void 0
20408
20408
  };
20409
20409
  }
20410
- function handleUnrepresentable(schema, ctx, json2, params, message) {
20410
+ function handleUnrepresentable(schema, ctx, json3, params, message) {
20411
20411
  const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message }) : ctx.unrepresentable;
20412
20412
  if (result === "any")
20413
20413
  return false;
20414
20414
  if (result === void 0 || result === "throw")
20415
20415
  throw new Error(message);
20416
- Object.assign(json2, result);
20416
+ Object.assign(json3, result);
20417
20417
  return true;
20418
20418
  }
20419
20419
  function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
@@ -20649,12 +20649,12 @@ function foldObjects(members2) {
20649
20649
  }
20650
20650
  return folded;
20651
20651
  }
20652
- function foldIntersection(json2) {
20653
- const allOf = json2.allOf;
20652
+ function foldIntersection(json3) {
20653
+ const allOf = json3.allOf;
20654
20654
  if (!Array.isArray(allOf) || allOf.length < 2)
20655
20655
  return;
20656
20656
  for (const key of FOLDABLE_KEYS)
20657
- if (key in json2)
20657
+ if (key in json3)
20658
20658
  return;
20659
20659
  const unions = allOf.filter((m) => UNION_KEYS.some((k) => Array.isArray(m[k])));
20660
20660
  let folded = null;
@@ -20673,8 +20673,8 @@ function foldIntersection(json2) {
20673
20673
  }
20674
20674
  if (!folded)
20675
20675
  return;
20676
- delete json2.allOf;
20677
- assignProps(json2, folded);
20676
+ delete json3.allOf;
20677
+ assignProps(json3, folded);
20678
20678
  }
20679
20679
  function finalize(ctx, schema) {
20680
20680
  const root = ctx.seen.get(schema);
@@ -20756,20 +20756,20 @@ function finalize(ctx, schema) {
20756
20756
  if (ctx.intersections.length) {
20757
20757
  const carriers = /* @__PURE__ */ new Map();
20758
20758
  for (const seen of ctx.seen.values()) {
20759
- for (const json2 of [seen.schema, seen.def]) {
20760
- const allOf = json2?.allOf;
20759
+ for (const json3 of [seen.schema, seen.def]) {
20760
+ const allOf = json3?.allOf;
20761
20761
  if (!Array.isArray(allOf))
20762
20762
  continue;
20763
20763
  const existing = carriers.get(allOf);
20764
20764
  if (existing)
20765
- existing.push(json2);
20765
+ existing.push(json3);
20766
20766
  else
20767
- carriers.set(allOf, [json2]);
20767
+ carriers.set(allOf, [json3]);
20768
20768
  }
20769
20769
  }
20770
20770
  for (const allOf of ctx.intersections) {
20771
- for (const json2 of carriers.get(allOf) ?? [])
20772
- foldIntersection(json2);
20771
+ for (const json3 of carriers.get(allOf) ?? [])
20772
+ foldIntersection(json3);
20773
20773
  }
20774
20774
  }
20775
20775
  }
@@ -21004,29 +21004,29 @@ var exactPatterns = /* @__PURE__ */ new Map([
21004
21004
  ]);
21005
21005
  var exactPattern = (p) => exactPatterns.get(p) ?? p;
21006
21006
  var stringProcessor = (schema, ctx, _json, _params) => {
21007
- const json2 = _json;
21008
- json2.type = "string";
21007
+ const json3 = _json;
21008
+ json3.type = "string";
21009
21009
  const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
21010
21010
  if (typeof minimum === "number")
21011
- json2.minLength = minimum;
21011
+ json3.minLength = minimum;
21012
21012
  if (typeof maximum === "number")
21013
- json2.maxLength = maximum;
21013
+ json3.maxLength = maximum;
21014
21014
  if (format) {
21015
- json2.format = formatMap[format] ?? format;
21016
- if (json2.format === "")
21017
- delete json2.format;
21015
+ json3.format = formatMap[format] ?? format;
21016
+ if (json3.format === "")
21017
+ delete json3.format;
21018
21018
  if (format === "time" || laxFormat) {
21019
- delete json2.format;
21019
+ delete json3.format;
21020
21020
  }
21021
21021
  }
21022
21022
  if (contentEncoding)
21023
- json2.contentEncoding = contentEncoding;
21023
+ json3.contentEncoding = contentEncoding;
21024
21024
  if (patterns && patterns.size > 0) {
21025
21025
  const patternList = [...patterns].map(exactPattern);
21026
21026
  if (patternList.length === 1)
21027
- json2.pattern = patternList[0].source;
21027
+ json3.pattern = patternList[0].source;
21028
21028
  else if (patternList.length > 1) {
21029
- json2.allOf = [
21029
+ json3.allOf = [
21030
21030
  ...patternList.map((regex) => ({
21031
21031
  ...ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0" ? { type: "string" } : {},
21032
21032
  pattern: regex.source
@@ -21036,31 +21036,31 @@ var stringProcessor = (schema, ctx, _json, _params) => {
21036
21036
  }
21037
21037
  };
21038
21038
  var numberProcessor = (schema, ctx, _json, params) => {
21039
- const json2 = _json;
21039
+ const json3 = _json;
21040
21040
  const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
21041
- json2.type = isInt ? "integer" : "number";
21041
+ json3.type = isInt ? "integer" : "number";
21042
21042
  const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
21043
21043
  const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
21044
21044
  const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
21045
21045
  if (exMin) {
21046
21046
  if (legacy) {
21047
- json2.minimum = exclusiveMinimum;
21048
- json2.exclusiveMinimum = true;
21047
+ json3.minimum = exclusiveMinimum;
21048
+ json3.exclusiveMinimum = true;
21049
21049
  } else {
21050
- json2.exclusiveMinimum = exclusiveMinimum;
21050
+ json3.exclusiveMinimum = exclusiveMinimum;
21051
21051
  }
21052
21052
  } else if (typeof minimum === "number") {
21053
- json2.minimum = minimum;
21053
+ json3.minimum = minimum;
21054
21054
  }
21055
21055
  if (exMax) {
21056
21056
  if (legacy) {
21057
- json2.maximum = exclusiveMaximum;
21058
- json2.exclusiveMaximum = true;
21057
+ json3.maximum = exclusiveMaximum;
21058
+ json3.exclusiveMaximum = true;
21059
21059
  } else {
21060
- json2.exclusiveMaximum = exclusiveMaximum;
21060
+ json3.exclusiveMaximum = exclusiveMaximum;
21061
21061
  }
21062
21062
  } else if (typeof maximum === "number") {
21063
- json2.maximum = maximum;
21063
+ json3.maximum = maximum;
21064
21064
  }
21065
21065
  if (multipleOf) {
21066
21066
  const divisors = /* @__PURE__ */ new Set();
@@ -21068,75 +21068,75 @@ var numberProcessor = (schema, ctx, _json, params) => {
21068
21068
  if (Number.isFinite(divisor) && divisor !== 0)
21069
21069
  divisors.add(Math.abs(divisor));
21070
21070
  else
21071
- handleUnrepresentable(schema, ctx, json2, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
21071
+ handleUnrepresentable(schema, ctx, json3, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
21072
21072
  }
21073
21073
  const [first, ...rest] = divisors;
21074
21074
  if (first !== void 0)
21075
- json2.multipleOf = first;
21075
+ json3.multipleOf = first;
21076
21076
  if (rest.length)
21077
- json2.allOf = [...json2.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
21077
+ json3.allOf = [...json3.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
21078
21078
  }
21079
21079
  };
21080
- var booleanProcessor = (_schema, _ctx, json2, _params) => {
21081
- json2.type = "boolean";
21080
+ var booleanProcessor = (_schema, _ctx, json3, _params) => {
21081
+ json3.type = "boolean";
21082
21082
  };
21083
- var bigintProcessor = (schema, ctx, json2, params) => {
21084
- handleUnrepresentable(schema, ctx, json2, params, "BigInt cannot be represented in JSON Schema");
21083
+ var bigintProcessor = (schema, ctx, json3, params) => {
21084
+ handleUnrepresentable(schema, ctx, json3, params, "BigInt cannot be represented in JSON Schema");
21085
21085
  };
21086
- var symbolProcessor = (schema, ctx, json2, params) => {
21087
- handleUnrepresentable(schema, ctx, json2, params, "Symbols cannot be represented in JSON Schema");
21086
+ var symbolProcessor = (schema, ctx, json3, params) => {
21087
+ handleUnrepresentable(schema, ctx, json3, params, "Symbols cannot be represented in JSON Schema");
21088
21088
  };
21089
- var nullProcessor = (_schema, ctx, json2, _params) => {
21089
+ var nullProcessor = (_schema, ctx, json3, _params) => {
21090
21090
  if (ctx.target === "openapi-3.0") {
21091
- json2.type = "string";
21092
- json2.nullable = true;
21093
- json2.enum = [null];
21091
+ json3.type = "string";
21092
+ json3.nullable = true;
21093
+ json3.enum = [null];
21094
21094
  } else {
21095
- json2.type = "null";
21095
+ json3.type = "null";
21096
21096
  }
21097
21097
  };
21098
- var undefinedProcessor = (schema, ctx, json2, params) => {
21099
- handleUnrepresentable(schema, ctx, json2, params, "Undefined cannot be represented in JSON Schema");
21098
+ var undefinedProcessor = (schema, ctx, json3, params) => {
21099
+ handleUnrepresentable(schema, ctx, json3, params, "Undefined cannot be represented in JSON Schema");
21100
21100
  };
21101
- var voidProcessor = (schema, ctx, json2, params) => {
21102
- handleUnrepresentable(schema, ctx, json2, params, "Void cannot be represented in JSON Schema");
21101
+ var voidProcessor = (schema, ctx, json3, params) => {
21102
+ handleUnrepresentable(schema, ctx, json3, params, "Void cannot be represented in JSON Schema");
21103
21103
  };
21104
- var neverProcessor = (_schema, _ctx, json2, _params) => {
21105
- json2.not = {};
21104
+ var neverProcessor = (_schema, _ctx, json3, _params) => {
21105
+ json3.not = {};
21106
21106
  };
21107
21107
  var anyProcessor = (_schema, _ctx, _json, _params) => {
21108
21108
  };
21109
21109
  var unknownProcessor = (_schema, _ctx, _json, _params) => {
21110
21110
  };
21111
- var dateProcessor = (schema, ctx, json2, params) => {
21112
- handleUnrepresentable(schema, ctx, json2, params, "Date cannot be represented in JSON Schema");
21111
+ var dateProcessor = (schema, ctx, json3, params) => {
21112
+ handleUnrepresentable(schema, ctx, json3, params, "Date cannot be represented in JSON Schema");
21113
21113
  };
21114
- var enumProcessor = (schema, _ctx, json2, _params) => {
21114
+ var enumProcessor = (schema, _ctx, json3, _params) => {
21115
21115
  const def = schema._zod.def;
21116
21116
  const values = getEnumValues(def.entries);
21117
21117
  if (values.length === 0) {
21118
- json2.not = {};
21118
+ json3.not = {};
21119
21119
  return;
21120
21120
  }
21121
21121
  if (values.every((v) => typeof v === "number"))
21122
- json2.type = "number";
21122
+ json3.type = "number";
21123
21123
  if (values.every((v) => typeof v === "string"))
21124
- json2.type = "string";
21125
- json2.enum = values;
21124
+ json3.type = "string";
21125
+ json3.enum = values;
21126
21126
  };
21127
- var literalProcessor = (schema, ctx, json2, params) => {
21127
+ var literalProcessor = (schema, ctx, json3, params) => {
21128
21128
  const def = schema._zod.def;
21129
21129
  if (def.values.length === 0) {
21130
- json2.not = {};
21130
+ json3.not = {};
21131
21131
  return;
21132
21132
  }
21133
21133
  const vals = [];
21134
21134
  for (const val of def.values) {
21135
21135
  if (val === void 0) {
21136
- if (handleUnrepresentable(schema, ctx, json2, params, "Literal `undefined` cannot be represented in JSON Schema"))
21136
+ if (handleUnrepresentable(schema, ctx, json3, params, "Literal `undefined` cannot be represented in JSON Schema"))
21137
21137
  return;
21138
21138
  } else if (typeof val === "bigint") {
21139
- if (handleUnrepresentable(schema, ctx, json2, params, "BigInt literals cannot be represented in JSON Schema"))
21139
+ if (handleUnrepresentable(schema, ctx, json3, params, "BigInt literals cannot be represented in JSON Schema"))
21140
21140
  return;
21141
21141
  vals.push(Number(val));
21142
21142
  } else {
@@ -21146,37 +21146,37 @@ var literalProcessor = (schema, ctx, json2, params) => {
21146
21146
  if (vals.length === 0) {
21147
21147
  } else if (vals.length === 1) {
21148
21148
  const val = vals[0];
21149
- json2.type = val === null ? "null" : typeof val;
21149
+ json3.type = val === null ? "null" : typeof val;
21150
21150
  if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
21151
- json2.enum = [val];
21151
+ json3.enum = [val];
21152
21152
  } else {
21153
- json2.const = val;
21153
+ json3.const = val;
21154
21154
  }
21155
21155
  } else {
21156
21156
  if (vals.every((v) => typeof v === "number"))
21157
- json2.type = "number";
21157
+ json3.type = "number";
21158
21158
  if (vals.every((v) => typeof v === "string"))
21159
- json2.type = "string";
21159
+ json3.type = "string";
21160
21160
  if (vals.every((v) => typeof v === "boolean"))
21161
- json2.type = "boolean";
21161
+ json3.type = "boolean";
21162
21162
  if (vals.every((v) => v === null))
21163
- json2.type = "null";
21164
- json2.enum = vals;
21163
+ json3.type = "null";
21164
+ json3.enum = vals;
21165
21165
  }
21166
21166
  };
21167
- var nanProcessor = (schema, ctx, json2, params) => {
21168
- handleUnrepresentable(schema, ctx, json2, params, "NaN cannot be represented in JSON Schema");
21167
+ var nanProcessor = (schema, ctx, json3, params) => {
21168
+ handleUnrepresentable(schema, ctx, json3, params, "NaN cannot be represented in JSON Schema");
21169
21169
  };
21170
- var templateLiteralProcessor = (schema, _ctx, json2, _params) => {
21171
- const _json = json2;
21170
+ var templateLiteralProcessor = (schema, _ctx, json3, _params) => {
21171
+ const _json = json3;
21172
21172
  const pattern = schema._zod.pattern;
21173
21173
  if (!pattern)
21174
21174
  throw new Error("Pattern not found in template literal");
21175
21175
  _json.type = "string";
21176
21176
  _json.pattern = pattern.source;
21177
21177
  };
21178
- var fileProcessor = (schema, _ctx, json2, _params) => {
21179
- const _json = json2;
21178
+ var fileProcessor = (schema, _ctx, json3, _params) => {
21179
+ const _json = json3;
21180
21180
  _json.type = "string";
21181
21181
  _json.format = "binary";
21182
21182
  _json.contentEncoding = "binary";
@@ -21194,34 +21194,34 @@ var fileProcessor = (schema, _ctx, json2, _params) => {
21194
21194
  else
21195
21195
  _json.anyOf = mime.map((m) => ({ contentMediaType: m }));
21196
21196
  };
21197
- var successProcessor = (_schema, _ctx, json2, _params) => {
21198
- json2.type = "boolean";
21197
+ var successProcessor = (_schema, _ctx, json3, _params) => {
21198
+ json3.type = "boolean";
21199
21199
  };
21200
- var customProcessor = (schema, ctx, json2, params) => {
21201
- handleUnrepresentable(schema, ctx, json2, params, "Custom types cannot be represented in JSON Schema");
21200
+ var customProcessor = (schema, ctx, json3, params) => {
21201
+ handleUnrepresentable(schema, ctx, json3, params, "Custom types cannot be represented in JSON Schema");
21202
21202
  };
21203
- var functionProcessor = (schema, ctx, json2, params) => {
21204
- handleUnrepresentable(schema, ctx, json2, params, "Function types cannot be represented in JSON Schema");
21203
+ var functionProcessor = (schema, ctx, json3, params) => {
21204
+ handleUnrepresentable(schema, ctx, json3, params, "Function types cannot be represented in JSON Schema");
21205
21205
  };
21206
- var transformProcessor = (schema, ctx, json2, params) => {
21207
- handleUnrepresentable(schema, ctx, json2, params, "Transforms cannot be represented in JSON Schema");
21206
+ var transformProcessor = (schema, ctx, json3, params) => {
21207
+ handleUnrepresentable(schema, ctx, json3, params, "Transforms cannot be represented in JSON Schema");
21208
21208
  };
21209
- var mapProcessor = (schema, ctx, json2, params) => {
21210
- handleUnrepresentable(schema, ctx, json2, params, "Map cannot be represented in JSON Schema");
21209
+ var mapProcessor = (schema, ctx, json3, params) => {
21210
+ handleUnrepresentable(schema, ctx, json3, params, "Map cannot be represented in JSON Schema");
21211
21211
  };
21212
- var setProcessor = (schema, ctx, json2, params) => {
21213
- handleUnrepresentable(schema, ctx, json2, params, "Set cannot be represented in JSON Schema");
21212
+ var setProcessor = (schema, ctx, json3, params) => {
21213
+ handleUnrepresentable(schema, ctx, json3, params, "Set cannot be represented in JSON Schema");
21214
21214
  };
21215
21215
  var arrayProcessor = (schema, ctx, _json, params) => {
21216
- const json2 = _json;
21216
+ const json3 = _json;
21217
21217
  const def = schema._zod.def;
21218
21218
  const { minimum, maximum } = aggregateChecks(schema);
21219
21219
  if (typeof minimum === "number")
21220
- json2.minItems = minimum;
21220
+ json3.minItems = minimum;
21221
21221
  if (typeof maximum === "number")
21222
- json2.maxItems = maximum;
21223
- json2.type = "array";
21224
- json2.items = processSchema(def.element, ctx, {
21222
+ json3.maxItems = maximum;
21223
+ json3.type = "array";
21224
+ json3.items = processSchema(def.element, ctx, {
21225
21225
  ...params,
21226
21226
  path: [...params.path, "items"]
21227
21227
  });
@@ -21237,17 +21237,17 @@ function inputOptin(schema) {
21237
21237
  return schema._zod.optin;
21238
21238
  }
21239
21239
  var objectProcessor = (schema, ctx, _json, params) => {
21240
- const json2 = _json;
21240
+ const json3 = _json;
21241
21241
  const def = schema._zod.def;
21242
21242
  const shape = def.shape;
21243
21243
  const symbolKeys = Object.getOwnPropertySymbols(shape);
21244
- if (symbolKeys.length && handleUnrepresentable(schema, ctx, json2, params, "Symbol keys cannot be represented in JSON Schema")) {
21244
+ if (symbolKeys.length && handleUnrepresentable(schema, ctx, json3, params, "Symbol keys cannot be represented in JSON Schema")) {
21245
21245
  return;
21246
21246
  }
21247
- json2.type = "object";
21248
- json2.properties = {};
21247
+ json3.type = "object";
21248
+ json3.properties = {};
21249
21249
  for (const key in shape) {
21250
- assignProp(json2.properties, key, processSchema(shape[key], ctx, {
21250
+ assignProp(json3.properties, key, processSchema(shape[key], ctx, {
21251
21251
  ...params,
21252
21252
  path: [...params.path, "properties", key]
21253
21253
  }));
@@ -21260,21 +21260,21 @@ var objectProcessor = (schema, ctx, _json, params) => {
21260
21260
  }
21261
21261
  }
21262
21262
  if (requiredKeys.length > 0) {
21263
- json2.required = requiredKeys;
21263
+ json3.required = requiredKeys;
21264
21264
  }
21265
21265
  if (def.catchall?._zod.def.type === "never") {
21266
- json2.additionalProperties = false;
21266
+ json3.additionalProperties = false;
21267
21267
  } else if (!def.catchall) {
21268
21268
  if (ctx.io === "output")
21269
- json2.additionalProperties = false;
21269
+ json3.additionalProperties = false;
21270
21270
  } else if (def.catchall) {
21271
- json2.additionalProperties = processSchema(def.catchall, ctx, {
21271
+ json3.additionalProperties = processSchema(def.catchall, ctx, {
21272
21272
  ...params,
21273
21273
  path: [...params.path, "additionalProperties"]
21274
21274
  });
21275
21275
  }
21276
21276
  };
21277
- var unionProcessor = (schema, ctx, json2, params) => {
21277
+ var unionProcessor = (schema, ctx, json3, params) => {
21278
21278
  const def = schema._zod.def;
21279
21279
  const isExclusive = def.inclusive === false;
21280
21280
  const options = def.options.map((x, i) => processSchema(x, ctx, {
@@ -21282,12 +21282,12 @@ var unionProcessor = (schema, ctx, json2, params) => {
21282
21282
  path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
21283
21283
  }));
21284
21284
  if (isExclusive) {
21285
- json2.oneOf = options;
21285
+ json3.oneOf = options;
21286
21286
  } else {
21287
- json2.anyOf = options;
21287
+ json3.anyOf = options;
21288
21288
  }
21289
21289
  };
21290
- var intersectionProcessor = (schema, ctx, json2, params) => {
21290
+ var intersectionProcessor = (schema, ctx, json3, params) => {
21291
21291
  const def = schema._zod.def;
21292
21292
  const a = processSchema(def.left, ctx, {
21293
21293
  ...params,
@@ -21302,13 +21302,13 @@ var intersectionProcessor = (schema, ctx, json2, params) => {
21302
21302
  ...isSimpleIntersection(a) ? a.allOf : [a],
21303
21303
  ...isSimpleIntersection(b) ? b.allOf : [b]
21304
21304
  ];
21305
- json2.allOf = allOf;
21305
+ json3.allOf = allOf;
21306
21306
  ctx.intersections.push(allOf);
21307
21307
  };
21308
21308
  var tupleProcessor = (schema, ctx, _json, params) => {
21309
- const json2 = _json;
21309
+ const json3 = _json;
21310
21310
  const def = schema._zod.def;
21311
- json2.type = "array";
21311
+ json3.type = "array";
21312
21312
  const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
21313
21313
  const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
21314
21314
  const prefixItems = def.items.map((x, i) => processSchema(x, ctx, {
@@ -21330,70 +21330,70 @@ var tupleProcessor = (schema, ctx, _json, params) => {
21330
21330
  const maxItems = def.items.length;
21331
21331
  const isClosed = !def.rest;
21332
21332
  if (ctx.target === "draft-2020-12") {
21333
- json2.prefixItems = prefixItems;
21333
+ json3.prefixItems = prefixItems;
21334
21334
  if (isClosed) {
21335
- json2.items = false;
21335
+ json3.items = false;
21336
21336
  } else if (rest) {
21337
- json2.items = rest;
21337
+ json3.items = rest;
21338
21338
  }
21339
21339
  if (minItems > 0)
21340
- json2.minItems = minItems;
21340
+ json3.minItems = minItems;
21341
21341
  if (isClosed)
21342
- json2.maxItems = maxItems;
21342
+ json3.maxItems = maxItems;
21343
21343
  } else if (ctx.target === "openapi-3.0") {
21344
- json2.items = {
21344
+ json3.items = {
21345
21345
  anyOf: prefixItems
21346
21346
  };
21347
21347
  if (rest) {
21348
- json2.items.anyOf.push(rest);
21348
+ json3.items.anyOf.push(rest);
21349
21349
  }
21350
21350
  if (minItems > 0)
21351
- json2.minItems = minItems;
21351
+ json3.minItems = minItems;
21352
21352
  if (isClosed)
21353
- json2.maxItems = maxItems;
21353
+ json3.maxItems = maxItems;
21354
21354
  } else {
21355
- json2.items = prefixItems;
21355
+ json3.items = prefixItems;
21356
21356
  if (isClosed) {
21357
- json2.additionalItems = false;
21357
+ json3.additionalItems = false;
21358
21358
  } else if (rest) {
21359
- json2.additionalItems = rest;
21359
+ json3.additionalItems = rest;
21360
21360
  }
21361
21361
  if (minItems > 0)
21362
- json2.minItems = minItems;
21362
+ json3.minItems = minItems;
21363
21363
  if (isClosed)
21364
- json2.maxItems = maxItems;
21364
+ json3.maxItems = maxItems;
21365
21365
  }
21366
21366
  const { minimum, maximum } = aggregateChecks(schema);
21367
21367
  if (typeof minimum === "number")
21368
- json2.minItems = minimum;
21368
+ json3.minItems = minimum;
21369
21369
  if (typeof maximum === "number")
21370
- json2.maxItems = maximum;
21370
+ json3.maxItems = maximum;
21371
21371
  };
21372
- function stringifyKeyNames(bySchema, json2, visited) {
21373
- if (json2.$ref) {
21374
- if (visited.has(json2))
21375
- return json2;
21376
- visited.add(json2);
21377
- const def = bySchema.get(json2)?.def;
21372
+ function stringifyKeyNames(bySchema, json3, visited) {
21373
+ if (json3.$ref) {
21374
+ if (visited.has(json3))
21375
+ return json3;
21376
+ visited.add(json3);
21377
+ const def = bySchema.get(json3)?.def;
21378
21378
  if (!def)
21379
- return json2;
21379
+ return json3;
21380
21380
  const inlined = stringifyKeyNames(bySchema, def, visited);
21381
- return inlined === def ? json2 : inlined;
21381
+ return inlined === def ? json3 : inlined;
21382
21382
  }
21383
21383
  for (const keyword of ["anyOf", "oneOf"]) {
21384
- const branches = json2[keyword];
21384
+ const branches = json3[keyword];
21385
21385
  if (!Array.isArray(branches))
21386
21386
  continue;
21387
21387
  const mapped = branches.map((branch) => stringifyKeyNames(bySchema, branch, visited));
21388
21388
  if (mapped.some((branch, i) => branch !== branches[i]))
21389
- json2 = { ...json2, [keyword]: mapped };
21389
+ json3 = { ...json3, [keyword]: mapped };
21390
21390
  }
21391
- const types = Array.isArray(json2.type) ? json2.type : [json2.type];
21391
+ const types = Array.isArray(json3.type) ? json3.type : [json3.type];
21392
21392
  const numericType = !types.includes("string") && types.some((t3) => t3 === "number" || t3 === "integer");
21393
- const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
21393
+ const values = json3.enum ?? (json3.const !== void 0 ? [json3.const] : void 0);
21394
21394
  if (!numericType && !values?.some((v) => typeof v === "number"))
21395
- return json2;
21396
- const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json2;
21395
+ return json3;
21396
+ const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json3;
21397
21397
  if (rest.enum)
21398
21398
  rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
21399
21399
  else if (typeof rest.const === "number")
@@ -21433,9 +21433,9 @@ function rewriteKeyNames(ctx) {
21433
21433
  }
21434
21434
  }
21435
21435
  var recordProcessor = (schema, ctx, _json, params) => {
21436
- const json2 = _json;
21436
+ const json3 = _json;
21437
21437
  const def = schema._zod.def;
21438
- json2.type = "object";
21438
+ json3.type = "object";
21439
21439
  const keyType = def.keyType;
21440
21440
  const patterns = aggregateChecks(keyType).patterns;
21441
21441
  if (def.mode === "loose" && patterns && patterns.size > 0) {
@@ -21443,13 +21443,13 @@ var recordProcessor = (schema, ctx, _json, params) => {
21443
21443
  ...params,
21444
21444
  path: [...params.path, "patternProperties", "*"]
21445
21445
  });
21446
- json2.patternProperties = {};
21446
+ json3.patternProperties = {};
21447
21447
  for (const pattern of patterns) {
21448
- assignProp(json2.patternProperties, exactPattern(pattern).source, valueSchema);
21448
+ assignProp(json3.patternProperties, exactPattern(pattern).source, valueSchema);
21449
21449
  }
21450
21450
  } else {
21451
21451
  if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
21452
- json2.propertyNames = processSchema(def.keyType, ctx, {
21452
+ json3.propertyNames = processSchema(def.keyType, ctx, {
21453
21453
  ...params,
21454
21454
  path: [...params.path, "propertyNames"]
21455
21455
  });
@@ -21461,7 +21461,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
21461
21461
  }
21462
21462
  pending.push(schema);
21463
21463
  }
21464
- json2.additionalProperties = processSchema(def.valueType, ctx, {
21464
+ json3.additionalProperties = processSchema(def.valueType, ctx, {
21465
21465
  ...params,
21466
21466
  path: [...params.path, "additionalProperties"]
21467
21467
  });
@@ -21471,19 +21471,19 @@ var recordProcessor = (schema, ctx, _json, params) => {
21471
21471
  if (keyValues && !def.partial && !omittableOnInput) {
21472
21472
  const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
21473
21473
  if (validKeyValues.length > 0) {
21474
- json2.required = validKeyValues.map(String);
21474
+ json3.required = validKeyValues.map(String);
21475
21475
  }
21476
21476
  }
21477
21477
  };
21478
- var nullableProcessor = (schema, ctx, json2, params) => {
21478
+ var nullableProcessor = (schema, ctx, json3, params) => {
21479
21479
  const def = schema._zod.def;
21480
21480
  const inner = processSchema(def.innerType, ctx, params);
21481
21481
  const seen = ctx.seen.get(schema);
21482
21482
  if (ctx.target === "openapi-3.0") {
21483
21483
  seen.ref = def.innerType;
21484
- json2.nullable = true;
21484
+ json3.nullable = true;
21485
21485
  } else {
21486
- json2.anyOf = [inner, { type: "null" }];
21486
+ json3.anyOf = [inner, { type: "null" }];
21487
21487
  }
21488
21488
  };
21489
21489
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
@@ -21493,7 +21493,7 @@ var nonoptionalProcessor = (schema, ctx, _json, params) => {
21493
21493
  seen.ref = def.innerType;
21494
21494
  };
21495
21495
  var UNREPRESENTABLE_DEFAULT = /* @__PURE__ */ Symbol();
21496
- function serializeDefaultValue(value, schema, ctx, json2, params) {
21496
+ function serializeDefaultValue(value, schema, ctx, json3, params) {
21497
21497
  let unrepresentable = false;
21498
21498
  const serialized = JSON.stringify(value, (_, val) => {
21499
21499
  if (typeof val !== "bigint")
@@ -21503,30 +21503,30 @@ function serializeDefaultValue(value, schema, ctx, json2, params) {
21503
21503
  });
21504
21504
  if (!unrepresentable)
21505
21505
  return JSON.parse(serialized);
21506
- handleUnrepresentable(schema, ctx, json2, params, "BigInt defaults cannot be represented in JSON Schema");
21506
+ handleUnrepresentable(schema, ctx, json3, params, "BigInt defaults cannot be represented in JSON Schema");
21507
21507
  return UNREPRESENTABLE_DEFAULT;
21508
21508
  }
21509
- var defaultProcessor = (schema, ctx, json2, params) => {
21509
+ var defaultProcessor = (schema, ctx, json3, params) => {
21510
21510
  const def = schema._zod.def;
21511
21511
  processSchema(def.innerType, ctx, params);
21512
21512
  const seen = ctx.seen.get(schema);
21513
21513
  seen.ref = def.innerType;
21514
- const value = serializeDefaultValue(def.defaultValue, schema, ctx, json2, params);
21514
+ const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
21515
21515
  if (value !== UNREPRESENTABLE_DEFAULT)
21516
- json2.default = value;
21516
+ json3.default = value;
21517
21517
  };
21518
- var prefaultProcessor = (schema, ctx, json2, params) => {
21518
+ var prefaultProcessor = (schema, ctx, json3, params) => {
21519
21519
  const def = schema._zod.def;
21520
21520
  processSchema(def.innerType, ctx, params);
21521
21521
  const seen = ctx.seen.get(schema);
21522
21522
  seen.ref = def.innerType;
21523
21523
  if (ctx.io !== "input")
21524
21524
  return;
21525
- const value = serializeDefaultValue(def.defaultValue, schema, ctx, json2, params);
21525
+ const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
21526
21526
  if (value !== UNREPRESENTABLE_DEFAULT)
21527
- json2._prefault = value;
21527
+ json3._prefault = value;
21528
21528
  };
21529
- var catchProcessor = (schema, ctx, json2, params) => {
21529
+ var catchProcessor = (schema, ctx, json3, params) => {
21530
21530
  const def = schema._zod.def;
21531
21531
  processSchema(def.innerType, ctx, params);
21532
21532
  const seen = ctx.seen.get(schema);
@@ -21535,10 +21535,10 @@ var catchProcessor = (schema, ctx, json2, params) => {
21535
21535
  try {
21536
21536
  catchValue = def.catchValue(void 0);
21537
21537
  } catch {
21538
- handleUnrepresentable(schema, ctx, json2, params, "Dynamic catch values are not supported in JSON Schema");
21538
+ handleUnrepresentable(schema, ctx, json3, params, "Dynamic catch values are not supported in JSON Schema");
21539
21539
  return;
21540
21540
  }
21541
- json2.default = catchValue;
21541
+ json3.default = catchValue;
21542
21542
  };
21543
21543
  var pipeProcessor = (schema, ctx, _json, params) => {
21544
21544
  const def = schema._zod.def;
@@ -21548,12 +21548,12 @@ var pipeProcessor = (schema, ctx, _json, params) => {
21548
21548
  const seen = ctx.seen.get(schema);
21549
21549
  seen.ref = innerType;
21550
21550
  };
21551
- var readonlyProcessor = (schema, ctx, json2, params) => {
21551
+ var readonlyProcessor = (schema, ctx, json3, params) => {
21552
21552
  const def = schema._zod.def;
21553
21553
  processSchema(def.innerType, ctx, params);
21554
21554
  const seen = ctx.seen.get(schema);
21555
21555
  seen.ref = def.innerType;
21556
- json2.readOnly = true;
21556
+ json3.readOnly = true;
21557
21557
  };
21558
21558
  var promiseProcessor = (schema, ctx, _json, params) => {
21559
21559
  const def = schema._zod.def;
@@ -22195,7 +22195,7 @@ var _ZodString = /* @__PURE__ */ $constructor(
22195
22195
  (inst, def) => {
22196
22196
  $ZodString.init(inst, def);
22197
22197
  ZodType.init(inst, def);
22198
- inst._zod.processJSONSchema = (ctx, json2, params) => stringProcessor(inst, ctx, json2, params);
22198
+ inst._zod.processJSONSchema = (ctx, json3, params) => stringProcessor(inst, ctx, json3, params);
22199
22199
  },
22200
22200
  /* @__PURE__ */ util_exports.derived({
22201
22201
  format: (inst) => aggregateChecks(inst).format ?? null,
@@ -22554,7 +22554,7 @@ var ZodNumber = /* @__PURE__ */ $constructor(
22554
22554
  (inst, def) => {
22555
22555
  $ZodNumber.init(inst, def);
22556
22556
  ZodType.init(inst, def);
22557
- inst._zod.processJSONSchema = (ctx, json2, params) => numberProcessor(inst, ctx, json2, params);
22557
+ inst._zod.processJSONSchema = (ctx, json3, params) => numberProcessor(inst, ctx, json3, params);
22558
22558
  inst.isFinite = true;
22559
22559
  },
22560
22560
  /* @__PURE__ */ util_exports.derived({
@@ -22644,7 +22644,7 @@ function uint32(params) {
22644
22644
  var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
22645
22645
  $ZodBoolean.init(inst, def);
22646
22646
  ZodType.init(inst, def);
22647
- inst._zod.processJSONSchema = (ctx, json2, params) => booleanProcessor(inst, ctx, json2, params);
22647
+ inst._zod.processJSONSchema = (ctx, json3, params) => booleanProcessor(inst, ctx, json3, params);
22648
22648
  });
22649
22649
  function boolean2(params) {
22650
22650
  return _boolean(ZodBoolean, params);
@@ -22654,7 +22654,7 @@ var ZodBigInt = /* @__PURE__ */ $constructor(
22654
22654
  (inst, def) => {
22655
22655
  $ZodBigInt.init(inst, def);
22656
22656
  ZodType.init(inst, def);
22657
- inst._zod.processJSONSchema = (ctx, json2, params) => bigintProcessor(inst, ctx, json2, params);
22657
+ inst._zod.processJSONSchema = (ctx, json3, params) => bigintProcessor(inst, ctx, json3, params);
22658
22658
  },
22659
22659
  /* @__PURE__ */ util_exports.derived({
22660
22660
  minValue: (inst) => aggregateChecks(inst).minimum ?? null,
@@ -22712,7 +22712,7 @@ function uint64(params) {
22712
22712
  var ZodSymbol = /* @__PURE__ */ $constructor("ZodSymbol", (inst, def) => {
22713
22713
  $ZodSymbol.init(inst, def);
22714
22714
  ZodType.init(inst, def);
22715
- inst._zod.processJSONSchema = (ctx, json2, params) => symbolProcessor(inst, ctx, json2, params);
22715
+ inst._zod.processJSONSchema = (ctx, json3, params) => symbolProcessor(inst, ctx, json3, params);
22716
22716
  });
22717
22717
  function symbol(params) {
22718
22718
  return _symbol(ZodSymbol, params);
@@ -22720,7 +22720,7 @@ function symbol(params) {
22720
22720
  var ZodUndefined = /* @__PURE__ */ $constructor("ZodUndefined", (inst, def) => {
22721
22721
  $ZodUndefined.init(inst, def);
22722
22722
  ZodType.init(inst, def);
22723
- inst._zod.processJSONSchema = (ctx, json2, params) => undefinedProcessor(inst, ctx, json2, params);
22723
+ inst._zod.processJSONSchema = (ctx, json3, params) => undefinedProcessor(inst, ctx, json3, params);
22724
22724
  });
22725
22725
  function _undefined3(params) {
22726
22726
  return _undefined2(ZodUndefined, params);
@@ -22728,7 +22728,7 @@ function _undefined3(params) {
22728
22728
  var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
22729
22729
  $ZodNull.init(inst, def);
22730
22730
  ZodType.init(inst, def);
22731
- inst._zod.processJSONSchema = (ctx, json2, params) => nullProcessor(inst, ctx, json2, params);
22731
+ inst._zod.processJSONSchema = (ctx, json3, params) => nullProcessor(inst, ctx, json3, params);
22732
22732
  });
22733
22733
  function _null3(params) {
22734
22734
  return _null2(ZodNull, params);
@@ -22736,7 +22736,7 @@ function _null3(params) {
22736
22736
  var ZodAny = /* @__PURE__ */ $constructor("ZodAny", (inst, def) => {
22737
22737
  $ZodAny.init(inst, def);
22738
22738
  ZodType.init(inst, def);
22739
- inst._zod.processJSONSchema = (ctx, json2, params) => anyProcessor(inst, ctx, json2, params);
22739
+ inst._zod.processJSONSchema = (ctx, json3, params) => anyProcessor(inst, ctx, json3, params);
22740
22740
  });
22741
22741
  function any() {
22742
22742
  return _any(ZodAny);
@@ -22744,7 +22744,7 @@ function any() {
22744
22744
  var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
22745
22745
  $ZodUnknown.init(inst, def);
22746
22746
  ZodType.init(inst, def);
22747
- inst._zod.processJSONSchema = (ctx, json2, params) => unknownProcessor(inst, ctx, json2, params);
22747
+ inst._zod.processJSONSchema = (ctx, json3, params) => unknownProcessor(inst, ctx, json3, params);
22748
22748
  });
22749
22749
  function unknown() {
22750
22750
  return _unknown(ZodUnknown);
@@ -22752,7 +22752,7 @@ function unknown() {
22752
22752
  var ZodNever = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
22753
22753
  $ZodNever.init(inst, def);
22754
22754
  ZodType.init(inst, def);
22755
- inst._zod.processJSONSchema = (ctx, json2, params) => neverProcessor(inst, ctx, json2, params);
22755
+ inst._zod.processJSONSchema = (ctx, json3, params) => neverProcessor(inst, ctx, json3, params);
22756
22756
  });
22757
22757
  function never(params) {
22758
22758
  return _never(ZodNever, params);
@@ -22760,7 +22760,7 @@ function never(params) {
22760
22760
  var ZodVoid = /* @__PURE__ */ $constructor("ZodVoid", (inst, def) => {
22761
22761
  $ZodVoid.init(inst, def);
22762
22762
  ZodType.init(inst, def);
22763
- inst._zod.processJSONSchema = (ctx, json2, params) => voidProcessor(inst, ctx, json2, params);
22763
+ inst._zod.processJSONSchema = (ctx, json3, params) => voidProcessor(inst, ctx, json3, params);
22764
22764
  });
22765
22765
  function _void2(params) {
22766
22766
  return _void(ZodVoid, params);
@@ -22770,7 +22770,7 @@ var ZodDate = /* @__PURE__ */ $constructor(
22770
22770
  (inst, def) => {
22771
22771
  $ZodDate.init(inst, def);
22772
22772
  ZodType.init(inst, def);
22773
- inst._zod.processJSONSchema = (ctx, json2, params) => dateProcessor(inst, ctx, json2, params);
22773
+ inst._zod.processJSONSchema = (ctx, json3, params) => dateProcessor(inst, ctx, json3, params);
22774
22774
  inst.min = (value, params) => inst.check(_gte(value, params));
22775
22775
  inst.max = (value, params) => inst.check(_lte(value, params));
22776
22776
  },
@@ -22792,7 +22792,7 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
22792
22792
  _ensureDefaultMemoizer();
22793
22793
  $ZodArray.init(inst, def);
22794
22794
  ZodType.init(inst, def);
22795
- inst._zod.processJSONSchema = (ctx, json2, params) => arrayProcessor(inst, ctx, json2, params);
22795
+ inst._zod.processJSONSchema = (ctx, json3, params) => arrayProcessor(inst, ctx, json3, params);
22796
22796
  inst.element = def.element;
22797
22797
  }, {
22798
22798
  min(n, params) {
@@ -22822,7 +22822,7 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
22822
22822
  _ensureDefaultMemoizer();
22823
22823
  $ZodObjectJIT.init(inst, def);
22824
22824
  ZodType.init(inst, def);
22825
- inst._zod.processJSONSchema = (ctx, json2, params) => objectProcessor(inst, ctx, json2, params);
22825
+ inst._zod.processJSONSchema = (ctx, json3, params) => objectProcessor(inst, ctx, json3, params);
22826
22826
  util_exports.installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
22827
22827
  }, {
22828
22828
  keyof() {
@@ -22895,7 +22895,7 @@ function looseObject(shape, params) {
22895
22895
  var ZodUnion = /* @__PURE__ */ $constructor("ZodUnion", (inst, def) => {
22896
22896
  $ZodUnion.init(inst, def);
22897
22897
  ZodType.init(inst, def);
22898
- inst._zod.processJSONSchema = (ctx, json2, params) => unionProcessor(inst, ctx, json2, params);
22898
+ inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
22899
22899
  inst.options = def.options;
22900
22900
  });
22901
22901
  function union(options, params) {
@@ -22908,7 +22908,7 @@ function union(options, params) {
22908
22908
  var ZodXor = /* @__PURE__ */ $constructor("ZodXor", (inst, def) => {
22909
22909
  ZodUnion.init(inst, def);
22910
22910
  $ZodXor.init(inst, def);
22911
- inst._zod.processJSONSchema = (ctx, json2, params) => unionProcessor(inst, ctx, json2, params);
22911
+ inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
22912
22912
  inst.options = def.options;
22913
22913
  });
22914
22914
  function xor(options, params) {
@@ -22934,7 +22934,7 @@ function discriminatedUnion(discriminator, options, params) {
22934
22934
  var ZodIntersection = /* @__PURE__ */ $constructor("ZodIntersection", (inst, def) => {
22935
22935
  $ZodIntersection.init(inst, def);
22936
22936
  ZodType.init(inst, def);
22937
- inst._zod.processJSONSchema = (ctx, json2, params) => intersectionProcessor(inst, ctx, json2, params);
22937
+ inst._zod.processJSONSchema = (ctx, json3, params) => intersectionProcessor(inst, ctx, json3, params);
22938
22938
  });
22939
22939
  function intersection(left, right) {
22940
22940
  return new ZodIntersection({
@@ -22947,7 +22947,7 @@ var ZodTuple = /* @__PURE__ */ $constructor("ZodTuple", (inst, def) => {
22947
22947
  _ensureDefaultMemoizer();
22948
22948
  $ZodTuple.init(inst, def);
22949
22949
  ZodType.init(inst, def);
22950
- inst._zod.processJSONSchema = (ctx, json2, params) => tupleProcessor(inst, ctx, json2, params);
22950
+ inst._zod.processJSONSchema = (ctx, json3, params) => tupleProcessor(inst, ctx, json3, params);
22951
22951
  }, {
22952
22952
  rest(rest) {
22953
22953
  return this.clone({
@@ -22980,7 +22980,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
22980
22980
  _ensureDefaultMemoizer();
22981
22981
  $ZodRecord.init(inst, def);
22982
22982
  ZodType.init(inst, def);
22983
- inst._zod.processJSONSchema = (ctx, json2, params) => recordProcessor(inst, ctx, json2, params);
22983
+ inst._zod.processJSONSchema = (ctx, json3, params) => recordProcessor(inst, ctx, json3, params);
22984
22984
  inst.keyType = def.keyType;
22985
22985
  inst.valueType = def.valueType;
22986
22986
  });
@@ -23022,7 +23022,7 @@ var ZodMap = /* @__PURE__ */ $constructor("ZodMap", (inst, def) => {
23022
23022
  _ensureDefaultMemoizer();
23023
23023
  $ZodMap.init(inst, def);
23024
23024
  ZodType.init(inst, def);
23025
- inst._zod.processJSONSchema = (ctx, json2, params) => mapProcessor(inst, ctx, json2, params);
23025
+ inst._zod.processJSONSchema = (ctx, json3, params) => mapProcessor(inst, ctx, json3, params);
23026
23026
  inst.keyType = def.keyType;
23027
23027
  inst.valueType = def.valueType;
23028
23028
  inst.min = (...args) => inst.check(_minSize(...args));
@@ -23042,7 +23042,7 @@ var ZodSet = /* @__PURE__ */ $constructor("ZodSet", (inst, def) => {
23042
23042
  _ensureDefaultMemoizer();
23043
23043
  $ZodSet.init(inst, def);
23044
23044
  ZodType.init(inst, def);
23045
- inst._zod.processJSONSchema = (ctx, json2, params) => setProcessor(inst, ctx, json2, params);
23045
+ inst._zod.processJSONSchema = (ctx, json3, params) => setProcessor(inst, ctx, json3, params);
23046
23046
  inst.min = (...args) => inst.check(_minSize(...args));
23047
23047
  inst.nonempty = (params) => inst.check(_minSize(1, params));
23048
23048
  inst.max = (...args) => inst.check(_maxSize(...args));
@@ -23058,7 +23058,7 @@ function set(valueType, params) {
23058
23058
  var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
23059
23059
  $ZodEnum.init(inst, def);
23060
23060
  ZodType.init(inst, def);
23061
- inst._zod.processJSONSchema = (ctx, json2, params) => enumProcessor(inst, ctx, json2, params);
23061
+ inst._zod.processJSONSchema = (ctx, json3, params) => enumProcessor(inst, ctx, json3, params);
23062
23062
  inst.enum = def.entries;
23063
23063
  inst.options = [...inst._zod.values];
23064
23064
  const keys2 = new Set(Object.keys(def.entries));
@@ -23111,7 +23111,7 @@ function nativeEnum(entries, params) {
23111
23111
  var ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
23112
23112
  $ZodLiteral.init(inst, def);
23113
23113
  ZodType.init(inst, def);
23114
- inst._zod.processJSONSchema = (ctx, json2, params) => literalProcessor(inst, ctx, json2, params);
23114
+ inst._zod.processJSONSchema = (ctx, json3, params) => literalProcessor(inst, ctx, json3, params);
23115
23115
  inst.values = new Set(def.values);
23116
23116
  Object.defineProperty(inst, "value", {
23117
23117
  get() {
@@ -23132,7 +23132,7 @@ function literal(value, params) {
23132
23132
  var ZodFile = /* @__PURE__ */ $constructor("ZodFile", (inst, def) => {
23133
23133
  $ZodFile.init(inst, def);
23134
23134
  ZodType.init(inst, def);
23135
- inst._zod.processJSONSchema = (ctx, json2, params) => fileProcessor(inst, ctx, json2, params);
23135
+ inst._zod.processJSONSchema = (ctx, json3, params) => fileProcessor(inst, ctx, json3, params);
23136
23136
  inst.min = (size, params) => inst.check(_minSize(size, params));
23137
23137
  inst.max = (size, params) => inst.check(_maxSize(size, params));
23138
23138
  inst.mime = (types, params) => inst.check(_mime(Array.isArray(types) ? types : [types], params));
@@ -23144,7 +23144,7 @@ var ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
23144
23144
  _ensureDefaultMemoizer();
23145
23145
  $ZodTransform.init(inst, def);
23146
23146
  ZodType.init(inst, def);
23147
- inst._zod.processJSONSchema = (ctx, json2, params) => transformProcessor(inst, ctx, json2, params);
23147
+ inst._zod.processJSONSchema = (ctx, json3, params) => transformProcessor(inst, ctx, json3, params);
23148
23148
  inst._zod.parse = (payload, _ctx) => {
23149
23149
  if (_ctx.direction === "backward") {
23150
23150
  throw new $ZodEncodeError(inst.constructor.name);
@@ -23183,7 +23183,7 @@ function transform(fn) {
23183
23183
  var ZodOptional = /* @__PURE__ */ $constructor("ZodOptional", (inst, def) => {
23184
23184
  $ZodOptional.init(inst, def);
23185
23185
  ZodType.init(inst, def);
23186
- inst._zod.processJSONSchema = (ctx, json2, params) => optionalProcessor(inst, ctx, json2, params);
23186
+ inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
23187
23187
  inst.unwrap = () => inst._zod.def.innerType;
23188
23188
  });
23189
23189
  function optional(innerType) {
@@ -23195,7 +23195,7 @@ function optional(innerType) {
23195
23195
  var ZodExactOptional = /* @__PURE__ */ $constructor("ZodExactOptional", (inst, def) => {
23196
23196
  $ZodExactOptional.init(inst, def);
23197
23197
  ZodType.init(inst, def);
23198
- inst._zod.processJSONSchema = (ctx, json2, params) => optionalProcessor(inst, ctx, json2, params);
23198
+ inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
23199
23199
  inst.unwrap = () => inst._zod.def.innerType;
23200
23200
  });
23201
23201
  function exactOptional(innerType) {
@@ -23207,7 +23207,7 @@ function exactOptional(innerType) {
23207
23207
  var ZodNullable = /* @__PURE__ */ $constructor("ZodNullable", (inst, def) => {
23208
23208
  $ZodNullable.init(inst, def);
23209
23209
  ZodType.init(inst, def);
23210
- inst._zod.processJSONSchema = (ctx, json2, params) => nullableProcessor(inst, ctx, json2, params);
23210
+ inst._zod.processJSONSchema = (ctx, json3, params) => nullableProcessor(inst, ctx, json3, params);
23211
23211
  inst.unwrap = () => inst._zod.def.innerType;
23212
23212
  });
23213
23213
  function nullable(innerType) {
@@ -23222,7 +23222,7 @@ function nullish2(innerType) {
23222
23222
  var ZodDefault = /* @__PURE__ */ $constructor("ZodDefault", (inst, def) => {
23223
23223
  $ZodDefault.init(inst, def);
23224
23224
  ZodType.init(inst, def);
23225
- inst._zod.processJSONSchema = (ctx, json2, params) => defaultProcessor(inst, ctx, json2, params);
23225
+ inst._zod.processJSONSchema = (ctx, json3, params) => defaultProcessor(inst, ctx, json3, params);
23226
23226
  inst.unwrap = () => inst._zod.def.innerType;
23227
23227
  inst.removeDefault = inst.unwrap;
23228
23228
  });
@@ -23238,7 +23238,7 @@ function _default2(innerType, defaultValue) {
23238
23238
  var ZodPrefault = /* @__PURE__ */ $constructor("ZodPrefault", (inst, def) => {
23239
23239
  $ZodPrefault.init(inst, def);
23240
23240
  ZodType.init(inst, def);
23241
- inst._zod.processJSONSchema = (ctx, json2, params) => prefaultProcessor(inst, ctx, json2, params);
23241
+ inst._zod.processJSONSchema = (ctx, json3, params) => prefaultProcessor(inst, ctx, json3, params);
23242
23242
  inst.unwrap = () => inst._zod.def.innerType;
23243
23243
  });
23244
23244
  function prefault(innerType, defaultValue) {
@@ -23253,7 +23253,7 @@ function prefault(innerType, defaultValue) {
23253
23253
  var ZodNonOptional = /* @__PURE__ */ $constructor("ZodNonOptional", (inst, def) => {
23254
23254
  $ZodNonOptional.init(inst, def);
23255
23255
  ZodType.init(inst, def);
23256
- inst._zod.processJSONSchema = (ctx, json2, params) => nonoptionalProcessor(inst, ctx, json2, params);
23256
+ inst._zod.processJSONSchema = (ctx, json3, params) => nonoptionalProcessor(inst, ctx, json3, params);
23257
23257
  inst.unwrap = () => inst._zod.def.innerType;
23258
23258
  });
23259
23259
  function nonoptional(innerType, params) {
@@ -23266,7 +23266,7 @@ function nonoptional(innerType, params) {
23266
23266
  var ZodSuccess = /* @__PURE__ */ $constructor("ZodSuccess", (inst, def) => {
23267
23267
  $ZodSuccess.init(inst, def);
23268
23268
  ZodType.init(inst, def);
23269
- inst._zod.processJSONSchema = (ctx, json2, params) => successProcessor(inst, ctx, json2, params);
23269
+ inst._zod.processJSONSchema = (ctx, json3, params) => successProcessor(inst, ctx, json3, params);
23270
23270
  inst.unwrap = () => inst._zod.def.innerType;
23271
23271
  });
23272
23272
  function success(innerType) {
@@ -23278,7 +23278,7 @@ function success(innerType) {
23278
23278
  var ZodCatch = /* @__PURE__ */ $constructor("ZodCatch", (inst, def) => {
23279
23279
  $ZodCatch.init(inst, def);
23280
23280
  ZodType.init(inst, def);
23281
- inst._zod.processJSONSchema = (ctx, json2, params) => catchProcessor(inst, ctx, json2, params);
23281
+ inst._zod.processJSONSchema = (ctx, json3, params) => catchProcessor(inst, ctx, json3, params);
23282
23282
  inst.unwrap = () => inst._zod.def.innerType;
23283
23283
  inst.removeCatch = inst.unwrap;
23284
23284
  });
@@ -23292,7 +23292,7 @@ function _catch2(innerType, catchValue) {
23292
23292
  var ZodNaN = /* @__PURE__ */ $constructor("ZodNaN", (inst, def) => {
23293
23293
  $ZodNaN.init(inst, def);
23294
23294
  ZodType.init(inst, def);
23295
- inst._zod.processJSONSchema = (ctx, json2, params) => nanProcessor(inst, ctx, json2, params);
23295
+ inst._zod.processJSONSchema = (ctx, json3, params) => nanProcessor(inst, ctx, json3, params);
23296
23296
  });
23297
23297
  function nan(params) {
23298
23298
  return _nan(ZodNaN, params);
@@ -23300,7 +23300,7 @@ function nan(params) {
23300
23300
  var ZodPipe = /* @__PURE__ */ $constructor("ZodPipe", (inst, def) => {
23301
23301
  $ZodPipe.init(inst, def);
23302
23302
  ZodType.init(inst, def);
23303
- inst._zod.processJSONSchema = (ctx, json2, params) => pipeProcessor(inst, ctx, json2, params);
23303
+ inst._zod.processJSONSchema = (ctx, json3, params) => pipeProcessor(inst, ctx, json3, params);
23304
23304
  inst.in = def.in;
23305
23305
  inst.out = def.out;
23306
23306
  });
@@ -23342,7 +23342,7 @@ var ZodPreprocess = /* @__PURE__ */ $constructor("ZodPreprocess", (inst, def) =>
23342
23342
  var ZodReadonly = /* @__PURE__ */ $constructor("ZodReadonly", (inst, def) => {
23343
23343
  $ZodReadonly.init(inst, def);
23344
23344
  ZodType.init(inst, def);
23345
- inst._zod.processJSONSchema = (ctx, json2, params) => readonlyProcessor(inst, ctx, json2, params);
23345
+ inst._zod.processJSONSchema = (ctx, json3, params) => readonlyProcessor(inst, ctx, json3, params);
23346
23346
  inst.unwrap = () => inst._zod.def.innerType;
23347
23347
  });
23348
23348
  function readonly(innerType) {
@@ -23354,7 +23354,7 @@ function readonly(innerType) {
23354
23354
  var ZodTemplateLiteral = /* @__PURE__ */ $constructor("ZodTemplateLiteral", (inst, def) => {
23355
23355
  $ZodTemplateLiteral.init(inst, def);
23356
23356
  ZodType.init(inst, def);
23357
- inst._zod.processJSONSchema = (ctx, json2, params) => templateLiteralProcessor(inst, ctx, json2, params);
23357
+ inst._zod.processJSONSchema = (ctx, json3, params) => templateLiteralProcessor(inst, ctx, json3, params);
23358
23358
  });
23359
23359
  function templateLiteral(parts, params) {
23360
23360
  return new ZodTemplateLiteral({
@@ -23366,7 +23366,7 @@ function templateLiteral(parts, params) {
23366
23366
  var ZodLazy = /* @__PURE__ */ $constructor("ZodLazy", (inst, def) => {
23367
23367
  $ZodLazy.init(inst, def);
23368
23368
  ZodType.init(inst, def);
23369
- inst._zod.processJSONSchema = (ctx, json2, params) => lazyProcessor(inst, ctx, json2, params);
23369
+ inst._zod.processJSONSchema = (ctx, json3, params) => lazyProcessor(inst, ctx, json3, params);
23370
23370
  inst.unwrap = () => inst._zod.def.getter();
23371
23371
  });
23372
23372
  function lazy(getter) {
@@ -23378,7 +23378,7 @@ function lazy(getter) {
23378
23378
  var ZodPromise = /* @__PURE__ */ $constructor("ZodPromise", (inst, def) => {
23379
23379
  $ZodPromise.init(inst, def);
23380
23380
  ZodType.init(inst, def);
23381
- inst._zod.processJSONSchema = (ctx, json2, params) => promiseProcessor(inst, ctx, json2, params);
23381
+ inst._zod.processJSONSchema = (ctx, json3, params) => promiseProcessor(inst, ctx, json3, params);
23382
23382
  inst.unwrap = () => inst._zod.def.innerType;
23383
23383
  });
23384
23384
  function promise(innerType) {
@@ -23390,7 +23390,7 @@ function promise(innerType) {
23390
23390
  var ZodFunction = /* @__PURE__ */ $constructor("ZodFunction", (inst, def) => {
23391
23391
  $ZodFunction.init(inst, def);
23392
23392
  ZodType.init(inst, def);
23393
- inst._zod.processJSONSchema = (ctx, json2, params) => functionProcessor(inst, ctx, json2, params);
23393
+ inst._zod.processJSONSchema = (ctx, json3, params) => functionProcessor(inst, ctx, json3, params);
23394
23394
  });
23395
23395
  function _function(params) {
23396
23396
  return new ZodFunction({
@@ -23402,7 +23402,7 @@ function _function(params) {
23402
23402
  var ZodCustom = /* @__PURE__ */ $constructor("ZodCustom", (inst, def) => {
23403
23403
  $ZodCustom.init(inst, def);
23404
23404
  ZodType.init(inst, def);
23405
- inst._zod.processJSONSchema = (ctx, json2, params) => customProcessor(inst, ctx, json2, params);
23405
+ inst._zod.processJSONSchema = (ctx, json3, params) => customProcessor(inst, ctx, json3, params);
23406
23406
  });
23407
23407
  function check(fn) {
23408
23408
  const ch = new $ZodCheck({
@@ -23793,20 +23793,20 @@ function checkArrayGuards(arraySchema, guards) {
23793
23793
  if (guards.containsSchema) {
23794
23794
  const minContains = guards.minContains ?? 1;
23795
23795
  const ceiling = guards.maxContains !== void 0 ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
23796
- let matches = 0;
23796
+ let matches2 = 0;
23797
23797
  for (const item of items2) {
23798
- if (guards.containsSchema.safeParse(item).success && ++matches >= ceiling)
23798
+ if (guards.containsSchema.safeParse(item).success && ++matches2 >= ceiling)
23799
23799
  break;
23800
23800
  }
23801
- if (matches < minContains) {
23801
+ if (matches2 < minContains) {
23802
23802
  payload.issues.push({
23803
23803
  code: "custom",
23804
- message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches}`,
23804
+ message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches2}`,
23805
23805
  input: items2,
23806
23806
  continue: true
23807
23807
  });
23808
23808
  }
23809
- if (guards.maxContains !== void 0 && matches > guards.maxContains) {
23809
+ if (guards.maxContains !== void 0 && matches2 > guards.maxContains) {
23810
23810
  payload.issues.push({
23811
23811
  code: "custom",
23812
23812
  message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
@@ -24631,7 +24631,7 @@ var projectInitV5 = external_exports.discriminatedUnion("ok", [
24631
24631
  external_exports.strictObject({ contract: external_exports.literal("project-init"), version: external_exports.literal(5), ok: external_exports.literal(false), error: external_exports.strictObject({ code: external_exports.string(), message: external_exports.string() }) })
24632
24632
  ]);
24633
24633
 
24634
- // ../../packages/contracts/dist/versions/browser-specs-v2.js
24634
+ // ../../packages/contracts/dist/versions/browser-specs-v4.js
24635
24635
  var requirement = external_exports.strictObject({ id: external_exports.string(), title: external_exports.string(), body: external_exports.string() });
24636
24636
  var contributor = external_exports.strictObject({ email: external_exports.string(), name: external_exports.string(), commits: external_exports.number().int().nonnegative(), latest: external_exports.string() });
24637
24637
  var source = external_exports.strictObject({ title: external_exports.string(), path: external_exports.string().optional(), url: external_exports.string().optional(), note: external_exports.string().optional() });
@@ -24646,37 +24646,103 @@ var feature = external_exports.strictObject({
24646
24646
  contributors: external_exports.array(contributor),
24647
24647
  updatedAt: external_exports.string().nullable()
24648
24648
  });
24649
- var snapshot = requirement.extend({ specId: external_exports.string(), path: external_exports.string(), sources: external_exports.array(source).optional() }).nullable();
24650
24649
  var document = external_exports.strictObject({ id: external_exports.string(), path: external_exports.string(), title: external_exports.string(), body: external_exports.string(), updatedAt: external_exports.string().nullable() });
24651
- var browserSpecsV2 = external_exports.strictObject({
24650
+ var oid2 = external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
24651
+ var browserSpecsV4 = external_exports.strictObject({
24652
24652
  contract: external_exports.literal("browser-specs"),
24653
- version: external_exports.literal(2),
24653
+ version: external_exports.literal(4),
24654
24654
  sessionId: external_exports.string(),
24655
- head: external_exports.string().nullable(),
24655
+ head: oid2.nullable(),
24656
24656
  observedAt: external_exports.string(),
24657
24657
  working: external_exports.boolean(),
24658
24658
  features: external_exports.array(feature),
24659
- documents: external_exports.array(document).default([]),
24660
- events: external_exports.array(external_exports.strictObject({
24661
- key: external_exports.string(),
24662
- commit: external_exports.string(),
24663
- date: external_exports.string(),
24664
- author: external_exports.string(),
24665
- email: external_exports.string(),
24666
- committer: external_exports.string(),
24667
- message: external_exports.string(),
24668
- id: external_exports.string(),
24669
- kind: external_exports.enum(["requirement", "design", "wiki"]).optional(),
24670
- types: external_exports.array(external_exports.enum(["created", "modified", "moved", "deleted"])),
24671
- before: snapshot,
24672
- after: snapshot,
24673
- reasons: external_exports.array(external_exports.string())
24674
- })),
24659
+ documents: external_exports.array(document),
24675
24660
  contributors: external_exports.array(contributor),
24676
- contributorsLimited: external_exports.boolean(),
24677
- nextCursor: external_exports.number().int().nonnegative().nullable(),
24661
+ contributorsLimited: external_exports.boolean()
24662
+ });
24663
+ var reference = external_exports.strictObject({ id: external_exports.string(), title: external_exports.string(), specId: external_exports.string(), path: external_exports.string() }).nullable();
24664
+ var snapshot = requirement.extend({ specId: external_exports.string(), path: external_exports.string(), sources: external_exports.array(source).optional() }).nullable();
24665
+ var changeType = external_exports.enum(["created", "modified", "moved", "deleted"]);
24666
+ var event = external_exports.strictObject({
24667
+ key: external_exports.string(),
24668
+ commit: oid2,
24669
+ date: external_exports.string(),
24670
+ author: external_exports.string(),
24671
+ email: external_exports.string(),
24672
+ committer: external_exports.string(),
24673
+ message: external_exports.string(),
24674
+ id: external_exports.string(),
24675
+ kind: external_exports.enum(["requirement", "design", "wiki"]),
24676
+ types: external_exports.array(changeType),
24677
+ before: reference,
24678
+ after: reference,
24679
+ reasons: external_exports.array(external_exports.string())
24680
+ });
24681
+ var browserHistoryV1 = external_exports.strictObject({
24682
+ contract: external_exports.literal("browser-history"),
24683
+ version: external_exports.literal(1),
24684
+ sessionId: external_exports.string(),
24685
+ head: oid2,
24686
+ // Matching changes in all of history, not in this page; `offset` is where this page starts among them.
24687
+ total: external_exports.number().int().nonnegative(),
24688
+ offset: external_exports.number().int().nonnegative(),
24689
+ events: external_exports.array(event),
24690
+ // History reaches back to records in the legacy JSON format, which it does not read.
24678
24691
  boundary: external_exports.boolean()
24679
24692
  });
24693
+ var browserHistorySummaryV1 = external_exports.strictObject({
24694
+ contract: external_exports.literal("browser-history-summary"),
24695
+ version: external_exports.literal(1),
24696
+ sessionId: external_exports.string(),
24697
+ head: oid2,
24698
+ total: external_exports.number().int().nonnegative(),
24699
+ byType: external_exports.strictObject({ created: external_exports.number().int().nonnegative(), modified: external_exports.number().int().nonnegative(), moved: external_exports.number().int().nonnegative(), deleted: external_exports.number().int().nonnegative() }),
24700
+ // One entry per commit within three weeks of the newest change, so the reader can count by its own calendar day.
24701
+ pulse: external_exports.array(external_exports.strictObject({ date: external_exports.string(), count: external_exports.number().int().positive() })),
24702
+ // The newest commits: a few of their changes each and how many there are in all.
24703
+ recent: external_exports.array(external_exports.strictObject({ commit: oid2, count: external_exports.number().int().positive(), events: external_exports.array(event) }))
24704
+ });
24705
+ var browserChangeV1 = external_exports.strictObject({
24706
+ contract: external_exports.literal("browser-change"),
24707
+ version: external_exports.literal(1),
24708
+ sessionId: external_exports.string(),
24709
+ event,
24710
+ before: snapshot,
24711
+ after: snapshot
24712
+ });
24713
+ var browserSearchV1 = external_exports.strictObject({
24714
+ contract: external_exports.literal("browser-search"),
24715
+ version: external_exports.literal(1),
24716
+ sessionId: external_exports.string(),
24717
+ query: external_exports.string(),
24718
+ hits: external_exports.array(external_exports.strictObject({
24719
+ id: external_exports.string(),
24720
+ kind: external_exports.enum(["feature", "requirement", "design", "document", "history"]),
24721
+ title: external_exports.string(),
24722
+ where: external_exports.string(),
24723
+ line: external_exports.string(),
24724
+ // What the hit opens: a feature (with the requirement or design tab), a wiki page, or one change in the activity.
24725
+ featureId: external_exports.string().optional(),
24726
+ documentId: external_exports.string().optional(),
24727
+ key: external_exports.string().optional()
24728
+ }))
24729
+ });
24730
+ var headQuery = oid2;
24731
+ var count = (max) => external_exports.string().regex(/^(0|[1-9]\d{0,6})$/).transform(Number).pipe(external_exports.number().int().min(0).max(max));
24732
+ var browserHistoryQueryV1 = external_exports.strictObject({
24733
+ head: headQuery,
24734
+ offset: count(1e6).optional(),
24735
+ limit: count(100).pipe(external_exports.number().min(1)).optional(),
24736
+ kind: changeType.optional(),
24737
+ document: external_exports.enum(["requirement", "design", "wiki"]).optional(),
24738
+ feature: external_exports.string().regex(/^S-[a-z2-7]{10}$/).optional(),
24739
+ author: external_exports.string().min(1).max(320).optional(),
24740
+ q: external_exports.string().max(200).optional()
24741
+ });
24742
+ var browserHistorySummaryQueryV1 = external_exports.strictObject({ head: headQuery });
24743
+ var browserChangeQueryV1 = external_exports.strictObject({ key: external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64}):[RSW]-[a-z2-7]{10}$/) });
24744
+ var browserSearchQueryV1 = external_exports.strictObject({ q: external_exports.string().min(1).max(200), head: headQuery.optional() });
24745
+ var changelogQueryV1 = external_exports.strictObject({ lang: external_exports.string().regex(/^[a-z]{2}(?:-[A-Z]{2})?$/).optional() });
24680
24746
 
24681
24747
  // ../../packages/contracts/dist/versions/changelog-v1.js
24682
24748
  var items = external_exports.array(external_exports.string().min(1));
@@ -24750,14 +24816,9 @@ var messages_default2 = {
24750
24816
  "help.migrate": ".tryce \uC800\uC7A5\uC18C\uB97C .gitifact\uB85C \uC804\uD658 (\uACBD\uB85C\uC640 \uB9C8\uCEE4\uB9CC \uBC14\uAFB8\uACE0 ID\xB7\uC774\uC720\xB7\uC774\uB825\uC740 \uBCF4\uC874)",
24751
24817
  "help.migrateDryRun": "\uD30C\uC77C\uC744 \uBC14\uAFB8\uC9C0 \uC54A\uACE0 \uC804\uD658 \uACC4\uD68D \uD655\uC778",
24752
24818
  "help.spec": "Markdown \uBA85\uC138 \uC791\uC131\xB7\uC870\uD68C\xB7Git \uAE30\uB85D",
24753
- "help.deprecated": "Deprecated: 0.6.0\uC5D0\uC11C \uC81C\uAC70 \uC608\uC815. spec commit\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
24754
24819
  "help.specCommit": "\uBCC0\uACBD \uC774\uC720 \uAE30\uB85D\uACFC \uAD00\uB828 \uD30C\uC77C \uCEE4\uBC0B\uC744 \uD55C \uBC88\uC5D0 \uC2E4\uD589",
24755
24820
  "help.specCommitFile": "reasons\xB7paths\xB7message\xB7authorization\uC744 \uB2F4\uC740 JSON \uD30C\uC77C (-\uB294 \uD45C\uC900 \uC785\uB825)",
24756
24821
  "help.specCommitDryRun": "\uD30C\uC77C\uC744 \uC4F0\uAC70\uB098 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uACE0 \uACB0\uACFC\uB9CC \uD655\uC778",
24757
- "help.specCommitPlanFile": "\uCEE4\uBC0B \uC785\uB825 \uB610\uB294 \uACC4\uD68D JSON \uD30C\uC77C",
24758
- "help.specPrepareFile": "expected\uC640 \uCD5C\uC885 reasons\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
24759
- "help.specVerifyFile": "prepare\uC758 verification \uAC1D\uCCB4\uB97C \uB2F4\uC740 JSON \uD30C\uC77C",
24760
- "help.specVerifyStaged": "index \uC6D0\uBB38\uB3C4 \uBE44\uAD50",
24761
24822
  "help.specSaveFile": "expected\uC640 operations\uB97C \uB2F4\uC740 UTF-8 JSON \uD30C\uC77C (-\uB294 \uD45C\uC900 \uC785\uB825)",
24762
24823
  "help.specReadRef": "\uC77D\uC744 \uCEE4\uBC0B",
24763
24824
  "help.specDiffFrom": "\uC774\uC804 \uCEE4\uBC0B",
@@ -24823,13 +24884,6 @@ var messages_default2 = {
24823
24884
  "commit.fileChangedPreparing": "\uCEE4\uBC0B \uC900\uBE44 \uC911 \uD30C\uC77C\xB7\uC815\uCC45\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4: {path}",
24824
24885
  "commit.resultUnknown": "\uCEE4\uBC0B \uACB0\uACFC\uB97C \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24825
24886
  "commit.uncertain": "Git \uC2E4\uD589 \uACB0\uACFC\uB97C \uD655\uC778\uD574\uC57C \uD569\uB2C8\uB2E4. \uC7AC\uC2DC\uB3C4\uD558\uC9C0 \uB9D0\uACE0 HEAD\uC640 \uBCF5\uAD6C \uC790\uB8CC\uB97C \uD655\uC778\uD558\uC138\uC694: {path}",
24826
- "commit.existingStagingPlan": "\uAE30\uC874 staging\uC744 \uBCF4\uC874\uD569\uB2C8\uB2E4. \uC120\uD0DD \uBC94\uC704\uB97C \uC815\uB9AC\uD55C \uD6C4 \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
24827
- "commit.designUseSpecCommit": "\uC124\uACC4 \uBCC0\uACBD\uC740 spec commit\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.",
24828
- "commit.indexChangedPlanning": "\uACC4\uD68D \uC911 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
24829
- "commit.planCorrupted": "\uCEE4\uBC0B \uACC4\uD68D\uC774 \uC190\uC0C1\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
24830
- "commit.planScope": "\uACC4\uD68D\uC758 \uC800\uC7A5\uC18C \uB610\uB294 \uD30C\uC77C \uBC94\uC704\uAC00 \uB2E4\uB985\uB2C8\uB2E4.",
24831
- "commit.planStale": "\uACC4\uD68D \uC774\uD6C4 \uD30C\uC77C\xB7\uC815\uCC45\xB7index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uACC4\uD68D\uD558\uC138\uC694.",
24832
- "commit.indexChangedLocked": "\uC7A0\uAE08 \uC911 index\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
24833
24887
  "store.legacyLock": "\uC774\uC804 Tryce \uC2E4\uD589\uC758 \uC7A0\uAE08 \uB610\uB294 \uBCF5\uAD6C \uC790\uB8CC\uAC00 \uC788\uC2B5\uB2C8\uB2E4: {path}",
24834
24888
  "store.storeNotDirectory": ".gitifact\uB294 \uC77C\uBC18 \uB514\uB809\uD130\uB9AC\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
24835
24889
  "store.migrateFirst": ".tryce \uC800\uC7A5\uC18C\uC785\uB2C8\uB2E4. gitifact migrate\uB85C .gitifact\uC5D0 \uC804\uD658\uD55C \uB4A4 \uC0AC\uC6A9\uD558\uC138\uC694.",
@@ -24866,6 +24920,7 @@ var messages_default2 = {
24866
24920
  "server.apiNotFound": "API\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
24867
24921
  "server.sessionChanged": "\uC11C\uBC84 \uC138\uC158\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.",
24868
24922
  "server.badRange": "\uC870\uD68C \uBC94\uC704\uB97C \uD655\uC778\uD558\uC138\uC694.",
24923
+ "server.changeNotFound": "\uADF8 \uCEE4\uBC0B\uC5D0 \uD574\uB2F9 \uBCC0\uACBD\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
24869
24924
  "server.specsUnreadable": "\uBA85\uC138\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24870
24925
  "server.refreshOrigin": "\uC0C8\uB85C\uACE0\uCE68\uC5D0\uB294 \uAC19\uC740 \uCD9C\uCC98\uC758 Origin\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
24871
24926
  "server.fileNotFound": "\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
@@ -24891,18 +24946,8 @@ var messages_default2 = {
24891
24946
  "reader.blobShape": "\uAC80\uD1A0 \uC870\uD68C blob \uD615\uC2DD \uB610\uB294 1 MiB \uD55C\uB3C4\uB97C \uD655\uC778\uD558\uC138\uC694.",
24892
24947
  "reader.totalLimit": "\uBA85\uC138 \uC804\uCCB4 \uC870\uD68C 16 MiB \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4.",
24893
24948
  "reader.blobBoundary": "Git blob \uC751\uB2F5 \uACBD\uACC4\uAC00 \uB2E4\uB985\uB2C8\uB2E4.",
24894
- "prepare.integrationInProgress": "Git \uD1B5\uD569 \uC791\uC5C5 \uC911\uC5D0\uB294 \uC2E4\uD5D8\uC6A9 \uCEE4\uBC0B \uC900\uBE44\uB97C \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
24949
+ "prepare.integrationInProgress": "Git \uD1B5\uD569 \uC791\uC5C5 \uC911\uC5D0\uB294 \uBA85\uC138\uB97C \uC77D\uC5B4 \uCEE4\uBC0B\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
24895
24950
  "prepare.headChanged": "HEAD \uB610\uB294 \uBE0C\uB79C\uCE58\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. changes\uBD80\uD130 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
24896
- "prepare.invalidInput": "\uC798\uBABB\uB41C \uC900\uBE44 \uC785\uB825\uC785\uB2C8\uB2E4.",
24897
- "prepare.expectedReasons": "expected\uC640 reasons\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
24898
- "prepare.staleInput": "\uC900\uBE44 \uC785\uB825\uC774 \uC624\uB798\uB410\uC2B5\uB2C8\uB2E4. changes\uBD80\uD130 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.",
24899
- "prepare.invalidVerifyInput": "\uC798\uBABB\uB41C \uD655\uC778 \uC785\uB825\uC785\uB2C8\uB2E4.",
24900
- "prepare.verificationRequired": "prepare\uAC00 \uBC18\uD658\uD55C verification \uAC1D\uCCB4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
24901
- "prepare.changedAfterPrepare": "\uC900\uBE44 \uB4A4 HEAD \uB610\uB294 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC900\uBE44\uD558\uC138\uC694.",
24902
- "prepare.stagingScope": "staging\uC758 \uBA85\uC138 \uBC94\uC704\uAC00 \uC900\uBE44\uD55C \uC6D0\uBB38\uACFC \uB2E4\uB985\uB2C8\uB2E4.",
24903
- "prepare.stagingContent": "staging \uC6D0\uBB38\uC774 \uC900\uBE44\uD55C \uD30C\uC77C\uACFC \uB2E4\uB985\uB2C8\uB2E4: {path}",
24904
- "prepare.stagingChanged": "\uD655\uC778 \uC911 staging\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
24905
- "prepare.specsChanged": "\uD655\uC778 \uC911 \uBA85\uC138\uAC00 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4.",
24906
24951
  "commitFiles.relativePath": "\uC800\uC7A5\uC18C \uC0C1\uB300 \uACBD\uB85C\uC758 \uBA85\uC138 \uB610\uB294 \uC77C\uBC18 \uD30C\uC77C\uB9CC \uC120\uD0DD\uD558\uC138\uC694.",
24907
24952
  "commitFiles.linkOrDirectory": "\uB9C1\uD06C\xB7\uB514\uB809\uD130\uB9AC\xB7\uD2B9\uC218 \uD30C\uC77C\uC740 \uC120\uD0DD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
24908
24953
  "commitFiles.nestedRepository": "\uC911\uCCA9 \uC800\uC7A5\uC18C\uB294 \uC120\uD0DD\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
@@ -24948,7 +24993,6 @@ var messages_default2 = {
24948
24993
  "agentBlock.duplicateStart": "GITIFACT \uC2DC\uC791 \uB9C8\uCEE4\uAC00 \uC5EC\uB7EC \uAC1C\uC785\uB2C8\uB2E4. \uC911\uBCF5 \uBE14\uB85D\uC744 \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
24949
24994
  "specReader.headUnreadable": "HEAD\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24950
24995
  "specReader.schemaRequired": "\uC0C8 \uC2A4\uD0A4\uB9C8 \uD504\uB85C\uC81D\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
24951
- "specReader.historyChanged": "\uC774\uB825\uC774 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68 \uD6C4 \uB2E4\uC2DC \uC870\uD68C\uD558\uC138\uC694.",
24952
24996
  "specReader.authorUnreadable": "Git \uC791\uC131\uC790\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24953
24997
  "specReader.historyUnreadable": "Git \uC774\uB825 \uD615\uC2DD\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24954
24998
  "specReader.projectChanged": "\uC870\uD68C \uC911 \uD504\uB85C\uC81D\uD2B8\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68\uD558\uC138\uC694.",
@@ -24963,11 +25007,11 @@ var messages_default2 = {
24963
25007
  "docs.summary.workflow": "\uC2DC\uC791 \uC2DC \uD655\uC778\uD560 \uAC83, \uC694\uAD6C\uC0AC\uD56D\uC73C\uB85C \uB0A8\uAE38 \uC694\uCCAD\uC758 \uAD6C\uBD84, \uB9C8\uBB34\uB9AC \uBCF4\uACE0",
24964
25008
  "docs.summary.spec": "\uC0AC\uC6A9\uC790 \uC2A4\uD1A0\uB9AC\xB7\uC218\uC6A9 \uC870\uAC74 \uD615\uC2DD, ID \uADDC\uCE59, spec save \uC785\uB825",
24965
25009
  "docs.summary.design": "design.md \uBAA9\uCC28, \uCC38\uC870 \uC8FC\uC11D\uACFC \uCC38\uACE0 \uBB38\uC11C, \uAC1C\uC815 \uBC29\uC2DD",
25010
+ "docs.summary.writing": "\uC704\uD0A4\xB7\uC694\uAD6C\uC0AC\uD56D\xB7\uC124\uACC4\uC5D0 \uACF5\uD1B5\uC73C\uB85C \uC801\uC6A9\uD558\uB294 \uBB38\uCCB4, \uC778\uC6A9\uACFC Alert, AI \uC2AC\uB86D \uC81C\uAC70",
24966
25011
  "docs.summary.commit": "spec commit \uC785\uB825, \uC774\uC720 \uAE30\uB85D, \uC2E4\uD328 \uD6C4 \uBCF5\uAD6C",
24967
25012
  "help.browserNoUpdateCheck": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC744 \uC704\uD55C npm \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uB054 (GITIFACT_NO_UPDATE_CHECK\uC640 \uAC19\uC74C)",
24968
25013
  "help.updateCommit": "\uAC31\uC2E0\uD55C GITIFACT \uBE14\uB85D\uC774 HEAD\uC640 \uBE14\uB85D \uC548\uC5D0\uC11C\uB9CC \uB2E4\uB974\uBA74 \uADF8 \uD30C\uC77C\uB9CC \uACE0\uC815 \uBA54\uC2DC\uC9C0\uB85C \uCEE4\uBC0B",
24969
25014
  "help.update": "\uC0C8 \uBC84\uC804 \uD655\uC778\uACFC \uC124\uCE58 \uBC29\uBC95 \uC548\uB0B4, \uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68 \uD30C\uC77C\uC758 GITIFACT \uBE14\uB85D\uC744 \uD604\uC7AC \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0",
24970
- "server.badLanguage": "\uC5B8\uC5B4 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
24971
25015
  "server.changelogNotFound": "\uD328\uCE58\uB178\uD2B8\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24972
25016
  "server.changelogUnreadable": "\uD328\uCE58\uB178\uD2B8\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
24973
25017
  "update.text.current": "\uD604\uC7AC \uBC84\uC804: {version}",
@@ -25069,43 +25113,7 @@ async function runStatus(format) {
25069
25113
  import { createServer } from "node:http";
25070
25114
  import { randomUUID as randomUUID4 } from "node:crypto";
25071
25115
  import { fileURLToPath } from "node:url";
25072
- import { lstat as lstat4, readFile as readFile4 } from "node:fs/promises";
25073
- import { join as join5 } from "node:path";
25074
-
25075
- // src/server/assets.ts
25076
- import { readdir, readFile } from "node:fs/promises";
25077
- import { join } from "node:path";
25078
- async function loadBrowserAssets(directory) {
25079
- const assets = /* @__PURE__ */ new Map();
25080
- async function walk(current, prefix) {
25081
- for (const entry2 of await readdir(current, { withFileTypes: true })) {
25082
- if (entry2.isSymbolicLink()) throw new Error(t2("browser.assetSymlink"));
25083
- const name = prefix + entry2.name;
25084
- if (entry2.isDirectory()) await walk(join(current, entry2.name), name + "/");
25085
- else if (entry2.isFile()) assets.set("/" + name, await readFile(join(current, entry2.name)));
25086
- }
25087
- }
25088
- try {
25089
- await walk(directory, "");
25090
- if (!assets.has("/index.html")) throw new Error("missing index");
25091
- } catch {
25092
- throw new Error(t2("browser.assetsUnreadable"));
25093
- }
25094
- return assets;
25095
- }
25096
- function contentType(path3) {
25097
- if (path3.endsWith(".html")) return "text/html; charset=utf-8";
25098
- if (path3.endsWith(".js")) return "text/javascript; charset=utf-8";
25099
- if (path3.endsWith(".css")) return "text/css; charset=utf-8";
25100
- if (path3.endsWith(".svg")) return "image/svg+xml";
25101
- if (path3.endsWith(".woff2")) return "font/woff2";
25102
- if (path3.endsWith(".png")) return "image/png";
25103
- if (/\.jpe?g$/.test(path3)) return "image/jpeg";
25104
- if (path3.endsWith(".gif")) return "image/gif";
25105
- if (path3.endsWith(".webp")) return "image/webp";
25106
- if (path3.endsWith(".pdf")) return "application/pdf";
25107
- return "application/octet-stream";
25108
- }
25116
+ import { readFile as readFile5 } from "node:fs/promises";
25109
25117
 
25110
25118
  // src/server/status-session.ts
25111
25119
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -25193,6 +25201,172 @@ function createStatusSession(initial, read, cliVersion = "0.0.0") {
25193
25201
  };
25194
25202
  }
25195
25203
 
25204
+ // src/server/http/respond.ts
25205
+ var HttpError = class extends Error {
25206
+ constructor(status, code, message) {
25207
+ super(message);
25208
+ this.status = status;
25209
+ this.code = code;
25210
+ }
25211
+ status;
25212
+ code;
25213
+ };
25214
+ function json2(response, status, value) {
25215
+ response.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
25216
+ response.end(JSON.stringify(value) + "\n");
25217
+ }
25218
+ function fail4(response, status, code, message) {
25219
+ json2(response, status, browserHttpErrorV1.parse({ contract: "browser-http-error", version: 1, error: { code, message } }));
25220
+ }
25221
+
25222
+ // src/server/http/guard.ts
25223
+ function admit(request, response, origin, dev) {
25224
+ response.setHeader("X-Content-Type-Options", "nosniff");
25225
+ response.setHeader("X-Frame-Options", "DENY");
25226
+ response.setHeader("Referrer-Policy", "no-referrer");
25227
+ response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'");
25228
+ if (request.headers.host !== new URL(origin).host) {
25229
+ fail4(response, 403, "FORBIDDEN", t2("server.forbiddenHost"));
25230
+ return;
25231
+ }
25232
+ const requestOrigin = request.headers.origin;
25233
+ const allowedOrigin = requestOrigin === origin || dev && requestOrigin === "http://127.0.0.1:5173";
25234
+ if (requestOrigin && !allowedOrigin) {
25235
+ fail4(response, 403, "FORBIDDEN", t2("server.forbiddenOrigin"));
25236
+ return;
25237
+ }
25238
+ const raw = request.url ?? "/";
25239
+ if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) {
25240
+ fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
25241
+ return;
25242
+ }
25243
+ let url2;
25244
+ let path3;
25245
+ try {
25246
+ url2 = new URL(raw, origin);
25247
+ path3 = decodeURIComponent(url2.pathname);
25248
+ } catch {
25249
+ fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
25250
+ return;
25251
+ }
25252
+ if (path3.includes("\0") || path3.includes("\\") || path3.split("/").some((part) => part === ".." || part === ".")) {
25253
+ fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
25254
+ return;
25255
+ }
25256
+ if (request.headers["transfer-encoding"] || request.headers["content-length"] && request.headers["content-length"] !== "0") {
25257
+ request.resume();
25258
+ fail4(response, 400, "BAD_REQUEST", t2("server.noBody"));
25259
+ return;
25260
+ }
25261
+ const api = path3 === "/api" || path3.startsWith("/api/");
25262
+ if (api && request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) {
25263
+ fail4(response, 403, "FORBIDDEN", t2("server.crossSite"));
25264
+ return;
25265
+ }
25266
+ return { url: url2, path: path3, api, allowedOrigin: !!allowedOrigin };
25267
+ }
25268
+
25269
+ // src/server/http/router.ts
25270
+ var route = (value) => value;
25271
+ var ok = (body) => ({ status: 200, body });
25272
+ var matches = (route2, path3) => route2.path.endsWith("/*") ? path3.startsWith(route2.path.slice(0, -1)) : route2.path === path3;
25273
+ async function dispatch(routes, sessionId, url2, path3, request, response, allowedOrigin) {
25274
+ const candidates2 = routes.filter((r) => matches(r, path3));
25275
+ if (!candidates2.length) return fail4(response, 404, "NOT_FOUND", t2("server.apiNotFound"));
25276
+ const found = candidates2.find((r) => r.method === request.method);
25277
+ if (!found) {
25278
+ response.setHeader("Allow", candidates2.map((r) => r.method).join(", "));
25279
+ return fail4(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
25280
+ }
25281
+ let query = {};
25282
+ if (found.query) {
25283
+ const keys2 = [...url2.searchParams.keys()];
25284
+ if (new Set(keys2).size !== keys2.length) return fail4(response, 400, "BAD_REQUEST", t2("server.badRange"));
25285
+ const parsed = found.query.safeParse(Object.fromEntries(url2.searchParams));
25286
+ if (!parsed.success) return fail4(response, 400, "BAD_REQUEST", t2("server.badRange"));
25287
+ query = parsed.data;
25288
+ } else if (url2.search) return fail4(response, 400, "BAD_REQUEST", t2("server.noQuery"));
25289
+ if (found.session && request.headers["x-gitifact-session"] !== sessionId) return fail4(response, 409, "SESSION_CHANGED", t2("server.sessionChanged"));
25290
+ try {
25291
+ const reply = await found.handle({ query, path: path3, request, response, allowedOrigin });
25292
+ if (reply && !response.destroyed) json2(response, reply.status, reply.body);
25293
+ } catch (error62) {
25294
+ if (error62 instanceof HttpError) return fail4(response, error62.status, error62.code, error62.message);
25295
+ fail4(response, 503, "INTERNAL_ERROR", error62 instanceof Error && error62.message ? error62.message : found.unreadable ?? t2("server.internal"));
25296
+ }
25297
+ }
25298
+
25299
+ // src/server/http/static-files.ts
25300
+ import { readdir, readFile } from "node:fs/promises";
25301
+ import { join } from "node:path";
25302
+ async function loadBrowserAssets(directory) {
25303
+ const assets = /* @__PURE__ */ new Map();
25304
+ async function walk(current, prefix) {
25305
+ for (const entry2 of await readdir(current, { withFileTypes: true })) {
25306
+ if (entry2.isSymbolicLink()) throw new Error(t2("browser.assetSymlink"));
25307
+ const name = prefix + entry2.name;
25308
+ if (entry2.isDirectory()) await walk(join(current, entry2.name), name + "/");
25309
+ else if (entry2.isFile()) assets.set("/" + name, await readFile(join(current, entry2.name)));
25310
+ }
25311
+ }
25312
+ try {
25313
+ await walk(directory, "");
25314
+ if (!assets.has("/index.html")) throw new Error("missing index");
25315
+ } catch {
25316
+ throw new Error(t2("browser.assetsUnreadable"));
25317
+ }
25318
+ return assets;
25319
+ }
25320
+ function contentType(path3) {
25321
+ if (path3.endsWith(".html")) return "text/html; charset=utf-8";
25322
+ if (path3.endsWith(".js")) return "text/javascript; charset=utf-8";
25323
+ if (path3.endsWith(".css")) return "text/css; charset=utf-8";
25324
+ if (path3.endsWith(".svg")) return "image/svg+xml";
25325
+ if (path3.endsWith(".woff2")) return "font/woff2";
25326
+ if (path3.endsWith(".png")) return "image/png";
25327
+ if (/\.jpe?g$/.test(path3)) return "image/jpeg";
25328
+ if (path3.endsWith(".gif")) return "image/gif";
25329
+ if (path3.endsWith(".webp")) return "image/webp";
25330
+ if (path3.endsWith(".pdf")) return "application/pdf";
25331
+ return "application/octet-stream";
25332
+ }
25333
+ function serveStatic(request, response, path3, assets) {
25334
+ if (request.method !== "GET" && request.method !== "HEAD") {
25335
+ response.setHeader("Allow", "GET, HEAD");
25336
+ return fail4(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
25337
+ }
25338
+ let assetPath = path3 === "/" ? "/index.html" : path3;
25339
+ let asset = assets.get(assetPath);
25340
+ if (!asset && !path3.startsWith("/assets/") && !path3.split("/").some((part) => part.includes(".")) && request.headers.accept?.includes("text/html")) {
25341
+ asset = assets.get("/index.html");
25342
+ assetPath = "/index.html";
25343
+ }
25344
+ if (!asset) return fail4(response, 404, "NOT_FOUND", t2("server.fileNotFound"));
25345
+ response.writeHead(200, { "Content-Type": contentType(assetPath), "Cache-Control": "no-cache", "Content-Length": asset.length });
25346
+ response.end(request.method === "HEAD" ? void 0 : asset);
25347
+ }
25348
+
25349
+ // src/server/routes/project-routes.ts
25350
+ function projectRoutes(store, readChangelog) {
25351
+ return [
25352
+ // Re-reading the session never contacts the registry; it returns the state the single startup check left.
25353
+ route({ method: "GET", path: "/api/v1/session", session: false, handle: () => ok(store.session) }),
25354
+ route({ method: "GET", path: "/api/v1/status", session: true, handle: () => ({ status: store.latest.ok ? 200 : 503, body: store.latest }) }),
25355
+ route({ method: "POST", path: "/api/v1/status/refresh", session: true, handle: async ({ allowedOrigin }) => {
25356
+ if (!allowedOrigin) throw new HttpError(403, "FORBIDDEN", t2("server.refreshOrigin"));
25357
+ const value = await store.refresh();
25358
+ return { status: value.ok ? 200 : 503, body: value };
25359
+ } }),
25360
+ route({ method: "GET", path: "/api/v1/changelog", session: true, query: changelogQueryV1, unreadable: t2("server.changelogUnreadable"), handle: async ({ query }) => {
25361
+ const language = query.lang ?? defaultLanguage2;
25362
+ const own2 = await readChangelog(language);
25363
+ const text2 = own2 ?? (language === defaultLanguage2 ? null : await readChangelog(defaultLanguage2));
25364
+ if (text2 === null) throw new HttpError(404, "NOT_FOUND", t2("server.changelogNotFound"));
25365
+ return ok(changelogV1.parse({ contract: "changelog", version: 1, language: own2 === null ? defaultLanguage2 : language, fallback: own2 === null, entries: parseChangelog(text2) }));
25366
+ } })
25367
+ ];
25368
+ }
25369
+
25196
25370
  // src/adapters/git/command-scope.ts
25197
25371
  import { AsyncLocalStorage } from "node:async_hooks";
25198
25372
  var storage = new AsyncLocalStorage();
@@ -25235,19 +25409,24 @@ function specPreviewReader(cwd) {
25235
25409
  }
25236
25410
  };
25237
25411
  return {
25412
+ /** Git under the same guarded environment, for readers that shape their own commands (the browser's history). */
25413
+ run(args, input2) {
25414
+ return git(args, input2);
25415
+ },
25416
+ decode: decode5,
25238
25417
  async index() {
25239
25418
  const output2 = decode5(await git(["ls-files", "--stage", "-z", "--", ...RECORD_PATHSPECS]));
25240
25419
  const files = /* @__PURE__ */ new Map();
25241
25420
  for (const row of output2.split("\0").filter(Boolean)) {
25242
25421
  const match = /^(\d+) ([a-f0-9]+) ([0-3])\t([\s\S]+)$/.exec(row);
25243
25422
  if (!match) throw new SpecPreviewError(t2("reader.invalidIndexEntry"));
25244
- const [, mode, oid2, stage, path3] = match;
25423
+ const [, mode, oid3, stage, path3] = match;
25245
25424
  if (!["100644", "100755"].includes(mode) || stage !== "0") throw new SpecPreviewError(t2("reader.stagingConflictOrLink"));
25246
25425
  if (!recordPathPattern.test(path3)) {
25247
25426
  if (path3.startsWith(WIKI_DIR + "/")) continue;
25248
25427
  throw new SpecPreviewError(t2("reader.stagingUnsupported"));
25249
25428
  }
25250
- files.set(path3, oid2);
25429
+ files.set(path3, oid3);
25251
25430
  }
25252
25431
  return files;
25253
25432
  },
@@ -25280,12 +25459,12 @@ function specPreviewReader(cwd) {
25280
25459
  });
25281
25460
  },
25282
25461
  async resolve(ref) {
25283
- const oid2 = (await git(["rev-parse", "--verify", "--end-of-options", ref + "^{commit}"])).toString("ascii").trim();
25284
- if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid2)) throw new SpecPreviewError(t2("reader.commitUnknown"));
25285
- return oid2;
25462
+ const oid3 = (await git(["rev-parse", "--verify", "--end-of-options", ref + "^{commit}"])).toString("ascii").trim();
25463
+ if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid3)) throw new SpecPreviewError(t2("reader.commitUnknown"));
25464
+ return oid3;
25286
25465
  },
25287
- async files(oid2, allowLegacyBaseline = false) {
25288
- const entries = decode5(await git(["ls-tree", "--full-tree", "-r", "-z", oid2, "--", ...RECORD_PATHSPECS]));
25466
+ async files(oid3, allowLegacyBaseline = false) {
25467
+ const entries = decode5(await git(["ls-tree", "--full-tree", "-r", "-z", oid3, "--", ...RECORD_PATHSPECS]));
25289
25468
  const files = /* @__PURE__ */ new Map();
25290
25469
  let legacy;
25291
25470
  for (const row of entries.split("\0").filter(Boolean)) {
@@ -25305,7 +25484,7 @@ function specPreviewReader(cwd) {
25305
25484
  if (new Set([...files.keys()].map((p) => p.split("/")[0])).size > 1) throw new SpecPreviewError(t2("reader.mixedStores"));
25306
25485
  if (legacy) {
25307
25486
  if (files.size) throw new SpecPreviewError(t2("reader.mixedFormats"));
25308
- parseProjectConfig(decode5(await git(["show", `${oid2}:${legacy}/config.json`])));
25487
+ parseProjectConfig(decode5(await git(["show", `${oid3}:${legacy}/config.json`])));
25309
25488
  }
25310
25489
  if (files.size > 2e3) throw new SpecPreviewError(t2("reader.fileLimit"));
25311
25490
  const blobs = /* @__PURE__ */ new Map();
@@ -25329,12 +25508,12 @@ function specPreviewReader(cwd) {
25329
25508
  }
25330
25509
  return new Map([...files].map(([path3, id]) => [path3, blobs.get(id)]));
25331
25510
  },
25332
- async read(oid2) {
25333
- const files = await this.files(oid2);
25511
+ async read(oid3) {
25512
+ const files = await this.files(oid3);
25334
25513
  return parsePreviewFiles(files);
25335
25514
  },
25336
- async readBundle(oid2) {
25337
- return parsePreviewBundle(await this.files(oid2));
25515
+ async readBundle(oid3) {
25516
+ return parsePreviewBundle(await this.files(oid3));
25338
25517
  }
25339
25518
  };
25340
25519
  }
@@ -25468,7 +25647,7 @@ async function publishConfig(root, text2, recheck, beforePublish, replace = fals
25468
25647
  }
25469
25648
 
25470
25649
  // src/adapters/filesystem/spec-preview-store.ts
25471
- var fail4 = (message) => {
25650
+ var fail5 = (message) => {
25472
25651
  throw new SpecPreviewError(message);
25473
25652
  };
25474
25653
  var info2 = async (path3) => lstat3(path3).catch((e) => {
@@ -25478,7 +25657,7 @@ var info2 = async (path3) => lstat3(path3).catch((e) => {
25478
25657
  var digest = (value) => createHash2("sha256").update(value).digest("hex");
25479
25658
  var LEGACY_LOCKS = ["tryce-spec-preview.lock", "tryce-spec-commit.lock"];
25480
25659
  async function failOnLegacyLock(gitDir) {
25481
- for (const name of LEGACY_LOCKS) if (await info2(join4(gitDir, name))) fail4(t2("store.legacyLock", { path: join4(gitDir, name) }));
25660
+ for (const name of LEGACY_LOCKS) if (await info2(join4(gitDir, name))) fail5(t2("store.legacyLock", { path: join4(gitDir, name) }));
25482
25661
  }
25483
25662
  var decode3 = (bytes) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
25484
25663
  var generatePreviewId = (prefix) => prefix + "-" + [...randomBytes(10)].map((n) => "abcdefghijklmnopqrstuvwxyz234567"[n & 31]).join("");
@@ -25486,29 +25665,29 @@ var PreservedPreviewError = class extends SpecPreviewError {
25486
25665
  };
25487
25666
  async function snapshot2(root) {
25488
25667
  const files = /* @__PURE__ */ new Map();
25489
- let count = 0;
25668
+ let count2 = 0;
25490
25669
  let bytes = 0;
25491
25670
  const parent = await info2(join4(root, ".gitifact"));
25492
- if (parent && (!parent.isDirectory() || parent.isSymbolicLink())) fail4(t2("store.storeNotDirectory"));
25493
- if (!parent && await info2(join4(root, ".tryce"))) fail4(t2("store.migrateFirst"));
25671
+ if (parent && (!parent.isDirectory() || parent.isSymbolicLink())) fail5(t2("store.storeNotDirectory"));
25672
+ if (!parent && await info2(join4(root, ".tryce"))) fail5(t2("store.migrateFirst"));
25494
25673
  const config2 = await readConfigFile(root);
25495
- if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info2(join4(root, "specs"))) fail4(t2("store.legacyProject"));
25674
+ if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info2(join4(root, "specs"))) fail5(t2("store.legacyProject"));
25496
25675
  async function visit2(path3, depth, documents) {
25497
25676
  const stat3 = await info2(join4(root, path3));
25498
25677
  if (!stat3) return;
25499
- if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile()) fail4(t2("store.linkOrSpecial", { path: path3 }));
25500
- if (++count > 4e3) fail4(t2("store.tooManyFiles"));
25678
+ if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile()) fail5(t2("store.linkOrSpecial", { path: path3 }));
25679
+ if (++count2 > 4e3) fail5(t2("store.tooManyFiles"));
25501
25680
  if (stat3.isDirectory()) {
25502
- if (depth > (documents ? 8 : 1)) fail4(t2("store.tooDeep", { path: path3 }));
25681
+ if (depth > (documents ? 8 : 1)) fail5(t2("store.tooDeep", { path: path3 }));
25503
25682
  for (const name of (await readdir3(join4(root, path3))).sort()) await visit2(path3 + "/" + name, depth + 1, documents);
25504
25683
  } else {
25505
- if (path3.endsWith("/tryce.json")) fail4(t2("store.legacyJson"));
25684
+ if (path3.endsWith("/tryce.json")) fail5(t2("store.legacyJson"));
25506
25685
  if (documents ? !(path3.endsWith(".md") || depth === 1 && path3.endsWith("/history.jsonl")) : !/\/(requirements\.md|design\.md|history\.jsonl)$/.test(path3)) return;
25507
- if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/")) fail4(t2("store.unsupportedPath", { path: path3 }));
25508
- if (stat3.nlink !== 1 || stat3.size > 1024 * 1024) fail4(t2("store.hardLinkOrSize"));
25686
+ if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/")) fail5(t2("store.unsupportedPath", { path: path3 }));
25687
+ if (stat3.nlink !== 1 || stat3.size > 1024 * 1024) fail5(t2("store.hardLinkOrSize"));
25509
25688
  const raw = await readFile3(join4(root, path3));
25510
25689
  bytes += raw.length;
25511
- if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024) fail4(t2("store.sizeLimit"));
25690
+ if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024) fail5(t2("store.sizeLimit"));
25512
25691
  files.set(path3, decode3(raw));
25513
25692
  }
25514
25693
  }
@@ -25520,11 +25699,11 @@ async function snapshot2(root) {
25520
25699
  async function readWorkingPreviewState(cwd) {
25521
25700
  const { root, gitDir } = await specPreviewReader(cwd).location();
25522
25701
  await failOnLegacyLock(gitDir);
25523
- if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail4(t2("store.locked"));
25702
+ if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail5(t2("store.locked"));
25524
25703
  const first = await snapshot2(root);
25525
25704
  const second = await snapshot2(root);
25526
- if (first.stamp !== second.stamp) fail4(t2("store.changedWhileReading"));
25527
- if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail4(t2("store.lockedWhileReading"));
25705
+ if (first.stamp !== second.stamp) fail5(t2("store.changedWhileReading"));
25706
+ if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail5(t2("store.lockedWhileReading"));
25528
25707
  return first;
25529
25708
  }
25530
25709
  async function readWorkingPreview(cwd) {
@@ -25532,9 +25711,9 @@ async function readWorkingPreview(cwd) {
25532
25711
  return { stamp, specs, wiki, warnings: await workingWarnings(root, bundle) };
25533
25712
  }
25534
25713
  async function saveWorkingPreview(cwd, input2, publish = rename2) {
25535
- if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail4(t2("store.invalidInput"));
25714
+ if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("store.invalidInput"));
25536
25715
  const request = input2;
25537
- if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string") fail4(t2("store.expectedOperations"));
25716
+ if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string") fail5(t2("store.expectedOperations"));
25538
25717
  return previewTransaction(cwd, request.expected, async (before) => {
25539
25718
  const result = editSpecPreview(before.bundle, request.operations, generatePreviewId);
25540
25719
  const writes = /* @__PURE__ */ new Map();
@@ -25562,7 +25741,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25562
25741
  try {
25563
25742
  await mkdir2(lock);
25564
25743
  } catch (e) {
25565
- if (e.code === "EEXIST") fail4(t2("store.locked"));
25744
+ if (e.code === "EEXIST") fail5(t2("store.locked"));
25566
25745
  throw e;
25567
25746
  }
25568
25747
  const createdDirs = [];
@@ -25573,7 +25752,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25573
25752
  async function directory(path3) {
25574
25753
  const stat3 = await info2(path3);
25575
25754
  if (stat3) {
25576
- if (!stat3.isDirectory() || stat3.isSymbolicLink()) fail4(t2("store.notDirectory", { path: path3 }));
25755
+ if (!stat3.isDirectory() || stat3.isSymbolicLink()) fail5(t2("store.notDirectory", { path: path3 }));
25577
25756
  return;
25578
25757
  }
25579
25758
  await directory(dirname(path3));
@@ -25582,11 +25761,11 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25582
25761
  }
25583
25762
  try {
25584
25763
  const before = await snapshot2(root);
25585
- if (before.stamp !== expected2) fail4(t2("store.staleExpected"));
25764
+ if (before.stamp !== expected2) fail5(t2("store.staleExpected"));
25586
25765
  const result = await build(before);
25587
25766
  for (const [path3, after2] of result.writes) {
25588
- if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p))) fail4(t2("store.unsupportedSavePath"));
25589
- if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024) fail4(t2("store.fileSizeLimit"));
25767
+ if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p))) fail5(t2("store.unsupportedSavePath"));
25768
+ if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024) fail5(t2("store.fileSizeLimit"));
25590
25769
  changed.push({ path: path3, before: before.files.get(path3) ?? null, after: after2 });
25591
25770
  }
25592
25771
  const finalFiles = new Map(before.files);
@@ -25594,7 +25773,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25594
25773
  if (c.after === null) finalFiles.delete(c.path);
25595
25774
  else finalFiles.set(c.path, c.after);
25596
25775
  }
25597
- if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024) fail4(t2("store.totalLimit"));
25776
+ if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024) fail5(t2("store.totalLimit"));
25598
25777
  await writeFile(join4(lock, "recovery.json"), JSON.stringify({ root, changed }), { flag: "wx" });
25599
25778
  for (const c of changed) {
25600
25779
  if (c.after === null) {
@@ -25606,19 +25785,19 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25606
25785
  await writeFile(temp, c.after, { flag: "wx" });
25607
25786
  temporary.push(temp);
25608
25787
  }
25609
- if ((await snapshot2(root)).stamp !== before.stamp) fail4(t2("store.changedPreparing"));
25788
+ if ((await snapshot2(root)).stamp !== before.stamp) fail5(t2("store.changedPreparing"));
25610
25789
  await result.recheck?.();
25611
25790
  for (let i = 0; i < changed.length; i++) {
25612
25791
  const c = changed[i];
25613
25792
  const path3 = join4(root, c.path);
25614
25793
  const stat3 = await info2(path3);
25615
- if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before) fail4(t2("store.changedBeforeWrite"));
25794
+ if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before) fail5(t2("store.changedBeforeWrite"));
25616
25795
  if (c.after === null) await unlink2(path3);
25617
25796
  else await publish(temporary[i], path3);
25618
25797
  published.push(c);
25619
25798
  }
25620
25799
  const after = await snapshot2(root);
25621
- if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? ""))) fail4(t2("store.changedWhileWriting"));
25800
+ if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? ""))) fail5(t2("store.changedWhileWriting"));
25622
25801
  await result.recheck?.();
25623
25802
  await afterPublish?.(after);
25624
25803
  return { ...result.data, stamp: after.stamp, paths: changed.map((c) => c.path), specs: after.specs, wiki: after.wiki, warnings: await workingWarnings(root, after.bundle) };
@@ -25646,7 +25825,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25646
25825
  keepRecovery = true;
25647
25826
  }
25648
25827
  }
25649
- if (keepRecovery) fail4(t2("store.recoveryIncomplete", { path: lock }));
25828
+ if (keepRecovery) fail5(t2("store.recoveryIncomplete", { path: lock }));
25650
25829
  throw error62;
25651
25830
  } finally {
25652
25831
  for (const path3 of temporary.filter(Boolean)) await unlink2(path3).catch((e) => {
@@ -25663,147 +25842,686 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
25663
25842
  }
25664
25843
  }
25665
25844
 
25666
- // src/server/spec-reader.ts
25667
- function createSpecBrowserReader(root, sessionId, inherited = process.env) {
25845
+ // src/server/checkout/checkout-reader.ts
25846
+ var tally = (people, name, email3, latest) => {
25847
+ const person = people.get(email3);
25848
+ if (person) person.commits++;
25849
+ else people.set(email3, { name, email: email3, latest, commits: 1 });
25850
+ };
25851
+ async function settled(reads) {
25852
+ const results = await Promise.allSettled(reads);
25853
+ const failure2 = results.find((r) => r.status === "rejected");
25854
+ if (failure2) throw failure2.reason;
25855
+ return results.map((r) => r.value);
25856
+ }
25857
+ function createCheckoutReader(root, sessionId, inherited = process.env) {
25668
25858
  const reader = specPreviewReader(root);
25669
25859
  const runner = createGitRunner();
25670
25860
  const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_REPLACE_OBJECTS: "1", GIT_TERMINAL_PROMPT: "0", LC_ALL: "C" };
25671
- const git = async (args, acceptedExitCodes = [0]) => (await runner(["--no-optional-locks", ...args], { cwd: root, env, timeoutMs: 15e3, maxBytes: 16 * 1024 * 1024, acceptedExitCodes })).toString("utf8");
25861
+ const git = async (args, acceptedExitCodes = [0]) => (await runner(["--no-optional-locks", ...args], { cwd: root, env, timeoutMs: 15e3, maxBytes: 32 * 1024 * 1024, acceptedExitCodes })).toString("utf8");
25672
25862
  const readHead = async () => {
25673
25863
  const head = (await git(["rev-parse", "--verify", "--quiet", "HEAD"], [0, 1])).trim();
25674
25864
  if (head && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError(t2("specReader.headUnreadable"));
25675
25865
  if (!head) await reader.baseline();
25676
25866
  return head || null;
25677
25867
  };
25678
- const snapshots = /* @__PURE__ */ new Map();
25679
- const snapshot3 = (oid2) => {
25680
- let value = snapshots.get(oid2);
25681
- if (!value) {
25682
- value = reader.readBundle(oid2).catch((e) => {
25683
- snapshots.delete(oid2);
25684
- throw e;
25685
- });
25686
- snapshots.set(oid2, value);
25687
- }
25688
- if (snapshots.size > 128) snapshots.delete(snapshots.keys().next().value);
25689
- return value;
25690
- };
25691
- let peopleCache;
25692
25868
  const pending = /* @__PURE__ */ new Map();
25693
- async function read(cursor, expectedHead) {
25869
+ async function storeAuthors(head) {
25870
+ const text2 = await git(["log", "--format=%x1e%aN%x00%aE%x00%aI", "-z", "--name-only", "--no-renames", "--max-count=20000", head, "--", ".gitifact", ".tryce"]);
25871
+ const folders = /* @__PURE__ */ new Map();
25872
+ const pages = /* @__PURE__ */ new Map();
25873
+ for (const chunk of text2.split("")) {
25874
+ if (!chunk) continue;
25875
+ const [name, email3, date5, ...paths2] = chunk.split("\0");
25876
+ if (!name || !email3 || !date5) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
25877
+ const seen = /* @__PURE__ */ new Set();
25878
+ for (const raw of paths2) {
25879
+ const path3 = raw.replace(/^\n/, "");
25880
+ if (!path3) continue;
25881
+ const folder = /^\.(?:gitifact|tryce)\/(spec\/[^/]+)\//.exec(path3)?.[1];
25882
+ if (folder && !seen.has(folder)) {
25883
+ seen.add(folder);
25884
+ let entry2 = folders.get(folder);
25885
+ if (!entry2) folders.set(folder, entry2 = { people: /* @__PURE__ */ new Map(), count: 0, latest: date5 });
25886
+ if (entry2.count < 2e3) {
25887
+ entry2.count++;
25888
+ tally(entry2.people, name, email3, date5);
25889
+ }
25890
+ }
25891
+ if (path3.startsWith(WIKI_DIR + "/") && !pages.has(path3)) pages.set(path3, date5);
25892
+ }
25893
+ }
25894
+ return { folders, pages };
25895
+ }
25896
+ async function read() {
25694
25897
  const raw = await readConfigFile(root);
25695
25898
  if (!raw || !("schemaVersion" in parseManagedConfig(raw))) throw new SpecPreviewError(t2("specReader.schemaRequired"));
25696
- const base = { head: await readHead() };
25697
- if (cursor > 0 && expectedHead !== base.head) throw new SpecPreviewError(t2("specReader.historyChanged"));
25698
- const current = await readWorkingPreviewState(root);
25699
- const bare = current.specs.map(({ history: _history, ...s }) => ({ ...s, contributors: [], updatedAt: null }));
25700
- const bareDocuments = current.wiki.documents.map((d) => ({ ...d, updatedAt: null }));
25701
- if (!base.head) return browserSpecsV2.parse({ contract: "browser-specs", version: 2, sessionId, head: null, observedAt: (/* @__PURE__ */ new Date()).toISOString(), working: bare.length > 0 || bareDocuments.length > 0, features: bare, documents: bareDocuments, events: [], contributors: [], contributorsLimited: false, nextCursor: null, boundary: false });
25702
- const head = base.head;
25703
- const features = await Promise.all(bare.map(async (feature2) => {
25704
- const folder = feature2.path.replace(/^\.(?:gitifact|tryce)\/(spec\/[^/]+)\/requirements\.md$/, "$1");
25705
- const lines = (await git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=2000", head, "--", `.gitifact/${folder}`, `.tryce/${folder}`])).trim().split("\n").filter(Boolean);
25706
- const people = /* @__PURE__ */ new Map();
25707
- for (const line of lines) {
25708
- const [name, email3, latest] = line.split("\0");
25709
- if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
25710
- const person = people.get(email3);
25711
- if (person) person.commits++;
25712
- else people.set(email3, { name, email: email3, latest, commits: 1 });
25713
- }
25714
- return { ...feature2, contributors: [...people.values()].sort((a, b) => b.commits - a.commits), updatedAt: lines[0]?.split("\0")[2] ?? null };
25715
- }));
25716
- const documents = await Promise.all(bareDocuments.map(async (doc) => ({ ...doc, updatedAt: (await git(["log", "--format=%aI", "--max-count=1", head, "--", doc.path])).trim() || null })));
25717
- const documentDirs = [WIKI_DIR];
25718
- const [rows, dirty] = await Promise.all([
25719
- git([
25720
- "log",
25721
- "--first-parent",
25722
- "--date-order",
25723
- "--format=%H%x00%P%x00%aN%x00%aE%x00%aI%x00%cN%x00%s",
25724
- "--max-count=11",
25725
- "--skip=" + cursor,
25726
- head,
25727
- "--",
25728
- ...[".gitifact", ".tryce"].flatMap((d) => [`:(glob)${d}/spec/*/requirements.md`, `:(glob)${d}/spec/*/design.md`, `:(glob)${d}/spec/*/history.jsonl`]),
25729
- ...documentDirs.flatMap((d) => [`:(glob)${d}/**/*.md`, `:(glob)${d}/history.jsonl`])
25730
- ]),
25731
- git(["status", "--porcelain=v1", "--", ".gitifact/spec", ...documentDirs])
25899
+ const head = await readHead();
25900
+ const [current, dirty, authors, everyone] = await settled([
25901
+ readWorkingPreviewState(root),
25902
+ head ? git(["status", "--porcelain=v1", "--", ".gitifact/spec", WIKI_DIR]) : Promise.resolve(""),
25903
+ head ? storeAuthors(head) : Promise.resolve(void 0),
25904
+ // Git mailmap may change without a new HEAD; refresh names with every observation that carries them.
25905
+ head ? git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=10001", head]) : Promise.resolve("")
25732
25906
  ]);
25733
- {
25734
- const people = /* @__PURE__ */ new Map();
25735
- const lines = (await git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=10001", head])).trim().split("\n").filter(Boolean);
25736
- for (const line of lines.slice(0, 1e4)) {
25737
- const [name, email3, latest] = line.split("\0");
25738
- if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
25739
- const person = people.get(email3);
25740
- if (person) person.commits++;
25741
- else people.set(email3, { name, email: email3, latest, commits: 1 });
25742
- }
25743
- peopleCache = { key: head, data: [...people.values()].sort((a, b) => b.commits - a.commits), limited: lines.length > 1e4 };
25744
- }
25745
- const commits = rows.trim().split("\n").filter(Boolean);
25746
- let boundary = false;
25747
- const groups = await Promise.all(commits.slice(0, 10).map(async (row) => {
25748
- const [commit, parents, author, email3, date5, committer, message] = row.split("\0");
25749
- if (!commit || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
25750
- const after = await snapshot3(commit);
25751
- let before = emptyBundle();
25752
- const parent = parents?.split(" ")[0];
25753
- if (parent) {
25754
- try {
25755
- before = await snapshot3(parent);
25756
- } catch (error62) {
25757
- if (error62 instanceof LegacyBaselineError) boundary = true;
25758
- else throw error62;
25759
- }
25760
- }
25761
- return comparePreviewBundles(before, after).changes.map((c) => ({
25762
- key: commit + ":" + c.id,
25763
- commit,
25764
- author,
25765
- email: email3,
25766
- date: date5,
25767
- committer,
25768
- message,
25769
- id: c.id,
25770
- kind: c.kind,
25771
- types: c.types,
25772
- before: c.before,
25773
- after: c.after,
25774
- reasons: c.reasons.map((r) => r.reason)
25775
- }));
25776
- }));
25777
- if (await readHead() !== head || (await readWorkingPreviewState(root)).stamp !== current.stamp) throw new SpecPreviewError(t2("specReader.projectChanged"));
25778
- return browserSpecsV2.parse({
25907
+ const people = /* @__PURE__ */ new Map();
25908
+ const lines = everyone.trim().split("\n").filter(Boolean);
25909
+ for (const line of lines.slice(0, 1e4)) {
25910
+ const [name, email3, latest] = line.split("\0");
25911
+ if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
25912
+ tally(people, name, email3, latest);
25913
+ }
25914
+ const features = current.specs.map(({ history: _history, ...feature2 }) => {
25915
+ const entry2 = authors?.folders.get(feature2.path.replace(/^\.(?:gitifact|tryce)\/(spec\/[^/]+)\/requirements\.md$/, "$1"));
25916
+ return { ...feature2, contributors: entry2 ? [...entry2.people.values()].sort((a, b) => b.commits - a.commits) : [], updatedAt: entry2?.latest ?? null };
25917
+ });
25918
+ const documents = current.wiki.documents.map((doc) => ({ ...doc, updatedAt: authors?.pages.get(doc.path) ?? null }));
25919
+ if (await readHead() !== head) throw new SpecPreviewError(t2("specReader.projectChanged"));
25920
+ const checkout = browserSpecsV4.parse({
25779
25921
  contract: "browser-specs",
25780
- version: 2,
25922
+ version: 4,
25781
25923
  sessionId,
25782
25924
  head,
25783
25925
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
25784
- working: !!dirty.trim(),
25926
+ working: head ? !!dirty.trim() : features.length > 0 || documents.length > 0,
25785
25927
  features,
25786
25928
  documents,
25787
- events: groups.flat(),
25788
- contributors: peopleCache.data,
25789
- contributorsLimited: peopleCache.limited,
25790
- nextCursor: commits.length > 10 ? cursor + 10 : null,
25791
- boundary
25929
+ contributors: [...people.values()].sort((a, b) => b.commits - a.commits),
25930
+ contributorsLimited: lines.length > 1e4
25931
+ });
25932
+ const search = features.flatMap((f) => [
25933
+ { kind: "feature", ref: f.id, title: f.title, where: f.path.replace(/^\.gitifact\//, ""), body: f.description, featureId: f.id },
25934
+ ...f.requirements.map((r) => ({ kind: "requirement", ref: r.id, title: r.title, where: f.title, body: r.body, featureId: f.id })),
25935
+ ...f.design ? [{ kind: "design", ref: f.id + ":design", title: f.design.title, where: f.title, body: f.design.body, featureId: f.id }] : []
25936
+ ]).concat(documents.map((d) => ({ kind: "document", ref: d.id, title: d.title, where: d.path.replace(/^\.gitifact\/wiki\//, ""), body: d.body, documentId: d.id })));
25937
+ return { checkout, stamp: current.stamp, search };
25938
+ }
25939
+ return () => {
25940
+ let value = pending.get("");
25941
+ if (!value) {
25942
+ value = read().finally(() => pending.delete(""));
25943
+ pending.set("", value);
25944
+ }
25945
+ return value;
25946
+ };
25947
+ }
25948
+
25949
+ // src/server/history/commit-changes.ts
25950
+ var HISTORY_PATHSPECS = [
25951
+ ...STORE_DIRS.flatMap((d) => [`:(glob)${d}/spec/*/requirements.md`, `:(glob)${d}/spec/*/design.md`, `:(glob)${d}/spec/*/history.jsonl`]),
25952
+ `:(glob)${WIKI_DIR}/**/*.md`,
25953
+ `:(glob)${WIKI_HISTORY_PATH}`
25954
+ ];
25955
+ var RECORD_ROOTS = [...STORE_DIRS.map((d) => d + "/spec/"), WIKI_DIR + "/"];
25956
+ var isLegacy = (path3) => RECORD_ROOTS.some((root) => path3.startsWith(root)) && path3.endsWith("/tryce.json");
25957
+ var isZero = (oid3) => /^0+$/.test(oid3);
25958
+ var FORMAT = "%x1e%H%x00%P%x00%aN%x00%aE%x00%aI%x00%cN%x00%s";
25959
+ var BATCH = 100;
25960
+ function createCommitChanges(root, snapshot3) {
25961
+ const reader = specPreviewReader(root);
25962
+ function parseLog(text2) {
25963
+ return text2.split("").filter((chunk) => chunk.length).map((chunk) => {
25964
+ const parts = chunk.split("\0");
25965
+ const [commit, parents, author, email3, date5, committer, message] = parts;
25966
+ if (!commit || parents === void 0 || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
25967
+ const entries = [];
25968
+ for (let i = 7; i < parts.length; i++) {
25969
+ const meta3 = parts[i].replace(/^\n/, "");
25970
+ if (!meta3.startsWith(":")) continue;
25971
+ const [, , oldBlob, newBlob] = meta3.split(" ");
25972
+ const path3 = parts[++i];
25973
+ if (!oldBlob || !newBlob || path3 === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
25974
+ if (recordPathPattern.test(path3) || isLegacy(path3)) entries.push({ oldBlob, newBlob, path: path3 });
25975
+ }
25976
+ return { commit, parent: parents.split(" ")[0] || void 0, author, email: email3, date: date5, committer, message, entries };
25792
25977
  });
25793
25978
  }
25794
- return (cursor = 0, head) => {
25795
- const key = `${cursor}:${head ?? ""}`;
25796
- let value = pending.get(key);
25979
+ function wanted(entries) {
25980
+ const folders = /* @__PURE__ */ new Set();
25981
+ const pages = /* @__PURE__ */ new Set();
25982
+ for (const { path: path3 } of entries) {
25983
+ if (isLegacy(path3)) continue;
25984
+ if (path3.startsWith(WIKI_DIR + "/")) {
25985
+ pages.add(path3);
25986
+ pages.add(WIKI_HISTORY_PATH);
25987
+ continue;
25988
+ }
25989
+ folders.add(path3.replace(/\/[^/]+$/, ""));
25990
+ }
25991
+ return [...[...folders].flatMap((f) => ["requirements.md", "design.md", "history.jsonl"].map((n) => f + "/" + n)), ...pages];
25992
+ }
25993
+ async function readBlobs(names) {
25994
+ const found = /* @__PURE__ */ new Map();
25995
+ if (!names.length) return found;
25996
+ const output2 = await reader.run(["cat-file", "--batch"], Buffer.from(names.join("\n") + "\n"));
25997
+ let offset = 0;
25998
+ let total = 0;
25999
+ for (const name of names) {
26000
+ const end = output2.indexOf(10, offset);
26001
+ if (end < 0) throw new SpecPreviewError(t2("reader.blobBoundary"));
26002
+ const header = output2.subarray(offset, end).toString("utf8");
26003
+ if (header.endsWith(" missing")) {
26004
+ offset = end + 1;
26005
+ continue;
26006
+ }
26007
+ const [, type, sizeText] = header.split(" ");
26008
+ const size = Number(sizeText);
26009
+ if (type !== "blob" || !Number.isSafeInteger(size) || size < 0 || size > 1024 * 1024 || output2[end + size + 1] !== 10) throw new SpecPreviewError(t2("reader.blobShape"));
26010
+ total += size;
26011
+ if (total > 64 * 1024 * 1024) throw new SpecPreviewError(t2("reader.totalLimit"));
26012
+ found.set(name, reader.decode(output2.subarray(end + 1, end + 1 + size)));
26013
+ offset = end + size + 2;
26014
+ }
26015
+ if (offset !== output2.length) throw new SpecPreviewError(t2("reader.blobBoundary"));
26016
+ return found;
26017
+ }
26018
+ const eventsOf = (c, changes) => changes.map((change2) => ({
26019
+ key: c.commit + ":" + change2.id,
26020
+ commit: c.commit,
26021
+ author: c.author,
26022
+ email: c.email,
26023
+ date: c.date,
26024
+ committer: c.committer,
26025
+ message: c.message,
26026
+ id: change2.id,
26027
+ kind: change2.kind,
26028
+ types: change2.types,
26029
+ before: change2.before,
26030
+ after: change2.after,
26031
+ reasons: change2.reasons.map((r) => r.reason)
26032
+ }));
26033
+ async function wholeStore(c) {
26034
+ const after = await snapshot3(c.commit);
26035
+ let before = emptyBundle();
26036
+ let boundary = false;
26037
+ if (c.parent) {
26038
+ try {
26039
+ before = await snapshot3(c.parent);
26040
+ } catch (error62) {
26041
+ if (error62 instanceof LegacyBaselineError) boundary = true;
26042
+ else throw error62;
26043
+ }
26044
+ }
26045
+ return { commit: c.commit, events: eventsOf(c, comparePreviewBundles(before, after).changes), boundary };
26046
+ }
26047
+ async function batch(commits) {
26048
+ const names = /* @__PURE__ */ new Map();
26049
+ for (const c of commits.filter((c2) => !c2.entries.some((e) => isLegacy(e.path) && !isZero(e.newBlob)))) {
26050
+ const files = wanted(c.entries);
26051
+ const boundary = c.entries.some((e) => isLegacy(e.path) && !isZero(e.oldBlob));
26052
+ names.set(c, { after: files.map((f) => c.commit + ":" + f), before: c.parent && !boundary ? files.map((f) => c.parent + ":" + f) : [], boundary });
26053
+ }
26054
+ let blobs;
26055
+ try {
26056
+ blobs = await readBlobs([...names.values()].flatMap((n) => [...n.before, ...n.after]));
26057
+ } catch {
26058
+ blobs = void 0;
26059
+ }
26060
+ const result = [];
26061
+ for (const c of commits) {
26062
+ let value;
26063
+ const want = names.get(c);
26064
+ if (want && blobs) {
26065
+ try {
26066
+ const side = (list, rev) => new Map(list.filter((name) => blobs.has(name)).map((name) => [name.slice(rev.length + 1), blobs.get(name)]));
26067
+ const after = parsePreviewBundle(side(want.after, c.commit));
26068
+ const before = want.before.length ? parsePreviewBundle(side(want.before, c.parent)) : emptyBundle();
26069
+ value = { commit: c.commit, events: eventsOf(c, comparePreviewBundles(before, after).changes), boundary: want.boundary };
26070
+ } catch {
26071
+ value = void 0;
26072
+ }
26073
+ }
26074
+ result.push(value ?? await wholeStore(c));
26075
+ }
26076
+ return result;
26077
+ }
26078
+ return {
26079
+ /** The commits of `head`'s first-parent history that touched records, newest first. One Git process. */
26080
+ async lineage(head) {
26081
+ const text2 = reader.decode(await reader.run(["rev-list", "--first-parent", head, "--", ...HISTORY_PATHSPECS]));
26082
+ return text2.split("\n").filter(Boolean);
26083
+ },
26084
+ /** The changes of the given commits, in the given order; two Git processes per hundred commits. */
26085
+ async of(commits) {
26086
+ const out = [];
26087
+ for (let i = 0; i < commits.length; i += BATCH) {
26088
+ const slice = commits.slice(i, i + BATCH);
26089
+ const raw = parseLog(reader.decode(await reader.run(
26090
+ ["log", "--stdin", "--no-walk=unsorted", "--diff-merges=first-parent", "--raw", "-z", "--no-renames", "--no-abbrev", `--format=${FORMAT}`],
26091
+ Buffer.from(slice.join("\n") + "\n")
26092
+ )));
26093
+ const byCommit = new Map(raw.map((c) => [c.commit, c]));
26094
+ const missing2 = slice.find((oid3) => !byCommit.has(oid3));
26095
+ if (missing2) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
26096
+ out.push(...await batch(slice.map((oid3) => byCommit.get(oid3))));
26097
+ }
26098
+ return out;
26099
+ }
26100
+ };
26101
+ }
26102
+
26103
+ // src/server/history/index-database.ts
26104
+ import { DatabaseSync } from "node:sqlite";
26105
+ import { mkdir as mkdir3, rm } from "node:fs/promises";
26106
+ import { join as join5 } from "node:path";
26107
+ var INDEX_FORMAT = 1;
26108
+ var SCHEMA = `
26109
+ -- Commits already read, and whether the commit's parent was legacy JSON the history does not read past.
26110
+ CREATE TABLE commits (oid TEXT PRIMARY KEY, boundary INTEGER NOT NULL);
26111
+ -- One row per change. 'row' is the list shape as JSON; 'detail' the text on both sides.
26112
+ CREATE TABLE changes (
26113
+ key TEXT PRIMARY KEY, oid TEXT NOT NULL, ord INTEGER NOT NULL,
26114
+ id TEXT NOT NULL, kind TEXT NOT NULL, types TEXT NOT NULL, email TEXT NOT NULL, date TEXT NOT NULL,
26115
+ before_spec TEXT, after_spec TEXT, needle TEXT NOT NULL, row TEXT NOT NULL, detail TEXT NOT NULL);
26116
+ CREATE INDEX changes_by_commit ON changes (oid, ord);
26117
+ -- The commits of one HEAD's first-parent history that touched records, newest first (pos 0).
26118
+ CREATE TABLE lineage (head TEXT NOT NULL, pos INTEGER NOT NULL, oid TEXT NOT NULL, PRIMARY KEY (head, pos));
26119
+ CREATE INDEX lineage_by_commit ON lineage (head, oid);
26120
+ CREATE TABLE heads (head TEXT PRIMARY KEY, seen INTEGER NOT NULL);
26121
+ -- Which checkout of which worktree the search rows describe.
26122
+ CREATE TABLE checkouts (scope TEXT PRIMARY KEY, stamp TEXT NOT NULL);
26123
+ -- Everything the search box finds. The searched columns hold lower-cased text; trigram lets LIKE '%...%' use the
26124
+ -- index from three characters on and scan below that. The rest is carried for display and navigation.
26125
+ CREATE VIRTUAL TABLE search USING fts5(
26126
+ scope UNINDEXED, kind UNINDEXED, ref UNINDEXED, oid UNINDEXED, payload UNINDEXED,
26127
+ title, place, body, tokenize = 'trigram');
26128
+ `;
26129
+ function prepare(db) {
26130
+ db.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL;");
26131
+ const version2 = db.prepare("PRAGMA user_version").get().user_version;
26132
+ if (version2 === INDEX_FORMAT) return;
26133
+ db.exec("BEGIN IMMEDIATE");
26134
+ try {
26135
+ for (const { name, type } of db.prepare("SELECT name, type FROM sqlite_master WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'search_%'").all()) {
26136
+ db.exec(`DROP ${type === "view" ? "VIEW" : "TABLE"} IF EXISTS "${name}"`);
26137
+ }
26138
+ db.exec(SCHEMA);
26139
+ db.exec(`PRAGMA user_version = ${INDEX_FORMAT}`);
26140
+ db.exec("COMMIT");
26141
+ } catch (error62) {
26142
+ db.exec("ROLLBACK");
26143
+ throw error62;
26144
+ }
26145
+ }
26146
+ function createIndexDatabase(root) {
26147
+ let path3;
26148
+ let memory;
26149
+ const usable = (file2) => {
26150
+ try {
26151
+ const probe = new DatabaseSync(file2);
26152
+ try {
26153
+ prepare(probe);
26154
+ } finally {
26155
+ probe.close();
26156
+ }
26157
+ return true;
26158
+ } catch {
26159
+ return false;
26160
+ }
26161
+ };
26162
+ const locate = () => path3 ??= (async () => {
26163
+ try {
26164
+ const git = specPreviewReader(root);
26165
+ const common = git.decode(await git.run(["rev-parse", "--path-format=absolute", "--git-common-dir"])).trim();
26166
+ const folder = join5(common, "gitifact");
26167
+ await mkdir3(folder, { recursive: true });
26168
+ const file2 = join5(folder, "index.sqlite");
26169
+ if (usable(file2)) return file2;
26170
+ for (const leftover of [file2, file2 + "-wal", file2 + "-shm"]) await rm(leftover, { force: true });
26171
+ return usable(file2) ? file2 : void 0;
26172
+ } catch {
26173
+ return void 0;
26174
+ }
26175
+ })();
26176
+ return {
26177
+ /** Runs `use` on an open database. Everything inside is synchronous, so the connection never outlives the call. */
26178
+ async with(use) {
26179
+ const file2 = await locate();
26180
+ if (!file2) {
26181
+ if (!memory) {
26182
+ memory = new DatabaseSync(":memory:");
26183
+ prepare(memory);
26184
+ }
26185
+ return use(memory);
26186
+ }
26187
+ const db = new DatabaseSync(file2);
26188
+ try {
26189
+ prepare(db);
26190
+ return use(db);
26191
+ } finally {
26192
+ db.close();
26193
+ }
26194
+ },
26195
+ /** Where the index is kept, or undefined when it lives in memory. */
26196
+ location: () => locate()
26197
+ };
26198
+ }
26199
+ function transaction(db, write) {
26200
+ db.exec("BEGIN IMMEDIATE");
26201
+ try {
26202
+ const value = write();
26203
+ db.exec("COMMIT");
26204
+ return value;
26205
+ } catch (error62) {
26206
+ db.exec("ROLLBACK");
26207
+ throw error62;
26208
+ }
26209
+ }
26210
+
26211
+ // src/server/history/search-text.ts
26212
+ function plain(body) {
26213
+ return body.replace(/```[\s\S]*?```/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/^\s*[#>]+\s*/gm, " ").replace(/^\s*[-*+]\s+/gm, " ").replace(/^\s*\|/gm, " ").replace(/\|/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/[*_`]/g, "").replace(/\s+/g, " ").trim();
26214
+ }
26215
+ function snippet(text2, query) {
26216
+ const at = text2.toLowerCase().indexOf(query);
26217
+ if (at < 0) return text2.slice(0, 90);
26218
+ const from = Math.max(0, at - 30);
26219
+ return (from > 0 ? "\u2026" : "") + text2.slice(from, at + query.length + 70).trim() + (at + query.length + 70 < text2.length ? "\u2026" : "");
26220
+ }
26221
+ var containing = (query) => "%" + query.replace(/[\\%_]/g, (c) => "\\" + c) + "%";
26222
+
26223
+ // src/server/history/history-index.ts
26224
+ var listed = (e) => {
26225
+ const reference2 = (s) => s ? { id: s.id, title: s.title, specId: s.specId, path: s.path } : null;
26226
+ return { ...e, before: reference2(e.before), after: reference2(e.after) };
26227
+ };
26228
+ var titleOf = (e) => (e.after ?? e.before)?.title ?? e.id;
26229
+ var DAY = 864e5;
26230
+ var KEPT_HEADS = 4;
26231
+ var RECENT_COMMITS = 3;
26232
+ var RECENT_CHANGES = 12;
26233
+ function createHistoryIndex(root, snapshot3) {
26234
+ const changes = createCommitChanges(root, snapshot3);
26235
+ const database = createIndexDatabase(root);
26236
+ const building = /* @__PURE__ */ new Map();
26237
+ const built = /* @__PURE__ */ new Set();
26238
+ function insert(db, commits) {
26239
+ const commit = db.prepare("INSERT OR IGNORE INTO commits (oid, boundary) VALUES (?, ?)");
26240
+ const change2 = db.prepare("INSERT OR IGNORE INTO changes (key, oid, ord, id, kind, types, email, date, before_spec, after_spec, needle, row, detail) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
26241
+ const search = db.prepare("INSERT INTO search (scope, kind, ref, oid, payload, title, place, body) VALUES (?,?,?,?,?,?,?,?)");
26242
+ transaction(db, () => {
26243
+ for (const c of commits) {
26244
+ if (!Number(commit.run(c.commit, c.boundary ? 1 : 0).changes)) continue;
26245
+ c.events.forEach((e, ord) => {
26246
+ change2.run(
26247
+ e.key,
26248
+ e.commit,
26249
+ ord,
26250
+ e.id,
26251
+ e.kind,
26252
+ e.types.join(","),
26253
+ e.email,
26254
+ e.date,
26255
+ e.before?.specId ?? null,
26256
+ e.after?.specId ?? null,
26257
+ [e.id, e.before?.title ?? "", e.after?.title ?? ""].join(" ").toLowerCase(),
26258
+ JSON.stringify(listed(e)),
26259
+ JSON.stringify({ before: e.before, after: e.after })
26260
+ );
26261
+ const line = e.reasons.length ? e.reasons.join(" \xB7 ") : e.message;
26262
+ const where2 = e.commit.slice(0, 7) + " \xB7 " + e.author;
26263
+ search.run(
26264
+ "history",
26265
+ "history",
26266
+ e.key,
26267
+ e.commit,
26268
+ JSON.stringify({ title: titleOf(e), where: where2, line }),
26269
+ titleOf(e).toLowerCase(),
26270
+ where2.toLowerCase(),
26271
+ [line, e.message, e.id].join(" ").toLowerCase()
26272
+ );
26273
+ });
26274
+ }
26275
+ });
26276
+ }
26277
+ async function build(head) {
26278
+ const lineage = await changes.lineage(head);
26279
+ const known = await database.with((db) => new Set(db.prepare("SELECT oid FROM commits").all().map((r) => r.oid)));
26280
+ const missing2 = lineage.filter((oid3) => !known.has(oid3));
26281
+ for (let i = 0; i < missing2.length; i += 100) {
26282
+ const read = await changes.of(missing2.slice(i, i + 100));
26283
+ await database.with((db) => insert(db, read));
26284
+ }
26285
+ await database.with((db) => transaction(db, () => {
26286
+ db.prepare("DELETE FROM lineage WHERE head = ?").run(head);
26287
+ const row = db.prepare("INSERT INTO lineage (head, pos, oid) VALUES (?, ?, ?)");
26288
+ lineage.forEach((oid3, pos) => row.run(head, pos, oid3));
26289
+ db.prepare("INSERT INTO heads (head, seen) VALUES (?, ?) ON CONFLICT (head) DO UPDATE SET seen = excluded.seen").run(head, Date.now());
26290
+ for (const { head: old } of db.prepare("SELECT head FROM heads ORDER BY seen DESC LIMIT -1 OFFSET ?").all(KEPT_HEADS)) {
26291
+ db.prepare("DELETE FROM lineage WHERE head = ?").run(old);
26292
+ db.prepare("DELETE FROM heads WHERE head = ?").run(old);
26293
+ }
26294
+ }));
26295
+ }
26296
+ function ensure(head) {
26297
+ if (built.has(head)) return Promise.resolve();
26298
+ let pending = building.get(head);
26299
+ if (!pending) {
26300
+ pending = build(head).then(() => {
26301
+ built.add(head);
26302
+ }).finally(() => building.delete(head));
26303
+ building.set(head, pending);
26304
+ }
26305
+ return pending;
26306
+ }
26307
+ function where(filter) {
26308
+ const clauses = [];
26309
+ const params = [];
26310
+ if (filter.kind) {
26311
+ clauses.push("instr(',' || c.types || ',', ?) > 0");
26312
+ params.push("," + filter.kind + ",");
26313
+ }
26314
+ if (filter.document) {
26315
+ clauses.push("c.kind = ?");
26316
+ params.push(filter.document);
26317
+ }
26318
+ if (filter.feature) {
26319
+ clauses.push("(c.before_spec = ? OR c.after_spec = ?)");
26320
+ params.push(filter.feature, filter.feature);
26321
+ }
26322
+ if (filter.author) {
26323
+ clauses.push("c.email = ?");
26324
+ params.push(filter.author);
26325
+ }
26326
+ if (filter.q?.trim()) {
26327
+ clauses.push("instr(c.needle, ?) > 0");
26328
+ params.push(filter.q.trim().toLowerCase());
26329
+ }
26330
+ return { sql: clauses.map((c) => " AND " + c).join(""), params };
26331
+ }
26332
+ return {
26333
+ ensure,
26334
+ /** One page of the changes that match, newest first, with how many match in all. */
26335
+ async page(head, filter, offset, limit) {
26336
+ await ensure(head);
26337
+ return database.with((db) => {
26338
+ const { sql, params } = where(filter);
26339
+ const from = "FROM lineage l JOIN changes c ON c.oid = l.oid WHERE l.head = ?" + sql;
26340
+ const total = Number(db.prepare("SELECT count(*) AS n " + from).get(head, ...params).n);
26341
+ const rows = db.prepare(`SELECT c.row ${from} ORDER BY l.pos, c.ord LIMIT ? OFFSET ?`).all(head, ...params, limit, offset);
26342
+ const boundary = !!db.prepare("SELECT 1 FROM lineage l JOIN commits m ON m.oid = l.oid WHERE l.head = ? AND m.boundary = 1 LIMIT 1").get(head);
26343
+ return { total, events: rows.map((r) => JSON.parse(r.row)), boundary };
26344
+ });
26345
+ },
26346
+ /** Counts over all of history and its newest commits, for the overview. */
26347
+ async summary(head) {
26348
+ await ensure(head);
26349
+ return database.with((db) => {
26350
+ const from = "FROM lineage l JOIN changes c ON c.oid = l.oid WHERE l.head = ?";
26351
+ const count2 = (type) => Number(db.prepare(`SELECT count(*) AS n ${from} AND instr(',' || c.types || ',', ?) > 0`).get(head, "," + type + ",").n);
26352
+ const total = Number(db.prepare(`SELECT count(*) AS n ${from}`).get(head).n);
26353
+ const commits = db.prepare(`SELECT l.oid AS oid, max(c.date) AS date, count(*) AS n ${from} GROUP BY l.pos, l.oid ORDER BY l.pos`).all(head);
26354
+ const newest = Math.max(0, ...commits.map((c) => Date.parse(c.date)).filter(Number.isFinite));
26355
+ const pulse = commits.filter((c) => Date.parse(c.date) >= newest - 22 * DAY).map((c) => ({ date: c.date, count: Number(c.n) }));
26356
+ const recent = commits.slice(0, RECENT_COMMITS).map((c) => ({
26357
+ commit: c.oid,
26358
+ count: Number(c.n),
26359
+ events: db.prepare("SELECT row FROM changes WHERE oid = ? ORDER BY ord LIMIT ?").all(c.oid, RECENT_CHANGES).map((r) => JSON.parse(r.row))
26360
+ }));
26361
+ return { total, byType: { created: count2("created"), modified: count2("modified"), moved: count2("moved"), deleted: count2("deleted") }, pulse, recent };
26362
+ });
26363
+ },
26364
+ /** One change with the text on both sides; a commit the index has not read yet is read now. */
26365
+ async change(key) {
26366
+ const lookup = () => database.with((db) => db.prepare("SELECT row, detail FROM changes WHERE key = ?").get(key));
26367
+ let found = await lookup();
26368
+ if (!found) {
26369
+ const commit = key.slice(0, key.indexOf(":"));
26370
+ const known = await database.with((db) => !!db.prepare("SELECT 1 FROM commits WHERE oid = ?").get(commit));
26371
+ if (known) return void 0;
26372
+ const read = await changes.of([commit]).catch(() => void 0);
26373
+ if (!read) return void 0;
26374
+ await database.with((db) => insert(db, read));
26375
+ found = await lookup();
26376
+ }
26377
+ if (!found) return void 0;
26378
+ const detail = JSON.parse(found.detail);
26379
+ return { event: JSON.parse(found.row), before: detail.before, after: detail.after };
26380
+ },
26381
+ /** Replaces the search rows of one worktree's checkout when it changed since they were written. */
26382
+ async syncCheckout(scope, stamp, documents) {
26383
+ await database.with((db) => {
26384
+ const current = db.prepare("SELECT stamp FROM checkouts WHERE scope = ?").get(scope);
26385
+ if (current?.stamp === stamp) return;
26386
+ transaction(db, () => {
26387
+ db.prepare("DELETE FROM search WHERE scope = ?").run(scope);
26388
+ const row = db.prepare("INSERT INTO search (scope, kind, ref, oid, payload, title, place, body) VALUES (?,?,?,?,?,?,?,?)");
26389
+ for (const d of documents) {
26390
+ const body = plain(d.body);
26391
+ row.run(
26392
+ scope,
26393
+ d.kind,
26394
+ d.ref,
26395
+ null,
26396
+ JSON.stringify({ title: d.title, where: d.where, body, featureId: d.featureId, documentId: d.documentId }),
26397
+ d.title.toLowerCase(),
26398
+ d.where.toLowerCase(),
26399
+ body.toLowerCase()
26400
+ );
26401
+ }
26402
+ db.prepare("INSERT INTO checkouts (scope, stamp) VALUES (?, ?) ON CONFLICT (scope) DO UPDATE SET stamp = excluded.stamp").run(scope, stamp);
26403
+ });
26404
+ });
26405
+ },
26406
+ /**
26407
+ * Records whose title, place or text holds the query. The checkout comes first — a title match before a place
26408
+ * match before a text match — then past changes of `head`'s history, newest first.
26409
+ */
26410
+ async search(scope, head, raw) {
26411
+ const query = raw.trim().toLowerCase();
26412
+ if (!query) return [];
26413
+ if (head) await ensure(head);
26414
+ return database.with((db) => {
26415
+ const literal2 = /[\\%_]/.test(query);
26416
+ const match = (column) => literal2 ? `instr(${column}, ?) > 0` : `${column} LIKE ?`;
26417
+ const needle = literal2 ? query : containing(query);
26418
+ const found = db.prepare(`SELECT kind, ref, payload, title, place, body FROM search WHERE scope = ? AND (${match("title")} OR ${match("place")} OR ${match("body")}) LIMIT 400`).all(scope, needle, needle, needle);
26419
+ const documents = found.map((r) => {
26420
+ const at = r.title.indexOf(query);
26421
+ const rank = at === 0 ? 0 : at > 0 ? 1 : r.place.includes(query) ? 2 : 3;
26422
+ const p = JSON.parse(r.payload);
26423
+ const hit = {
26424
+ id: r.ref,
26425
+ kind: r.kind,
26426
+ title: p.title,
26427
+ where: p.where,
26428
+ line: snippet(p.body, query),
26429
+ ...p.featureId ? { featureId: p.featureId } : {},
26430
+ ...p.documentId ? { documentId: p.documentId } : {}
26431
+ };
26432
+ return { rank, hit };
26433
+ }).sort((a, b) => a.rank - b.rank || a.hit.title.localeCompare(b.hit.title)).slice(0, 24).map((r) => r.hit);
26434
+ const past = !head ? [] : db.prepare(`SELECT s.ref AS ref, s.payload AS payload FROM search s JOIN lineage l ON l.head = ? AND l.oid = s.oid
26435
+ WHERE s.scope = 'history' AND (${match("s.title")} OR ${match("s.body")}) ORDER BY l.pos LIMIT 8`).all(head, needle, needle).map((r) => {
26436
+ const p = JSON.parse(r.payload);
26437
+ return { id: r.ref, kind: "history", title: p.title, where: p.where, line: snippet(p.line, query), key: r.ref };
26438
+ });
26439
+ return [...documents, ...past];
26440
+ });
26441
+ }
26442
+ };
26443
+ }
26444
+
26445
+ // src/server/routes/record-routes.ts
26446
+ var PAGE = 50;
26447
+ function recordRoutes(root, sessionId, env) {
26448
+ const reader = specPreviewReader(root);
26449
+ const snapshots = /* @__PURE__ */ new Map();
26450
+ const snapshot3 = (oid3) => {
26451
+ let value = snapshots.get(oid3);
25797
26452
  if (!value) {
25798
- value = read(cursor, head).finally(() => pending.delete(key));
25799
- pending.set(key, value);
26453
+ value = reader.readBundle(oid3).catch((e) => {
26454
+ snapshots.delete(oid3);
26455
+ throw e;
26456
+ });
26457
+ snapshots.set(oid3, value);
25800
26458
  }
26459
+ if (snapshots.size > 128) snapshots.delete(snapshots.keys().next().value);
25801
26460
  return value;
25802
26461
  };
26462
+ const readCheckout = createCheckoutReader(root, sessionId, env);
26463
+ const history = createHistoryIndex(root, snapshot3);
26464
+ const scope = "checkout:" + root;
26465
+ const unreadable = t2("server.specsUnreadable");
26466
+ let synced;
26467
+ const checkout = async () => {
26468
+ const read = await readCheckout();
26469
+ synced = history.syncCheckout(scope, read.stamp, read.search);
26470
+ await synced;
26471
+ return read.checkout;
26472
+ };
26473
+ return [
26474
+ route({ method: "GET", path: "/api/v1/specs", session: true, unreadable, handle: async () => {
26475
+ return ok(await checkout());
26476
+ } }),
26477
+ route({ method: "GET", path: "/api/v1/history", session: true, query: browserHistoryQueryV1, unreadable, handle: async ({ query }) => {
26478
+ const offset = query.offset ?? 0;
26479
+ const page = await history.page(query.head, { kind: query.kind, document: query.document, feature: query.feature, author: query.author, q: query.q }, offset, query.limit ?? PAGE);
26480
+ return ok(browserHistoryV1.parse({ contract: "browser-history", version: 1, sessionId, head: query.head, offset, ...page }));
26481
+ } }),
26482
+ route({ method: "GET", path: "/api/v1/history/summary", session: true, query: browserHistorySummaryQueryV1, unreadable, handle: async ({ query }) => ok(browserHistorySummaryV1.parse({ contract: "browser-history-summary", version: 1, sessionId, head: query.head, ...await history.summary(query.head) })) }),
26483
+ route({ method: "GET", path: "/api/v1/change", session: true, query: browserChangeQueryV1, unreadable, handle: async ({ query }) => {
26484
+ const change2 = await history.change(query.key);
26485
+ if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.changeNotFound"));
26486
+ return ok(browserChangeV1.parse({ contract: "browser-change", version: 1, sessionId, ...change2 }));
26487
+ } }),
26488
+ route({ method: "GET", path: "/api/v1/search", session: true, query: browserSearchQueryV1, unreadable, handle: async ({ query }) => {
26489
+ await (synced ?? checkout()).catch(() => void 0);
26490
+ return ok(browserSearchV1.parse({ contract: "browser-search", version: 1, sessionId, query: query.q, hits: await history.search(scope, query.head ?? null, query.q) }));
26491
+ } })
26492
+ ];
26493
+ }
26494
+
26495
+ // src/server/routes/asset-routes.ts
26496
+ import { lstat as lstat4, readFile as readFile4 } from "node:fs/promises";
26497
+ import { join as join6 } from "node:path";
26498
+ function assetRoutes(root) {
26499
+ return [
26500
+ route({ method: "GET", path: "/api/v1/assets/*", session: false, handle: async ({ path: path3, response }) => {
26501
+ const relative = path3.slice("/api/v1/assets/".length);
26502
+ const assetPath = ASSETS_DIR + "/" + relative;
26503
+ if (!isAssetPath(assetPath)) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
26504
+ const file2 = join6(root, ...assetPath.split("/"));
26505
+ const stat3 = await lstat4(file2).catch(() => void 0);
26506
+ if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 20 * 1024 * 1024) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
26507
+ const bytes = await readFile4(file2);
26508
+ const extension = assetExtension(relative);
26509
+ const inline = ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension);
26510
+ response.writeHead(200, {
26511
+ "Content-Type": contentType("." + extension),
26512
+ "Cache-Control": "no-cache",
26513
+ "Content-Length": bytes.length,
26514
+ "Content-Security-Policy": "default-src 'none'; sandbox",
26515
+ "Content-Disposition": inline ? "inline" : 'attachment; filename="' + encodeURIComponent(relative.split("/").pop()) + '"'
26516
+ });
26517
+ response.end(bytes);
26518
+ return void 0;
26519
+ } })
26520
+ ];
25803
26521
  }
25804
26522
 
25805
26523
  // src/server/browser-server.ts
25806
- var readBundledChangelog = (language) => readFile4(new URL("./i18n/" + language + "/changelog.md", import.meta.url), "utf8").catch((error62) => {
26524
+ var readBundledChangelog = (language) => readFile5(new URL("./i18n/" + language + "/changelog.md", import.meta.url), "utf8").catch((error62) => {
25807
26525
  if (error62.code === "ENOENT") return null;
25808
26526
  throw error62;
25809
26527
  });
@@ -25828,127 +26546,24 @@ async function startBrowserServer(options) {
25828
26546
  }
25829
26547
  const store = createStatusSession(initial, () => read(controller.signal), options.cliVersion);
25830
26548
  const sessionId = store.session.sessionId;
25831
- const readChangelog = options.readChangelog ?? readBundledChangelog;
26549
+ const root = initial.repository.rootPath;
26550
+ const routes = [
26551
+ ...projectRoutes(store, options.readChangelog ?? readBundledChangelog),
26552
+ ...recordRoutes(root, sessionId, options.env),
26553
+ ...assetRoutes(root)
26554
+ ];
25832
26555
  let updatePending;
25833
26556
  let closing = false;
25834
26557
  let origin = "";
25835
- const readSpecs = createSpecBrowserReader(initial.repository.rootPath, sessionId, options.env);
25836
- function json2(response, status, value) {
25837
- response.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
25838
- response.end(JSON.stringify(value) + "\n");
25839
- }
25840
- function fail8(response, status, code, message) {
25841
- json2(response, status, browserHttpErrorV1.parse({ contract: "browser-http-error", version: 1, error: { code, message } }));
25842
- }
25843
- async function handle(request, response) {
25844
- response.setHeader("X-Content-Type-Options", "nosniff");
25845
- response.setHeader("X-Frame-Options", "DENY");
25846
- response.setHeader("Referrer-Policy", "no-referrer");
25847
- response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'");
25848
- if (closing) return fail8(response, 503, "SERVER_CLOSING", t2("server.closing"));
25849
- if (request.headers.host !== new URL(origin).host) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenHost"));
25850
- const requestOrigin = request.headers.origin;
25851
- const allowedOrigin = requestOrigin === origin || options.dev && requestOrigin === "http://127.0.0.1:5173";
25852
- if (requestOrigin && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenOrigin"));
25853
- const raw = request.url ?? "/";
25854
- if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
25855
- let url2;
25856
- let path3;
25857
- try {
25858
- url2 = new URL(raw, origin);
25859
- path3 = decodeURIComponent(url2.pathname);
25860
- } catch {
25861
- return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
25862
- }
25863
- if (path3.includes("\0") || path3.includes("\\") || path3.split("/").some((part) => part === ".." || part === ".")) {
25864
- return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
25865
- }
25866
- if (request.headers["transfer-encoding"] || request.headers["content-length"] && request.headers["content-length"] !== "0") {
25867
- request.resume();
25868
- return fail8(response, 400, "BAD_REQUEST", t2("server.noBody"));
25869
- }
25870
- const api = path3 === "/api" || path3.startsWith("/api/");
25871
- if (api) {
25872
- if (request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.crossSite"));
25873
- if (url2.search && path3 !== "/api/v1/specs" && path3 !== "/api/v1/changelog") return fail8(response, 400, "BAD_REQUEST", t2("server.noQuery"));
25874
- if (path3.startsWith("/api/v1/assets/")) {
25875
- const relative = path3.slice("/api/v1/assets/".length);
25876
- const assetPath2 = ASSETS_DIR + "/" + relative;
25877
- if (request.method !== "GET") {
25878
- response.setHeader("Allow", "GET");
25879
- return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
25880
- }
25881
- if (!isAssetPath(assetPath2)) return fail8(response, 404, "NOT_FOUND", t2("server.assetNotFound"));
25882
- const file2 = join5(initial.repository.rootPath, ...assetPath2.split("/"));
25883
- const stat3 = await lstat4(file2).catch(() => void 0);
25884
- if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 20 * 1024 * 1024) return fail8(response, 404, "NOT_FOUND", t2("server.assetNotFound"));
25885
- const bytes = await readFile4(file2);
25886
- const extension = assetExtension(relative);
25887
- const inline = ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension);
25888
- response.writeHead(200, {
25889
- "Content-Type": contentType("." + extension),
25890
- "Cache-Control": "no-cache",
25891
- "Content-Length": bytes.length,
25892
- "Content-Security-Policy": "default-src 'none'; sandbox",
25893
- "Content-Disposition": inline ? "inline" : 'attachment; filename="' + encodeURIComponent(relative.split("/").pop()) + '"'
25894
- });
25895
- response.end(bytes);
25896
- return;
25897
- }
25898
- const method = path3 === "/api/v1/status/refresh" ? "POST" : "GET";
25899
- if (!["/api/v1/session", "/api/v1/status", "/api/v1/status/refresh", "/api/v1/specs", "/api/v1/changelog"].includes(path3)) return fail8(response, 404, "NOT_FOUND", t2("server.apiNotFound"));
25900
- if (request.method !== method) {
25901
- response.setHeader("Allow", method);
25902
- return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
25903
- }
25904
- if (path3 === "/api/v1/session") return json2(response, 200, store.session);
25905
- if (request.headers["x-gitifact-session"] !== sessionId) return fail8(response, 409, "SESSION_CHANGED", t2("server.sessionChanged"));
25906
- if (path3 === "/api/v1/specs") {
25907
- const cursor = url2.searchParams.get("cursor") ?? "0";
25908
- const head = url2.searchParams.get("head");
25909
- if ([...url2.searchParams.keys()].some((k) => !["cursor", "head"].includes(k)) || url2.searchParams.getAll("cursor").length > 1 || url2.searchParams.getAll("head").length > 1 || !/^(0|[1-9]\d{0,5})$/.test(cursor) || head !== null && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) return fail8(response, 400, "BAD_REQUEST", t2("server.badRange"));
25910
- try {
25911
- json2(response, 200, await readSpecs(Number(cursor), head ?? void 0));
25912
- } catch (error62) {
25913
- fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.specsUnreadable"));
25914
- }
25915
- return;
25916
- }
25917
- if (path3 === "/api/v1/changelog") {
25918
- const language = url2.searchParams.get("lang") ?? defaultLanguage2;
25919
- if ([...url2.searchParams.keys()].some((key) => key !== "lang") || url2.searchParams.getAll("lang").length > 1 || !/^[a-z]{2}(?:-[A-Z]{2})?$/.test(language)) return fail8(response, 400, "BAD_REQUEST", t2("server.badLanguage"));
25920
- try {
25921
- const own2 = await readChangelog(language);
25922
- const text2 = own2 ?? (language === defaultLanguage2 ? null : await readChangelog(defaultLanguage2));
25923
- if (text2 === null) return fail8(response, 404, "NOT_FOUND", t2("server.changelogNotFound"));
25924
- json2(response, 200, changelogV1.parse({ contract: "changelog", version: 1, language: own2 === null ? defaultLanguage2 : language, fallback: own2 === null, entries: parseChangelog(text2) }));
25925
- } catch (error62) {
25926
- fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.changelogUnreadable"));
25927
- }
25928
- return;
25929
- }
25930
- if (method === "POST" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.refreshOrigin"));
25931
- const value = method === "POST" ? await store.refresh() : store.latest;
25932
- if (!response.destroyed) json2(response, value.ok ? 200 : 503, value);
25933
- return;
25934
- }
25935
- if (request.method !== "GET" && request.method !== "HEAD") {
25936
- response.setHeader("Allow", "GET, HEAD");
25937
- return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
25938
- }
25939
- let asset = assets.get(path3 === "/" ? "/index.html" : path3);
25940
- let assetPath = path3 === "/" ? "/index.html" : path3;
25941
- if (!asset && !path3.startsWith("/assets/") && !path3.split("/").some((part) => part.includes(".")) && request.headers.accept?.includes("text/html")) {
25942
- asset = assets.get("/index.html");
25943
- assetPath = "/index.html";
25944
- }
25945
- if (!asset) return fail8(response, 404, "NOT_FOUND", t2("server.fileNotFound"));
25946
- response.writeHead(200, { "Content-Type": contentType(assetPath), "Cache-Control": "no-cache", "Content-Length": asset.length });
25947
- response.end(request.method === "HEAD" ? void 0 : asset);
25948
- }
25949
26558
  const server = createServer({ requestTimeout: 5e3, headersTimeout: 5e3, maxHeaderSize: 8192 }, (request, response) => {
25950
- void handle(request, response).catch(() => {
25951
- if (!response.headersSent && !response.destroyed) fail8(response, 500, "INTERNAL_ERROR", t2("server.internal"));
26559
+ void (async () => {
26560
+ if (closing) return fail4(response, 503, "SERVER_CLOSING", t2("server.closing"));
26561
+ const admitted = admit(request, response, origin, !!options.dev);
26562
+ if (!admitted) return;
26563
+ if (admitted.api) return dispatch(routes, sessionId, admitted.url, admitted.path, request, response, admitted.allowedOrigin);
26564
+ return serveStatic(request, response, admitted.path, assets);
26565
+ })().catch(() => {
26566
+ if (!response.headersSent && !response.destroyed) fail4(response, 500, "INTERNAL_ERROR", t2("server.internal"));
25952
26567
  else response.destroy();
25953
26568
  });
25954
26569
  });
@@ -26055,13 +26670,13 @@ async function runBrowser(options, version2) {
26055
26670
  }
26056
26671
 
26057
26672
  // src/commands/spec-init.ts
26058
- import { mkdir as mkdir4, readdir as readdir4, writeFile as writeFile2 } from "node:fs/promises";
26059
- import { join as join9 } from "node:path";
26673
+ import { mkdir as mkdir5, readdir as readdir4, writeFile as writeFile2 } from "node:fs/promises";
26674
+ import { join as join10 } from "node:path";
26060
26675
 
26061
26676
  // src/adapters/git/init-repository.ts
26062
26677
  import { createHash as createHash3 } from "node:crypto";
26063
- import { readFile as readFile5 } from "node:fs/promises";
26064
- import { join as join6 } from "node:path";
26678
+ import { readFile as readFile6 } from "node:fs/promises";
26679
+ import { join as join7 } from "node:path";
26065
26680
  function initRepository(cwd, inherited = process.env) {
26066
26681
  const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_LAZY_FETCH: "1", GIT_TERMINAL_PROMPT: "0", GIT_LITERAL_PATHSPECS: "1", LC_ALL: "C" };
26067
26682
  const runner = createGitRunner();
@@ -26081,10 +26696,10 @@ function initRepository(cwd, inherited = process.env) {
26081
26696
  const gitDir = locations.length === 2 ? locations[0] : decodeGitLine(await git(["rev-parse", "--absolute-git-dir"], root));
26082
26697
  const indexPath = locations.length === 2 ? locations[1] : decodeGitLine(await git(["rev-parse", "--path-format=absolute", "--git-path", "index"], root));
26083
26698
  for (const marker2 of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"]) {
26084
- if (await fileInfo(join6(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
26699
+ if (await fileInfo(join7(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
26085
26700
  }
26086
26701
  if (state.changes.some((change2) => change2.kind === "unmerged")) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
26087
- const index = await readFile5(indexPath).catch((error62) => {
26702
+ const index = await readFile6(indexPath).catch((error62) => {
26088
26703
  if (error62.code === "ENOENT") return Buffer.alloc(0);
26089
26704
  throw error62;
26090
26705
  });
@@ -26118,18 +26733,18 @@ function initRepository(cwd, inherited = process.env) {
26118
26733
  }
26119
26734
 
26120
26735
  // src/adapters/filesystem/managed-file.ts
26121
- import { open as open3, readFile as readFile6, mkdir as mkdir3, realpath as realpath2, rename as rename3, link as link2, unlink as unlink3 } from "node:fs/promises";
26122
- import { join as join7, dirname as dirname2 } from "node:path";
26736
+ import { open as open3, readFile as readFile7, mkdir as mkdir4, realpath as realpath2, rename as rename3, link as link2, unlink as unlink3 } from "node:fs/promises";
26737
+ import { join as join8, dirname as dirname2 } from "node:path";
26123
26738
  import { randomUUID as randomUUID5 } from "node:crypto";
26124
26739
  var DEFAULT_LIMIT = 1024 * 1024;
26125
26740
  async function managedPath(root, path3, create = false) {
26126
26741
  let full = root;
26127
26742
  const parts = path3.split("/");
26128
26743
  for (let i = 0; i < parts.length; i++) {
26129
- full = join7(full, parts[i]);
26744
+ full = join8(full, parts[i]);
26130
26745
  let info7 = await fileInfo(full);
26131
26746
  if (!info7 && create && i < parts.length - 1) {
26132
- await mkdir3(full).catch((error62) => {
26747
+ await mkdir4(full).catch((error62) => {
26133
26748
  if (error62.code !== "EEXIST") throw error62;
26134
26749
  });
26135
26750
  info7 = await fileInfo(full);
@@ -26145,7 +26760,7 @@ async function managedRead(root, path3, limit = DEFAULT_LIMIT) {
26145
26760
  const before = await fileInfo(full);
26146
26761
  if (!before) return null;
26147
26762
  if (before.size > limit) throw new InitError("FILE_TOO_LARGE", t2("managedFile.tooLarge", { kib: limit / 1024, path: path3 }));
26148
- const bytes = await readFile6(full);
26763
+ const bytes = await readFile7(full);
26149
26764
  await managedPath(root, path3);
26150
26765
  const after = await fileInfo(full);
26151
26766
  if (!after || before.ino !== after.ino || before.dev !== after.dev || before.mtimeMs !== after.mtimeMs || bytes.length > limit) {
@@ -26174,7 +26789,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
26174
26789
  if (previous !== null) await unlink3(full);
26175
26790
  return;
26176
26791
  }
26177
- const temp = join7(directory, ".gitifact-managed-" + randomUUID5() + ".tmp");
26792
+ const temp = join8(directory, ".gitifact-managed-" + randomUUID5() + ".tmp");
26178
26793
  const handle = await open3(temp, "wx", 384);
26179
26794
  const tempOwner = await handle.stat();
26180
26795
  try {
@@ -26186,7 +26801,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
26186
26801
  }
26187
26802
  await recheck();
26188
26803
  await unchanged();
26189
- if (await managedRead(root, path3) !== previous || await readFile6(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", t2("managedFile.publishTargetChanged", { path: path3 }));
26804
+ if (await managedRead(root, path3) !== previous || await readFile7(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", t2("managedFile.publishTargetChanged", { path: path3 }));
26190
26805
  if (previous === null) await link2(temp, full);
26191
26806
  else await rename3(temp, full);
26192
26807
  } finally {
@@ -26197,14 +26812,14 @@ async function managedWrite(root, path3, previous, next, recheck) {
26197
26812
  }
26198
26813
 
26199
26814
  // src/commands/agent-block.ts
26200
- import { readFile as readFile8 } from "node:fs/promises";
26815
+ import { readFile as readFile9 } from "node:fs/promises";
26201
26816
 
26202
26817
  // src/commands/docs.ts
26203
- import { lstat as lstat5, readFile as readFile7 } from "node:fs/promises";
26204
- import { dirname as dirname3, join as join8 } from "node:path";
26205
- var docTopics = ["workflow", "spec", "design", "wiki", "commit"];
26818
+ import { lstat as lstat5, readFile as readFile8 } from "node:fs/promises";
26819
+ import { dirname as dirname3, join as join9 } from "node:path";
26820
+ var docTopics = ["workflow", "spec", "design", "wiki", "writing", "commit"];
26206
26821
  var isDocTopic = (value) => docTopics.includes(value);
26207
- var readBundledDoc = (name, lang) => readFile7(new URL("./i18n/" + lang + "/docs/" + name + ".md", import.meta.url), "utf8");
26822
+ var readBundledDoc = (name, lang) => readFile8(new URL("./i18n/" + lang + "/docs/" + name + ".md", import.meta.url), "utf8");
26208
26823
  var info3 = (path3) => lstat5(path3).catch((e) => {
26209
26824
  if (e.code === "ENOENT") return void 0;
26210
26825
  throw e;
@@ -26215,16 +26830,16 @@ function listDocTopics(lang = defaultLanguage2) {
26215
26830
  }
26216
26831
  async function findProjectRoot(cwd) {
26217
26832
  for (let dir = cwd; ; dir = dirname3(dir)) {
26218
- if ((await info3(join8(dir, ".gitifact", "config.json")))?.isFile()) return dir;
26833
+ if ((await info3(join9(dir, ".gitifact", "config.json")))?.isFile()) return dir;
26219
26834
  if (dirname3(dir) === dir) return void 0;
26220
26835
  }
26221
26836
  }
26222
26837
  async function readWikiPolicy(root) {
26223
26838
  if (!root) return void 0;
26224
- const path3 = join8(root, ...WIKI_ENTRY_PATH.split("/"));
26839
+ const path3 = join9(root, ...WIKI_ENTRY_PATH.split("/"));
26225
26840
  const stat3 = await info3(path3);
26226
26841
  if (!stat3?.isFile() || stat3.size > 1024 * 1024) return void 0;
26227
- const lines = (await readFile7(path3, "utf8")).replace(/\r\n/g, "\n").split("\n");
26842
+ const lines = (await readFile8(path3, "utf8")).replace(/\r\n/g, "\n").split("\n");
26228
26843
  if (lines[0] === "---") {
26229
26844
  const end = lines.indexOf("---", 1);
26230
26845
  if (end > 0) lines.splice(0, end + 1);
@@ -26276,7 +26891,7 @@ function boilerplateFor(path3) {
26276
26891
  const name = path3 === "AGENTS.md" ? path3 : path3.split("/").pop().replace(/^\./, "").replace(/\.md$/, "");
26277
26892
  return "# " + name + "\n\nProject-specific guidance for AI coding agents.\n";
26278
26893
  }
26279
- var readBundledBlock = (lang) => readFile8(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
26894
+ var readBundledBlock = (lang) => readFile9(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
26280
26895
  async function renderAgentBlock(version2, controls = {}, lang = defaultLanguage2) {
26281
26896
  const body = await (controls.readBlock ?? readBundledBlock)(lang);
26282
26897
  const filled = body.trimEnd().replace(/\{(version|language|topics)\}/g, (_whole, name) => name === "version" ? version2 : name === "language" ? lang : docTopics.join(", "));
@@ -26435,8 +27050,8 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
26435
27050
  const text2 = JSON.stringify(config2, null, 2) + "\n";
26436
27051
  const replaceLegacy = async (before, version2) => {
26437
27052
  const onlyConfig = async () => {
26438
- const entries = await readdir4(join9(root, ".gitifact"));
26439
- if (await fileInfo(join9(root, "specs")) || entries.some((name) => name !== "config.json" && !/^\.init-[a-f0-9-]+\.tmp$/.test(name))) {
27053
+ const entries = await readdir4(join10(root, ".gitifact"));
27054
+ if (await fileInfo(join10(root, "specs")) || entries.some((name) => name !== "config.json" && !/^\.init-[a-f0-9-]+\.tmp$/.test(name))) {
26440
27055
  throw new InitError("UNSUPPORTED_SCHEMA", t2("init.legacyRecords", { version: String(version2) }));
26441
27056
  }
26442
27057
  };
@@ -26467,8 +27082,8 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
26467
27082
  }
26468
27083
  if (first.trackedConfig) throw new InitError("CONFIG_DELETED", t2("init.configDeleted"));
26469
27084
  const checkRecords = async () => {
26470
- if (await fileInfo(join9(root, "specs"))) throw new InitError("EXISTING_RECORDS", t2("init.existingSpecs"));
26471
- const entries = await readdir4(join9(root, ".gitifact")).catch((e) => {
27085
+ if (await fileInfo(join10(root, "specs"))) throw new InitError("EXISTING_RECORDS", t2("init.existingSpecs"));
27086
+ const entries = await readdir4(join10(root, ".gitifact")).catch((e) => {
26472
27087
  if (e.code === "ENOENT") return [];
26473
27088
  throw e;
26474
27089
  });
@@ -26505,7 +27120,7 @@ function legacySchemaVersion(text2) {
26505
27120
  return Number.isInteger(version2) && version2 < SCHEMA_VERSION ? version2 : void 0;
26506
27121
  }
26507
27122
  async function writeWikiPolicy(root, readDoc) {
26508
- if (await fileInfo(join9(root, ...WIKI_DIR.split("/")))) return;
27123
+ if (await fileInfo(join10(root, ...WIKI_DIR.split("/")))) return;
26509
27124
  const template = await readDoc("wiki.default").catch((e) => {
26510
27125
  if (e.code === "ENOENT") return void 0;
26511
27126
  throw e;
@@ -26514,8 +27129,8 @@ async function writeWikiPolicy(root, readDoc) {
26514
27129
  const doc = { id: generatePreviewId("W"), path: WIKI_ENTRY_PATH, title: t2("init.wikiReadmeTitle"), body: template.trim() };
26515
27130
  const text2 = renderDocument(doc);
26516
27131
  parseDocument(doc.path, text2);
26517
- await mkdir4(join9(root, ...WIKI_DIR.split("/")), { recursive: true });
26518
- await writeFile2(join9(root, ...WIKI_ENTRY_PATH.split("/")), text2, { flag: "wx" });
27132
+ await mkdir5(join10(root, ...WIKI_DIR.split("/")), { recursive: true });
27133
+ await writeFile2(join10(root, ...WIKI_ENTRY_PATH.split("/")), text2, { flag: "wx" });
26519
27134
  }
26520
27135
 
26521
27136
  // src/commands/init.ts
@@ -26693,11 +27308,11 @@ async function runUpdate(options, version2) {
26693
27308
  import { join as join15 } from "node:path";
26694
27309
  import { readFile as readFile12, stat as stat2 } from "node:fs/promises";
26695
27310
 
26696
- // src/adapters/filesystem/spec-preview-prepare.ts
27311
+ // src/adapters/filesystem/spec-preview-context.ts
26697
27312
  import { lstat as lstat6 } from "node:fs/promises";
26698
- import { join as join10 } from "node:path";
27313
+ import { join as join11 } from "node:path";
26699
27314
  import { createHash as createHash4 } from "node:crypto";
26700
- var fail5 = (message) => {
27315
+ var fail6 = (message) => {
26701
27316
  throw new SpecPreviewError(message);
26702
27317
  };
26703
27318
  var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
@@ -26708,11 +27323,11 @@ async function readPreviewContext(cwd) {
26708
27323
  const { gitDir } = await reader.location();
26709
27324
  const checkOperation = async () => {
26710
27325
  for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) {
26711
- const exists = await lstat6(join10(gitDir, name)).catch((e) => {
27326
+ const exists = await lstat6(join11(gitDir, name)).catch((e) => {
26712
27327
  if (e.code === "ENOENT") return void 0;
26713
27328
  throw e;
26714
27329
  });
26715
- if (exists) fail5(t2("prepare.integrationInProgress"));
27330
+ if (exists) fail6(t2("prepare.integrationInProgress"));
26716
27331
  }
26717
27332
  };
26718
27333
  await checkOperation();
@@ -26723,7 +27338,7 @@ async function readPreviewContext(cwd) {
26723
27338
  const specs = bundle.specs;
26724
27339
  const recheck = async () => {
26725
27340
  await checkOperation();
26726
- if (!same(base, await reader.baseline())) fail5(t2("prepare.headChanged"));
27341
+ if (!same(base, await reader.baseline())) fail6(t2("prepare.headChanged"));
26727
27342
  };
26728
27343
  return { reader, base, files, specs, bundle, recheck, working };
26729
27344
  }
@@ -26736,50 +27351,12 @@ async function readFinalPreviewChanges(cwd) {
26736
27351
  const pendingReasons = pendingPreviewReasons(c.bundle, current.bundle);
26737
27352
  return { base: c.base, expected: expected(c.base, current.stamp), stamp: current.stamp, pendingReasons, ...delta };
26738
27353
  }
26739
- async function prepareWorkingPreview(cwd, input2, publish) {
26740
- if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("prepare.invalidInput"));
26741
- const request = input2;
26742
- if (Object.keys(request).sort().join(",") !== "expected,reasons" || typeof request.expected !== "string") fail5(t2("prepare.expectedReasons"));
26743
- const c = await context(cwd);
26744
- const current = await readWorkingPreviewState(cwd);
26745
- if (request.expected !== expected(c.base, current.stamp)) fail5(t2("prepare.staleInput"));
26746
- const result = await previewTransaction(cwd, current.stamp, async (before) => {
26747
- await c.recheck();
26748
- const prepared = prepareSpecPreview(c.bundle, before.bundle, c.files, before.files, request.reasons, () => generatePreviewId("H"));
26749
- return { writes: prepared.writes, data: { changes: prepared.changes, specChanges: prepared.specChanges, reasons: prepared.reasons, withoutReason: prepared.withoutReason }, recheck: c.recheck };
26750
- }, publish);
26751
- return { ...result, base: c.base, expected: expected(c.base, result.stamp), verification: { base: c.base, stamp: result.stamp } };
26752
- }
26753
- async function verifyPreparedPreview(cwd, input2, staged) {
26754
- if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("prepare.invalidVerifyInput"));
26755
- const request = input2;
26756
- if (Object.keys(request).sort().join(",") !== "base,stamp" || typeof request.stamp !== "string") fail5(t2("prepare.verificationRequired"));
26757
- const c = await context(cwd);
26758
- const current = await readWorkingPreviewState(cwd);
26759
- if (!same(request.base, c.base) || request.stamp !== current.stamp) fail5(t2("prepare.changedAfterPrepare"));
26760
- finalSpecPreviewChanges(c.bundle, current.bundle);
26761
- comparePreviewBundles(c.bundle, current.bundle);
26762
- if (staged) {
26763
- const index = await c.reader.index();
26764
- if (index.size !== current.files.size) fail5(t2("prepare.stagingScope"));
26765
- for (const [path3, source2] of current.files) {
26766
- const oid2 = index.get(path3);
26767
- const bytes = Buffer.from(source2);
26768
- const hash3 = createHash4(oid2?.length === 64 ? "sha256" : "sha1").update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
26769
- if (oid2 !== hash3) fail5(t2("prepare.stagingContent", { path: path3 }));
26770
- }
26771
- if (!same([...index], [...await c.reader.index()])) fail5(t2("prepare.stagingChanged"));
26772
- }
26773
- if ((await readWorkingPreviewState(cwd)).stamp !== current.stamp) fail5(t2("prepare.specsChanged"));
26774
- await c.recheck();
26775
- return { verified: true, scope: staged ? "staged" : "working", base: c.base, stamp: current.stamp };
26776
- }
26777
27354
 
26778
27355
  // src/adapters/filesystem/agent-inputs.ts
26779
27356
  import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
26780
- import { lstat as lstat7, mkdir as mkdir5, readdir as readdir5, realpath as realpath3, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
27357
+ import { lstat as lstat7, mkdir as mkdir6, readdir as readdir5, realpath as realpath3, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
26781
27358
  import { tmpdir } from "node:os";
26782
- import { basename, dirname as dirname4, join as join11 } from "node:path";
27359
+ import { basename, dirname as dirname4, join as join12 } from "node:path";
26783
27360
  var maxAge = 7 * 24 * 60 * 60 * 1e3;
26784
27361
  var info4 = (path3) => lstat7(path3).catch((e) => {
26785
27362
  if (e.code === "ENOENT") return void 0;
@@ -26788,14 +27365,14 @@ var info4 = (path3) => lstat7(path3).catch((e) => {
26788
27365
  var comparable = (path3) => process.platform === "win32" ? path3.toLowerCase() : path3;
26789
27366
  async function candidates(root, controls) {
26790
27367
  const key = createHash5("sha256").update(comparable(await realpath3(root))).digest("hex").slice(0, 16);
26791
- return { system: join11((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join11(root, ".gitifact", "tmp") };
27368
+ return { system: join12((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join12(root, ".gitifact", "tmp") };
26792
27369
  }
26793
27370
  async function writable(directory) {
26794
27371
  try {
26795
- await mkdir5(directory, { recursive: true });
27372
+ await mkdir6(directory, { recursive: true });
26796
27373
  const stat3 = await info4(directory);
26797
27374
  if (!stat3?.isDirectory() || stat3.isSymbolicLink()) return false;
26798
- const probe = join11(directory, ".probe-" + randomBytes2(8).toString("hex"));
27375
+ const probe = join12(directory, ".probe-" + randomBytes2(8).toString("hex"));
26799
27376
  await writeFile3(probe, "", { flag: "wx" });
26800
27377
  await unlink4(probe);
26801
27378
  return true;
@@ -26809,7 +27386,7 @@ async function prepareAgentInputs(root, controls = {}) {
26809
27386
  if (await writable(system)) directory = system;
26810
27387
  else if (await writable(project)) {
26811
27388
  directory = project;
26812
- await writeFile3(join11(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
27389
+ await writeFile3(join12(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
26813
27390
  if (e.code !== "EEXIST") throw e;
26814
27391
  });
26815
27392
  }
@@ -26817,10 +27394,10 @@ async function prepareAgentInputs(root, controls = {}) {
26817
27394
  const now = (controls.now ?? Date.now)();
26818
27395
  for (const name of await readdir5(directory).catch(() => [])) {
26819
27396
  if (name === ".gitignore") continue;
26820
- const stat3 = await info4(join11(directory, name)).catch(() => void 0);
26821
- if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join11(directory, name)).catch(() => void 0);
27397
+ const stat3 = await info4(join12(directory, name)).catch(() => void 0);
27398
+ if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join12(directory, name)).catch(() => void 0);
26822
27399
  }
26823
- return { save: join11(directory, "save.json"), commit: join11(directory, "commit.json") };
27400
+ return { save: join12(directory, "save.json"), commit: join12(directory, "commit.json") };
26824
27401
  }
26825
27402
  async function discardAgentInput(root, file2, controls = {}) {
26826
27403
  try {
@@ -26840,20 +27417,20 @@ async function discardAgentInput(root, file2, controls = {}) {
26840
27417
  }
26841
27418
  }
26842
27419
 
26843
- // src/commands/spec-preview-commit.ts
26844
- import { randomUUID as randomUUID6 } from "node:crypto";
26845
- import { readFile as readFile10, mkdir as mkdir6, open as open4, rename as rename4, unlink as unlink5, rmdir as rmdir2, writeFile as writeFile4 } from "node:fs/promises";
26846
- import { join as join13 } from "node:path";
27420
+ // src/commands/spec-commit.ts
27421
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
27422
+ import { mkdir as mkdir7, open as open4, readFile as readFile11, rename as rename4, rmdir as rmdir2, unlink as unlink5, writeFile as writeFile4 } from "node:fs/promises";
27423
+ import { join as join14 } from "node:path";
26847
27424
 
26848
27425
  // src/commands/spec-commit-files.ts
26849
27426
  import { createHash as createHash6 } from "node:crypto";
26850
- import { lstat as lstat8, readFile as readFile9 } from "node:fs/promises";
26851
- import { join as join12 } from "node:path";
26852
- var fail6 = (message) => {
27427
+ import { lstat as lstat8, readFile as readFile10 } from "node:fs/promises";
27428
+ import { join as join13 } from "node:path";
27429
+ var fail7 = (message) => {
26853
27430
  throw new SpecPreviewError(message);
26854
27431
  };
26855
27432
  var hash2 = (value) => createHash6("sha256").update(value).digest("hex");
26856
- var optional2 = (path3) => readFile9(path3).catch((e) => {
27433
+ var optional2 = (path3) => readFile10(path3).catch((e) => {
26857
27434
  if (e.code === "ENOENT") return null;
26858
27435
  throw e;
26859
27436
  });
@@ -26863,34 +27440,34 @@ var info5 = (path3) => lstat8(path3).catch((e) => {
26863
27440
  });
26864
27441
  var record2 = (path3) => recordPathPattern.test(path3);
26865
27442
  function validPath2(path3) {
26866
- if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git")) fail6(t2("commitFiles.relativePath"));
27443
+ if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git")) fail7(t2("commitFiles.relativePath"));
26867
27444
  }
26868
27445
  async function fingerprint(root, path3) {
26869
27446
  validPath2(path3);
26870
27447
  const parts = path3.split("/");
26871
27448
  for (let i = 1; i <= parts.length; i++) {
26872
- const target = join12(root, ...parts.slice(0, i));
27449
+ const target = join13(root, ...parts.slice(0, i));
26873
27450
  const stat3 = await info5(target);
26874
27451
  if (!stat3) return null;
26875
- if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail6(t2("commitFiles.linkOrDirectory"));
26876
- if (i < parts.length && await info5(join12(target, ".git"))) fail6(t2("commitFiles.nestedRepository"));
27452
+ if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail7(t2("commitFiles.linkOrDirectory"));
27453
+ if (i < parts.length && await info5(join13(target, ".git"))) fail7(t2("commitFiles.nestedRepository"));
26877
27454
  if (i === parts.length) {
26878
- if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail6(t2("commitFiles.hardLinkOrSize"));
26879
- return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile9(target)]));
27455
+ if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail7(t2("commitFiles.hardLinkOrSize"));
27456
+ return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile10(target)]));
26880
27457
  }
26881
27458
  }
26882
27459
  return null;
26883
27460
  }
26884
27461
  function object3(input2) {
26885
- if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return fail6(t2("commitFiles.invalidInput"));
27462
+ if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return fail7(t2("commitFiles.invalidInput"));
26886
27463
  return input2;
26887
27464
  }
26888
27465
  function text(value, limit) {
26889
- if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return fail6(t2("commitFiles.emptyOrTooLong"));
27466
+ if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return fail7(t2("commitFiles.emptyOrTooLong"));
26890
27467
  return value;
26891
27468
  }
26892
27469
  function paths(value, limit = 128) {
26893
- if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return fail6(t2("commitFiles.invalidPaths"));
27470
+ if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return fail7(t2("commitFiles.invalidPaths"));
26894
27471
  const list = [...new Set(value)].sort();
26895
27472
  list.forEach(validPath2);
26896
27473
  return list;
@@ -26907,189 +27484,30 @@ async function checkLegacySelection(root, selected) {
26907
27484
  const legacyJson = /^\.(?:gitifact|tryce)\/(?:spec\/[^/]+\/tryce\.json|notes\/N-[a-f0-9-]+\.json|mode-[a-f0-9-]+\.json|config\.(?:init-1|prototype-1)\.[a-f0-9]+\.json)$|^\.gitifact\/(?:product|guides|overrides)\/.+$/;
26908
27485
  for (const p of selected.filter((p2) => p2.startsWith(".gitifact/") && !record2(p2) && p2 !== ".gitifact/config.json")) {
26909
27486
  if (isAssetPath(p)) continue;
26910
- if (!legacyJson.test(p) || await fingerprint(root, p) !== null) fail6(t2("commitFiles.legacyDeleteOnly", { path: p }));
27487
+ if (!legacyJson.test(p) || await fingerprint(root, p) !== null) fail7(t2("commitFiles.legacyDeleteOnly", { path: p }));
26911
27488
  }
26912
27489
  for (const p of selected.filter((p2) => p2.startsWith(".tryce/"))) {
26913
- if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null) fail6(t2("commitFiles.tryceDeleteOnly", { path: p }));
26914
- }
26915
- }
26916
-
26917
- // src/commands/spec-preview-commit.ts
26918
- var seal = (p) => hash2(JSON.stringify(p));
26919
- async function previewCommit(cwd, action, input2) {
26920
- const reader = specPreviewReader(cwd);
26921
- const { root, gitDir } = await reader.location();
26922
- const runner = createGitRunner();
26923
- const git = (args, index) => runner(["-c", "core.fsmonitor=false", ...args], {
26924
- cwd: root,
26925
- env: {
26926
- ...process.env,
26927
- GIT_LITERAL_PATHSPECS: "1",
26928
- GIT_GLOB_PATHSPECS: "0",
26929
- GIT_NOGLOB_PATHSPECS: "0",
26930
- GIT_ICASE_PATHSPECS: "0",
26931
- GIT_OPTIONAL_LOCKS: "0",
26932
- GIT_NO_LAZY_FETCH: "1",
26933
- GIT_NO_REPLACE_OBJECTS: "1",
26934
- GIT_TERMINAL_PROMPT: "0",
26935
- ...index ? { GIT_INDEX_FILE: index } : {}
26936
- },
26937
- timeoutMs: 12e4,
26938
- maxBytes: 32 * 1024 * 1024
26939
- });
26940
- const indexPath = (await git(["rev-parse", "--path-format=absolute", "--git-path", "index"])).toString("utf8").trim();
26941
- const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
26942
- const busy = join13(gitDir, "gitifact-spec-commit.lock");
26943
- if (await info5(busy)) fail6(t2("commit.busy", { path: busy }));
26944
- if ((await staged()).length) fail6(t2("commit.existingStagingPlan"));
26945
- const request = object3(input2);
26946
- let plan;
26947
- if (action === "plan") {
26948
- if (Object.keys(request).some((k) => !["verification", "paths", "message", "requirements", "authorization", "policyFiles"].includes(k))) fail6(t2("commit.unknownField"));
26949
- await verifyPreparedPreview(cwd, request.verification, false);
26950
- const selected2 = paths(request.paths);
26951
- const authorization = object3(request.authorization);
26952
- await checkLegacySelection(root, selected2);
26953
- if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6(t2("commit.authorizationRequired"));
26954
- const message = text(request.message, 4e3);
26955
- if (/^\s*Gitifact-/im.test(message)) fail6(t2("commit.trailerInMessage"));
26956
- const state = await readWorkingPreviewState(cwd);
26957
- const base = await reader.baseline();
26958
- const previous = base.head ? await reader.files(base.head, state.config !== void 0) : /* @__PURE__ */ new Map();
26959
- const pending = [.../* @__PURE__ */ new Set([...previous.keys(), ...state.files.keys()])].filter((p) => previous.get(p) !== state.files.get(p));
26960
- if (pending.some((p) => !selected2.includes(p))) fail6(t2("commit.selectPending"));
26961
- const delta = await readFinalPreviewChanges(cwd);
26962
- const references = request.requirements ?? [];
26963
- if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6(t2("commit.invalidReferences"));
26964
- if (delta.changes.some((c) => c.kind === "design")) fail6(t2("commit.designUseSpecCommit"));
26965
- const known = /* @__PURE__ */ new Set([...state.specs.flatMap((s) => s.requirements.map((r) => r.id)), ...delta.changes.map((c) => c.id)]);
26966
- if (references.some((r) => !known.has(r))) fail6(t2("commit.unknownRequirement"));
26967
- const extra = request.policyFiles === void 0 ? [] : paths(request.policyFiles, 1024);
26968
- const contents = async (list) => Promise.all(list.map(async (path3) => ({ path: path3, hash: await fingerprint(root, path3) })));
26969
- const data2 = {
26970
- kind: "spec-preview-commit",
26971
- root,
26972
- verification: request.verification,
26973
- index: hash2(await optional2(indexPath) ?? Buffer.alloc(0)),
26974
- files: await contents(selected2),
26975
- context: await contents([.../* @__PURE__ */ new Set([...policyPaths(selected2), ...extra])].sort()),
26976
- message,
26977
- requirements: [.../* @__PURE__ */ new Set([...references, ...delta.changes.map((c) => c.id)])].sort(),
26978
- authorization: { basis: String(authorization.basis), evidence: text(authorization.evidence, 2e3) }
26979
- };
26980
- await verifyPreparedPreview(cwd, request.verification, false);
26981
- if (data2.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6(t2("commit.indexChangedPlanning"));
26982
- return { outcome: "planned", plan: { ...data2, digest: seal(data2) }, committed: false };
26983
- }
26984
- const { digest: digest2, ...data } = request;
26985
- if (request.kind !== "spec-preview-commit" || typeof digest2 !== "string" || digest2 !== seal(data)) fail6(t2("commit.planCorrupted"));
26986
- plan = request;
26987
- if (plan.root !== root || !Array.isArray(plan.files) || !Array.isArray(plan.context)) fail6(t2("commit.planScope"));
26988
- const selected = paths(plan.files.map((f) => f.path));
26989
- const refreshed = await previewCommit(cwd, "plan", {
26990
- verification: plan.verification,
26991
- paths: selected,
26992
- message: plan.message,
26993
- requirements: plan.requirements,
26994
- authorization: plan.authorization,
26995
- policyFiles: plan.context.map((f) => f.path)
26996
- });
26997
- if (!("plan" in refreshed) || refreshed.plan.digest !== plan.digest) fail6(t2("commit.planStale"));
26998
- const before = await reader.baseline();
26999
- const original = await optional2(indexPath);
27000
- await mkdir6(busy);
27001
- const draftLock = join13(gitDir, "gitifact-spec-preview.lock");
27002
- let draftOwned = false;
27003
- let indexLock;
27004
- let uncertain = false;
27005
- let commitStarted = false;
27006
- const temporary = join13(gitDir, "gitifact-commit-index-" + randomUUID6());
27007
- const checkFiles = async () => {
27008
- for (const f of [...plan.files, ...plan.context]) if (f.hash !== await fingerprint(root, f.path)) fail6(t2("commit.fileChangedPreparing", { path: f.path }));
27009
- if ((await readLockedPreviewState(root)).stamp !== object3(plan.verification).stamp) fail6(t2("commit.specsChangedPreparing"));
27010
- for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) if (await info5(join13(gitDir, name))) fail6(t2("commit.integrationStarted"));
27011
- };
27012
- try {
27013
- await verifyPreparedPreview(cwd, plan.verification, false);
27014
- await mkdir6(draftLock);
27015
- draftOwned = true;
27016
- indexLock = await open4(indexPath + ".lock", "wx", 384);
27017
- if (plan.index !== hash2(await optional2(indexPath) ?? Buffer.alloc(0)) || (await staged()).length) fail6(t2("commit.indexChangedLocked"));
27018
- await writeFile4(join13(busy, "recovery.json"), JSON.stringify({ before, originalIndex: original?.toString("base64") ?? null, temporary, plan }));
27019
- if (original) await writeFile4(temporary, original, { flag: "wx" });
27020
- else await git(["read-tree", "--empty"], temporary);
27021
- await git(["add", "--", ...selected], temporary);
27022
- const actual = await staged(temporary);
27023
- if (!actual.length || actual.some((p) => !selected.includes(p))) fail6(t2("commit.unexpectedFiles"));
27024
- for (const file2 of plan.files.filter((f) => record2(f.path) && f.hash !== null)) {
27025
- const stagedBytes = await git(["show", ":" + file2.path], temporary);
27026
- if (!stagedBytes.equals(await readFile10(join13(root, file2.path)))) fail6(t2("commit.filterChanged"));
27027
- }
27028
- await checkFiles();
27029
- if (JSON.stringify(before) !== JSON.stringify(await reader.baseline())) fail6(t2("commit.headChanged"));
27030
- const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
27031
- const trailers = plan.requirements.map((id) => "Gitifact-Req: " + id);
27032
- commitStarted = true;
27033
- await git(["commit", "-m", plan.message.trim() + (trailers.length ? "\n\n" + trailers.join("\n") : "")], temporary);
27034
- const after = await reader.baseline();
27035
- const actualTree = (await git(["rev-parse", "HEAD^{tree}"])).toString("utf8").trim();
27036
- const parents = (await git(["rev-list", "--parents", "-n", "1", "HEAD"])).toString("utf8").trim().split(" ").slice(1);
27037
- const message = (await git(["log", "-1", "--format=%B"])).toString("utf8");
27038
- if (actualTree !== tree || after.branch !== before.branch || JSON.stringify(parents) !== JSON.stringify(before.head ? [before.head] : []) || trailers.some((t3) => !message.split(/\r?\n/).includes(t3))) fail6(t2("commit.resultAltered"));
27039
- if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== plan.index) fail6(t2("commit.indexChangedAfter"));
27040
- if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6(t2("commit.hookChangedStaging"));
27041
- await indexLock.writeFile(await readFile10(temporary));
27042
- await indexLock.sync();
27043
- await indexLock.close();
27044
- await rename4(indexPath + ".lock", indexPath);
27045
- indexLock = void 0;
27046
- return { outcome: "committed", commit: after.head, paths: actual, requirements: plan.requirements, pushed: false };
27047
- } catch (error62) {
27048
- if (commitStarted) {
27049
- try {
27050
- uncertain = JSON.stringify(before) !== JSON.stringify(await reader.baseline());
27051
- } catch {
27052
- uncertain = true;
27053
- }
27054
- }
27055
- if (uncertain) fail6(t2("commit.uncertain", { path: busy }));
27056
- throw error62;
27057
- } finally {
27058
- await indexLock?.close().catch(() => {
27059
- });
27060
- if (!uncertain) {
27061
- if (indexLock) await unlink5(indexPath + ".lock").catch(() => {
27062
- });
27063
- await unlink5(temporary).catch(() => {
27064
- });
27065
- await unlink5(join13(busy, "recovery.json")).catch(() => {
27066
- });
27067
- await rmdir2(busy);
27068
- if (draftOwned) await rmdir2(draftLock);
27069
- }
27490
+ if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null) fail7(t2("commitFiles.tryceDeleteOnly", { path: p }));
27070
27491
  }
27071
27492
  }
27072
27493
 
27073
27494
  // src/commands/spec-commit.ts
27074
- import { createHash as createHash8, randomUUID as randomUUID7 } from "node:crypto";
27075
- import { mkdir as mkdir7, open as open5, readFile as readFile11, rename as rename5, rmdir as rmdir3, unlink as unlink6, writeFile as writeFile5 } from "node:fs/promises";
27076
- import { join as join14 } from "node:path";
27077
27495
  var fields = ["reasons", "paths", "message", "authorization", "requirements", "policyFiles", "expected"];
27078
27496
  var integration = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"];
27079
27497
  var same2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
27080
27498
  async function specCommit(cwd, input2, dryRun) {
27081
27499
  const request = object3(input2);
27082
- if (Object.keys(request).some((k) => !fields.includes(k))) fail6(t2("commit.unknownField"));
27500
+ if (Object.keys(request).some((k) => !fields.includes(k))) fail7(t2("commit.unknownField"));
27083
27501
  const selected = paths(request.paths);
27084
27502
  const authorization = object3(request.authorization);
27085
- if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail6(t2("commit.authorizationRequired"));
27503
+ if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail7(t2("commit.authorizationRequired"));
27086
27504
  text(authorization.evidence, 2e3);
27087
27505
  const message = text(request.message, 4e3);
27088
- if (/^\s*Gitifact-/im.test(message)) fail6(t2("commit.trailerInMessage"));
27506
+ if (/^\s*Gitifact-/im.test(message)) fail7(t2("commit.trailerInMessage"));
27089
27507
  const references = request.requirements ?? [];
27090
- if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail6(t2("commit.invalidReferences"));
27508
+ if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail7(t2("commit.invalidReferences"));
27091
27509
  const extra = request.policyFiles === void 0 ? [] : paths(request.policyFiles, 1024);
27092
- if (request.expected !== void 0 && typeof request.expected !== "string") fail6(t2("commit.expectedType"));
27510
+ if (request.expected !== void 0 && typeof request.expected !== "string") fail7(t2("commit.expectedType"));
27093
27511
  const c = await readPreviewContext(cwd);
27094
27512
  const { root, gitDir, indexPath, objectFormat } = await c.reader.location();
27095
27513
  const runner = createGitRunner();
@@ -27114,26 +27532,26 @@ async function specCommit(cwd, input2, dryRun) {
27114
27532
  const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
27115
27533
  const busy = join14(gitDir, "gitifact-spec-commit.lock");
27116
27534
  await failOnLegacyLock(gitDir);
27117
- if (await info5(busy)) fail6(t2("commit.busy", { path: busy }));
27118
- if ((await staged()).length) fail6(t2("commit.existingStaging"));
27535
+ if (await info5(busy)) fail7(t2("commit.busy", { path: busy }));
27536
+ if ((await staged()).length) fail7(t2("commit.existingStaging"));
27119
27537
  const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
27120
27538
  const current = c.working;
27121
- if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp)) fail6(t2("commit.staleInput"));
27539
+ if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp)) fail7(t2("commit.staleInput"));
27122
27540
  const reasons = request.reasons ?? pendingPreviewReasons(c.bundle, current.bundle).map((h) => ({ requirements: h.requirements, ...h.designs ? { designs: h.designs } : {}, ...h.documents ? { documents: h.documents } : {}, reason: h.reason }));
27123
27541
  const prepared = prepareSpecPreview(c.bundle, current.bundle, c.files, current.files, reasons, () => generatePreviewId("H"));
27124
27542
  const blobId = (text2) => {
27125
27543
  const bytes = Buffer.from(text2);
27126
- return createHash8(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
27544
+ return createHash7(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
27127
27545
  };
27128
27546
  const present = [...current.files.keys()];
27129
- if (present.some((p) => p.includes("\n"))) fail6(t2("commit.newlinePath"));
27547
+ if (present.some((p) => p.includes("\n"))) fail7(t2("commit.newlinePath"));
27130
27548
  const stored = present.length ? (await git(["hash-object", "--stdin-paths"], void 0, Buffer.from(present.join("\n") + "\n"))).toString("utf8").split("\n") : [""];
27131
- if (stored.length !== present.length + 1) fail6(t2("commit.storedShape"));
27549
+ if (stored.length !== present.length + 1) fail7(t2("commit.storedShape"));
27132
27550
  const workingIds = new Map(present.map((p, i) => [p, stored[i]]));
27133
27551
  const writes = new Map([...prepared.writes].filter(([p, next]) => next === null || workingIds.get(p) !== blobId(next)));
27134
27552
  const finalId = (p) => writes.has(p) ? writes.get(p) === null ? void 0 : blobId(writes.get(p)) : workingIds.get(p);
27135
27553
  const pending = [.../* @__PURE__ */ new Set([...c.files.keys(), ...present, ...writes.keys()])].filter((p) => (c.files.has(p) ? blobId(c.files.get(p)) : void 0) !== finalId(p));
27136
- if (pending.some((p) => !selected.includes(p))) fail6(t2("commit.selectPending"));
27554
+ if (pending.some((p) => !selected.includes(p))) fail7(t2("commit.selectPending"));
27137
27555
  const finalFiles = new Map(current.files);
27138
27556
  for (const [path3, next] of writes) {
27139
27557
  if (next === null) finalFiles.delete(path3);
@@ -27142,7 +27560,7 @@ async function specCommit(cwd, input2, dryRun) {
27142
27560
  await checkLegacySelection(root, selected);
27143
27561
  const stageable = selected.filter((p) => !record2(p) || finalFiles.has(p) || c.files.has(p));
27144
27562
  const known = /* @__PURE__ */ new Set([...current.specs.flatMap((s) => s.requirements.map((r) => r.id)), ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)]);
27145
- if (references.some((r) => !known.has(r))) fail6(t2("commit.unknownRequirement"));
27563
+ if (references.some((r) => !known.has(r))) fail7(t2("commit.unknownRequirement"));
27146
27564
  const requirements = [.../* @__PURE__ */ new Set([...references, ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)])].sort();
27147
27565
  const contextPaths = [.../* @__PURE__ */ new Set([...policyPaths(selected), ...extra])].sort();
27148
27566
  const hashes = async (list) => new Map(await Promise.all(list.map(async (p) => [p, await fingerprint(root, p)])));
@@ -27166,7 +27584,7 @@ async function specCommit(cwd, input2, dryRun) {
27166
27584
  ...prepared.changes.filter((c2) => c2.kind === "design").map((c2) => "Gitifact-Design: " + c2.id),
27167
27585
  ...prepared.changes.filter((c2) => c2.kind === "wiki").map((c2) => "Gitifact-Doc: " + c2.id)
27168
27586
  ];
27169
- const temporary = join14(gitDir, "gitifact-commit-index-" + randomUUID7());
27587
+ const temporary = join14(gitDir, "gitifact-commit-index-" + randomUUID6());
27170
27588
  let owned = false;
27171
27589
  let uncertain = false;
27172
27590
  let indexLock;
@@ -27176,23 +27594,23 @@ async function specCommit(cwd, input2, dryRun) {
27176
27594
  await mkdir7(busy);
27177
27595
  owned = true;
27178
27596
  } catch (e) {
27179
- if (e.code === "EEXIST") fail6(t2("commit.busy", { path: busy }));
27597
+ if (e.code === "EEXIST") fail7(t2("commit.busy", { path: busy }));
27180
27598
  throw e;
27181
27599
  }
27182
- await previewTransaction(cwd, current.stamp, async () => ({ writes, data: {}, recheck: c.recheck }), rename5, async (published) => {
27600
+ await previewTransaction(cwd, current.stamp, async () => ({ writes, data: {}, recheck: c.recheck }), rename4, async (published) => {
27183
27601
  let commitStarted = false;
27184
27602
  try {
27185
- const lock = indexLock = await open5(indexPath + ".lock", "wx", 384);
27603
+ const lock = indexLock = await open4(indexPath + ".lock", "wx", 384);
27186
27604
  const original = await optional2(indexPath);
27187
- if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail6(t2("commit.indexChanged"));
27605
+ if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail7(t2("commit.indexChanged"));
27188
27606
  const locked = await hashes([.../* @__PURE__ */ new Set([...selected, ...contextPaths])]);
27189
- for (const [path3, value] of started) if (locked.get(path3) !== value) fail6(t2("commit.fileChangedRunning", { path: path3 }));
27190
- await writeFile5(join14(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
27191
- if (original) await writeFile5(temporary, original, { flag: "wx" });
27607
+ for (const [path3, value] of started) if (locked.get(path3) !== value) fail7(t2("commit.fileChangedRunning", { path: path3 }));
27608
+ await writeFile4(join14(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
27609
+ if (original) await writeFile4(temporary, original, { flag: "wx" });
27192
27610
  else await git(["read-tree", "--empty"], temporary);
27193
27611
  await git(["add", "--", ...stageable], temporary);
27194
27612
  const actual = await staged(temporary);
27195
- if (!actual.length || actual.some((p) => !selected.includes(p))) fail6(t2("commit.unexpectedFiles"));
27613
+ if (!actual.length || actual.some((p) => !selected.includes(p))) fail7(t2("commit.unexpectedFiles"));
27196
27614
  const records = selected.filter((p) => record2(p) && locked.get(p) !== null);
27197
27615
  if (records.length) {
27198
27616
  const output2 = await git(["cat-file", "--batch"], temporary, Buffer.from(records.map((p) => ":" + p).join("\n") + "\n"));
@@ -27201,35 +27619,35 @@ async function specCommit(cwd, input2, dryRun) {
27201
27619
  const end = output2.indexOf(10, offset);
27202
27620
  const header = output2.subarray(offset, end).toString("utf8").split(" ");
27203
27621
  const size = Number(header[2]);
27204
- if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail6(t2("commit.stagedUnreadable", { path: path3 }));
27622
+ if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail7(t2("commit.stagedUnreadable", { path: path3 }));
27205
27623
  const staged2 = output2.subarray(end + 1, end + 1 + size);
27206
27624
  const file2 = await readFile11(join14(root, path3));
27207
- if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail6(t2("commit.filterChanged"));
27625
+ if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail7(t2("commit.filterChanged"));
27208
27626
  offset = end + size + 2;
27209
27627
  }
27210
27628
  }
27211
27629
  const again = await hashes([...locked.keys()]);
27212
- for (const [path3, value] of locked) if (again.get(path3) !== value) fail6(t2("commit.fileChangedPreparing", { path: path3 }));
27213
- if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail6(t2("commit.specsChangedPreparing"));
27214
- for (const name of integration) if (await info5(join14(gitDir, name))) fail6(t2("commit.integrationStarted"));
27215
- if (!same2(c.base, await c.reader.baseline())) fail6(t2("commit.headChanged"));
27630
+ for (const [path3, value] of locked) if (again.get(path3) !== value) fail7(t2("commit.fileChangedPreparing", { path: path3 }));
27631
+ if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail7(t2("commit.specsChangedPreparing"));
27632
+ for (const name of integration) if (await info5(join14(gitDir, name))) fail7(t2("commit.integrationStarted"));
27633
+ if (!same2(c.base, await c.reader.baseline())) fail7(t2("commit.headChanged"));
27216
27634
  const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
27217
27635
  commitStarted = true;
27218
27636
  await git(["commit", "-m", message.trim() + (trailers.length ? "\n\n" + trailers.join("\n") : "")], temporary);
27219
27637
  const after = await c.reader.baseline();
27220
- if (!after.head) return fail6(t2("commit.resultUnknown"));
27638
+ if (!after.head) return fail7(t2("commit.resultUnknown"));
27221
27639
  const raw = (await git(["cat-file", "commit", after.head])).toString("utf8");
27222
27640
  const split = raw.indexOf("\n\n");
27223
27641
  const headers = raw.slice(0, split < 0 ? raw.length : split).split("\n");
27224
27642
  const body = split < 0 ? "" : raw.slice(split + 2);
27225
27643
  const parents = headers.filter((h) => h.startsWith("parent ")).map((h) => h.slice(7));
27226
- if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((t3) => !body.split(/\r?\n/).includes(t3))) fail6(t2("commit.resultAltered"));
27227
- if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail6(t2("commit.indexChangedAfter"));
27228
- if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail6(t2("commit.hookChangedStaging"));
27644
+ if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((t3) => !body.split(/\r?\n/).includes(t3))) fail7(t2("commit.resultAltered"));
27645
+ if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail7(t2("commit.indexChangedAfter"));
27646
+ if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail7(t2("commit.hookChangedStaging"));
27229
27647
  await lock.writeFile(await readFile11(temporary));
27230
27648
  await lock.sync();
27231
27649
  await lock.close();
27232
- await rename5(indexPath + ".lock", indexPath);
27650
+ await rename4(indexPath + ".lock", indexPath);
27233
27651
  indexLock = void 0;
27234
27652
  committed = { commit: after.head, paths: actual };
27235
27653
  } catch (error62) {
@@ -27248,14 +27666,14 @@ async function specCommit(cwd, input2, dryRun) {
27248
27666
  await indexLock?.close().catch(() => {
27249
27667
  });
27250
27668
  if (!uncertain) {
27251
- if (indexLock) await unlink6(indexPath + ".lock").catch(() => {
27669
+ if (indexLock) await unlink5(indexPath + ".lock").catch(() => {
27252
27670
  });
27253
- await unlink6(temporary).catch(() => {
27671
+ await unlink5(temporary).catch(() => {
27254
27672
  });
27255
27673
  if (owned) {
27256
- await unlink6(join14(busy, "recovery.json")).catch(() => {
27674
+ await unlink5(join14(busy, "recovery.json")).catch(() => {
27257
27675
  });
27258
- await rmdir3(busy);
27676
+ await rmdir2(busy);
27259
27677
  }
27260
27678
  }
27261
27679
  }
@@ -27277,7 +27695,7 @@ async function execute(action, options, controls) {
27277
27695
  const config2 = parseManagedConfig(raw);
27278
27696
  if (!("schemaVersion" in config2)) throw new SpecPreviewError(t2("preview.legacyProject"));
27279
27697
  await initRepository(root).validateBaseline(config2, root, "HEAD", objectFormat);
27280
- if (["working", "save", "changes", "prepare", "verify", "commit-plan", "commit-apply", "commit"].includes(action)) {
27698
+ if (["working", "save", "changes", "commit"].includes(action)) {
27281
27699
  let result;
27282
27700
  const inputs = () => prepareAgentInputs(root, controls).catch(() => void 0);
27283
27701
  if (action === "working") result = narrowWorking(await readWorkingPreview(process.cwd()), options, await inputs());
@@ -27291,7 +27709,7 @@ async function execute(action, options, controls) {
27291
27709
  } catch {
27292
27710
  throw new SpecPreviewError(t2("preview.inputJson"));
27293
27711
  }
27294
- result = action === "commit" ? await specCommit(process.cwd(), input2, !!options.dryRun) : action === "commit-plan" || action === "commit-apply" ? await previewCommit(process.cwd(), action === "commit-plan" ? "plan" : "apply", input2) : action === "prepare" ? await prepareWorkingPreview(process.cwd(), input2) : action === "verify" ? await verifyPreparedPreview(process.cwd(), input2, !!options.staged) : await saveWorkingPreview(process.cwd(), input2);
27712
+ result = action === "commit" ? await specCommit(process.cwd(), input2, !!options.dryRun) : await saveWorkingPreview(process.cwd(), input2);
27295
27713
  const consumed = action === "save" || action === "commit" && result.outcome === "committed";
27296
27714
  if (consumed && options.file !== "-") result = { ...result, inputRemoved: await discardAgentInput(root, options.file, controls) };
27297
27715
  }
@@ -27349,36 +27767,36 @@ function narrowWorking(working, options, inputs) {
27349
27767
  }
27350
27768
 
27351
27769
  // src/commands/migrate.ts
27352
- import { lstat as lstat10, readdir as readdir6, readFile as readFile13, rename as rename6, writeFile as writeFile6, unlink as unlink7 } from "node:fs/promises";
27770
+ import { lstat as lstat9, readdir as readdir6, readFile as readFile13, rename as rename5, writeFile as writeFile5, unlink as unlink6 } from "node:fs/promises";
27353
27771
  import { join as join16 } from "node:path";
27354
27772
  import { randomBytes as randomBytes3 } from "node:crypto";
27355
27773
  var operations2 = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
27356
- var info6 = (path3) => lstat10(path3).catch((e) => {
27774
+ var info6 = (path3) => lstat9(path3).catch((e) => {
27357
27775
  if (e.code === "ENOENT") return void 0;
27358
27776
  throw e;
27359
27777
  });
27360
27778
  var decode4 = (bytes) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
27361
- var fail7 = (code, message) => {
27779
+ var fail8 = (code, message) => {
27362
27780
  throw new InitError(code, message);
27363
27781
  };
27364
27782
  async function migrateStore(cwd, dryRun = false) {
27365
27783
  const reader = specPreviewReader(cwd);
27366
27784
  const { root, gitDir } = await reader.location();
27367
- for (const marker3 of operations2) if (await info6(join16(gitDir, marker3))) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
27368
- if (await reader.hasUnmerged()) fail7("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
27369
- for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info6(join16(gitDir, name))) fail7("LOCKED", t2("migrate.locked", { path: join16(gitDir, name) }));
27785
+ for (const marker3 of operations2) if (await info6(join16(gitDir, marker3))) fail8("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
27786
+ if (await reader.hasUnmerged()) fail8("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
27787
+ for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info6(join16(gitDir, name))) fail8("LOCKED", t2("migrate.locked", { path: join16(gitDir, name) }));
27370
27788
  const from = join16(root, ".tryce");
27371
27789
  const to = join16(root, ".gitifact");
27372
27790
  const fromInfo = await info6(from);
27373
- if (await info6(to)) fail7("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
27374
- if (!fromInfo) return fail7("NOTHING_TO_MIGRATE", t2("migrate.nothingToMigrate"));
27375
- if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail7("PATH_CONFLICT", t2("migrate.notDirectory"));
27791
+ if (await info6(to)) fail8("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
27792
+ if (!fromInfo) return fail8("NOTHING_TO_MIGRATE", t2("migrate.nothingToMigrate"));
27793
+ if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail8("PATH_CONFLICT", t2("migrate.notDirectory"));
27376
27794
  const configInfo = await info6(join16(from, "config.json"));
27377
- if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail7("NOT_INITIALIZED", t2("migrate.noConfig"));
27795
+ if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail8("NOT_INITIALIZED", t2("migrate.noConfig"));
27378
27796
  const config2 = parseManagedConfig(decode4(await readFile13(join16(from, "config.json"))));
27379
- if (!("schemaVersion" in config2)) fail7("UNSUPPORTED_FORMAT", t2("migrate.legacyJson"));
27797
+ if (!("schemaVersion" in config2)) fail8("UNSUPPORTED_FORMAT", t2("migrate.legacyJson"));
27380
27798
  const top = (await readdir6(from)).sort();
27381
- if (top.some((name) => name !== "config.json" && name !== "spec")) fail7("UNSUPPORTED_FORMAT", t2("migrate.extraEntries"));
27799
+ if (top.some((name) => name !== "config.json" && name !== "spec")) fail8("UNSUPPORTED_FORMAT", t2("migrate.extraEntries"));
27382
27800
  const files = /* @__PURE__ */ new Map();
27383
27801
  const rewrites = [];
27384
27802
  const legacyRecords = [];
@@ -27387,11 +27805,11 @@ async function migrateStore(cwd, dryRun = false) {
27387
27805
  for (const feature2 of (await readdir6(join16(from, "spec"))).sort()) {
27388
27806
  const dir = join16(from, "spec", feature2);
27389
27807
  const stat3 = await info6(dir);
27390
- if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail7("UNSUPPORTED_FORMAT", t2("migrate.notSpecFolder", { feature: feature2 }));
27808
+ if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail8("UNSUPPORTED_FORMAT", t2("migrate.notSpecFolder", { feature: feature2 }));
27391
27809
  for (const name of (await readdir6(dir)).sort()) {
27392
- if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail7("UNSUPPORTED_FORMAT", t2("migrate.unsupportedFile", { feature: feature2, name }));
27810
+ if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail8("UNSUPPORTED_FORMAT", t2("migrate.unsupportedFile", { feature: feature2, name }));
27393
27811
  const fileStat = await info6(join16(dir, name));
27394
- if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail7("UNSUPPORTED_FORMAT", t2("migrate.fileTooLarge", { name }));
27812
+ if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail8("UNSUPPORTED_FORMAT", t2("migrate.fileTooLarge", { name }));
27395
27813
  const newPath = `.gitifact/spec/${feature2}/${name}`;
27396
27814
  if (name === "tryce.json") {
27397
27815
  legacyRecords.push(newPath);
@@ -27408,9 +27826,9 @@ async function migrateStore(cwd, dryRun = false) {
27408
27826
  if (new RegExp(`^ {0,3}${fence.char}{${fence.size},}\\s*$`).test(line)) fence = void 0;
27409
27827
  return line;
27410
27828
  }
27411
- const open6 = /^ {0,3}(`{3,}|~{3,})/.exec(line);
27412
- if (open6) {
27413
- fence = { char: open6[1][0], size: open6[1].length };
27829
+ const open5 = /^ {0,3}(`{3,}|~{3,})/.exec(line);
27830
+ if (open5) {
27831
+ fence = { char: open5[1][0], size: open5[1].length };
27414
27832
  return line;
27415
27833
  }
27416
27834
  return marker2.test(line) ? line.replace(/^<!-- tryce-/, "<!-- gitifact-") : line;
@@ -27440,15 +27858,15 @@ async function migrateStore(cwd, dryRun = false) {
27440
27858
  ]
27441
27859
  });
27442
27860
  if (dryRun) return result("planned");
27443
- await rename6(from, to);
27861
+ await rename5(from, to);
27444
27862
  for (const r of rewrites) {
27445
27863
  const full = join16(root, r.path);
27446
27864
  const temp = join16(root, ".gitifact", "spec", ".gitifact-migrate-" + randomBytes3(8).toString("hex"));
27447
- await writeFile6(temp, r.content, { flag: "wx" });
27865
+ await writeFile5(temp, r.content, { flag: "wx" });
27448
27866
  try {
27449
- await rename6(temp, full);
27867
+ await rename5(temp, full);
27450
27868
  } finally {
27451
- await unlink7(temp).catch(() => {
27869
+ await unlink6(temp).catch(() => {
27452
27870
  });
27453
27871
  }
27454
27872
  }
@@ -27466,24 +27884,20 @@ async function runMigrate(options) {
27466
27884
  }
27467
27885
 
27468
27886
  // src/main.ts
27469
- var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.5.1").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
27887
+ var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.6.1").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
27470
27888
  program2.command("status").description(t2("help.status")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action(async (options) => {
27471
27889
  await runStatus(options.format);
27472
27890
  });
27473
- program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.5.1"));
27474
- program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.5.1"));
27891
+ program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.6.1"));
27892
+ program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.6.1"));
27475
27893
  program2.command("docs").description(t2("help.docs")).argument("[topic]", t2("help.docsTopic")).allowExcessArguments(false).action(async (topic) => {
27476
27894
  await runDocs(topic);
27477
27895
  });
27478
- program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).action((options) => runUpdate(options, "0.5.1"));
27896
+ program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).action((options) => runUpdate(options, "0.6.1"));
27479
27897
  program2.command("migrate").description(t2("help.migrate")).allowExcessArguments(false).option("--dry-run", t2("help.migrateDryRun")).action(runMigrate);
27480
27898
  var spec = program2.command("spec").description(t2("help.spec"));
27481
- var replaced = t2("help.deprecated");
27482
27899
  spec.command("commit").description(t2("help.specCommit")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specCommitFile")).option("--dry-run", t2("help.specCommitDryRun")).action((o) => runSpecPreview("commit", o));
27483
- for (const action of ["commit-plan", "commit-apply"]) spec.command(action).description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specCommitPlanFile")).action((o) => runSpecPreview(action, o));
27484
27900
  spec.command("changes").description(t2("help.specChanges")).allowExcessArguments(false).action((o) => runSpecPreview("changes", o));
27485
- spec.command("prepare").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specPrepareFile")).action((o) => runSpecPreview("prepare", o));
27486
- spec.command("verify").description(replaced).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specVerifyFile")).option("--staged", t2("help.specVerifyStaged")).action((o) => runSpecPreview("verify", o));
27487
27901
  spec.command("working").description(t2("help.specWorking")).allowExcessArguments(false).addOption(new Option("--stamp", t2("help.specWorkingStamp")).conflicts(["feature", "ids"])).option("--feature <name>", t2("help.specWorkingFeature")).option("--ids", t2("help.specWorkingIds")).action((o) => runSpecPreview("working", o));
27488
27902
  spec.command("save").description(t2("help.specSave")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specSaveFile")).action((o) => runSpecPreview("save", o));
27489
27903
  spec.command("read").description(t2("help.specRead")).allowExcessArguments(false).option("--ref <commit>", t2("help.specReadRef"), "HEAD").action((o) => runSpecPreview("read", o));