@narumitw/pi-sync 0.57.9 → 0.57.11

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 (169) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +7 -1
  3. package/dist/chunks/{agent-candidate-GNEYR225.ts → agent-candidate-OCDPRI5G.ts} +12 -9
  4. package/dist/chunks/{agent-plan-3L7CRFDM.ts → agent-plan-P5B5RGZ7.ts} +22 -18
  5. package/dist/chunks/{agent-plan-3L7CRFDM.ts.map → agent-plan-P5B5RGZ7.ts.map} +1 -1
  6. package/dist/chunks/{agent-refusal-retry-RPTMUQXK.ts → agent-refusal-retry-476YGNU5.ts} +11 -8
  7. package/dist/chunks/{agent-refusal-retry-RPTMUQXK.ts.map → agent-refusal-retry-476YGNU5.ts.map} +1 -1
  8. package/dist/chunks/{agent-store-55CZOCPX.ts → agent-store-RJSMNOYP.ts} +12 -11
  9. package/dist/chunks/{agent-store-55CZOCPX.ts.map → agent-store-RJSMNOYP.ts.map} +1 -1
  10. package/dist/chunks/agent-sync-EUK2CPSS.ts +22 -0
  11. package/dist/chunks/{chunk-U3XRI2HF.ts → chunk-3IYAPMST.ts} +11 -11
  12. package/dist/chunks/{chunk-B4QZBDBT.ts → chunk-45COPAK7.ts} +10 -3
  13. package/dist/chunks/chunk-45COPAK7.ts.map +7 -0
  14. package/dist/chunks/chunk-5SFMBY5P.ts +26 -0
  15. package/dist/chunks/chunk-5SFMBY5P.ts.map +7 -0
  16. package/dist/chunks/{chunk-ED3TYIVW.ts → chunk-5TSCBBPP.ts} +5 -5
  17. package/dist/chunks/{chunk-5QAE3G3K.ts → chunk-67INJPKR.ts} +6 -6
  18. package/dist/chunks/{chunk-IWZH5KYS.ts → chunk-6LD5KX55.ts} +10 -10
  19. package/dist/chunks/{chunk-AAEEHR7H.ts → chunk-6O3EDBRL.ts} +2 -2
  20. package/dist/chunks/{chunk-CRKTAPSL.ts → chunk-7A35ZAVO.ts} +333 -237
  21. package/dist/chunks/chunk-7A35ZAVO.ts.map +7 -0
  22. package/dist/chunks/{chunk-6FVVRTL5.ts → chunk-7OLLPPLU.ts} +77 -63
  23. package/dist/chunks/chunk-7OLLPPLU.ts.map +7 -0
  24. package/dist/chunks/{chunk-PQW6GS4J.ts → chunk-7ZIYU5QS.ts} +12 -10
  25. package/dist/chunks/{chunk-PQW6GS4J.ts.map → chunk-7ZIYU5QS.ts.map} +1 -1
  26. package/dist/chunks/{chunk-S7QS4AWK.ts → chunk-AKMV47YC.ts} +5 -5
  27. package/dist/chunks/chunk-AR2DGDUI.ts +55 -0
  28. package/dist/chunks/chunk-AR2DGDUI.ts.map +7 -0
  29. package/dist/chunks/{chunk-GNH73BJ5.ts → chunk-BEST45H2.ts} +7 -7
  30. package/dist/chunks/chunk-CBLTWXAU.ts +114 -0
  31. package/dist/chunks/chunk-CBLTWXAU.ts.map +7 -0
  32. package/dist/chunks/{chunk-GP5DU62N.ts → chunk-CPT2BN6N.ts} +2 -2
  33. package/dist/chunks/{chunk-UPNVIUBN.ts → chunk-DN4IA7MR.ts} +6 -6
  34. package/dist/chunks/{chunk-PG7NMFP2.ts → chunk-DRTC4PKM.ts} +8 -8
  35. package/dist/chunks/chunk-ESKOPQVB.ts +348 -0
  36. package/dist/chunks/chunk-ESKOPQVB.ts.map +7 -0
  37. package/dist/chunks/{chunk-MKKF4IMY.ts → chunk-F7E3VFXU.ts} +5 -5
  38. package/dist/chunks/{chunk-HUZ5CR4W.ts → chunk-FHE2DCA2.ts} +3 -52
  39. package/dist/chunks/chunk-FHE2DCA2.ts.map +7 -0
  40. package/dist/chunks/{chunk-UBV24CG4.ts → chunk-FLHCOJCD.ts} +3 -3
  41. package/dist/chunks/chunk-GNYGNHFF.ts +27 -0
  42. package/dist/chunks/chunk-GNYGNHFF.ts.map +7 -0
  43. package/dist/chunks/chunk-KYTT7KV4.ts +319 -0
  44. package/dist/chunks/chunk-KYTT7KV4.ts.map +7 -0
  45. package/dist/chunks/{chunk-A6HU4ERM.ts → chunk-MKSMJPVA.ts} +6 -23
  46. package/dist/chunks/chunk-MKSMJPVA.ts.map +7 -0
  47. package/dist/chunks/{chunk-ORGBI36T.ts → chunk-OJARL2TG.ts} +4 -4
  48. package/dist/chunks/{chunk-JCH3VXIO.ts → chunk-OKPPZA4D.ts} +150 -91
  49. package/dist/chunks/chunk-OKPPZA4D.ts.map +7 -0
  50. package/dist/chunks/{chunk-QO333NM4.ts → chunk-OVBAW7KV.ts} +180 -133
  51. package/dist/chunks/chunk-OVBAW7KV.ts.map +7 -0
  52. package/dist/chunks/{chunk-GSNPASKB.ts → chunk-Q23JJW7E.ts} +6 -6
  53. package/dist/chunks/{chunk-YK52VDXG.ts → chunk-TIMWN2RH.ts} +10 -8
  54. package/dist/chunks/{chunk-YK52VDXG.ts.map → chunk-TIMWN2RH.ts.map} +1 -1
  55. package/dist/chunks/{chunk-UOHR7LRO.ts → chunk-TZC7GDJE.ts} +10 -22
  56. package/dist/chunks/chunk-TZC7GDJE.ts.map +7 -0
  57. package/dist/chunks/chunk-X7R6DCVF.ts +28 -0
  58. package/dist/chunks/chunk-X7R6DCVF.ts.map +7 -0
  59. package/dist/chunks/{chunk-76NB4R7U.ts → chunk-XJHQPB3E.ts} +2 -2
  60. package/dist/chunks/{chunk-BDB4IDM3.ts → chunk-Y4UVXOLQ.ts} +8 -6
  61. package/dist/chunks/{chunk-BDB4IDM3.ts.map → chunk-Y4UVXOLQ.ts.map} +1 -1
  62. package/dist/chunks/{chunk-P7DD5PWZ.ts → chunk-ZDDBZH72.ts} +3 -3
  63. package/dist/chunks/command-handler-F2E7A5T5.ts +548 -0
  64. package/dist/chunks/command-handler-F2E7A5T5.ts.map +7 -0
  65. package/dist/chunks/{config-KGIYTTXQ.ts → config-HYG7G5EM.ts} +7 -6
  66. package/dist/chunks/{conflict-artifacts-FXFIIBCB.ts → conflict-artifacts-J6WSDCWP.ts} +13 -9
  67. package/dist/chunks/{conflict-review-3X37QEIT.ts → conflict-review-2QMO2K6Q.ts} +31 -25
  68. package/dist/chunks/{conflict-review-3X37QEIT.ts.map → conflict-review-2QMO2K6Q.ts.map} +1 -1
  69. package/dist/chunks/{continuous-record-SQJ47CXN.ts → continuous-record-AH7JGYKM.ts} +8 -7
  70. package/dist/chunks/{continuous-sync-Q6QUD6TY.ts → continuous-sync-VRMXCA5X.ts} +33 -28
  71. package/dist/chunks/{continuous-sync-Q6QUD6TY.ts.map → continuous-sync-VRMXCA5X.ts.map} +1 -1
  72. package/dist/chunks/{file-selection-3JJYOVNR.ts → file-selection-IELTXSGZ.ts} +11 -10
  73. package/dist/chunks/{file-selection-3JJYOVNR.ts.map → file-selection-IELTXSGZ.ts.map} +1 -1
  74. package/dist/chunks/{git-backend-NYKSG5X6.ts → git-backend-KHD36W27.ts} +15 -12
  75. package/dist/chunks/{git-backend-NYKSG5X6.ts.map → git-backend-KHD36W27.ts.map} +1 -1
  76. package/dist/chunks/{local-fields-6DGYOOIK.ts → local-fields-JEKAPZKD.ts} +9 -5
  77. package/dist/chunks/manager-result-dispatcher-6W52NM7F.ts +32 -0
  78. package/dist/chunks/{manager-ui-ZH6DEC2G.ts → manager-ui-LM7DSJ2Y.ts} +124 -67
  79. package/dist/chunks/manager-ui-LM7DSJ2Y.ts.map +7 -0
  80. package/dist/chunks/{merge-baseline-store-RFCAH7KL.ts → merge-baseline-store-65GKUMXI.ts} +6 -5
  81. package/dist/chunks/remote-selection-ui-TD4C4W3J.ts +31 -0
  82. package/dist/chunks/{s3-backend-F7PR5FB3.ts → s3-backend-L24UZ6IK.ts} +24 -18
  83. package/dist/chunks/s3-backend-L24UZ6IK.ts.map +7 -0
  84. package/dist/chunks/{setup-switch-E7PHKI6J.ts → setup-switch-PIPXYPCW.ts} +6 -7
  85. package/dist/chunks/{setup-wizard-OVHZYXNW.ts → setup-wizard-RR5U3SUB.ts} +8 -9
  86. package/dist/chunks/{setup-wizard-OVHZYXNW.ts.map → setup-wizard-RR5U3SUB.ts.map} +1 -1
  87. package/dist/chunks/{snapshot-THS5EY2L.ts → snapshot-RGNDYT6A.ts} +10 -6
  88. package/dist/chunks/snapshot-transaction-26BQO36S.ts +24 -0
  89. package/dist/chunks/sync-inspection-MOMLGUTD.ts +25 -0
  90. package/dist/chunks/sync-inspection-MOMLGUTD.ts.map +7 -0
  91. package/dist/chunks/{sync-operations-Y72GNIQ2.ts → sync-operations-CV3TULLD.ts} +66 -57
  92. package/dist/chunks/{sync-operations-Y72GNIQ2.ts.map → sync-operations-CV3TULLD.ts.map} +1 -1
  93. package/dist/chunks/{sync-state-CFL4RRRB.ts → sync-state-7L4NT7W2.ts} +8 -5
  94. package/dist/chunks/sync-state-7L4NT7W2.ts.map +7 -0
  95. package/dist/chunks/{webdav-backend-TGFUH3SF.ts → webdav-backend-3ZCACILP.ts} +15 -12
  96. package/dist/chunks/{webdav-backend-TGFUH3SF.ts.map → webdav-backend-3ZCACILP.ts.map} +1 -1
  97. package/dist/index.ts +54 -537
  98. package/dist/index.ts.map +3 -3
  99. package/package.json +2 -2
  100. package/skills/configure-pi-sync/references/configuration.md +8 -1
  101. package/src/backends/s3/s3-client.ts +8 -1
  102. package/src/commands/command-execution.ts +8 -3
  103. package/src/paths.ts +6 -1
  104. package/src/settings/config-file.ts +205 -118
  105. package/src/settings/config.ts +2 -2
  106. package/src/settings/settings-management.ts +15 -1
  107. package/src/settings/settings-store.ts +0 -14
  108. package/src/settings/settings-validation.ts +1 -1
  109. package/src/snapshot/session-paths.ts +15 -2
  110. package/src/snapshot/snapshot-mutation-queues.ts +142 -0
  111. package/src/snapshot/snapshot-transaction-directory.ts +16 -0
  112. package/src/snapshot/snapshot-transaction.ts +123 -137
  113. package/src/sync/automatic-sync.ts +12 -6
  114. package/src/sync/local-field-policy.ts +29 -0
  115. package/src/sync/local-fields.ts +3 -29
  116. package/src/sync/merge-apply.ts +6 -0
  117. package/src/sync/mutation-owner.ts +22 -0
  118. package/src/sync/startup-check.ts +3 -2
  119. package/src/sync/sync-loaders.ts +4 -0
  120. package/src/sync/sync-local.ts +2 -19
  121. package/src/sync-extension.ts +7 -2
  122. package/src/ui/cancellable-operation.ts +36 -13
  123. package/src/ui/manager-state.ts +3 -1
  124. package/src/ui/manager-ui.ts +76 -24
  125. package/src/ui/remote-selection-ui.ts +131 -82
  126. package/src/ui/settings-ui.ts +2 -1
  127. package/dist/chunks/chunk-6FVVRTL5.ts.map +0 -7
  128. package/dist/chunks/chunk-A6HU4ERM.ts.map +0 -7
  129. package/dist/chunks/chunk-B4QZBDBT.ts.map +0 -7
  130. package/dist/chunks/chunk-CRKTAPSL.ts.map +0 -7
  131. package/dist/chunks/chunk-HUZ5CR4W.ts.map +0 -7
  132. package/dist/chunks/chunk-JCH3VXIO.ts.map +0 -7
  133. package/dist/chunks/chunk-QO333NM4.ts.map +0 -7
  134. package/dist/chunks/chunk-QOFMXPM5.ts +0 -735
  135. package/dist/chunks/chunk-QOFMXPM5.ts.map +0 -7
  136. package/dist/chunks/chunk-UOHR7LRO.ts.map +0 -7
  137. package/dist/chunks/manager-result-dispatcher-HOCM2GDA.ts +0 -24
  138. package/dist/chunks/manager-ui-ZH6DEC2G.ts.map +0 -7
  139. package/dist/chunks/remote-selection-ui-YFPGYGNE.ts +0 -23
  140. package/dist/chunks/s3-backend-F7PR5FB3.ts.map +0 -7
  141. package/dist/chunks/sync-inspection-J25EEKZK.ts +0 -21
  142. /package/dist/chunks/{agent-candidate-GNEYR225.ts.map → agent-candidate-OCDPRI5G.ts.map} +0 -0
  143. /package/dist/chunks/{config-KGIYTTXQ.ts.map → agent-sync-EUK2CPSS.ts.map} +0 -0
  144. /package/dist/chunks/{chunk-U3XRI2HF.ts.map → chunk-3IYAPMST.ts.map} +0 -0
  145. /package/dist/chunks/{chunk-ED3TYIVW.ts.map → chunk-5TSCBBPP.ts.map} +0 -0
  146. /package/dist/chunks/{chunk-5QAE3G3K.ts.map → chunk-67INJPKR.ts.map} +0 -0
  147. /package/dist/chunks/{chunk-IWZH5KYS.ts.map → chunk-6LD5KX55.ts.map} +0 -0
  148. /package/dist/chunks/{chunk-AAEEHR7H.ts.map → chunk-6O3EDBRL.ts.map} +0 -0
  149. /package/dist/chunks/{chunk-S7QS4AWK.ts.map → chunk-AKMV47YC.ts.map} +0 -0
  150. /package/dist/chunks/{chunk-GNH73BJ5.ts.map → chunk-BEST45H2.ts.map} +0 -0
  151. /package/dist/chunks/{chunk-GP5DU62N.ts.map → chunk-CPT2BN6N.ts.map} +0 -0
  152. /package/dist/chunks/{chunk-UPNVIUBN.ts.map → chunk-DN4IA7MR.ts.map} +0 -0
  153. /package/dist/chunks/{chunk-PG7NMFP2.ts.map → chunk-DRTC4PKM.ts.map} +0 -0
  154. /package/dist/chunks/{chunk-MKKF4IMY.ts.map → chunk-F7E3VFXU.ts.map} +0 -0
  155. /package/dist/chunks/{chunk-UBV24CG4.ts.map → chunk-FLHCOJCD.ts.map} +0 -0
  156. /package/dist/chunks/{chunk-ORGBI36T.ts.map → chunk-OJARL2TG.ts.map} +0 -0
  157. /package/dist/chunks/{chunk-GSNPASKB.ts.map → chunk-Q23JJW7E.ts.map} +0 -0
  158. /package/dist/chunks/{chunk-76NB4R7U.ts.map → chunk-XJHQPB3E.ts.map} +0 -0
  159. /package/dist/chunks/{chunk-P7DD5PWZ.ts.map → chunk-ZDDBZH72.ts.map} +0 -0
  160. /package/dist/chunks/{conflict-artifacts-FXFIIBCB.ts.map → config-HYG7G5EM.ts.map} +0 -0
  161. /package/dist/chunks/{continuous-record-SQJ47CXN.ts.map → conflict-artifacts-J6WSDCWP.ts.map} +0 -0
  162. /package/dist/chunks/{local-fields-6DGYOOIK.ts.map → continuous-record-AH7JGYKM.ts.map} +0 -0
  163. /package/dist/chunks/{manager-result-dispatcher-HOCM2GDA.ts.map → local-fields-JEKAPZKD.ts.map} +0 -0
  164. /package/dist/chunks/{merge-baseline-store-RFCAH7KL.ts.map → manager-result-dispatcher-6W52NM7F.ts.map} +0 -0
  165. /package/dist/chunks/{remote-selection-ui-YFPGYGNE.ts.map → merge-baseline-store-65GKUMXI.ts.map} +0 -0
  166. /package/dist/chunks/{setup-switch-E7PHKI6J.ts.map → remote-selection-ui-TD4C4W3J.ts.map} +0 -0
  167. /package/dist/chunks/{snapshot-THS5EY2L.ts.map → setup-switch-PIPXYPCW.ts.map} +0 -0
  168. /package/dist/chunks/{sync-inspection-J25EEKZK.ts.map → snapshot-RGNDYT6A.ts.map} +0 -0
  169. /package/dist/chunks/{sync-state-CFL4RRRB.ts.map → snapshot-transaction-26BQO36S.ts.map} +0 -0
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/state/mutation-directory-sync.ts", "../../src/snapshot/snapshot-transaction.ts", "../../src/snapshot/snapshot-case-replacement.ts", "../../src/snapshot/snapshot-root-transition.ts", "../../src/snapshot/snapshot-transaction-plan.ts"],
4
- "sourcesContent": ["import path from \"node:path\";\nimport { isPathInside } from \"../paths.js\";\nimport { mergePathIdentity } from \"../sync/file-merge-planner.js\";\nimport { syncDirectory } from \"./json-file.js\";\n\n/** Persist created ancestor names as well as the immediate rename/delete directory. */\nexport async function syncMutationParents(\n targets: readonly string[],\n roots: readonly string[],\n options: { signal?: AbortSignal; validateMutation?: () => void } = {},\n) {\n const directories = new Set<string>();\n for (const target of targets) {\n const root = roots.map((root) => path.resolve(root)).find((root) => isPathInside(root, target));\n if (!root) throw new Error(\"Unowned mutation directory.\");\n for (let parent = path.dirname(target); ; parent = path.dirname(parent)) {\n directories.add(parent);\n if (mergePathIdentity(parent) === mergePathIdentity(root)) break;\n if (path.dirname(parent) === parent) throw new Error(\"Mutation directory escaped its owned root.\");\n }\n }\n for (const directory of [...directories].sort((a, b) => b.length - a.length)) {\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n try {\n await syncDirectory(directory);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n }\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n }\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport type { Stats } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { withFileMutationQueue } from \"@earendil-works/pi-coding-agent\";\nimport { assertWithinRoot, isDeniedPath, isPathInside } from \"../paths.js\";\nimport { syncDirectory, writeJson } from \"../state/json-file.js\";\nimport { withLock } from \"../state/lock.js\";\nimport { syncMutationParents } from \"../state/mutation-directory-sync.js\";\nimport { stateDir } from \"../state/state-directory.js\";\nimport { mergePathIdentity } from \"../sync/file-merge-planner.js\";\nimport { agentDir, configuredSessionDir } from \"./session-paths.js\";\nimport { caseReplacementSpelling, coalesceCaseReplacements, isCaseReplacement } from \"./snapshot-case-replacement.js\";\nimport { sessionStorageRoot } from \"./snapshot-paths.js\";\nimport {\n prepareSessionRootTransition,\n resolveTransitionSessionRoot,\n type SessionRootTransition,\n validateSessionRootTransition,\n} from \"./snapshot-root-transition.js\";\nimport { fileImage, indexTransactionPlan } from \"./snapshot-transaction-plan.js\";\nimport type { SnapshotApplyPlan } from \"./snapshot-types.js\";\n\nconst JOURNAL_VERSION = 4;\ninterface TransactionEntry {\n target: string;\n /** Version 5: one physical file, original target spelling and intended installed spelling. */\n afterTarget?: string;\n backupName: string;\n kind: \"missing\" | \"file\" | \"directory\" | \"symlink\";\n linkTarget?: string;\n beforeImage?: string;\n afterImage?: string;\n postFiles?: { relative: string; image: string }[];\n /** Durable intent permits only a missing intermediate image, never unknown bytes. */\n removalPending?: boolean;\n /** Published before materialization: absence/partial trees can no longer prove an unstarted replacement. */\n replacementStarted?: boolean;\n /** Published before copying to a transaction-derived sibling staging path. */\n recoveryStaged?: boolean;\n}\ninterface TransactionJournal {\n version: number;\n /** Version 6: durable files are accepted; surviving evidence permits cleanup only. */\n completed?: boolean;\n root: string;\n sessionRoot?: string;\n /** Version 7: reviewed settings images authorize recovery from either transition root. */\n sessionRootTransition?: SessionRootTransition;\n entries: TransactionEntry[];\n}\ninterface TransactionOptions {\n sessionDir?: string;\n signal?: AbortSignal;\n validateMutation?: () => void;\n protectedTargets?: readonly string[];\n /** Fresh apply authorization only; recovery remains bound to durable journal images. */\n expectedPreimages?: ReadonlyMap<string, string>;\n resolveConfiguredSessionDir?: boolean;\n}\n\nexport async function applySnapshotTransaction(plan: SnapshotApplyPlan, options: TransactionOptions = {}) {\n options.validateMutation?.();\n await recoverPendingSnapshotTransactions(options);\n const coalesced = await coalesceCaseReplacements(path.resolve(agentDir()), plan);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n const targets = [...new Set([...coalesced.plan.deletes, ...coalesced.plan.writes.map((item) => item.target)])].sort();\n if (targets.length > 16_384)\n throw new Error(\"Snapshot transaction exceeds its target bound; review a smaller transfer.\");\n return withTargetQueues(targets, async () => {\n options.signal?.throwIfAborted();\n if (\n targets.some((target) =>\n options.protectedTargets?.some(\n (protectedTarget) =>\n mergePathIdentity(target) === mergePathIdentity(protectedTarget) ||\n isPathInside(mergePathIdentity(target), mergePathIdentity(protectedTarget)),\n ),\n )\n )\n throw new Error(\"Snapshot transaction targets the current session; review is required.\");\n for (const [before, after] of coalesced.replacements) {\n if ((await caseReplacementSpelling(before, after)) !== before)\n throw new Error(\"Case replacement changed before preparation; review is required.\");\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n }\n const originalTargets = new Map([...coalesced.replacements].map(([before, after]) => [after, before]));\n const expectedPreimages = new Map(\n [...(options.expectedPreimages ?? [])].map(([target, expected]) => [\n originalTargets.get(target) ?? target,\n expected,\n ]),\n );\n // A case-sensitive spelling replacement has two targets, unlike a coalesced physical alias.\n // Bind both the source bytes and destination absence/bytes before capturing their backups.\n for (const [target, expected] of options.expectedPreimages ?? []) {\n if (originalTargets.has(target)) continue;\n const variants = coalesced.plan.deletes.filter(\n (candidate) =>\n candidate !== target &&\n path.dirname(candidate) === path.dirname(target) &&\n mergePathIdentity(candidate) === mergePathIdentity(target),\n );\n if (variants.length > 1) throw new Error(\"Ambiguous reviewed file preimage spellings; review required.\");\n const original = variants[0];\n if (!original) continue;\n const destination = await image(target);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (destination !== \"missing\" && destination !== expected)\n throw new Error(\"Reviewed destination preimage changed before apply.\");\n expectedPreimages.set(original, expected);\n expectedPreimages.set(target, destination);\n }\n for (const [target, expected] of expectedPreimages) {\n const current = await image(target);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (current !== expected)\n throw new Error(\"Reviewed file preimage changed before apply; snapshot installation refused.\");\n }\n const transaction = await prepareTransaction(\n coalesced.plan,\n targets,\n { ...options, expectedPreimages },\n coalesced.replacements,\n );\n const entriesByTarget = new Map(\n transaction.journal.entries.flatMap((entry) => [\n [entry.target, entry] as const,\n ...(entry.afterTarget ? [[entry.afterTarget, entry] as const] : []),\n ]),\n );\n try {\n for (const target of transaction.deletes.sort((a, b) => a.length - b.length)) {\n options.signal?.throwIfAborted();\n const entry = entriesByTarget.get(target);\n if (!entry) throw new Error(\"Unowned transaction target.\");\n await removeOwnedTarget(transaction.directory, entry, transaction.journal, options);\n await syncDirectory(path.dirname(target));\n }\n await withCaseDestinationQueues([...coalesced.replacements], options, async () => {\n await retireRemovalIntent(\n transaction.directory,\n transaction.journal,\n transaction.journal.entries.filter(\n (entry) => entry.removalPending && (entry.afterImage !== \"missing\" || (entry.postFiles?.length ?? 0) > 0),\n ),\n options,\n );\n // Only this uninterrupted call knows which deleted writes have not attempted installation yet.\n const uninstalledWrites = new Set(transaction.deletedWrites);\n for (const item of plan.writes) {\n options.signal?.throwIfAborted();\n const entry = entriesByTarget.get(item.target);\n if (!entry) throw new Error(\"Unowned transaction target.\");\n const deletedByThisCall = uninstalledWrites.delete(entry.target);\n await verifyTarget(transaction.directory, entry, transaction.journal, deletedByThisCall);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await fs.mkdir(path.dirname(item.target), { recursive: true });\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n const temp = path.join(path.dirname(item.target), `.pi-sync.json.${randomUUID()}.apply`);\n try {\n let mode = 0o600;\n try {\n const stat = await fs.lstat(item.target);\n if (stat.isFile()) mode = stat.mode & 0o777;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n const handle = await fs.open(temp, \"wx\", mode);\n try {\n await handle.writeFile(item.content);\n await handle.sync();\n } finally {\n await handle.close();\n }\n await verifyTarget(transaction.directory, entry, transaction.journal, deletedByThisCall);\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n await fs.rename(temp, item.target);\n await syncDirectory(path.dirname(item.target));\n } finally {\n await fs.rm(temp, { force: true });\n }\n }\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await syncMutationParents(\n targets,\n [transaction.journal.root, ...(transaction.journal.sessionRoot ? [transaction.journal.sessionRoot] : [])],\n options,\n );\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n });\n } catch (error) {\n // Aborted owners cannot roll back files after another session has replaced them.\n if (options.signal?.aborted)\n throw new Error(\"Snapshot apply cancelled; guarded transaction evidence retained for review.\");\n // Additional spelling queues have been released: do not start a case rollback\n // under only the original key. Startup recovery reserves its own destination key.\n if (coalesced.replacements.size)\n throw new Error(\"Case replacement apply failed; guarded transaction evidence retained for review.\", {\n cause: error,\n });\n try {\n await restoreTransaction(transaction.directory, transaction.journal, options);\n } catch (recoveryError) {\n throw new AggregateError(\n [error, recoveryError],\n \"Snapshot apply failed and guarded recovery requires review. Transaction and backup retained; newer bytes were not restored over.\",\n );\n }\n throw error;\n }\n // Files are durably installed. Cleanup cannot roll back once it starts deleting evidence.\n await completeTransaction(transaction.directory, transaction.journal);\n });\n}\n\nexport async function recoverSnapshotTransactionsOnStartup(options: TransactionOptions = {}) {\n if (!(await pendingTransactionEntries()).some((entry) => entry.isDirectory())) return;\n // A pending settings.json may itself be the interrupted postimage. Read each journal\n // before consulting that file, and only consult it when a session target needs it.\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await withLock(\n \"recovery\",\n () => recoverPendingSnapshotTransactions({ ...options, resolveConfiguredSessionDir: true }),\n {\n reclaimStale: true,\n },\n );\n}\n\nexport async function recoverPendingSnapshotTransactions(options: TransactionOptions = {}) {\n for (const entry of (await pendingTransactionEntries()).sort((a, b) => a.name.localeCompare(b.name))) {\n if (!entry.isDirectory()) continue;\n const directory = path.join(transactionRoot(), entry.name);\n let journal: TransactionJournal;\n try {\n const file = path.join(directory, \"journal.json\");\n const stat = await fs.lstat(file);\n if (!stat.isFile() || stat.size > 32 * 1024 * 1024) throw new Error(\"Invalid journal file.\");\n journal = JSON.parse(await fs.readFile(file, \"utf8\")) as TransactionJournal;\n } catch (error) {\n // Unknown evidence is not disposable, including interrupted preparation directories.\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") continue;\n throw new Error(\"Cannot recover malformed pi-sync transaction; preserve private evidence for review.\");\n }\n let sessionDir = options.sessionDir;\n if (\n sessionDir === undefined &&\n options.resolveConfiguredSessionDir &&\n !journal.completed &&\n transactionHasSessionTargets(journal)\n ) {\n sessionDir = await configuredSessionDir();\n }\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (journal.sessionRootTransition && !journal.completed) {\n // Validate every path before consulting backup evidence under the recorded root.\n validateJournal(directory, journal, journal.sessionRoot);\n sessionDir = await resolveTransitionSessionRoot(\n directory,\n journal.root,\n journal.sessionRoot as string,\n journal.sessionRootTransition,\n journal.entries,\n path.resolve(sessionStorageRoot(journal.root, sessionDir)),\n options,\n );\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n }\n validateJournal(directory, journal, sessionDir);\n if (journal.completed) {\n await removeTransaction(directory);\n continue;\n }\n await withTargetQueues(journal.entries.map((entry) => entry.target).sort(), () =>\n restoreTransaction(directory, journal, { ...options, sessionDir }),\n );\n }\n}\n\nasync function pendingTransactionEntries() {\n try {\n return await fs.readdir(transactionRoot(), { withFileTypes: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n throw error;\n }\n}\n\nasync function prepareTransaction(\n plan: SnapshotApplyPlan,\n targets: string[],\n options: TransactionOptions,\n replacements = new Map<string, string>(),\n) {\n const { sessionDir } = options;\n const root = path.resolve(agentDir());\n const sessionRoot = sessionDir ? path.resolve(sessionStorageRoot(root, sessionDir)) : undefined;\n const indexed = indexTransactionPlan(plan, targets);\n const directory = path.join(transactionRoot(), randomUUID());\n const backupDirectory = path.join(directory, \"before\");\n await fs.mkdir(backupDirectory, { recursive: true, mode: 0o700 });\n const entries: TransactionEntry[] = [];\n for (const [index, target] of targets.entries()) {\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n assertAllowedTarget(root, sessionRoot, target);\n await assertSafeParents(root, sessionRoot, target);\n const entry: TransactionEntry = { target, backupName: `${index}`, kind: \"missing\" };\n if (replacements.has(target)) entry.afterTarget = replacements.get(target);\n const backup = path.join(backupDirectory, entry.backupName);\n try {\n const stat = await fs.lstat(target);\n if (stat.isSymbolicLink()) {\n entry.kind = \"symlink\";\n entry.linkTarget = await fs.readlink(target);\n } else if (stat.isDirectory()) {\n entry.kind = \"directory\";\n await fs.cp(target, backup, {\n recursive: true,\n dereference: false,\n verbatimSymlinks: true,\n preserveTimestamps: true,\n filter: () => {\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n return true;\n },\n });\n } else if (stat.isFile()) {\n entry.kind = \"file\";\n await fs.copyFile(target, backup);\n await fs.chmod(backup, stat.mode);\n } else throw new Error(\"Unsupported existing snapshot target.\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n }\n entry.beforeImage =\n entry.kind === \"symlink\"\n ? `symlink:${entry.linkTarget}`\n : entry.kind === \"missing\"\n ? \"missing\"\n : await image(backup, true);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n const expected = options.expectedPreimages?.get(target);\n if (expected !== undefined && entry.beforeImage !== expected)\n throw new Error(\"Reviewed file preimage changed during backup; private preparation evidence retained.\");\n if (entry.afterTarget) {\n if (entry.kind !== \"file\" || (await caseReplacementSpelling(target, entry.afterTarget)) !== target)\n throw new Error(\"Case replacement preimage changed during backup; evidence retained for review.\");\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n }\n entry.afterImage = indexed.writeImages.get(target) ?? \"missing\";\n entry.postFiles = indexed.postFiles.get(target) ?? [];\n entries.push(entry);\n }\n // File fsync does not persist the name linking each backup into this directory.\n await syncDirectory(backupDirectory);\n const effectiveRoot = sessionRoot ?? path.join(root, \"sessions\");\n const sessionRootTransition = await prepareSessionRootTransition(\n directory,\n root,\n effectiveRoot,\n entries,\n plan,\n options,\n );\n const journal: TransactionJournal = {\n version: sessionRootTransition ? 7 : replacements.size ? 5 : JOURNAL_VERSION,\n root,\n sessionRoot: sessionRootTransition ? effectiveRoot : sessionRoot,\n sessionRootTransition,\n entries,\n };\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n await writeJson(path.join(directory, \"journal.json\"), journal, { maxBytes: 32 * 1024 * 1024 });\n await syncDirectory(transactionRoot());\n await syncDirectory(stateDir());\n await syncDirectory(path.dirname(stateDir()));\n return { directory, journal, deletes: indexed.deletes, deletedWrites: indexed.deletedWrites };\n}\n\nasync function restoreTransaction(directory: string, journal: TransactionJournal, options: TransactionOptions) {\n validateJournal(directory, journal, options.sessionDir);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n for (const entry of journal.entries) {\n if (\n options.protectedTargets?.some(\n (target) =>\n mergePathIdentity(target) === mergePathIdentity(entry.target) ||\n isPathInside(mergePathIdentity(entry.target), mergePathIdentity(target)),\n )\n )\n throw new Error(\n \"Pending transaction touches the current session; resume a different session before guarded recovery.\",\n );\n await verifyTarget(directory, entry, journal);\n }\n // Recover copies left by a process crash even when the target is already restored.\n for (const entry of journal.entries) {\n if (!entry.recoveryStaged) continue;\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await assertSafeParents(journal.root, journal.sessionRoot, entry.target);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await fs.rm(recoveryStagePath(directory, entry), { recursive: true, force: true });\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n }\n // Verify the complete group before removing any path. Recheck each destructive boundary.\n for (const entry of [...journal.entries].sort((a, b) => a.target.length - b.target.length)) {\n const current = await verifyTarget(directory, entry, journal);\n const before = await beforeImage(directory, entry);\n const spellingMatches = async () =>\n !entry.afterTarget || (await caseReplacementSpelling(entry.target, entry.afterTarget)) === entry.target;\n if (current === before && (await spellingMatches())) continue;\n options.signal?.throwIfAborted();\n options.validateMutation?.();\n if (entry.kind === \"file\") {\n const temporary = await prepareRecoveryStage(directory, journal, entry, options);\n try {\n await fs.mkdir(path.dirname(entry.target), { recursive: true });\n await fs.copyFile(path.join(directory, \"before\", entry.backupName), temporary);\n // Windows requires write access to flush an existing regular file.\n const handle = await fs.open(temporary, process.platform === \"win32\" ? \"r+\" : \"r\");\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n const verified = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (verified === before && (await spellingMatches())) continue;\n const needsCaseQueue =\n entry.afterTarget !== undefined &&\n (await caseReplacementSpelling(entry.target, entry.afterTarget)) === entry.afterTarget;\n if (needsCaseQueue) {\n // Keep the installed-spelling queue while reserving the now-missing original spelling.\n await removeOwnedTarget(directory, entry, journal, options);\n } else if (\n verified.startsWith(\"directory:\") &&\n !(await removeOwnedTarget(directory, entry, journal, options, before))\n )\n continue;\n await withCaseDestinationQueues(\n needsCaseQueue && entry.afterTarget ? [[entry.afterTarget, entry.target]] : [],\n options,\n async () => {\n const atRename = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (atRename === before && (await spellingMatches())) return;\n await retireRestorationIntent(directory, journal, entry, options);\n const atInstall = await verifyTarget(directory, entry, journal, atRename === \"missing\");\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (atInstall === before && (await spellingMatches())) return;\n await fs.rename(temporary, entry.target);\n await syncDirectory(path.dirname(entry.target));\n },\n );\n } finally {\n await fs.rm(temporary, { force: true });\n }\n continue;\n }\n if (entry.kind === \"missing\") {\n await removeOwnedTarget(directory, entry, journal, options, before);\n continue;\n }\n const temporary = await prepareRecoveryStage(directory, journal, entry, options);\n try {\n await fs.mkdir(path.dirname(entry.target), { recursive: true });\n await assertSafeParents(journal.root, journal.sessionRoot, entry.target);\n if (entry.kind === \"directory\") {\n await fs.cp(path.join(directory, \"before\", entry.backupName), temporary, {\n recursive: true,\n dereference: false,\n verbatimSymlinks: true,\n preserveTimestamps: true,\n filter: () => {\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n return true;\n },\n });\n } else if (entry.linkTarget !== undefined) await fs.symlink(entry.linkTarget, temporary);\n if ((await image(temporary, true)) !== before)\n throw new Error(\"Staged recovery image differs from the backup; evidence retained.\");\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (!(await removeOwnedTarget(directory, entry, journal, options, before))) continue;\n const atRename = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (atRename === before) continue;\n await retireRestorationIntent(directory, journal, entry, options);\n const atInstall = await verifyTarget(directory, entry, journal, atRename === \"missing\");\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (atInstall === before) continue;\n await fs.rename(temporary, entry.target);\n await syncDirectory(path.dirname(entry.target));\n } finally {\n await fs.rm(temporary, { recursive: true, force: true });\n }\n }\n await syncMutationParents(\n journal.entries.map((entry) => entry.target),\n [journal.root, ...(journal.sessionRoot ? [journal.sessionRoot] : [])],\n options,\n );\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n await completeTransaction(directory, journal);\n}\n\nasync function verifyTarget(\n directory: string,\n entry: TransactionEntry,\n journal: TransactionJournal,\n deletedByThisCall = false,\n) {\n await assertSafeParents(journal.root, journal.sessionRoot, entry.target);\n // Hash the potentially large backup before observing the live target, not after it.\n const before = await beforeImage(directory, entry);\n if (journal.version >= 2 && before !== entry.beforeImage)\n throw new Error(\"Transaction backup changed; preserve evidence for review.\");\n if (entry.afterTarget) await caseReplacementSpelling(entry.target, entry.afterTarget);\n const current = await image(entry.target);\n if (current === before) return current;\n if (current === \"missing\") {\n if (deletedByThisCall || (journal.version >= 4 && entry.removalPending && !entry.replacementStarted))\n return current;\n } else if (\n journal.version >= 2 &&\n (current === entry.afterImage ||\n (await ownedPostTree(\n entry.target,\n entry.postFiles ?? [],\n journal.version < 4 || entry.replacementStarted === true || !entry.removalPending,\n )))\n )\n return current;\n throw new Error(\n \"Transaction target has unrecognized or newer bytes; automatic rollback refused. Preserve the transaction and review its backup with Pi closed.\",\n );\n}\n\nasync function removeOwnedTarget(\n directory: string,\n entry: TransactionEntry,\n journal: TransactionJournal,\n options: TransactionOptions,\n restoringBefore?: string,\n) {\n const current = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (restoringBefore !== undefined && current === restoringBefore) return false;\n // Persist intent before removal, including descendants affected by a recursive delete.\n // Until replacement is armed, interrupted removal can recognize absence without accepting unknown bytes.\n upgradeRemovalEvidence(journal);\n for (const affected of journal.entries) {\n if (affected.target === entry.target || isStrictlyInside(entry.target, affected.target)) {\n affected.removalPending = true;\n affected.replacementStarted = false;\n }\n }\n await writeJson(path.join(directory, \"journal.json\"), journal, { maxBytes: 32 * 1024 * 1024 });\n const verified = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (restoringBefore !== undefined && verified === restoringBefore) return false;\n await fs.rm(entry.target, { recursive: true, force: true });\n await syncDirectory(path.dirname(entry.target));\n return true;\n}\n\nfunction upgradeRemovalEvidence(journal: TransactionJournal) {\n if (journal.version < JOURNAL_VERSION) {\n // Old pending markers may already have survived a committed replacement.\n for (const entry of journal.entries) entry.removalPending = false;\n journal.version = JOURNAL_VERSION;\n }\n}\n\nasync function retireRemovalIntent(\n directory: string,\n journal: TransactionJournal,\n entries: TransactionEntry[],\n options: TransactionOptions,\n) {\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (!entries.length) return;\n upgradeRemovalEvidence(journal);\n for (const entry of entries) {\n entry.removalPending = false;\n entry.replacementStarted = true;\n }\n await writeJson(path.join(directory, \"journal.json\"), journal, { maxBytes: 32 * 1024 * 1024 });\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n}\n\nasync function retireRestorationIntent(\n directory: string,\n journal: TransactionJournal,\n entry: TransactionEntry,\n options: TransactionOptions,\n) {\n // Installing a complete parent preimage supersedes descendant replacement progress too.\n for (const child of journal.entries) {\n if (isStrictlyInside(entry.target, child.target)) {\n child.removalPending = false;\n child.replacementStarted = false;\n }\n }\n await retireRemovalIntent(directory, journal, [entry], options);\n}\n\nfunction recoveryStagePath(directory: string, entry: TransactionEntry) {\n const token = createHash(\"sha256\").update(directory).update(\"\\\\0\").update(entry.backupName).digest(\"hex\");\n return path.join(\n path.dirname(entry.target),\n `.pi-sync.json.${token}.${entry.kind === \"file\" ? \"restore\" : \"restore-tree\"}`,\n );\n}\n\nasync function prepareRecoveryStage(\n directory: string,\n journal: TransactionJournal,\n entry: TransactionEntry,\n options: TransactionOptions,\n) {\n const temporary = recoveryStagePath(directory, entry);\n if (!entry.recoveryStaged) {\n try {\n await fs.lstat(temporary);\n throw new Error(\"Unowned recovery staging path; preserve evidence for review.\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n entry.recoveryStaged = true;\n await writeJson(path.join(directory, \"journal.json\"), journal, { maxBytes: 32 * 1024 * 1024 });\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n }\n return temporary;\n}\n\nasync function beforeImage(directory: string, entry: TransactionEntry) {\n if (entry.kind === \"missing\") return \"missing\";\n if (entry.kind === \"symlink\") return `symlink:${entry.linkTarget}`;\n const value = await image(path.join(directory, \"before\", entry.backupName));\n if (value === \"missing\") throw new Error(\"Transaction backup is missing; preserve evidence for review.\");\n return value;\n}\nasync function image(target: string, durable = false): Promise<string> {\n let stat: Stats;\n try {\n stat = await fs.lstat(target);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\") return \"missing\";\n throw error;\n }\n if (stat.isSymbolicLink()) return `symlink:${await fs.readlink(target)}`;\n if (stat.isFile()) {\n const content = await fs.readFile(target);\n if (durable) {\n // Keep POSIX read-only backup permissions; Windows flushing requires write access.\n const handle = await fs.open(target, process.platform === \"win32\" ? \"r+\" : \"r\");\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n }\n return fileImage(content);\n }\n if (!stat.isDirectory()) throw new Error(\"Unsupported transaction image.\");\n const entries = [];\n for (const name of (await fs.readdir(target)).sort())\n entries.push([name, await image(path.join(target, name), durable)]);\n if (durable) await syncDirectory(target);\n return `directory:${createHash(\"sha256\").update(JSON.stringify(entries)).digest(\"hex\")}`;\n}\nasync function ownedPostTree(target: string, files: { relative: string; image: string }[], requireComplete: boolean) {\n if (!files.length) return false;\n const expected = new Map(files.map((file) => [mergePathIdentity(file.relative), file.image]));\n const prefixes = new Set<string>();\n for (const relative of expected.keys()) {\n for (\n let parent = path.dirname(relative);\n parent !== \".\" && parent !== path.dirname(parent);\n parent = path.dirname(parent)\n )\n prefixes.add(parent);\n }\n const seen = new Set<string>();\n async function visit(directory: string): Promise<boolean> {\n let stat: Stats;\n try {\n stat = await fs.lstat(directory);\n } catch {\n return false;\n }\n if (!stat.isDirectory() || stat.isSymbolicLink()) return false;\n for (const name of await fs.readdir(directory)) {\n const child = path.join(directory, name);\n const relative = mergePathIdentity(path.relative(target, child));\n const stat = await fs.lstat(child);\n if (stat.isDirectory() && !stat.isSymbolicLink()) {\n if (!prefixes.has(relative) || !(await visit(child))) return false;\n } else {\n if (expected.get(relative) !== (await image(child))) return false;\n seen.add(relative);\n }\n }\n return true;\n }\n return (await visit(target)) && (!requireComplete || [...expected.keys()].every((key) => seen.has(key)));\n}\n\nfunction validateJournal(directory: string, journal: TransactionJournal, sessionDir?: string) {\n if (\n ![1, 2, 3, 4, 5, 6, 7].includes(journal.version) ||\n !Array.isArray(journal.entries) ||\n journal.entries.length > 16_384\n )\n throw new Error(\"Unsupported pi-sync transaction journal; preserve evidence for review.\");\n if (journal.completed !== undefined && (![6, 7].includes(journal.version) || journal.completed !== true))\n throw new Error(\"Invalid transaction completion evidence.\");\n const root = path.resolve(agentDir());\n if (typeof journal.root !== \"string\" || path.resolve(journal.root) !== root)\n throw new Error(\"Transaction root no longer matches the Pi agent directory.\");\n if (journal.sessionRootTransition !== undefined) {\n if (journal.version !== 7 || typeof journal.sessionRoot !== \"string\")\n throw new Error(\"Invalid session root-transition version.\");\n validateSessionRootTransition(journal.sessionRootTransition);\n } else if (journal.version === 7) throw new Error(\"Missing session root-transition evidence.\");\n const trustedSessionRoot = sessionDir\n ? path.resolve(sessionStorageRoot(root, sessionDir))\n : path.join(root, \"sessions\");\n if (\n journal.sessionRoot !== undefined &&\n (typeof journal.sessionRoot !== \"string\" ||\n !path.isAbsolute(journal.sessionRoot) ||\n path.resolve(journal.sessionRoot) !== journal.sessionRoot ||\n (!journal.completed && transactionHasSessionTargets(journal) && journal.sessionRoot !== trustedSessionRoot))\n )\n throw new Error(\"Transaction session root is not owned by this context; preserve evidence for review.\");\n for (const entry of journal.entries) {\n if (\n !entry ||\n typeof entry.target !== \"string\" ||\n !path.isAbsolute(entry.target) ||\n path.resolve(entry.target) !== entry.target ||\n typeof entry.backupName !== \"string\" ||\n !/^\\d+$/u.test(entry.backupName) ||\n ![\"missing\", \"file\", \"directory\", \"symlink\"].includes(entry.kind)\n )\n throw new Error(\"Invalid pi-sync transaction entry.\");\n assertWithinRoot(directory, path.join(directory, \"before\", entry.backupName));\n assertAllowedTarget(root, journal.sessionRoot, entry.target);\n if (\n entry.afterTarget !== undefined &&\n (![5, 6, 7].includes(journal.version) ||\n typeof entry.afterTarget !== \"string\" ||\n !isCaseReplacement(root, entry.target, entry.afterTarget) ||\n path.resolve(entry.afterTarget) !== entry.afterTarget ||\n entry.kind !== \"file\")\n )\n throw new Error(\"Invalid transaction case replacement evidence.\");\n if (entry.afterTarget) assertAllowedTarget(root, journal.sessionRoot, entry.afterTarget);\n if (\n journal.version >= 2 &&\n ((entry.beforeImage === undefined ? !journal.completed : typeof entry.beforeImage !== \"string\") ||\n (entry.afterImage === undefined ? !journal.completed : typeof entry.afterImage !== \"string\") ||\n (entry.postFiles === undefined ? !journal.completed : !Array.isArray(entry.postFiles)))\n )\n throw new Error(\"Invalid transaction postimage evidence.\");\n if (entry.recoveryStaged !== undefined && typeof entry.recoveryStaged !== \"boolean\")\n throw new Error(\"Invalid recovery staging evidence.\");\n if (entry.removalPending !== undefined && (journal.version < 3 || typeof entry.removalPending !== \"boolean\"))\n throw new Error(\"Invalid transaction removal evidence.\");\n if (\n entry.replacementStarted !== undefined &&\n (journal.version < 4 || typeof entry.replacementStarted !== \"boolean\")\n )\n throw new Error(\"Invalid transaction replacement evidence.\");\n if (entry.removalPending && entry.replacementStarted)\n throw new Error(\"Conflicting transaction replacement evidence.\");\n for (const file of entry.postFiles ?? []) {\n if (\n typeof file.relative !== \"string\" ||\n typeof file.image !== \"string\" ||\n !isStrictlyInside(entry.target, path.resolve(entry.target, file.relative))\n )\n throw new Error(\"Invalid transaction subtree evidence.\");\n }\n }\n}\nfunction transactionHasSessionTargets(journal: TransactionJournal) {\n const root = path.resolve(agentDir());\n return (\n Array.isArray(journal.entries) &&\n journal.entries.some(\n (entry) =>\n typeof entry?.target === \"string\" &&\n (!isPathInside(root, entry.target) ||\n isPathInside(path.join(root, \"sessions\"), entry.target) ||\n (typeof journal.sessionRoot === \"string\" && isPathInside(journal.sessionRoot, entry.target))),\n )\n );\n}\nfunction isStrictlyInside(root: string, target: string) {\n return path.relative(path.resolve(root), path.resolve(target)) !== \"\" && isPathInside(root, target);\n}\n\nfunction assertAllowedTarget(root: string, sessionRoot: string | undefined, target: string) {\n const resolved = path.resolve(target);\n if (isStrictlyInside(root, resolved)) {\n if (isDeniedPath(path.relative(root, resolved))) throw new Error(\"Transaction targets denied private storage.\");\n assertWithinRoot(root, resolved);\n return;\n }\n if (sessionRoot && isStrictlyInside(sessionRoot, resolved)) {\n if (isDeniedPath(`sessions/${path.relative(sessionRoot, resolved)}`))\n throw new Error(\"Transaction targets denied session storage.\");\n assertWithinRoot(sessionRoot, resolved);\n return;\n }\n throw new Error(\"Transaction target is outside configured roots.\");\n}\nasync function assertSafeParents(root: string, sessionRoot: string | undefined, target: string) {\n assertAllowedTarget(root, sessionRoot, target);\n const boundary = isPathInside(root, target) ? root : sessionRoot;\n for (\n let parent = path.dirname(target);\n boundary && mergePathIdentity(parent) !== mergePathIdentity(boundary);\n parent = path.dirname(parent)\n ) {\n if (path.dirname(parent) === parent) throw new Error(\"Transaction parent did not reach its owned boundary.\");\n try {\n const stat = await fs.lstat(parent);\n if ((!stat.isDirectory() && !stat.isFile()) || stat.isSymbolicLink())\n throw new Error(\"Unsafe transaction parent.\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n }\n }\n}\nasync function withTargetQueues<T>(targets: string[], action: () => Promise<T>) {\n const keys = new Set<string>();\n for (const target of targets) {\n let key = path.resolve(target);\n try {\n key = await fs.realpath(target);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") throw error;\n }\n if (keys.has(key)) throw new Error(\"Transaction targets alias the same file.\");\n keys.add(key);\n }\n async function acquire(index: number): Promise<T> {\n const target = targets[index];\n return target ? withFileMutationQueue(target, () => acquire(index + 1)) : action();\n }\n return acquire(0);\n}\nasync function withCaseDestinationQueues<T>(\n spellings: readonly (readonly [string, string])[],\n options: TransactionOptions,\n action: () => Promise<T>,\n): Promise<T> {\n if (!spellings.length) return action();\n const requireAbsent = async () => {\n for (const [before, after] of spellings) {\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n const spelling = await caseReplacementSpelling(before, after);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (spelling !== undefined)\n throw new Error(\"Case replacement changed before destination queue reservation; evidence retained.\");\n }\n };\n // Existing aliases share one non-reentrant realpath queue. Only after removal can\n // we reserve the distinct missing spelling while retaining the original queue.\n // Pi writers that registered in the gap finish before this callback; refuse their\n // bytes, including recognizable pre/postimages, rather than treating them as ours.\n await requireAbsent();\n return withTargetQueues(\n spellings.map(([, after]) => after),\n async () => {\n await requireAbsent();\n return action();\n },\n );\n}\nasync function completeTransaction(directory: string, journal: TransactionJournal) {\n // Publish completion before deleting any backup. A surviving journal after power loss\n // may only retry cleanup, never roll back already accepted files.\n await writeJson(\n path.join(directory, \"journal.json\"),\n { ...journal, version: journal.sessionRootTransition ? 7 : 6, completed: true },\n {\n maxBytes: 32 * 1024 * 1024,\n },\n );\n await removeTransaction(directory);\n}\nasync function removeTransaction(directory: string) {\n await fs.rm(directory, { recursive: true, force: true });\n // After evidence deletion, failure cannot safely trigger rollback or withhold acceptance.\n // A failed cleanup fsync may leave obsolete evidence after power loss; live file durability\n // was established before cleanup; a surviving completed journal allows only cleanup.\n await syncDirectory(transactionRoot()).catch(() => {});\n}\nfunction transactionRoot() {\n return path.join(stateDir(), \"transactions\");\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { SnapshotApplyPlan } from \"./snapshot-types.js\";\n\n/** Only the top-level file correction produced by addTopLevelCaseVariantDeletes is eligible. */\nexport function isCaseReplacement(root: string, before: string, after: string) {\n return (\n before !== after &&\n path.dirname(before) === root &&\n path.dirname(after) === root &&\n path.basename(before).toLowerCase() === path.basename(after).toLowerCase()\n );\n}\n\n/** Absence is handled by the journal's removal/replacement evidence, never by naming evidence. */\nexport async function caseReplacementSpelling(before: string, after: string): Promise<string | undefined> {\n const observations = await Promise.all(\n [before, after].map(async (target) => {\n try {\n const stat = await fs.lstat(target);\n if (!stat.isFile() || stat.nlink !== 1) throw new Error(\"Unsafe case replacement target.\");\n return await fs.realpath(target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n }),\n );\n if (observations.every((value) => value === undefined)) return undefined;\n if (!observations[0] || observations[0] !== observations[1])\n throw new Error(\"Case replacement no longer identifies one physical file; preserve evidence for review.\");\n const names = (await fs.readdir(path.dirname(before))).filter(\n (name) => name.toLowerCase() === path.basename(before).toLowerCase(),\n );\n if (names.length !== 1 || (names[0] !== path.basename(before) && names[0] !== path.basename(after)))\n throw new Error(\"Case replacement spelling changed; preserve evidence for review.\");\n return path.join(path.dirname(before), names[0]);\n}\n\nexport async function coalesceCaseReplacements(root: string, plan: SnapshotApplyPlan) {\n const replacements = new Map<string, string>();\n const deletesByCase = new Map<string, string[]>();\n const writeTargets = new Set(plan.writes.map((item) => item.target));\n for (const target of new Set(plan.deletes)) {\n if (path.dirname(target) !== root || writeTargets.has(target)) continue;\n const key = path.basename(target).toLowerCase();\n const group = deletesByCase.get(key) ?? [];\n group.push(target);\n deletesByCase.set(key, group);\n }\n for (const item of plan.writes) {\n if (path.dirname(item.target) !== root) continue;\n const candidates = deletesByCase.get(path.basename(item.target).toLowerCase()) ?? [];\n if (candidates.length !== 1) continue;\n const before = candidates[0];\n if (!before || !isCaseReplacement(root, before, item.target)) continue;\n // Different real paths on a case-sensitive filesystem remain independent targets.\n let beforePath: string;\n let afterPath: string;\n try {\n [beforePath, afterPath] = await Promise.all([fs.realpath(before), fs.realpath(item.target)]);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") continue;\n throw error;\n }\n if (beforePath !== afterPath) continue;\n if (replacements.has(before)) throw new Error(\"Multiple writes alias a case replacement target.\");\n if ((await caseReplacementSpelling(before, item.target)) !== before)\n throw new Error(\"Case replacement preimage spelling changed; review is required.\");\n replacements.set(before, item.target);\n }\n const beforeByAfter = new Map([...replacements].map(([before, after]) => [after, before]));\n return {\n replacements,\n plan: {\n deletes: plan.deletes,\n writes: plan.writes.map((item) => ({ ...item, target: beforeByAfter.get(item.target) ?? item.target })),\n },\n };\n}\n", "import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { isPathInside } from \"../paths.js\";\nimport { syncDirectory } from \"../state/json-file.js\";\nimport { expandSessionDir } from \"./session-paths.js\";\nimport { sessionStorageRoot } from \"./snapshot-paths.js\";\nimport { fileImage } from \"./snapshot-transaction-plan.js\";\nimport type { SnapshotApplyPlan } from \"./snapshot-types.js\";\n\nexport interface SessionRootTransition {\n beforeRoot: string;\n /** null is a verified missing postimage, never an empty settings file. */\n settingsAfterBase64?: string | null;\n /** Reviewed bytes live in a private fsynced sidecar, pinned by the entry afterImage. */\n settingsAfterFile?: true;\n}\ninterface TransitionGuards {\n signal?: AbortSignal;\n validateMutation?: () => void;\n}\nfunction validateOwner(guards: TransitionGuards) {\n guards.validateMutation?.();\n guards.signal?.throwIfAborted();\n}\ninterface SettingsEntry {\n target: string;\n afterTarget?: string;\n backupName: string;\n kind: string;\n beforeImage?: string;\n afterImage?: string;\n}\n\nfunction rootFromSettings(root: string, bytes: Buffer) {\n let settings: unknown;\n try {\n settings = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes));\n } catch {\n throw new Error(\"Invalid settings root-transition evidence.\");\n }\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings))\n throw new Error(\"Invalid settings root-transition evidence.\");\n const value = (settings as { sessionDir?: unknown }).sessionDir;\n if (value !== undefined && typeof value !== \"string\") throw new Error(\"Invalid settings root-transition evidence.\");\n return path.resolve(sessionStorageRoot(root, value ? expandSessionDir(value) : undefined));\n}\n\nasync function beforeRoot(directory: string, root: string, entry: SettingsEntry, guards: TransitionGuards) {\n validateOwner(guards);\n if (entry.kind === \"missing\" && entry.beforeImage === \"missing\") return path.join(root, \"sessions\");\n if (entry.kind !== \"file\") throw new Error(\"Root transition requires regular settings preimage evidence.\");\n const backup = path.join(directory, \"before\", entry.backupName);\n const stat = await fs.lstat(backup);\n validateOwner(guards);\n if (!stat.isFile()) throw new Error(\"Invalid settings root-transition backup.\");\n const bytes = await fs.readFile(backup);\n validateOwner(guards);\n if (fileImage(bytes) !== entry.beforeImage) throw new Error(\"Changed settings root-transition backup.\");\n return rootFromSettings(root, bytes);\n}\n\nexport async function prepareSessionRootTransition(\n directory: string,\n root: string,\n sessionRoot: string,\n entries: SettingsEntry[],\n plan: SnapshotApplyPlan,\n guards: TransitionGuards = {},\n): Promise<SessionRootTransition | undefined> {\n const settingsTarget = path.join(root, \"settings.json\");\n const entry = entries.find((item) => item.target === settingsTarget || item.afterTarget === settingsTarget);\n const write = plan.writes.find((item) => item.target === settingsTarget || item.target === entry?.target);\n if (!entry || !entries.some((item) => item !== entry && isPathInside(sessionRoot, item.target))) return undefined;\n const deleted = !write && plan.deletes.includes(entry.target) && entry.afterImage === \"missing\";\n if (!write && !deleted) return undefined;\n const afterRoot = write ? rootFromSettings(root, write.content) : path.join(root, \"sessions\");\n // An explicit context root is not a settings-driven transition.\n if (afterRoot !== sessionRoot) return undefined;\n const previous = await beforeRoot(directory, root, entry, guards);\n if (previous === sessionRoot) return undefined;\n if (write && fileImage(write.content) !== entry.afterImage) throw new Error(\"Changed settings transition postimage.\");\n if (!write) return { beforeRoot: previous, settingsAfterBase64: null };\n validateOwner(guards);\n const handle = await fs.open(path.join(directory, \"settings-after\"), \"wx\", 0o600);\n try {\n validateOwner(guards);\n await handle.writeFile(write.content);\n validateOwner(guards);\n await handle.sync();\n validateOwner(guards);\n } finally {\n await handle.close();\n }\n await syncDirectory(directory);\n validateOwner(guards);\n return { beforeRoot: previous, settingsAfterFile: true };\n}\n\nexport function validateSessionRootTransition(value: SessionRootTransition) {\n if (\n !value ||\n typeof value.beforeRoot !== \"string\" ||\n !path.isAbsolute(value.beforeRoot) ||\n path.resolve(value.beforeRoot) !== value.beforeRoot ||\n (value.settingsAfterFile !== undefined && value.settingsAfterFile !== true) ||\n (value.settingsAfterFile === true\n ? value.settingsAfterBase64 !== undefined\n : value.settingsAfterBase64 !== null &&\n (typeof value.settingsAfterBase64 !== \"string\" ||\n value.settingsAfterBase64.length > 32 * 1024 * 1024 ||\n Buffer.from(value.settingsAfterBase64, \"base64\").toString(\"base64\") !== value.settingsAfterBase64))\n )\n throw new Error(\"Invalid session root-transition evidence.\");\n}\n\n/** Authorization is bound to both settings images, never just an arbitrary pinned root. */\nexport async function resolveTransitionSessionRoot(\n directory: string,\n root: string,\n sessionRoot: string,\n transition: SessionRootTransition,\n entries: SettingsEntry[],\n currentRoot: string,\n guards: TransitionGuards = {},\n) {\n const settingsTarget = path.join(root, \"settings.json\");\n const entry = entries.find((item) => item.target === settingsTarget || item.afterTarget === settingsTarget);\n if (!entry) throw new Error(\"Missing settings root-transition evidence.\");\n let after: Buffer | undefined;\n if (transition.settingsAfterFile) {\n const file = path.join(directory, \"settings-after\");\n const stat = await fs.lstat(file);\n validateOwner(guards);\n if (\n !stat.isFile() ||\n stat.isSymbolicLink() ||\n stat.nlink !== 1 ||\n (process.platform !== \"win32\" && (stat.mode & 0o077) !== 0)\n )\n throw new Error(\"Unsafe settings root-transition postimage.\");\n after = await fs.readFile(file);\n validateOwner(guards);\n } else if (transition.settingsAfterBase64 !== null)\n after = Buffer.from(transition.settingsAfterBase64 as string, \"base64\");\n if (\n (after ? fileImage(after) : \"missing\") !== entry.afterImage ||\n (after ? rootFromSettings(root, after) : path.join(root, \"sessions\")) !== sessionRoot ||\n (await beforeRoot(directory, root, entry, guards)) !== transition.beforeRoot\n )\n throw new Error(\"Inconsistent settings root-transition evidence.\");\n if (currentRoot !== transition.beforeRoot && currentRoot !== sessionRoot)\n throw new Error(\"Transaction session root is not owned by this context; preserve evidence for review.\");\n return sessionRoot;\n}\n", "import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport { isPathInside } from \"../paths.js\";\nimport type { SnapshotApplyPlan } from \"./snapshot-types.js\";\n\nexport function fileImage(content: Buffer) {\n return `file:${createHash(\"sha256\").update(content).digest(\"hex\")}`;\n}\n\n/** Work follows path depth and emitted evidence, not every target/write pair. */\nexport function indexTransactionPlan(plan: SnapshotApplyPlan, targets: readonly string[]) {\n const targetIndex = indexTargets(targets);\n const writeImages = new Map<string, string>();\n const postFiles = new Map(targets.map((target) => [target, [] as { relative: string; image: string }[]]));\n for (const write of plan.writes) {\n const image = fileImage(write.content);\n // Preserve the first exact write and the original descendant order, including duplicates.\n if (!writeImages.has(write.target)) writeImages.set(write.target, image);\n for (const ancestor of ancestorTargets(write.target, targetIndex, false)) {\n if (ancestor !== write.target && isStrictDescendant(ancestor, write.target)) {\n postFiles.get(ancestor)?.push({ relative: path.relative(ancestor, write.target), image });\n }\n }\n }\n const deleteIndex = indexTargets(plan.deletes);\n const deletes = plan.deletes.filter((target) => {\n for (const ancestor of ancestorTargets(target, deleteIndex, false)) {\n if (ancestor !== target && isStrictDescendant(ancestor, target)) return false;\n }\n return true;\n });\n const deletedWrites = new Set<string>();\n const outerDeleteIndex = indexTargets(deletes);\n for (const write of plan.writes) {\n for (const ancestor of ancestorTargets(write.target, outerDeleteIndex)) {\n if (ancestor === write.target || isPathInside(ancestor, write.target)) {\n deletedWrites.add(write.target);\n break;\n }\n }\n }\n return { writeImages, postFiles, deletes, deletedWrites };\n}\n\nfunction isStrictDescendant(parent: string, target: string) {\n return path.relative(path.resolve(parent), path.resolve(target)) !== \"\" && isPathInside(parent, target);\n}\n\nfunction pathKey(target: string) {\n const resolved = path.resolve(target);\n return process.platform === \"win32\" ? resolved.toLowerCase() : resolved;\n}\n\nfunction indexTargets(targets: readonly string[]) {\n const index = new Map<string, string[]>();\n for (const target of new Set(targets)) {\n const key = pathKey(target);\n const rows = index.get(key) ?? [];\n rows.push(target);\n index.set(key, rows);\n }\n return index;\n}\n\nfunction* ancestorTargets(target: string, index: Map<string, string[]>, includeSelf = true) {\n const resolved = path.resolve(target);\n // Strict-descendant queries skip the same-address bucket, including native case aliases.\n for (let ancestor = includeSelf ? resolved : path.dirname(resolved); ; ancestor = path.dirname(ancestor)) {\n yield* index.get(pathKey(ancestor)) ?? [];\n if (path.dirname(ancestor) === ancestor) return;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["root", "createHash", "fs", "path", "path", "fs", "path", "path", "image", "path", "path", "fs", "path", "fs", "entry", "temporary", "createHash", "stat"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/paths.ts", "../../src/state/json-file.ts"],
4
- "sourcesContent": ["import path from \"node:path\";\n\nexport function isDeniedPath(relativePath: string) {\n const normalized = toPosix(relativePath);\n const lower = normalized.toLowerCase();\n const segments = lower.split(\"/\");\n const base = path.posix.basename(lower);\n return (\n segments.includes(\"node_modules\") ||\n segments.includes(\".git\") ||\n segments.includes(\".pisync\") ||\n segments.includes(\"pi-sync\") ||\n segments.includes(\".pi-sync-state-migration.lock\") ||\n base === \".env\" ||\n base.startsWith(\".env.\") ||\n base.endsWith(\".env\") ||\n base.includes(\"secret\") ||\n base.includes(\"token\") ||\n base === \"pi-sync.json\" ||\n base.startsWith(\"pi-sync.json.\") ||\n base.startsWith(\".pi-sync.json.\") ||\n base === \"pi-sync.local.json\" ||\n base.startsWith(\"pi-sync.local.json.\") ||\n base.startsWith(\".pi-sync.local.json.\")\n );\n}\n\nexport function isPathInside(parent: string, child: string) {\n const relative = path.relative(path.resolve(parent), path.resolve(child));\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nexport function safeJoin(root: string, relativePath: string) {\n const target = path.resolve(root, relativePath);\n assertWithinRoot(root, target, relativePath);\n return target;\n}\n\nexport function assertWithinRoot(root: string, target: string, label = target) {\n const resolvedRoot = path.resolve(root);\n const resolvedTarget = path.resolve(target);\n if (resolvedTarget !== resolvedRoot && !resolvedTarget.startsWith(`${resolvedRoot}${path.sep}`)) {\n throw new Error(`Unsafe path in snapshot: ${label}`);\n }\n}\n\nexport function encodeKey(key: string) {\n return key.split(\"/\").map(encodeURIComponent).join(\"/\");\n}\n\nexport function posixJoin(...parts: string[]) {\n return parts\n .map((part) => trimSlashes(part))\n .filter(Boolean)\n .join(\"/\");\n}\n\nexport function parentPaths(relativePath: string) {\n const results: string[] = [];\n let index = relativePath.lastIndexOf(\"/\");\n while (index > 0) {\n results.push(relativePath.slice(0, index));\n index = relativePath.lastIndexOf(\"/\", index - 1);\n }\n return results;\n}\n\nexport function toPosix(value: string) {\n return value.split(path.sep).join(\"/\");\n}\n\nfunction trimSlashes(value: string) {\n return value.replace(/^\\/+|\\/+$/g, \"\");\n}\n\nexport function safeName(value: string) {\n return value.replace(/[^A-Za-z0-9._-]/g, \"_\");\n}\n", "import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport async function readJsonIfExists<T>(filePath: string): Promise<T | undefined> {\n try {\n return JSON.parse(await fs.readFile(filePath, \"utf8\")) as T;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n}\n\nexport async function writeJson(filePath: string, value: unknown, options: { maxBytes?: number } = {}) {\n const content = `${JSON.stringify(value, null, \"\\t\")}\\n`;\n if (options.maxBytes !== undefined && Buffer.byteLength(content) > options.maxBytes)\n throw new Error(\n \"Private state document exceeds its storage bound; preserve existing evidence and use reviewed recovery.\",\n );\n await fs.mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 });\n const temp = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n const handle = await fs.open(temp, \"wx\", 0o600);\n try {\n await handle.writeFile(content);\n await handle.sync();\n } finally {\n await handle.close();\n }\n if (process.platform !== \"win32\") await fs.chmod(temp, 0o600);\n await fs.rename(temp, filePath);\n await syncDirectory(path.dirname(filePath));\n } finally {\n await fs.rm(temp, { force: true });\n }\n}\n\n/** POSIX rename/unlink durability; Windows does not expose directory fsync through Node. */\nexport async function syncDirectory(directory: string) {\n if (process.platform === \"win32\") return;\n const handle = await fs.open(directory, \"r\");\n try {\n await handle.sync();\n } finally {\n await handle.close();\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["path"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/ui/remote-selection-ui.ts", "../../src/ui/cancellable-operation.ts"],
4
- "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport {\n loadConfig,\n loadPartialConfig,\n type SyncSetupStorageReview,\n syncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { throwIfAborted } from \"../sync/signals.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport { type RunRoute, type RunRouteResult, runCancellableOperation } from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n try {\n let decision = options.decision;\n if (!decision) {\n const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n if (!inspected || signal?.aborted) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n );\n if (result.kind !== \"refresh\") return result;\n const refreshed = await runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n );\n if (!refreshed || signal?.aborted) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (signal?.aborted) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationReview: PartialConfig | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const currentConfig = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n const acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal },\n );\n if (signal.aborted) return { kind: \"close\" as const };\n if (!acknowledged) return { kind: \"stay\" as const };\n }\n const review = await runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, signal, factory);\n if (signal.aborted) throw signal.reason;\n await revalidateAndAdopt(loaded, state.decision, signal);\n return loaded;\n });\n if (signal.aborted) return { kind: \"close\" as const };\n options.onSelectionResolved?.();\n continuationReview = {\n ...review.storageReview,\n setupName: state.decision.setupName,\n include: [...state.decision.remoteInclude],\n automatic: review.config.automatic,\n automaticTransfer: review.config.automaticTransfer,\n agentMode: review.config.agentMode,\n continuous: review.config.continuous,\n onSwitch: review.config.onSwitch,\n showStatus: review.config.showStatus,\n };\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadPartialConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n if (!sameContinuationReview(latest, continuationReview)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent: () => !sessionSignal?.aborted,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n storageReview: SyncSetupStorageReview;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n assertLocalSelectionCurrent(config, decision);\n const partial = await loadPartialConfig(decision.setupName);\n throwIfAborted(signal);\n if (!sameSyncInclude(partial.include, decision.localInclude)) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n );\n }\n const backend = await factory(config);\n throwIfAborted(signal);\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(review: AdoptionReview, decision: RemoteSelectionDecision, signal: AbortSignal) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => ({\n ...setup,\n sync: { ...setup.sync, include: [...decision.remoteInclude] },\n }),\n {\n expectedStorage: review.storageReview,\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n return (\n left.setupName === right.setupName &&\n left.connectionName === right.connectionName &&\n left.storageKind === right.storageKind &&\n left.storagePath === right.storagePath &&\n left.bucket === right.bucket &&\n left.branch === right.branch &&\n Boolean(left.agentMode) === Boolean(right.agentMode) &&\n Boolean(left.continuous) === Boolean(right.continuous) &&\n sameSyncInclude(left.include, right.include)\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { isKeyRelease, Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n onDialog?: (active: boolean) => void,\n retryRefusal?: boolean,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelAcrossDialogs?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const {\n commitAware = false,\n cancelAcrossDialogs = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n target,\n signal,\n } = options;\n if (ctx.mode !== \"tui\") {\n return (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n }\n let commitStarted = false;\n let routeResult: RunRouteResult | undefined;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted,\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const cancel = (data: string) => {\n // Raw terminal listeners run before Pi filters Kitty key releases.\n if (isKeyRelease(data)) return false;\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) return false;\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n } else complete({ cancelled: true });\n return true;\n };\n // Pi dialogs replace this loader and restore the normal editor. Defer\n // ordinary keys while they are open; retain raw cancellation afterward.\n // Ctrl+C remains the root flow's hard-cancel path regardless of focus.\n let activeDialogs = 0;\n const unsubscribe = cancelAcrossDialogs\n ? ctx.ui.onTerminalInput((data) => {\n if (isKeyRelease(data)) return;\n if (activeDialogs > 0 && !matchesKey(data, Key.ctrl(\"c\"))) return;\n return cancel(data) ? { consume: true } : undefined;\n })\n : undefined;\n let pendingRoute: ReturnType<RunRoute>;\n try {\n pendingRoute = runRoute(\n route,\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n target,\n cancelAcrossDialogs\n ? (active) => {\n activeDialogs += active ? 1 : -1;\n }\n : undefined,\n );\n } catch (error) {\n unsubscribe?.();\n loader.dispose();\n throw error;\n }\n const operation = pendingRoute.then(\n (result) => {\n routeResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n if (width <= 0) return [];\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput: cancel,\n dispose() {\n unsubscribe?.();\n loader.dispose();\n },\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return routeResult ?? { kind: \"failed\" };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,YAAY,eAAe;;;ACDpC,SAAS,sBAA6C;AACtD,SAAS,cAAc,KAAK,YAAY,uBAAuB;AAC/D,SAAS,wBAAwB,4BAA4B;AA8B7D,eAAsB,wBACpB,KACA,SACA,OACA,UACA,UAAuC,CAAC,GACH;AACrC,QAAM;AAAA,IACJ,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,IAAI,SAAS,OAAO;AACtB,WAAQ,MAAM,SAAS,OAAO,QAAQ,QAAW,MAAM,KAAM,EAAE,MAAM,SAAS;AAAA,EAChF;AACA,MAAI,gBAAgB;AACpB,MAAI;AACJ,QAAM,cAAc,MAAM,qBAAiF,KAAK;AAAA,IAC9G;AAAA,IACA,WAAW,MAAM,CAAC,QAAQ;AAAA,IAC1B,QAAQ,CAAC,EAAE,KAAK,OAAO,aAAa,QAAQ,mBAAmB,SAAS,MAAM;AAC5E,YAAM,SAAS,IAAI,eAAe,KAAK,OAAO,SAAS,EAAE,aAAa,MAAM,CAAC;AAC7E,YAAM,aAAa,uBAAuB,aAAa;AAAA,QACrD;AAAA,UACE,MAAM,CAAC,GAAG,YAAY,QAAQ,mBAAmB,EAAE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,GAAG,CAAC,GAAG,QAAQ;AAAA,UACvG,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AACD,YAAM,SAAS,CAAC,SAAiB;AAE/B,YAAI,aAAa,IAAI,EAAG,QAAO;AAC/B,YAAI,CAAC,WAAW,MAAM,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,YAAY,QAAQ,MAAM,mBAAmB,EAAG,QAAO;AAChG,YAAI,eAAe;AACjB,cAAI,GAAG,OAAO,sEAAsE,SAAS;AAAA,QAC/F,MAAO,UAAS,EAAE,WAAW,KAAK,CAAC;AACnC,eAAO;AAAA,MACT;AAIA,UAAI,gBAAgB;AACpB,YAAM,cAAc,sBAChB,IAAI,GAAG,gBAAgB,CAAC,SAAS;AAC/B,YAAI,aAAa,IAAI,EAAG;AACxB,YAAI,gBAAgB,KAAK,CAAC,WAAW,MAAM,IAAI,KAAK,GAAG,CAAC,EAAG;AAC3D,eAAO,OAAO,IAAI,IAAI,EAAE,SAAS,KAAK,IAAI;AAAA,MAC5C,CAAC,IACD;AACJ,UAAI;AACJ,UAAI;AACF,uBAAe;AAAA,UACb;AAAA,UACA;AAAA,UACA,cAAc,MAAO,gBAAgB,OAAQ;AAAA,UAC7C;AAAA,UACA,sBACI,CAAC,WAAW;AACV,6BAAiB,SAAS,IAAI;AAAA,UAChC,IACA;AAAA,QACN;AAAA,MACF,SAAS,OAAO;AACd,sBAAc;AACd,eAAO,QAAQ;AACf,cAAM;AAAA,MACR;AACA,YAAM,YAAY,aAAa;AAAA,QAC7B,CAAC,WAAW;AACV,wBAAc;AACd,mBAAS,CAAC,CAAC;AAAA,QACb;AAAA,QACA,CAAC,UAAmB,SAAS,EAAE,MAAM,CAAC;AAAA,MACxC;AACA,aAAO;AAAA,QACL,OAAO,OAAe;AACpB,cAAI,SAAS,EAAG,QAAO,CAAC;AACxB,gBAAM,YAAY,KAAK,IAAI,GAAG,KAAK;AACnC,gBAAM,QAAQ,OAAO,OAAO,SAAS;AACrC,gBAAM,eAAe,MAAM,GAAG,EAAE;AAChC,iBAAO;AAAA,YACL,GAAG,MAAM,MAAM,GAAG,EAAE;AAAA,YACpB,gBAAgB,MAAM,GAAG,OAAO,UAAU,GAAG,WAAW,EAAE;AAAA,YAC1D,GAAI,iBAAiB,SAAY,CAAC,IAAI,CAAC,YAAY;AAAA,UACrD;AAAA,QACF;AAAA,QACA,YAAY,MAAM,OAAO,WAAW;AAAA,QACpC,aAAa;AAAA,QACb,UAAU;AACR,wBAAc;AACd,iBAAO,QAAQ;AAAA,QACjB;AAAA,QACA,gBAAgB,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF,CAAC;AACD,MAAI,YAAY,SAAS,QAAS,OAAM,YAAY;AACpD,MAAI,YAAY,SAAS,YAAa,QAAO,EAAE,MAAM,SAAS;AAC9D,MAAI,YAAY,MAAM,WAAW;AAC/B,QAAI,iBAAkB,KAAI,GAAG,OAAO,kBAAkB,MAAM;AAC5D,WAAO,EAAE,MAAM,YAAY;AAAA,EAC7B;AACA,MAAI,YAAY,MAAM,MAAO,OAAM,YAAY,MAAM;AACrD,SAAO,eAAe,EAAE,MAAM,SAAS;AACzC;AAEA,SAAS,oBAAoB,OAAe;AAE1C,SAAO,gCAAgC,KAAK,KAAK;AACnD;;;ADjGA,eAAsB,0BACpB,KACA,WACA,QACA,UAA8B,mBAC9B,UAAwC,CAAC,GACH;AACtC,MAAI;AACF,QAAI,WAAW,QAAQ;AACvB,QAAI,CAAC,UAAU;AACb,YAAM,YAAY,MAAM,iCAAiC,KAAK,WAAW,QAAQ,OAAO;AACxF,UAAI,CAAC,aAAa,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAG1D,UAAI,UAAU,SAAS,WAAW,UAAU,MAAM,SAAS,aAAa;AACtE,gBAAQ,sBAAsB;AAAA,MAChC;AACA,UAAI,UAAU,SAAS,SAAS;AAC9B,YAAI,GAAG,OAAO,8DAA8D,MAAM;AAClF,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,QAAQ;AACnC,YAAI,GAAG,OAAO,0DAA0D,MAAM;AAC9E,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,UAAU;AACrC,YAAI,IAAI,SAAS,OAAO;AACtB,cAAI,GAAG,OAAO,oBAAoB,UAAU,QAAQ,UAAU,MAAM,UAAU,GAAG,MAAM;AACvF,iBAAO,EAAE,MAAM,OAAO;AAAA,QACxB;AACA,cAAM,oBAAoB,KAAK,UAAU,QAAQ,UAAU,MAAM,YAAY,MAAM;AACnF,eAAO,QAAQ,UAAU,EAAE,MAAM,QAAQ,IAAI,EAAE,MAAM,OAAO;AAAA,MAC9D;AACA,iBAAW,kBAAkB,UAAU,QAAQ,UAAU,KAAK;AAAA,IAChE;AAEA,QAAI,IAAI,SAAS,OAAO;AACtB,UAAI,GAAG,OAAO,6BAA6B,QAAQ,GAAG,SAAS;AAC/D,aAAO,EAAE,MAAM,OAAO;AAAA,IACxB;AAEA,QAAI,kBAAkB;AACtB,eAAS;AACP,UAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC5C,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA,QAAQ,UAAU;AAAA,QAClB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,OAAO,SAAS,UAAW,QAAO;AACtC,YAAM,YAAY,MAAM;AAAA,QAA2B;AAAA,QAAS,MAC1D,iCAAiC,KAAK,gBAAgB,WAAW,QAAQ,OAAO;AAAA,MAClF;AACA,UAAI,CAAC,aAAa,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC1D,UAAI,UAAU,SAAS,SAAS;AAC9B,gBAAQ,sBAAsB;AAC9B,YAAI,GAAG,OAAO,mEAAmE,SAAS;AAC1F,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,UAAI,UAAU,MAAM,SAAS,aAAa;AACxC,YAAI,GAAG;AAAA,UACL,UAAU,MAAM,SAAS,SACrB,uDACA;AAAA,UACJ;AAAA,QACF;AACA,gBAAQ,sBAAsB;AAC9B,eAAO,EAAE,MAAM,OAAO;AAAA,MACxB;AACA,wBAAkB,kBAAkB,UAAU,QAAQ,UAAU,KAAK;AAAA,IACvE;AAAA,EACF,SAAS,OAAO;AACd,QAAI,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ;AAC5C,QAAI,GAAG,OAAO,oCAAoC,aAAa,KAAK,CAAC,IAAI,OAAO;AAChF,WAAO,EAAE,MAAM,OAAO;AAAA,EACxB,UAAE;AACA,kBAAc,KAAK,MAAS;AAAA,EAC9B;AACF;AAIA,eAAe,wBACb,KACA,iBACA,QACA,UACA,eACA,SACA,SAC+B;AAO/B,MAAI,YAAuB,EAAE,UAAU,iBAAiB,OAAO,MAAM;AACrE,MAAI;AACJ,MAAI;AACJ,MAAI,mBAAmB;AACvB,QAAM,QAAQ,WAAW,aAAa,SAAS;AAC/C,QAAM,OAAO,WAAwD;AAAA,IACnE,OAAO;AAAA,IACP,SAAS;AAAA,MACP,QAAQ,CAAC,EAAE,MAAM,OAAO;AAAA,QACtB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,sBAAsB,MAAM,QAAQ;AAAA,QAC3C,OAAO;AAAA,UACL;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,IAAI;AAAA,UACN;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,QAAQ;AAAA,UACV;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,OAAO;AAAA,YACP,aAAa;AAAA,YACb,QAAQ;AAAA,UACV;AAAA,UACA,EAAE,IAAI,UAAU,OAAO,QAAQ,eAAe,UAAU,QAAQ,SAAS;AAAA,QAC3E;AAAA,QACA,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,CAAC,EAAE,MAAM,OAAO;AAAA,QACtB,MAAM;AAAA,QACN,OAAO,8BAA2B,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,QAC5E,SAAS,0BAA0B,MAAM,QAAQ;AAAA,QACjD,QAAQ,EAAE,MAAM,OAAO;AAAA,QACvB,cAAc;AAAA,QACd,MAAM;AAAA,MACR;AAAA,MACA,OAAO,CAAC,EAAE,MAAM,OAAO;AAAA,QACrB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,UACL,eAAe,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,UACzD;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,GAAI,WACA;AAAA,YACE;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,cAAc,MAAM;AAAA,cAC3B,aAAa;AAAA,cACb,QAAQ;AAAA,YACV;AAAA,UACF,IACA,CAAC;AAAA,UACL,EAAE,IAAI,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,QAC9C;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,OAAO,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AAChD,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,gBAAgB,MAAM,WAAW,MAAM,SAAS,SAAS;AAC/D,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,sCAA4B,eAAe,MAAM,QAAQ;AACzD,cAAI,CAAC,cAAc,QAAQ,SAAS,UAAU,KAAK,MAAM,SAAS,cAAc,SAAS,UAAU,GAAG;AACpG,kBAAM,eAAe,MAAM,IAAI,GAAG;AAAA,cAChC;AAAA,cACA;AAAA,cACA,EAAE,OAAO;AAAA,YACX;AACA,gBAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,gBAAI,CAAC,aAAc,QAAO,EAAE,MAAM,OAAgB;AAAA,UACpD;AACA,gBAAM,SAAS,MAAM,2BAA2B,SAAS,YAAY;AACnE,kBAAM,SAAS,MAAM,mBAAmB,MAAM,UAAU,QAAQ,OAAO;AACvE,gBAAI,OAAO,QAAS,OAAM,OAAO;AACjC,kBAAM,mBAAmB,QAAQ,MAAM,UAAU,MAAM;AACvD,mBAAO;AAAA,UACT,CAAC;AACD,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,kBAAQ,sBAAsB;AAC9B,+BAAqB;AAAA,YACnB,GAAG,OAAO;AAAA,YACV,WAAW,MAAM,SAAS;AAAA,YAC1B,SAAS,CAAC,GAAG,MAAM,SAAS,aAAa;AAAA,YACzC,WAAW,OAAO,OAAO;AAAA,YACzB,mBAAmB,OAAO,OAAO;AAAA,YACjC,WAAW,OAAO,OAAO;AAAA,YACzB,YAAY,OAAO,OAAO;AAAA,YAC1B,UAAU,OAAO,OAAO;AAAA,YACxB,YAAY,OAAO,OAAO;AAAA,UAC5B;AACA,sBAAY,EAAE,UAAU,MAAM,UAAU,OAAO,KAAK;AACpD,iBAAO,EAAE,MAAM,MAAe,QAAQ,QAAiB;AAAA,QACzD,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,mBAAmB,KAAK,GAAG;AAC7B,gBAAI,GAAG,OAAO,GAAG,aAAa,KAAK,CAAC,+BAA+B,SAAS;AAC5E,+BAAmB;AACnB,mBAAO,EAAE,MAAM,QAAiB;AAAA,UAClC;AACA,cAAI,GAAG,OAAO,2CAA2C,aAAa,KAAK,CAAC,IAAI,OAAO;AACvF,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,MAAM,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AAC/C,YAAI,CAAC,UAAU;AACb,cAAI,GAAG,OAAO,oDAAoD,OAAO;AACzE,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AACA,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,SAAS,MAAM,WAAW,MAAM,SAAS,SAAS;AACxD,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,sCAA4B,QAAQ,MAAM,QAAQ;AAClD,gBAAM,SAAS,MAAM;AAAA,YACnB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,cACE,aAAa;AAAA,cACb,kBAAkB;AAAA,cAClB,QAAQ,MAAM,SAAS;AAAA,cACvB;AAAA,YACF;AAAA,UACF;AACA,iBAAO,wBAAwB,QAAQ,MAAM;AAAA,QAC/C,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,mBAAmB,KAAK,GAAG;AAC7B,gBAAI,GAAG,OAAO,GAAG,aAAa,KAAK,CAAC,+BAA+B,SAAS;AAC5E,+BAAmB;AACnB,mBAAO,EAAE,MAAM,QAAiB;AAAA,UAClC;AACA,cAAI,GAAG,OAAO,wCAAwC,aAAa,KAAK,CAAC,IAAI,OAAO;AACpF,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,UAAU,OAAO,EAAE,OAAO,QAAQ,aAAa,MAAM;AACnD,YAAI,CAAC,YAAY,CAAC,mBAAoB,QAAO,EAAE,MAAM,OAAgB;AACrE,cAAM,SAAS,eAAe,eAAe,YAAY;AACzD,YAAI;AACF,gBAAM,SAAS,MAAM,kBAAkB,MAAM,SAAS,SAAS;AAC/D,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,CAAC,uBAAuB,QAAQ,kBAAkB,GAAG;AACvD,kBAAM,IAAI;AAAA,cACR,oBAAe,iBAAiB,MAAM,SAAS,SAAS,CAAC;AAAA,YAC3D;AAAA,UACF;AACA,gBAAM,SAAS,MAAM,wBAAwB,KAAK,kBAAkB,MAAM,GAAG,OAAO,UAAU;AAAA,YAC5F,aAAa;AAAA,YACb,kBAAkB,6BAA6B,KAAK;AAAA,YACpD,QAAQ,MAAM,SAAS;AAAA,YACvB;AAAA,UACF,CAAC;AACD,iBAAO,wBAAwB,QAAQ,KAAK;AAAA,QAC9C,SAAS,OAAO;AACd,cAAI,OAAO,QAAS,QAAO,EAAE,MAAM,QAAiB;AACpD,cAAI,GAAG,OAAO,uBAAuB,aAAa,KAAK,CAAC,IAAI,OAAO;AACnE,iBAAO,EAAE,MAAM,OAAgB;AAAA,QACjC;AAAA,MACF;AAAA,MACA,QAAQ,aAAa,EAAE,MAAM,OAAO;AAAA,MACpC,MAAM,YAAY;AAChB,qBAAa,EAAE,MAAM,OAAO;AAC5B,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF,CAAC;AAED,WAAS,wBACP,QACA,aACA;AACA,QAAI,OAAO,SAAS,eAAe,OAAO,YAAY,WAAW;AAC/D,cAAQ,sBAAsB;AAAA,IAChC;AACA,QAAI,OAAO,SAAS,UAAU;AAC5B,mBAAa,EAAE,MAAM,SAAS;AAC9B,aAAO,EAAE,MAAM,QAAiB;AAAA,IAClC;AACA,QACE,OAAO,SAAS,eACf,OAAO,SAAS,eAAe,OAAO,YAAY,eACnD,OAAO,SAAS,UAChB;AACA,aAAO,EAAE,MAAM,OAAgB;AAAA,IACjC;AACA,iBAAa,EAAE,MAAM,gBAAgB,QAAQ,OAAO,YAAY;AAChE,WAAO,EAAE,MAAM,QAAiB;AAAA,EAClC;AAEA,QAAM,aAAa,MAAM,QAAQ,KAAK,MAAM;AAAA,IAC1C,UAAU,MAAM;AAAA,IAChB,QAAQ;AAAA,IACR,WAAW,MAAM,CAAC,eAAe;AAAA,IACjC,SAAS,CAAC,UAAU,UAAU,IAAI,GAAG,OAAO,aAAa,KAAK,GAAG,OAAO;AAAA,EAC1E,CAAC;AACD,MAAI,eAAe,WAAW,WAAW,SAAS,QAAS,QAAO,EAAE,MAAM,QAAQ;AAClF,MAAI,iBAAkB,QAAO,EAAE,MAAM,UAAU;AAC/C,MAAI,WAAY,QAAO;AACvB,MAAI,WAAW,SAAS,UAAU;AAChC,WAAO,WAAW,WAAW,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,MAAM,SAAS;AAAA,EAC5E;AACA,SAAO,EAAE,MAAM,SAAS;AAC1B;AASA,eAAe,mBACb,UACA,QACA,SACyB;AACzB,QAAM,SAAS,MAAM,WAAW,SAAS,SAAS;AAClD,iBAAe,MAAM;AACrB,8BAA4B,QAAQ,QAAQ;AAC5C,QAAM,UAAU,MAAM,kBAAkB,SAAS,SAAS;AAC1D,iBAAe,MAAM;AACrB,MAAI,CAAC,gBAAgB,QAAQ,SAAS,SAAS,YAAY,GAAG;AAC5D,UAAM,IAAI;AAAA,MACR,oBAAe,iBAAiB,SAAS,SAAS,CAAC;AAAA,IACrD;AAAA,EACF;AACA,QAAM,UAAU,MAAM,QAAQ,MAAM;AACpC,iBAAe,MAAM;AACrB,QAAM,eAAe,MAAM,QAAQ,SAAS,MAAM;AAClD,iBAAe,MAAM;AACrB,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,gCAAgC,uDAAuD;AAAA,EACnG;AACA,QAAM,WAAW,MAAM,oBAAoB,SAAS,cAAc,MAAM;AACxE,iBAAe,MAAM;AACrB,QAAM,QAAQ,uBAAuB,OAAO,SAAS,QAAQ;AAC7D,MAAI,MAAM,SAAS,eAAe,CAAC,gBAAgB,MAAM,SAAS,SAAS,aAAa,GAAG;AACzF,UAAM,IAAI,gCAAgC,8DAA8D;AAAA,EAC1G;AACA,SAAO,EAAE,QAAQ,eAAe,SAAS,SAAS,aAAa;AACjE;AAEA,eAAe,mBAAmB,QAAwB,UAAmC,QAAqB;AAChH,QAAM,cAAc,MAAM,OAAO,QAAQ,SAAS,MAAM;AACxD,iBAAe,MAAM;AACrB,MAAI,CAAC,eAAe,CAAC,OAAO,QAAQ,aAAa,OAAO,aAAa,UAAU,YAAY,QAAQ,GAAG;AACpG,UAAM,IAAI,gCAAgC,uDAAuD;AAAA,EACnG;AACA,QAAM,kBAAkB,MAAM,oBAAoB,OAAO,SAAS,aAAa,MAAM;AACrF,iBAAe,MAAM;AACrB,QAAM,eAAe,uBAAuB,OAAO,OAAO,SAAS,eAAe;AAClF,MAAI,aAAa,SAAS,eAAe,CAAC,gBAAgB,aAAa,SAAS,SAAS,aAAa,GAAG;AACvG,UAAM,IAAI,gCAAgC,8DAA8D;AAAA,EAC1G;AACA,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,CAAC,WAAW;AAAA,MACV,GAAG;AAAA,MACH,MAAM,EAAE,GAAG,MAAM,MAAM,SAAS,CAAC,GAAG,SAAS,aAAa,EAAE;AAAA,IAC9D;AAAA,IACA;AAAA,MACE,iBAAiB,OAAO;AAAA,MACxB,iBAAiB,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,iCACb,KACA,WACA,QACA,SAKA;AACA,QAAM,SAAS,MAAM,WAAW,SAAS;AACzC,MAAI,QAAQ,QAAS,QAAO;AAC5B,gBAAc,KAAK,+BAA+B,iBAAiB,OAAO,SAAS,CAAC,EAAE;AACtF,QAAM,UAAU,MAAM,QAAQ,MAAM;AACpC,MAAI,QAAQ,QAAS,QAAO;AAC5B,QAAM,OAAO,MAAM,QAAQ,SAAS,MAAM;AAC1C,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,SAAS,OAAO;AAC1C,QAAM,WAAW,MAAM,oBAAoB,SAAS,MAAM,MAAM;AAChE,MAAI,QAAQ,QAAS,QAAO;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO,uBAAuB,OAAO,SAAS,QAAQ;AAAA,EACxD;AACF;AAEA,eAAe,oBACb,KACA,QACA,YACA,QACA;AACA,QAAM,OAAO,WAAqE;AAAA,IAChF,OAAO;AAAA,IACP,SAAS;AAAA,MACP,QAAQ,OAAO;AAAA,QACb,MAAM;AAAA,QACN,OAAO,+BAA4B,iBAAiB,OAAO,SAAS,CAAC;AAAA,QACrE,OAAO;AAAA,UACL;AAAA,UACA;AAAA,QACF;AAAA,QACA,OAAO;AAAA,UACL,EAAE,IAAI,UAAU,OAAO,2BAA2B,IAAI,SAAS;AAAA,UAC/D,EAAE,IAAI,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,QAC9C;AAAA,QACA,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO;AAAA,QACb,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA,GAAI,WAAW,SAAS,IACpB,WAAW,IAAI,CAAC,SAAS,eAAe,iBAAiB,IAAI,CAAC,EAAE,IAChE,CAAC,gCAAgC;AAAA,UACrC;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,QACX,QAAQ,EAAE,MAAM,OAAO;AAAA,QACvB,cAAc;AAAA,QACd,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,SAAS,EAAE,MAAM,aAAa,EAAE,MAAM,QAAQ,GAAG;AAAA,EACnD,CAAC;AACD,QAAM,QAAQ,KAAK,MAAM;AAAA,IACvB,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,WAAW,MAAM,CAAC,QAAQ;AAAA,EAC5B,CAAC;AACH;AAEA,SAAS,sBAAsB,UAAmC;AAChE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,eAAe,iBAAiB,SAAS,SAAS,CAAC;AAAA,IACnD;AAAA,IACA,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE,CAAC,oDAAoD,IACrD,CAAC,sBAAsB,WAAW,WAAW,MAAM,4BAAyB,WAAW,UAAU,MAAM,EAAE;AAAA,EAC/G;AACF;AAEA,SAAS,0BAA0B,UAAmC;AACpE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE,CAAC,6DAA6D,EAAE,IAChE,CAAC;AAAA,IACL;AAAA,IACA,GAAI,WAAW,WAAW,SAAS,IAC/B,WAAW,WAAW,IAAI,CAAC,SAAS,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACjE,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,WAAW,UAAU,SAAS,IAC9B,WAAW,UAAU,IAAI,CAAC,SAAS,KAAK,iBAAiB,IAAI,CAAC,EAAE,IAChE,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,SAAS,cAAc,SAAS,IAChC,SAAS,cAAc,IAAI,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACrF,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,SAAS,aAAa,SAAS,IAC/B,SAAS,aAAa,IAAI,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,iBAAiB,IAAI,CAAC,EAAE,IACpF,CAAC,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,6BAA6B,UAAmC;AACvE,QAAM,aAAa,mBAAmB,SAAS,cAAc,SAAS,aAAa;AACnF,SAAO;AAAA,IACL,4BAAuB,iBAAiB,SAAS,SAAS,CAAC;AAAA,IAC3D,gBAAgB,SAAS,WAAW,UAAU,CAAC;AAAA,IAC/C,gBAAgB,SAAS,WAAW,SAAS,CAAC;AAAA,IAC9C,GAAI,WAAW,WAAW,WAAW,KAAK,WAAW,UAAU,WAAW,IACtE;AAAA,MACE;AAAA,MACA,iBAAiB,SAAS,SAAS,aAAa,CAAC;AAAA,MACjD,iBAAiB,SAAS,SAAS,YAAY,CAAC;AAAA,IAClD,IACA,CAAC;AAAA,IACL;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,oBAAoB,QAAuB,YAA+B;AACjF,SAAO,6BAAwB,iBAAiB,OAAO,SAAS,CAAC,+CAA0C,WAAW,MAAM,aAAa,WAAW,WAAW,IAAI,SAAS,QAAQ;AACtL;AAEA,SAAS,kBACP,QACA,OACyB;AACzB,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,gBAAgB,4BAA4B,MAAM;AAAA,IAClD,cAAc,CAAC,GAAG,OAAO,OAAO;AAAA,IAChC,eAAe,CAAC,GAAG,MAAM,OAAO;AAAA,EAClC;AACF;AAEA,SAAS,4BAA4B,QAAuB,UAAmC;AAC7F,MACE,4BAA4B,MAAM,MAAM,SAAS,kBACjD,gBAAgB,OAAO,SAAS,SAAS,YAAY,GACrD;AACA;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR,oBAAe,iBAAiB,OAAO,SAAS,CAAC;AAAA,EACnD;AACF;AAEA,SAAS,uBAAuB,MAAqB,OAAsB;AACzE,SACE,KAAK,cAAc,MAAM,aACzB,KAAK,mBAAmB,MAAM,kBAC9B,KAAK,gBAAgB,MAAM,eAC3B,KAAK,gBAAgB,MAAM,eAC3B,KAAK,WAAW,MAAM,UACtB,KAAK,WAAW,MAAM,UACtB,QAAQ,KAAK,SAAS,MAAM,QAAQ,MAAM,SAAS,KACnD,QAAQ,KAAK,UAAU,MAAM,QAAQ,MAAM,UAAU,KACrD,gBAAgB,KAAK,SAAS,MAAM,OAAO;AAE/C;AAEA,SAAS,cAAc,QAA+B;AACpD,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,OAAQ,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,kBAAkB,QAA+B;AACxD,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,OAAQ,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,6BAA6B,OAAiC;AACrE,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,OAAQ,QAAO;AAC7B,SAAO;AACT;AAEA,SAAS,SAAS,QAA2B;AAC3C,SAAO,OAAO,SAAS,IAAI,OAAO,IAAI,gBAAgB,EAAE,KAAK,IAAI,IAAI;AACvE;AAEA,IAAM,kCAAN,cAA8C,MAAM;AAAA,EAClD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,mBAAmB,OAAgB;AAC1C,SAAO,iBAAiB,mCAAmC,iBAAiB;AAC9E;AAEA,SAAS,2BACP,SACA,MACA;AACA,SAAO,QAAQ,kBAAkB,QAAQ,gBAAgB,IAAI,IAAI,KAAK;AACxE;AAEA,SAAS,eAAe,eAAwC,cAA2B;AACzF,SAAO,gBAAgB,YAAY,IAAI,CAAC,eAAe,YAAY,CAAC,IAAI;AAC1E;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/settings/config.ts", "../../src/settings/config-file.ts", "../../src/settings/settings-validation.ts", "../../src/settings/settings-store.ts"],
4
- "sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { backendIdentityCoordinates } from \"../backends/backend-identity.js\";\nimport { normalizeGitBranch, normalizeGitDirectory, normalizeGitRemote } from \"../backends/git/git-config.js\";\nimport { normalizeWebDavPath, normalizeWebDavUrl } from \"../backends/webdav/webdav-config.js\";\nimport { normalizeLocalFields } from \"../sync/local-fields.js\";\nimport { normalizeSyncInclude } from \"../sync/sync-policy.js\";\nimport { localConfigPath, readActiveLocalConfigDocumentForRepair } from \"./config-file.js\";\nimport { requireSettings } from \"./settings-store.js\";\nimport type {\n AnySyncConfig,\n OnSwitchAction,\n PartialConfig,\n PiSyncSettingsV3,\n StorageConnectionSettings,\n SyncSetupSettings,\n} from \"./settings-types.js\";\nimport {\n DEFAULT_ON_SWITCH,\n isCloudflareR2Endpoint,\n normalizeS3Bucket,\n normalizeS3Endpoint,\n normalizeStoragePath,\n optionalString,\n ownObject,\n requiredString,\n validateConfigName,\n validateSettingsDocument,\n} from \"./settings-validation.js\";\n\nexport async function loadConfig(setupName?: string): Promise<AnySyncConfig> {\n return configFromSettings(await requireSettings(), setupName);\n}\n\n/** A background freshness read must never trigger legacy-file publication. */\nexport async function loadConfigForCheck(): Promise<AnySyncConfig> {\n const document = await readActiveLocalConfigDocumentForRepair();\n if (!document) throw new Error(`Missing pi-sync settings: ${localConfigPath()}`);\n validateSettingsDocument(document.parsed);\n return configFromSettings(document.parsed as PiSyncSettingsV3);\n}\n\nfunction configFromSettings(settings: PiSyncSettingsV3, setupName?: string): AnySyncConfig {\n const selectedName = setupName ?? settings.activeSyncSetup;\n if (!selectedName) throw new Error(\"No sync setups are configured.\");\n validateConfigName(selectedName, \"sync setup\");\n const setup = ownObject<SyncSetupSettings>(settings.syncSetups, selectedName);\n if (!setup) throw new Error(`Invalid pi-sync settings: sync setup \u201C${selectedName}\u201D was not found.`);\n const connectionName = setup.storage.connection;\n const connection = ownObject<StorageConnectionSettings>(settings.storageConnections, connectionName);\n if (!connection) {\n throw new Error(\n `Invalid pi-sync settings: sync setup \u201C${selectedName}\u201D references missing storage connection \u201C${connectionName}\u201D.`,\n );\n }\n return {\n ...resolveSyncConfig(\n selectedName,\n setup,\n connectionName,\n connection,\n settings.onSwitch,\n settings.skipSecretScan ?? false,\n settings.showStatus ?? true,\n ),\n debug: settings.debug ?? false,\n };\n}\n\nexport type SyncSetupStorageReview = Pick<\n PartialConfig,\n \"connectionName\" | \"storageKind\" | \"storagePath\" | \"bucket\" | \"branch\"\n>;\n\n/** A validated setup-facing projection used by manager and settings UI. */\nexport async function loadPartialConfig(setupName?: string): Promise<PartialConfig> {\n const config = await loadConfig(setupName);\n return {\n setupName: config.setupName,\n ...storageReviewFromConfig(config),\n include: [...config.include],\n automatic: config.automatic,\n automaticTransfer: config.automaticTransfer ?? false,\n agentMode: config.agentMode ?? false,\n continuous: config.continuous ?? false,\n onSwitch: config.onSwitch,\n showStatus: config.showStatus,\n };\n}\n\nexport function syncSetupStorageReview(\n setupName: string,\n setup: SyncSetupSettings,\n connectionName: string,\n connection: StorageConnectionSettings,\n): SyncSetupStorageReview {\n return storageReviewFromConfig(\n resolveSyncConfig(setupName, setup, connectionName, connection, DEFAULT_ON_SWITCH, false, true),\n );\n}\n\nexport function syncSetupReviewIdentity(\n setupName: string,\n setup: SyncSetupSettings,\n connectionName: string,\n connection: StorageConnectionSettings,\n) {\n return syncConfigReviewIdentity(\n resolveSyncConfig(setupName, setup, connectionName, connection, DEFAULT_ON_SWITCH, false, true),\n );\n}\n\nexport function syncConfigReviewIdentity(config: AnySyncConfig) {\n return JSON.stringify([\n config.setupName,\n config.connectionName,\n backendIdentityCoordinates(config),\n config.include,\n config.automatic,\n config.automaticTransfer ?? false,\n config.agentMode ?? false,\n config.localFields,\n config.mergeSettings ?? false,\n config.mergeContent ?? false,\n config.partialSync ?? false,\n // Preserve existing Off identities and cached candidates across the upgrade.\n ...(config.continuous ? [\"continuous\"] : []),\n ]);\n}\n\nexport function syncConfigReviewFingerprint(config: AnySyncConfig) {\n return createHash(\"sha256\").update(syncConfigReviewIdentity(config)).digest(\"hex\");\n}\n\n/** Internal freshness token, including credentials; never display or persist it. */\nexport function syncCheckConfigFingerprint(config: AnySyncConfig) {\n return createHash(\"sha256\")\n .update(JSON.stringify({ ...config, showStatus: undefined, debug: undefined }))\n .digest(\"hex\");\n}\n\nfunction storageReviewFromConfig(config: AnySyncConfig): SyncSetupStorageReview {\n return {\n connectionName: config.connectionName,\n storageKind: config.backend.type,\n storagePath: config.storagePath,\n ...(config.backend.type === \"s3\"\n ? { bucket: config.backend.destination.bucket }\n : config.backend.type === \"git\"\n ? { branch: config.backend.destination.branch }\n : {}),\n };\n}\n\nfunction resolveSyncConfig(\n setupName: string,\n setup: SyncSetupSettings,\n connectionName: string,\n connection: StorageConnectionSettings,\n onSwitch: OnSwitchAction,\n skipSecretScan: boolean,\n showStatus: boolean,\n): AnySyncConfig {\n const storagePath = normalizeStoragePath(setup.storage.path);\n const namespace = storagePath === \"./\" ? \"root\" : storagePath.slice(storagePath.lastIndexOf(\"/\") + 1);\n const include = normalizeSyncInclude(setup.sync.include);\n const common = {\n setupName,\n connectionName,\n storagePath,\n snapshotIdentity: namespace,\n include,\n automatic: setup.sync.automatic,\n automaticTransfer: setup.sync.automaticTransfer ?? false,\n agentMode: setup.sync.agentMode ?? false,\n continuous: setup.sync.continuous ?? false,\n localFields: setup.sync.localFields === undefined ? undefined : normalizeLocalFields(setup.sync.localFields),\n mergeSettings: setup.sync.mergeSettings ?? false,\n mergeContent: setup.sync.mergeContent ?? false,\n partialSync: setup.sync.partialSync ?? false,\n onSwitch,\n skipSecretScan,\n showStatus,\n };\n if (connection.type === \"git\") {\n return {\n ...common,\n backend: {\n type: \"git\",\n profile: { kind: \"git\", remote: normalizeGitRemote(connection.remote) as string },\n destination: {\n branch: normalizeGitBranch(setup.storage.branch),\n directory: normalizeGitDirectory(storagePath),\n namespace,\n },\n },\n };\n }\n if (connection.type === \"webdav\") {\n return {\n ...common,\n backend: {\n type: \"webdav\",\n profile: {\n kind: \"webdav\",\n url: normalizeWebDavUrl(connection.url) as string,\n username: connection.credentials.username,\n password: connection.credentials.password,\n },\n destination: { path: normalizeWebDavPath(storagePath), namespace },\n },\n };\n }\n return {\n ...common,\n backend: {\n type: \"s3\",\n profile: {\n kind: isCloudflareR2Endpoint(connection.endpoint) ? \"r2\" : \"s3-compatible\",\n endpoint: normalizeS3Endpoint(connection.endpoint),\n region: requiredString(connection.region, \"S3 region\"),\n accessKeyId: connection.credentials.accessKeyId,\n secretAccessKey: connection.credentials.secretAccessKey,\n sessionToken: optionalString(connection.credentials.sessionToken, \"S3 session token\"),\n },\n destination: {\n bucket: normalizeS3Bucket(setup.storage.bucket),\n prefix: storagePath,\n namespace,\n },\n },\n };\n}\n\nexport function sessionTokenWarnings(config: { endpoint?: string; sessionToken?: string }) {\n if (!isCloudflareR2Endpoint(config.endpoint) || !config.sessionToken) return [];\n return [\n \"session token: configured for Cloudflare R2; if R2 rejects X-Amz-Security-Token, pi-sync retries once without it. R2 static access keys usually do not need a session token.\",\n ];\n}\n\nexport function syncSessionsWarnings(config: { include: readonly string[] }) {\n if (!config.include.includes(\"sessions\")) return [];\n return [\n \"sessions: included; Pi session JSONL can contain prompts, tool output, file paths, images, and secrets. Sync sessions only to storage you trust.\",\n ];\n}\n\nexport function isEnabled(value: boolean | string | undefined, defaultValue: boolean) {\n if (value === undefined) return defaultValue;\n if (typeof value === \"boolean\") return value;\n return ![\"0\", \"false\", \"no\", \"off\"].includes(value.trim().toLowerCase());\n}\n\nexport function isExplicitlyEnabled(value: boolean | string | undefined) {\n if (typeof value === \"boolean\") return value;\n return [\"1\", \"true\", \"yes\", \"on\"].includes(value?.trim().toLowerCase() ?? \"\");\n}\n", "import { randomUUID } from \"node:crypto\";\nimport {\n mkdir,\n mkdirSync,\n realpath,\n realpathSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n utimes,\n utimesSync,\n} from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport lockfile from \"proper-lockfile\";\n\nconst CONFIG_FILE_NAME = \"pi-sync.json\";\nconst LEGACY_CONFIG_FILE_NAME = \"pi-sync.local.json\";\nconst configMigrationNotices = new Map<string, string>();\nconst legacyPresenceNoticed = new Set<string>();\nconst CONFIG_LOCK_STALE_MS = 30_000;\nconst CONFIG_LOCK_UPDATE_MS = 10_000;\nconst LOCKFILE_FS_ADAPTER = {\n mkdir,\n mkdirSync,\n realpath,\n realpathSync,\n rmdir,\n rmdirSync,\n stat,\n statSync,\n utimes,\n utimesSync,\n};\n\ntype PublishFile = (source: string, destination: string) => Promise<void>;\nlet publishConfigFile: PublishFile = publishFileWithoutReplacement;\nlet beforeConfigPublicationHook: () => Promise<void> = async () => undefined;\nlet afterMissingConfigReadProbeHook: () => Promise<void> = async () => undefined;\nlet afterReplacementInstalledHook: () => Promise<void> = async () => undefined;\nlet afterConfigQuarantinedHook: () => Promise<void> = async () => undefined;\n\nexport type FileIdentity = { dev: number; ino: number };\n\nexport async function withConfigFilePublicationForTest<T>(publish: PublishFile, run: () => Promise<T>): Promise<T> {\n const previous = publishConfigFile;\n publishConfigFile = publish;\n try {\n return await run();\n } finally {\n publishConfigFile = previous;\n }\n}\n\nexport async function withConfigPublicationReadyHookForTest<T>(\n hook: () => Promise<void>,\n run: () => Promise<T>,\n): Promise<T> {\n const previous = beforeConfigPublicationHook;\n beforeConfigPublicationHook = hook;\n try {\n return await run();\n } finally {\n beforeConfigPublicationHook = previous;\n }\n}\n\nexport async function withMissingConfigReadProbeHookForTest<T>(\n hook: () => Promise<void>,\n run: () => Promise<T>,\n): Promise<T> {\n const previous = afterMissingConfigReadProbeHook;\n afterMissingConfigReadProbeHook = hook;\n try {\n return await run();\n } finally {\n afterMissingConfigReadProbeHook = previous;\n }\n}\n\nexport async function withConfigReplacementInstalledHookForTest<T>(\n hook: () => Promise<void>,\n run: () => Promise<T>,\n): Promise<T> {\n const previous = afterReplacementInstalledHook;\n afterReplacementInstalledHook = hook;\n try {\n return await run();\n } finally {\n afterReplacementInstalledHook = previous;\n }\n}\n\nexport async function withConfigQuarantinedHookForTest<T>(\n hook: () => Promise<void>,\n run: () => Promise<T>,\n): Promise<T> {\n const previous = afterConfigQuarantinedHook;\n afterConfigQuarantinedHook = hook;\n try {\n return await run();\n } finally {\n afterConfigQuarantinedHook = previous;\n }\n}\n\ntype ConfigSnapshot = {\n bytes: Buffer;\n identity: FileIdentity;\n parsed: Record<string, unknown>;\n};\n\nexport type LocalConfigDocument = ConfigSnapshot & { path: string };\n\nexport function localConfigPath() {\n return path.join(getAgentDir(), CONFIG_FILE_NAME);\n}\n\nexport function legacyLocalConfigPath() {\n return path.join(getAgentDir(), LEGACY_CONFIG_FILE_NAME);\n}\n\nexport async function activeLocalConfigPath() {\n const canonicalPath = localConfigPath();\n const legacyPath = legacyLocalConfigPath();\n return withLocalConfigReadLockIfNeeded(async () => {\n if (await pathExists(canonicalPath)) return canonicalPath;\n return (await pathExists(legacyPath)) ? legacyPath : canonicalPath;\n });\n}\n\nexport function consumeLocalConfigMigrationNotice() {\n const configPath = localConfigPath();\n const notice = configMigrationNotices.get(configPath);\n configMigrationNotices.delete(configPath);\n return notice;\n}\n\nexport async function readActiveLocalConfigDocumentForRepair(): Promise<LocalConfigDocument | undefined> {\n const canonicalPath = localConfigPath();\n const legacyPath = legacyLocalConfigPath();\n return withLocalConfigReadLockIfNeeded(async () => {\n const filePath = (await pathExists(canonicalPath)) ? canonicalPath : legacyPath;\n const snapshot = await readConfigSnapshotIfExists(filePath);\n return snapshot ? { path: filePath, ...snapshot } : undefined;\n });\n}\n\nexport async function readMigratingLocalConfigDocument(\n validateForMigration: (settings: Record<string, unknown>) => void,\n): Promise<LocalConfigDocument | undefined> {\n return withLocalConfigReadLockIfNeeded(async () => {\n const configPath = await prepareLocalConfigPath(validateForMigration);\n const snapshot = await readConfigSnapshotIfExists(configPath);\n return snapshot ? { path: configPath, ...snapshot } : undefined;\n });\n}\n\nasync function withLocalConfigReadLockIfNeeded<T>(read: () => Promise<T>): Promise<T> {\n if ((await pathExists(localConfigPath())) || (await pathExists(legacyLocalConfigPath()))) {\n return withLocalConfigFileLock(read);\n }\n await afterMissingConfigReadProbeHook();\n if (await pathExists(configMutationLockPath())) return withLocalConfigFileLock(read);\n return read();\n}\n\nexport function updateLocalConfigDocument<T extends Record<string, unknown>>(\n defaultValue: T,\n update: (current: T) => T,\n validate: (value: Record<string, unknown>) => void,\n signal?: AbortSignal,\n): Promise<T> {\n return withLocalConfigFileLock(async () => {\n signal?.throwIfAborted();\n const configPath = await prepareLocalConfigPath(validate);\n const snapshot = await readConfigSnapshotIfExists(configPath);\n const document = snapshot ? { path: configPath, ...snapshot } : undefined;\n const current = document ? (structuredClone(document.parsed) as T) : structuredClone(defaultValue);\n const next = update(current);\n validate(next);\n signal?.throwIfAborted();\n if (document && JSON.stringify(document.parsed) === JSON.stringify(next)) return next;\n if (document) await replaceLocalConfigDocumentUnlocked(document, next);\n else await installPrivateConfigExclusively(localConfigPath(), serializedConfig(next));\n return next;\n });\n}\n\nexport function createLocalConfigDocument(value: Record<string, unknown>) {\n return withLocalConfigFileLock(async () => {\n const bytes = serializedConfig(value);\n try {\n await installPrivateConfigExclusively(localConfigPath(), bytes);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new Error(\"Pi-sync settings were created concurrently; reopen settings and retry.\");\n }\n throw error;\n }\n });\n}\n\nexport function replaceLocalConfigDocument(document: LocalConfigDocument, value: Record<string, unknown>) {\n return withLocalConfigFileLock(() => replaceLocalConfigDocumentUnlocked(document, value));\n}\n\nasync function replaceLocalConfigDocumentUnlocked(document: LocalConfigDocument, value: Record<string, unknown>) {\n const nextBytes = serializedConfig(value);\n const canonicalPath = localConfigPath();\n if (document.path !== canonicalPath) {\n if (!(await configDocumentStillMatches(document))) throw settingsChangedError();\n let installed: FileIdentity;\n try {\n installed = await installPrivateConfigExclusively(canonicalPath, nextBytes);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new Error(\"Canonical settings were created concurrently; no settings were replaced.\");\n }\n throw error;\n }\n if (!(await configDocumentStillMatches(document))) {\n await quarantineAndRemoveConfigIfMatchesUnlocked(canonicalPath, installed, nextBytes);\n throw settingsChangedError();\n }\n return;\n }\n\n const quarantinePath = await claimCanonicalConfigDocument(document);\n let installed: FileIdentity;\n try {\n installed = await installPrivateConfigExclusively(canonicalPath, nextBytes);\n } catch (error) {\n await restoreQuarantinedConfig(canonicalPath, quarantinePath);\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new Error(\"Canonical settings changed concurrently; no settings were replaced.\");\n }\n throw error;\n }\n try {\n await afterReplacementInstalledHook();\n if (!(await fileIdentityAndContentsMatch(quarantinePath, document.identity, document.bytes))) {\n throw settingsChangedError();\n }\n if (process.platform !== \"win32\") await fs.chmod(quarantinePath, 0o600);\n } catch (error) {\n await quarantineAndRemoveConfigIfMatchesUnlocked(canonicalPath, installed, nextBytes);\n await restoreQuarantinedConfig(canonicalPath, quarantinePath);\n throw error;\n }\n await fs.rm(quarantinePath).catch(() => undefined);\n await syncParentDirectory(canonicalPath).catch(() => undefined);\n}\n\nasync function prepareLocalConfigPath(validateForMigration: (settings: Record<string, unknown>) => void) {\n const canonicalPath = localConfigPath();\n const legacyPath = legacyLocalConfigPath();\n if (await pathExists(canonicalPath)) {\n const legacyStatus = await secureIgnoredLegacyIfPresent(legacyPath);\n if (legacyStatus !== \"missing\" && !legacyPresenceNoticed.has(canonicalPath)) {\n legacyPresenceNoticed.add(canonicalPath);\n recordConfigMigrationNotice(\n canonicalPath,\n legacyStatus === \"private\"\n ? `${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} takes precedence. Delete ${LEGACY_CONFIG_FILE_NAME} after confirming your settings.`\n : `${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} takes precedence, but pi-sync could not verify them as a private regular file. Secure or delete the legacy path after confirming your settings.`,\n );\n }\n return canonicalPath;\n }\n\n const legacy = await readConfigSnapshotIfExists(legacyPath);\n if (!legacy) return canonicalPath;\n validateForMigration(legacy.parsed);\n\n let installedIdentity: FileIdentity;\n try {\n installedIdentity = await installPrivateConfigExclusively(canonicalPath, legacy.bytes);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n recordConfigMigrationNotice(\n canonicalPath,\n `${LEGACY_CONFIG_FILE_NAME} legacy settings were ignored because ${CONFIG_FILE_NAME} was created concurrently and takes precedence.`,\n );\n return canonicalPath;\n }\n recordConfigMigrationNotice(\n canonicalPath,\n `Could not migrate ${LEGACY_CONFIG_FILE_NAME} to ${CONFIG_FILE_NAME}; the legacy settings were used for this session and were not changed.`,\n );\n return legacyPath;\n }\n\n if (!(await configSnapshotStillMatches(legacyPath, legacy))) {\n const removed = await quarantineAndRemoveConfigIfMatchesUnlocked(canonicalPath, installedIdentity, legacy.bytes);\n recordConfigMigrationNotice(\n canonicalPath,\n removed\n ? `${LEGACY_CONFIG_FILE_NAME} changed during migration; the stale ${CONFIG_FILE_NAME} copy was removed and the legacy settings were used for this session.`\n : `${LEGACY_CONFIG_FILE_NAME} changed during migration, but ${CONFIG_FILE_NAME} was replaced concurrently and takes precedence.`,\n );\n return removed ? legacyPath : canonicalPath;\n }\n\n legacyPresenceNoticed.add(canonicalPath);\n recordConfigMigrationNotice(\n canonicalPath,\n `pi-sync settings migrated from ${LEGACY_CONFIG_FILE_NAME} to ${CONFIG_FILE_NAME}; the private legacy file was retained as a recovery copy and can be deleted after verification.`,\n );\n return canonicalPath;\n}\n\nasync function secureIgnoredLegacyIfPresent(filePath: string) {\n let pathStat: Awaited<ReturnType<typeof fs.lstat>>;\n try {\n pathStat = await fs.lstat(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return \"missing\" as const;\n return \"unsafe\" as const;\n }\n if (pathStat.isSymbolicLink() || !pathStat.isFile()) return \"unsafe\" as const;\n\n let handle: fs.FileHandle | undefined;\n try {\n handle = await fs.open(filePath, \"r\");\n const openedStat = await handle.stat();\n if (openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {\n return \"unsafe\" as const;\n }\n if (process.platform !== \"win32\" && (openedStat.mode & 0o777) !== 0o600) {\n await handle.chmod(0o600);\n }\n return \"private\" as const;\n } catch {\n return \"unsafe\" as const;\n } finally {\n await handle?.close().catch(() => undefined);\n }\n}\n\nasync function readConfigSnapshotIfExists(filePath: string): Promise<ConfigSnapshot | undefined> {\n let pathStat: Awaited<ReturnType<typeof fs.lstat>>;\n try {\n pathStat = await fs.lstat(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n if (pathStat.isSymbolicLink()) {\n throw new Error(`Refusing to read symlinked pi-sync config: ${filePath}`);\n }\n if (!pathStat.isFile()) throw new Error(`pi-sync config is not a regular file: ${filePath}`);\n\n const handle = await fs.open(filePath, \"r\");\n try {\n const openedStat = await handle.stat();\n if (openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {\n throw new Error(`pi-sync config changed while opening: ${filePath}`);\n }\n if (process.platform !== \"win32\" && (openedStat.mode & 0o777) !== 0o600) {\n await handle.chmod(0o600);\n }\n const bytes = await handle.readFile();\n return {\n bytes,\n identity: { dev: openedStat.dev, ino: openedStat.ino },\n parsed: parseConfigObject(bytes, filePath),\n };\n } finally {\n await handle.close();\n }\n}\n\nfunction serializedConfig(value: Record<string, unknown>) {\n return Buffer.from(`${JSON.stringify(value, null, \"\\t\")}\\n`, \"utf8\");\n}\n\nfunction parseConfigObject(bytes: Buffer, filePath: string) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n throw new SyntaxError(`Invalid JSON in pi-sync config: ${filePath}`);\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`pi-sync config must contain a JSON object: ${filePath}`);\n }\n return parsed as Record<string, unknown>;\n}\n\nasync function installPrivateConfigExclusively(filePath: string, bytes: Buffer) {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n const temporaryPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.migrate`,\n );\n let handle: fs.FileHandle | undefined;\n try {\n handle = await fs.open(temporaryPath, \"wx\", 0o600);\n await handle.writeFile(bytes);\n if (process.platform !== \"win32\") await handle.chmod(0o600);\n await handle.sync();\n await handle.close();\n handle = undefined;\n await publishConfigFile(temporaryPath, filePath);\n const installed = await fs.lstat(filePath);\n let publishedHandle: fs.FileHandle | undefined;\n let publicationError: unknown;\n try {\n if (installed.isSymbolicLink() || !installed.isFile()) {\n throw new Error(`Published pi-sync settings are not a regular file: ${filePath}`);\n }\n publishedHandle = await fs.open(filePath, \"r+\");\n const published = await publishedHandle.stat();\n if (published.dev !== installed.dev || published.ino !== installed.ino) {\n throw new Error(`Published pi-sync settings changed while opening: ${filePath}`);\n }\n if (process.platform !== \"win32\") await publishedHandle.chmod(0o600);\n await publishedHandle.sync();\n await syncParentDirectory(filePath);\n } catch (error) {\n publicationError = error;\n } finally {\n await publishedHandle?.close().catch(() => undefined);\n }\n if (publicationError) {\n await quarantineAndRemoveConfigIfMatchesUnlocked(filePath, { dev: installed.dev, ino: installed.ino }, bytes);\n throw publicationError;\n }\n return { dev: installed.dev, ino: installed.ino };\n } finally {\n await handle?.close().catch(() => undefined);\n await fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function configDocumentStillMatches(document: LocalConfigDocument) {\n return fileIdentityAndContentsMatch(document.path, document.identity, document.bytes);\n}\n\nasync function claimCanonicalConfigDocument(document: LocalConfigDocument) {\n const quarantinePath = path.join(\n path.dirname(document.path),\n `.${path.basename(document.path)}.${randomUUID()}.schema-migration-source`,\n );\n try {\n await fs.rename(document.path, quarantinePath);\n await syncParentDirectory(document.path);\n } catch (error) {\n await restoreQuarantinedConfig(document.path, quarantinePath);\n throw error;\n }\n if (!(await fileIdentityAndContentsMatch(quarantinePath, document.identity, document.bytes))) {\n await restoreQuarantinedConfig(document.path, quarantinePath);\n throw settingsChangedError();\n }\n if (await pathExists(document.path)) {\n await restoreQuarantinedConfig(document.path, quarantinePath);\n throw new Error(\"Canonical settings changed concurrently; no settings were replaced.\");\n }\n return quarantinePath;\n}\n\nfunction settingsChangedError() {\n return new Error(\"pi-sync settings changed during migration; no settings were replaced.\");\n}\n\nasync function configSnapshotStillMatches(filePath: string, snapshot: ConfigSnapshot) {\n return fileIdentityAndContentsMatch(filePath, snapshot.identity, snapshot.bytes);\n}\n\nexport function quarantineAndRemoveConfigIfMatches(filePath: string, identity: FileIdentity, expectedBytes: Buffer) {\n return withLocalConfigFileLock(() => quarantineAndRemoveConfigIfMatchesUnlocked(filePath, identity, expectedBytes));\n}\n\nasync function quarantineAndRemoveConfigIfMatchesUnlocked(\n filePath: string,\n identity: FileIdentity,\n expectedBytes: Buffer,\n) {\n const quarantinePath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${randomUUID()}.migration-retired`,\n );\n try {\n await fs.rename(filePath, quarantinePath);\n } catch {\n return false;\n }\n await afterConfigQuarantinedHook();\n try {\n await syncParentDirectory(filePath);\n } catch {\n await restoreQuarantinedConfig(filePath, quarantinePath);\n return false;\n }\n\n const matches = await fileIdentityAndContentsMatch(quarantinePath, identity, expectedBytes);\n if (!matches) {\n await restoreQuarantinedConfig(filePath, quarantinePath);\n return false;\n }\n if (await pathExists(filePath)) {\n await fs.rm(quarantinePath, { force: true });\n await syncParentDirectory(filePath);\n return false;\n }\n await fs.rm(quarantinePath);\n await syncParentDirectory(filePath);\n return true;\n}\n\nasync function fileIdentityAndContentsMatch(filePath: string, identity: FileIdentity, expectedBytes: Buffer) {\n try {\n const current = await fs.lstat(filePath);\n if (current.isSymbolicLink()) return false;\n if (current.dev !== identity.dev || current.ino !== identity.ino) return false;\n return (await fs.readFile(filePath)).equals(expectedBytes);\n } catch {\n return false;\n }\n}\n\nasync function restoreQuarantinedConfig(filePath: string, quarantinePath: string) {\n try {\n await renameFileWithoutReplacement(quarantinePath, filePath);\n if (process.platform !== \"win32\") await fs.chmod(filePath, 0o600);\n await syncParentDirectory(filePath);\n return;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") return;\n }\n try {\n if (process.platform !== \"win32\") await fs.chmod(quarantinePath, 0o600);\n await syncParentDirectory(filePath);\n } catch {\n // Preserve the quarantine rather than risk deleting settings that changed concurrently.\n }\n}\n\nfunction configMutationLockPath() {\n return `${localConfigPath()}.mutation-lock`;\n}\n\nexport async function withLocalConfigFileLock<T>(run: () => Promise<T>): Promise<T> {\n const configPath = localConfigPath();\n await fs.mkdir(path.dirname(configPath), { recursive: true });\n let compromisedError: Error | undefined;\n const release = await lockfile.lock(configPath, {\n fs: LOCKFILE_FS_ADAPTER,\n lockfilePath: configMutationLockPath(),\n realpath: false,\n stale: CONFIG_LOCK_STALE_MS,\n update: CONFIG_LOCK_UPDATE_MS,\n retries: { retries: 100, factor: 1.2, minTimeout: 10, maxTimeout: 100 },\n onCompromised: (error) => {\n compromisedError = error;\n },\n });\n try {\n const result = await run();\n if (compromisedError) throw compromisedError;\n return result;\n } finally {\n await release();\n }\n}\n\nasync function syncParentDirectory(filePath: string) {\n if (process.platform === \"win32\") return;\n let handle: fs.FileHandle | undefined;\n try {\n handle = await fs.open(path.dirname(filePath), \"r\");\n await handle.sync();\n } finally {\n await handle?.close().catch(() => undefined);\n }\n}\n\nasync function publishFileWithoutReplacement(source: string, destination: string) {\n await beforeConfigPublicationHook();\n await renameFileWithoutReplacement(source, destination);\n}\n\nasync function renameFileWithoutReplacement(source: string, destination: string) {\n if (await pathExists(destination)) {\n throw Object.assign(new Error(`Settings already exist: ${destination}`), { code: \"EEXIST\" });\n }\n await fs.rename(source, destination);\n}\n\nasync function pathExists(filePath: string) {\n try {\n await fs.lstat(filePath);\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n}\n\nfunction recordConfigMigrationNotice(configPath: string, notice: string) {\n if (!configMigrationNotices.has(configPath)) configMigrationNotices.set(configPath, notice);\n}\n", "import path from \"node:path\";\nimport { normalizeEndpointIdentity } from \"../backends/backend-identity.js\";\nimport {\n normalizeGitBranch,\n normalizeGitDirectory,\n normalizeGitRemote,\n normalizeGitRemoteIdentity,\n} from \"../backends/git/git-config.js\";\nimport {\n normalizeWebDavIdentityUrl,\n normalizeWebDavPath,\n normalizeWebDavUrl,\n validateWebDavCredentials,\n} from \"../backends/webdav/webdav-config.js\";\nimport { normalizeLocalFields } from \"../sync/local-fields.js\";\nimport { normalizeSyncInclude } from \"../sync/sync-policy.js\";\nimport { localConfigPath } from \"./config-file.js\";\nimport type {\n OnSwitchAction,\n PiSyncSettingsV3,\n StorageConnectionSettings,\n SyncSetupSettings,\n} from \"./settings-types.js\";\n\nexport const DEFAULT_ON_SWITCH: OnSwitchAction = \"ask-before-pull\";\n\nexport function normalizeOnSwitch(value: unknown): OnSwitchAction {\n if (value === \"ask-before-pull\" || value === \"pull-after-switch\" || value === \"switch-only\") {\n return value;\n }\n throw new Error(\n 'Invalid pi-sync settings: onSwitch must be \"ask-before-pull\", \"pull-after-switch\", or \"switch-only\".',\n );\n}\n\nexport function validateSettingsDocument(value: Record<string, unknown>): PiSyncSettingsV3 {\n if (value.version !== 3 && value.version !== 4 && value.version !== 5) {\n throw new Error(\n `Unsupported pi-sync settings: version 3 or 4 or 5 is required. Keep the existing ${path.basename(localConfigPath())} for recovery and use a compatible pi-sync client or review a separate supported setup; do not downgrade portable field policies. pi-sync will not migrate or overwrite unsupported settings.`,\n );\n }\n rejectLegacyFields(\n value,\n [\n \"profiles\",\n \"targets\",\n \"activeTarget\",\n \"targetSwitchAction\",\n \"endpoint\",\n \"bucket\",\n \"region\",\n \"accessKeyId\",\n \"secretAccessKey\",\n \"sessionToken\",\n \"profile\",\n \"prefix\",\n \"autoSync\",\n \"syncFiles\",\n \"syncSessions\",\n \"extraFiles\",\n ],\n \"top level\",\n );\n normalizeOnSwitch(value.onSwitch);\n if (value.skipSecretScan !== undefined && typeof value.skipSecretScan !== \"boolean\") {\n throw new Error(\"Invalid pi-sync settings: skipSecretScan must be boolean.\");\n }\n if (value.showStatus !== undefined && typeof value.showStatus !== \"boolean\") {\n throw new Error(\"Invalid pi-sync settings: showStatus must be boolean.\");\n }\n if (value.debug !== undefined && typeof value.debug !== \"boolean\") {\n throw new Error(\"Invalid pi-sync settings: debug must be boolean.\");\n }\n const storageConnections = requireNamedObjectMap(\n value.storageConnections,\n \"storageConnections\",\n \"storage connection\",\n );\n const syncSetups = requireNamedObjectMap(value.syncSetups, \"syncSetups\", \"sync setup\");\n for (const name of Object.keys(storageConnections)) {\n validateStorageConnection(\n name,\n requireOwnObject(storageConnections, name, \"storage connection\") as Record<string, unknown>,\n );\n }\n for (const name of Object.keys(syncSetups)) {\n validateSyncSetup(\n name,\n requireOwnObject(syncSetups, name, \"sync setup\") as Record<string, unknown>,\n storageConnections,\n );\n }\n const names = Object.keys(syncSetups);\n const activeSyncSetup = optionalCanonicalReference(value.activeSyncSetup, \"activeSyncSetup\");\n if (names.length === 0) {\n if (activeSyncSetup !== undefined) {\n throw new Error(\"Invalid pi-sync settings: empty syncSetups cannot have activeSyncSetup.\");\n }\n } else if (!activeSyncSetup || !Object.hasOwn(syncSetups, activeSyncSetup)) {\n throw new Error(\"Invalid pi-sync settings: activeSyncSetup must reference an existing own-property sync setup.\");\n }\n for (const setup of Object.values(syncSetups)) {\n const policy = (setup as SyncSetupSettings).sync;\n if (policy.localFields !== undefined && value.version !== 4 && value.version !== 5)\n throw new Error(\"localFields requires explicit settings version 4; older binaries must refuse portable state.\");\n }\n for (const setup of Object.values(syncSetups)) {\n const policy = (setup as SyncSetupSettings).sync;\n if ((policy.mergeContent || policy.partialSync) && value.version !== 5)\n throw new Error(\"Content/partial sync requires explicit settings version 5.\");\n }\n validateUniqueRemoteSyncSetups(syncSetups, storageConnections);\n return value as PiSyncSettingsV3;\n}\n\nfunction validateStorageConnection(name: string, value: Record<string, unknown>) {\n rejectLegacyFields(\n value,\n [\"kind\", \"accessKeyId\", \"secretAccessKey\", \"sessionToken\", \"username\", \"password\"],\n `storage connection \u201C${name}\u201D`,\n );\n const type = requiredString(value.type, `storage connection \u201C${name}\u201D type`);\n if (type !== \"s3\" && type !== \"git\" && type !== \"webdav\") {\n throw new Error(`Invalid pi-sync settings: storage connection \u201C${name}\u201D has unsupported type.`);\n }\n const known = [\"endpoint\", \"region\", \"remote\", \"url\", \"credentials\"];\n const allowed =\n type === \"s3\"\n ? new Set([\"endpoint\", \"region\", \"credentials\"])\n : type === \"git\"\n ? new Set([\"remote\"])\n : new Set([\"url\", \"credentials\"]);\n if (known.some((field) => Object.hasOwn(value, field) && !allowed.has(field))) {\n throw new Error(\n `Invalid pi-sync settings: ${type.toUpperCase()} storage connection \u201C${name}\u201D mixes backend fields.`,\n );\n }\n if (type === \"git\") {\n if (!normalizeGitRemote(requiredString(value.remote, `Git remote for \u201C${name}\u201D`))) {\n throw new Error(`Invalid pi-sync settings: Git remote for \u201C${name}\u201D is required.`);\n }\n return;\n }\n const credentials = requireRecord(value.credentials, `credentials for storage connection \u201C${name}\u201D`);\n if (type === \"webdav\") {\n normalizeWebDavUrl(requiredString(value.url, `WebDAV URL for \u201C${name}\u201D`));\n const username = requiredString(credentials.username, `WebDAV username for \u201C${name}\u201D`);\n const password = requiredSecret(credentials.password, `WebDAV password for \u201C${name}\u201D`);\n if ([\"accessKeyId\", \"secretAccessKey\", \"sessionToken\"].some((field) => Object.hasOwn(credentials, field))) {\n throw new Error(`Invalid pi-sync settings: WebDAV credentials for \u201C${name}\u201D mix fields.`);\n }\n validateWebDavCredentials(username, password);\n return;\n }\n normalizeS3Endpoint(requiredString(value.endpoint, `S3 endpoint for \u201C${name}\u201D`));\n requiredString(value.region, `S3 region for \u201C${name}\u201D`);\n requiredString(credentials.accessKeyId, `S3 access key id for \u201C${name}\u201D`);\n requiredSecret(credentials.secretAccessKey, `S3 secret access key for \u201C${name}\u201D`);\n optionalString(credentials.sessionToken, `S3 session token for \u201C${name}\u201D`);\n if ([\"username\", \"password\"].some((field) => Object.hasOwn(credentials, field))) {\n throw new Error(`Invalid pi-sync settings: S3 credentials for \u201C${name}\u201D mix fields.`);\n }\n}\n\nfunction validateSyncSetup(name: string, value: Record<string, unknown>, connections: Record<string, unknown>) {\n rejectLegacyFields(\n value,\n [\n \"profile\",\n \"bucket\",\n \"branch\",\n \"path\",\n \"prefix\",\n \"directory\",\n \"namespace\",\n \"autoSync\",\n \"syncFiles\",\n \"syncSessions\",\n \"extraFiles\",\n ],\n `sync setup \u201C${name}\u201D`,\n );\n const storage = requireRecord(value.storage, `storage for sync setup \u201C${name}\u201D`);\n const sync = requireRecord(value.sync, `sync policy for sync setup \u201C${name}\u201D`);\n rejectLegacyFields(storage, [\"profile\", \"prefix\", \"directory\", \"namespace\"], `storage for sync setup \u201C${name}\u201D`);\n rejectLegacyFields(\n sync,\n [\"autoSync\", \"syncFiles\", \"syncSessions\", \"extraFiles\"],\n `sync policy for sync setup \u201C${name}\u201D`,\n );\n const connectionName = requiredCanonicalReference(\n storage.connection,\n `storage connection reference for sync setup \u201C${name}\u201D`,\n );\n validateConfigName(connectionName, \"storage connection reference\");\n const connection = ownObject<Record<string, unknown>>(connections, connectionName);\n if (!connection) {\n throw new Error(\n `Invalid pi-sync settings: sync setup \u201C${name}\u201D references missing storage connection \u201C${connectionName}\u201D.`,\n );\n }\n const type = connection.type;\n normalizeStoragePath(requiredString(storage.path, `storage path for sync setup \u201C${name}\u201D`));\n if (type === \"s3\") {\n normalizeS3Bucket(requiredString(storage.bucket, `S3 bucket for sync setup \u201C${name}\u201D`));\n if (Object.hasOwn(storage, \"branch\")) mixedSetupError(\"S3\", name);\n } else if (type === \"git\") {\n normalizeGitBranch(requiredString(storage.branch, `Git branch for sync setup \u201C${name}\u201D`));\n if (Object.hasOwn(storage, \"bucket\")) mixedSetupError(\"Git\", name);\n } else if (type === \"webdav\") {\n if (Object.hasOwn(storage, \"bucket\") || Object.hasOwn(storage, \"branch\")) {\n mixedSetupError(\"WebDAV\", name);\n }\n }\n if (!Object.hasOwn(sync, \"include\")) {\n throw new Error(`Invalid pi-sync settings: sync setup \u201C${name}\u201D is missing sync.include.`);\n }\n const include = normalizeSyncInclude(sync.include);\n const localFields = normalizeLocalFields(sync.localFields);\n if (localFields.length > 0 && !include.includes(\"settings.json\"))\n throw new Error(\"Nonempty localFields requires settings.json in sync.include.\");\n for (const key of [\"mergeContent\", \"partialSync\", \"agentMode\", \"continuous\"])\n if (sync[key] !== undefined && typeof sync[key] !== \"boolean\") throw new Error(`${key} must be boolean.`);\n if (sync.mergeSettings !== undefined && typeof sync.mergeSettings !== \"boolean\")\n throw new Error(\"mergeSettings must be boolean.\");\n if (sync.automaticTransfer !== undefined && typeof sync.automaticTransfer !== \"boolean\") {\n throw new Error(`Invalid pi-sync settings: sync setup \u201C${name}\u201D sync.automaticTransfer must be boolean.`);\n }\n if (typeof sync.automatic !== \"boolean\") {\n throw new Error(`Invalid pi-sync settings: sync setup \u201C${name}\u201D sync.automatic must be boolean.`);\n }\n}\n\nfunction mixedSetupError(type: string, name: string): never {\n throw new Error(`Invalid pi-sync settings: ${type} sync setup \u201C${name}\u201D mixes backend fields.`);\n}\n\nexport function validateUniqueRemoteSyncSetups(setups: Record<string, unknown>, connections: Record<string, unknown>) {\n const identities = new Map<string, string>();\n for (const name of Object.keys(setups)) {\n const setup = requireOwnObject(setups, name, \"sync setup\") as unknown as SyncSetupSettings;\n const connection = requireOwnObject(\n connections,\n setup.storage.connection,\n \"storage connection\",\n ) as unknown as StorageConnectionSettings;\n const identity = effectiveSyncSetupRemoteIdentity(setup, connection);\n const existing = identities.get(identity);\n if (existing) {\n throw new Error(\n `Invalid pi-sync settings: sync setups \u201C${existing}\u201D and \u201C${name}\u201D use the same normalized remote location.`,\n );\n }\n identities.set(identity, name);\n }\n}\n\nexport function effectiveSyncSetupRemoteIdentity(setup: SyncSetupSettings, connection: StorageConnectionSettings) {\n const storagePath = normalizeStoragePath(setup.storage.path);\n if (connection.type === \"git\") {\n return JSON.stringify([\n \"git\",\n normalizeGitRemoteIdentity(connection.remote),\n normalizeGitBranch(setup.storage.branch),\n normalizeGitDirectory(storagePath),\n ]);\n }\n if (connection.type === \"webdav\") {\n return JSON.stringify([\n \"webdav\",\n normalizeWebDavIdentityUrl(connection.url),\n connection.credentials.username.trim(),\n normalizeWebDavPath(storagePath),\n ]);\n }\n return JSON.stringify([\n \"s3\",\n normalizeEndpointIdentity(connection.endpoint),\n normalizeS3Bucket(setup.storage.bucket),\n storagePath,\n ]);\n}\n\nfunction rejectLegacyFields(value: Record<string, unknown>, fields: readonly string[], context: string) {\n const field = fields.find((candidate) => Object.hasOwn(value, candidate));\n if (field) {\n throw new Error(`Invalid pi-sync settings: ${context} contains unsupported version 1/2 field \u201C${field}\u201D.`);\n }\n}\n\nfunction requireNamedObjectMap(value: unknown, field: string, itemLabel: string) {\n const result = requireRecord(value, field);\n for (const name of Object.keys(result)) validateConfigName(name, itemLabel);\n return result;\n}\n\nfunction requireOwnObject(value: Record<string, unknown>, key: string, label: string) {\n const item = ownObject(value, key);\n if (!item) throw new Error(`Invalid pi-sync settings: ${label} \u201C${key}\u201D must be an object.`);\n return item;\n}\n\nexport function ownObject<T extends object>(value: Record<string, unknown>, key: string): T | undefined {\n if (!Object.hasOwn(value, key)) return undefined;\n const item = value[key];\n return item && typeof item === \"object\" && !Array.isArray(item) ? (item as T) : undefined;\n}\n\nfunction requireRecord(value: unknown, field: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`Invalid pi-sync settings: ${field} must be an object.`);\n }\n return value as Record<string, unknown>;\n}\n\nexport function validateConfigName(value: string, field: string) {\n if (\n !value.trim() ||\n value !== value.trim() ||\n value.length > 100 ||\n value === \"__proto__\" ||\n value === \"prototype\" ||\n value === \"constructor\" ||\n hasControlCharacter(value)\n ) {\n throw new Error(`Invalid pi-sync settings: invalid ${field} name.`);\n }\n}\n\nexport function requiredString(value: unknown, field: string) {\n if (typeof value !== \"string\" || !value.trim() || hasControlCharacter(value)) {\n throw new Error(`Invalid pi-sync settings: ${field} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction requiredCanonicalReference(value: unknown, field: string) {\n const normalized = requiredString(value, field);\n if (value !== normalized) {\n throw new Error(`Invalid pi-sync settings: ${field} must not have surrounding whitespace.`);\n }\n return normalized;\n}\n\nfunction optionalCanonicalReference(value: unknown, field: string) {\n const normalized = optionalString(value, field);\n if (normalized !== undefined && value !== normalized) {\n throw new Error(`Invalid pi-sync settings: ${field} must not have surrounding whitespace.`);\n }\n return normalized;\n}\n\nfunction requiredSecret(value: unknown, field: string) {\n if (typeof value !== \"string\" || !value || hasControlCharacter(value)) {\n throw new Error(`Invalid pi-sync settings: ${field} must be configured.`);\n }\n return value;\n}\n\nexport function optionalString(value: unknown, field: string) {\n if (value === undefined) return undefined;\n if (typeof value !== \"string\" || hasControlCharacter(value)) {\n throw new Error(`Invalid pi-sync settings: ${field} must be a string.`);\n }\n return value.trim() || undefined;\n}\n\nexport function normalizeStoragePath(value: string) {\n if (value.trim() === \".\" || value.trim() === \"./\") return \"./\";\n const normalized = value.trim().replace(/^\\/+|\\/+$/gu, \"\");\n if (\n !normalized ||\n normalized.length > 1024 ||\n normalized.startsWith(\"-\") ||\n normalized.includes(\"\\\\\") ||\n hasControlCharacter(normalized) ||\n normalized.split(\"/\").some((segment) => !segment || segment === \".\" || segment === \"..\")\n ) {\n throw new Error(\"Invalid pi-sync settings: storage.path must be a safe relative path.\");\n }\n return normalized;\n}\n\nexport function normalizeS3Endpoint(value: string) {\n let url: URL;\n try {\n url = new URL(value.trim());\n } catch {\n throw new Error(\"Invalid pi-sync S3 endpoint.\");\n }\n const loopback = url.hostname === \"127.0.0.1\" || url.hostname === \"localhost\" || url.hostname === \"[::1]\";\n if (\n (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && loopback)) ||\n url.username ||\n url.password ||\n url.search ||\n url.hash\n ) {\n throw new Error(\"Invalid pi-sync S3 endpoint: HTTPS is required except for loopback.\");\n }\n url.pathname = url.pathname.replace(/\\/+$/gu, \"\");\n return url.toString().replace(/\\/$/u, \"\");\n}\n\nexport function normalizeS3Bucket(value: string | undefined) {\n const bucket = requiredString(value, \"S3 bucket\");\n if (bucket.includes(\"/\") || bucket.includes(\"\\\\\") || bucket.startsWith(\"-\")) {\n throw new Error(\"Invalid pi-sync S3 bucket.\");\n }\n return bucket;\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Stored settings cannot contain controls.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n\nexport function isCloudflareR2Endpoint(endpoint: string | undefined) {\n const value = endpoint?.trim();\n if (!value) return false;\n try {\n const hostname = new URL(value).hostname.toLowerCase();\n return hostname === \"r2.cloudflarestorage.com\" || hostname.endsWith(\".r2.cloudflarestorage.com\");\n } catch {\n return false;\n }\n}\n\nexport function ownRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n", "import { localConfigPath, readMigratingLocalConfigDocument, updateLocalConfigDocument } from \"./config-file.js\";\nimport type { OnSwitchAction, PiSyncSettingsV3 } from \"./settings-types.js\";\nimport { DEFAULT_ON_SWITCH, validateSettingsDocument } from \"./settings-validation.js\";\n\nlet configUpdateQueue: Promise<void> = Promise.resolve();\n\nexport async function requireSettings() {\n const settings = await readLocalConfigObject();\n if (!settings) {\n throw new Error(`Missing pi-sync settings. Open /sync and choose Set up sync, or create ${localConfigPath()}.`);\n }\n return settings;\n}\n\nexport async function configuredSyncSetupNames() {\n const settings = await readLocalConfigObject();\n return settings ? Object.keys(settings.syncSetups).sort((left, right) => left.localeCompare(right)) : [];\n}\n\nexport async function loadOnSwitch(): Promise<OnSwitchAction> {\n return (await requireSettings()).onSwitch;\n}\n\nexport function localConfigTemplate(): PiSyncSettingsV3 {\n return {\n version: 3,\n onSwitch: DEFAULT_ON_SWITCH,\n skipSecretScan: false,\n showStatus: true,\n debug: false,\n storageConnections: {},\n syncSetups: {},\n };\n}\n\nexport async function readLocalConfigDocument() {\n const document = await readMigratingLocalConfigDocument((settings) => {\n validateSettingsDocument(settings);\n });\n if (document) validateSettingsDocument(document.parsed);\n return document;\n}\n\nexport async function readLocalConfigObject(): Promise<PiSyncSettingsV3 | undefined> {\n return (await readLocalConfigDocument())?.parsed as PiSyncSettingsV3 | undefined;\n}\n\nexport function updateLocalConfig(update: (current: PiSyncSettingsV3) => PiSyncSettingsV3, signal?: AbortSignal) {\n const operation = configUpdateQueue.then(() => {\n signal?.throwIfAborted();\n return performLocalConfigUpdate(update, signal);\n });\n configUpdateQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n return operation;\n}\n\nasync function performLocalConfigUpdate(update: (current: PiSyncSettingsV3) => PiSyncSettingsV3, signal?: AbortSignal) {\n return updateLocalConfigDocument(localConfigTemplate(), update, validateSettingsDocument, signal);\n}\n"],
5
- "mappings": "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",
6
- "names": ["installed", "path", "path"]
7
- }