create-windy 0.6.8 → 0.6.10

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 (80) hide show
  1. package/README.md +4 -1
  2. package/dist/cli.js +1012 -329
  3. package/package.json +1 -1
  4. package/template/.windy-template.json +3 -3
  5. package/template/README.md +8 -2
  6. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +2 -0
  7. package/template/apps/agent-server/tests/test_multimodal.py +30 -0
  8. package/template/apps/agent-server/tests/test_postgres_store.py +1 -0
  9. package/template/apps/agent-server/tests/test_sqlite_store.py +1 -0
  10. package/template/apps/server/src/agent/remote-runtime.test.ts +1 -0
  11. package/template/apps/server/src/agent/run-audit.ts +1 -0
  12. package/template/apps/server/src/agent/run-contracts.ts +1 -0
  13. package/template/apps/server/src/agent/run-facade.ts +2 -2
  14. package/template/apps/server/src/agent/run-operation-registry.ts +7 -0
  15. package/template/apps/server/src/agent/run-output-schema.ts +15 -0
  16. package/template/apps/server/src/agent/run-release.ts +11 -0
  17. package/template/apps/server/src/agent/supervisor-output-schema.test.ts +95 -0
  18. package/template/apps/server/src/agent/vision-input.ts +37 -2
  19. package/template/apps/server/src/license/pairing-http.ts +138 -0
  20. package/template/apps/server/src/license/pairing-routes.test.ts +282 -0
  21. package/template/apps/server/src/license/pairing-routes.ts +257 -0
  22. package/template/apps/server/src/license/pairing-service.test.ts +320 -0
  23. package/template/apps/server/src/license/pairing-service.ts +321 -0
  24. package/template/apps/server/src/license/restriction.test.ts +11 -0
  25. package/template/apps/server/src/license/restriction.ts +5 -0
  26. package/template/apps/server/src/license/routes.ts +8 -1
  27. package/template/apps/server/src/license/runtime-service.ts +20 -0
  28. package/template/apps/server/src/runtime-development.ts +1 -0
  29. package/template/apps/web/package.json +6 -4
  30. package/template/apps/web/src/components/license/LicensePairingCard.vue +177 -0
  31. package/template/apps/web/src/components/license/LicensePairingCard.webtest.ts +113 -0
  32. package/template/apps/web/src/composables/useLicensePairing.ts +168 -0
  33. package/template/apps/web/src/composables/useLicenseRuntime.ts +11 -0
  34. package/template/apps/web/src/layout/AppSidebar.vue +1 -0
  35. package/template/apps/web/src/pages/license/LicensePage.vue +8 -0
  36. package/template/apps/web/src/pages/ui/UiComponentPage.vue +7 -0
  37. package/template/apps/web/src/pages/ui/UiComponentPage.webtest.ts +94 -0
  38. package/template/apps/web/src/pages/ui/component-catalog.ts +248 -0
  39. package/template/apps/web/src/pages/ui/components/ComponentPreviewCard.vue +50 -0
  40. package/template/apps/web/src/pages/ui/components/DataComponentShowcases.vue +131 -0
  41. package/template/apps/web/src/pages/ui/components/FeedbackComponentShowcases.vue +158 -0
  42. package/template/apps/web/src/pages/ui/components/FoundationComponentShowcases.vue +129 -0
  43. package/template/apps/web/src/pages/ui/components/NavigationComponentShowcases.vue +155 -0
  44. package/template/apps/web/src/pages/ui/components/ProjectComponentShowcases.vue +31 -0
  45. package/template/apps/web/src/pages/ui/components/UiComponentGallery.vue +238 -0
  46. package/template/apps/web/src/router/index.ts +2 -0
  47. package/template/apps/web/src/router/manifest-routes.webtest.ts +1 -0
  48. package/template/apps/web/src/router/platform-admin-route-bindings.ts +3 -1
  49. package/template/apps/web/src/services/license-api.ts +60 -0
  50. package/template/apps/web/src/style.webtest.ts +5 -6
  51. package/template/docs/architecture/ai-runtime.md +5 -0
  52. package/template/docs/development/business-web-routes.md +3 -1
  53. package/template/docs/development/ui-component-gallery.md +44 -0
  54. package/template/docs/license/license-pairing-activation.md +67 -0
  55. package/template/docs/operations/incremental-delivery.md +10 -9
  56. package/template/docs/platform/agent-supervisor-output-contract.md +80 -0
  57. package/template/packages/ai-client/package.json +1 -1
  58. package/template/packages/ai-client/src/agent/contracts/final-answer.test.ts +67 -0
  59. package/template/packages/ai-client/src/agent/contracts/final-answer.ts +53 -0
  60. package/template/packages/ai-client/src/agent/contracts/index.ts +1 -0
  61. package/template/packages/modules/index.ts +1 -0
  62. package/template/packages/modules/package.json +1 -1
  63. package/template/packages/modules/src/system-admin-routes.ts +8 -0
  64. package/template/packages/modules/src/system-admin-ui-catalog.ts +6 -2
  65. package/template/packages/modules/src/system-agent-supervisor.test.ts +48 -0
  66. package/template/packages/modules/src/system-agent-supervisor.ts +101 -0
  67. package/template/packages/modules/src/system-api-control-plane.ts +37 -0
  68. package/template/packages/modules/src/system-features.ts +5 -0
  69. package/template/packages/modules/src/system-license-pairing.test.ts +44 -0
  70. package/template/packages/modules/src/system-module-catalog.ts +10 -19
  71. package/template/packages/modules/src/system-module-menu-selection.ts +15 -0
  72. package/template/packages/modules/src/system-module-schema-catalog.ts +14 -0
  73. package/template/packages/modules/src/system-modules.ts +13 -0
  74. package/template/packages/modules/src/system-permissions.ts +2 -0
  75. package/template/packages/modules/src/system-ui-components.test.ts +36 -0
  76. package/template/packages/server-sdk/index.ts +5 -0
  77. package/template/packages/server-sdk/package.json +3 -1
  78. package/template/packages/server-sdk/src/ai-operation-registration.ts +4 -0
  79. package/template/packages/server-sdk/src/system-agent-supervisor.test.ts +87 -0
  80. package/template/packages/server-sdk/src/system-agent-supervisor.ts +89 -0
