codexgpt 1.0.0

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 (654) hide show
  1. package/AGENTS.example.md +20 -0
  2. package/CHANGELOG.md +342 -0
  3. package/CHATGPT_PROMPT.md +12 -0
  4. package/CLOUDFLARED_VERIFIED_INSTALL.md +94 -0
  5. package/CODEX_PROMPT.md +12 -0
  6. package/CONTRIBUTING.md +62 -0
  7. package/DOMAIN_SETUP.md +275 -0
  8. package/FAQ.md +366 -0
  9. package/FAQ_ZH.md +329 -0
  10. package/LICENSE +21 -0
  11. package/PUBLIC_LAUNCH_CHECKLIST.md +111 -0
  12. package/README.md +490 -0
  13. package/README_ZH.md +747 -0
  14. package/SECURITY.md +295 -0
  15. package/config.example.env +103 -0
  16. package/dist/access/fullAccessLease.js +148 -0
  17. package/dist/access/fullAccessLease.js.map +1 -0
  18. package/dist/access/protectedRoots.js +122 -0
  19. package/dist/access/protectedRoots.js.map +1 -0
  20. package/dist/access/rootAdmission.js +347 -0
  21. package/dist/access/rootAdmission.js.map +1 -0
  22. package/dist/analysis/cache.js +27 -0
  23. package/dist/analysis/cache.js.map +1 -0
  24. package/dist/analysis/classify.js +102 -0
  25. package/dist/analysis/classify.js.map +1 -0
  26. package/dist/analysis/extract.js +139 -0
  27. package/dist/analysis/extract.js.map +1 -0
  28. package/dist/analysis/graph.js +22 -0
  29. package/dist/analysis/graph.js.map +1 -0
  30. package/dist/analysis/impact.js +167 -0
  31. package/dist/analysis/impact.js.map +1 -0
  32. package/dist/analysis/index.js +215 -0
  33. package/dist/analysis/index.js.map +1 -0
  34. package/dist/analysis/inventory.js +51 -0
  35. package/dist/analysis/inventory.js.map +1 -0
  36. package/dist/analysis/providers.js +24 -0
  37. package/dist/analysis/providers.js.map +1 -0
  38. package/dist/analysis/rank.js +27 -0
  39. package/dist/analysis/rank.js.map +1 -0
  40. package/dist/analysis/types.js +8 -0
  41. package/dist/analysis/types.js.map +1 -0
  42. package/dist/audit/canonicalJson.js +79 -0
  43. package/dist/audit/canonicalJson.js.map +1 -0
  44. package/dist/audit/diagnostics.js +128 -0
  45. package/dist/audit/diagnostics.js.map +1 -0
  46. package/dist/audit/index.js +12 -0
  47. package/dist/audit/index.js.map +1 -0
  48. package/dist/audit/lifecycleV3.js +53 -0
  49. package/dist/audit/lifecycleV3.js.map +1 -0
  50. package/dist/audit/lifecycleV4.js +70 -0
  51. package/dist/audit/lifecycleV4.js.map +1 -0
  52. package/dist/audit/lock.js +195 -0
  53. package/dist/audit/lock.js.map +1 -0
  54. package/dist/audit/queryTool.js +120 -0
  55. package/dist/audit/queryTool.js.map +1 -0
  56. package/dist/audit/runtime.js +48 -0
  57. package/dist/audit/runtime.js.map +1 -0
  58. package/dist/audit/schemas.js +640 -0
  59. package/dist/audit/schemas.js.map +1 -0
  60. package/dist/audit/store.js +1309 -0
  61. package/dist/audit/store.js.map +1 -0
  62. package/dist/audit/transactionParticipant.js +45 -0
  63. package/dist/audit/transactionParticipant.js.map +1 -0
  64. package/dist/audit/types.js +11 -0
  65. package/dist/audit/types.js.map +1 -0
  66. package/dist/auth/audit.js +44 -0
  67. package/dist/auth/audit.js.map +1 -0
  68. package/dist/auth/authorizationStore.js +333 -0
  69. package/dist/auth/authorizationStore.js.map +1 -0
  70. package/dist/auth/challenges.js +25 -0
  71. package/dist/auth/challenges.js.map +1 -0
  72. package/dist/auth/clientStore.js +469 -0
  73. package/dist/auth/clientStore.js.map +1 -0
  74. package/dist/auth/cloudflareConfig.js +112 -0
  75. package/dist/auth/cloudflareConfig.js.map +1 -0
  76. package/dist/auth/configuration.js +167 -0
  77. package/dist/auth/configuration.js.map +1 -0
  78. package/dist/auth/credentialStore.js +65 -0
  79. package/dist/auth/credentialStore.js.map +1 -0
  80. package/dist/auth/deploymentLock.js +220 -0
  81. package/dist/auth/deploymentLock.js.map +1 -0
  82. package/dist/auth/deploymentRegistry.js +149 -0
  83. package/dist/auth/deploymentRegistry.js.map +1 -0
  84. package/dist/auth/errors.js +26 -0
  85. package/dist/auth/errors.js.map +1 -0
  86. package/dist/auth/grantStore.js +307 -0
  87. package/dist/auth/grantStore.js.map +1 -0
  88. package/dist/auth/index.js +39 -0
  89. package/dist/auth/index.js.map +1 -0
  90. package/dist/auth/keyManager.js +148 -0
  91. package/dist/auth/keyManager.js.map +1 -0
  92. package/dist/auth/localAdminSession.js +173 -0
  93. package/dist/auth/localAdminSession.js.map +1 -0
  94. package/dist/auth/metadata.js +69 -0
  95. package/dist/auth/metadata.js.map +1 -0
  96. package/dist/auth/oauthProvider.js +589 -0
  97. package/dist/auth/oauthProvider.js.map +1 -0
  98. package/dist/auth/ownerApproval.js +51 -0
  99. package/dist/auth/ownerApproval.js.map +1 -0
  100. package/dist/auth/policyIdentity.js +189 -0
  101. package/dist/auth/policyIdentity.js.map +1 -0
  102. package/dist/auth/rateLimits.js +66 -0
  103. package/dist/auth/rateLimits.js.map +1 -0
  104. package/dist/auth/recovery.js +275 -0
  105. package/dist/auth/recovery.js.map +1 -0
  106. package/dist/auth/requestContext.js +34 -0
  107. package/dist/auth/requestContext.js.map +1 -0
  108. package/dist/auth/resourceMiddleware.js +147 -0
  109. package/dist/auth/resourceMiddleware.js.map +1 -0
  110. package/dist/auth/runtimeStatus.js +51 -0
  111. package/dist/auth/runtimeStatus.js.map +1 -0
  112. package/dist/auth/schemas.js +84 -0
  113. package/dist/auth/schemas.js.map +1 -0
  114. package/dist/auth/stateStore.js +468 -0
  115. package/dist/auth/stateStore.js.map +1 -0
  116. package/dist/auth/tokenService.js +631 -0
  117. package/dist/auth/tokenService.js.map +1 -0
  118. package/dist/auth/toolSecurity.js +108 -0
  119. package/dist/auth/toolSecurity.js.map +1 -0
  120. package/dist/auth/types.js +6 -0
  121. package/dist/auth/types.js.map +1 -0
  122. package/dist/auth/windowsDpapi.js +193 -0
  123. package/dist/auth/windowsDpapi.js.map +1 -0
  124. package/dist/bashOps.js +292 -0
  125. package/dist/bashOps.js.map +1 -0
  126. package/dist/capabilitiesOps.js +412 -0
  127. package/dist/capabilitiesOps.js.map +1 -0
  128. package/dist/changesets/crypto.js +92 -0
  129. package/dist/changesets/crypto.js.map +1 -0
  130. package/dist/changesets/index.js +9 -0
  131. package/dist/changesets/index.js.map +1 -0
  132. package/dist/changesets/moveStore.js +237 -0
  133. package/dist/changesets/moveStore.js.map +1 -0
  134. package/dist/changesets/moveUndo.js +386 -0
  135. package/dist/changesets/moveUndo.js.map +1 -0
  136. package/dist/changesets/schemas.js +234 -0
  137. package/dist/changesets/schemas.js.map +1 -0
  138. package/dist/changesets/store.js +573 -0
  139. package/dist/changesets/store.js.map +1 -0
  140. package/dist/changesets/types.js +9 -0
  141. package/dist/changesets/types.js.map +1 -0
  142. package/dist/changesets/undo.js +525 -0
  143. package/dist/changesets/undo.js.map +1 -0
  144. package/dist/changesets/unifiedUndo.js +31 -0
  145. package/dist/changesets/unifiedUndo.js.map +1 -0
  146. package/dist/cliEnvironment.js +85 -0
  147. package/dist/cliEnvironment.js.map +1 -0
  148. package/dist/codexSessions.js +733 -0
  149. package/dist/codexSessions.js.map +1 -0
  150. package/dist/codexgptSupertool.js +216 -0
  151. package/dist/codexgptSupertool.js.map +1 -0
  152. package/dist/codexproSupertool.js +204 -0
  153. package/dist/codexproSupertool.js.map +1 -0
  154. package/dist/config.js +733 -0
  155. package/dist/config.js.map +1 -0
  156. package/dist/control/localApprovalClient.js +287 -0
  157. package/dist/control/localApprovalClient.js.map +1 -0
  158. package/dist/control/localApprovalServer.js +466 -0
  159. package/dist/control/localApprovalServer.js.map +1 -0
  160. package/dist/control/runtime.js +178 -0
  161. package/dist/control/runtime.js.map +1 -0
  162. package/dist/control/schemas.js +184 -0
  163. package/dist/control/schemas.js.map +1 -0
  164. package/dist/control/windowsLocalControl.js +348 -0
  165. package/dist/control/windowsLocalControl.js.map +1 -0
  166. package/dist/fsOps.js +541 -0
  167. package/dist/fsOps.js.map +1 -0
  168. package/dist/git/admission.js +26 -0
  169. package/dist/git/admission.js.map +1 -0
  170. package/dist/git/branchService.js +51 -0
  171. package/dist/git/branchService.js.map +1 -0
  172. package/dist/git/capabilities.js +143 -0
  173. package/dist/git/capabilities.js.map +1 -0
  174. package/dist/git/commitService.js +344 -0
  175. package/dist/git/commitService.js.map +1 -0
  176. package/dist/git/durableState.js +151 -0
  177. package/dist/git/durableState.js.map +1 -0
  178. package/dist/git/execution.js +451 -0
  179. package/dist/git/execution.js.map +1 -0
  180. package/dist/git/fileTransaction.js +50 -0
  181. package/dist/git/fileTransaction.js.map +1 -0
  182. package/dist/git/indexService.js +421 -0
  183. package/dist/git/indexService.js.map +1 -0
  184. package/dist/git/integrations.js +653 -0
  185. package/dist/git/integrations.js.map +1 -0
  186. package/dist/git/locks.js +287 -0
  187. package/dist/git/locks.js.map +1 -0
  188. package/dist/git/mutationContext.js +92 -0
  189. package/dist/git/mutationContext.js.map +1 -0
  190. package/dist/git/mutationJournal.js +91 -0
  191. package/dist/git/mutationJournal.js.map +1 -0
  192. package/dist/git/mutationService.js +352 -0
  193. package/dist/git/mutationService.js.map +1 -0
  194. package/dist/git/normalization.js +57 -0
  195. package/dist/git/normalization.js.map +1 -0
  196. package/dist/git/objectQuarantine.js +243 -0
  197. package/dist/git/objectQuarantine.js.map +1 -0
  198. package/dist/git/opaqueRecordStore.js +187 -0
  199. package/dist/git/opaqueRecordStore.js.map +1 -0
  200. package/dist/git/operationStore.js +287 -0
  201. package/dist/git/operationStore.js.map +1 -0
  202. package/dist/git/parsers.js +311 -0
  203. package/dist/git/parsers.js.map +1 -0
  204. package/dist/git/privateIndex.js +79 -0
  205. package/dist/git/privateIndex.js.map +1 -0
  206. package/dist/git/productionBootstrap.js +39 -0
  207. package/dist/git/productionBootstrap.js.map +1 -0
  208. package/dist/git/readService.js +846 -0
  209. package/dist/git/readService.js.map +1 -0
  210. package/dist/git/recovery.js +417 -0
  211. package/dist/git/recovery.js.map +1 -0
  212. package/dist/git/repositoryIdentity.js +611 -0
  213. package/dist/git/repositoryIdentity.js.map +1 -0
  214. package/dist/git/repositoryStore.js +237 -0
  215. package/dist/git/repositoryStore.js.map +1 -0
  216. package/dist/git/resources.js +113 -0
  217. package/dist/git/resources.js.map +1 -0
  218. package/dist/git/restoreService.js +178 -0
  219. package/dist/git/restoreService.js.map +1 -0
  220. package/dist/git/reviewToken.js +86 -0
  221. package/dist/git/reviewToken.js.map +1 -0
  222. package/dist/git/stashService.js +566 -0
  223. package/dist/git/stashService.js.map +1 -0
  224. package/dist/git/stateToken.js +139 -0
  225. package/dist/git/stateToken.js.map +1 -0
  226. package/dist/gitOps.js +147 -0
  227. package/dist/gitOps.js.map +1 -0
  228. package/dist/guard.js +608 -0
  229. package/dist/guard.js.map +1 -0
  230. package/dist/guidance/diagnostics.js +14 -0
  231. package/dist/guidance/diagnostics.js.map +1 -0
  232. package/dist/guidance/instructions.js +167 -0
  233. package/dist/guidance/instructions.js.map +1 -0
  234. package/dist/guidance/mode.js +18 -0
  235. package/dist/guidance/mode.js.map +1 -0
  236. package/dist/guidance/openaiSkillMetadata.js +29 -0
  237. package/dist/guidance/openaiSkillMetadata.js.map +1 -0
  238. package/dist/guidance/safeTextReader.js +171 -0
  239. package/dist/guidance/safeTextReader.js.map +1 -0
  240. package/dist/guidance/skillCatalog.js +70 -0
  241. package/dist/guidance/skillCatalog.js.map +1 -0
  242. package/dist/guidance/skillDiscovery.js +353 -0
  243. package/dist/guidance/skillDiscovery.js.map +1 -0
  244. package/dist/guidance/skillMetadata.js +115 -0
  245. package/dist/guidance/skillMetadata.js.map +1 -0
  246. package/dist/guidance/skillResources.js +146 -0
  247. package/dist/guidance/skillResources.js.map +1 -0
  248. package/dist/handoffOps.js +449 -0
  249. package/dist/handoffOps.js.map +1 -0
  250. package/dist/http/localAdminApp.js +203 -0
  251. package/dist/http/localAdminApp.js.map +1 -0
  252. package/dist/http/oauthMcpRuntime.js +294 -0
  253. package/dist/http/oauthMcpRuntime.js.map +1 -0
  254. package/dist/http/publicApp.js +350 -0
  255. package/dist/http/publicApp.js.map +1 -0
  256. package/dist/http/securityHeaders.js +11 -0
  257. package/dist/http/securityHeaders.js.map +1 -0
  258. package/dist/http.js +2076 -0
  259. package/dist/http.js.map +1 -0
  260. package/dist/moves/engine.js +1079 -0
  261. package/dist/moves/engine.js.map +1 -0
  262. package/dist/moves/index.js +6 -0
  263. package/dist/moves/index.js.map +1 -0
  264. package/dist/moves/planner.js +270 -0
  265. package/dist/moves/planner.js.map +1 -0
  266. package/dist/moves/recovery.js +557 -0
  267. package/dist/moves/recovery.js.map +1 -0
  268. package/dist/moves/service.js +300 -0
  269. package/dist/moves/service.js.map +1 -0
  270. package/dist/moves/types.js +11 -0
  271. package/dist/moves/types.js.map +1 -0
  272. package/dist/mutations/index.js +4 -0
  273. package/dist/mutations/index.js.map +1 -0
  274. package/dist/mutations/lifecycle.js +165 -0
  275. package/dist/mutations/lifecycle.js.map +1 -0
  276. package/dist/mutations/localService.js +163 -0
  277. package/dist/mutations/localService.js.map +1 -0
  278. package/dist/mutations/runtime.js +322 -0
  279. package/dist/mutations/runtime.js.map +1 -0
  280. package/dist/mutations/types.js +2 -0
  281. package/dist/mutations/types.js.map +1 -0
  282. package/dist/mutations/writers.js +360 -0
  283. package/dist/mutations/writers.js.map +1 -0
  284. package/dist/patchOps.js +420 -0
  285. package/dist/patchOps.js.map +1 -0
  286. package/dist/policy/approval.js +306 -0
  287. package/dist/policy/approval.js.map +1 -0
  288. package/dist/policy/audit.js +88 -0
  289. package/dist/policy/audit.js.map +1 -0
  290. package/dist/policy/authorizationFacts.js +187 -0
  291. package/dist/policy/authorizationFacts.js.map +1 -0
  292. package/dist/policy/compat.js +104 -0
  293. package/dist/policy/compat.js.map +1 -0
  294. package/dist/policy/context.js +31 -0
  295. package/dist/policy/context.js.map +1 -0
  296. package/dist/policy/enforcement.js +46 -0
  297. package/dist/policy/enforcement.js.map +1 -0
  298. package/dist/policy/evaluator.js +338 -0
  299. package/dist/policy/evaluator.js.map +1 -0
  300. package/dist/policy/executionCapabilities.js +80 -0
  301. package/dist/policy/executionCapabilities.js.map +1 -0
  302. package/dist/policy/executionResources.js +192 -0
  303. package/dist/policy/executionResources.js.map +1 -0
  304. package/dist/policy/fullAccessResources.js +23 -0
  305. package/dist/policy/fullAccessResources.js.map +1 -0
  306. package/dist/policy/hardPolicy.js +50 -0
  307. package/dist/policy/hardPolicy.js.map +1 -0
  308. package/dist/policy/identity.js +142 -0
  309. package/dist/policy/identity.js.map +1 -0
  310. package/dist/policy/integration.js +331 -0
  311. package/dist/policy/integration.js.map +1 -0
  312. package/dist/policy/pendingApprovals.js +301 -0
  313. package/dist/policy/pendingApprovals.js.map +1 -0
  314. package/dist/policy/profileStore.js +367 -0
  315. package/dist/policy/profileStore.js.map +1 -0
  316. package/dist/policy/resources.js +249 -0
  317. package/dist/policy/resources.js.map +1 -0
  318. package/dist/policy/runtime.js +713 -0
  319. package/dist/policy/runtime.js.map +1 -0
  320. package/dist/policy/schemas.js +625 -0
  321. package/dist/policy/schemas.js.map +1 -0
  322. package/dist/policy/toolPolicy.js +141 -0
  323. package/dist/policy/toolPolicy.js.map +1 -0
  324. package/dist/policy/transport.js +10 -0
  325. package/dist/policy/transport.js.map +1 -0
  326. package/dist/policy/types.js +31 -0
  327. package/dist/policy/types.js.map +1 -0
  328. package/dist/proContext.js +675 -0
  329. package/dist/proContext.js.map +1 -0
  330. package/dist/process/authority.js +18 -0
  331. package/dist/process/authority.js.map +1 -0
  332. package/dist/process/backendDiscovery.js +83 -0
  333. package/dist/process/backendDiscovery.js.map +1 -0
  334. package/dist/process/commandCompiler.js +71 -0
  335. package/dist/process/commandCompiler.js.map +1 -0
  336. package/dist/process/outputCursor.js +67 -0
  337. package/dist/process/outputCursor.js.map +1 -0
  338. package/dist/process/outputQuota.js +94 -0
  339. package/dist/process/outputQuota.js.map +1 -0
  340. package/dist/process/outputRing.js +138 -0
  341. package/dist/process/outputRing.js.map +1 -0
  342. package/dist/process/processAuditCoordinator.js +52 -0
  343. package/dist/process/processAuditCoordinator.js.map +1 -0
  344. package/dist/process/processManager.js +311 -0
  345. package/dist/process/processManager.js.map +1 -0
  346. package/dist/process/runCommand.js +332 -0
  347. package/dist/process/runCommand.js.map +1 -0
  348. package/dist/process/streamingRedactor.js +105 -0
  349. package/dist/process/streamingRedactor.js.map +1 -0
  350. package/dist/process/types.js +2 -0
  351. package/dist/process/types.js.map +1 -0
  352. package/dist/process/windowsHostClient.js +604 -0
  353. package/dist/process/windowsHostClient.js.map +1 -0
  354. package/dist/process/windowsHostProtocol.js +270 -0
  355. package/dist/process/windowsHostProtocol.js.map +1 -0
  356. package/dist/process/windowsPersistentBackend.js +263 -0
  357. package/dist/process/windowsPersistentBackend.js.map +1 -0
  358. package/dist/productionRuntime.js +907 -0
  359. package/dist/productionRuntime.js.map +1 -0
  360. package/dist/profileStore.js +231 -0
  361. package/dist/profileStore.js.map +1 -0
  362. package/dist/redact.js +124 -0
  363. package/dist/redact.js.map +1 -0
  364. package/dist/searchOps.js +186 -0
  365. package/dist/searchOps.js.map +1 -0
  366. package/dist/selfTestOps.js +786 -0
  367. package/dist/selfTestOps.js.map +1 -0
  368. package/dist/semantic/budgets.js +12 -0
  369. package/dist/semantic/budgets.js.map +1 -0
  370. package/dist/semantic/builtin/typescriptAssets.js +68 -0
  371. package/dist/semantic/builtin/typescriptAssets.js.map +1 -0
  372. package/dist/semantic/builtin/typescriptProvider.js +211 -0
  373. package/dist/semantic/builtin/typescriptProvider.js.map +1 -0
  374. package/dist/semantic/builtin/typescriptWorker.js +365 -0
  375. package/dist/semantic/builtin/typescriptWorker.js.map +1 -0
  376. package/dist/semantic/diffPreview.js +36 -0
  377. package/dist/semantic/diffPreview.js.map +1 -0
  378. package/dist/semantic/index.js +11 -0
  379. package/dist/semantic/index.js.map +1 -0
  380. package/dist/semantic/manager.js +522 -0
  381. package/dist/semantic/manager.js.map +1 -0
  382. package/dist/semantic/positions.js +86 -0
  383. package/dist/semantic/positions.js.map +1 -0
  384. package/dist/semantic/previewStore.js +276 -0
  385. package/dist/semantic/previewStore.js.map +1 -0
  386. package/dist/semantic/projectResolver.js +309 -0
  387. package/dist/semantic/projectResolver.js.map +1 -0
  388. package/dist/semantic/sourceSnapshot.js +54 -0
  389. package/dist/semantic/sourceSnapshot.js.map +1 -0
  390. package/dist/semantic/status.js +46 -0
  391. package/dist/semantic/status.js.map +1 -0
  392. package/dist/semantic/types.js +2 -0
  393. package/dist/semantic/types.js.map +1 -0
  394. package/dist/server.js +8676 -0
  395. package/dist/server.js.map +1 -0
  396. package/dist/stdio.js +64 -0
  397. package/dist/stdio.js.map +1 -0
  398. package/dist/toolCardWidget.js +2000 -0
  399. package/dist/toolCardWidget.js.map +1 -0
  400. package/dist/tools/contracts/catalog.js +111 -0
  401. package/dist/tools/contracts/catalog.js.map +1 -0
  402. package/dist/tools/contracts/index.js +8 -0
  403. package/dist/tools/contracts/index.js.map +1 -0
  404. package/dist/tools/contracts/registration.js +27 -0
  405. package/dist/tools/contracts/registration.js.map +1 -0
  406. package/dist/tools/contracts/schemas.js +11 -0
  407. package/dist/tools/contracts/schemas.js.map +1 -0
  408. package/dist/tools/contracts/types.js +2 -0
  409. package/dist/tools/contracts/types.js.map +1 -0
  410. package/dist/tools/contracts/v3.js +76 -0
  411. package/dist/tools/contracts/v3.js.map +1 -0
  412. package/dist/tools/contracts/v4.js +39 -0
  413. package/dist/tools/contracts/v4.js.map +1 -0
  414. package/dist/tools/contracts/v5.js +20 -0
  415. package/dist/tools/contracts/v5.js.map +1 -0
  416. package/dist/tools/phase3dServer.js +350 -0
  417. package/dist/tools/phase3dServer.js.map +1 -0
  418. package/dist/tools/schemas/applyPatch.js +388 -0
  419. package/dist/tools/schemas/applyPatch.js.map +1 -0
  420. package/dist/tools/schemas/bash.js +202 -0
  421. package/dist/tools/schemas/bash.js.map +1 -0
  422. package/dist/tools/schemas/closeWorkspace.js +105 -0
  423. package/dist/tools/schemas/closeWorkspace.js.map +1 -0
  424. package/dist/tools/schemas/codexContext.js +402 -0
  425. package/dist/tools/schemas/codexContext.js.map +1 -0
  426. package/dist/tools/schemas/codexSessions.js +328 -0
  427. package/dist/tools/schemas/codexSessions.js.map +1 -0
  428. package/dist/tools/schemas/codexgpt.js +1068 -0
  429. package/dist/tools/schemas/codexgpt.js.map +1 -0
  430. package/dist/tools/schemas/codexgptInventory.js +359 -0
  431. package/dist/tools/schemas/codexgptInventory.js.map +1 -0
  432. package/dist/tools/schemas/codexgptSelfTest.js +563 -0
  433. package/dist/tools/schemas/codexgptSelfTest.js.map +1 -0
  434. package/dist/tools/schemas/codexpro.js +917 -0
  435. package/dist/tools/schemas/codexpro.js.map +1 -0
  436. package/dist/tools/schemas/codexproInventory.js +352 -0
  437. package/dist/tools/schemas/codexproInventory.js.map +1 -0
  438. package/dist/tools/schemas/codexproSelfTest.js +546 -0
  439. package/dist/tools/schemas/codexproSelfTest.js.map +1 -0
  440. package/dist/tools/schemas/common.js +21 -0
  441. package/dist/tools/schemas/common.js.map +1 -0
  442. package/dist/tools/schemas/createTaskWorktree.js +51 -0
  443. package/dist/tools/schemas/createTaskWorktree.js.map +1 -0
  444. package/dist/tools/schemas/edit.js +321 -0
  445. package/dist/tools/schemas/edit.js.map +1 -0
  446. package/dist/tools/schemas/execution.js +330 -0
  447. package/dist/tools/schemas/execution.js.map +1 -0
  448. package/dist/tools/schemas/exportProContext.js +370 -0
  449. package/dist/tools/schemas/exportProContext.js.map +1 -0
  450. package/dist/tools/schemas/getTaskWorktree.js +19 -0
  451. package/dist/tools/schemas/getTaskWorktree.js.map +1 -0
  452. package/dist/tools/schemas/gitBranch.js +42 -0
  453. package/dist/tools/schemas/gitBranch.js.map +1 -0
  454. package/dist/tools/schemas/gitCommit.js +40 -0
  455. package/dist/tools/schemas/gitCommit.js.map +1 -0
  456. package/dist/tools/schemas/gitCreateBranch.js +22 -0
  457. package/dist/tools/schemas/gitCreateBranch.js.map +1 -0
  458. package/dist/tools/schemas/gitDiff.js +222 -0
  459. package/dist/tools/schemas/gitDiff.js.map +1 -0
  460. package/dist/tools/schemas/gitLog.js +41 -0
  461. package/dist/tools/schemas/gitLog.js.map +1 -0
  462. package/dist/tools/schemas/gitRestore.js +47 -0
  463. package/dist/tools/schemas/gitRestore.js.map +1 -0
  464. package/dist/tools/schemas/gitStage.js +33 -0
  465. package/dist/tools/schemas/gitStage.js.map +1 -0
  466. package/dist/tools/schemas/gitStash.js +102 -0
  467. package/dist/tools/schemas/gitStash.js.map +1 -0
  468. package/dist/tools/schemas/gitStatus.js +226 -0
  469. package/dist/tools/schemas/gitStatus.js.map +1 -0
  470. package/dist/tools/schemas/gitV4Common.js +205 -0
  471. package/dist/tools/schemas/gitV4Common.js.map +1 -0
  472. package/dist/tools/schemas/guidance.js +40 -0
  473. package/dist/tools/schemas/guidance.js.map +1 -0
  474. package/dist/tools/schemas/handoffToAgent.js +276 -0
  475. package/dist/tools/schemas/handoffToAgent.js.map +1 -0
  476. package/dist/tools/schemas/handoffToCodex.js +137 -0
  477. package/dist/tools/schemas/handoffToCodex.js.map +1 -0
  478. package/dist/tools/schemas/inspectWorkspace.js +379 -0
  479. package/dist/tools/schemas/inspectWorkspace.js.map +1 -0
  480. package/dist/tools/schemas/listTaskWorktrees.js +21 -0
  481. package/dist/tools/schemas/listTaskWorktrees.js.map +1 -0
  482. package/dist/tools/schemas/listWorkspaces.js +134 -0
  483. package/dist/tools/schemas/listWorkspaces.js.map +1 -0
  484. package/dist/tools/schemas/loadSkill.js +619 -0
  485. package/dist/tools/schemas/loadSkill.js.map +1 -0
  486. package/dist/tools/schemas/mergeTaskWorktree.js +105 -0
  487. package/dist/tools/schemas/mergeTaskWorktree.js.map +1 -0
  488. package/dist/tools/schemas/movePaths.js +175 -0
  489. package/dist/tools/schemas/movePaths.js.map +1 -0
  490. package/dist/tools/schemas/openCurrentWorkspace.js +174 -0
  491. package/dist/tools/schemas/openCurrentWorkspace.js.map +1 -0
  492. package/dist/tools/schemas/openFullAccessWorkspace.js +81 -0
  493. package/dist/tools/schemas/openFullAccessWorkspace.js.map +1 -0
  494. package/dist/tools/schemas/openWorkspace.js +193 -0
  495. package/dist/tools/schemas/openWorkspace.js.map +1 -0
  496. package/dist/tools/schemas/queryAuditEvents.js +193 -0
  497. package/dist/tools/schemas/queryAuditEvents.js.map +1 -0
  498. package/dist/tools/schemas/read.js +199 -0
  499. package/dist/tools/schemas/read.js.map +1 -0
  500. package/dist/tools/schemas/readCodexSession.js +353 -0
  501. package/dist/tools/schemas/readCodexSession.js.map +1 -0
  502. package/dist/tools/schemas/readHandoff.js +446 -0
  503. package/dist/tools/schemas/readHandoff.js.map +1 -0
  504. package/dist/tools/schemas/removeTaskWorktree.js +40 -0
  505. package/dist/tools/schemas/removeTaskWorktree.js.map +1 -0
  506. package/dist/tools/schemas/search.js +235 -0
  507. package/dist/tools/schemas/search.js.map +1 -0
  508. package/dist/tools/schemas/semantic.js +195 -0
  509. package/dist/tools/schemas/semantic.js.map +1 -0
  510. package/dist/tools/schemas/serverConfig.js +157 -0
  511. package/dist/tools/schemas/serverConfig.js.map +1 -0
  512. package/dist/tools/schemas/showChanges.js +283 -0
  513. package/dist/tools/schemas/showChanges.js.map +1 -0
  514. package/dist/tools/schemas/transactionResult.js +11 -0
  515. package/dist/tools/schemas/transactionResult.js.map +1 -0
  516. package/dist/tools/schemas/tree.js +136 -0
  517. package/dist/tools/schemas/tree.js.map +1 -0
  518. package/dist/tools/schemas/undoChangeSet.js +152 -0
  519. package/dist/tools/schemas/undoChangeSet.js.map +1 -0
  520. package/dist/tools/schemas/waitForHandoff.js +462 -0
  521. package/dist/tools/schemas/waitForHandoff.js.map +1 -0
  522. package/dist/tools/schemas/workspaceSnapshot.js +145 -0
  523. package/dist/tools/schemas/workspaceSnapshot.js.map +1 -0
  524. package/dist/tools/schemas/write.js +285 -0
  525. package/dist/tools/schemas/write.js.map +1 -0
  526. package/dist/transactions/atomicFs.js +438 -0
  527. package/dist/transactions/atomicFs.js.map +1 -0
  528. package/dist/transactions/atomicStateFile.js +190 -0
  529. package/dist/transactions/atomicStateFile.js.map +1 -0
  530. package/dist/transactions/engine.js +574 -0
  531. package/dist/transactions/engine.js.map +1 -0
  532. package/dist/transactions/index.js +12 -0
  533. package/dist/transactions/index.js.map +1 -0
  534. package/dist/transactions/installation.js +158 -0
  535. package/dist/transactions/installation.js.map +1 -0
  536. package/dist/transactions/manifestV2Store.js +96 -0
  537. package/dist/transactions/manifestV2Store.js.map +1 -0
  538. package/dist/transactions/participantRecovery.js +98 -0
  539. package/dist/transactions/participantRecovery.js.map +1 -0
  540. package/dist/transactions/recovery.js +513 -0
  541. package/dist/transactions/recovery.js.map +1 -0
  542. package/dist/transactions/schemas.js +365 -0
  543. package/dist/transactions/schemas.js.map +1 -0
  544. package/dist/transactions/stateRoot.js +63 -0
  545. package/dist/transactions/stateRoot.js.map +1 -0
  546. package/dist/transactions/types.js +11 -0
  547. package/dist/transactions/types.js.map +1 -0
  548. package/dist/transactions/workspaceLock.js +201 -0
  549. package/dist/transactions/workspaceLock.js.map +1 -0
  550. package/dist/workspaceOps.js +924 -0
  551. package/dist/workspaceOps.js.map +1 -0
  552. package/dist/worktrees/candidateWorkspace.js +566 -0
  553. package/dist/worktrees/candidateWorkspace.js.map +1 -0
  554. package/dist/worktrees/manager.js +258 -0
  555. package/dist/worktrees/manager.js.map +1 -0
  556. package/dist/worktrees/materializer.js +60 -0
  557. package/dist/worktrees/materializer.js.map +1 -0
  558. package/dist/worktrees/mergeExecute.js +498 -0
  559. package/dist/worktrees/mergeExecute.js.map +1 -0
  560. package/dist/worktrees/mergePlanStore.js +247 -0
  561. package/dist/worktrees/mergePlanStore.js.map +1 -0
  562. package/dist/worktrees/mergePrepare.js +709 -0
  563. package/dist/worktrees/mergePrepare.js.map +1 -0
  564. package/dist/worktrees/recovery.js +294 -0
  565. package/dist/worktrees/recovery.js.map +1 -0
  566. package/dist/worktrees/remove.js +296 -0
  567. package/dist/worktrees/remove.js.map +1 -0
  568. package/dist/worktrees/remover.js +57 -0
  569. package/dist/worktrees/remover.js.map +1 -0
  570. package/dist/worktrees/root.js +47 -0
  571. package/dist/worktrees/root.js.map +1 -0
  572. package/dist/worktrees/service.js +245 -0
  573. package/dist/worktrees/service.js.map +1 -0
  574. package/dist/worktrees/store.js +156 -0
  575. package/dist/worktrees/store.js.map +1 -0
  576. package/dist/worktrees/treeManifest.js +106 -0
  577. package/dist/worktrees/treeManifest.js.map +1 -0
  578. package/dist/worktrees/verificationReceipts.js +215 -0
  579. package/dist/worktrees/verificationReceipts.js.map +1 -0
  580. package/dist/worktrees/verificationTerminal.js +23 -0
  581. package/dist/worktrees/verificationTerminal.js.map +1 -0
  582. package/dist/worktrees/workspaceAuthority.js +64 -0
  583. package/dist/worktrees/workspaceAuthority.js.map +1 -0
  584. package/docs/favicon.svg +5 -0
  585. package/docs/index.html +624 -0
  586. package/docs/og.svg +52 -0
  587. package/docs/script.js +33 -0
  588. package/docs/star.svg +11 -0
  589. package/docs/styles.css +1571 -0
  590. package/docs/zh.html +428 -0
  591. package/package.json +121 -0
  592. package/scripts/analysis-cli-smoke.mjs +81 -0
  593. package/scripts/analysis-smoke.mjs +179 -0
  594. package/scripts/atomic-file.mjs +137 -0
  595. package/scripts/ci-change-classifier.mjs +59 -0
  596. package/scripts/ci-failure-summary.mjs +92 -0
  597. package/scripts/cloudflared-installer.mjs +215 -0
  598. package/scripts/cloudflared-release.mjs +63 -0
  599. package/scripts/codexgpt-entry.mjs +235 -0
  600. package/scripts/codexgpt.mjs +4987 -0
  601. package/scripts/connector-auth-output-shim.cjs +66 -0
  602. package/scripts/doctor-smoke.mjs +90 -0
  603. package/scripts/doctor.mjs +165 -0
  604. package/scripts/exact-head-ci.mjs +126 -0
  605. package/scripts/execute-handoff-smoke-platform-compat.mjs +38 -0
  606. package/scripts/execute-handoff-smoke.mjs +1117 -0
  607. package/scripts/g8-u-live-probe.mjs +208 -0
  608. package/scripts/http-smoke-compat.mjs +151 -0
  609. package/scripts/http-smoke.mjs +776 -0
  610. package/scripts/long-task-runner.mjs +1037 -0
  611. package/scripts/oauth-admin.mjs +1608 -0
  612. package/scripts/output-bounds.mjs +29 -0
  613. package/scripts/owned-temp-root.d.mts +50 -0
  614. package/scripts/owned-temp-root.mjs +567 -0
  615. package/scripts/phase-4a-smoke.mjs +36 -0
  616. package/scripts/policy-windows-spike.mjs +135 -0
  617. package/scripts/pro-apply.mjs +152 -0
  618. package/scripts/pro-bundle.mjs +121 -0
  619. package/scripts/pro-smoke.mjs +97 -0
  620. package/scripts/process-identity.mjs +67 -0
  621. package/scripts/repository-policy.mjs +166 -0
  622. package/scripts/run-and-summarize.mjs +134 -0
  623. package/scripts/run-smoke.mjs +52 -0
  624. package/scripts/run-with-cleanup.mjs +98 -0
  625. package/scripts/settings-smoke-platform-compat.mjs +85 -0
  626. package/scripts/settings-smoke.mjs +769 -0
  627. package/scripts/smoke-platform-compat.mjs +302 -0
  628. package/scripts/smoke.mjs +1180 -0
  629. package/scripts/stress-contract-compat.mjs +94 -0
  630. package/scripts/stress.mjs +882 -0
  631. package/scripts/test-domains.mjs +247 -0
  632. package/scripts/test-execution-profile-manifest.mjs +273 -0
  633. package/scripts/test-execution-profiles.mjs +147 -0
  634. package/scripts/test-performance-reporter.mjs +291 -0
  635. package/scripts/toolchain-manager.mjs +266 -0
  636. package/scripts/toolchains.json +19 -0
  637. package/scripts/windows-conpty-probe-child.mjs +82 -0
  638. package/scripts/windows-conpty-worker.ps1 +24 -0
  639. package/scripts/windows-credential-host-manifest.json +16 -0
  640. package/scripts/windows-credential-host-protocol-v1.json +16 -0
  641. package/scripts/windows-credential-host.cs +256 -0
  642. package/scripts/windows-credential-host.ps1 +26 -0
  643. package/scripts/windows-local-control-manifest.json +23 -0
  644. package/scripts/windows-local-control-spike.cs +738 -0
  645. package/scripts/windows-local-control-spike.mjs +415 -0
  646. package/scripts/windows-local-control-spike.ps1 +35 -0
  647. package/scripts/windows-local-control.cs +738 -0
  648. package/scripts/windows-local-control.ps1 +35 -0
  649. package/scripts/windows-native-api-inventory-v1.json +90 -0
  650. package/scripts/windows-process-host-manifest.json +20 -0
  651. package/scripts/windows-process-host-protocol-v1.json +59 -0
  652. package/scripts/windows-process-host.cs +2385 -0
  653. package/scripts/windows-process-host.ps1 +59 -0
  654. package/scripts/windows-realpath-shim.cjs +78 -0
@@ -0,0 +1,1079 @@
1
+ import path from "node:path";
2
+ import { createHash } from "node:crypto";
3
+ import fsp from "node:fs/promises";
4
+ import { TransactionManifestV2Store } from "../transactions/manifestV2Store.js";
5
+ import { workspaceStateKeyForRoot } from "../transactions/installation.js";
6
+ import { TransactionError } from "../transactions/types.js";
7
+ import { MovePlanner } from "./planner.js";
8
+ import { MovePathsError } from "./types.js";
9
+ const TRANSIENT_WINDOWS_CODES = new Set(["EPERM", "EACCES", "EBUSY"]);
10
+ const NO_FAULTS = { hit() { } };
11
+ function identity(stat) {
12
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.dev <= 0n || stat.ino <= 0n) {
13
+ throw new TransactionError("ATOMIC_BACKEND_UNAVAILABLE", "Stable ordinary-file identity is unavailable.");
14
+ }
15
+ return { device: stat.dev.toString(), fileId: stat.ino.toString() };
16
+ }
17
+ function directoryIdentity(stat) {
18
+ if (!stat.isDirectory() || stat.isSymbolicLink() || stat.dev <= 0n || stat.ino <= 0n) {
19
+ throw new TransactionError("ATOMIC_BACKEND_UNAVAILABLE", "Stable ordinary-directory identity is unavailable.");
20
+ }
21
+ return { device: stat.dev.toString(), fileId: stat.ino.toString() };
22
+ }
23
+ function identityEquals(expected, actual) {
24
+ return expected.device === actual.device && expected.fileId === actual.fileId;
25
+ }
26
+ function contained(child, root) {
27
+ const relative = path.relative(root, child);
28
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
29
+ }
30
+ async function pathIdentity(absPath) {
31
+ try {
32
+ return identity(await fsp.lstat(absPath, { bigint: true }));
33
+ }
34
+ catch (error) {
35
+ if (error.code === "ENOENT")
36
+ return null;
37
+ throw error;
38
+ }
39
+ }
40
+ async function pathEntryExists(absPath) {
41
+ try {
42
+ await fsp.lstat(absPath);
43
+ return true;
44
+ }
45
+ catch (error) {
46
+ if (error.code === "ENOENT")
47
+ return false;
48
+ throw error;
49
+ }
50
+ }
51
+ async function handleIdentity(handle) {
52
+ return identity(await handle.stat({ bigint: true }));
53
+ }
54
+ async function hashHandle(handle, expectedBytes) {
55
+ const hash = createHash("sha256");
56
+ const buffer = Buffer.allocUnsafe(1024 * 1024);
57
+ let position = 0;
58
+ while (position < expectedBytes) {
59
+ const length = Math.min(buffer.length, expectedBytes - position);
60
+ const { bytesRead } = await handle.read(buffer, 0, length, position);
61
+ if (bytesRead <= 0) {
62
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move content changed during verification.");
63
+ }
64
+ hash.update(buffer.subarray(0, bytesRead));
65
+ position += bytesRead;
66
+ }
67
+ const extra = await handle.read(Buffer.allocUnsafe(1), 0, 1, position);
68
+ if (extra.bytesRead !== 0) {
69
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move content size changed during verification.");
70
+ }
71
+ return hash.digest("hex");
72
+ }
73
+ async function assertExpectedPath(absPath, expected) {
74
+ const actual = await pathIdentity(absPath);
75
+ if (!actual || !identityEquals(expected, actual)) {
76
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move path no longer identifies the expected file object.");
77
+ }
78
+ }
79
+ async function assertExpectedHandle(operation) {
80
+ const actual = await handleIdentity(operation.handle);
81
+ if (!identityEquals(operation.objectIdentity, actual)) {
82
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move source handle no longer identifies the expected file object.");
83
+ }
84
+ }
85
+ async function openExpectedHandle(absPath, expected) {
86
+ const handle = await fsp.open(absPath, "r");
87
+ try {
88
+ const actual = await handleIdentity(handle);
89
+ if (!identityEquals(expected, actual)) {
90
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move handoff handle identifies an unexpected file object.");
91
+ }
92
+ return handle;
93
+ }
94
+ catch (error) {
95
+ await handle.close().catch(() => undefined);
96
+ throw error;
97
+ }
98
+ }
99
+ async function assertDestinationSpelling(absPath) {
100
+ if (process.platform !== "win32")
101
+ return;
102
+ const parent = path.dirname(absPath);
103
+ const expected = path.basename(absPath);
104
+ const names = await fsp.readdir(parent);
105
+ if (!names.includes(expected)) {
106
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Windows destination entry spelling is not exact.");
107
+ }
108
+ }
109
+ async function delay(ms) {
110
+ await new Promise((resolve) => setTimeout(resolve, ms));
111
+ }
112
+ async function withTransientRetry(action, revalidate) {
113
+ let lastError;
114
+ for (let attempt = 0; attempt < 4; attempt += 1) {
115
+ try {
116
+ return await action();
117
+ }
118
+ catch (error) {
119
+ lastError = error;
120
+ const code = error.code ?? "";
121
+ if (code === "EEXIST" || !TRANSIENT_WINDOWS_CODES.has(code) || process.platform !== "win32" || attempt === 3) {
122
+ throw error;
123
+ }
124
+ await revalidate();
125
+ await delay(5 * (attempt + 1));
126
+ }
127
+ }
128
+ throw lastError;
129
+ }
130
+ function operationFromInspection(operation, stageRelativePath) {
131
+ return {
132
+ operationId: operation.operationId,
133
+ kind: "move",
134
+ state: "planned",
135
+ sourceRelativePath: operation.sourceRelativePath,
136
+ destinationRelativePath: operation.destinationRelativePath,
137
+ sourceComparisonKey: operation.sourceComparisonKey,
138
+ destinationComparisonKey: operation.destinationComparisonKey,
139
+ sourceExistingParentRelativePath: operation.sourceExistingParentRelativePath,
140
+ sourceExistingParentIdentity: operation.sourceExistingParentIdentity,
141
+ destinationExistingParentRelativePath: operation.destinationExistingParentRelativePath,
142
+ destinationExistingParentIdentity: operation.destinationExistingParentIdentity,
143
+ stageRelativePath,
144
+ objectIdentity: operation.objectIdentity,
145
+ version: operation.version
146
+ };
147
+ }
148
+ function participantFacts(names) {
149
+ return Object.fromEntries(names.map((name) => [name, "pending"]));
150
+ }
151
+ function toTransactionError(error, fallback) {
152
+ if (error instanceof TransactionError)
153
+ return error;
154
+ if (error instanceof MovePathsError) {
155
+ if (error.code === "FILE_VERSION_CONFLICT") {
156
+ return new TransactionError("FILE_VERSION_CONFLICT", error.message);
157
+ }
158
+ if (error.code === "CROSS_VOLUME_MOVE" || error.code === "ATOMIC_BACKEND_UNAVAILABLE") {
159
+ return new TransactionError("ATOMIC_BACKEND_UNAVAILABLE", error.message);
160
+ }
161
+ return new TransactionError("TRANSACTION_PRECONDITION_FAILED", error.message);
162
+ }
163
+ const code = error?.code ?? "";
164
+ if (["EXDEV", "EMLINK", "ENOSYS", "ENOTSUP", "EOPNOTSUPP"].includes(code)) {
165
+ return new TransactionError("ATOMIC_BACKEND_UNAVAILABLE", "The filesystem cannot provide the required same-volume hard-link transaction backend.");
166
+ }
167
+ return new TransactionError("TRANSACTION_FAILED", fallback);
168
+ }
169
+ export class MoveTransactionCoordinator {
170
+ guard;
171
+ stateRoot;
172
+ masterKey;
173
+ locks;
174
+ options;
175
+ planner;
176
+ store;
177
+ faults;
178
+ filesystem;
179
+ constructor(config, guard, stateRoot, masterKey, locks, options) {
180
+ this.guard = guard;
181
+ this.stateRoot = stateRoot;
182
+ this.masterKey = masterKey;
183
+ this.locks = locks;
184
+ this.options = options;
185
+ this.planner = new MovePlanner(config);
186
+ this.store = new TransactionManifestV2Store(stateRoot, masterKey);
187
+ this.faults = options.faultInjector ?? NO_FAULTS;
188
+ this.filesystem = {
189
+ mkdir: options.filesystem?.mkdir ?? fsp.mkdir,
190
+ link: options.filesystem?.link ?? fsp.link,
191
+ unlink: options.filesystem?.unlink ?? fsp.unlink,
192
+ rmdir: options.filesystem?.rmdir ?? fsp.rmdir
193
+ };
194
+ }
195
+ dispose() {
196
+ this.store.dispose();
197
+ }
198
+ opaqueId(prefix) {
199
+ const bytes = this.options.randomBytes(16);
200
+ if (!Buffer.isBuffer(bytes) || bytes.length !== 16) {
201
+ throw new TransactionError("TRANSACTION_STATE_CORRUPT", "Move transaction ID source is invalid.");
202
+ }
203
+ return `${prefix}_${bytes.toString("hex")}`;
204
+ }
205
+ artifactToken() {
206
+ const bytes = this.options.randomBytes(8);
207
+ if (!Buffer.isBuffer(bytes) || bytes.length !== 8) {
208
+ throw new TransactionError("TRANSACTION_STATE_CORRUPT", "Move artifact ID source is invalid.");
209
+ }
210
+ return bytes.toString("hex");
211
+ }
212
+ async allocateOperations(batch, operations) {
213
+ const used = new Set();
214
+ const result = [];
215
+ for (const operation of operations) {
216
+ let stageRelativePath = null;
217
+ for (let attempt = 0; attempt < 16; attempt += 1) {
218
+ const stageAbsPath = path.join(path.dirname(operation.sourceAbsPath), `.codexgpt-txn-${this.artifactToken()}.move`);
219
+ const relative = path.relative(batch.workspace.root, stageAbsPath).replaceAll("\\", "/");
220
+ if (used.has(relative) || await pathEntryExists(stageAbsPath))
221
+ continue;
222
+ used.add(relative);
223
+ stageRelativePath = relative;
224
+ break;
225
+ }
226
+ if (!stageRelativePath) {
227
+ throw new TransactionError("TRANSACTION_BUSY", "A unique move stage name could not be reserved.");
228
+ }
229
+ result.push(operationFromInspection(operation, stageRelativePath));
230
+ }
231
+ return result;
232
+ }
233
+ timestamp() {
234
+ const value = new Date(this.options.now()).toISOString();
235
+ if (value === "Invalid Date") {
236
+ throw new TransactionError("TRANSACTION_STATE_CORRUPT", "Move transaction clock is invalid.");
237
+ }
238
+ return value;
239
+ }
240
+ validateRequest(request) {
241
+ if (!request.workspace?.root || !request.workspace.id || !request.workspace.openedAt) {
242
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move workspace is invalid.");
243
+ }
244
+ if (!Array.isArray(request.requiredParticipants) || request.requiredParticipants.length > 32) {
245
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participants are invalid.");
246
+ }
247
+ if (new Set(request.requiredParticipants).size !== request.requiredParticipants.length) {
248
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participants are duplicate.");
249
+ }
250
+ const suppliedReferences = request.participantReferences ?? {};
251
+ for (const name of request.requiredParticipants) {
252
+ if (!/^[a-z][a-z0-9._-]{0,63}$/.test(name)) {
253
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participant name is invalid.");
254
+ }
255
+ const reference = suppliedReferences[name];
256
+ if (reference !== undefined && !/^[a-z0-9][a-z0-9._:-]{0,159}$/.test(reference)) {
257
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participant reference is invalid.");
258
+ }
259
+ }
260
+ if (Object.keys(suppliedReferences).some((name) => !request.requiredParticipants.includes(name))) {
261
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participant references contain an unknown participant.");
262
+ }
263
+ }
264
+ async validateDirectoryRemovalPlan(batch, requested) {
265
+ const root = batch.workspace.root;
266
+ const normalized = requested.map((value) => ({
267
+ relativePath: value.relativePath.replace(/\\/g, "/").normalize("NFC"),
268
+ objectIdentity: value.objectIdentity
269
+ }));
270
+ const relativePaths = normalized.map((value) => value.relativePath);
271
+ if (new Set(relativePaths).size !== relativePaths.length) {
272
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move directory-removal plan contains duplicates.");
273
+ }
274
+ const absoluteByRelative = new Map();
275
+ for (const fact of normalized) {
276
+ const relative = fact.relativePath;
277
+ if (!relative || path.isAbsolute(relative) || relative.includes("\0")) {
278
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move directory-removal path is invalid.");
279
+ }
280
+ const absolute = path.resolve(root, relative);
281
+ if (absolute === root || !contained(absolute, root)) {
282
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move directory-removal path escaped the workspace.");
283
+ }
284
+ let facts;
285
+ try {
286
+ facts = this.guard.resolvePolicyFacts(batch.workspace, relative, { forWrite: true });
287
+ }
288
+ catch {
289
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory no longer satisfies workspace policy.");
290
+ }
291
+ if (!facts.targetExists || path.resolve(facts.absPath) !== absolute) {
292
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory path identity changed.");
293
+ }
294
+ const stat = await fsp.lstat(absolute, { bigint: true }).catch((error) => {
295
+ if (error.code === "ENOENT") {
296
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A directory selected for undo cleanup no longer exists.");
297
+ }
298
+ throw error;
299
+ });
300
+ const actualIdentity = directoryIdentity(stat);
301
+ if (!identityEquals(fact.objectIdentity, actualIdentity)) {
302
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory object identity changed.");
303
+ }
304
+ absoluteByRelative.set(relative, absolute);
305
+ }
306
+ const plannedAbs = new Set(absoluteByRelative.values());
307
+ const sourceAbs = new Set(batch.operations.map((operation) => path.resolve(operation.sourceAbsPath)));
308
+ for (const [relative, absolute] of absoluteByRelative) {
309
+ const entries = await fsp.readdir(absolute, { withFileTypes: true });
310
+ for (const entry of entries) {
311
+ const child = path.resolve(absolute, entry.name);
312
+ if (entry.isSymbolicLink()) {
313
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory contains a symbolic link.");
314
+ }
315
+ if (entry.isDirectory()) {
316
+ if (!plannedAbs.has(child)) {
317
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory contains an unrelated directory.");
318
+ }
319
+ continue;
320
+ }
321
+ if (!entry.isFile() || !sourceAbs.has(child)) {
322
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory contains an unrelated entry.");
323
+ }
324
+ }
325
+ if (batch.createdDirectories.includes(relative)) {
326
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "A move cannot create and remove the same directory.");
327
+ }
328
+ }
329
+ return normalized.sort((left, right) => right.relativePath.split("/").length - left.relativePath.split("/").length ||
330
+ right.relativePath.localeCompare(left.relativePath));
331
+ }
332
+ async preview(workspace, moves, createParents, removeEmptyDirectoriesAfterInstall = []) {
333
+ const batch = await this.planner.inspect(workspace, moves, createParents);
334
+ try {
335
+ await this.validateDirectoryRemovalPlan(batch, removeEmptyDirectoriesAfterInstall);
336
+ return batch;
337
+ }
338
+ catch (error) {
339
+ await batch.close();
340
+ throw error;
341
+ }
342
+ }
343
+ async prepare(request) {
344
+ this.validateRequest(request);
345
+ await this.options.recoveryCoordinator?.ensureWorkspaceReady(request.workspace.root);
346
+ const workspaceStateKey = workspaceStateKeyForRoot(request.workspace.root, this.masterKey);
347
+ const transactionId = this.opaqueId("tx");
348
+ const changeSetId = this.opaqueId("cs");
349
+ const lock = this.locks.acquire({ workspaceStateKey, transactionId });
350
+ let batch;
351
+ let released = false;
352
+ try {
353
+ batch = await this.planner.inspect(request.workspace, request.moves, request.createParents);
354
+ const plannedRemovedDirectoryFacts = await this.validateDirectoryRemovalPlan(batch, request.removeEmptyDirectoriesAfterInstall ?? []);
355
+ const createdAt = this.timestamp();
356
+ const orderedInspections = [...batch.operations]
357
+ .sort((left, right) => left.sourceComparisonKey.localeCompare(right.sourceComparisonKey) ||
358
+ left.operationId.localeCompare(right.operationId));
359
+ const orderedOperations = await this.allocateOperations(batch, orderedInspections);
360
+ const suppliedReferences = request.participantReferences ?? {};
361
+ const resolvedReferences = Object.fromEntries(request.requiredParticipants.map((name) => [
362
+ name,
363
+ suppliedReferences[name] ?? `${name}:${name === "change_set" ? changeSetId : transactionId}`
364
+ ]));
365
+ const initial = {
366
+ schemaVersion: 2,
367
+ transactionId,
368
+ changeSetId,
369
+ workspaceStateKey,
370
+ generation: 1,
371
+ createdAt,
372
+ updatedAt: createdAt,
373
+ state: "preparing",
374
+ operations: orderedOperations,
375
+ plannedCreatedDirectories: [...batch.createdDirectories],
376
+ createdDirectories: [],
377
+ createdDirectoryIdentities: {},
378
+ plannedRemovedDirectories: plannedRemovedDirectoryFacts.map((fact) => fact.relativePath),
379
+ plannedRemovedDirectoryIdentities: Object.fromEntries(plannedRemovedDirectoryFacts.map((fact) => [fact.relativePath, fact.objectIdentity])),
380
+ removedDirectories: [],
381
+ requiredParticipants: [...request.requiredParticipants],
382
+ participantReferences: resolvedReferences,
383
+ participantFacts: participantFacts(request.requiredParticipants)
384
+ };
385
+ this.store.writeInitial(initial);
386
+ let manifest = this.store.read(workspaceStateKey, transactionId);
387
+ await this.faults.hit("after_manifest_preparing", { operationCount: orderedOperations.length });
388
+ manifest = this.transition(manifest, { state: "prepared" });
389
+ await this.faults.hit("after_manifest_prepared", { operationCount: orderedOperations.length });
390
+ const context = {
391
+ manifest,
392
+ batch,
393
+ lock,
394
+ released,
395
+ lifecycle: "prepared"
396
+ };
397
+ return new PreparedMoveTransactionImpl(this, context);
398
+ }
399
+ catch (error) {
400
+ await batch?.close();
401
+ if (!released) {
402
+ try {
403
+ lock.release();
404
+ released = true;
405
+ }
406
+ catch {
407
+ // Preserve lock evidence if release cannot be proven.
408
+ }
409
+ }
410
+ throw toTransactionError(error, "Move preparation failed.");
411
+ }
412
+ }
413
+ transition(previous, patch) {
414
+ const { manifestMac: _ignored, ...facts } = previous;
415
+ const next = {
416
+ ...facts,
417
+ ...patch,
418
+ generation: previous.generation + 1,
419
+ updatedAt: this.timestamp()
420
+ };
421
+ this.store.writeNext(previous, next);
422
+ return this.store.read(previous.workspaceStateKey, previous.transactionId);
423
+ }
424
+ replaceOperation(operations, replacement) {
425
+ return operations.map((operation) => operation.operationId === replacement.operationId ? replacement : operation);
426
+ }
427
+ inspected(context, operationId) {
428
+ const operation = context.batch.operations.find((value) => value.operationId === operationId);
429
+ if (!operation) {
430
+ throw new TransactionError("TRANSACTION_STATE_CORRUPT", "Move operation inspection evidence is missing.");
431
+ }
432
+ return operation;
433
+ }
434
+ stageAbs(context, operation) {
435
+ return path.resolve(context.batch.workspace.root, operation.stageRelativePath);
436
+ }
437
+ async assertDirectoryIdentity(absolute, expected) {
438
+ const actual = directoryIdentity(await fsp.lstat(absolute, { bigint: true }));
439
+ if (expected && !identityEquals(expected, actual)) {
440
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move directory object identity changed.");
441
+ }
442
+ const real = await fsp.realpath(absolute);
443
+ if (path.resolve(real) !== path.resolve(absolute)) {
444
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move directory resolves through a link or reparse point.");
445
+ }
446
+ }
447
+ policyFacts(context, relativePath) {
448
+ try {
449
+ return this.guard.resolvePolicyFacts(context.batch.workspace, relativePath, { forWrite: true });
450
+ }
451
+ catch {
452
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move path no longer satisfies workspace policy.");
453
+ }
454
+ }
455
+ async assertSourcePolicy(context, operation) {
456
+ const facts = this.policyFacts(context, operation.sourceRelativePath);
457
+ if (!facts.targetExists ||
458
+ path.resolve(facts.absPath) !== path.resolve(operation.sourceAbsPath) ||
459
+ facts.comparisonKey !== operation.sourceComparisonKey ||
460
+ path.resolve(facts.existingParent) !== path.resolve(operation.sourceExistingParent) ||
461
+ facts.existingParentIdentity !== operation.sourceExistingParentIdentity) {
462
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move source path or parent identity changed.");
463
+ }
464
+ await this.assertDirectoryIdentity(operation.sourceExistingParent);
465
+ }
466
+ async assertCreationPathReady(context, relativePath) {
467
+ const absolute = path.resolve(context.batch.workspace.root, relativePath);
468
+ const facts = this.policyFacts(context, relativePath);
469
+ const parent = path.dirname(absolute);
470
+ if (facts.targetExists ||
471
+ path.resolve(facts.absPath) !== absolute ||
472
+ path.resolve(facts.existingParent) !== parent) {
473
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move-created directory path or parent identity changed.");
474
+ }
475
+ const parentRelative = path.relative(context.batch.workspace.root, parent).replaceAll("\\", "/") || ".";
476
+ const expectedIdentity = context.manifest.createdDirectoryIdentities[parentRelative];
477
+ if (expectedIdentity) {
478
+ await this.assertDirectoryIdentity(parent, expectedIdentity);
479
+ return;
480
+ }
481
+ const original = context.batch.operations.find((operation) => path.resolve(operation.destinationExistingParent) === parent);
482
+ if (!original || facts.existingParentIdentity !== original.destinationExistingParentIdentity) {
483
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move-created directory existing parent changed.");
484
+ }
485
+ await this.assertDirectoryIdentity(parent);
486
+ }
487
+ async assertDestinationAbsent(context, operation) {
488
+ const facts = this.policyFacts(context, operation.destinationRelativePath);
489
+ const parent = path.dirname(operation.destinationAbsPath);
490
+ if (facts.targetExists ||
491
+ path.resolve(facts.absPath) !== path.resolve(operation.destinationAbsPath) ||
492
+ facts.comparisonKey !== operation.destinationComparisonKey ||
493
+ path.resolve(facts.existingParent) !== parent) {
494
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move destination path or parent identity changed.");
495
+ }
496
+ const parentRelative = path.relative(context.batch.workspace.root, parent).replaceAll("\\", "/") || ".";
497
+ const expectedIdentity = context.manifest.createdDirectoryIdentities[parentRelative];
498
+ if (expectedIdentity) {
499
+ await this.assertDirectoryIdentity(parent, expectedIdentity);
500
+ return;
501
+ }
502
+ if (path.resolve(operation.destinationExistingParent) !== parent ||
503
+ facts.existingParentIdentity !== operation.destinationExistingParentIdentity) {
504
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move destination existing parent changed.");
505
+ }
506
+ await this.assertDirectoryIdentity(parent);
507
+ }
508
+ async createDirectories(context) {
509
+ for (let index = 0; index < context.manifest.plannedCreatedDirectories.length; index += 1) {
510
+ const relativePath = context.manifest.plannedCreatedDirectories[index];
511
+ const absPath = path.resolve(context.batch.workspace.root, relativePath);
512
+ await this.assertCreationPathReady(context, relativePath);
513
+ await this.faults.hit("before_each_directory_create", {
514
+ index,
515
+ directoryCount: context.manifest.plannedCreatedDirectories.length
516
+ });
517
+ try {
518
+ await this.filesystem.mkdir(absPath);
519
+ }
520
+ catch (error) {
521
+ if (error.code === "EEXIST") {
522
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move destination directory appeared concurrently.");
523
+ }
524
+ throw error;
525
+ }
526
+ await this.faults.hit("after_each_directory_create_before_manifest", {
527
+ index,
528
+ directoryCount: context.manifest.plannedCreatedDirectories.length
529
+ });
530
+ const createdIdentity = directoryIdentity(await fsp.lstat(absPath, { bigint: true }));
531
+ context.manifest = this.transition(context.manifest, {
532
+ createdDirectories: [...context.manifest.createdDirectories, relativePath],
533
+ createdDirectoryIdentities: {
534
+ ...context.manifest.createdDirectoryIdentities,
535
+ [relativePath]: createdIdentity
536
+ }
537
+ });
538
+ await this.faults.hit("after_each_directory_create", {
539
+ index,
540
+ directoryCount: context.manifest.plannedCreatedDirectories.length
541
+ });
542
+ }
543
+ }
544
+ async stageAll(context) {
545
+ const ordered = [...context.manifest.operations].sort((left, right) => left.sourceComparisonKey.localeCompare(right.sourceComparisonKey) ||
546
+ left.operationId.localeCompare(right.operationId));
547
+ for (let index = 0; index < ordered.length; index += 1) {
548
+ let operation = context.manifest.operations.find((value) => value.operationId === ordered[index].operationId);
549
+ const inspected = this.inspected(context, operation.operationId);
550
+ const stageAbsPath = this.stageAbs(context, operation);
551
+ await this.assertSourcePolicy(context, inspected);
552
+ await assertExpectedHandle(inspected);
553
+ await assertExpectedPath(inspected.sourceAbsPath, operation.objectIdentity);
554
+ if (await pathEntryExists(stageAbsPath)) {
555
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move stage name appeared concurrently.");
556
+ }
557
+ await this.faults.hit("before_each_stage_link", {
558
+ operationId: operation.operationId,
559
+ index,
560
+ operationCount: ordered.length
561
+ });
562
+ await withTransientRetry(() => this.filesystem.link(inspected.sourceAbsPath, stageAbsPath), async () => {
563
+ await this.assertSourcePolicy(context, inspected);
564
+ await assertExpectedHandle(inspected);
565
+ await assertExpectedPath(inspected.sourceAbsPath, operation.objectIdentity);
566
+ if (await pathEntryExists(stageAbsPath)) {
567
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move stage name appeared concurrently.");
568
+ }
569
+ });
570
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
571
+ await this.faults.hit("after_each_stage_link_before_manifest", {
572
+ operationId: operation.operationId,
573
+ index,
574
+ operationCount: ordered.length
575
+ });
576
+ operation = { ...operation, state: "staged_link_ready" };
577
+ context.manifest = this.transition(context.manifest, {
578
+ operations: this.replaceOperation(context.manifest.operations, operation)
579
+ });
580
+ await this.faults.hit("after_each_stage", {
581
+ operationId: operation.operationId,
582
+ index,
583
+ operationCount: ordered.length
584
+ });
585
+ await this.assertSourcePolicy(context, inspected);
586
+ await assertExpectedHandle(inspected);
587
+ await assertExpectedPath(inspected.sourceAbsPath, operation.objectIdentity);
588
+ const sourceHandle = inspected.handle;
589
+ const stageHandle = await openExpectedHandle(stageAbsPath, operation.objectIdentity);
590
+ let stageHandleTransferred = false;
591
+ try {
592
+ await this.faults.hit("before_each_source_unlink", {
593
+ operationId: operation.operationId,
594
+ index,
595
+ operationCount: ordered.length
596
+ });
597
+ await withTransientRetry(() => this.filesystem.unlink(inspected.sourceAbsPath), async () => {
598
+ await this.assertSourcePolicy(context, inspected);
599
+ await assertExpectedHandle(inspected);
600
+ await assertExpectedPath(inspected.sourceAbsPath, operation.objectIdentity);
601
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
602
+ });
603
+ await sourceHandle.close();
604
+ inspected.handle = stageHandle;
605
+ stageHandleTransferred = true;
606
+ await this.faults.hit("after_each_source_unlink_before_manifest", {
607
+ operationId: operation.operationId,
608
+ index,
609
+ operationCount: ordered.length
610
+ });
611
+ operation = { ...operation, state: "source_name_removed" };
612
+ context.manifest = this.transition(context.manifest, {
613
+ operations: this.replaceOperation(context.manifest.operations, operation)
614
+ });
615
+ }
616
+ finally {
617
+ if (!stageHandleTransferred)
618
+ await stageHandle.close().catch(() => undefined);
619
+ }
620
+ }
621
+ }
622
+ async installAll(context) {
623
+ const ordered = [...context.manifest.operations].sort((left, right) => left.destinationComparisonKey.localeCompare(right.destinationComparisonKey) ||
624
+ left.operationId.localeCompare(right.operationId));
625
+ for (let index = 0; index < ordered.length; index += 1) {
626
+ let operation = context.manifest.operations.find((value) => value.operationId === ordered[index].operationId);
627
+ const inspected = this.inspected(context, operation.operationId);
628
+ const stageAbsPath = this.stageAbs(context, operation);
629
+ await this.assertDestinationAbsent(context, inspected);
630
+ await assertExpectedHandle(inspected);
631
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
632
+ if (await pathEntryExists(inspected.destinationAbsPath)) {
633
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move destination appeared concurrently.");
634
+ }
635
+ await this.faults.hit("before_each_destination_link", {
636
+ operationId: operation.operationId,
637
+ index,
638
+ operationCount: ordered.length
639
+ });
640
+ await withTransientRetry(() => this.filesystem.link(stageAbsPath, inspected.destinationAbsPath), async () => {
641
+ await this.assertDestinationAbsent(context, inspected);
642
+ await assertExpectedHandle(inspected);
643
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
644
+ if (await pathEntryExists(inspected.destinationAbsPath)) {
645
+ throw new TransactionError("FILE_VERSION_CONFLICT", "A move destination appeared concurrently.");
646
+ }
647
+ });
648
+ await assertExpectedPath(inspected.destinationAbsPath, operation.objectIdentity);
649
+ await assertDestinationSpelling(inspected.destinationAbsPath);
650
+ await this.faults.hit("after_each_destination_link_before_manifest", {
651
+ operationId: operation.operationId,
652
+ index,
653
+ operationCount: ordered.length
654
+ });
655
+ operation = { ...operation, state: "destination_link_ready" };
656
+ context.manifest = this.transition(context.manifest, {
657
+ operations: this.replaceOperation(context.manifest.operations, operation)
658
+ });
659
+ const digest = await hashHandle(inspected.handle, operation.version.bytes);
660
+ if (digest !== operation.version.sha256) {
661
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Move destination content verification failed.");
662
+ }
663
+ await this.faults.hit("before_each_stage_unlink", {
664
+ operationId: operation.operationId,
665
+ index,
666
+ operationCount: ordered.length
667
+ });
668
+ await withTransientRetry(() => this.filesystem.unlink(stageAbsPath), async () => {
669
+ await assertExpectedHandle(inspected);
670
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
671
+ await assertExpectedPath(inspected.destinationAbsPath, operation.objectIdentity);
672
+ });
673
+ await inspected.handle.close();
674
+ await this.faults.hit("after_each_stage_unlink_before_manifest", {
675
+ operationId: operation.operationId,
676
+ index,
677
+ operationCount: ordered.length
678
+ });
679
+ operation = { ...operation, state: "installed" };
680
+ context.manifest = this.transition(context.manifest, {
681
+ operations: this.replaceOperation(context.manifest.operations, operation)
682
+ });
683
+ await this.faults.hit("after_each_install", {
684
+ operationId: operation.operationId,
685
+ index,
686
+ operationCount: ordered.length
687
+ });
688
+ }
689
+ }
690
+ async removePlannedDirectories(context) {
691
+ for (let index = 0; index < context.manifest.plannedRemovedDirectories.length; index += 1) {
692
+ const relativePath = context.manifest.plannedRemovedDirectories[index];
693
+ const absPath = path.resolve(context.batch.workspace.root, relativePath);
694
+ const expectedIdentity = context.manifest.plannedRemovedDirectoryIdentities[relativePath];
695
+ if (!expectedIdentity) {
696
+ throw new TransactionError("TRANSACTION_STATE_CORRUPT", "Undo cleanup directory identity is missing.");
697
+ }
698
+ const facts = this.policyFacts(context, relativePath);
699
+ if (!facts.targetExists || path.resolve(facts.absPath) !== absPath) {
700
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory path identity changed.");
701
+ }
702
+ await this.assertDirectoryIdentity(absPath, expectedIdentity);
703
+ if ((await fsp.readdir(absPath)).length !== 0) {
704
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory is no longer empty.");
705
+ }
706
+ await this.faults.hit("before_each_directory_remove", {
707
+ index,
708
+ directoryCount: context.manifest.plannedRemovedDirectories.length
709
+ });
710
+ await withTransientRetry(() => this.filesystem.rmdir(absPath), async () => {
711
+ await this.assertDirectoryIdentity(absPath, expectedIdentity);
712
+ if ((await fsp.readdir(absPath)).length !== 0) {
713
+ throw new TransactionError("FILE_VERSION_CONFLICT", "Undo cleanup directory is no longer empty.");
714
+ }
715
+ });
716
+ await this.faults.hit("after_each_directory_remove_before_manifest", {
717
+ index,
718
+ directoryCount: context.manifest.plannedRemovedDirectories.length
719
+ });
720
+ context.manifest = this.transition(context.manifest, {
721
+ removedDirectories: [...context.manifest.removedDirectories, relativePath]
722
+ });
723
+ await this.faults.hit("after_each_directory_remove", {
724
+ index,
725
+ directoryCount: context.manifest.plannedRemovedDirectories.length
726
+ });
727
+ }
728
+ }
729
+ async commitContext(context) {
730
+ if (context.lifecycle !== "prepared") {
731
+ throw new TransactionError("TRANSACTION_FAILED", "Move transaction is not prepared.");
732
+ }
733
+ try {
734
+ context.manifest = this.transition(context.manifest, { state: "committing" });
735
+ await this.faults.hit("after_manifest_committing", {
736
+ operationCount: context.manifest.operations.length
737
+ });
738
+ await this.createDirectories(context);
739
+ await this.stageAll(context);
740
+ await this.installAll(context);
741
+ context.manifest = this.transition(context.manifest, { state: "committed_pending_participants" });
742
+ await this.faults.hit("after_manifest_pending_participants", {
743
+ participantCount: context.manifest.requiredParticipants.length
744
+ });
745
+ context.lifecycle = "pending";
746
+ return new PendingMoveTransactionCommitImpl(this, context);
747
+ }
748
+ catch (error) {
749
+ try {
750
+ await this.rollbackContext(context, "commit_failed");
751
+ }
752
+ catch (rollbackError) {
753
+ throw rollbackError;
754
+ }
755
+ throw toTransactionError(error, "Atomic move failed.");
756
+ }
757
+ }
758
+ async ensureRollbackStages(context) {
759
+ for (const operation of context.manifest.operations) {
760
+ const inspected = this.inspected(context, operation.operationId);
761
+ const stageAbsPath = this.stageAbs(context, operation);
762
+ const stageIdentity = await pathIdentity(stageAbsPath);
763
+ if (stageIdentity) {
764
+ if (!identityEquals(operation.objectIdentity, stageIdentity)) {
765
+ throw new TransactionError("ROLLBACK_FAILED", "Move stage object identity is ambiguous.");
766
+ }
767
+ continue;
768
+ }
769
+ const sourceIdentity = await pathIdentity(inspected.sourceAbsPath);
770
+ if (sourceIdentity && identityEquals(operation.objectIdentity, sourceIdentity))
771
+ continue;
772
+ const destinationIdentity = await pathIdentity(inspected.destinationAbsPath);
773
+ if (!destinationIdentity || !identityEquals(operation.objectIdentity, destinationIdentity)) {
774
+ throw new TransactionError("ROLLBACK_FAILED", "Move rollback has no authenticated object link.");
775
+ }
776
+ await this.filesystem.link(inspected.destinationAbsPath, stageAbsPath);
777
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
778
+ }
779
+ }
780
+ async removeInstalledDestinations(context) {
781
+ const expectedSources = new Map(context.manifest.operations.map((operation) => [operation.sourceComparisonKey, operation.objectIdentity]));
782
+ for (const operation of context.manifest.operations) {
783
+ const inspected = this.inspected(context, operation.operationId);
784
+ const actual = await pathIdentity(inspected.destinationAbsPath);
785
+ if (!actual)
786
+ continue;
787
+ if (identityEquals(operation.objectIdentity, actual)) {
788
+ await this.filesystem.unlink(inspected.destinationAbsPath);
789
+ continue;
790
+ }
791
+ const originalSource = expectedSources.get(operation.destinationComparisonKey);
792
+ if (originalSource && identityEquals(originalSource, actual))
793
+ continue;
794
+ if (["planned", "staged_link_ready", "source_name_removed"].includes(operation.state)) {
795
+ continue;
796
+ }
797
+ throw new TransactionError("ROLLBACK_FAILED", "A move destination contains an unrelated file object.");
798
+ }
799
+ }
800
+ async restoreOriginalSources(context) {
801
+ for (const operation of context.manifest.operations) {
802
+ const inspected = this.inspected(context, operation.operationId);
803
+ const current = await pathIdentity(inspected.sourceAbsPath);
804
+ if (current) {
805
+ if (!identityEquals(operation.objectIdentity, current)) {
806
+ throw new TransactionError("ROLLBACK_FAILED", "A move source contains an unrelated file object.");
807
+ }
808
+ }
809
+ else {
810
+ const stageAbsPath = this.stageAbs(context, operation);
811
+ await assertExpectedPath(stageAbsPath, operation.objectIdentity);
812
+ await this.filesystem.link(stageAbsPath, inspected.sourceAbsPath);
813
+ await assertExpectedPath(inspected.sourceAbsPath, operation.objectIdentity);
814
+ if (process.platform === "win32")
815
+ await assertDestinationSpelling(inspected.sourceAbsPath);
816
+ }
817
+ }
818
+ }
819
+ async cleanupRollbackStages(context) {
820
+ for (const operation of context.manifest.operations) {
821
+ const stageAbsPath = this.stageAbs(context, operation);
822
+ const actual = await pathIdentity(stageAbsPath);
823
+ if (!actual)
824
+ continue;
825
+ if (!identityEquals(operation.objectIdentity, actual)) {
826
+ throw new TransactionError("ROLLBACK_FAILED", "Move rollback stage identity changed.");
827
+ }
828
+ await this.filesystem.unlink(stageAbsPath);
829
+ }
830
+ }
831
+ async rollbackContext(context, reason) {
832
+ if (context.lifecycle === "committed") {
833
+ throw new TransactionError("ROLLBACK_FAILED", "A committed move transaction cannot be rolled back.");
834
+ }
835
+ if (context.lifecycle === "rolled_back")
836
+ return;
837
+ try {
838
+ if (context.manifest.state !== "rolling_back") {
839
+ context.manifest = this.transition(context.manifest, {
840
+ state: "rolling_back",
841
+ failureCode: context.manifest.failureCode ?? "TRANSACTION_FAILED",
842
+ failureMessage: context.manifest.failureMessage ?? `Move rollback requested: ${reason}`
843
+ });
844
+ }
845
+ await this.ensureRollbackStages(context);
846
+ await this.removeInstalledDestinations(context);
847
+ await this.restoreOriginalSources(context);
848
+ await this.cleanupRollbackStages(context);
849
+ for (let index = context.manifest.createdDirectories.length - 1; index >= 0; index -= 1) {
850
+ const relativePath = context.manifest.createdDirectories[index];
851
+ const absPath = path.resolve(context.batch.workspace.root, relativePath);
852
+ const expectedIdentity = context.manifest.createdDirectoryIdentities[relativePath];
853
+ if (!expectedIdentity) {
854
+ throw new TransactionError("ROLLBACK_FAILED", "Move-created directory identity evidence is missing.");
855
+ }
856
+ try {
857
+ await this.assertDirectoryIdentity(absPath, expectedIdentity);
858
+ await this.filesystem.rmdir(absPath);
859
+ }
860
+ catch (error) {
861
+ if (error.code !== "ENOENT")
862
+ throw error;
863
+ }
864
+ }
865
+ for (const relativePath of context.manifest.plannedCreatedDirectories) {
866
+ if (context.manifest.createdDirectories.includes(relativePath))
867
+ continue;
868
+ if (await pathEntryExists(path.resolve(context.batch.workspace.root, relativePath))) {
869
+ throw new TransactionError("ROLLBACK_FAILED", "An unjournaled planned move directory requires recovery review.");
870
+ }
871
+ }
872
+ context.manifest = this.transition(context.manifest, {
873
+ state: "rolled_back",
874
+ operations: context.manifest.operations.map((operation) => ({
875
+ ...operation,
876
+ state: "rolled_back"
877
+ }))
878
+ });
879
+ context.lifecycle = "rolled_back";
880
+ await context.batch.close();
881
+ this.releaseContext(context);
882
+ }
883
+ catch {
884
+ context.lifecycle = "recovery_required";
885
+ try {
886
+ context.manifest = this.transition(context.manifest, {
887
+ state: "recovery_required",
888
+ failureCode: "ROLLBACK_FAILED",
889
+ failureMessage: "Move rollback could not be proven complete."
890
+ });
891
+ }
892
+ catch {
893
+ // Preserve the last authenticated manifest and workspace evidence.
894
+ }
895
+ await context.batch.close();
896
+ this.releaseContextBestEffort(context);
897
+ throw new TransactionError("ROLLBACK_FAILED", "Move rollback could not be proven complete.", { transactionId: context.manifest.transactionId });
898
+ }
899
+ }
900
+ async participantContext(context, name, action) {
901
+ if (context.lifecycle !== "pending") {
902
+ throw new TransactionError("TRANSACTION_FAILED", "Move transaction is not awaiting participants.");
903
+ }
904
+ if (!context.manifest.requiredParticipants.includes(name)) {
905
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Unknown move participant.");
906
+ }
907
+ if (context.manifest.participantFacts[name] !== "pending") {
908
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "Move participant is not pending.");
909
+ }
910
+ let effectCompleted = false;
911
+ try {
912
+ await action();
913
+ effectCompleted = true;
914
+ await this.faults.hit("after_each_participant_effect_before_manifest", {
915
+ participantIndex: context.manifest.requiredParticipants.indexOf(name),
916
+ participantCount: context.manifest.requiredParticipants.length
917
+ });
918
+ context.manifest = this.transition(context.manifest, {
919
+ participantFacts: { ...context.manifest.participantFacts, [name]: "committed" }
920
+ });
921
+ await this.faults.hit("after_each_participant", {
922
+ participantIndex: context.manifest.requiredParticipants.indexOf(name),
923
+ participantCount: context.manifest.requiredParticipants.length
924
+ });
925
+ }
926
+ catch (error) {
927
+ if (effectCompleted) {
928
+ context.lifecycle = "recovery_required";
929
+ await context.batch.close();
930
+ this.releaseContextBestEffort(context);
931
+ throw new TransactionError("TRANSACTION_RECOVERY_REQUIRED", "A durable move participant requires recovery reconciliation.", { transactionId: context.manifest.transactionId });
932
+ }
933
+ context.manifest = this.transition(context.manifest, {
934
+ participantFacts: { ...context.manifest.participantFacts, [name]: "failed" },
935
+ failureCode: "TRANSACTION_FAILED",
936
+ failureMessage: "A required move participant failed."
937
+ });
938
+ await this.rollbackContext(context, "participant_failed");
939
+ throw toTransactionError(error, "A required move participant failed.");
940
+ }
941
+ }
942
+ async finalizeContext(context) {
943
+ if (context.lifecycle !== "pending") {
944
+ throw new TransactionError("TRANSACTION_FAILED", "Move transaction cannot be finalized.");
945
+ }
946
+ const incomplete = context.manifest.requiredParticipants.find((name) => context.manifest.participantFacts[name] !== "committed");
947
+ if (incomplete) {
948
+ throw new TransactionError("TRANSACTION_PRECONDITION_FAILED", "A required move participant is incomplete.");
949
+ }
950
+ try {
951
+ context.manifest = this.transition(context.manifest, { state: "commit_decided" });
952
+ await this.faults.hit("after_manifest_commit_decided", {
953
+ operationCount: context.manifest.operations.length,
954
+ directoryCount: context.manifest.plannedRemovedDirectories.length
955
+ });
956
+ await this.removePlannedDirectories(context);
957
+ context.manifest = this.transition(context.manifest, {
958
+ state: "committed",
959
+ operations: context.manifest.operations.map((operation) => ({
960
+ ...operation,
961
+ state: "finalized"
962
+ }))
963
+ });
964
+ await this.faults.hit("after_manifest_committed", {
965
+ operationCount: context.manifest.operations.length
966
+ });
967
+ context.lifecycle = "committed";
968
+ let cleanupPending = false;
969
+ for (const operation of context.manifest.operations) {
970
+ const stageAbsPath = this.stageAbs(context, operation);
971
+ try {
972
+ await this.filesystem.unlink(stageAbsPath);
973
+ }
974
+ catch (error) {
975
+ if (error.code !== "ENOENT")
976
+ cleanupPending = true;
977
+ }
978
+ }
979
+ await context.batch.close();
980
+ this.releaseContext(context);
981
+ return {
982
+ transactionId: context.manifest.transactionId,
983
+ changeSetId: context.manifest.changeSetId,
984
+ committedAt: context.manifest.updatedAt,
985
+ operationCount: context.manifest.operations.length,
986
+ cleanupPending
987
+ };
988
+ }
989
+ catch {
990
+ context.lifecycle = "recovery_required";
991
+ await context.batch.close();
992
+ this.releaseContextBestEffort(context);
993
+ throw new TransactionError("TRANSACTION_RECOVERY_REQUIRED", "Move commit decision requires recovery before another mutation.", { transactionId: context.manifest.transactionId });
994
+ }
995
+ }
996
+ releaseContext(context) {
997
+ if (context.released)
998
+ return;
999
+ context.lock.release();
1000
+ context.released = true;
1001
+ }
1002
+ releaseContextBestEffort(context) {
1003
+ try {
1004
+ this.releaseContext(context);
1005
+ }
1006
+ catch {
1007
+ // Recovery evidence remains authoritative.
1008
+ }
1009
+ }
1010
+ preparedCommit(context) {
1011
+ return this.commitContext(context);
1012
+ }
1013
+ preparedRollback(context, reason) {
1014
+ return this.rollbackContext(context, reason);
1015
+ }
1016
+ participantCommit(context, name, action) {
1017
+ return this.participantContext(context, name, action);
1018
+ }
1019
+ pendingFinalize(context) {
1020
+ return this.finalizeContext(context);
1021
+ }
1022
+ pendingRollback(context, reason) {
1023
+ return this.rollbackContext(context, reason);
1024
+ }
1025
+ }
1026
+ class PreparedMoveTransactionImpl {
1027
+ coordinator;
1028
+ context;
1029
+ transactionId;
1030
+ changeSetId;
1031
+ operations;
1032
+ createdDirectories;
1033
+ totalBytes;
1034
+ constructor(coordinator, context) {
1035
+ this.coordinator = coordinator;
1036
+ this.context = context;
1037
+ this.transactionId = context.manifest.transactionId;
1038
+ this.changeSetId = context.manifest.changeSetId;
1039
+ this.operations = context.batch.operations;
1040
+ this.createdDirectories = context.batch.createdDirectories;
1041
+ this.totalBytes = context.batch.totalBytes;
1042
+ }
1043
+ createdDirectoryFacts() {
1044
+ return this.context.manifest.createdDirectories.map((relativePath) => ({
1045
+ relativePath,
1046
+ objectIdentity: this.context.manifest.createdDirectoryIdentities[relativePath]
1047
+ }));
1048
+ }
1049
+ commit() {
1050
+ return this.coordinator.preparedCommit(this.context);
1051
+ }
1052
+ rollback(reason) {
1053
+ return this.coordinator.preparedRollback(this.context, reason);
1054
+ }
1055
+ }
1056
+ class PendingMoveTransactionCommitImpl {
1057
+ coordinator;
1058
+ context;
1059
+ transactionId;
1060
+ changeSetId;
1061
+ operationCount;
1062
+ constructor(coordinator, context) {
1063
+ this.coordinator = coordinator;
1064
+ this.context = context;
1065
+ this.transactionId = context.manifest.transactionId;
1066
+ this.changeSetId = context.manifest.changeSetId;
1067
+ this.operationCount = context.manifest.operations.length;
1068
+ }
1069
+ commitParticipant(name, action) {
1070
+ return this.coordinator.participantCommit(this.context, name, action);
1071
+ }
1072
+ finalize() {
1073
+ return this.coordinator.pendingFinalize(this.context);
1074
+ }
1075
+ rollback(reason) {
1076
+ return this.coordinator.pendingRollback(this.context, reason);
1077
+ }
1078
+ }
1079
+ //# sourceMappingURL=engine.js.map