package/dist/cli.js CHANGED
@@ -388,6 +388,7 @@ var optionalModuleManifests = [
388
388
  "docs/platform/agent-run-attestation.md",
389
389
  "docs/platform/agent-runtime.md",
390
390
  "docs/platform/agent-runtime-observability.md",
391
+ "docs/platform/agent-supervisor-output-contract.md",
391
392
  "docs/platform/agent-tools.md",
392
393
  "docs/platform/agent-tool-approval.md",
393
394
  "docs/platform/agent-tool-sandbox.md",
@@ -653,7 +654,17 @@ var platformModules = [
653
654
  {
654
655
  sourceName: "@southwind-ai/license",
655
656
  name: "@southwind-ai/license",
656
- version: "^0.1.4"
657
+ version: "^0.1.9"
658
+ },
659
+ {
660
+ sourceName: "qrcode",
661
+ name: "qrcode",
662
+ version: "^1.5.4"
663
+ },
664
+ {
665
+ sourceName: "@types/qrcode",
666
+ name: "@types/qrcode",
667
+ version: "^1.5.6"
657
668
  }
658
669
  ],
659
670
  fileRoots: [
@@ -663,11 +674,16 @@ var platformModules = [
663
674
  "apps/web/src/composables/useLicenseReminderRefresh.ts",
664
675
  "apps/web/src/composables/useLicenseReminderRefresh.webtest.ts",
665
676
  "apps/web/src/composables/useLicenseRuntime.ts",
677
+ "apps/web/src/composables/useLicensePairing.ts",
666
678
  "apps/web/src/services/license-api.ts",
667
679
  "apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts",
668
- "apps/web/src/router/index.webtest.ts"
680
+ "apps/web/src/router/index.webtest.ts",
681
+ "packages/modules/src/system-license-pairing.test.ts"
682
+ ],
683
+ documentation: [
684
+ "docs/license/license-offline-activation-code.md",
685
+ "docs/license/license-pairing-activation.md"
669
686
  ],
670
- documentation: ["docs/license/license-offline-activation-code.md"],
671
687
  schemaFiles: [
672
688
  "packages/database/src/schema/license-legacy.ts",
673
689
  "packages/database/src/schema/license-v1.ts"
@@ -1309,11 +1325,11 @@ import {
1309
1325
  rm as rm4,
1310
1326
  writeFile as writeFile9
1311
1327
  } from "fs/promises";
1312
- import { basename as basename5, extname as extname3, join as join11 } from "path";
1328
+ import { basename as basename6, extname as extname3, join as join12 } from "path";
1313
1329
 
1314
1330
  // src/customer-docker.ts
1315
1331
  import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
1316
- import { join as join4 } from "path";
1332
+ import { join as join5 } from "path";
1317
1333
 
1318
1334
  // src/managed-files.ts
1319
1335
  import { createHash } from "crypto";
@@ -1533,37 +1549,38 @@ function matchesRoot(path, roots) {
1533
1549
  }
1534
1550
 
1535
1551
  // src/update/transaction-paths.ts
1536
- import { constants as constants3, closeSync as closeSync4 } from "fs";
1552
+ import { constants as constants4, closeSync as closeSync5 } from "fs";
1537
1553
  import { realpath, stat } from "fs/promises";
1538
- import { dirname as dirname2, resolve as resolve3 } from "path";
1554
+ import { dirname as dirname3, resolve as resolve3 } from "path";
1539
1555
 
1540
1556
  // src/update/transaction-native.ts
1541
1557
  import {
1542
- constants,
1543
- closeSync,
1558
+ constants as constants2,
1559
+ closeSync as closeSync2,
1544
1560
  fchmodSync,
1545
- fstatSync,
1561
+ fstatSync as fstatSync2,
1546
1562
  fsyncSync as fsyncSync2,
1547
1563
  readFileSync,
1548
1564
  writeSync
1549
1565
  } from "fs";
1550
- import { open as open2 } from "fs/promises";
1566
+ import { open as open3 } from "fs/promises";
1551
1567
  import {
1552
- basename as basename2,
1553
- dirname,
1568
+ basename as basename3,
1569
+ dirname as dirname2,
1554
1570
  isAbsolute,
1555
- relative as relative2,
1571
+ relative as relative3,
1556
1572
  resolve as resolve2,
1557
1573
  sep as sep2
1558
1574
  } from "path";
1559
- import { dlopen, FFIType, ptr, read } from "bun:ffi";
1575
+ import { dlopen as dlopen2, FFIType as FFIType2, ptr as ptr2, read } from "bun:ffi";
1560
1576
 
1561
1577
  // src/update/transaction-native-durability.ts
1562
1578
  import { fsyncSync } from "fs";
1563
1579
  var observer;
1564
1580
  function syncMutatedDirectory(operation, directoryFd) {
1565
1581
  observer?.({ operation, phase: "mutation", directoryFd });
1566
- fsyncSync(directoryFd);
1582
+ if (process.platform !== "win32")
1583
+ fsyncSync(directoryFd);
1567
1584
  observer?.({ operation, phase: "directory-fsync", directoryFd });
1568
1585
  }
1569
1586
 
@@ -1624,38 +1641,305 @@ function libcCandidates() {
1624
1641
  ];
1625
1642
  }
1626
1643
 
1644
+ // src/update/transaction-native-windows.ts
1645
+ import {
1646
+ closeSync,
1647
+ constants,
1648
+ fstatSync,
1649
+ linkSync,
1650
+ lstatSync,
1651
+ mkdirSync,
1652
+ openSync,
1653
+ rmdirSync,
1654
+ unlinkSync
1655
+ } from "fs";
1656
+ import { open as open2 } from "fs/promises";
1657
+ import { basename as basename2, dirname, join as join3, relative as relative2 } from "path";
1658
+
1659
+ // src/update/transaction-windows-api.ts
1660
+ import { dlopen, FFIType, ptr } from "bun:ffi";
1661
+ var moveFileWriteThrough = 8;
1662
+ var replaceFileWriteThrough = 2;
1663
+ var kernel32;
1664
+ function replaceWindowsFile(target, replacement, backup) {
1665
+ const api = windowsApi();
1666
+ const targetBuffer = wideString(target);
1667
+ const replacementBuffer = wideString(replacement);
1668
+ const backupBuffer = backup ? wideString(backup) : undefined;
1669
+ const result = api.symbols.ReplaceFileW(ptr(targetBuffer), ptr(replacementBuffer), backupBuffer ? ptr(backupBuffer) : null, replaceFileWriteThrough, null, null);
1670
+ if (!result)
1671
+ throw windowsError("ReplaceFileW", target);
1672
+ }
1673
+ function moveWindowsFileNoReplace(source, target) {
1674
+ const api = windowsApi();
1675
+ const sourceBuffer = wideString(source);
1676
+ const targetBuffer = wideString(target);
1677
+ if (!api.symbols.MoveFileExW(ptr(sourceBuffer), ptr(targetBuffer), moveFileWriteThrough)) {
1678
+ throw windowsError("MoveFileExW", `${source} -> ${target}`);
1679
+ }
1680
+ }
1681
+ function windowsApi() {
1682
+ if (process.env.WINDY_TEST_NATIVE_UNAVAILABLE === "1") {
1683
+ throw new Error("\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u53E5\u67C4 API\uFF1A\u6D4B\u8BD5\u4E0D\u53EF\u7528\u5E73\u53F0");
1684
+ }
1685
+ if (process.platform !== "win32") {
1686
+ throw new Error("Windows \u539F\u5B50\u76EE\u5F55\u9879 API \u5728\u5F53\u524D\u5E73\u53F0\u4E0D\u53EF\u7528");
1687
+ }
1688
+ return kernel32 ??= openWindowsApi();
1689
+ }
1690
+ function openWindowsApi() {
1691
+ return dlopen("kernel32.dll", {
1692
+ GetLastError: { args: [], returns: FFIType.u32 },
1693
+ MoveFileExW: {
1694
+ args: [FFIType.ptr, FFIType.ptr, FFIType.u32],
1695
+ returns: FFIType.i32
1696
+ },
1697
+ ReplaceFileW: {
1698
+ args: [
1699
+ FFIType.ptr,
1700
+ FFIType.ptr,
1701
+ FFIType.ptr,
1702
+ FFIType.u32,
1703
+ FFIType.ptr,
1704
+ FFIType.ptr
1705
+ ],
1706
+ returns: FFIType.i32
1707
+ }
1708
+ });
1709
+ }
1710
+ function windowsError(syscall, path) {
1711
+ const nativeCode = windowsApi().symbols.GetLastError();
1712
+ const code = nativeCode === 2 || nativeCode === 3 ? "ENOENT" : nativeCode === 80 || nativeCode === 183 ? "EEXIST" : nativeCode === 145 ? "ENOTEMPTY" : nativeCode === 5 ? "EACCES" : "EIO";
1713
+ return Object.assign(new Error(`${syscall} ${path} \u5931\u8D25\uFF08${nativeCode}\uFF09`), {
1714
+ code,
1715
+ errno: nativeCode,
1716
+ syscall,
1717
+ path
1718
+ });
1719
+ }
1720
+ function wideString(value) {
1721
+ return Buffer.from(`${value}\x00`, "utf16le");
1722
+ }
1723
+
1724
+ // src/update/transaction-native-windows.ts
1725
+ var directoryPaths = new Map;
1726
+ async function openWindowsAnchoredParent(root, target, createParents, createdDirectoryMode) {
1727
+ const parentPath = dirname(target);
1728
+ const relativeParent = relative2(root, parentPath);
1729
+ const components = relativeParent ? relativeParent.split(/[\\/]/) : [];
1730
+ const handles = [];
1731
+ const rootHandle = await openCheckedDirectory(root);
1732
+ handles.push(rootHandle);
1733
+ let currentPath = root;
1734
+ try {
1735
+ for (const component of components) {
1736
+ currentPath = join3(currentPath, component);
1737
+ try {
1738
+ assertDirectoryPath(currentPath);
1739
+ } catch (error) {
1740
+ if (!createParents || !hasFsCode(error, "ENOENT"))
1741
+ throw error;
1742
+ mkdirSync(currentPath, { mode: createdDirectoryMode });
1743
+ syncMutatedDirectory("mkdirat", handles.at(-1).fd);
1744
+ }
1745
+ handles.push(await openCheckedDirectory(currentPath));
1746
+ }
1747
+ } catch (error) {
1748
+ await closeHandles(handles);
1749
+ throw error;
1750
+ }
1751
+ const directoryHandle = handles.at(-1);
1752
+ return {
1753
+ fd: directoryHandle.fd,
1754
+ leaf: basename2(target),
1755
+ directoryPath: currentPath,
1756
+ async close() {
1757
+ await closeHandles(handles);
1758
+ }
1759
+ };
1760
+ }
1761
+ function windowsOpenFileAt(parent, flags, mode) {
1762
+ const directoryPath = parent.directoryPath ?? windowsDirectoryPath(parent.fd);
1763
+ assertDirectoryHandle(parent.fd, directoryPath);
1764
+ const path = childPath(directoryPath, parent.leaf);
1765
+ let before;
1766
+ try {
1767
+ before = lstatSync(path, { bigint: true });
1768
+ if (before.isSymbolicLink())
1769
+ throw reparseError(path);
1770
+ } catch (error) {
1771
+ if (!hasFsCode(error, "ENOENT"))
1772
+ throw error;
1773
+ }
1774
+ const fd = openSync(path, flags, mode);
1775
+ try {
1776
+ if (before) {
1777
+ const opened = fstatSync(fd, { bigint: true });
1778
+ if (opened.dev !== before.dev || opened.ino !== before.ino) {
1779
+ throw reparseError(path);
1780
+ }
1781
+ }
1782
+ return fd;
1783
+ } catch (error) {
1784
+ closeSync(fd);
1785
+ throw error;
1786
+ }
1787
+ }
1788
+ function windowsLinkAt(parent, sourceName, targetName) {
1789
+ assertDirectoryHandle(parent.fd, parent.directoryPath);
1790
+ linkSync(childPath(parent.directoryPath, sourceName), childPath(parent.directoryPath, targetName));
1791
+ }
1792
+ function windowsUnlinkAt(parent, name, directory) {
1793
+ assertDirectoryHandle(parent.fd, parent.directoryPath);
1794
+ const path = childPath(parent.directoryPath, name);
1795
+ const info = lstatSync(path);
1796
+ if (info.isSymbolicLink())
1797
+ throw reparseError(path);
1798
+ if (directory)
1799
+ rmdirSync(path);
1800
+ else
1801
+ unlinkSync(path);
1802
+ }
1803
+ function windowsOpenChildDirectoryAt(directoryFd, name) {
1804
+ const parentPath = windowsDirectoryPath(directoryFd);
1805
+ assertDirectoryHandle(directoryFd, parentPath);
1806
+ const path = childPath(parentPath, name);
1807
+ assertDirectoryPath(path);
1808
+ const fd = openSync(path, constants.O_RDONLY);
1809
+ try {
1810
+ registerDirectory(fd, path);
1811
+ assertDirectoryHandle(fd, path);
1812
+ return fd;
1813
+ } catch (error) {
1814
+ directoryPaths.delete(fd);
1815
+ closeSync(fd);
1816
+ throw error;
1817
+ }
1818
+ }
1819
+ function closeWindowsDirectoryFd(fd) {
1820
+ directoryPaths.delete(fd);
1821
+ closeSync(fd);
1822
+ }
1823
+ function windowsExchangeAt(parent, left, right) {
1824
+ assertDirectoryHandle(parent.fd, parent.directoryPath);
1825
+ const leftPath = childPath(parent.directoryPath, left);
1826
+ const rightPath = childPath(parent.directoryPath, right);
1827
+ const backupPath = `${leftPath}.exchange-backup`;
1828
+ assertMissing(backupPath);
1829
+ replaceWindowsFile(rightPath, leftPath, backupPath);
1830
+ try {
1831
+ moveWindowsFileNoReplace(backupPath, leftPath);
1832
+ } catch (error) {
1833
+ try {
1834
+ replaceWindowsFile(rightPath, backupPath);
1835
+ } catch {}
1836
+ throw error;
1837
+ }
1838
+ }
1839
+ function windowsMoveNoReplaceAt(parent, source, target) {
1840
+ assertDirectoryHandle(parent.fd, parent.directoryPath);
1841
+ moveWindowsFileNoReplace(childPath(parent.directoryPath, source), childPath(parent.directoryPath, target));
1842
+ }
1843
+ function windowsDirectoryPath(fd) {
1844
+ const path = directoryPaths.get(fd);
1845
+ if (!path)
1846
+ throw new Error("Windows \u4E8B\u52A1\u76EE\u5F55\u53E5\u67C4\u672A\u6CE8\u518C\uFF0C\u4E8B\u52A1\u5B89\u5168\u5173\u95ED");
1847
+ return path;
1848
+ }
1849
+ async function openCheckedDirectory(path) {
1850
+ assertDirectoryPath(path);
1851
+ const handle = await open2(path, constants.O_RDONLY);
1852
+ try {
1853
+ registerDirectory(handle.fd, path);
1854
+ assertDirectoryHandle(handle.fd, path);
1855
+ return handle;
1856
+ } catch (error) {
1857
+ directoryPaths.delete(handle.fd);
1858
+ await handle.close();
1859
+ throw error;
1860
+ }
1861
+ }
1862
+ function registerDirectory(fd, path) {
1863
+ directoryPaths.set(fd, path);
1864
+ }
1865
+ async function closeHandles(handles) {
1866
+ for (const handle of handles.reverse()) {
1867
+ directoryPaths.delete(handle.fd);
1868
+ await handle.close();
1869
+ }
1870
+ }
1871
+ function assertDirectoryPath(path) {
1872
+ const info = lstatSync(path, { bigint: true });
1873
+ if (info.isSymbolicLink())
1874
+ throw reparseError(path);
1875
+ if (!info.isDirectory())
1876
+ throw fsError("ENOTDIR", path);
1877
+ }
1878
+ function assertDirectoryHandle(fd, path) {
1879
+ const opened = fstatSync(fd, { bigint: true });
1880
+ const current = lstatSync(path, { bigint: true });
1881
+ if (current.isSymbolicLink() || !opened.isDirectory() || !current.isDirectory() || opened.dev !== current.dev || opened.ino !== current.ino) {
1882
+ throw reparseError(path);
1883
+ }
1884
+ }
1885
+ function childPath(directory, name) {
1886
+ if (!name || name.includes("/") || name.includes("\\") || name.includes("\x00")) {
1887
+ throw new Error(`Windows \u4E8B\u52A1\u76EE\u5F55\u9879\u540D\u79F0\u4E0D\u5B89\u5168\uFF1A${name}`);
1888
+ }
1889
+ return join3(directory, name);
1890
+ }
1891
+ function assertMissing(path) {
1892
+ try {
1893
+ lstatSync(path);
1894
+ } catch (error) {
1895
+ if (hasFsCode(error, "ENOENT"))
1896
+ return;
1897
+ throw error;
1898
+ }
1899
+ throw fsError("EEXIST", path);
1900
+ }
1901
+ function reparseError(path) {
1902
+ return fsError("ELOOP", path);
1903
+ }
1904
+ function fsError(code, path) {
1905
+ return Object.assign(new Error(`${code}: ${path}`), { code, path });
1906
+ }
1907
+ function hasFsCode(error, code) {
1908
+ return error instanceof Error && "code" in error && error.code === code;
1909
+ }
1910
+
1627
1911
  // src/update/transaction-native.ts
1628
1912
  var nativeSymbols = {
1629
1913
  openat: {
1630
- args: [FFIType.i32, FFIType.ptr, FFIType.i32, FFIType.i32],
1631
- returns: FFIType.i32
1914
+ args: [FFIType2.i32, FFIType2.ptr, FFIType2.i32, FFIType2.i32],
1915
+ returns: FFIType2.i32
1632
1916
  },
1633
1917
  mkdirat: {
1634
- args: [FFIType.i32, FFIType.ptr, FFIType.i32],
1635
- returns: FFIType.i32
1918
+ args: [FFIType2.i32, FFIType2.ptr, FFIType2.i32],
1919
+ returns: FFIType2.i32
1636
1920
  },
1637
1921
  linkat: {
1638
- args: [FFIType.i32, FFIType.ptr, FFIType.i32, FFIType.ptr, FFIType.i32],
1639
- returns: FFIType.i32
1922
+ args: [FFIType2.i32, FFIType2.ptr, FFIType2.i32, FFIType2.ptr, FFIType2.i32],
1923
+ returns: FFIType2.i32
1640
1924
  },
1641
1925
  unlinkat: {
1642
- args: [FFIType.i32, FFIType.ptr, FFIType.i32],
1643
- returns: FFIType.i32
1926
+ args: [FFIType2.i32, FFIType2.ptr, FFIType2.i32],
1927
+ returns: FFIType2.i32
1644
1928
  },
1645
1929
  [process.platform === "darwin" ? "__error" : "__errno_location"]: {
1646
1930
  args: [],
1647
- returns: FFIType.ptr
1931
+ returns: FFIType2.ptr
1648
1932
  }
1649
1933
  };
1650
- var directoryFlags = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;
1934
+ var directoryFlags = constants2.O_RDONLY | constants2.O_DIRECTORY | constants2.O_NOFOLLOW;
1651
1935
  var removeDirectoryFlag = process.platform === "darwin" ? 128 : 512;
1652
- var getLibc = createLazyLibcLoader((candidate) => dlopen(candidate, nativeSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u53E5\u67C4 API");
1936
+ var getLibc = createLazyLibcLoader((candidate) => dlopen2(candidate, nativeSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u53E5\u67C4 API");
1653
1937
  function resolveSafeTarget(root, path) {
1654
1938
  if (!path || isAbsolute(path) || path.includes("\x00") || path.split(/[\\/]/).includes("..")) {
1655
1939
  throw new Error(`\u66F4\u65B0\u8BA1\u5212\u5305\u542B\u4E0D\u5B89\u5168\u8DEF\u5F84\uFF1A${path}`);
1656
1940
  }
1657
1941
  const target = resolve2(root, path);
1658
- const pathFromRoot = relative2(root, target);
1942
+ const pathFromRoot = relative3(root, target);
1659
1943
  if (pathFromRoot === ".." || pathFromRoot.startsWith(`..${sep2}`) || isAbsolute(pathFromRoot)) {
1660
1944
  throw new Error(`\u66F4\u65B0\u8BA1\u5212\u5305\u542B\u4E0D\u5B89\u5168\u8DEF\u5F84\uFF1A${path}`);
1661
1945
  }
@@ -1663,9 +1947,15 @@ function resolveSafeTarget(root, path) {
1663
1947
  }
1664
1948
  async function openAnchoredParent(root, path, createParents, createdDirectoryMode = 448) {
1665
1949
  const target = resolveSafeTarget(root, path);
1666
- const parentPath = relative2(root, dirname(target));
1950
+ if (process.platform === "win32") {
1951
+ if (process.env.WINDY_TEST_NATIVE_UNAVAILABLE === "1") {
1952
+ throw new Error("\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u53E5\u67C4 API\uFF1A\u6D4B\u8BD5\u4E0D\u53EF\u7528\u5E73\u53F0");
1953
+ }
1954
+ return openWindowsAnchoredParent(root, target, createParents, createdDirectoryMode);
1955
+ }
1956
+ const parentPath = relative3(root, dirname2(target));
1667
1957
  const components = parentPath === "" ? [] : parentPath.split(sep2).filter(Boolean);
1668
- const rootHandle = await open2(root, directoryFlags);
1958
+ const rootHandle = await open3(root, directoryFlags);
1669
1959
  const childDescriptors = [];
1670
1960
  let current = rootHandle.fd;
1671
1961
  try {
@@ -1675,13 +1965,13 @@ async function openAnchoredParent(root, path, createParents, createdDirectoryMod
1675
1965
  try {
1676
1966
  child = nativeOpenAt(current, component, directoryFlags);
1677
1967
  } catch (error) {
1678
- if (!createParents || !hasFsCode(error, "ENOENT"))
1968
+ if (!createParents || !hasFsCode2(error, "ENOENT"))
1679
1969
  throw error;
1680
1970
  try {
1681
1971
  nativeMkdirAt(current, component, createdDirectoryMode);
1682
1972
  created = true;
1683
1973
  } catch (mkdirError) {
1684
- if (!hasFsCode(mkdirError, "EEXIST"))
1974
+ if (!hasFsCode2(mkdirError, "EEXIST"))
1685
1975
  throw mkdirError;
1686
1976
  }
1687
1977
  child = nativeOpenAt(current, component, directoryFlags);
@@ -1698,7 +1988,7 @@ async function openAnchoredParent(root, path, createParents, createdDirectoryMod
1698
1988
  }
1699
1989
  return {
1700
1990
  fd: current,
1701
- leaf: basename2(target),
1991
+ leaf: basename3(target),
1702
1992
  async close() {
1703
1993
  closeDescriptors(childDescriptors);
1704
1994
  await rootHandle.close();
@@ -1706,32 +1996,35 @@ async function openAnchoredParent(root, path, createParents, createdDirectoryMod
1706
1996
  };
1707
1997
  }
1708
1998
  function openFileAt(parent, flags, mode = 384) {
1999
+ if (process.platform === "win32") {
2000
+ return windowsOpenFileAt(parent, flags, mode);
2001
+ }
1709
2002
  return nativeOpenAt(parent.fd, parent.leaf, flags, mode);
1710
2003
  }
1711
2004
  function readFileAt(parent) {
1712
- const fd = openFileAt(parent, constants.O_RDONLY | constants.O_NOFOLLOW);
2005
+ const fd = openFileAt(parent, constants2.O_RDONLY | constants2.O_NOFOLLOW);
1713
2006
  try {
1714
- const info = fstatSync(fd);
2007
+ const info = fstatSync2(fd);
1715
2008
  if (!info.isFile())
1716
2009
  throw new Error(`\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${parent.leaf}`);
1717
2010
  return readFileSync(fd);
1718
2011
  } finally {
1719
- closeSync(fd);
2012
+ closeSync2(fd);
1720
2013
  }
1721
2014
  }
1722
2015
  function fileModeAt(parent) {
1723
- const fd = openFileAt(parent, constants.O_RDONLY | constants.O_NOFOLLOW);
2016
+ const fd = openFileAt(parent, constants2.O_RDONLY | constants2.O_NOFOLLOW);
1724
2017
  try {
1725
- const info = fstatSync(fd);
2018
+ const info = fstatSync2(fd);
1726
2019
  if (!info.isFile())
1727
2020
  throw new Error(`\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${parent.leaf}`);
1728
2021
  return info.mode & 511;
1729
2022
  } finally {
1730
- closeSync(fd);
2023
+ closeSync2(fd);
1731
2024
  }
1732
2025
  }
1733
2026
  function writeExclusiveAt(parent, content, mode = 384) {
1734
- const fd = openFileAt(parent, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, mode);
2027
+ const fd = openFileAt(parent, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, mode);
1735
2028
  try {
1736
2029
  fchmodSync(fd, mode);
1737
2030
  const buffer = typeof content === "string" ? Buffer.from(content) : Buffer.from(content);
@@ -1741,34 +2034,58 @@ function writeExclusiveAt(parent, content, mode = 384) {
1741
2034
  }
1742
2035
  fsyncSync2(fd);
1743
2036
  } finally {
1744
- closeSync(fd);
2037
+ closeSync2(fd);
1745
2038
  }
1746
2039
  syncMutatedDirectory("create", parent.fd);
1747
2040
  }
1748
2041
  function linkAt(parent, sourceName, targetName) {
2042
+ if (process.platform === "win32") {
2043
+ windowsLinkAt(parent, sourceName, targetName);
2044
+ syncMutatedDirectory("linkat", parent.fd);
2045
+ return;
2046
+ }
1749
2047
  const libc = getLibc();
1750
2048
  const sourceBuffer = cString(sourceName);
1751
2049
  const targetBuffer = cString(targetName);
1752
- if (libc.symbols.linkat(parent.fd, ptr(sourceBuffer), parent.fd, ptr(targetBuffer), 0) < 0) {
2050
+ if (libc.symbols.linkat(parent.fd, ptr2(sourceBuffer), parent.fd, ptr2(targetBuffer), 0) < 0) {
1753
2051
  throw nativeError("linkat", `${sourceName} -> ${targetName}`);
1754
2052
  }
1755
2053
  syncMutatedDirectory("linkat", parent.fd);
1756
2054
  }
1757
2055
  function unlinkAt(parent, directory = false) {
2056
+ if (process.platform === "win32") {
2057
+ windowsUnlinkAt(parent, parent.leaf, directory);
2058
+ syncMutatedDirectory("unlinkat", parent.fd);
2059
+ return;
2060
+ }
1758
2061
  nativeUnlinkAt(parent.fd, parent.leaf, directory ? removeDirectoryFlag : 0);
1759
2062
  syncMutatedDirectory("unlinkat", parent.fd);
1760
2063
  }
1761
2064
  function openChildDirectoryAt(directoryFd, name) {
2065
+ if (process.platform === "win32") {
2066
+ return windowsOpenChildDirectoryAt(directoryFd, name);
2067
+ }
1762
2068
  return nativeOpenAt(directoryFd, name, directoryFlags);
1763
2069
  }
1764
2070
  function unlinkNameAt(directoryFd, name, directory = false) {
2071
+ if (process.platform === "win32") {
2072
+ const parent = {
2073
+ fd: directoryFd,
2074
+ leaf: name,
2075
+ directoryPath: windowsDirectoryPath(directoryFd),
2076
+ async close() {}
2077
+ };
2078
+ windowsUnlinkAt(parent, name, directory);
2079
+ syncMutatedDirectory("unlinkat", directoryFd);
2080
+ return;
2081
+ }
1765
2082
  nativeUnlinkAt(directoryFd, name, directory ? removeDirectoryFlag : 0);
1766
2083
  syncMutatedDirectory("unlinkat", directoryFd);
1767
2084
  }
1768
2085
  function nativeOpenAt(directoryFd, name, flags, mode = 0) {
1769
2086
  const libc = getLibc();
1770
2087
  const nameBuffer = cString(name);
1771
- const result = libc.symbols.openat(directoryFd, ptr(nameBuffer), flags, mode);
2088
+ const result = libc.symbols.openat(directoryFd, ptr2(nameBuffer), flags, mode);
1772
2089
  if (result < 0)
1773
2090
  throw nativeError("openat", name);
1774
2091
  return result;
@@ -1776,7 +2093,7 @@ function nativeOpenAt(directoryFd, name, flags, mode = 0) {
1776
2093
  function nativeMkdirAt(directoryFd, name, mode) {
1777
2094
  const libc = getLibc();
1778
2095
  const nameBuffer = cString(name);
1779
- if (libc.symbols.mkdirat(directoryFd, ptr(nameBuffer), mode) < 0) {
2096
+ if (libc.symbols.mkdirat(directoryFd, ptr2(nameBuffer), mode) < 0) {
1780
2097
  throw nativeError("mkdirat", name);
1781
2098
  }
1782
2099
  syncMutatedDirectory("mkdirat", directoryFd);
@@ -1784,7 +2101,7 @@ function nativeMkdirAt(directoryFd, name, mode) {
1784
2101
  function nativeUnlinkAt(directoryFd, name, flags) {
1785
2102
  const libc = getLibc();
1786
2103
  const nameBuffer = cString(name);
1787
- if (libc.symbols.unlinkat(directoryFd, ptr(nameBuffer), flags) < 0) {
2104
+ if (libc.symbols.unlinkat(directoryFd, ptr2(nameBuffer), flags) < 0) {
1788
2105
  throw nativeError("unlinkat", name);
1789
2106
  }
1790
2107
  }
@@ -1808,35 +2125,38 @@ function cString(value) {
1808
2125
  }
1809
2126
  function closeDescriptors(descriptors) {
1810
2127
  for (const descriptor of descriptors.reverse())
1811
- closeSync(descriptor);
2128
+ closeSync2(descriptor);
1812
2129
  }
1813
- function hasFsCode(error, code) {
2130
+ function hasFsCode2(error, code) {
1814
2131
  return error instanceof Error && "code" in error && error.code === code;
1815
2132
  }
1816
2133
 
1817
2134
  // src/update/transaction-tree.ts
1818
- import { constants as constants2, closeSync as closeSync3, fstatSync as fstatSync2 } from "fs";
2135
+ import { constants as constants3, closeSync as closeSync4, fstatSync as fstatSync3 } from "fs";
1819
2136
 
1820
2137
  // src/update/transaction-native-directory.ts
1821
- import { closeSync as closeSync2 } from "fs";
1822
- import { dlopen as dlopen2, FFIType as FFIType2, read as read2, toArrayBuffer } from "bun:ffi";
2138
+ import { closeSync as closeSync3, readdirSync } from "fs";
2139
+ import { dlopen as dlopen3, FFIType as FFIType3, read as read2, toArrayBuffer } from "bun:ffi";
1823
2140
  var errnoName = process.platform === "darwin" ? "__error" : "__errno_location";
1824
2141
  var symbols = {
1825
- dup: { args: [FFIType2.i32], returns: FFIType2.i32 },
1826
- fdopendir: { args: [FFIType2.i32], returns: FFIType2.ptr },
1827
- readdir: { args: [FFIType2.ptr], returns: FFIType2.ptr },
1828
- closedir: { args: [FFIType2.ptr], returns: FFIType2.i32 },
1829
- [errnoName]: { args: [], returns: FFIType2.ptr }
2142
+ dup: { args: [FFIType3.i32], returns: FFIType3.i32 },
2143
+ fdopendir: { args: [FFIType3.i32], returns: FFIType3.ptr },
2144
+ readdir: { args: [FFIType3.ptr], returns: FFIType3.ptr },
2145
+ closedir: { args: [FFIType3.ptr], returns: FFIType3.i32 },
2146
+ [errnoName]: { args: [], returns: FFIType3.ptr }
1830
2147
  };
1831
- var getLibc2 = createLazyLibcLoader((candidate) => dlopen2(candidate, symbols), "\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u679A\u4E3E API\uFF0C\u4E8B\u52A1\u5B89\u5168\u5173\u95ED");
2148
+ var getLibc2 = createLazyLibcLoader((candidate) => dlopen3(candidate, symbols), "\u65E0\u6CD5\u52A0\u8F7D\u5B89\u5168\u76EE\u5F55\u679A\u4E3E API\uFF0C\u4E8B\u52A1\u5B89\u5168\u5173\u95ED");
1832
2149
  function readDirectoryNames(directoryFd) {
2150
+ if (process.platform === "win32") {
2151
+ return readdirSync(windowsDirectoryPath(directoryFd));
2152
+ }
1833
2153
  const libc = getLibc2();
1834
2154
  const duplicate = libc.symbols.dup(directoryFd);
1835
2155
  if (duplicate < 0)
1836
2156
  throw new Error("\u65E0\u6CD5\u590D\u5236\u5907\u4EFD\u76EE\u5F55\u53E5\u67C4\uFF0C\u4E8B\u52A1\u5B89\u5168\u5173\u95ED");
1837
2157
  const directory = libc.symbols.fdopendir(duplicate);
1838
2158
  if (!directory) {
1839
- closeSync2(duplicate);
2159
+ closeSync3(duplicate);
1840
2160
  throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u5907\u4EFD\u76EE\u5F55\u53E5\u67C4\uFF0C\u4E8B\u52A1\u5B89\u5168\u5173\u95ED");
1841
2161
  }
1842
2162
  const names = [];
@@ -1891,7 +2211,7 @@ async function removeKnownTree(root, path, knownFiles, hooks) {
1891
2211
  try {
1892
2212
  parent = await openAnchoredParent(root, path, false);
1893
2213
  } catch (error) {
1894
- if (hasFsCode2(error, "ENOENT"))
2214
+ if (hasFsCode3(error, "ENOENT"))
1895
2215
  return;
1896
2216
  throw safePathError(error, path);
1897
2217
  }
@@ -1908,11 +2228,11 @@ async function removeKnownTree(root, path, knownFiles, hooks) {
1908
2228
  }
1909
2229
  unlinkAt(parent, true);
1910
2230
  } catch (error) {
1911
- if (!hasFsCode2(error, "ENOENT"))
2231
+ if (!hasFsCode3(error, "ENOENT"))
1912
2232
  throw safePathError(error, path);
1913
2233
  } finally {
1914
2234
  if (treeFd !== undefined)
1915
- closeSync3(treeFd);
2235
+ closeDirectory(treeFd);
1916
2236
  await parent.close();
1917
2237
  }
1918
2238
  }
@@ -1934,7 +2254,7 @@ function inspectDirectory(directoryFd, directory, expected) {
1934
2254
  try {
1935
2255
  inspectDirectory(childFd, directory ? `${directory}/${name}` : name, expected);
1936
2256
  } finally {
1937
- closeSync3(childFd);
2257
+ closeDirectory(childFd);
1938
2258
  }
1939
2259
  }
1940
2260
  }
@@ -1944,13 +2264,13 @@ function assertRegularFile(directoryFd, name) {
1944
2264
  leaf: name,
1945
2265
  async close() {}
1946
2266
  };
1947
- const fileFd = openFileAt(parent, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
2267
+ const fileFd = openFileAt(parent, constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK);
1948
2268
  try {
1949
- if (!fstatSync2(fileFd).isFile()) {
2269
+ if (!fstatSync3(fileFd).isFile()) {
1950
2270
  throw new Error(`\u5907\u4EFD\u6761\u76EE\u7C7B\u578B\u5F02\u5E38\uFF1A${name}`);
1951
2271
  }
1952
2272
  } finally {
1953
- closeSync3(fileFd);
2273
+ closeSync4(fileFd);
1954
2274
  }
1955
2275
  }
1956
2276
  function expectedTree(files) {
@@ -1996,13 +2316,19 @@ async function removeTreeEntry(treeFd, path, directory) {
1996
2316
  }
1997
2317
  unlinkNameAt(current, leaf, directory);
1998
2318
  } catch (error) {
1999
- if (!hasFsCode2(error, "ENOENT"))
2319
+ if (!hasFsCode3(error, "ENOENT"))
2000
2320
  throw error;
2001
2321
  } finally {
2002
2322
  for (const descriptor of descriptors.reverse())
2003
- closeSync3(descriptor);
2323
+ closeDirectory(descriptor);
2004
2324
  }
2005
2325
  }
2326
+ function closeDirectory(fd) {
2327
+ if (process.platform === "win32")
2328
+ closeWindowsDirectoryFd(fd);
2329
+ else
2330
+ closeSync4(fd);
2331
+ }
2006
2332
  function assertKnownTreePath(path) {
2007
2333
  const parts = path.split("/");
2008
2334
  if (!path || path.includes("\\") || path.includes("\x00") || parts.some((part) => !part || part === "." || part === "..")) {
@@ -2011,14 +2337,14 @@ function assertKnownTreePath(path) {
2011
2337
  return parts.join("/");
2012
2338
  }
2013
2339
  function safePathError(error, path) {
2014
- if (hasFsCode2(error, "ELOOP") || hasFsCode2(error, "ENOTDIR")) {
2340
+ if (hasFsCode3(error, "ELOOP") || hasFsCode3(error, "ENOTDIR")) {
2015
2341
  return new Error(`\u4E8B\u52A1\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u6216\u975E\u76EE\u5F55\u7EC4\u4EF6\uFF1A${path}`, {
2016
2342
  cause: error
2017
2343
  });
2018
2344
  }
2019
2345
  return error;
2020
2346
  }
2021
- function hasFsCode2(error, code) {
2347
+ function hasFsCode3(error, code) {
2022
2348
  return error instanceof Error && "code" in error && error.code === code;
2023
2349
  }
2024
2350
 
@@ -2041,15 +2367,15 @@ async function inspectSafePath(root, path) {
2041
2367
  try {
2042
2368
  parent = await openAnchoredParent(root, path, false);
2043
2369
  } catch (error) {
2044
- if (hasFsCode3(error, "ENOENT"))
2370
+ if (hasFsCode4(error, "ENOENT"))
2045
2371
  return target;
2046
2372
  throw safePathError2(error, path);
2047
2373
  }
2048
2374
  try {
2049
- const fd = openFileAt(parent, constants3.O_RDONLY | constants3.O_NOFOLLOW);
2050
- closeSync4(fd);
2375
+ const fd = openFileAt(parent, constants4.O_RDONLY | constants4.O_NOFOLLOW);
2376
+ closeSync5(fd);
2051
2377
  } catch (error) {
2052
- if (hasFsCode3(error, "ENOENT"))
2378
+ if (hasFsCode4(error, "ENOENT"))
2053
2379
  return target;
2054
2380
  throw safePathError2(error, path);
2055
2381
  } finally {
@@ -2062,16 +2388,16 @@ async function safePathExists(root, path) {
2062
2388
  try {
2063
2389
  parent = await openAnchoredParent(root, path, false);
2064
2390
  } catch (error) {
2065
- if (hasFsCode3(error, "ENOENT"))
2391
+ if (hasFsCode4(error, "ENOENT"))
2066
2392
  return false;
2067
2393
  throw safePathError2(error, path);
2068
2394
  }
2069
2395
  try {
2070
- const fd = openFileAt(parent, constants3.O_RDONLY | constants3.O_NOFOLLOW);
2071
- closeSync4(fd);
2396
+ const fd = openFileAt(parent, constants4.O_RDONLY | constants4.O_NOFOLLOW);
2397
+ closeSync5(fd);
2072
2398
  return true;
2073
2399
  } catch (error) {
2074
- if (hasFsCode3(error, "ENOENT"))
2400
+ if (hasFsCode4(error, "ENOENT"))
2075
2401
  return false;
2076
2402
  throw safePathError2(error, path);
2077
2403
  } finally {
@@ -2083,14 +2409,14 @@ async function readSafeOptional(root, path) {
2083
2409
  try {
2084
2410
  parent = await openAnchoredParent(root, path, false);
2085
2411
  } catch (error) {
2086
- if (hasFsCode3(error, "ENOENT"))
2412
+ if (hasFsCode4(error, "ENOENT"))
2087
2413
  return;
2088
2414
  throw safePathError2(error, path);
2089
2415
  }
2090
2416
  try {
2091
2417
  return readFileAt(parent);
2092
2418
  } catch (error) {
2093
- if (hasFsCode3(error, "ENOENT"))
2419
+ if (hasFsCode4(error, "ENOENT"))
2094
2420
  return;
2095
2421
  throw safePathError2(error, path);
2096
2422
  } finally {
@@ -2102,14 +2428,14 @@ async function safeFileMode(root, path) {
2102
2428
  try {
2103
2429
  parent = await openAnchoredParent(root, path, false);
2104
2430
  } catch (error) {
2105
- if (hasFsCode3(error, "ENOENT"))
2431
+ if (hasFsCode4(error, "ENOENT"))
2106
2432
  return;
2107
2433
  throw safePathError2(error, path);
2108
2434
  }
2109
2435
  try {
2110
2436
  return fileModeAt(parent);
2111
2437
  } catch (error) {
2112
- if (hasFsCode3(error, "ENOENT"))
2438
+ if (hasFsCode4(error, "ENOENT"))
2113
2439
  return;
2114
2440
  throw safePathError2(error, path);
2115
2441
  } finally {
@@ -2146,7 +2472,7 @@ async function validateBackupDirectory(root, updateId, backupDirectory) {
2146
2472
  return relativePath;
2147
2473
  }
2148
2474
  async function removeEmptyDeletedFileParents(deletedFile, projectRoot) {
2149
- let directory = dirname2(deletedFile);
2475
+ let directory = dirname3(deletedFile);
2150
2476
  while (directory !== ".") {
2151
2477
  try {
2152
2478
  await removeEmptyDirectorySafe(projectRoot, directory);
@@ -2155,7 +2481,7 @@ async function removeEmptyDeletedFileParents(deletedFile, projectRoot) {
2155
2481
  return;
2156
2482
  throw error;
2157
2483
  }
2158
- directory = dirname2(directory);
2484
+ directory = dirname3(directory);
2159
2485
  }
2160
2486
  }
2161
2487
  async function removeEmptyDirectorySafe(root, path) {
@@ -2163,24 +2489,24 @@ async function removeEmptyDirectorySafe(root, path) {
2163
2489
  try {
2164
2490
  parent = await openAnchoredParent(root, path, false);
2165
2491
  } catch (error) {
2166
- if (hasFsCode3(error, "ENOENT"))
2492
+ if (hasFsCode4(error, "ENOENT"))
2167
2493
  return;
2168
2494
  throw safePathError2(error, path);
2169
2495
  }
2170
2496
  try {
2171
2497
  unlinkAt(parent, true);
2172
2498
  } catch (error) {
2173
- if (!hasFsCode3(error, "ENOENT"))
2499
+ if (!hasFsCode4(error, "ENOENT"))
2174
2500
  throw safePathError2(error, path);
2175
2501
  } finally {
2176
2502
  await parent.close();
2177
2503
  }
2178
2504
  }
2179
- function hasFsCode3(error, code) {
2505
+ function hasFsCode4(error, code) {
2180
2506
  return error instanceof Error && "code" in error && error.code === code;
2181
2507
  }
2182
2508
  function safePathError2(error, path) {
2183
- if (hasFsCode3(error, "ELOOP") || hasFsCode3(error, "ENOTDIR")) {
2509
+ if (hasFsCode4(error, "ELOOP") || hasFsCode4(error, "ENOTDIR")) {
2184
2510
  return new Error(`\u4E8B\u52A1\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u6216\u975E\u76EE\u5F55\u7EC4\u4EF6\uFF1A${path}`, {
2185
2511
  cause: error
2186
2512
  });
@@ -2196,7 +2522,7 @@ function isDirectoryNotRemovable(error) {
2196
2522
 
2197
2523
  // src/workspace-membership.ts
2198
2524
  import { readdir as readdir2 } from "fs/promises";
2199
- import { join as join3 } from "path";
2525
+ import { join as join4 } from "path";
2200
2526
  function deriveFinalWorkspaceMembership(current, target, files) {
2201
2527
  const membersByBase = new Map;
2202
2528
  for (const expectation of [...current, ...target]) {
@@ -2228,7 +2554,7 @@ function deriveFinalWorkspaceMembership(current, target, files) {
2228
2554
  async function snapshotWorkspaceBase(root, base) {
2229
2555
  assertSafeWorkspaceBase(base);
2230
2556
  await inspectSafePath(root, base);
2231
- const entries = await readdir2(join3(root, base), {
2557
+ const entries = await readdir2(join4(root, base), {
2232
2558
  withFileTypes: true
2233
2559
  }).catch((error) => {
2234
2560
  if (isMissing2(error))
@@ -2270,8 +2596,8 @@ function isDirectWorkspaceManifest(base, path) {
2270
2596
  const prefix = `${base}/`;
2271
2597
  if (!path.startsWith(prefix))
2272
2598
  return false;
2273
- const relative3 = path.slice(prefix.length);
2274
- const segments = relative3.split("/");
2599
+ const relative4 = path.slice(prefix.length);
2600
+ const segments = relative4.split("/");
2275
2601
  return segments.length === 2 && segments[0]?.length > 0 && segments[1] === "package.json";
2276
2602
  }
2277
2603
  function isMissing2(error) {
@@ -2478,7 +2804,7 @@ var supplierWorkspaceCopies = [
2478
2804
  var supplierWorkspacePaths = ["packages/license-sdk"];
2479
2805
  async function prepareCustomerDockerfiles(root) {
2480
2806
  await Promise.all(["apps/server/Dockerfile", webDockerfilePath].map(async (path) => {
2481
- const absolutePath = join4(root, path);
2807
+ const absolutePath = join5(root, path);
2482
2808
  const source = await readFile3(absolutePath, "utf8");
2483
2809
  await writeFile2(absolutePath, rewriteCustomerDockerfile(source));
2484
2810
  }));
@@ -2487,7 +2813,7 @@ async function prepareCustomerDockerfiles(root) {
2487
2813
  requireAnchors: true
2488
2814
  });
2489
2815
  if (plan.changed && plan.content !== undefined) {
2490
- await writeFile2(join4(root, target.dockerfilePath), plan.content);
2816
+ await writeFile2(join5(root, target.dockerfilePath), plan.content);
2491
2817
  }
2492
2818
  }
2493
2819
  }
@@ -2502,7 +2828,7 @@ function rewriteCustomerDockerfile(source) {
2502
2828
 
2503
2829
  // src/code-quality.ts
2504
2830
  import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
2505
- import { join as join5 } from "path";
2831
+ import { join as join6 } from "path";
2506
2832
  var oxcStarterPolicy = [
2507
2833
  "- \u751F\u6210\u65F6\u9ED8\u8BA4\u9884\u88C5 Oxlint\u3001Oxfmt\u3001lint-staged \u4E0E Husky\u3002",
2508
2834
  "- \u63D0\u4EA4\u524D\u81EA\u52A8\u683C\u5F0F\u5316\u6682\u5B58\u6587\u4EF6\uFF1Blint\u3001typecheck \u548C test \u4FDD\u7559\u4E3A\u663E\u5F0F\u547D\u4EE4\u3002",
@@ -2511,7 +2837,7 @@ var oxcStarterPolicy = [
2511
2837
  `);
2512
2838
  var noCodeQualityPolicy = "- \u672C\u9879\u76EE\u751F\u6210\u65F6\u672A\u5F15\u5165 lint \u6216 format \u5DE5\u5177\uFF1B\u9879\u76EE\u6240\u6709\u8005\u53EF\u6309\u56E2\u961F\u9700\u8981\u81EA\u884C\u9009\u62E9\u3002";
2513
2839
  async function reflectCodeQualityChoice(targetDirectory, includeOxc) {
2514
- const path = join5(targetDirectory, "AGENTS.md");
2840
+ const path = join6(targetDirectory, "AGENTS.md");
2515
2841
  const source = await readFile4(path, "utf8");
2516
2842
  if (includeOxc)
2517
2843
  return;
@@ -2523,18 +2849,18 @@ async function reflectCodeQualityChoice(targetDirectory, includeOxc) {
2523
2849
 
2524
2850
  // src/license-files.ts
2525
2851
  import { mkdir, readFile as readFile5, rm as rm2, writeFile as writeFile4 } from "fs/promises";
2526
- import { dirname as dirname3, join as join6, resolve as resolve4 } from "path";
2852
+ import { dirname as dirname4, join as join7, resolve as resolve4 } from "path";
2527
2853
  import { fileURLToPath } from "url";
2528
- var packageRoot = resolve4(dirname3(fileURLToPath(import.meta.url)), "..");
2854
+ var packageRoot = resolve4(dirname4(fileURLToPath(import.meta.url)), "..");
2529
2855
  var apacheLicensePath = resolve4(packageRoot, "LICENSE");
2530
2856
  var windyLicensePath = ".windy/licenses/WINDY-APACHE-2.0.txt";
2531
2857
  async function applyWindyBaseLicense(targetDirectory) {
2532
- const target = join6(targetDirectory, windyLicensePath);
2533
- await mkdir(dirname3(target), { recursive: true });
2858
+ const target = join7(targetDirectory, windyLicensePath);
2859
+ await mkdir(dirname4(target), { recursive: true });
2534
2860
  await writeFile4(target, await readFile5(apacheLicensePath));
2535
2861
  }
2536
2862
  async function applyProjectLicense(targetDirectory, license, holder, year = new Date().getFullYear()) {
2537
- const target = join6(targetDirectory, "LICENSE");
2863
+ const target = join7(targetDirectory, "LICENSE");
2538
2864
  if (license === "UNLICENSED") {
2539
2865
  await rm2(target, { force: true });
2540
2866
  return;
@@ -2577,7 +2903,7 @@ SOFTWARE.
2577
2903
 
2578
2904
  // src/module-materializer.ts
2579
2905
  import { lstat as lstat3, readFile as readFile6, readdir as readdir3, rm as rm3, writeFile as writeFile5 } from "fs/promises";
2580
- import { basename as basename3, extname, join as join7, relative as relative3, sep as sep3 } from "path";
2906
+ import { basename as basename4, extname, join as join8, relative as relative4, sep as sep3 } from "path";
2581
2907
  var textExtensions = new Set([
2582
2908
  ".css",
2583
2909
  ".html",
@@ -2613,7 +2939,7 @@ async function materializeSelectedModules(targetDirectory, selectedNames) {
2613
2939
  ...manifest.documentation,
2614
2940
  ...manifest.schemaFiles
2615
2941
  ]));
2616
- await Promise.all([...new Set(removedRoots)].map((path) => rm3(join7(targetDirectory, path), { recursive: true, force: true })));
2942
+ await Promise.all([...new Set(removedRoots)].map((path) => rm3(join8(targetDirectory, path), { recursive: true, force: true })));
2617
2943
  await pruneWorkspaceReferences(targetDirectory, removedPackageNames, removedRoots);
2618
2944
  }
2619
2945
  function collapseRemovalRoots(paths) {
@@ -2628,7 +2954,7 @@ function collapseRemovalRoots(paths) {
2628
2954
  }
2629
2955
  async function stripModuleBlocks(root, selected) {
2630
2956
  for (const path of await collectFiles2(root)) {
2631
- if (basename3(path) !== "Dockerfile" && !textExtensions.has(extname(path))) {
2957
+ if (basename4(path) !== "Dockerfile" && !textExtensions.has(extname(path))) {
2632
2958
  continue;
2633
2959
  }
2634
2960
  const source = await readFile6(path, "utf8");
@@ -2668,7 +2994,7 @@ async function readRemovedPackageNames(root, roots) {
2668
2994
  const names = new Set;
2669
2995
  for (const packageRoot2 of roots) {
2670
2996
  try {
2671
- const value = JSON.parse(await readFile6(join7(root, packageRoot2, "package.json"), "utf8"));
2997
+ const value = JSON.parse(await readFile6(join8(root, packageRoot2, "package.json"), "utf8"));
2672
2998
  if (value.name)
2673
2999
  names.add(value.name);
2674
3000
  } catch (error) {
@@ -2680,7 +3006,7 @@ async function readRemovedPackageNames(root, roots) {
2680
3006
  }
2681
3007
  async function pruneWorkspaceReferences(root, removedPackages, removedRoots) {
2682
3008
  for (const path of await collectFiles2(root)) {
2683
- if (basename3(path) === "package.json") {
3009
+ if (basename4(path) === "package.json") {
2684
3010
  const value = JSON.parse(await readFile6(path, "utf8"));
2685
3011
  let changed = false;
2686
3012
  for (const section of ["dependencies", "devDependencies"]) {
@@ -2697,7 +3023,7 @@ async function pruneWorkspaceReferences(root, removedPackages, removedRoots) {
2697
3023
  `);
2698
3024
  continue;
2699
3025
  }
2700
- if (basename3(path) !== "Dockerfile")
3026
+ if (basename4(path) !== "Dockerfile")
2701
3027
  continue;
2702
3028
  const source = await readFile6(path, "utf8");
2703
3029
  const output = source.split(`
@@ -2711,7 +3037,7 @@ async function pruneDatabaseArtifacts(root, tableNames, statementTokens) {
2711
3037
  if (!tableNames.length && !statementTokens.length)
2712
3038
  return;
2713
3039
  const tablePatterns = tableNames.map((name) => new RegExp(`(?:"${escapeRegExp(name)}"|\\b${escapeRegExp(name)}\\b)`));
2714
- const drizzleRoot = join7(root, "packages/database/drizzle");
3040
+ const drizzleRoot = join8(root, "packages/database/drizzle");
2715
3041
  try {
2716
3042
  for (const path of await collectFiles2(drizzleRoot)) {
2717
3043
  if (path.endsWith(".sql")) {
@@ -2754,7 +3080,7 @@ async function collectFiles2(root) {
2754
3080
  for (const name of (await readdir3(directory)).sort()) {
2755
3081
  if ([".git", "node_modules", "dist"].includes(name))
2756
3082
  continue;
2757
- const path = join7(directory, name);
3083
+ const path = join8(directory, name);
2758
3084
  const metadata = await lstat3(path);
2759
3085
  if (metadata.isSymbolicLink())
2760
3086
  continue;
@@ -2766,7 +3092,7 @@ async function collectFiles2(root) {
2766
3092
  }
2767
3093
  }
2768
3094
  function relativePath(root, path) {
2769
- return relative3(root, path).split(sep3).join("/");
3095
+ return relative4(root, path).split(sep3).join("/");
2770
3096
  }
2771
3097
  function escapeRegExp(value) {
2772
3098
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -3280,7 +3606,7 @@ License \u7B7E\u53D1\u4E2D\u5FC3\u3001\u72EC\u7ACB\u7B7E\u540D\u670D\u52A1\u3001
3280
3606
  - \u90E8\u7F72\u671F\u6A21\u5757\u7BA1\u7406\uFF1A[\u6A21\u5757\u751F\u547D\u5468\u671F](./development/module-lifecycle.md)\u3002
3281
3607
  - \u4E1A\u52A1\u6A21\u5757\u5F00\u53D1\uFF1A[windy-business-module Skill](../.agents/skills/windy-business-module/SKILL.md)\u3002
3282
3608
  ${includeStorage ? "- \u5927\u62A5\u544A\u5BFC\u5165\uFF1A[\u53D7\u6CBB\u7406\u7684\u5927\u62A5\u544A\u6682\u5B58](./architecture/report-staging.md)\u3002" : ""}
3283
- ${includeOfflineLicense ? "- License \u6D88\u8D39\u7AEF\uFF1A[\u79BB\u7EBF\u6FC0\u6D3B\u4E0E\u5B89\u88C5\u534F\u8BAE](./license/license-offline-activation-code.md)\uFF1B\u8FD0\u884C\u65F6\u80FD\u529B\u7531 npm \u4F9D\u8D56 `@southwind-ai/license` \u63D0\u4F9B\u3002" : ""}
3609
+ ${includeOfflineLicense ? "- License \u6D88\u8D39\u7AEF\uFF1A[\u79BB\u7EBF\u6FC0\u6D3B\u4E0E\u5B89\u88C5\u534F\u8BAE](./license/license-offline-activation-code.md)\u4E0E[\u624B\u673A\u626B\u7801\u914D\u5BF9\u6FC0\u6D3B](./license/license-pairing-activation.md)\uFF1B\u8FD0\u884C\u65F6\u80FD\u529B\u7531 npm \u4F9D\u8D56 `@southwind-ai/license` \u63D0\u4F9B\u3002" : ""}
3284
3610
  - \u8FD0\u7EF4\uFF1A[\u53EF\u89C2\u6D4B\u6027](./operations/observability.md)${includeOperations ? " \u4E0E [\u8FD0\u7EF4\u603B\u89C8](./platform/operations-overview.md)" : ""}\u3002
3285
3611
  - \u4EA4\u4ED8\uFF1A[\u6309 registry digest \u4E0E OCI blob \u5DEE\u91CF\u53D1\u5E03](./operations/incremental-delivery.md)\u3002
3286
3612
  ${includeAgent ? "- Agent\u3001\u591A\u6A21\u6001 Runtime \u4E0E MCP\uFF1A[Agent Runtime \u63A5\u5165](./platform/agent-runtime.md)\u3001[Document AI Runtime](./platform/document-ai-runtime.md)\u3001[Speech AI Runtime](./platform/speech-ai-runtime.md)\u3001[\u53D7\u63A7\u5DE5\u5177](./platform/agent-tools.md)\u4E0E[MCP \u4E1A\u52A1\u80FD\u529B](./architecture/mcp-business-capabilities.md)\u3002" : ""}
@@ -3338,6 +3664,10 @@ Drizzle migration\uFF0C\u518D\u542F\u52A8 Server \u4E0E Web\uFF1B\u4E0D\u8981\u8
3338
3664
  BuildKit \u4E2D\u7684 Bun \u5305\u4E0B\u8F7D\u7F13\u5B58\uFF0C\u53EA\u4E0B\u8F7D\u65B0\u589E\u6216\u53D1\u751F\u53D8\u5316\u7684\u4F9D\u8D56\uFF1B\u51B7\u5B89\u88C5\u6BCF 15 \u79D2\u8F93\u51FA\u4E00\u6B21
3339
3665
  \u4E0D\u542B registry \u5730\u5740\u6216\u51ED\u636E\u7684\u8FDB\u5EA6\u5FC3\u8DF3\u3002
3340
3666
 
3667
+ Windows 10/11 \u53EF\u5728\u539F\u751F PowerShell \u4E2D\u914D\u5408 Docker Desktop \u76F4\u63A5\u8FD0\u884C \`bun run dev\` \u4E0E
3668
+ \`bun run dev:build\`\uFF0C\u4E0D\u9700\u8981 WSL\u3002Windows \u662F\u672C\u5730\u5F00\u53D1\u5BBF\u4E3B\uFF1B\u751F\u4EA7\u4EA4\u4ED8\u4ECD\u4F7F\u7528 Linux
3669
+ amd64 \u5BB9\u5668\u3002
3670
+
3341
3671
  | \u670D\u52A1 | \u5730\u5740 |
3342
3672
  | ---- | ---- |
3343
3673
  | Web | http://localhost:18746 |
@@ -3480,7 +3810,8 @@ browser-safe \`./admin\` \u4E0E project-owned \u7684
3480
3810
  \`apps/web/src/app/web-composition.ts\` \u88C5\u914D\u9875\u9762\uFF0C\u4E0D\u590D\u5236\u7B2C\u4E8C\u4EFD Feature\u3001Permission
3481
3811
  \u6216\u8DEF\u7531\u6E05\u5355\u3002\u6574\u4E2A \`apps/web/src\` \u4E0E\u6574\u4E2A \`apps/server/src/app\` \u90FD\u662F
3482
3812
  project-owned\uFF0C\u5BA2\u6237\u53EF\u4EE5\u4FEE\u6539 Router\u3001layout\u3001\u9875\u9762\u3001Host \u548C Server \u7EC4\u5408\uFF1B\u666E\u901A
3483
- \`windy update\` \u4E0D\u4F1A\u8986\u76D6\u6216\u4E09\u65B9\u5408\u5E76\u8FD9\u4E9B\u6587\u4EF6\u3002
3813
+ \`windy update\` \u4E0D\u4F1A\u6574\u6587\u4EF6\u8986\u76D6\u6216\u4E09\u65B9\u5408\u5E76\u8FD9\u4E9B\u6587\u4EF6\u3002\u7248\u672C recipe \u53EA\u6709\u5728\u663E\u5F0F\u767B\u8BB0
3814
+ path \u4E0E\u786E\u5B9A\u6027\u8BED\u4E49\u951A\u70B9\u540E\u624D\u80FD\u505A\u5E42\u7B49\u8FFD\u52A0\uFF1B\u951A\u70B9\u7F3A\u5931\u6216\u4E0D\u552F\u4E00\u65F6\u5FC5\u987B\u5728\u5199\u5165\u524D\u505C\u6B62\u3002
3484
3815
 
3485
3816
  \u7CBE\u786E\u751F\u6210\u6765\u6E90\u4FDD\u7559\u5728 \`.windy/generation.json\`\u3002\u5F53\u524D\u7248\u672C\u5DF2\u63D0\u4F9B\u53EF\u56DE\u6EDA\u7684
3486
3817
  \`windy update\` \u4E0E \`windy module list/enable/disable\`\u3002\u5F53\u524D\u5185\u7F6E\u6A21\u5757\u4ECD\u4F9D\u8D56
@@ -3514,7 +3845,8 @@ ${includeOxc ? "\u63D0\u4EA4\u65F6 Husky \u4F1A\u901A\u8FC7 lint-staged \u4E0E O
3514
3845
  \u66F4\u65B0\u524D\u65E0\u9700\u63D0\u4EA4\u3001\u6682\u5B58\u6216\u6E05\u7406\u4E1A\u52A1\u6539\u52A8\u3002\`--dry-run\` \u53EA\u751F\u6210\u8BA1\u5212\uFF0C\u4E0D\u5199\u9879\u76EE\uFF1B\u65E0\u5173 WIP
3515
3846
  \u4FDD\u6301\u539F\u6837\uFF0C\u547D\u4E2D\u540C\u4E00\u8DEF\u5F84\u65F6\u6309\u51BB\u7ED3\u5FEB\u7167\u4E0E\u4E09\u65B9\u5408\u5E76 fail closed\u3002\u6B63\u5F0F\u66F4\u65B0\u5148\u5907\u4EFD\uFF0C\u518D\u505A
3516
3847
  package \u5B57\u6BB5\u7EA7\u5408\u5E76\u3001\u5171\u4EAB\u811A\u624B\u67B6\u4E09\u65B9\u5408\u5E76\u4E0E\u5B8C\u6574\u9A8C\u8BC1\u3002\u6574\u4E2A \`apps/web/src\` \u548C
3517
- \`apps/server/src/app\` \u4FDD\u6301\u9879\u76EE\u7248\u672C\u3002\u4EFB\u4F55\u51B2\u7A81\u90FD\u4F1A\u5728\u5199\u5165\u524D\u4E2D\u6B62\uFF0C\u6A21\u5757\u542F\u505C\u5728\u4EA4\u4E92
3848
+ \`apps/server/src/app\` \u9ED8\u8BA4\u4FDD\u6301\u9879\u76EE\u7248\u672C\uFF1B\u5DF2\u767B\u8BB0\u7248\u672C recipe \u53EA\u4FEE\u6539\u5176\u58F0\u660E\u7684\u7A84\u951A\u70B9\u3002
3849
+ \u4EFB\u4F55\u51B2\u7A81\u90FD\u4F1A\u5728\u5199\u5165\u524D\u4E2D\u6B62\uFF0C\u6A21\u5757\u542F\u505C\u5728\u4EA4\u4E92
3518
3850
  \u7EC8\u7AEF\u786E\u8BA4\uFF1BCI\u3001Agent \u6216\u5176\u5B83\u975E TTY \u73AF\u5883\u5FC5\u987B\u663E\u5F0F\u4F20\u5165 \`--yes\`\u3002
3519
3851
  \u65E0\u5E76\u53D1\u53D8\u5316\u7684\u9A8C\u8BC1\u5931\u8D25\u4F1A\u81EA\u52A8\u56DE\u6EDA\uFF1B\u4E2D\u65AD\u6062\u590D\u4F7F\u7528
3520
3852
  \`bun run windy doctor --repair\`\u3002\u8BE5\u547D\u4EE4\u5728\u63D0\u4EA4\u70B9\u524D\u4FDD\u7559\u5E76\u53D1\u7F16\u8F91\u5E76\u56DE\u6EDA\u5176\u4F59\u8DEF\u5F84\uFF0C
@@ -3694,10 +4026,13 @@ var templateDocumentationFiles = [
3694
4026
  "docs/development/custom-error-pages.md",
3695
4027
  "docs/development/custom-login-page.md",
3696
4028
  "docs/development/module-lifecycle.md",
4029
+ "docs/development/ui-component-gallery.md",
3697
4030
  "docs/license/license-offline-activation-code.md",
4031
+ "docs/license/license-pairing-activation.md",
3698
4032
  "docs/operations/observability.md",
3699
4033
  "docs/operations/incremental-delivery.md",
3700
4034
  "docs/platform/agent-run-attestation.md",
4035
+ "docs/platform/agent-supervisor-output-contract.md",
3701
4036
  "docs/platform/agent-tools.md",
3702
4037
  "docs/platform/agent-runtime.md",
3703
4038
  "docs/platform/agent-runtime-observability.md",
@@ -3759,11 +4094,11 @@ function isExcludedTemplateName(name) {
3759
4094
  // src/provenance.ts
3760
4095
  import { createHash as createHash2 } from "crypto";
3761
4096
  import { mkdir as mkdir2, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
3762
- import { join as join8 } from "path";
4097
+ import { join as join9 } from "path";
3763
4098
  var templateMetadataFile = ".windy-template.json";
3764
4099
  var generationMetadataFile = ".windy/generation.json";
3765
4100
  async function readTemplateMetadata(sourceRoot) {
3766
- const path = join8(sourceRoot, templateMetadataFile);
4101
+ const path = join9(sourceRoot, templateMetadataFile);
3767
4102
  const parsed = JSON.parse(await readFile7(path, "utf8"));
3768
4103
  if (!isTemplateMetadata(parsed)) {
3769
4104
  throw new Error("create-windy \u6A21\u677F\u6765\u6E90\u5143\u6570\u636E\u65E0\u6548");
@@ -3774,7 +4109,7 @@ async function readGenerationProvenance(targetDirectory) {
3774
4109
  return (await readGenerationProvenanceSnapshot(targetDirectory)).provenance;
3775
4110
  }
3776
4111
  async function readGenerationProvenanceSnapshot(targetDirectory) {
3777
- const path = join8(targetDirectory, generationMetadataFile);
4112
+ const path = join9(targetDirectory, generationMetadataFile);
3778
4113
  const content = await readFile7(path);
3779
4114
  return {
3780
4115
  content,
@@ -3815,8 +4150,8 @@ async function writeGenerationProvenance(targetDirectory, metadata, profile, sel
3815
4150
  includeOxc
3816
4151
  }
3817
4152
  };
3818
- const path = join8(targetDirectory, generationMetadataFile);
3819
- await mkdir2(join8(path, ".."), { recursive: true });
4153
+ const path = join9(targetDirectory, generationMetadataFile);
4154
+ await mkdir2(join9(path, ".."), { recursive: true });
3820
4155
  await writeFile6(path, `${JSON.stringify(provenance, null, 2)}
3821
4156
  `);
3822
4157
  }
@@ -3843,7 +4178,7 @@ function isModuleVersion(value) {
3843
4178
 
3844
4179
  // src/registry-dependencies.ts
3845
4180
  import { lstat as lstat4, readFile as readFile8, readdir as readdir4, writeFile as writeFile7 } from "fs/promises";
3846
- import { basename as basename4, extname as extname2, join as join9 } from "path";
4181
+ import { basename as basename5, extname as extname2, join as join10 } from "path";
3847
4182
  var dependencySections = [
3848
4183
  "dependencies",
3849
4184
  "devDependencies",
@@ -3867,7 +4202,7 @@ async function materializeRegistryDependencies(root, dependencies) {
3867
4202
  for (const path of await collectFiles3(root)) {
3868
4203
  if (!replaceableExtensions.has(extname2(path)))
3869
4204
  continue;
3870
- if (basename4(path) === "package.json") {
4205
+ if (basename5(path) === "package.json") {
3871
4206
  await rewritePackageJson(path, dependencies);
3872
4207
  continue;
3873
4208
  }
@@ -3904,7 +4239,7 @@ async function collectFiles3(root) {
3904
4239
  for (const name of (await readdir4(directory)).sort()) {
3905
4240
  if ([".git", "node_modules", "dist"].includes(name))
3906
4241
  continue;
3907
- const path = join9(directory, name);
4242
+ const path = join10(directory, name);
3908
4243
  const metadata = await lstat4(path);
3909
4244
  if (metadata.isSymbolicLink())
3910
4245
  continue;
@@ -3919,10 +4254,10 @@ async function collectFiles3(root) {
3919
4254
  // src/project-module-registry.ts
3920
4255
  import { createHash as createHash3 } from "crypto";
3921
4256
  import { readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
3922
- import { join as join10 } from "path";
4257
+ import { join as join11 } from "path";
3923
4258
  var projectModuleRegistryPath = "windy.modules.json";
3924
4259
  async function readProjectModuleRegistrySnapshot(projectDirectory, installedNames) {
3925
- const path = join10(projectDirectory, projectModuleRegistryPath);
4260
+ const path = join11(projectDirectory, projectModuleRegistryPath);
3926
4261
  let content;
3927
4262
  try {
3928
4263
  content = await readFile9(path);
@@ -3975,7 +4310,7 @@ async function writeInitialProjectModuleRegistry(targetDirectory, selectedNames)
3975
4310
  config: {}
3976
4311
  })));
3977
4312
  const registry = { schemaVersion: 1, modules };
3978
- await writeFile8(join10(targetDirectory, projectModuleRegistryPath), `${JSON.stringify(registry, null, 2)}
4313
+ await writeFile8(join11(targetDirectory, projectModuleRegistryPath), `${JSON.stringify(registry, null, 2)}
3979
4314
  `);
3980
4315
  }
3981
4316
  function assertRegistryMatchesInstalled(registry, installedNames) {
@@ -4031,29 +4366,29 @@ async function generateProject(input) {
4031
4366
  const selectedModules = input.selectedModules ?? templateMetadata.modules.filter(({ name }) => requestedIncludeExample || name !== "work-order").map(({ name }) => name);
4032
4367
  const includeExample = selectedModules.includes("work-order");
4033
4368
  for (const relativePath2 of generationTemplatePaths(true, includeOxc)) {
4034
- await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join11(input.targetDirectory, relativePath2));
4369
+ await copyTree(await resolveTemplateSource(input.sourceRoot, relativePath2), join12(input.targetDirectory, relativePath2));
4035
4370
  }
4036
4371
  await materializeSelectedModules(input.targetDirectory, selectedModules);
4037
4372
  await materializeRegistryDependencies(input.targetDirectory, selectedModuleManifests(selectedModules).flatMap(({ registryDependencies }) => registryDependencies));
4038
- const packagePath = join11(input.targetDirectory, "package.json");
4373
+ const packagePath = join12(input.targetDirectory, "package.json");
4039
4374
  const packageJson = JSON.parse(await readFile10(packagePath, "utf8"));
4040
4375
  await writeFile9(packagePath, `${JSON.stringify(createStarterPackage(packageJson, input.projectName, includeOxc, projectLicense, selectedModules, templateMetadata.generatorVersion), null, 2)}
4041
4376
  `);
4042
- await writeFile9(join11(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage")));
4043
- await writeFile9(join11(input.targetDirectory, ".env.example"), environmentExample(includeExample, selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage")));
4044
- await writeFile9(join11(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
4045
- await writeFile9(join11(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), selectedModules.includes("system.agent"), selectedModules.includes("system.operations"), selectedModules.includes("system.storage")));
4377
+ await writeFile9(join12(input.targetDirectory, "docker-compose.yml"), starterComposeFor(selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage")));
4378
+ await writeFile9(join12(input.targetDirectory, ".env.example"), environmentExample(includeExample, selectedModules.includes("system.agent"), selectedModules.includes("system.search"), selectedModules.includes("system.storage")));
4379
+ await writeFile9(join12(input.targetDirectory, "README.md"), starterReadme(input.projectName, includeExample, includeOxc, projectLicense, selectedModules));
4380
+ await writeFile9(join12(input.targetDirectory, "docs/README.md"), starterDocsReadme(selectedModules.includes("system.license"), selectedModules.includes("system.agent"), selectedModules.includes("system.operations"), selectedModules.includes("system.storage")));
4046
4381
  await reflectCodeQualityChoice(input.targetDirectory, includeOxc);
4047
4382
  await applyWindyBaseLicense(input.targetDirectory);
4048
4383
  await applyProjectLicense(input.targetDirectory, projectLicense, input.licenseHolder);
4049
4384
  await prepareCustomerDockerfiles(input.targetDirectory);
4050
4385
  await writeGenerationProvenance(input.targetDirectory, templateMetadata, input.profile ?? starterProfile.key, selectedModules, includeOxc, projectLicense);
4051
4386
  await writeInitialProjectModuleRegistry(input.targetDirectory, selectedModules);
4052
- await rm4(join11(input.targetDirectory, "bun.lock"), { force: true });
4387
+ await rm4(join12(input.targetDirectory, "bun.lock"), { force: true });
4053
4388
  await writeManagedFilesManifest(input.targetDirectory, templateMetadata.generatorVersion);
4054
4389
  }
4055
4390
  async function resolveTemplateSource(sourceRoot, relativePath2) {
4056
- const source = join11(sourceRoot, relativePath2);
4391
+ const source = join12(sourceRoot, relativePath2);
4057
4392
  try {
4058
4393
  await lstat5(source);
4059
4394
  return source;
@@ -4064,12 +4399,12 @@ async function resolveTemplateSource(sourceRoot, relativePath2) {
4064
4399
  const alias = npmTemplateAliases[relativePath2];
4065
4400
  if (!alias)
4066
4401
  return source;
4067
- return join11(sourceRoot, alias);
4402
+ return join12(sourceRoot, alias);
4068
4403
  }
4069
4404
  async function assertGeneratedProjectIsClean(targetDirectory) {
4070
4405
  const violations = [];
4071
4406
  await walk(targetDirectory, async (path) => {
4072
- const name = basename5(path);
4407
+ const name = basename6(path);
4073
4408
  const extension = extname3(name).toLowerCase();
4074
4409
  if (isExcludedTemplateName(name) || excludedRuntimeFiles.has(name) || [".key", ".pem", ".p12", ".pfx"].includes(extension)) {
4075
4410
  violations.push(path.slice(targetDirectory.length + 1));
@@ -4100,17 +4435,17 @@ async function assertTargetAvailable(targetDirectory) {
4100
4435
  }
4101
4436
  async function copyTree(source, target) {
4102
4437
  const metadata = await lstat5(source);
4103
- const name = basename5(source);
4438
+ const name = basename6(source);
4104
4439
  if (shouldExclude(name) || metadata.isSymbolicLink())
4105
4440
  return;
4106
4441
  if (metadata.isDirectory()) {
4107
4442
  await mkdir3(target, { recursive: true });
4108
4443
  for (const child of await readdir5(source)) {
4109
- await copyTree(join11(source, child), join11(target, child));
4444
+ await copyTree(join12(source, child), join12(target, child));
4110
4445
  }
4111
4446
  return;
4112
4447
  }
4113
- await mkdir3(join11(target, ".."), { recursive: true });
4448
+ await mkdir3(join12(target, ".."), { recursive: true });
4114
4449
  await copyFile(source, target);
4115
4450
  }
4116
4451
  function shouldExclude(name) {
@@ -4118,7 +4453,7 @@ function shouldExclude(name) {
4118
4453
  }
4119
4454
  async function walk(directory, visit) {
4120
4455
  for (const name of await readdir5(directory)) {
4121
- const path = join11(directory, name);
4456
+ const path = join12(directory, name);
4122
4457
  await visit(path);
4123
4458
  if ((await lstat5(path)).isDirectory())
4124
4459
  await walk(path, visit);
@@ -4130,10 +4465,10 @@ function isMissing5(error) {
4130
4465
 
4131
4466
  // src/template-root.ts
4132
4467
  import { access } from "fs/promises";
4133
- import { dirname as dirname4, resolve as resolve5 } from "path";
4468
+ import { dirname as dirname5, resolve as resolve5 } from "path";
4134
4469
  import { fileURLToPath as fileURLToPath2 } from "url";
4135
4470
  async function resolveTemplateRoot() {
4136
- const currentDirectory = dirname4(fileURLToPath2(import.meta.url));
4471
+ const currentDirectory = dirname5(fileURLToPath2(import.meta.url));
4137
4472
  const templateRoot = resolve5(currentDirectory, "../template");
4138
4473
  try {
4139
4474
  await access(resolve5(templateRoot, "package.json"));
@@ -5975,7 +6310,7 @@ import { resolve as resolve8 } from "path";
5975
6310
 
5976
6311
  // src/update/doctor.ts
5977
6312
  import { readFile as readFile11 } from "fs/promises";
5978
- import { join as join15 } from "path";
6313
+ import { join as join16 } from "path";
5979
6314
 
5980
6315
  // src/update/process.ts
5981
6316
  import { spawn as spawn2 } from "child_process";
@@ -6028,10 +6363,10 @@ function withoutParentGitRepository(source) {
6028
6363
  }
6029
6364
 
6030
6365
  // src/update/transaction-cas.ts
6031
- import { basename as basename6, dirname as dirname5 } from "path";
6366
+ import { basename as basename8, dirname as dirname7 } from "path";
6032
6367
 
6033
6368
  // src/update/transaction-native-cas.ts
6034
- import { ptr as ptr2, read as read3, dlopen as dlopen3, FFIType as FFIType3 } from "bun:ffi";
6369
+ import { ptr as ptr3, read as read3, dlopen as dlopen4, FFIType as FFIType4 } from "bun:ffi";
6035
6370
 
6036
6371
  // src/update/transaction-native-cas-config.ts
6037
6372
  function nativeRenameConfiguration(platform) {
@@ -6056,19 +6391,19 @@ function nativeRenameConfiguration(platform) {
6056
6391
 
6057
6392
  // src/update/transaction-native-cas.ts
6058
6393
  var renameSignature = {
6059
- args: [FFIType3.i32, FFIType3.ptr, FFIType3.i32, FFIType3.ptr, FFIType3.i32],
6060
- returns: FFIType3.i32
6394
+ args: [FFIType4.i32, FFIType4.ptr, FFIType4.i32, FFIType4.ptr, FFIType4.i32],
6395
+ returns: FFIType4.i32
6061
6396
  };
6062
6397
  var linuxSymbols = {
6063
6398
  renameat2: renameSignature,
6064
- __errno_location: { args: [], returns: FFIType3.ptr }
6399
+ __errno_location: { args: [], returns: FFIType4.ptr }
6065
6400
  };
6066
6401
  var darwinSymbols = {
6067
6402
  renameatx_np: renameSignature,
6068
- __error: { args: [], returns: FFIType3.ptr }
6403
+ __error: { args: [], returns: FFIType4.ptr }
6069
6404
  };
6070
- var getLinuxLibc = createLazyLibcLoader((candidate) => dlopen3(candidate, linuxSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D renameat2\uFF0C\u4E8B\u52A1 CAS \u5B89\u5168\u5173\u95ED");
6071
- var getDarwinLibc = createLazyLibcLoader((candidate) => dlopen3(candidate, darwinSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D renameatx_np\uFF0C\u4E8B\u52A1 CAS \u5B89\u5168\u5173\u95ED");
6405
+ var getLinuxLibc = createLazyLibcLoader((candidate) => dlopen4(candidate, linuxSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D renameat2\uFF0C\u4E8B\u52A1 CAS \u5B89\u5168\u5173\u95ED");
6406
+ var getDarwinLibc = createLazyLibcLoader((candidate) => dlopen4(candidate, darwinSymbols), "\u5F53\u524D\u5E73\u53F0\u65E0\u6CD5\u52A0\u8F7D renameatx_np\uFF0C\u4E8B\u52A1 CAS \u5B89\u5168\u5173\u95ED");
6072
6407
  function exchangeAt(parent, left, right, rollback = false) {
6073
6408
  atomicRename(parent, left, right, "exchange");
6074
6409
  syncMutatedDirectory(rollback ? "rename-exchange-back" : "rename-exchange", parent.fd);
@@ -6078,10 +6413,18 @@ function moveNoReplaceAt(parent, source, target) {
6078
6413
  syncMutatedDirectory("rename-noreplace", parent.fd);
6079
6414
  }
6080
6415
  function atomicRename(parent, source, target, operation) {
6416
+ if (process.platform === "win32") {
6417
+ if (operation === "exchange") {
6418
+ windowsExchangeAt(parent, source, target);
6419
+ } else {
6420
+ windowsMoveNoReplaceAt(parent, source, target);
6421
+ }
6422
+ return;
6423
+ }
6081
6424
  const configuration = nativeRenameConfiguration(process.platform);
6082
6425
  if (process.platform === "linux") {
6083
6426
  const libc = getLinuxLibc();
6084
- const result = libc.symbols.renameat2(parent.fd, ptr2(cString2(source)), parent.fd, ptr2(cString2(target)), operation === "exchange" ? configuration.exchangeFlag : configuration.noReplaceFlag);
6427
+ const result = libc.symbols.renameat2(parent.fd, ptr3(cString2(source)), parent.fd, ptr3(cString2(target)), operation === "exchange" ? configuration.exchangeFlag : configuration.noReplaceFlag);
6085
6428
  if (result < 0) {
6086
6429
  throw linuxError(`renameat2 ${source} -> ${target}`);
6087
6430
  }
@@ -6089,7 +6432,7 @@ function atomicRename(parent, source, target, operation) {
6089
6432
  }
6090
6433
  if (process.platform === "darwin") {
6091
6434
  const libc = getDarwinLibc();
6092
- const result = libc.symbols.renameatx_np(parent.fd, ptr2(cString2(source)), parent.fd, ptr2(cString2(target)), operation === "exchange" ? configuration.exchangeFlag : configuration.noReplaceFlag);
6435
+ const result = libc.symbols.renameatx_np(parent.fd, ptr3(cString2(source)), parent.fd, ptr3(cString2(target)), operation === "exchange" ? configuration.exchangeFlag : configuration.noReplaceFlag);
6093
6436
  if (result < 0) {
6094
6437
  throw darwinError(`renameatx_np ${source} -> ${target}`);
6095
6438
  }
@@ -6122,18 +6465,18 @@ function cString2(value) {
6122
6465
  }
6123
6466
 
6124
6467
  // src/update/transaction-cas-proof.ts
6125
- import { closeSync as closeSync5, constants as constants4, fstatSync as fstatSync3, readSync } from "fs";
6468
+ import { closeSync as closeSync6, constants as constants5, fstatSync as fstatSync4, readSync } from "fs";
6126
6469
  function openFileProof(parent) {
6127
- const fd = openFileAt(parent, constants4.O_RDONLY | constants4.O_NOFOLLOW);
6470
+ const fd = openFileAt(parent, constants5.O_RDONLY | constants5.O_NOFOLLOW);
6128
6471
  try {
6129
6472
  const identity = identityOf(fd);
6130
6473
  return {
6131
6474
  fd,
6132
6475
  ...identity,
6133
- close: () => closeSync5(fd)
6476
+ close: () => closeSync6(fd)
6134
6477
  };
6135
6478
  } catch (error) {
6136
- closeSync5(fd);
6479
+ closeSync6(fd);
6137
6480
  throw error;
6138
6481
  }
6139
6482
  }
@@ -6151,7 +6494,7 @@ function assertProofPayload(proof, content, mode) {
6151
6494
  function pathMatchesProof(parent, proof) {
6152
6495
  let fd;
6153
6496
  try {
6154
- fd = openFileAt(parent, constants4.O_RDONLY | constants4.O_NOFOLLOW);
6497
+ fd = openFileAt(parent, constants5.O_RDONLY | constants5.O_NOFOLLOW);
6155
6498
  } catch {
6156
6499
  return false;
6157
6500
  }
@@ -6159,7 +6502,7 @@ function pathMatchesProof(parent, proof) {
6159
6502
  const identity = identityOf(fd);
6160
6503
  return identity.device === proof.device && identity.inode === proof.inode;
6161
6504
  } finally {
6162
- closeSync5(fd);
6505
+ closeSync6(fd);
6163
6506
  }
6164
6507
  }
6165
6508
  function pathMatchesExpectedProof(parent, proof, expected, expectedMode) {
@@ -6180,7 +6523,7 @@ function modeOfProof(proof) {
6180
6523
  return inspectProof(proof).mode;
6181
6524
  }
6182
6525
  function inspectProof(proof) {
6183
- const stat2 = fstatSync3(proof.fd, { bigint: true });
6526
+ const stat2 = fstatSync4(proof.fd, { bigint: true });
6184
6527
  if (!stat2.isFile())
6185
6528
  throw new Error("\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
6186
6529
  if (stat2.dev !== proof.device || stat2.ino !== proof.inode) {
@@ -6197,7 +6540,7 @@ function inspectProof(proof) {
6197
6540
  throw new Error("\u4E8B\u52A1\u76EE\u6807\u8BFB\u53D6\u63D0\u524D\u7ED3\u675F");
6198
6541
  offset += count;
6199
6542
  }
6200
- const after = fstatSync3(proof.fd, { bigint: true });
6543
+ const after = fstatSync4(proof.fd, { bigint: true });
6201
6544
  if (after.dev !== stat2.dev || after.ino !== stat2.ino || after.size !== stat2.size || after.mtimeNs !== stat2.mtimeNs || after.ctimeNs !== stat2.ctimeNs || after.mode !== stat2.mode) {
6202
6545
  throw new Error("\u4E8B\u52A1\u76EE\u6807\u5728\u8BC1\u660E\u671F\u95F4\u53D1\u751F\u53D8\u5316");
6203
6546
  }
@@ -6207,7 +6550,7 @@ function inspectProof(proof) {
6207
6550
  };
6208
6551
  }
6209
6552
  function identityOf(fd) {
6210
- const stat2 = fstatSync3(fd, { bigint: true });
6553
+ const stat2 = fstatSync4(fd, { bigint: true });
6211
6554
  if (!stat2.isFile())
6212
6555
  throw new Error("\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
6213
6556
  return { device: stat2.dev, inode: stat2.ino };
@@ -6328,11 +6671,218 @@ function isBackupEntry(value) {
6328
6671
  return typeof entry.path === "string" && typeof entry.existed === "boolean" && (entry.mode === undefined || Number.isInteger(entry.mode) && entry.mode >= 0 && entry.mode <= 511);
6329
6672
  }
6330
6673
 
6674
+ // src/update/transaction-cas-windows.ts
6675
+ import { basename as basename7, dirname as dirname6 } from "path";
6676
+ import { closeSync as closeSync7, constants as constants6, fstatSync as fstatSync5, readSync as readSync2 } from "fs";
6677
+ async function windowsAnchoredCompareAndReplace(input) {
6678
+ assertSameDirectory(input.path, input.temporaryPath);
6679
+ const parent = await openAnchoredParent(input.root, input.path, true, input.parentMode);
6680
+ const temporaryName = basename7(input.temporaryPath);
6681
+ let ownsTemporary = false;
6682
+ let exchanged = false;
6683
+ let containsUnknownProjectBytes = false;
6684
+ try {
6685
+ const targetSnapshot = input.expected.kind === "hash" ? snapshot(parent) : undefined;
6686
+ const requestedMode = input.mode ?? targetSnapshot?.mode ?? 384;
6687
+ writeExclusiveAt(withLeaf(parent, temporaryName), input.content, requestedMode);
6688
+ ownsTemporary = true;
6689
+ const desiredSnapshot = snapshot(withLeaf(parent, temporaryName));
6690
+ if (!matchesPayload(desiredSnapshot, input.content))
6691
+ throw casError(input.path);
6692
+ await input.hooks?.beforeAtomicRename?.();
6693
+ if (input.expected.kind === "missing") {
6694
+ publishMissing(parent, temporaryName, input, desiredSnapshot);
6695
+ await input.hooks?.afterAtomicRenameBeforeInspect?.();
6696
+ ownsTemporary = pathMatchesPayload(withLeaf(parent, temporaryName), desiredSnapshot, input.content);
6697
+ containsUnknownProjectBytes = !ownsTemporary;
6698
+ if (!ownsTemporary)
6699
+ throw casError(input.path, input.temporaryPath);
6700
+ return;
6701
+ }
6702
+ if (!targetSnapshot || !pathMatches(parent, targetSnapshot) || !matchesExpected(targetSnapshot, input.expected) || !pathMatches(withLeaf(parent, temporaryName), desiredSnapshot) || !matchesPayload(desiredSnapshot, input.content)) {
6703
+ throw casError(input.path);
6704
+ }
6705
+ exchangeAt(parent, temporaryName, parent.leaf);
6706
+ exchanged = true;
6707
+ ownsTemporary = false;
6708
+ containsUnknownProjectBytes = true;
6709
+ await input.hooks?.afterExchangeBeforeProof?.();
6710
+ if (!pathMatches(withLeaf(parent, temporaryName), targetSnapshot) || !matchesExpected(targetSnapshot, input.expected) || !pathMatches(parent, desiredSnapshot) || !matchesPayload(desiredSnapshot, input.content)) {
6711
+ await rollbackExchange(parent, temporaryName, input, targetSnapshot);
6712
+ exchanged = false;
6713
+ ownsTemporary = pathMatchesPayload(withLeaf(parent, temporaryName), desiredSnapshot, input.content);
6714
+ containsUnknownProjectBytes = !ownsTemporary;
6715
+ throw casError(input.path, ownsTemporary ? undefined : input.temporaryPath);
6716
+ }
6717
+ await input.hooks?.afterAtomicRenameBeforeInspect?.();
6718
+ ownsTemporary = pathMatches(withLeaf(parent, temporaryName), targetSnapshot) && matchesExpected(targetSnapshot, input.expected);
6719
+ containsUnknownProjectBytes = !ownsTemporary;
6720
+ if (!ownsTemporary)
6721
+ throw casError(input.path, input.temporaryPath);
6722
+ } catch (error) {
6723
+ if (error instanceof TransactionCasError)
6724
+ throw error;
6725
+ if (exchanged || containsUnknownProjectBytes) {
6726
+ throw casError(input.path, input.temporaryPath, error);
6727
+ }
6728
+ if (hasFsCode5(error, "ENOENT") || hasFsCode5(error, "EEXIST")) {
6729
+ throw casError(input.path);
6730
+ }
6731
+ throw error;
6732
+ } finally {
6733
+ if (ownsTemporary)
6734
+ removeTemporary(parent, temporaryName);
6735
+ await parent.close();
6736
+ }
6737
+ }
6738
+ async function windowsAnchoredCompareAndRemove(input) {
6739
+ assertSameDirectory(input.path, input.quarantinePath);
6740
+ if (input.expected.kind === "missing")
6741
+ return;
6742
+ const parent = await openAnchoredParent(input.root, input.path, false);
6743
+ const quarantineName = basename7(input.quarantinePath);
6744
+ let ownsQuarantine = false;
6745
+ try {
6746
+ const targetSnapshot = snapshot(parent);
6747
+ await input.hooks?.beforeAtomicRename?.();
6748
+ if (!pathMatches(parent, targetSnapshot) || !matchesExpected(targetSnapshot, input.expected)) {
6749
+ throw casError(input.path);
6750
+ }
6751
+ moveNoReplaceAt(parent, parent.leaf, quarantineName);
6752
+ ownsQuarantine = true;
6753
+ if (!pathMatches(withLeaf(parent, quarantineName), targetSnapshot) || !matchesExpected(targetSnapshot, input.expected)) {
6754
+ throw casError(input.path, input.quarantinePath);
6755
+ }
6756
+ await input.hooks?.afterAtomicRenameBeforeInspect?.();
6757
+ if (pathMatches(withLeaf(parent, quarantineName), targetSnapshot) && matchesExpected(targetSnapshot, input.expected)) {
6758
+ removeTemporary(parent, quarantineName);
6759
+ ownsQuarantine = false;
6760
+ return;
6761
+ }
6762
+ throw casError(input.path, input.quarantinePath);
6763
+ } catch (error) {
6764
+ if (error instanceof TransactionCasError)
6765
+ throw error;
6766
+ if (ownsQuarantine)
6767
+ throw casError(input.path, input.quarantinePath, error);
6768
+ if (hasFsCode5(error, "ENOENT") || hasFsCode5(error, "EEXIST")) {
6769
+ throw casError(input.path);
6770
+ }
6771
+ throw error;
6772
+ } finally {
6773
+ await parent.close();
6774
+ }
6775
+ }
6776
+ function publishMissing(parent, temporaryName, input, desiredSnapshot) {
6777
+ if (!pathMatches(withLeaf(parent, temporaryName), desiredSnapshot) || !matchesPayload(desiredSnapshot, input.content)) {
6778
+ throw casError(input.path);
6779
+ }
6780
+ try {
6781
+ linkAt(parent, temporaryName, parent.leaf);
6782
+ } catch (error) {
6783
+ if (hasFsCode5(error, "EEXIST"))
6784
+ throw casError(input.path);
6785
+ throw error;
6786
+ }
6787
+ if (!pathMatches(parent, desiredSnapshot) || !matchesPayload(desiredSnapshot, input.content)) {
6788
+ throw casError(input.path, input.temporaryPath);
6789
+ }
6790
+ }
6791
+ async function rollbackExchange(parent, temporaryName, input, targetSnapshot) {
6792
+ if (!pathMatches(withLeaf(parent, temporaryName), targetSnapshot) || !matchesExpected(targetSnapshot, input.expected)) {
6793
+ throw casError(input.path, input.temporaryPath);
6794
+ }
6795
+ await input.hooks?.beforeExchangeRollback?.();
6796
+ if (!pathMatches(withLeaf(parent, temporaryName), targetSnapshot) || !matchesExpected(targetSnapshot, input.expected)) {
6797
+ throw casError(input.path, input.temporaryPath);
6798
+ }
6799
+ exchangeAt(parent, temporaryName, parent.leaf, true);
6800
+ await input.hooks?.afterExchangeRollbackBeforeCleanup?.();
6801
+ }
6802
+ function snapshot(parent) {
6803
+ const fd = openFileAt(parent, constants6.O_RDONLY);
6804
+ try {
6805
+ const before = fstatSync5(fd, { bigint: true });
6806
+ if (!before.isFile())
6807
+ throw new Error("\u4E8B\u52A1\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
6808
+ if (before.size > BigInt(Number.MAX_SAFE_INTEGER)) {
6809
+ throw new Error("\u4E8B\u52A1\u76EE\u6807\u8FC7\u5927\uFF0C\u65E0\u6CD5\u5B89\u5168\u9A8C\u8BC1");
6810
+ }
6811
+ const content = Buffer.alloc(Number(before.size));
6812
+ let offset = 0;
6813
+ while (offset < content.length) {
6814
+ const count = readSync2(fd, content, offset, content.length - offset, offset);
6815
+ if (!count)
6816
+ throw new Error("\u4E8B\u52A1\u76EE\u6807\u8BFB\u53D6\u63D0\u524D\u7ED3\u675F");
6817
+ offset += count;
6818
+ }
6819
+ const after = fstatSync5(fd, { bigint: true });
6820
+ if (after.dev !== before.dev || after.ino !== before.ino || after.size !== before.size || after.mtimeNs !== before.mtimeNs || after.ctimeNs !== before.ctimeNs) {
6821
+ throw new Error("\u4E8B\u52A1\u76EE\u6807\u5728\u8BC1\u660E\u671F\u95F4\u53D1\u751F\u53D8\u5316");
6822
+ }
6823
+ return {
6824
+ device: before.dev,
6825
+ inode: before.ino,
6826
+ hash: hashContent(content),
6827
+ mode: Number(before.mode & 0o777n)
6828
+ };
6829
+ } finally {
6830
+ closeSync7(fd);
6831
+ }
6832
+ }
6833
+ function pathMatches(parent, expected) {
6834
+ try {
6835
+ const current = snapshot(parent);
6836
+ return current.device === expected.device && current.inode === expected.inode && current.hash === expected.hash;
6837
+ } catch {
6838
+ return false;
6839
+ }
6840
+ }
6841
+ function pathMatchesPayload(parent, expected, content) {
6842
+ try {
6843
+ const current = snapshot(parent);
6844
+ return current.device === expected.device && current.inode === expected.inode && current.hash === hashContent(content);
6845
+ } catch {
6846
+ return false;
6847
+ }
6848
+ }
6849
+ function matchesExpected(snapshot2, expected) {
6850
+ return expected.kind === "hash" && snapshot2.hash === expected.value;
6851
+ }
6852
+ function matchesPayload(snapshot2, content) {
6853
+ return snapshot2.hash === hashContent(content);
6854
+ }
6855
+ function removeTemporary(parent, name) {
6856
+ try {
6857
+ unlinkAt(withLeaf(parent, name));
6858
+ } catch (error) {
6859
+ if (!hasFsCode5(error, "ENOENT"))
6860
+ throw error;
6861
+ }
6862
+ }
6863
+ function withLeaf(parent, leaf) {
6864
+ return { ...parent, leaf };
6865
+ }
6866
+ function assertSameDirectory(path2, temporaryPath) {
6867
+ if (dirname6(path2) !== dirname6(temporaryPath)) {
6868
+ throw new Error("\u4E8B\u52A1 CAS \u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u4E0E\u76EE\u6807\u4F4D\u4E8E\u540C\u4E00\u76EE\u5F55");
6869
+ }
6870
+ }
6871
+ function casError(path2, artifactPath, cause) {
6872
+ return new TransactionCasError(`\u8BA1\u5212\u540E\u5DF2\u53D8\u5316\uFF1A${path2}`, path2, artifactPath ? [{ path: path2, artifactPath }] : [], { cause });
6873
+ }
6874
+ function hasFsCode5(error, code) {
6875
+ return error instanceof Error && "code" in error && error.code === code;
6876
+ }
6877
+
6331
6878
  // src/update/transaction-cas.ts
6332
6879
  async function anchoredCompareAndReplace(input) {
6333
- assertSameDirectory(input.path, input.temporaryPath);
6880
+ if (process.platform === "win32") {
6881
+ return windowsAnchoredCompareAndReplace(input);
6882
+ }
6883
+ assertSameDirectory2(input.path, input.temporaryPath);
6334
6884
  const parent = await openAnchoredParent(input.root, input.path, true, input.parentMode);
6335
- const temporaryName = basename6(input.temporaryPath);
6885
+ const temporaryName = basename8(input.temporaryPath);
6336
6886
  let ownsTemporary = false;
6337
6887
  let exchanged = false;
6338
6888
  let containsUnknownProjectBytes = false;
@@ -6343,103 +6893,106 @@ async function anchoredCompareAndReplace(input) {
6343
6893
  targetProof = openFileProof(parent);
6344
6894
  }
6345
6895
  const mode = input.mode ?? (targetProof ? modeOfProof(targetProof) : 384);
6346
- writeExclusiveAt(withLeaf(parent, temporaryName), input.content, mode);
6896
+ writeExclusiveAt(withLeaf2(parent, temporaryName), input.content, mode);
6347
6897
  ownsTemporary = true;
6348
- desiredProof = openFileProof(withLeaf(parent, temporaryName));
6898
+ desiredProof = openFileProof(withLeaf2(parent, temporaryName));
6349
6899
  await input.hooks?.beforeAtomicRename?.();
6350
6900
  if (input.expected.kind === "missing") {
6351
- await publishMissing(parent, temporaryName, input, desiredProof, mode);
6352
- ownsTemporary = pathMatchesPayloadProof(withLeaf(parent, temporaryName), desiredProof, input.content, mode);
6901
+ await publishMissing2(parent, temporaryName, input, desiredProof, mode);
6902
+ ownsTemporary = pathMatchesPayloadProof(withLeaf2(parent, temporaryName), desiredProof, input.content, mode);
6353
6903
  containsUnknownProjectBytes = !ownsTemporary;
6354
6904
  if (!ownsTemporary) {
6355
- throw casError(input.path, input.temporaryPath);
6905
+ throw casError2(input.path, input.temporaryPath);
6356
6906
  }
6357
6907
  return;
6358
6908
  }
6359
- if (!targetProof || !pathMatchesProof(parent, targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode) || !pathMatchesProof(withLeaf(parent, temporaryName), desiredProof) || !assertProofPayload(desiredProof, input.content, mode)) {
6360
- throw casError(input.path);
6909
+ if (!targetProof || !pathMatchesProof(parent, targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode) || !pathMatchesProof(withLeaf2(parent, temporaryName), desiredProof) || !assertProofPayload(desiredProof, input.content, mode)) {
6910
+ throw casError2(input.path);
6361
6911
  }
6362
6912
  exchangeAt(parent, temporaryName, parent.leaf);
6363
6913
  exchanged = true;
6364
6914
  ownsTemporary = false;
6365
6915
  containsUnknownProjectBytes = true;
6366
6916
  await input.hooks?.afterExchangeBeforeProof?.();
6367
- const proofValid = pathMatchesProof(withLeaf(parent, temporaryName), targetProof) && assertProofMatches(targetProof, input.expected, input.expectedMode) && pathMatchesProof(parent, desiredProof) && assertProofPayload(desiredProof, input.content, mode);
6917
+ const proofValid = pathMatchesProof(withLeaf2(parent, temporaryName), targetProof) && assertProofMatches(targetProof, input.expected, input.expectedMode) && pathMatchesProof(parent, desiredProof) && assertProofPayload(desiredProof, input.content, mode);
6368
6918
  if (!proofValid) {
6369
- await rollbackExchange(parent, temporaryName, input, targetProof);
6919
+ await rollbackExchange2(parent, temporaryName, input, targetProof);
6370
6920
  exchanged = false;
6371
- ownsTemporary = pathMatchesPayloadProof(withLeaf(parent, temporaryName), desiredProof, input.content, mode);
6921
+ ownsTemporary = pathMatchesPayloadProof(withLeaf2(parent, temporaryName), desiredProof, input.content, mode);
6372
6922
  containsUnknownProjectBytes = !ownsTemporary;
6373
- throw casError(input.path, ownsTemporary ? undefined : input.temporaryPath);
6923
+ throw casError2(input.path, ownsTemporary ? undefined : input.temporaryPath);
6374
6924
  }
6375
6925
  await input.hooks?.afterAtomicRenameBeforeInspect?.();
6376
- ownsTemporary = pathMatchesExpectedProof(withLeaf(parent, temporaryName), targetProof, input.expected, input.expectedMode);
6926
+ ownsTemporary = pathMatchesExpectedProof(withLeaf2(parent, temporaryName), targetProof, input.expected, input.expectedMode);
6377
6927
  containsUnknownProjectBytes = !ownsTemporary;
6378
6928
  if (!ownsTemporary) {
6379
- throw casError(input.path, input.temporaryPath);
6929
+ throw casError2(input.path, input.temporaryPath);
6380
6930
  }
6381
6931
  } catch (error) {
6382
6932
  if (error instanceof TransactionCasError)
6383
6933
  throw error;
6384
6934
  if (exchanged) {
6385
- throw casError(input.path, input.temporaryPath, error);
6935
+ throw casError2(input.path, input.temporaryPath, error);
6386
6936
  }
6387
6937
  if (containsUnknownProjectBytes) {
6388
- throw casError(input.path, input.temporaryPath, error);
6938
+ throw casError2(input.path, input.temporaryPath, error);
6389
6939
  }
6390
- if (hasFsCode3(error, "ENOENT") || hasFsCode3(error, "EEXIST") || hasFsCode3(error, "ELOOP") || hasFsCode3(error, "ENOTDIR")) {
6391
- throw casError(input.path);
6940
+ if (hasFsCode4(error, "ENOENT") || hasFsCode4(error, "EEXIST") || hasFsCode4(error, "ELOOP") || hasFsCode4(error, "ENOTDIR")) {
6941
+ throw casError2(input.path);
6392
6942
  }
6393
6943
  throw error;
6394
6944
  } finally {
6395
6945
  if (ownsTemporary)
6396
- removeTemporary(parent, temporaryName);
6946
+ removeTemporary2(parent, temporaryName);
6397
6947
  desiredProof?.close();
6398
6948
  targetProof?.close();
6399
6949
  await parent.close();
6400
6950
  }
6401
6951
  }
6402
6952
  async function anchoredCompareAndRemove(input) {
6403
- assertSameDirectory(input.path, input.quarantinePath);
6953
+ if (process.platform === "win32") {
6954
+ return windowsAnchoredCompareAndRemove(input);
6955
+ }
6956
+ assertSameDirectory2(input.path, input.quarantinePath);
6404
6957
  if (input.expected.kind === "missing")
6405
6958
  return;
6406
6959
  let parent;
6407
6960
  try {
6408
6961
  parent = await openAnchoredParent(input.root, input.path, false);
6409
6962
  } catch (error) {
6410
- if (hasFsCode3(error, "ENOENT"))
6411
- throw casError(input.path);
6963
+ if (hasFsCode4(error, "ENOENT"))
6964
+ throw casError2(input.path);
6412
6965
  throw error;
6413
6966
  }
6414
- const quarantineName = basename6(input.quarantinePath);
6967
+ const quarantineName = basename8(input.quarantinePath);
6415
6968
  let ownsQuarantine = false;
6416
6969
  let targetProof;
6417
6970
  try {
6418
6971
  targetProof = openFileProof(parent);
6419
6972
  await input.hooks?.beforeAtomicRename?.();
6420
6973
  if (!pathMatchesProof(parent, targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
6421
- throw casError(input.path);
6974
+ throw casError2(input.path);
6422
6975
  }
6423
6976
  moveNoReplaceAt(parent, parent.leaf, quarantineName);
6424
6977
  ownsQuarantine = true;
6425
- if (!pathMatchesProof(withLeaf(parent, quarantineName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
6426
- throw casError(input.path, input.quarantinePath);
6978
+ if (!pathMatchesProof(withLeaf2(parent, quarantineName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
6979
+ throw casError2(input.path, input.quarantinePath);
6427
6980
  }
6428
6981
  await input.hooks?.afterAtomicRenameBeforeInspect?.();
6429
- if (pathMatchesExpectedProof(withLeaf(parent, quarantineName), targetProof, input.expected, input.expectedMode)) {
6430
- removeTemporary(parent, quarantineName);
6982
+ if (pathMatchesExpectedProof(withLeaf2(parent, quarantineName), targetProof, input.expected, input.expectedMode)) {
6983
+ removeTemporary2(parent, quarantineName);
6431
6984
  ownsQuarantine = false;
6432
6985
  return;
6433
6986
  }
6434
- throw casError(input.path, input.quarantinePath);
6987
+ throw casError2(input.path, input.quarantinePath);
6435
6988
  } catch (error) {
6436
6989
  if (error instanceof TransactionCasError)
6437
6990
  throw error;
6438
6991
  if (ownsQuarantine) {
6439
- throw casError(input.path, input.quarantinePath, error);
6992
+ throw casError2(input.path, input.quarantinePath, error);
6440
6993
  }
6441
- if (hasFsCode3(error, "ENOENT") || hasFsCode3(error, "EEXIST")) {
6442
- throw casError(input.path);
6994
+ if (hasFsCode4(error, "ENOENT") || hasFsCode4(error, "EEXIST")) {
6995
+ throw casError2(input.path);
6443
6996
  }
6444
6997
  throw error;
6445
6998
  } finally {
@@ -6455,8 +7008,8 @@ async function linearizeExpectation(input) {
6455
7008
  content = readFileAt(parent);
6456
7009
  } catch (error) {
6457
7010
  await parent.close();
6458
- if (hasFsCode3(error, "ENOENT"))
6459
- throw casError(input.path);
7011
+ if (hasFsCode4(error, "ENOENT"))
7012
+ throw casError2(input.path);
6460
7013
  throw error;
6461
7014
  }
6462
7015
  await parent.close();
@@ -6468,61 +7021,61 @@ async function linearizeExpectation(input) {
6468
7021
  }
6469
7022
  throw new Error(`\u7F3A\u5931\u8DEF\u5F84\u5FC5\u987B\u7531\u5199\u5165\u6216\u5220\u9664 CAS \u63D0\u4F9B\u7EBF\u6027\u5316\u8BC1\u636E\uFF1A${input.path}`);
6470
7023
  }
6471
- async function publishMissing(parent, temporaryName, input, desiredProof, mode) {
6472
- if (!pathMatchesProof(withLeaf(parent, temporaryName), desiredProof) || !assertProofPayload(desiredProof, input.content, mode)) {
6473
- throw casError(input.path);
7024
+ async function publishMissing2(parent, temporaryName, input, desiredProof, mode) {
7025
+ if (!pathMatchesProof(withLeaf2(parent, temporaryName), desiredProof) || !assertProofPayload(desiredProof, input.content, mode)) {
7026
+ throw casError2(input.path);
6474
7027
  }
6475
7028
  try {
6476
7029
  linkAt(parent, temporaryName, parent.leaf);
6477
7030
  } catch (error) {
6478
- if (hasFsCode3(error, "EEXIST"))
6479
- throw casError(input.path);
7031
+ if (hasFsCode4(error, "EEXIST"))
7032
+ throw casError2(input.path);
6480
7033
  throw error;
6481
7034
  }
6482
7035
  if (!pathMatchesProof(parent, desiredProof) || !assertProofPayload(desiredProof, input.content, mode)) {
6483
- throw casError(input.path, input.temporaryPath);
7036
+ throw casError2(input.path, input.temporaryPath);
6484
7037
  }
6485
7038
  await input.hooks?.afterAtomicRenameBeforeInspect?.();
6486
7039
  }
6487
- async function rollbackExchange(parent, temporaryName, input, targetProof) {
6488
- if (!pathMatchesProof(withLeaf(parent, temporaryName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
6489
- throw casError(input.path, input.temporaryPath);
7040
+ async function rollbackExchange2(parent, temporaryName, input, targetProof) {
7041
+ if (!pathMatchesProof(withLeaf2(parent, temporaryName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
7042
+ throw casError2(input.path, input.temporaryPath);
6490
7043
  }
6491
7044
  await input.hooks?.beforeExchangeRollback?.();
6492
- if (!pathMatchesProof(withLeaf(parent, temporaryName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
6493
- throw casError(input.path, input.temporaryPath);
7045
+ if (!pathMatchesProof(withLeaf2(parent, temporaryName), targetProof) || !assertProofMatches(targetProof, input.expected, input.expectedMode)) {
7046
+ throw casError2(input.path, input.temporaryPath);
6494
7047
  }
6495
7048
  exchangeAt(parent, temporaryName, parent.leaf, true);
6496
7049
  await input.hooks?.afterExchangeRollbackBeforeCleanup?.();
6497
7050
  }
6498
- function removeTemporary(parent, name) {
7051
+ function removeTemporary2(parent, name) {
6499
7052
  try {
6500
- unlinkAt(withLeaf(parent, name));
7053
+ unlinkAt(withLeaf2(parent, name));
6501
7054
  } catch (error) {
6502
- if (!hasFsCode3(error, "ENOENT"))
7055
+ if (!hasFsCode4(error, "ENOENT"))
6503
7056
  throw error;
6504
7057
  }
6505
7058
  }
6506
- function withLeaf(parent, leaf) {
7059
+ function withLeaf2(parent, leaf) {
6507
7060
  return { ...parent, leaf };
6508
7061
  }
6509
- function assertSameDirectory(path2, temporaryPath) {
6510
- if (dirname5(path2) !== dirname5(temporaryPath)) {
7062
+ function assertSameDirectory2(path2, temporaryPath) {
7063
+ if (dirname7(path2) !== dirname7(temporaryPath)) {
6511
7064
  throw new Error("\u4E8B\u52A1 CAS \u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u4E0E\u76EE\u6807\u4F4D\u4E8E\u540C\u4E00\u76EE\u5F55");
6512
7065
  }
6513
7066
  }
6514
- function casError(path2, artifactPath, cause) {
7067
+ function casError2(path2, artifactPath, cause) {
6515
7068
  return new TransactionCasError(`\u8BA1\u5212\u540E\u5DF2\u53D8\u5316\uFF1A${path2}`, path2, artifactPath ? [{ path: path2, artifactPath }] : [], { cause });
6516
7069
  }
6517
7070
 
6518
7071
  // src/update/transaction-runtime.ts
6519
7072
  import { randomUUID as randomUUID2 } from "crypto";
6520
- import { join as join13 } from "path";
7073
+ import { join as join14 } from "path";
6521
7074
 
6522
7075
  // src/update/transaction-state-temporaries.ts
6523
7076
  import { randomUUID } from "crypto";
6524
7077
  import { readdir as readdir7 } from "fs/promises";
6525
- import { join as join12 } from "path";
7078
+ import { join as join13 } from "path";
6526
7079
  function serializeTransactionState(state) {
6527
7080
  return `${JSON.stringify(state, null, 2)}
6528
7081
  `;
@@ -6638,8 +7191,8 @@ function stateTemporaryName(identity, cleanup) {
6638
7191
  return `${prefix}.${identity.kind}.${identity.ownerToken}.${identity.nonce}.tmp`;
6639
7192
  }
6640
7193
  async function listWindyDirectory(root) {
6641
- return readdir7(join12(root, ".windy")).catch((error) => {
6642
- if (hasFsCode3(error, "ENOENT"))
7194
+ return readdir7(join13(root, ".windy")).catch((error) => {
7195
+ if (hasFsCode4(error, "ENOENT"))
6643
7196
  return [];
6644
7197
  throw error;
6645
7198
  });
@@ -6672,7 +7225,7 @@ function createTransactionState(root, updateId, entries, manifestHash) {
6672
7225
  return {
6673
7226
  schemaVersion: 1,
6674
7227
  updateId,
6675
- backupDirectory: join13(root, backupRelativePath(updateId)),
7228
+ backupDirectory: join14(root, backupRelativePath(updateId)),
6676
7229
  entries,
6677
7230
  ownerToken: randomUUID2(),
6678
7231
  phase: "claiming",
@@ -6691,7 +7244,7 @@ async function claimTransactionState(root, state, hooks) {
6691
7244
  expected: { kind: "missing" }
6692
7245
  });
6693
7246
  } catch (error) {
6694
- if (hasFsCode3(error, "EEXIST") || error instanceof TransactionCasError) {
7247
+ if (hasFsCode4(error, "EEXIST") || error instanceof TransactionCasError) {
6695
7248
  throw new Error("\u68C0\u6D4B\u5230\u672A\u5B8C\u6210\u66F4\u65B0\uFF0C\u8BF7\u5148\u8FD0\u884C bun run windy doctor --repair", { cause: error });
6696
7249
  }
6697
7250
  throw error;
@@ -6731,7 +7284,7 @@ async function backupEntriesToDisk(root, backupPath, entries, afterEntry) {
6731
7284
  if (entry.mode !== undefined && await safeFileMode(root, entry.path) !== entry.mode) {
6732
7285
  throw new TransactionCasError(`\u5F85\u5907\u4EFD\u6587\u4EF6 mode \u5DF2\u53D8\u5316\uFF1A${entry.path}`, entry.path);
6733
7286
  }
6734
- await writeExclusive(root, join13(backupPath, "files", entry.path), content, undefined, entry.mode);
7287
+ await writeExclusive(root, join14(backupPath, "files", entry.path), content, undefined, entry.mode);
6735
7288
  await afterEntry?.();
6736
7289
  }
6737
7290
  }
@@ -7039,8 +7592,8 @@ async function removeOwnedResidue(root, evidence, hash, mode) {
7039
7592
  }
7040
7593
 
7041
7594
  // src/update/transaction-recovery-files.ts
7042
- import { join as join14 } from "path";
7043
- function matchesExpected(actualHash, actualMode, expected, expectedMode) {
7595
+ import { join as join15 } from "path";
7596
+ function matchesExpected2(actualHash, actualMode, expected, expectedMode) {
7044
7597
  return expected.kind === "missing" ? actualHash === undefined : actualHash === expected.value && (expectedMode === undefined || actualMode === expectedMode);
7045
7598
  }
7046
7599
  async function readRecoveryBackups(root, backupPath, state, preserved) {
@@ -7051,7 +7604,7 @@ async function readRecoveryBackups(root, backupPath, state, preserved) {
7051
7604
  await inspectSafePath(root, entry.path);
7052
7605
  if (!entry.existed)
7053
7606
  continue;
7054
- const backupFile = join14(backupPath, "files", entry.path);
7607
+ const backupFile = join15(backupPath, "files", entry.path);
7055
7608
  const content = await readSafeOptional(root, backupFile);
7056
7609
  if (!content)
7057
7610
  throw new Error(`\u4E8B\u52A1\u5907\u4EFD\u7F3A\u5931\uFF1A${entry.path}`);
@@ -7065,7 +7618,7 @@ async function readRecoveryBackups(root, backupPath, state, preserved) {
7065
7618
  async function assertRestoredEntries(root, state, backups) {
7066
7619
  for (const entry of state.entries) {
7067
7620
  const expected = entry.existed ? { kind: "hash", value: hashContent(backups.get(entry.path)) } : { kind: "missing" };
7068
- if (!matchesExpected(await hashSafePath(root, entry.path), await safeFileMode(root, entry.path), expected, entry.mode)) {
7621
+ if (!matchesExpected2(await hashSafePath(root, entry.path), await safeFileMode(root, entry.path), expected, entry.mode)) {
7069
7622
  throw new Error(`\u4E8B\u52A1\u8DEF\u5F84\u5C1A\u672A\u771F\u5B9E\u6062\u590D\uFF1A${entry.path}`);
7070
7623
  }
7071
7624
  const evidence = state.recoveryEvidence?.find(({ path: path2 }) => path2 === entry.path);
@@ -7088,8 +7641,8 @@ async function unresolvedPreservePaths(root, backupPath, state) {
7088
7641
  const actualHash = await hashSafePath(root, path2);
7089
7642
  const actualMode = await safeFileMode(root, path2);
7090
7643
  const mutation = state.mutationEvidence?.find((evidence) => evidence.path === path2);
7091
- const matchesBackup = matchesExpected(actualHash, actualMode, backup, entry.mode);
7092
- const matchesOutcome = Boolean(mutation?.linearized && mutation.outcome && matchesExpected(actualHash, actualMode, mutation.outcome, mutation.outcomeMode));
7644
+ const matchesBackup = matchesExpected2(actualHash, actualMode, backup, entry.mode);
7645
+ const matchesOutcome = Boolean(mutation?.linearized && mutation.outcome && matchesExpected2(actualHash, actualMode, mutation.outcome, mutation.outcomeMode));
7093
7646
  const hasConflictArtifact = state.conflictArtifacts?.some((artifact) => artifact.path === path2) ?? false;
7094
7647
  if (!matchesBackup && (!matchesOutcome || hasConflictArtifact)) {
7095
7648
  unresolved.push(path2);
@@ -7161,7 +7714,7 @@ async function restoreUpdateState(projectDirectory, state, options) {
7161
7714
  const actualHash = await hashSafePath(root, entry.path);
7162
7715
  if (current.phase === "committing") {
7163
7716
  const expected = current.expectations?.find(({ path: path2 }) => path2 === entry.path);
7164
- if (!expected || !matchesExpected(actualHash, await safeFileMode(root, entry.path), expected.expected, expected.mode)) {
7717
+ if (!expected || !matchesExpected2(actualHash, await safeFileMode(root, entry.path), expected.expected, expected.mode)) {
7165
7718
  newlyPreserved.push(entry.path);
7166
7719
  } else {
7167
7720
  recoveryExpectations.set(entry.path, expected);
@@ -7171,9 +7724,9 @@ async function restoreUpdateState(projectDirectory, state, options) {
7171
7724
  const evidence = current.mutationEvidence?.find(({ path: path2 }) => path2 === entry.path);
7172
7725
  if (!evidence) {
7173
7726
  newlyPreserved.push(entry.path);
7174
- } else if (matchesExpected(actualHash, await safeFileMode(root, entry.path), evidence.before, evidence.beforeMode)) {
7727
+ } else if (matchesExpected2(actualHash, await safeFileMode(root, entry.path), evidence.before, evidence.beforeMode)) {
7175
7728
  continue;
7176
- } else if (evidence.outcome && matchesExpected(actualHash, await safeFileMode(root, entry.path), evidence.outcome, evidence.outcomeMode)) {
7729
+ } else if (evidence.outcome && matchesExpected2(actualHash, await safeFileMode(root, entry.path), evidence.outcome, evidence.outcomeMode)) {
7177
7730
  recoveryExpectations.set(entry.path, {
7178
7731
  expected: evidence.outcome,
7179
7732
  mode: evidence.outcomeMode
@@ -7682,7 +8235,7 @@ async function diagnoseProject(projectDirectory, repair = false) {
7682
8235
  if (file.ownership === "project-owned")
7683
8236
  continue;
7684
8237
  try {
7685
- const changed = hashContent(await readFile11(join15(projectDirectory, file.path))) !== file.hash;
8238
+ const changed = hashContent(await readFile11(join16(projectDirectory, file.path))) !== file.hash;
7686
8239
  if (!changed)
7687
8240
  continue;
7688
8241
  modifiedManagedFiles.push(file.path);
@@ -7727,6 +8280,16 @@ var recipes = [
7727
8280
  id: "starter-0.6.7-to-0.6.8",
7728
8281
  from: "0.6.7",
7729
8282
  to: "0.6.8"
8283
+ },
8284
+ {
8285
+ id: "starter-0.6.8-to-0.6.9",
8286
+ from: "0.6.8",
8287
+ to: "0.6.9"
8288
+ },
8289
+ {
8290
+ id: "starter-0.6.9-to-0.6.10",
8291
+ from: "0.6.9",
8292
+ to: "0.6.10"
7730
8293
  }
7731
8294
  ];
7732
8295
  function resolveRecipeChain(sourceVersion, targetVersion) {
@@ -7773,17 +8336,17 @@ function parseVersion2(version) {
7773
8336
 
7774
8337
  // src/update/updater.ts
7775
8338
  import { readFile as readFile23, rm as rm8 } from "fs/promises";
7776
- import { join as join27 } from "path";
8339
+ import { join as join28 } from "path";
7777
8340
 
7778
8341
  // src/update/artifacts.ts
7779
8342
  import { mkdtemp, readFile as readFile14 } from "fs/promises";
7780
8343
  import { tmpdir } from "os";
7781
- import { basename as basename8, join as join18 } from "path";
8344
+ import { basename as basename10, join as join19 } from "path";
7782
8345
 
7783
8346
  // src/update/published-artifacts.ts
7784
8347
  import { createHash as createHash4 } from "crypto";
7785
8348
  import { mkdir as mkdir6, readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
7786
- import { basename as basename7, join as join16 } from "path";
8349
+ import { basename as basename9, join as join17 } from "path";
7787
8350
 
7788
8351
  // src/update/safe-archive.ts
7789
8352
  import { mkdir as mkdir5 } from "fs/promises";
@@ -7835,17 +8398,17 @@ async function downloadPublicArtifact(temporaryRoot, label, version, expectedInt
7835
8398
  }
7836
8399
  const archive = await readBoundedResponse(response, `create-windy@${version} artifact `);
7837
8400
  verifyArchive(metadata, archive);
7838
- const destination = join16(temporaryRoot, `${label}-artifact`);
7839
- const archivePath = join16(temporaryRoot, `${label}.tgz`);
8401
+ const destination = join17(temporaryRoot, `${label}-artifact`);
8402
+ const archivePath = join17(temporaryRoot, `${label}.tgz`);
7840
8403
  await writeFile10(archivePath, archive);
7841
8404
  await extractSafeTarArchive({
7842
8405
  archivePath,
7843
8406
  destination,
7844
8407
  cwd: temporaryRoot
7845
8408
  });
7846
- const packageRoot2 = join16(destination, "package");
7847
- const packageJson = JSON.parse(await readFile12(join16(packageRoot2, "package.json"), "utf8"));
7848
- const template = await readTemplateMetadata(join16(packageRoot2, "template"));
8409
+ const packageRoot2 = join17(destination, "package");
8410
+ const packageJson = JSON.parse(await readFile12(join17(packageRoot2, "package.json"), "utf8"));
8411
+ const template = await readTemplateMetadata(join17(packageRoot2, "template"));
7849
8412
  if (packageJson.name !== "create-windy" || packageJson.version !== version || template.generatorVersion !== version) {
7850
8413
  throw new Error(`create-windy@${version} \u5305\u8EAB\u4EFD\u6216\u6A21\u677F\u5143\u6570\u636E\u4E0D\u4E00\u81F4`);
7851
8414
  }
@@ -7977,10 +8540,10 @@ function verifyArchive(metadata, archive) {
7977
8540
  }
7978
8541
  }
7979
8542
  async function generatePublicArtifactProject(temporaryRoot, label, projectName, packageRoot2, provenance) {
7980
- const parent = join16(temporaryRoot, label);
8543
+ const parent = join17(temporaryRoot, label);
7981
8544
  await mkdir6(parent, { recursive: true });
7982
8545
  const args = [
7983
- join16(packageRoot2, "dist/cli.js"),
8546
+ join17(packageRoot2, "dist/cli.js"),
7984
8547
  projectName,
7985
8548
  "--yes",
7986
8549
  "--skip-install",
@@ -8000,7 +8563,7 @@ async function generatePublicArtifactProject(temporaryRoot, label, projectName,
8000
8563
  }
8001
8564
  }
8002
8565
  await assertProcess("bun", args, parent);
8003
- return join16(parent, projectName);
8566
+ return join17(parent, projectName);
8004
8567
  }
8005
8568
 
8006
8569
  // src/module-history.ts
@@ -8011,15 +8574,15 @@ import {
8011
8574
  readFile as readFile13,
8012
8575
  writeFile as writeFile11
8013
8576
  } from "fs/promises";
8014
- import { dirname as dirname6, join as join17, relative as relative4, sep as sep4 } from "path";
8577
+ import { dirname as dirname8, join as join18, relative as relative5, sep as sep4 } from "path";
8015
8578
  async function archiveRemovedModuleMigrations(input) {
8016
8579
  await assertExistingHistoryIntegrity(input.projectDirectory);
8017
- let changed = await copyMigrationTree(input.projectDirectory, ".windy/module-history", join17(input.targetDirectory, ".windy/module-history"));
8580
+ let changed = await copyMigrationTree(input.projectDirectory, ".windy/module-history", join18(input.targetDirectory, ".windy/module-history"));
8018
8581
  const target = new Set(input.targetModules);
8019
8582
  const removed = moduleDistributionCatalog.filter(({ name }) => input.sourceModules.includes(name) && !target.has(name));
8020
8583
  for (const manifest of removed) {
8021
8584
  for (const root of manifest.migrationRoots) {
8022
- changed = await copyMigrationTree(input.projectDirectory, root, join17(input.targetDirectory, ".windy/module-history", manifest.name, root)) || changed;
8585
+ changed = await copyMigrationTree(input.projectDirectory, root, join18(input.targetDirectory, ".windy/module-history", manifest.name, root)) || changed;
8023
8586
  }
8024
8587
  }
8025
8588
  if (changed) {
@@ -8027,7 +8590,7 @@ async function archiveRemovedModuleMigrations(input) {
8027
8590
  }
8028
8591
  }
8029
8592
  async function assertExistingHistoryIntegrity(projectDirectory) {
8030
- const historyRoot = join17(projectDirectory, ".windy/module-history");
8593
+ const historyRoot = join18(projectDirectory, ".windy/module-history");
8031
8594
  const metadata = await readOptionalMetadata(historyRoot);
8032
8595
  if (!metadata)
8033
8596
  return;
@@ -8037,7 +8600,7 @@ async function assertExistingHistoryIntegrity(projectDirectory) {
8037
8600
  const manifest = await readManagedFilesManifest(projectDirectory);
8038
8601
  const expected = new Map(manifest.files.map((entry) => [entry.path, entry]));
8039
8602
  for (const path2 of await collectRegularFiles(historyRoot)) {
8040
- const relativePath2 = relative4(projectDirectory, path2).split(sep4).join("/");
8603
+ const relativePath2 = relative5(projectDirectory, path2).split(sep4).join("/");
8041
8604
  const entry = expected.get(relativePath2);
8042
8605
  if (!entry || isMissingManagedFile(entry)) {
8043
8606
  throw new Error(`\u6A21\u5757 migration \u5386\u53F2\u672A\u767B\u8BB0\u5230\u53D7\u7BA1\u6E05\u5355\uFF1A${relativePath2}`);
@@ -8048,7 +8611,7 @@ async function assertExistingHistoryIntegrity(projectDirectory) {
8048
8611
  }
8049
8612
  }
8050
8613
  async function copyMigrationTree(projectRoot, relativeRoot, targetRoot) {
8051
- const sourceRoot = join17(projectRoot, relativeRoot);
8614
+ const sourceRoot = join18(projectRoot, relativeRoot);
8052
8615
  const rootMetadata = await readOptionalMetadata(sourceRoot);
8053
8616
  if (!rootMetadata)
8054
8617
  return false;
@@ -8056,8 +8619,8 @@ async function copyMigrationTree(projectRoot, relativeRoot, targetRoot) {
8056
8619
  throw new Error(`\u6A21\u5757 migration \u6839\u76EE\u5F55\u65E0\u6548\uFF1A${relativeRoot}`);
8057
8620
  }
8058
8621
  for (const source of await collectRegularFiles(sourceRoot)) {
8059
- const target = join17(targetRoot, relative4(sourceRoot, source).split(sep4).join("/"));
8060
- await mkdir7(dirname6(target), { recursive: true });
8622
+ const target = join18(targetRoot, relative5(sourceRoot, source).split(sep4).join("/"));
8623
+ await mkdir7(dirname8(target), { recursive: true });
8061
8624
  await writeFile11(target, await readFile13(source));
8062
8625
  }
8063
8626
  return true;
@@ -8068,7 +8631,7 @@ async function collectRegularFiles(root) {
8068
8631
  return files.sort();
8069
8632
  async function visit(directory) {
8070
8633
  for (const name of (await readdir8(directory)).sort()) {
8071
- const path2 = join17(directory, name);
8634
+ const path2 = join18(directory, name);
8072
8635
  const metadata = await lstat6(path2);
8073
8636
  if (metadata.isSymbolicLink()) {
8074
8637
  throw new Error(`\u6A21\u5757 migration \u4E0D\u5141\u8BB8\u7B26\u53F7\u94FE\u63A5\uFF1A${path2}`);
@@ -8098,10 +8661,10 @@ class PublishedArtifactProvider {
8098
8661
  this.#fetch = fetcher;
8099
8662
  }
8100
8663
  async prepare(projectDirectory, provenance, targetModules) {
8101
- const temporaryRoot = await mkdtemp(join18(tmpdir(), "windy-update-"));
8664
+ const temporaryRoot = await mkdtemp(join19(tmpdir(), "windy-update-"));
8102
8665
  const projectName = await readProjectName2(projectDirectory);
8103
- const baseDirectory = join18(temporaryRoot, "base", projectName);
8104
- const targetDirectory = join18(temporaryRoot, "target", projectName);
8666
+ const baseDirectory = join19(temporaryRoot, "base", projectName);
8667
+ const targetDirectory = join19(temporaryRoot, "target", projectName);
8105
8668
  const baseArtifact = await downloadPublicArtifact(temporaryRoot, "base", provenance.generatorVersion, undefined, this.#fetch);
8106
8669
  if (baseArtifact.identity.templateCommit !== provenance.templateCommit) {
8107
8670
  throw new Error("Project Lock \u4E0E\u6765\u6E90 registry artifact \u7684 template commit \u4E0D\u4E00\u81F4");
@@ -8129,13 +8692,13 @@ class PublishedArtifactProvider {
8129
8692
  }
8130
8693
  }
8131
8694
  async function readProjectName2(projectDirectory) {
8132
- const source = JSON.parse(await readFile14(join18(projectDirectory, "package.json"), "utf8"));
8133
- return source.name || basename8(projectDirectory);
8695
+ const source = JSON.parse(await readFile14(join19(projectDirectory, "package.json"), "utf8"));
8696
+ return source.name || basename10(projectDirectory);
8134
8697
  }
8135
8698
 
8136
8699
  // src/update/planner.ts
8137
8700
  import { readFile as readFile21 } from "fs/promises";
8138
- import { dirname as dirname7, join as join25 } from "path";
8701
+ import { dirname as dirname9, join as join26 } from "path";
8139
8702
 
8140
8703
  // src/update/docker-copy-update-plan.ts
8141
8704
  async function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
@@ -8224,15 +8787,15 @@ function matchesWorkspace(pattern, directory) {
8224
8787
 
8225
8788
  // src/update/migration-reconciler.ts
8226
8789
  import { readFile as readFile18 } from "fs/promises";
8227
- import { join as join21 } from "path";
8790
+ import { join as join22 } from "path";
8228
8791
 
8229
8792
  // src/update/migration-adoption.ts
8230
8793
  import { readFile as readFile17 } from "fs/promises";
8231
- import { join as join20 } from "path";
8794
+ import { join as join21 } from "path";
8232
8795
 
8233
8796
  // src/update/migration-project-file.ts
8234
8797
  import { readFile as readFile15 } from "fs/promises";
8235
- import { join as join19 } from "path";
8798
+ import { join as join20 } from "path";
8236
8799
  async function readProjectJson(input, path2) {
8237
8800
  const content = await readProjectFile(input, path2);
8238
8801
  if (!content) {
@@ -8248,7 +8811,7 @@ async function readProjectFile(input, path2) {
8248
8811
  }
8249
8812
  let content;
8250
8813
  try {
8251
- content = await readFile15(join19(input.projectDirectory, path2));
8814
+ content = await readFile15(join20(input.projectDirectory, path2));
8252
8815
  } catch (error) {
8253
8816
  if (!isMissingFileError(error))
8254
8817
  throw error;
@@ -8389,10 +8952,10 @@ async function inspectPreexistingMigrationAdoptions(input) {
8389
8952
  projectBeforeBytes,
8390
8953
  projectAfterBytes
8391
8954
  ] = await Promise.all([
8392
- readFile17(join20(input.targetDirectory, `${drizzleRoot}/${candidate.tag}.sql`)),
8955
+ readFile17(join21(input.targetDirectory, `${drizzleRoot}/${candidate.tag}.sql`)),
8393
8956
  readProjectFile(input, projectSqlPath),
8394
- readJson(join20(input.targetDirectory, snapshotPath(previousTarget.tag))),
8395
- readJson(join20(input.targetDirectory, snapshotPath(candidate.tag))),
8957
+ readJson(join21(input.targetDirectory, snapshotPath(previousTarget.tag))),
8958
+ readJson(join21(input.targetDirectory, snapshotPath(candidate.tag))),
8396
8959
  readProjectFile(input, snapshotPath(previousProject.tag)),
8397
8960
  readProjectFile(input, projectSnapshotPath)
8398
8961
  ]);
@@ -8519,13 +9082,13 @@ async function reconcileDrizzleMigrations(input) {
8519
9082
  const tag = `${prefix}_${name}`;
8520
9083
  const sqlPath = `${drizzleRoot}/${tag}.sql`;
8521
9084
  const snapshotPath2 = `${drizzleRoot}/meta/${prefix}_snapshot.json`;
8522
- const sql = await readFile18(join21(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
9085
+ const sql = await readFile18(join22(input.targetDirectory, `${drizzleRoot}/${addition.tag}.sql`));
8523
9086
  merged.id = targetAfter.id;
8524
9087
  merged.prevId = currentSnapshot.id;
8525
- const snapshot = encodeJson(merged);
9088
+ const snapshot2 = encodeJson(merged);
8526
9089
  contentOverrides.set(sqlPath, sql);
8527
- contentOverrides.set(snapshotPath2, snapshot);
8528
- files.push(managedEntry(sqlPath, sql), managedEntry(snapshotPath2, snapshot));
9090
+ contentOverrides.set(snapshotPath2, snapshot2);
9091
+ files.push(managedEntry(sqlPath, sql), managedEntry(snapshotPath2, snapshot2));
8529
9092
  previousWhen = Math.max(previousWhen + 1, addition.when);
8530
9093
  mergedJournal.entries.push({
8531
9094
  ...addition,
@@ -8566,9 +9129,9 @@ function unchanged(targetManifest) {
8566
9129
  async function readJournals(input) {
8567
9130
  try {
8568
9131
  const [base, project, target] = await Promise.all([
8569
- readJson(join21(input.baseDirectory, journalPath)),
9132
+ readJson(join22(input.baseDirectory, journalPath)),
8570
9133
  readProjectJson(input, journalPath),
8571
- readJson(join21(input.targetDirectory, journalPath))
9134
+ readJson(join22(input.targetDirectory, journalPath))
8572
9135
  ]);
8573
9136
  return { base, project, target };
8574
9137
  } catch (error) {
@@ -8599,17 +9162,17 @@ async function readLatestSnapshot(input, journal) {
8599
9162
  return JSON.parse(new TextDecoder().decode(content));
8600
9163
  }
8601
9164
  async function readSnapshot(root, tag) {
8602
- return await readJson(join21(root, snapshotPath(tag)));
9165
+ return await readJson(join22(root, snapshotPath(tag)));
8603
9166
  }
8604
9167
 
8605
9168
  // src/update/planner-file.ts
8606
9169
  import { readFile as readFile19 } from "fs/promises";
8607
- import { join as join23 } from "path";
9170
+ import { join as join24 } from "path";
8608
9171
 
8609
9172
  // src/update/merge.ts
8610
9173
  import { mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile12 } from "fs/promises";
8611
9174
  import { tmpdir as tmpdir2 } from "os";
8612
- import { join as join22 } from "path";
9175
+ import { join as join23 } from "path";
8613
9176
 
8614
9177
  // src/update/merge-convergent-additions.ts
8615
9178
  async function reconcileConvergentAdditions(input) {
@@ -8751,11 +9314,11 @@ function sameLines(left, right) {
8751
9314
 
8752
9315
  // src/update/merge.ts
8753
9316
  async function mergeTextFile(base, ours, theirs) {
8754
- const root = await mkdtemp2(join22(tmpdir2(), "windy-merge-"));
9317
+ const root = await mkdtemp2(join23(tmpdir2(), "windy-merge-"));
8755
9318
  try {
8756
- const oursPath = join22(root, "ours");
8757
- const basePath = join22(root, "base");
8758
- const theirsPath = join22(root, "theirs");
9319
+ const oursPath = join23(root, "ours");
9320
+ const basePath = join23(root, "base");
9321
+ const theirsPath = join23(root, "theirs");
8759
9322
  await Promise.all([
8760
9323
  writeFile12(oursPath, ours),
8761
9324
  writeFile12(basePath, base),
@@ -9088,15 +9651,133 @@ function conflict(path2, reason, expectedProjectContent) {
9088
9651
  };
9089
9652
  }
9090
9653
 
9654
+ // src/update/recipe-project-owned.ts
9655
+ var managedPathsByRecipe = {
9656
+ "starter-0.6.8-to-0.6.9": [
9657
+ "apps/web/src/router/index.ts",
9658
+ "apps/web/src/router/platform-admin-route-bindings.ts"
9659
+ ]
9660
+ };
9661
+ function recipeManagedProjectOwnedPaths(recipes2) {
9662
+ return new Set(recipes2.flatMap((recipe) => managedPathsByRecipe[recipe] ?? []));
9663
+ }
9664
+ async function planRecipeProjectOwned(input) {
9665
+ if (!input.ours) {
9666
+ return conflict2(input, "\u7248\u672C recipe \u6240\u9700\u7684\u9879\u76EE\u951A\u70B9\u7F3A\u5931");
9667
+ }
9668
+ const source = new TextDecoder().decode(input.ours);
9669
+ const transformed = transformProjectAdminAnchor(input.path, source);
9670
+ if ("error" in transformed)
9671
+ return conflict2(input, transformed.error);
9672
+ if (transformed.content === source) {
9673
+ return preserve(input, "\u5DF2\u5305\u542B\u7248\u672C recipe \u76EE\u6807\u5185\u5BB9");
9674
+ }
9675
+ return update(input, new TextEncoder().encode(transformed.content));
9676
+ }
9677
+ function transformProjectAdminAnchor(path2, source) {
9678
+ if (path2 === "apps/web/src/router/index.ts") {
9679
+ return addComponentPageLoader(source);
9680
+ }
9681
+ if (path2 === "apps/web/src/router/platform-admin-route-bindings.ts") {
9682
+ return addComponentRouteBinding(source);
9683
+ }
9684
+ return { error: `\u7248\u672C recipe \u672A\u767B\u8BB0\u9879\u76EE\u951A\u70B9\uFF1A${path2}` };
9685
+ }
9686
+ function addComponentPageLoader(source) {
9687
+ if (/^\s*"ui-components"\s*:/m.test(source))
9688
+ return { content: source };
9689
+ const declaration = source.indexOf("const platformAdminPageComponents");
9690
+ const start = source.indexOf("= {", declaration);
9691
+ const end = source.indexOf(`
9692
+ };`, start);
9693
+ if (declaration < 0 || start < 0 || end < 0) {
9694
+ return { error: "\u627E\u4E0D\u5230 platformAdminPageComponents \u9879\u76EE\u951A\u70B9" };
9695
+ }
9696
+ const block = source.slice(start, end);
9697
+ const profiles = [...block.matchAll(/^(\s*)profile:\s*.*,$/gm)];
9698
+ if (profiles.length !== 1) {
9699
+ return { error: "platformAdminPageComponents profile \u951A\u70B9\u4E0D\u552F\u4E00" };
9700
+ }
9701
+ const profile = profiles[0];
9702
+ const insertion = `${profile[0]}
9703
+ ${profile[1]}"ui-components": () => import("@/pages/ui/UiComponentPage.vue"),`;
9704
+ return {
9705
+ content: source.slice(0, start) + block.replace(profile[0], insertion) + source.slice(end)
9706
+ };
9707
+ }
9708
+ function addComponentRouteBinding(source) {
9709
+ const unionStart = source.indexOf("export type PlatformAdminPageKey =");
9710
+ const interfaceStart = source.indexOf("export interface PlatformAdminRouteBinding", unionStart);
9711
+ if (unionStart < 0 || interfaceStart < 0) {
9712
+ return { error: "\u627E\u4E0D\u5230 PlatformAdminPageKey \u9879\u76EE\u951A\u70B9" };
9713
+ }
9714
+ let content = source;
9715
+ const union = content.slice(unionStart, interfaceStart);
9716
+ if (!union.includes('"ui-components"')) {
9717
+ const semicolon = content.lastIndexOf(";", interfaceStart);
9718
+ if (semicolon < unionStart) {
9719
+ return { error: "PlatformAdminPageKey \u7ED3\u675F\u951A\u70B9\u7F3A\u5931" };
9720
+ }
9721
+ content = `${content.slice(0, semicolon)}
9722
+ | "ui-components"${content.slice(semicolon)}`;
9723
+ }
9724
+ if (content.includes('routeKey: "system.ui-components"')) {
9725
+ return { content };
9726
+ }
9727
+ const features = [
9728
+ ...content.matchAll(/^(\s*)\{ routeKey: "system\.feature", page: "resource", resourceKey: "features" \},$/gm)
9729
+ ];
9730
+ if (features.length !== 1) {
9731
+ return { error: "system.feature Admin Route \u951A\u70B9\u4E0D\u552F\u4E00" };
9732
+ }
9733
+ const feature = features[0];
9734
+ return {
9735
+ content: content.replace(feature[0], `${feature[0]}
9736
+ ${feature[1]}{ routeKey: "system.ui-components", page: "ui-components" },`)
9737
+ };
9738
+ }
9739
+ function preserve(input, reason) {
9740
+ return {
9741
+ path: input.path,
9742
+ ownership: "project-owned",
9743
+ action: "preserve",
9744
+ reason,
9745
+ expectedProjectContent: input.expected
9746
+ };
9747
+ }
9748
+ function update(input, content) {
9749
+ return {
9750
+ path: input.path,
9751
+ ownership: "project-owned",
9752
+ action: "update",
9753
+ reason: "\u7248\u672C recipe \u66F4\u65B0\u9879\u76EE Admin \u6269\u5C55\u951A\u70B9",
9754
+ expectedProjectContent: input.expected,
9755
+ content
9756
+ };
9757
+ }
9758
+ function conflict2(input, message) {
9759
+ return {
9760
+ path: input.path,
9761
+ ownership: "project-owned",
9762
+ action: "preserve",
9763
+ reason: "\u5BA2\u6237\u5DF2\u4FEE\u6539",
9764
+ expectedProjectContent: input.expected,
9765
+ conflict: message
9766
+ };
9767
+ }
9768
+
9091
9769
  // src/update/planner-file.ts
9092
- async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false, forcePlatformBaseline = false) {
9770
+ async function planFile(path2, baseRoot, targetRoot, source, target, ours, provenance, targetContentOverride, manageGeneratedProjectOwned = false, forcePlatformBaseline = false, manageRecipeProjectOwned = false) {
9093
9771
  const [base, theirs] = await Promise.all([
9094
- readOptional(join23(baseRoot, path2)),
9095
- targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional(join23(targetRoot, path2))
9772
+ readOptional(join24(baseRoot, path2)),
9773
+ targetContentOverride ? Promise.resolve(targetContentOverride) : readOptional(join24(targetRoot, path2))
9096
9774
  ]);
9097
9775
  const ownership = source?.ownership ?? target?.ownership ?? classifyOwnership(path2);
9098
9776
  const expected = expectationForSnapshot(ours);
9099
9777
  if (ownership === "project-owned") {
9778
+ if (manageRecipeProjectOwned) {
9779
+ return planRecipeProjectOwned({ path: path2, ours, expected });
9780
+ }
9100
9781
  if (manageGeneratedProjectOwned) {
9101
9782
  return planGeneratedProjectOwned(path2, source, target, ours, theirs, expected);
9102
9783
  }
@@ -9104,26 +9785,26 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
9104
9785
  }
9105
9786
  if (path2.startsWith("packages/database/drizzle/") && path2.endsWith(".sql")) {
9106
9787
  if (source && !target) {
9107
- return conflict2(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
9788
+ return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u5220\u9664", expected);
9108
9789
  }
9109
9790
  if (source && target && source.hash !== target.hash) {
9110
- return conflict2(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
9791
+ return conflict3(path2, ownership, "\u5DF2\u53D1\u5E03 migration \u4E0D\u53EF\u6539\u5199\uFF0C\u53EA\u80FD\u8FFD\u52A0\u65B0\u6587\u4EF6", expected);
9111
9792
  }
9112
9793
  }
9113
9794
  if (!source && target) {
9114
9795
  if (!ours) {
9115
9796
  return readyPlannedFile(path2, ownership, "create", "\u76EE\u6807\u7248\u672C\u65B0\u589E", expected, theirs);
9116
9797
  }
9117
- return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict2(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
9798
+ return theirs && hashContent(ours) === target.hash ? readyPlannedFile(path2, ownership, "preserve", "\u5DF2\u5305\u542B\u76EE\u6807\u5185\u5BB9", expected) : conflict3(path2, ownership, "\u76EE\u6807\u7248\u672C\u65B0\u589E\u8DEF\u5F84\u5DF2\u88AB\u9879\u76EE\u5360\u7528", expected);
9118
9799
  }
9119
9800
  if (source && !target) {
9120
9801
  if (!ours) {
9121
9802
  return readyPlannedFile(path2, ownership, "preserve", "\u9879\u76EE\u5DF2\u5220\u9664", expected);
9122
9803
  }
9123
- return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict2(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
9804
+ return hashContent(ours) === source.hash ? readyPlannedFile(path2, ownership, "delete", "\u76EE\u6807\u7248\u672C\u5220\u9664", expected) : conflict3(path2, ownership, "\u5BA2\u6237\u4FEE\u6539\u540E Windy \u53C8\u5220\u9664", expected);
9124
9805
  }
9125
9806
  if (!source || !target || !ours || !theirs) {
9126
- return conflict2(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
9807
+ return conflict3(path2, ownership, "\u6587\u4EF6\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u4E0D\u80FD\u5B89\u5168\u63A8\u65AD", expected);
9127
9808
  }
9128
9809
  const oursChanged = hashContent(ours) !== source.hash;
9129
9810
  const sourceArtifactHash = artifactHashOf(source);
@@ -9137,7 +9818,7 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
9137
9818
  });
9138
9819
  if (forceTargetBaseline && path2.endsWith("package.json") && base) {
9139
9820
  const merged = mergePackageJson(base, ours, theirs);
9140
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
9821
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
9141
9822
  }
9142
9823
  if (forceTargetBaseline) {
9143
9824
  return readyPlannedFile(path2, ownership, "update", "\u5F3A\u5236\u91C7\u7528\u76EE\u6807\u5E73\u53F0\u57FA\u7EBF", expected, theirs);
@@ -9147,11 +9828,11 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
9147
9828
  }
9148
9829
  if (targetChanged && path2.endsWith("package.json") && base) {
9149
9830
  const merged = mergePackageJson(base, ours, theirs);
9150
- return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
9831
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "package.json \u5B57\u6BB5\u7EA7\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, `\u5B57\u6BB5\u51B2\u7A81\uFF1A${merged.conflicts.join("\u3001")}`, expected);
9151
9832
  }
9152
9833
  if (!oursChanged && targetChanged && adoptedProjectDelta && base) {
9153
9834
  const merged = await mergeTextFile(base, ours, theirs);
9154
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict2(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
9835
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76\u5DF2\u91C7\u7EB3\u9879\u76EE\u589E\u91CF", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
9155
9836
  }
9156
9837
  if (!oursChanged) {
9157
9838
  return readyPlannedFile(path2, ownership, "update", "\u4EC5 Windy \u4FEE\u6539", expected, theirs);
@@ -9164,9 +9845,9 @@ async function planFile(path2, baseRoot, targetRoot, source, target, ours, prove
9164
9845
  }
9165
9846
  if (base) {
9166
9847
  const merged = await mergeTextFile(base, ours, theirs);
9167
- return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict2(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
9848
+ return merged.content ? readyPlannedFile(path2, ownership, "update", "\u4E09\u65B9\u5408\u5E76", expected, merged.content) : conflict3(path2, ownership, merged.conflict || "\u4E09\u65B9\u5408\u5E76\u5931\u8D25", expected);
9168
9849
  }
9169
- return conflict2(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
9850
+ return conflict3(path2, ownership, "\u5BA2\u6237\u548C Windy \u5747\u5DF2\u4FEE\u6539", expected);
9170
9851
  }
9171
9852
  function shouldForcePlatformBaseline(input) {
9172
9853
  return input.forcePlatformBaseline && !input.oursChanged && input.base !== undefined && hashContent(input.base) !== input.sourceArtifactHash;
@@ -9187,7 +9868,7 @@ function readyPlannedFile(path2, ownership, action, reason, expectedProjectConte
9187
9868
  function expectationForSnapshot(content) {
9188
9869
  return content ? { kind: "hash", value: hashContent(content) } : { kind: "missing" };
9189
9870
  }
9190
- function conflict2(path2, ownership, reason, expectedProjectContent) {
9871
+ function conflict3(path2, ownership, reason, expectedProjectContent) {
9191
9872
  return {
9192
9873
  path: path2,
9193
9874
  ownership,
@@ -9252,26 +9933,26 @@ function hasExistingSourceForTest(path2, sourcePaths) {
9252
9933
 
9253
9934
  // src/update/planner-snapshots.ts
9254
9935
  import { readFile as readFile20, stat as stat2 } from "fs/promises";
9255
- import { join as join24 } from "path";
9936
+ import { join as join25 } from "path";
9256
9937
  async function snapshotProjectFiles(project, paths, seed) {
9257
9938
  const snapshots = new Map(seed);
9258
9939
  await Promise.all([...paths].filter((path2) => !snapshots.has(path2)).map(async (path2) => {
9259
- snapshots.set(path2, await readOptional2(join24(project, path2)));
9940
+ snapshots.set(path2, await readOptional2(join25(project, path2)));
9260
9941
  }));
9261
9942
  return snapshots;
9262
9943
  }
9263
9944
  async function snapshotProjectModes(project, paths) {
9264
- return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(join24(project, path2))])));
9945
+ return new Map(await Promise.all([...paths].map(async (path2) => [path2, await readModeOptional(join25(project, path2))])));
9265
9946
  }
9266
9947
  async function assertPlanSnapshots(project, expectations) {
9267
9948
  const changed = [];
9268
9949
  for (const expectation2 of expectations) {
9269
- const actual = expectationForSnapshot(await readOptional2(join24(project, expectation2.path)));
9950
+ const actual = expectationForSnapshot(await readOptional2(join25(project, expectation2.path)));
9270
9951
  if (JSON.stringify(actual) !== JSON.stringify(expectation2.expected)) {
9271
9952
  changed.push(expectation2.path);
9272
9953
  continue;
9273
9954
  }
9274
- if ("mode" in expectation2 && await readModeOptional(join24(project, expectation2.path)) !== expectation2.mode) {
9955
+ if ("mode" in expectation2 && await readModeOptional(join25(project, expectation2.path)) !== expectation2.mode) {
9275
9956
  changed.push(expectation2.path);
9276
9957
  }
9277
9958
  }
@@ -9347,7 +10028,7 @@ var oxcManagedPaths = new Set([
9347
10028
  ]);
9348
10029
  async function createUpdatePlan(request, artifacts, dependencies = {}) {
9349
10030
  await assertProjectReadyForUpdate(request.projectDirectory);
9350
- const manifestPath = join25(request.projectDirectory, ".windy/files.json");
10031
+ const manifestPath = join26(request.projectDirectory, ".windy/files.json");
9351
10032
  const expectedManifestHash = hashContent(await readFile21(manifestPath));
9352
10033
  const generationSnapshot = await readGenerationProvenanceSnapshot(request.projectDirectory);
9353
10034
  const provenance = generationSnapshot.provenance;
@@ -9361,6 +10042,7 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
9361
10042
  const versionRecipes = (dependencies.resolveVersionRecipes ?? resolveRecipeChain)(provenance.windyVersion, targetVersion);
9362
10043
  const moduleRecipes = resolveModuleRecipeIds(request);
9363
10044
  const recipes2 = [...versionRecipes.map(({ id }) => id), ...moduleRecipes];
10045
+ const recipeProjectOwnedPaths = recipeManagedProjectOwnedPaths(recipes2);
9364
10046
  const [rawSourceManifest, rawTargetManifest] = await Promise.all([
9365
10047
  readManagedFilesManifest(request.projectDirectory),
9366
10048
  readManagedFilesManifest(artifactSet.targetDirectory)
@@ -9394,8 +10076,8 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
9394
10076
  const paths = new Set([...sourceEntries.keys(), ...targetEntries.keys()]);
9395
10077
  for (const path2 of paths) {
9396
10078
  if (!projectSnapshots.has(path2)) {
9397
- projectSnapshots.set(path2, await readOptional2(join25(request.projectDirectory, path2)));
9398
- projectModes.set(path2, await readModeOptional(join25(request.projectDirectory, path2)));
10079
+ projectSnapshots.set(path2, await readOptional2(join26(request.projectDirectory, path2)));
10080
+ projectModes.set(path2, await readModeOptional(join26(request.projectDirectory, path2)));
9399
10081
  }
9400
10082
  }
9401
10083
  const files = await planFiles({
@@ -9407,7 +10089,8 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
9407
10089
  artifactSet,
9408
10090
  provenance,
9409
10091
  manageGeneratedProjectOwned: request.targetModules !== undefined,
9410
- forcePlatformBaseline: request.forcePlatformBaseline === true
10092
+ forcePlatformBaseline: request.forcePlatformBaseline === true,
10093
+ recipeProjectOwnedPaths
9411
10094
  });
9412
10095
  preserveTestsForExistingProjectOwnedSources(files, sourceEntries);
9413
10096
  await deriveDockerfilePlans(files, projectSnapshots, new Set([
@@ -9418,10 +10101,10 @@ async function createUpdatePlan(request, artifacts, dependencies = {}) {
9418
10101
  for (const file of files) {
9419
10102
  file.expectedProjectMode = projectModes.get(file.path);
9420
10103
  if (file.action === "create" || file.action === "update") {
9421
- file.mode = file.expectedProjectMode ?? await readModeOptional(join25(artifactSet.targetDirectory, file.path));
10104
+ file.mode = file.expectedProjectMode ?? await readModeOptional(join26(artifactSet.targetDirectory, file.path));
9422
10105
  }
9423
10106
  if (file.action === "create") {
9424
- file.parentMode = await readSourceParentMode(join25(artifactSet.targetDirectory, dirname7(file.path)));
10107
+ file.parentMode = await readSourceParentMode(join26(artifactSet.targetDirectory, dirname9(file.path)));
9425
10108
  }
9426
10109
  }
9427
10110
  const plannedPaths = new Set(files.map(({ path: path2 }) => path2));
@@ -9486,7 +10169,7 @@ async function planFiles(input) {
9486
10169
  } else if (forcedContent) {
9487
10170
  files.push(readyPlannedFile(path2, input.targetEntries.get(path2)?.ownership ?? input.sourceEntries.get(path2)?.ownership ?? classifyOwnership(path2), "update", "\u5408\u5E76\u5E73\u53F0\u4E0E\u4E0B\u6E38 migration \u5386\u53F2", expected, forcedContent));
9488
10171
  } else {
9489
- files.push(await planFile(path2, input.artifactSet.baseDirectory, input.artifactSet.targetDirectory, input.sourceEntries.get(path2), input.targetEntries.get(path2), ours, input.provenance, input.migrations.contentOverrides.get(path2), input.manageGeneratedProjectOwned, input.forcePlatformBaseline));
10172
+ files.push(await planFile(path2, input.artifactSet.baseDirectory, input.artifactSet.targetDirectory, input.sourceEntries.get(path2), input.targetEntries.get(path2), ours, input.provenance, input.migrations.contentOverrides.get(path2), input.manageGeneratedProjectOwned, input.forcePlatformBaseline, input.recipeProjectOwnedPaths.has(path2)));
9490
10173
  }
9491
10174
  }
9492
10175
  return files;
@@ -9568,7 +10251,7 @@ function frozenManifestHash(file, finalizedHashes) {
9568
10251
  // src/update/format-stabilizer.ts
9569
10252
  import { mkdir as mkdir8, mkdtemp as mkdtemp3, readFile as readFile22, rm as rm7, writeFile as writeFile13 } from "fs/promises";
9570
10253
  import { tmpdir as tmpdir3 } from "os";
9571
- import { dirname as dirname8, extname as extname4, join as join26, resolve as resolve6, sep as sep5 } from "path";
10254
+ import { dirname as dirname10, extname as extname4, join as join27, resolve as resolve6, sep as sep5 } from "path";
9572
10255
  var formattedExtensions = new Set([
9573
10256
  ".cjs",
9574
10257
  ".css",
@@ -9607,7 +10290,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
9607
10290
  }
9608
10291
  }
9609
10292
  inputs.set(".windy/generation.json", new TextEncoder().encode(generationContent));
9610
- const temporaryRoot = await mkdtemp3(join26(tmpdir3(), "windy-update-format-"));
10293
+ const temporaryRoot = await mkdtemp3(join27(tmpdir3(), "windy-update-format-"));
9611
10294
  try {
9612
10295
  const stagedPaths = await stageInputs(temporaryRoot, inputs);
9613
10296
  for (let offset = 0;offset < stagedPaths.length; offset += 80) {
@@ -9615,7 +10298,7 @@ async function stabilizeManagedContent(result2, execute, writeProjectFile) {
9615
10298
  "x",
9616
10299
  "oxfmt",
9617
10300
  "--write",
9618
- `--config=${join26(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
10301
+ `--config=${join27(result2.plan.projectDirectory, ".oxfmtrc.json")}`,
9619
10302
  ...stagedPaths.slice(offset, offset + 80)
9620
10303
  ], result2.plan.projectDirectory);
9621
10304
  }
@@ -9648,7 +10331,7 @@ async function stageInputs(temporaryRoot, inputs) {
9648
10331
  const paths = [];
9649
10332
  for (const [path2, content] of inputs) {
9650
10333
  const target = safeTemporaryPath(temporaryRoot, path2);
9651
- await mkdir8(dirname8(target), { recursive: true });
10334
+ await mkdir8(dirname10(target), { recursive: true });
9652
10335
  await writeFile13(target, content);
9653
10336
  paths.push(target);
9654
10337
  }
@@ -9776,7 +10459,7 @@ class DefaultStarterUpdater {
9776
10459
  const plannedPaths = new Set(result2.plan.files.map(({ path: path2 }) => path2));
9777
10460
  replaceExpectations(result2, verificationSnapshot.filter(({ path: path2 }) => !metadataPaths2.has(path2) && !plannedPaths.has(path2)));
9778
10461
  verificationExpectationsFrozen = true;
9779
- const packageJson = JSON.parse(await readFile23(join27(result2.plan.projectDirectory, "package.json"), "utf8"));
10462
+ const packageJson = JSON.parse(await readFile23(join28(result2.plan.projectDirectory, "package.json"), "utf8"));
9780
10463
  for (const name of ["lint", "typecheck", "test", "build"]) {
9781
10464
  if (!packageJson.scripts?.[name]) {
9782
10465
  steps.push({ name: `bun run ${name}`, status: "skipped" });
@@ -10007,9 +10690,9 @@ function assertEnabledConflicts(target, catalog) {
10007
10690
  for (const [name, enabled] of target) {
10008
10691
  if (!enabled)
10009
10692
  continue;
10010
- const conflict3 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
10011
- if (conflict3)
10012
- throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict3}`);
10693
+ const conflict4 = catalog.get(name).conflicts.find((candidate) => target.get(candidate));
10694
+ if (conflict4)
10695
+ throw new Error(`\u6A21\u5757\u51B2\u7A81\uFF1A${name} \u4E0E ${conflict4}`);
10013
10696
  }
10014
10697
  }
10015
10698
  function assertCompatible(version, range, name) {
@@ -10024,7 +10707,7 @@ function reconcileProjectModuleRegistryPlan(plan, current, lifecycle) {
10024
10707
  if (!registryFile) {
10025
10708
  throw new Error("\u6A21\u5757\u751F\u547D\u5468\u671F\u8BA1\u5212\u7F3A\u5C11 project-owned \u88C5\u914D\u9009\u62E9");
10026
10709
  }
10027
- plan.conflicts = plan.conflicts.filter((conflict3) => !conflict3.startsWith(`${projectModuleRegistryPath}\uFF1A`));
10710
+ plan.conflicts = plan.conflicts.filter((conflict4) => !conflict4.startsWith(`${projectModuleRegistryPath}\uFF1A`));
10028
10711
  delete registryFile.conflict;
10029
10712
  if (lifecycle.action === "update") {
10030
10713
  registryFile.action = "preserve";
@@ -10454,8 +11137,8 @@ function printModulePlan(plan, log) {
10454
11137
  for (const file of changed) {
10455
11138
  log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
10456
11139
  }
10457
- for (const conflict3 of plan.conflicts)
10458
- log(` conflict ${conflict3}`);
11140
+ for (const conflict4 of plan.conflicts)
11141
+ log(` conflict ${conflict4}`);
10459
11142
  }
10460
11143
  function hasChanges(lifecycle) {
10461
11144
  return lifecycle.addedModules.length > 0 || lifecycle.updatedModules.length > 0 || lifecycle.removedModules.length > 0;
@@ -10627,8 +11310,8 @@ function printPlan(plan) {
10627
11310
  console.log(`\u8BA1\u5212\u6539\u52A8\uFF1A${changed.length} \u4E2A\u6587\u4EF6\uFF1B\u51B2\u7A81\uFF1A${plan.conflicts.length}`);
10628
11311
  for (const file of changed)
10629
11312
  console.log(` ${file.action.padEnd(6)} ${file.path}\uFF08${file.reason}\uFF09`);
10630
- for (const conflict3 of plan.conflicts)
10631
- console.log(` conflict ${conflict3}`);
11313
+ for (const conflict4 of plan.conflicts)
11314
+ console.log(` conflict ${conflict4}`);
10632
11315
  if (plan.detachedToolchain)
10633
11316
  console.log("Oxc\uFF1A\u68C0\u6D4B\u5230\u5BA2\u6237\u63A5\u7BA1\uFF0C\u76F8\u5173\u914D\u7F6E\u4FDD\u6301\u4E0D\u53D8");
10634
11317
  }
@@ -10715,11 +11398,11 @@ import {
10715
11398
  rm as rm11,
10716
11399
  writeFile as writeFile14
10717
11400
  } from "fs/promises";
10718
- import { dirname as dirname9, join as join28, relative as relative6 } from "path";
11401
+ import { dirname as dirname11, join as join29, relative as relative7 } from "path";
10719
11402
 
10720
11403
  // src/module-schema/config.ts
10721
11404
  import { readFile as readFile24 } from "fs/promises";
10722
- import { isAbsolute as isAbsolute2, relative as relative5, resolve as resolve9 } from "path";
11405
+ import { isAbsolute as isAbsolute2, relative as relative6, resolve as resolve9 } from "path";
10723
11406
  async function readModuleSchemaLineageConfig(projectDirectory, configPath) {
10724
11407
  const absolutePath = resolveProjectPath(projectDirectory, configPath);
10725
11408
  const parsed = JSON.parse(await readFile24(absolutePath, "utf8"));
@@ -10737,7 +11420,7 @@ function resolveProjectPath(projectDirectory, path2) {
10737
11420
  if (isAbsolute2(path2))
10738
11421
  throw new Error(`\u8DEF\u5F84\u5FC5\u987B\u76F8\u5BF9\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${path2}`);
10739
11422
  const resolved = resolve9(projectDirectory, path2);
10740
- const projectRelative = relative5(projectDirectory, resolved);
11423
+ const projectRelative = relative6(projectDirectory, resolved);
10741
11424
  if (projectRelative.startsWith("..") || isAbsolute2(projectRelative)) {
10742
11425
  throw new Error(`\u8DEF\u5F84\u8D8A\u51FA\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${path2}`);
10743
11426
  }
@@ -10856,17 +11539,17 @@ async function handoffModuleSchemaLineages(options) {
10856
11539
  async function stageModuleLineages(project, temporaryRoot, config, execute) {
10857
11540
  const outputs = [];
10858
11541
  for (const [index, module2] of config.modules.entries()) {
10859
- const output = join28(temporaryRoot, `module-${index}`);
11542
+ const output = join29(temporaryRoot, `module-${index}`);
10860
11543
  await mkdir9(output, { recursive: true });
10861
- const generatedConfig = join28(temporaryRoot, `module-${index}.config.ts`);
10862
- await writeDrizzleConfig(generatedConfig, project, module2.schema, relative6(temporaryRoot, output));
11544
+ const generatedConfig = join29(temporaryRoot, `module-${index}.config.ts`);
11545
+ await writeDrizzleConfig(generatedConfig, project, module2.schema, relative7(temporaryRoot, output));
10863
11546
  await execute(generatedConfig, temporaryRoot);
10864
11547
  const sqlFiles = await listSqlFiles(output);
10865
11548
  if (sqlFiles.length !== 1) {
10866
11549
  throw new Error(`${module2.key} baseline \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration`);
10867
11550
  }
10868
- await writeFile14(join28(output, sqlFiles[0]), metadataOnlySql("module"));
10869
- await writeFile14(join28(output, "lineage.json"), `${JSON.stringify({
11551
+ await writeFile14(join29(output, sqlFiles[0]), metadataOnlySql("module"));
11552
+ await writeFile14(join29(output, "lineage.json"), `${JSON.stringify({
10870
11553
  schemaVersion: 1,
10871
11554
  moduleKey: module2.key,
10872
11555
  schema: module2.schema,
@@ -10880,17 +11563,17 @@ async function stageModuleLineages(project, temporaryRoot, config, execute) {
10880
11563
  }
10881
11564
  async function stagePlatformLineage(project, temporaryRoot, config, execute) {
10882
11565
  const source = resolveProjectPath(project, config.platform.out);
10883
- const output = join28(temporaryRoot, "platform");
11566
+ const output = join29(temporaryRoot, "platform");
10884
11567
  await cp(source, output, { recursive: true });
10885
11568
  const before = new Set(await listSqlFiles(output));
10886
- const generatedConfig = join28(temporaryRoot, "platform.config.ts");
10887
- await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative6(temporaryRoot, output));
11569
+ const generatedConfig = join29(temporaryRoot, "platform.config.ts");
11570
+ await writeDrizzleConfig(generatedConfig, project, config.platform.schema, relative7(temporaryRoot, output));
10888
11571
  await execute(generatedConfig, temporaryRoot);
10889
11572
  const created = (await listSqlFiles(output)).filter((path2) => !before.has(path2));
10890
11573
  if (created.length !== 1) {
10891
11574
  throw new Error("\u5E73\u53F0 lineage handoff \u5FC5\u987B\u6070\u597D\u751F\u6210\u4E00\u4E2A migration");
10892
11575
  }
10893
- const sqlPath = join28(output, created[0]);
11576
+ const sqlPath = join29(output, created[0]);
10894
11577
  const allowed = config.modules.flatMap(({ legacyPlatformTables }) => legacyPlatformTables);
10895
11578
  validatePlatformHandoffSql(await readFile25(sqlPath, "utf8"), allowed);
10896
11579
  await writeFile14(sqlPath, metadataOnlySql("platform"));
@@ -10898,7 +11581,7 @@ async function stagePlatformLineage(project, temporaryRoot, config, execute) {
10898
11581
  }
10899
11582
  async function installStagedLineages(project, temporaryRoot, config, stagedModules, stagedPlatform) {
10900
11583
  const platform = resolveProjectPath(project, config.platform.out);
10901
- const backup = join28(temporaryRoot, "platform-backup");
11584
+ const backup = join29(temporaryRoot, "platform-backup");
10902
11585
  const installed = [];
10903
11586
  await rename2(platform, backup);
10904
11587
  try {
@@ -10908,7 +11591,7 @@ async function installStagedLineages(project, temporaryRoot, config, stagedModul
10908
11591
  if (await exists(output)) {
10909
11592
  throw new Error(`${module2.key} lineage \u8F93\u51FA\u5DF2\u5B58\u5728\uFF0C\u7981\u6B62\u8986\u76D6`);
10910
11593
  }
10911
- await mkdir9(dirname9(output), { recursive: true });
11594
+ await mkdir9(dirname11(output), { recursive: true });
10912
11595
  await rename2(stagedModules[index], output);
10913
11596
  installed.push(output);
10914
11597
  }
@@ -10945,9 +11628,9 @@ async function validateSchemaSources(project, config) {
10945
11628
  }
10946
11629
  }
10947
11630
  async function createTemporaryRoot(project) {
10948
- const windy = join28(project, ".windy");
11631
+ const windy = join29(project, ".windy");
10949
11632
  await mkdir9(windy, { recursive: true });
10950
- return await mkdtemp4(join28(windy, "module-schema-handoff-"));
11633
+ return await mkdtemp4(join29(windy, "module-schema-handoff-"));
10951
11634
  }
10952
11635
  async function listSqlFiles(root) {
10953
11636
  return (await readdir9(root)).filter((path2) => path2.endsWith(".sql")).sort();