@narumitw/pi-sync 0.57.10 → 0.57.12

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 (173) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +32 -22
  3. package/dist/chunks/{agent-candidate-EYB35AGL.ts → agent-candidate-U2NU3GUX.ts} +11 -11
  4. package/dist/chunks/{agent-plan-KO43GTOR.ts → agent-plan-3YXDIJXO.ts} +25 -22
  5. package/dist/chunks/agent-plan-3YXDIJXO.ts.map +7 -0
  6. package/dist/chunks/{agent-refusal-retry-C2HQROTP.ts → agent-refusal-retry-476YGNU5.ts} +10 -10
  7. package/dist/chunks/{agent-runner-WMSCKSCB.ts → agent-runner-FCRV2Z75.ts} +11 -10
  8. package/dist/chunks/agent-runner-FCRV2Z75.ts.map +7 -0
  9. package/dist/chunks/{agent-store-UT52DS7B.ts → agent-store-7GINKTS7.ts} +8 -8
  10. package/dist/chunks/{agent-store-UT52DS7B.ts.map → agent-store-7GINKTS7.ts.map} +2 -2
  11. package/dist/chunks/{agent-sync-VM3TXWA3.ts → agent-sync-P6AWQXGK.ts} +6 -6
  12. package/dist/chunks/{chunk-JXWTEJS5.ts → chunk-45COPAK7.ts} +10 -3
  13. package/dist/chunks/chunk-45COPAK7.ts.map +7 -0
  14. package/dist/chunks/{chunk-DOJRPBQU.ts → chunk-5TSCBBPP.ts} +4 -4
  15. package/dist/chunks/{chunk-CDQGSZL3.ts → chunk-6LD5KX55.ts} +6 -6
  16. package/dist/chunks/{chunk-MDUORMCK.ts → chunk-6O3EDBRL.ts} +2 -2
  17. package/dist/chunks/{chunk-AAPAHANE.ts → chunk-7A35ZAVO.ts} +320 -219
  18. package/dist/chunks/chunk-7A35ZAVO.ts.map +7 -0
  19. package/dist/chunks/{chunk-STVQQ5KG.ts → chunk-7ZIYU5QS.ts} +6 -6
  20. package/dist/chunks/{chunk-AO6EDUA6.ts → chunk-AKMV47YC.ts} +3 -3
  21. package/dist/chunks/{chunk-66GAUVDL.ts → chunk-BEST45H2.ts} +6 -6
  22. package/dist/chunks/{chunk-DO55XUNU.ts → chunk-CBLTWXAU.ts} +15 -5
  23. package/dist/chunks/chunk-CBLTWXAU.ts.map +7 -0
  24. package/dist/chunks/{chunk-IMMMZUFC.ts → chunk-CQD2TJHE.ts} +7 -7
  25. package/dist/chunks/{chunk-IMMMZUFC.ts.map → chunk-CQD2TJHE.ts.map} +2 -2
  26. package/dist/chunks/{chunk-73MDIVYJ.ts → chunk-DN4IA7MR.ts} +6 -6
  27. package/dist/chunks/{chunk-PHANBTVM.ts → chunk-ESKOPQVB.ts} +4 -4
  28. package/dist/chunks/{chunk-YZ5BQNRZ.ts → chunk-FHE2DCA2.ts} +2 -2
  29. package/dist/chunks/{chunk-YZ5BQNRZ.ts.map → chunk-FHE2DCA2.ts.map} +2 -2
  30. package/dist/chunks/{chunk-MRIPZGPR.ts → chunk-FLHCOJCD.ts} +3 -3
  31. package/dist/chunks/{chunk-5WJQ6XOW.ts → chunk-GNYGNHFF.ts} +2 -2
  32. package/dist/chunks/{chunk-DFJGTVPX.ts → chunk-KYTT7KV4.ts} +2 -2
  33. package/dist/chunks/{chunk-UGSSZWQ6.ts → chunk-MKSMJPVA.ts} +2 -2
  34. package/dist/chunks/{chunk-2VSN3MFX.ts → chunk-MMQIEDZ6.ts} +33 -27
  35. package/dist/chunks/chunk-MMQIEDZ6.ts.map +7 -0
  36. package/dist/chunks/{chunk-RAMHGOX2.ts → chunk-OJARL2TG.ts} +4 -4
  37. package/dist/chunks/{chunk-BJXSCGQK.ts → chunk-OKPPZA4D.ts} +148 -89
  38. package/dist/chunks/chunk-OKPPZA4D.ts.map +7 -0
  39. package/dist/chunks/{chunk-RX3WGWVL.ts → chunk-OVBAW7KV.ts} +177 -130
  40. package/dist/chunks/chunk-OVBAW7KV.ts.map +7 -0
  41. package/dist/chunks/{chunk-U77DWNRH.ts → chunk-Q23JJW7E.ts} +3 -3
  42. package/dist/chunks/{chunk-NLWS55B6.ts → chunk-QPC5HT3A.ts} +2 -2
  43. package/dist/chunks/{chunk-NLWS55B6.ts.map → chunk-QPC5HT3A.ts.map} +1 -1
  44. package/dist/chunks/{chunk-4RLATUP4.ts → chunk-S5OCYVPS.ts} +7 -7
  45. package/dist/chunks/{chunk-4RLATUP4.ts.map → chunk-S5OCYVPS.ts.map} +2 -2
  46. package/dist/chunks/{chunk-QWV3XKNJ.ts → chunk-TIMWN2RH.ts} +5 -5
  47. package/dist/chunks/{chunk-Z5O2TLNF.ts → chunk-TZC7GDJE.ts} +7 -7
  48. package/dist/chunks/{chunk-UCD7TQDT.ts → chunk-U6GXGY5G.ts} +5 -5
  49. package/dist/chunks/{chunk-PWA3YN5Z.ts → chunk-XEODG2PE.ts} +3 -3
  50. package/dist/chunks/{chunk-TO2GMX3K.ts → chunk-XJHQPB3E.ts} +2 -2
  51. package/dist/chunks/{chunk-JY2RVOUL.ts → chunk-Y4UVXOLQ.ts} +5 -5
  52. package/dist/chunks/{chunk-ODF2M4RF.ts → chunk-ZC3IHFNM.ts} +8 -8
  53. package/dist/chunks/{chunk-ODF2M4RF.ts.map → chunk-ZC3IHFNM.ts.map} +2 -2
  54. package/dist/chunks/{chunk-M5IV3KL2.ts → chunk-ZDDBZH72.ts} +3 -3
  55. package/dist/chunks/{command-handler-FO6F2APH.ts → command-handler-VKLZBRLO.ts} +26 -21
  56. package/dist/chunks/command-handler-VKLZBRLO.ts.map +7 -0
  57. package/dist/chunks/{config-B37W7FXW.ts → config-HYG7G5EM.ts} +6 -4
  58. package/dist/chunks/{conflict-artifacts-6XGSSU5S.ts → conflict-artifacts-J6WSDCWP.ts} +12 -12
  59. package/dist/chunks/{conflict-review-BQSHSJB3.ts → conflict-review-GXA6Y7KY.ts} +23 -23
  60. package/dist/chunks/{continuous-record-4DQ2EAZS.ts → continuous-record-EPHGR2DU.ts} +6 -6
  61. package/dist/chunks/{continuous-sync-ZT3UEQLK.ts → continuous-sync-TTOSJCQU.ts} +18 -18
  62. package/dist/chunks/{file-selection-FBLKM25V.ts → file-selection-IELTXSGZ.ts} +6 -7
  63. package/dist/chunks/{file-selection-FBLKM25V.ts.map → file-selection-IELTXSGZ.ts.map} +1 -1
  64. package/dist/chunks/{git-backend-7PCWECRN.ts → git-backend-KHD36W27.ts} +6 -7
  65. package/dist/chunks/{git-backend-7PCWECRN.ts.map → git-backend-KHD36W27.ts.map} +1 -1
  66. package/dist/chunks/{local-fields-B6JWLPAE.ts → local-fields-JEKAPZKD.ts} +6 -7
  67. package/dist/chunks/manager-result-dispatcher-6W52NM7F.ts +32 -0
  68. package/dist/chunks/{manager-ui-DGRTG76I.ts → manager-ui-INVMAFEN.ts} +245 -224
  69. package/dist/chunks/manager-ui-INVMAFEN.ts.map +7 -0
  70. package/dist/chunks/{merge-baseline-store-HL3VLMAM.ts → merge-baseline-store-65GKUMXI.ts} +6 -6
  71. package/dist/chunks/{remote-selection-ui-OHMIQ32X.ts → remote-selection-ui-TD4C4W3J.ts} +16 -12
  72. package/dist/chunks/{s3-backend-CJXBEWWU.ts → s3-backend-L24UZ6IK.ts} +12 -10
  73. package/dist/chunks/s3-backend-L24UZ6IK.ts.map +7 -0
  74. package/dist/chunks/{setup-switch-66GWMBNH.ts → setup-switch-KLGESLQX.ts} +6 -6
  75. package/dist/chunks/{setup-wizard-OHZXJVQZ.ts → setup-wizard-ZQAK35BP.ts} +7 -7
  76. package/dist/chunks/{snapshot-VRHNAUUH.ts → snapshot-RGNDYT6A.ts} +5 -6
  77. package/dist/chunks/{snapshot-transaction-EUGA4VX6.ts → snapshot-transaction-26BQO36S.ts} +8 -8
  78. package/dist/chunks/{sync-inspection-4WFQEJOE.ts → sync-inspection-MOMLGUTD.ts} +11 -11
  79. package/dist/chunks/{sync-operations-X4AOXMBT.ts → sync-operations-TMGQHBF5.ts} +26 -26
  80. package/dist/chunks/{sync-operations-X4AOXMBT.ts.map → sync-operations-TMGQHBF5.ts.map} +2 -2
  81. package/dist/chunks/{sync-state-SWLSMK4G.ts → sync-state-7L4NT7W2.ts} +7 -8
  82. package/dist/chunks/{webdav-backend-2Q5ZEBST.ts → webdav-backend-3ZCACILP.ts} +7 -8
  83. package/dist/chunks/{webdav-backend-2Q5ZEBST.ts.map → webdav-backend-3ZCACILP.ts.map} +1 -1
  84. package/dist/index.ts +20 -20
  85. package/docs/agent-continuous-hardening.md +5 -5
  86. package/docs/agent-mode-verification.md +3 -3
  87. package/docs/agent-quality-verification.md +3 -3
  88. package/docs/continuous-sync-verification.md +2 -2
  89. package/docs/settings.md +9 -5
  90. package/docs/tui-contract.md +20 -3
  91. package/package.json +3 -3
  92. package/skills/configure-pi-sync/SKILL.md +3 -1
  93. package/skills/configure-pi-sync/references/configuration.md +56 -38
  94. package/src/backends/s3/s3-client.ts +8 -1
  95. package/src/commands/command-execution.ts +11 -6
  96. package/src/commands/command.ts +1 -1
  97. package/src/paths.ts +6 -1
  98. package/src/settings/config-file.ts +205 -118
  99. package/src/settings/config.ts +1 -1
  100. package/src/settings/settings-management.ts +15 -1
  101. package/src/settings/settings-store.ts +0 -14
  102. package/src/settings/settings-types.ts +1 -1
  103. package/src/snapshot/session-paths.ts +15 -2
  104. package/src/snapshot/snapshot-mutation-queues.ts +142 -0
  105. package/src/snapshot/snapshot-transaction.ts +122 -125
  106. package/src/sync/agent-candidate.ts +3 -3
  107. package/src/sync/agent-plan.ts +11 -8
  108. package/src/sync/agent-runner.ts +10 -9
  109. package/src/sync/agent-store.ts +1 -1
  110. package/src/sync/agent-sync.ts +2 -2
  111. package/src/sync/continuous-record.ts +1 -1
  112. package/src/sync/merge-apply.ts +6 -0
  113. package/src/sync/merged-sync.ts +4 -4
  114. package/src/sync/sync-mutations.ts +1 -1
  115. package/src/ui/agent-mode-setting.ts +6 -6
  116. package/src/ui/cancellable-operation.ts +36 -13
  117. package/src/ui/manager-state.ts +4 -2
  118. package/src/ui/manager-ui.ts +76 -24
  119. package/src/ui/remote-selection-ui.ts +131 -82
  120. package/src/ui/settings-ui.ts +21 -56
  121. package/src/ui/setup/setup-switcher.ts +2 -2
  122. package/src/ui/sync-setups-ui.ts +2 -2
  123. package/dist/chunks/agent-plan-KO43GTOR.ts.map +0 -7
  124. package/dist/chunks/agent-runner-WMSCKSCB.ts.map +0 -7
  125. package/dist/chunks/chunk-2VSN3MFX.ts.map +0 -7
  126. package/dist/chunks/chunk-AAPAHANE.ts.map +0 -7
  127. package/dist/chunks/chunk-BJXSCGQK.ts.map +0 -7
  128. package/dist/chunks/chunk-DO55XUNU.ts.map +0 -7
  129. package/dist/chunks/chunk-JXWTEJS5.ts.map +0 -7
  130. package/dist/chunks/chunk-RX3WGWVL.ts.map +0 -7
  131. package/dist/chunks/command-handler-FO6F2APH.ts.map +0 -7
  132. package/dist/chunks/manager-result-dispatcher-NODX3KKH.ts +0 -28
  133. package/dist/chunks/manager-ui-DGRTG76I.ts.map +0 -7
  134. package/dist/chunks/s3-backend-CJXBEWWU.ts.map +0 -7
  135. /package/dist/chunks/{agent-candidate-EYB35AGL.ts.map → agent-candidate-U2NU3GUX.ts.map} +0 -0
  136. /package/dist/chunks/{agent-refusal-retry-C2HQROTP.ts.map → agent-refusal-retry-476YGNU5.ts.map} +0 -0
  137. /package/dist/chunks/{agent-sync-VM3TXWA3.ts.map → agent-sync-P6AWQXGK.ts.map} +0 -0
  138. /package/dist/chunks/{chunk-DOJRPBQU.ts.map → chunk-5TSCBBPP.ts.map} +0 -0
  139. /package/dist/chunks/{chunk-CDQGSZL3.ts.map → chunk-6LD5KX55.ts.map} +0 -0
  140. /package/dist/chunks/{chunk-MDUORMCK.ts.map → chunk-6O3EDBRL.ts.map} +0 -0
  141. /package/dist/chunks/{chunk-STVQQ5KG.ts.map → chunk-7ZIYU5QS.ts.map} +0 -0
  142. /package/dist/chunks/{chunk-AO6EDUA6.ts.map → chunk-AKMV47YC.ts.map} +0 -0
  143. /package/dist/chunks/{chunk-66GAUVDL.ts.map → chunk-BEST45H2.ts.map} +0 -0
  144. /package/dist/chunks/{chunk-73MDIVYJ.ts.map → chunk-DN4IA7MR.ts.map} +0 -0
  145. /package/dist/chunks/{chunk-PHANBTVM.ts.map → chunk-ESKOPQVB.ts.map} +0 -0
  146. /package/dist/chunks/{chunk-MRIPZGPR.ts.map → chunk-FLHCOJCD.ts.map} +0 -0
  147. /package/dist/chunks/{chunk-5WJQ6XOW.ts.map → chunk-GNYGNHFF.ts.map} +0 -0
  148. /package/dist/chunks/{chunk-DFJGTVPX.ts.map → chunk-KYTT7KV4.ts.map} +0 -0
  149. /package/dist/chunks/{chunk-UGSSZWQ6.ts.map → chunk-MKSMJPVA.ts.map} +0 -0
  150. /package/dist/chunks/{chunk-RAMHGOX2.ts.map → chunk-OJARL2TG.ts.map} +0 -0
  151. /package/dist/chunks/{chunk-U77DWNRH.ts.map → chunk-Q23JJW7E.ts.map} +0 -0
  152. /package/dist/chunks/{chunk-QWV3XKNJ.ts.map → chunk-TIMWN2RH.ts.map} +0 -0
  153. /package/dist/chunks/{chunk-Z5O2TLNF.ts.map → chunk-TZC7GDJE.ts.map} +0 -0
  154. /package/dist/chunks/{chunk-UCD7TQDT.ts.map → chunk-U6GXGY5G.ts.map} +0 -0
  155. /package/dist/chunks/{chunk-PWA3YN5Z.ts.map → chunk-XEODG2PE.ts.map} +0 -0
  156. /package/dist/chunks/{chunk-TO2GMX3K.ts.map → chunk-XJHQPB3E.ts.map} +0 -0
  157. /package/dist/chunks/{chunk-JY2RVOUL.ts.map → chunk-Y4UVXOLQ.ts.map} +0 -0
  158. /package/dist/chunks/{chunk-M5IV3KL2.ts.map → chunk-ZDDBZH72.ts.map} +0 -0
  159. /package/dist/chunks/{config-B37W7FXW.ts.map → config-HYG7G5EM.ts.map} +0 -0
  160. /package/dist/chunks/{conflict-artifacts-6XGSSU5S.ts.map → conflict-artifacts-J6WSDCWP.ts.map} +0 -0
  161. /package/dist/chunks/{conflict-review-BQSHSJB3.ts.map → conflict-review-GXA6Y7KY.ts.map} +0 -0
  162. /package/dist/chunks/{continuous-record-4DQ2EAZS.ts.map → continuous-record-EPHGR2DU.ts.map} +0 -0
  163. /package/dist/chunks/{continuous-sync-ZT3UEQLK.ts.map → continuous-sync-TTOSJCQU.ts.map} +0 -0
  164. /package/dist/chunks/{local-fields-B6JWLPAE.ts.map → local-fields-JEKAPZKD.ts.map} +0 -0
  165. /package/dist/chunks/{manager-result-dispatcher-NODX3KKH.ts.map → manager-result-dispatcher-6W52NM7F.ts.map} +0 -0
  166. /package/dist/chunks/{merge-baseline-store-HL3VLMAM.ts.map → merge-baseline-store-65GKUMXI.ts.map} +0 -0
  167. /package/dist/chunks/{remote-selection-ui-OHMIQ32X.ts.map → remote-selection-ui-TD4C4W3J.ts.map} +0 -0
  168. /package/dist/chunks/{setup-switch-66GWMBNH.ts.map → setup-switch-KLGESLQX.ts.map} +0 -0
  169. /package/dist/chunks/{setup-wizard-OHZXJVQZ.ts.map → setup-wizard-ZQAK35BP.ts.map} +0 -0
  170. /package/dist/chunks/{snapshot-VRHNAUUH.ts.map → snapshot-RGNDYT6A.ts.map} +0 -0
  171. /package/dist/chunks/{snapshot-transaction-EUGA4VX6.ts.map → snapshot-transaction-26BQO36S.ts.map} +0 -0
  172. /package/dist/chunks/{sync-inspection-4WFQEJOE.ts.map → sync-inspection-MOMLGUTD.ts.map} +0 -0
  173. /package/dist/chunks/{sync-state-SWLSMK4G.ts.map → sync-state-7L4NT7W2.ts.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/snapshot/snapshot-transaction.ts", "../../src/state/mutation-directory-sync.ts", "../../src/snapshot/snapshot-case-replacement.ts", "../../src/snapshot/snapshot-mutation-queues.ts", "../../src/snapshot/snapshot-root-transition.ts", "../../src/snapshot/snapshot-transaction-plan.ts"],
4
+ "sourcesContent": ["import { createHash, randomUUID } from \"node:crypto\";\nimport type { Stats } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\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 { withMissingTargetQueues, withTargetQueues } from \"./snapshot-mutation-queues.js\";\nimport { sessionStorageRoot } from \"./snapshot-paths.js\";\nimport {\n prepareSessionRootTransition,\n resolveTransitionSessionRoot,\n type SessionRootTransition,\n validateSessionRootTransition,\n} from \"./snapshot-root-transition.js\";\nimport { pendingTransactionEntries, transactionRoot } from \"./snapshot-transaction-directory.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, options, async (heldKeys) => {\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 // A released additional key cannot authorize rollback, even for recognized raced bytes.\n const changesQueueKey = transaction.journal.entries.some(\n (entry) => !heldKeys.has(entry.target) || (entry.afterTarget && !heldKeys.has(entry.afterTarget)),\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 withMissingTargetQueues(\n transaction.journal.entries\n .filter((entry) => entry.removalPending)\n .flatMap((entry) => [entry.target, ...(entry.afterTarget ? [entry.afterTarget] : [])]),\n heldKeys,\n options,\n 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 );\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 queues have been released. Recovery must reserve missing keys afresh.\n if (changesQueueKey)\n throw new Error(\"Snapshot apply failed; guarded transaction evidence retained for review.\", {\n cause: error,\n });\n try {\n await restoreTransaction(transaction.directory, transaction.journal, options, heldKeys);\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(), options, (heldKeys) =>\n restoreTransaction(directory, journal, { ...options, sessionDir }, heldKeys),\n );\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(\n directory: string,\n journal: TransactionJournal,\n options: TransactionOptions,\n heldKeys: ReadonlySet<string>,\n) {\n validateJournal(directory, journal, options.sessionDir);\n const missingSpellings: string[] = [];\n for (const entry of journal.entries) {\n if (!entry.afterTarget) continue;\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n const spelling = await caseReplacementSpelling(entry.target, entry.afterTarget);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (spelling === undefined) missingSpellings.push(entry.target, entry.afterTarget);\n }\n // Reserve an interrupted removal's other spelling before staging or image checks:\n // recognizable bytes installed by a writer in that gap are not our postimage.\n return withMissingTargetQueues(missingSpellings, heldKeys, options, (reservedKeys) =>\n restoreQueuedTransaction(directory, journal, options, reservedKeys),\n );\n}\n\nasync function restoreQueuedTransaction(\n directory: string,\n journal: TransactionJournal,\n options: TransactionOptions,\n heldKeys: ReadonlySet<string>,\n) {\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 withMissingTargetQueues(\n entry.afterTarget && (needsCaseQueue || verified === \"missing\")\n ? [entry.target, entry.afterTarget]\n : verified.startsWith(\"directory:\")\n ? [entry.target]\n : [],\n heldKeys,\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 await withMissingTargetQueues([entry.target], heldKeys, options, async () => {\n const atRename = await verifyTarget(directory, entry, journal);\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n if (atRename === before) 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) return;\n await fs.rename(temporary, entry.target);\n await syncDirectory(path.dirname(entry.target));\n });\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 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}\n", "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 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 { withFileMutationQueue } from \"@earendil-works/pi-coding-agent\";\n\ntype MutationGuards = { signal?: AbortSignal; validateMutation?: () => void };\n\nfunction assertCurrent(options: MutationGuards) {\n options.validateMutation?.();\n options.signal?.throwIfAborted();\n}\n\nfunction isMissing(error: unknown) {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"ENOENT\" || code === \"ENOTDIR\";\n}\n\nasync function targetMissing(target: string, options: MutationGuards) {\n assertCurrent(options);\n try {\n await fs.lstat(target);\n assertCurrent(options);\n return false;\n } catch (error) {\n assertCurrent(options);\n if (!isMissing(error)) throw error;\n return true;\n }\n}\n\nasync function queueKey(target: string, options: MutationGuards) {\n assertCurrent(options);\n try {\n const key = await fs.realpath(target);\n assertCurrent(options);\n return key;\n } catch (error) {\n assertCurrent(options);\n if (!isMissing(error)) throw error;\n return path.resolve(target);\n }\n}\n\n/** Resolve missing descendants too, including descendants of a file scheduled for removal. */\nasync function assertCanonicalParent(target: string, options: MutationGuards) {\n const parent = path.dirname(path.resolve(target));\n const suffix: string[] = [];\n for (let current = parent; ; current = path.dirname(current)) {\n assertCurrent(options);\n let canonical: string;\n try {\n canonical = await fs.realpath(current);\n } catch (error) {\n assertCurrent(options);\n if (!isMissing(error) || path.dirname(current) === current) throw error;\n suffix.unshift(path.basename(current));\n continue;\n }\n assertCurrent(options);\n // Pi queues existing paths by realpath and missing paths by lexical resolve.\n // Its public API cannot reserve a missing alias key while that alias exists,\n // or report a key that changes during registration. Refuse aliased parents\n // before mutation rather than risk a non-reentrant queue or overwrite a writer.\n if (path.join(canonical, ...suffix) !== parent)\n throw new Error(\n \"Snapshot mutation through an aliased parent is unsafe; use the canonical agent/session path. Transaction evidence retained for review.\",\n );\n return;\n }\n}\n\nexport async function assertCanonicalMutationTargets(targets: readonly string[], options: MutationGuards) {\n for (const target of targets) await assertCanonicalParent(target, options);\n}\n\nexport async function withTargetQueues<T>(\n targets: readonly string[],\n options: MutationGuards,\n action: (heldKeys: ReadonlySet<string>) => Promise<T>,\n): Promise<T> {\n // Check the whole group before reserving any key or changing live files.\n await assertCanonicalMutationTargets(targets, options);\n const keys = new Set<string>();\n const missing = new Set<string>();\n for (const target of targets) {\n if (await targetMissing(target, options)) missing.add(target);\n const key = await queueKey(target, options);\n if (keys.has(key)) throw new Error(\"Transaction targets alias the same file.\");\n keys.add(key);\n }\n const ordered = [...keys].sort();\n async function acquire(index: number): Promise<T> {\n assertCurrent(options);\n const key = ordered[index];\n // Pass the resolved key, not an alias whose lookup can select a different key.\n if (key) return withFileMutationQueue(key, () => acquire(index + 1));\n for (const target of targets) {\n await assertCanonicalParent(target, options);\n if (missing.has(target) && !(await targetMissing(target, options)))\n throw new Error(\"Missing transaction target appeared during queue acquisition; review is required.\");\n if (!keys.has(await queueKey(target, options)))\n throw new Error(\"Transaction queue identity changed; review is required.\");\n }\n assertCurrent(options);\n return action(keys);\n }\n return acquire(0);\n}\n\nexport async function withMissingTargetQueues<T>(\n targets: readonly string[],\n heldKeys: ReadonlySet<string>,\n options: MutationGuards,\n action: (heldKeys: ReadonlySet<string>) => Promise<T>,\n): Promise<T> {\n const unique = [...new Set(targets)];\n const requireAbsent = async () => {\n for (const target of unique) {\n await assertCanonicalParent(target, options);\n if (!(await targetMissing(target, options)))\n throw new Error(\"Snapshot target changed before destination queue reservation; evidence retained.\");\n }\n };\n // Canonical parents make each missing key equal to the intended installed key.\n // Retain the old physical key and exclude it from these non-reentrant queues.\n const keys = unique\n .map((target) => path.resolve(target))\n .filter((key) => !heldKeys.has(key))\n .sort();\n await requireAbsent();\n const combined = new Set([...heldKeys, ...keys]);\n async function acquire(index: number): Promise<T> {\n assertCurrent(options);\n const key = keys[index];\n if (key) return withFileMutationQueue(key, () => acquire(index + 1));\n // A writer registered in the removal gap must finish before this check.\n // Even recognizable pre/postimages belong to that writer, not this transaction.\n await requireAbsent();\n assertCurrent(options);\n return action(combined);\n }\n return acquire(0);\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": ["createHash", "fs", "path", "root", "path", "fs", "path", "fs", "path", "path", "image", "path", "path", "fs", "path", "fs", "entry", "temporary", "createHash", "stat"]
7
+ }
@@ -4,10 +4,10 @@ import {
4
4
  fileHashMap,
5
5
  hasLocalChanges,
6
6
  remoteChangedSinceState
7
- } from "./chunk-JY2RVOUL.ts";
7
+ } from "./chunk-Y4UVXOLQ.ts";
8
8
  import {
9
9
  createSyncBackend
10
- } from "./chunk-RAMHGOX2.ts";
10
+ } from "./chunk-OJARL2TG.ts";
11
11
  import {
12
12
  createStartupTimings
13
13
  } from "./chunk-M6VQJIOU.ts";
@@ -17,13 +17,13 @@ import {
17
17
  import {
18
18
  readStateForConfig,
19
19
  syncStateFingerprint
20
- } from "./chunk-73MDIVYJ.ts";
20
+ } from "./chunk-DN4IA7MR.ts";
21
21
  import {
22
22
  createSnapshot
23
- } from "./chunk-PHANBTVM.ts";
23
+ } from "./chunk-ESKOPQVB.ts";
24
24
  import {
25
25
  inspectRemoteSelection
26
- } from "./chunk-DFJGTVPX.ts";
26
+ } from "./chunk-KYTT7KV4.ts";
27
27
 
28
28
  // src/sync/sync-inspection.ts
29
29
  import { createHash } from "node:crypto";
@@ -61,4 +61,4 @@ async function inspectSync(config, options, signal, factory = createSyncBackend,
61
61
  export {
62
62
  inspectSync
63
63
  };
64
- //# sourceMappingURL=chunk-STVQQ5KG.ts.map
64
+ //# sourceMappingURL=chunk-7ZIYU5QS.ts.map
@@ -6,7 +6,7 @@ import {
6
6
  mergeSession,
7
7
  mergeText,
8
8
  readMergeAncestors
9
- } from "./chunk-CDQGSZL3.ts";
9
+ } from "./chunk-6LD5KX55.ts";
10
10
  import {
11
11
  jsonEqual,
12
12
  parseSettingsDocument,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-ZW5ZLGBI.ts";
15
15
  import {
16
16
  mergePathIdentity
17
- } from "./chunk-TO2GMX3K.ts";
17
+ } from "./chunk-XJHQPB3E.ts";
18
18
 
19
19
  // src/sync/content-conflicts.ts
20
20
  import { createHash } from "node:crypto";
@@ -212,4 +212,4 @@ export {
212
212
  mergeAcceptedSettingsPackages,
213
213
  mergeSettingsJson
214
214
  };
215
- //# sourceMappingURL=chunk-AO6EDUA6.ts.map
215
+ //# sourceMappingURL=chunk-AKMV47YC.ts.map
@@ -3,20 +3,20 @@
3
3
  import {
4
4
  fileHashMap,
5
5
  sameHashes
6
- } from "./chunk-JY2RVOUL.ts";
6
+ } from "./chunk-Y4UVXOLQ.ts";
7
7
  import {
8
8
  portableSnapshot,
9
9
  sameLocalFields,
10
10
  validatePortableSnapshot,
11
11
  validateSnapshotFieldPolicy
12
- } from "./chunk-UGSSZWQ6.ts";
12
+ } from "./chunk-MKSMJPVA.ts";
13
13
  import {
14
14
  planFileMerge
15
- } from "./chunk-TO2GMX3K.ts";
15
+ } from "./chunk-XJHQPB3E.ts";
16
16
  import {
17
17
  statePathForConfig,
18
18
  syncStateFingerprint
19
- } from "./chunk-73MDIVYJ.ts";
19
+ } from "./chunk-DN4IA7MR.ts";
20
20
  import {
21
21
  readJsonIfExists,
22
22
  syncDirectory,
@@ -94,7 +94,7 @@ async function readMergeJournal(config) {
94
94
  if (journal.progress) {
95
95
  const before = fileHashMap(journal.before);
96
96
  const after = fileHashMap(journal.after);
97
- const { readConflictArtifact } = await import("./conflict-artifacts-6XGSSU5S.ts");
97
+ const { readConflictArtifact } = await import("./conflict-artifacts-J6WSDCWP.ts");
98
98
  const backendIdentity = JSON.parse(journal.identity)[1];
99
99
  if (typeof backendIdentity !== "string") throw new Error("Invalid partial backend identity.");
100
100
  const byArtifact = /* @__PURE__ */ new Map();
@@ -150,4 +150,4 @@ export {
150
150
  retireMergeJournal,
151
151
  requireNoMergeJournal
152
152
  };
153
- //# sourceMappingURL=chunk-66GAUVDL.ts.map
153
+ //# sourceMappingURL=chunk-BEST45H2.ts.map
@@ -1,8 +1,5 @@
1
1
  // @generated by scripts/build-runtime.mjs; do not edit.
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
- import {
4
- readJsonIfExists
5
- } from "./chunk-AR2DGDUI.ts";
6
3
 
7
4
  // src/snapshot/snapshot-paths.ts
8
5
  import path from "node:path";
@@ -16,6 +13,7 @@ function sessionStorageRoot(root, configuredSessionDir2) {
16
13
  }
17
14
 
18
15
  // src/snapshot/session-paths.ts
16
+ import fs from "node:fs/promises";
19
17
  import os from "node:os";
20
18
  import path2 from "node:path";
21
19
  import { getAgentDir } from "@earendil-works/pi-coding-agent";
@@ -29,7 +27,19 @@ function sessionDirFromContext(ctx) {
29
27
  return typeof getSessionDir === "function" ? getSessionDir.call(manager) : void 0;
30
28
  }
31
29
  async function configuredSessionDir() {
32
- const settings = await readJsonIfExists(path2.join(agentDir(), "settings.json"));
30
+ let content;
31
+ try {
32
+ content = await fs.readFile(path2.join(agentDir(), "settings.json"), "utf8");
33
+ } catch (error) {
34
+ if (error.code === "ENOENT") return void 0;
35
+ throw error;
36
+ }
37
+ let settings;
38
+ try {
39
+ settings = JSON.parse(content.replace(/^\uFEFF/u, ""));
40
+ } catch {
41
+ throw new SyntaxError("Pi settings.json cannot be parsed; repair the file before syncing.");
42
+ }
33
43
  return settings?.sessionDir ? expandSessionDir(settings.sessionDir) : void 0;
34
44
  }
35
45
  async function effectiveSessionRoot(ctx) {
@@ -101,4 +111,4 @@ export {
101
111
  expandSessionDir,
102
112
  snapshotOptionsForContext
103
113
  };
104
- //# sourceMappingURL=chunk-DO55XUNU.ts.map
114
+ //# sourceMappingURL=chunk-CBLTWXAU.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/snapshot/snapshot-paths.ts", "../../src/snapshot/session-paths.ts"],
4
+ "sourcesContent": ["import path from \"node:path\";\n\nfunction expandHome(value: string) {\n if (value === \"~\") return process.env.HOME ?? value;\n if (value.startsWith(\"~/\")) return path.join(process.env.HOME ?? \"~\", value.slice(2));\n return value;\n}\n\nexport function sessionStorageRoot(root: string, configuredSessionDir?: string) {\n return configuredSessionDir ? path.resolve(expandHome(configuredSessionDir)) : path.resolve(root, \"sessions\");\n}\n", "import fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { type ExtensionCommandContext, type ExtensionContext, getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { sessionStorageRoot } from \"./snapshot-paths.js\";\nimport type { Snapshot, SnapshotOptions } from \"./snapshot-types.js\";\n\nexport function sessionDirFromContext(ctx: ExtensionCommandContext | ExtensionContext) {\n const manager = ctx.sessionManager as typeof ctx.sessionManager & {\n usesDefaultSessionDir?: () => boolean;\n };\n const usesDefaultSessionDir = manager.usesDefaultSessionDir;\n if (typeof usesDefaultSessionDir === \"function\" && usesDefaultSessionDir.call(manager)) {\n return undefined;\n }\n const getSessionDir = manager.getSessionDir;\n return typeof getSessionDir === \"function\" ? (getSessionDir.call(manager) as string | undefined) : undefined;\n}\n\nexport async function configuredSessionDir() {\n let content: string;\n try {\n content = await fs.readFile(path.join(agentDir(), \"settings.json\"), \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n let settings: { sessionDir?: string } | null;\n try {\n // Pi accepts a leading UTF-8 BOM in its settings file; snapshot bytes stay unchanged.\n settings = JSON.parse(content.replace(/^\\uFEFF/u, \"\")) as typeof settings;\n } catch {\n throw new SyntaxError(\"Pi settings.json cannot be parsed; repair the file before syncing.\");\n }\n return settings?.sessionDir ? expandSessionDir(settings.sessionDir) : undefined;\n}\n\nexport async function effectiveSessionRoot(ctx: ExtensionCommandContext | ExtensionContext) {\n return path.resolve(sessionStorageRoot(agentDir(), sessionDirFromContext(ctx) ?? (await configuredSessionDir())));\n}\n\nexport async function sessionDirForApply(ctx: ExtensionCommandContext | ExtensionContext, snapshot: Snapshot) {\n const contextSessionDir = sessionDirFromContext(ctx);\n const localSessionDir = await configuredSessionDir();\n if (contextSessionDir && path.resolve(contextSessionDir) !== path.resolve(localSessionDir ?? \"\")) {\n return contextSessionDir;\n }\n return sessionDirFromSnapshot(snapshot) ?? contextSessionDir;\n}\n\n/** Hash-only merge plans cannot describe installation into a different session root. */\nexport function requireStableMergeSessionRoot(before: Snapshot, after: Snapshot) {\n const root = agentDir();\n if (\n path.resolve(sessionStorageRoot(root, sessionDirFromSnapshot(before))) !==\n path.resolve(sessionStorageRoot(root, sessionDirFromSnapshot(after)))\n ) {\n throw new Error(\n \"Merged transfer changes the session root; no local apply or baseline acceptance is allowed. Review /sync diff and choose an explicit push or pull direction.\",\n );\n }\n}\n\nfunction sessionDirFromSnapshot(snapshot: Snapshot) {\n const settingsFile = snapshot.files.find((file) => file.path === \"settings.json\");\n if (!settingsFile) return undefined;\n let settings: unknown;\n try {\n settings = JSON.parse(\n new TextDecoder(\"utf-8\", { fatal: true }).decode(\n decodeBase64Strict(settingsFile.contentBase64, settingsFile.path),\n ),\n );\n } catch {\n // JSON parser errors can quote private settings values; never surface their payload.\n throw new Error(\"Merged settings cannot be parsed; review a directional recovery.\");\n }\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings))\n throw new Error(\"Merged settings must be a JSON object; review a directional recovery.\");\n const sessionDir = (settings as { sessionDir?: unknown }).sessionDir;\n if (sessionDir !== undefined && typeof sessionDir !== \"string\")\n throw new Error(\"Merged sessionDir must be a string; review a directional recovery.\");\n return sessionDir ? expandSessionDir(sessionDir) : undefined;\n}\n\nfunction decodeBase64Strict(value: string, filePath: string) {\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value) || value.length % 4 !== 0) {\n throw new Error(`Invalid base64 content in snapshot file: ${filePath}`);\n }\n return Buffer.from(value, \"base64\");\n}\n\nexport function agentDir() {\n return getAgentDir();\n}\n\nexport function expandSessionDir(value: string) {\n return value === \"~\" || value.startsWith(\"~/\") ? path.join(os.homedir(), value.slice(2)) : value;\n}\n\nexport function snapshotOptionsForContext(\n ctx: ExtensionCommandContext | ExtensionContext,\n config: AnySyncConfig,\n): SnapshotOptions {\n return {\n include: config.include,\n sessionDir: sessionDirFromContext(ctx),\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["configuredSessionDir", "path", "path"]
7
+ }
@@ -4,20 +4,20 @@ import {
4
4
  COUPLED_FIELDS,
5
5
  mergeSettingsJson,
6
6
  snapshotFile
7
- } from "./chunk-AO6EDUA6.ts";
7
+ } from "./chunk-AKMV47YC.ts";
8
8
  import {
9
9
  edits,
10
10
  isMergeTextPath,
11
11
  lines,
12
12
  text
13
- } from "./chunk-CDQGSZL3.ts";
13
+ } from "./chunk-6LD5KX55.ts";
14
14
  import {
15
15
  parseJsonObjectDocument,
16
16
  parseSettingsDocument
17
17
  } from "./chunk-ZW5ZLGBI.ts";
18
18
  import {
19
19
  scanSnapshot
20
- } from "./chunk-PHANBTVM.ts";
20
+ } from "./chunk-ESKOPQVB.ts";
21
21
  import {
22
22
  AGENT_INPUT_BYTES,
23
23
  AGENT_MAX_UNITS,
@@ -71,7 +71,7 @@ function buildAgentEvidence(plan, local, remote, ancestors) {
71
71
  const evidence = { units: [], files: [], unsupported: [] };
72
72
  if (plan.kind !== "planned") return evidence;
73
73
  if (plan.conflicts.length > AGENT_MAX_UNITS)
74
- throw new Error("Agent mode paused: too many conflict paths for bounded analysis.");
74
+ throw new Error("Autonomous sync paused: too many conflict paths for bounded analysis.");
75
75
  for (const conflict of plan.conflicts) {
76
76
  try {
77
77
  if (conflict.reason !== "both-changed") throw new Error("unsupported conflict");
@@ -135,14 +135,14 @@ function buildAgentEvidence(plan, local, remote, ancestors) {
135
135
  }
136
136
  }
137
137
  if (evidence.units.length > AGENT_MAX_UNITS || Buffer.byteLength(JSON.stringify(evidence.units)) > AGENT_INPUT_BYTES)
138
- throw new Error("Agent mode paused: conflict evidence exceeds its input bound.");
138
+ throw new Error("Autonomous sync paused: conflict evidence exceeds its input bound.");
139
139
  if (scanSnapshot({
140
140
  ...local,
141
141
  files: evidence.units.flatMap(
142
142
  (unit) => [unit.path, unit.base, unit.local, unit.remote].map((value) => snapshotFile(unit.path, Buffer.from(value)))
143
143
  )
144
144
  }).length)
145
- throw new Error("Agent mode paused: possible secrets in model evidence; nothing was disclosed.");
145
+ throw new Error("Autonomous sync paused: possible secrets in model evidence; nothing was disclosed.");
146
146
  return evidence;
147
147
  }
148
148
  function parseAgentCandidate(raw, evidence) {
@@ -217,4 +217,4 @@ export {
217
217
  parseAgentCandidate,
218
218
  applyAgentCandidate
219
219
  };
220
- //# sourceMappingURL=chunk-IMMMZUFC.ts.map
220
+ //# sourceMappingURL=chunk-CQD2TJHE.ts.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sync/agent-candidate.ts"],
4
- "sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { scanSnapshot } from \"../snapshot/snapshot.js\";\nimport type { Snapshot, SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport { AGENT_INPUT_BYTES, AGENT_MAX_UNITS, AGENT_OUTPUT_BYTES } from \"./agent-policy.js\";\nimport { snapshotFile } from \"./content-conflicts.js\";\nimport type { FileMergePlan } from \"./file-merge-planner.js\";\nimport { parseJsonObjectDocument, parseSettingsDocument } from \"./json-document.js\";\nimport { COUPLED_FIELDS, mergeSettingsJson } from \"./settings-merge.js\";\nimport { edits, type Hunk, isMergeTextPath, lines, text } from \"./text-merge.js\";\n\nexport interface AgentUnit {\n id: string;\n path: string;\n kind: \"text\" | \"settings\";\n base: string;\n local: string;\n remote: string;\n}\ninterface CandidateFile {\n path: string;\n base: string;\n local: string;\n remote: string;\n parts?: (string | AgentUnit)[];\n fields?: { id: string; key: string }[];\n}\nexport interface AgentEvidence {\n units: AgentUnit[];\n files: CandidateFile[];\n unsupported: string[];\n}\nexport interface AgentCandidate {\n version: 1;\n results: (\n | { id: string; content: string }\n | { id: string; source: \"local\" | \"remote\" }\n | { id: string; refuse: true }\n )[];\n}\nexport const digest = (value: unknown) => createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\n\nfunction overlaps(a: Hunk, b: Hunk) {\n return a.start === a.end || b.start === b.end\n ? a.start <= b.end && b.start <= a.end\n : a.start < b.end && b.start < a.end;\n}\n\n/** Only overlapping edit regions are model-writable; all other bytes are assembled by code. */\nfunction textParts(filePath: string, baseText: string, localText: string, remoteText: string): (string | AgentUnit)[] {\n const base = lines(baseText);\n const changes = [\n ...edits(base, lines(localText)).map((hunk) => ({ ...hunk, side: \"local\" as const })),\n ...edits(base, lines(remoteText)).map((hunk) => ({ ...hunk, side: \"remote\" as const })),\n ].sort((a, b) => a.start - b.start || a.end - b.end);\n const clusters: (typeof changes)[] = [];\n for (const change of changes) {\n const last = clusters.at(-1);\n if (last?.some((item) => overlaps(item, change))) last.push(change);\n else clusters.push([change]);\n }\n const result: (string | AgentUnit)[] = [];\n let cursor = 0;\n for (const cluster of clusters) {\n const start = Math.min(...cluster.map((item) => item.start));\n const end = Math.max(...cluster.map((item) => item.end));\n result.push(base.slice(cursor, start).join(\"\"));\n const image = (side: \"local\" | \"remote\") => {\n let position = start;\n const output: string[] = [];\n for (const hunk of cluster.filter((item) => item.side === side)) {\n output.push(...base.slice(position, hunk.start), ...hunk.lines);\n position = hunk.end;\n }\n return [...output, ...base.slice(position, end)].join(\"\");\n };\n const local = image(\"local\");\n const remote = image(\"remote\");\n const original = base.slice(start, end).join(\"\");\n if (local === remote || local === original || remote === original) result.push(local === original ? remote : local);\n else result.push({ id: \"\", path: filePath, kind: \"text\", base: original, local, remote });\n cursor = end;\n }\n result.push(base.slice(cursor).join(\"\"));\n return result;\n}\n\nexport function buildAgentEvidence(\n plan: FileMergePlan,\n local: Snapshot,\n remote: Snapshot,\n ancestors: SnapshotFile[],\n): AgentEvidence {\n const evidence: AgentEvidence = { units: [], files: [], unsupported: [] };\n if (plan.kind !== \"planned\") return evidence;\n if (plan.conflicts.length > AGENT_MAX_UNITS)\n throw new Error(\"Agent mode paused: too many conflict paths for bounded analysis.\");\n for (const conflict of plan.conflicts) {\n try {\n if (conflict.reason !== \"both-changed\") throw new Error(\"unsupported conflict\");\n const versions = [ancestors, local.files, remote.files].map((files) => {\n const file = files.find((item) => item.path === conflict.path);\n if (!file) throw new Error(\"missing ancestor/version\");\n const bytes = Buffer.from(file.contentBase64, \"base64\");\n if (bytes.length > 8192) throw new Error(\"file bound\");\n return text(bytes);\n }) as [string, string, string];\n const [base, left, right] = versions;\n const file: CandidateFile = { path: conflict.path, base, local: left, remote: right };\n let units: AgentUnit[];\n if (conflict.path === \"settings.json\") {\n const documents = versions.map((value) => parseSettingsDocument(Buffer.from(value)));\n const merge = mergeSettingsJson(\n ...(versions.map((value) => Buffer.from(value)) as [Buffer, Buffer, Buffer]),\n undefined,\n true,\n );\n if (merge.kind === \"review\" && merge.reason !== \"field-conflict\") throw new Error(\"unsupported settings\");\n const fields = new Set(merge.kind === \"review\" ? merge.fields : []);\n const groups = COUPLED_FIELDS.map((group) => [...group] as string[]);\n const coupled = new Set(groups.flat());\n groups.push(...[...fields].filter((key) => !coupled.has(key)).map((key) => [key]));\n file.fields = [];\n units = groups\n .filter((group) => group.some((key) => fields.has(key)))\n .map((group) => {\n const values = documents.map((document) =>\n JSON.stringify(\n Object.fromEntries(\n group.flatMap((key) => {\n const node = document.root.members.get(key)?.node;\n return node ? [[key, node.value]] : [];\n }),\n ),\n ),\n );\n const unit: AgentUnit = {\n id: \"\",\n path: file.path,\n kind: \"settings\",\n base: values[0] ?? \"{}\",\n local: values[1] ?? \"{}\",\n remote: values[2] ?? \"{}\",\n };\n file.fields?.push({ id: String(evidence.units.length + file.fields.length), key: group[0] ?? \"\" });\n return unit;\n });\n } else {\n if (!isMergeTextPath(conflict.path)) throw new Error(\"unsupported path\");\n file.parts = textParts(file.path, base, left, right);\n units = file.parts.filter((part): part is AgentUnit => typeof part !== \"string\");\n }\n for (const unit of units) {\n unit.id = String(evidence.units.length);\n evidence.units.push(unit);\n }\n evidence.files.push(file);\n } catch {\n evidence.unsupported.push(conflict.path);\n }\n }\n if (evidence.units.length > AGENT_MAX_UNITS || Buffer.byteLength(JSON.stringify(evidence.units)) > AGENT_INPUT_BYTES)\n throw new Error(\"Agent mode paused: conflict evidence exceeds its input bound.\");\n // Scan only the actual disclosure image; skipSecretScan never authorizes model disclosure.\n if (\n scanSnapshot({\n ...local,\n files: evidence.units.flatMap((unit) =>\n [unit.path, unit.base, unit.local, unit.remote].map((value) => snapshotFile(unit.path, Buffer.from(value))),\n ),\n }).length\n )\n throw new Error(\"Agent mode paused: possible secrets in model evidence; nothing was disclosed.\");\n return evidence;\n}\n\nexport function parseAgentCandidate(raw: string, evidence: AgentEvidence): AgentCandidate {\n if (Buffer.byteLength(raw) > AGENT_OUTPUT_BYTES) throw new Error(\"Agent output exceeds its bound.\");\n const parsed = parseJsonObjectDocument(Buffer.from(raw)).root.value as Record<string, unknown>;\n if (\n Object.keys(parsed).sort().join(\",\") !== \"results,version\" ||\n parsed.version !== 1 ||\n !Array.isArray(parsed.results) ||\n parsed.results.length !== evidence.units.length\n )\n throw new Error(\"Invalid agent candidate contract.\");\n const seen = new Set<string>();\n for (const result of parsed.results) {\n if (!result || typeof result !== \"object\" || Array.isArray(result)) throw new Error(\"Invalid agent result.\");\n const row = result as Record<string, unknown>;\n const unit = evidence.units.find((unit) => unit.id === row.id);\n if (!unit || seen.has(unit.id)) throw new Error(\"Unowned or duplicate agent unit.\");\n seen.add(unit.id);\n const keys = Object.keys(row).sort().join(\",\");\n if (keys === \"id,refuse\" && row.refuse === true) continue;\n if (unit.kind === \"settings\" && keys === \"id,source\" && (row.source === \"local\" || row.source === \"remote\"))\n continue;\n if (unit.kind === \"text\" && keys === \"content,id\" && typeof row.content === \"string\" && row.content.length > 0) {\n text(Buffer.from(row.content));\n if (/^(?:<{7}|={7}|>{7}|\\|{7})/mu.test(row.content)) throw new Error(\"Unresolved conflict markers.\");\n continue;\n }\n throw new Error(\"Unsupported agent action.\");\n }\n return parsed as unknown as AgentCandidate;\n}\n\nexport function applyAgentCandidate(\n plan: FileMergePlan,\n evidence: AgentEvidence,\n candidate: AgentCandidate,\n): FileMergePlan {\n // Persisted candidates cross a trust boundary too.\n parseAgentCandidate(JSON.stringify(candidate), evidence);\n if (plan.kind !== \"planned\") throw new Error(\"Unverified merge plan.\");\n const results = new Map(candidate.results.map((row) => [row.id, row]));\n const replacements = new Map<string, SnapshotFile>();\n for (const file of evidence.files) {\n const units = evidence.units.filter((unit) => unit.path === file.path);\n if (units.some((unit) => results.get(unit.id) && \"refuse\" in (results.get(unit.id) ?? {}))) continue;\n let bytes: Buffer;\n if (file.parts) {\n bytes = Buffer.from(\n file.parts\n .map((part) => (typeof part === \"string\" ? part : (results.get(part.id) as { content: string }).content))\n .join(\"\"),\n );\n } else {\n const selections = new Map(\n (file.fields ?? []).map(({ id, key }) => [key, (results.get(id) as { source: \"local\" | \"remote\" }).source]),\n );\n const merged = mergeSettingsJson(\n Buffer.from(file.base),\n Buffer.from(file.local),\n Buffer.from(file.remote),\n selections,\n true,\n );\n if (merged.kind !== \"merged\") throw new Error(\"Agent settings units remain unresolved.\");\n // The existing renderer/parser retains atomic values, unknown members and exact numeric policy.\n parseSettingsDocument(merged.content);\n for (const { key } of file.fields ?? []) {\n if (!selections.has(key)) throw new Error(\"Missing atomic settings selection.\");\n }\n bytes = merged.content;\n }\n if (bytes.length > AGENT_OUTPUT_BYTES) throw new Error(\"Agent file exceeds output bound.\");\n replacements.set(file.path, snapshotFile(file.path, bytes));\n }\n const decisions = plan.decisions.map((decision) => {\n const file = replacements.get(decision.path);\n return file && decision.kind === \"conflict\"\n ? { kind: \"accepted\" as const, path: file.path, source: \"merged\" as const, file }\n : decision;\n });\n return { kind: \"planned\", decisions, conflicts: decisions.filter((item) => item.kind === \"conflict\") };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createHash } from \"node:crypto\";\nimport { scanSnapshot } from \"../snapshot/snapshot.js\";\nimport type { Snapshot, SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport { AGENT_INPUT_BYTES, AGENT_MAX_UNITS, AGENT_OUTPUT_BYTES } from \"./agent-policy.js\";\nimport { snapshotFile } from \"./content-conflicts.js\";\nimport type { FileMergePlan } from \"./file-merge-planner.js\";\nimport { parseJsonObjectDocument, parseSettingsDocument } from \"./json-document.js\";\nimport { COUPLED_FIELDS, mergeSettingsJson } from \"./settings-merge.js\";\nimport { edits, type Hunk, isMergeTextPath, lines, text } from \"./text-merge.js\";\n\nexport interface AgentUnit {\n id: string;\n path: string;\n kind: \"text\" | \"settings\";\n base: string;\n local: string;\n remote: string;\n}\ninterface CandidateFile {\n path: string;\n base: string;\n local: string;\n remote: string;\n parts?: (string | AgentUnit)[];\n fields?: { id: string; key: string }[];\n}\nexport interface AgentEvidence {\n units: AgentUnit[];\n files: CandidateFile[];\n unsupported: string[];\n}\nexport interface AgentCandidate {\n version: 1;\n results: (\n | { id: string; content: string }\n | { id: string; source: \"local\" | \"remote\" }\n | { id: string; refuse: true }\n )[];\n}\nexport const digest = (value: unknown) => createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\n\nfunction overlaps(a: Hunk, b: Hunk) {\n return a.start === a.end || b.start === b.end\n ? a.start <= b.end && b.start <= a.end\n : a.start < b.end && b.start < a.end;\n}\n\n/** Only overlapping edit regions are model-writable; all other bytes are assembled by code. */\nfunction textParts(filePath: string, baseText: string, localText: string, remoteText: string): (string | AgentUnit)[] {\n const base = lines(baseText);\n const changes = [\n ...edits(base, lines(localText)).map((hunk) => ({ ...hunk, side: \"local\" as const })),\n ...edits(base, lines(remoteText)).map((hunk) => ({ ...hunk, side: \"remote\" as const })),\n ].sort((a, b) => a.start - b.start || a.end - b.end);\n const clusters: (typeof changes)[] = [];\n for (const change of changes) {\n const last = clusters.at(-1);\n if (last?.some((item) => overlaps(item, change))) last.push(change);\n else clusters.push([change]);\n }\n const result: (string | AgentUnit)[] = [];\n let cursor = 0;\n for (const cluster of clusters) {\n const start = Math.min(...cluster.map((item) => item.start));\n const end = Math.max(...cluster.map((item) => item.end));\n result.push(base.slice(cursor, start).join(\"\"));\n const image = (side: \"local\" | \"remote\") => {\n let position = start;\n const output: string[] = [];\n for (const hunk of cluster.filter((item) => item.side === side)) {\n output.push(...base.slice(position, hunk.start), ...hunk.lines);\n position = hunk.end;\n }\n return [...output, ...base.slice(position, end)].join(\"\");\n };\n const local = image(\"local\");\n const remote = image(\"remote\");\n const original = base.slice(start, end).join(\"\");\n if (local === remote || local === original || remote === original) result.push(local === original ? remote : local);\n else result.push({ id: \"\", path: filePath, kind: \"text\", base: original, local, remote });\n cursor = end;\n }\n result.push(base.slice(cursor).join(\"\"));\n return result;\n}\n\nexport function buildAgentEvidence(\n plan: FileMergePlan,\n local: Snapshot,\n remote: Snapshot,\n ancestors: SnapshotFile[],\n): AgentEvidence {\n const evidence: AgentEvidence = { units: [], files: [], unsupported: [] };\n if (plan.kind !== \"planned\") return evidence;\n if (plan.conflicts.length > AGENT_MAX_UNITS)\n throw new Error(\"Autonomous sync paused: too many conflict paths for bounded analysis.\");\n for (const conflict of plan.conflicts) {\n try {\n if (conflict.reason !== \"both-changed\") throw new Error(\"unsupported conflict\");\n const versions = [ancestors, local.files, remote.files].map((files) => {\n const file = files.find((item) => item.path === conflict.path);\n if (!file) throw new Error(\"missing ancestor/version\");\n const bytes = Buffer.from(file.contentBase64, \"base64\");\n if (bytes.length > 8192) throw new Error(\"file bound\");\n return text(bytes);\n }) as [string, string, string];\n const [base, left, right] = versions;\n const file: CandidateFile = { path: conflict.path, base, local: left, remote: right };\n let units: AgentUnit[];\n if (conflict.path === \"settings.json\") {\n const documents = versions.map((value) => parseSettingsDocument(Buffer.from(value)));\n const merge = mergeSettingsJson(\n ...(versions.map((value) => Buffer.from(value)) as [Buffer, Buffer, Buffer]),\n undefined,\n true,\n );\n if (merge.kind === \"review\" && merge.reason !== \"field-conflict\") throw new Error(\"unsupported settings\");\n const fields = new Set(merge.kind === \"review\" ? merge.fields : []);\n const groups = COUPLED_FIELDS.map((group) => [...group] as string[]);\n const coupled = new Set(groups.flat());\n groups.push(...[...fields].filter((key) => !coupled.has(key)).map((key) => [key]));\n file.fields = [];\n units = groups\n .filter((group) => group.some((key) => fields.has(key)))\n .map((group) => {\n const values = documents.map((document) =>\n JSON.stringify(\n Object.fromEntries(\n group.flatMap((key) => {\n const node = document.root.members.get(key)?.node;\n return node ? [[key, node.value]] : [];\n }),\n ),\n ),\n );\n const unit: AgentUnit = {\n id: \"\",\n path: file.path,\n kind: \"settings\",\n base: values[0] ?? \"{}\",\n local: values[1] ?? \"{}\",\n remote: values[2] ?? \"{}\",\n };\n file.fields?.push({ id: String(evidence.units.length + file.fields.length), key: group[0] ?? \"\" });\n return unit;\n });\n } else {\n if (!isMergeTextPath(conflict.path)) throw new Error(\"unsupported path\");\n file.parts = textParts(file.path, base, left, right);\n units = file.parts.filter((part): part is AgentUnit => typeof part !== \"string\");\n }\n for (const unit of units) {\n unit.id = String(evidence.units.length);\n evidence.units.push(unit);\n }\n evidence.files.push(file);\n } catch {\n evidence.unsupported.push(conflict.path);\n }\n }\n if (evidence.units.length > AGENT_MAX_UNITS || Buffer.byteLength(JSON.stringify(evidence.units)) > AGENT_INPUT_BYTES)\n throw new Error(\"Autonomous sync paused: conflict evidence exceeds its input bound.\");\n // Scan only the actual disclosure image; skipSecretScan never authorizes model disclosure.\n if (\n scanSnapshot({\n ...local,\n files: evidence.units.flatMap((unit) =>\n [unit.path, unit.base, unit.local, unit.remote].map((value) => snapshotFile(unit.path, Buffer.from(value))),\n ),\n }).length\n )\n throw new Error(\"Autonomous sync paused: possible secrets in model evidence; nothing was disclosed.\");\n return evidence;\n}\n\nexport function parseAgentCandidate(raw: string, evidence: AgentEvidence): AgentCandidate {\n if (Buffer.byteLength(raw) > AGENT_OUTPUT_BYTES) throw new Error(\"Agent output exceeds its bound.\");\n const parsed = parseJsonObjectDocument(Buffer.from(raw)).root.value as Record<string, unknown>;\n if (\n Object.keys(parsed).sort().join(\",\") !== \"results,version\" ||\n parsed.version !== 1 ||\n !Array.isArray(parsed.results) ||\n parsed.results.length !== evidence.units.length\n )\n throw new Error(\"Invalid agent candidate contract.\");\n const seen = new Set<string>();\n for (const result of parsed.results) {\n if (!result || typeof result !== \"object\" || Array.isArray(result)) throw new Error(\"Invalid agent result.\");\n const row = result as Record<string, unknown>;\n const unit = evidence.units.find((unit) => unit.id === row.id);\n if (!unit || seen.has(unit.id)) throw new Error(\"Unowned or duplicate agent unit.\");\n seen.add(unit.id);\n const keys = Object.keys(row).sort().join(\",\");\n if (keys === \"id,refuse\" && row.refuse === true) continue;\n if (unit.kind === \"settings\" && keys === \"id,source\" && (row.source === \"local\" || row.source === \"remote\"))\n continue;\n if (unit.kind === \"text\" && keys === \"content,id\" && typeof row.content === \"string\" && row.content.length > 0) {\n text(Buffer.from(row.content));\n if (/^(?:<{7}|={7}|>{7}|\\|{7})/mu.test(row.content)) throw new Error(\"Unresolved conflict markers.\");\n continue;\n }\n throw new Error(\"Unsupported agent action.\");\n }\n return parsed as unknown as AgentCandidate;\n}\n\nexport function applyAgentCandidate(\n plan: FileMergePlan,\n evidence: AgentEvidence,\n candidate: AgentCandidate,\n): FileMergePlan {\n // Persisted candidates cross a trust boundary too.\n parseAgentCandidate(JSON.stringify(candidate), evidence);\n if (plan.kind !== \"planned\") throw new Error(\"Unverified merge plan.\");\n const results = new Map(candidate.results.map((row) => [row.id, row]));\n const replacements = new Map<string, SnapshotFile>();\n for (const file of evidence.files) {\n const units = evidence.units.filter((unit) => unit.path === file.path);\n if (units.some((unit) => results.get(unit.id) && \"refuse\" in (results.get(unit.id) ?? {}))) continue;\n let bytes: Buffer;\n if (file.parts) {\n bytes = Buffer.from(\n file.parts\n .map((part) => (typeof part === \"string\" ? part : (results.get(part.id) as { content: string }).content))\n .join(\"\"),\n );\n } else {\n const selections = new Map(\n (file.fields ?? []).map(({ id, key }) => [key, (results.get(id) as { source: \"local\" | \"remote\" }).source]),\n );\n const merged = mergeSettingsJson(\n Buffer.from(file.base),\n Buffer.from(file.local),\n Buffer.from(file.remote),\n selections,\n true,\n );\n if (merged.kind !== \"merged\") throw new Error(\"Agent settings units remain unresolved.\");\n // The existing renderer/parser retains atomic values, unknown members and exact numeric policy.\n parseSettingsDocument(merged.content);\n for (const { key } of file.fields ?? []) {\n if (!selections.has(key)) throw new Error(\"Missing atomic settings selection.\");\n }\n bytes = merged.content;\n }\n if (bytes.length > AGENT_OUTPUT_BYTES) throw new Error(\"Agent file exceeds output bound.\");\n replacements.set(file.path, snapshotFile(file.path, bytes));\n }\n const decisions = plan.decisions.map((decision) => {\n const file = replacements.get(decision.path);\n return file && decision.kind === \"conflict\"\n ? { kind: \"accepted\" as const, path: file.path, source: \"merged\" as const, file }\n : decision;\n });\n return { kind: \"planned\", decisions, conflicts: decisions.filter((item) => item.kind === \"conflict\") };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["file", "unit"]
7
7
  }
@@ -1,15 +1,15 @@
1
1
  // @generated by scripts/build-runtime.mjs; do not edit.
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+ import {
4
+ readJsonIfExists,
5
+ writeJson
6
+ } from "./chunk-AR2DGDUI.ts";
3
7
  import {
4
8
  stateDir
5
9
  } from "./chunk-SWRVXVFD.ts";
6
10
  import {
7
11
  backendIdentityCoordinates
8
12
  } from "./chunk-2JZFHNLM.ts";
9
- import {
10
- readJsonIfExists,
11
- writeJson
12
- } from "./chunk-AR2DGDUI.ts";
13
13
 
14
14
  // src/state/sync-state-store.ts
15
15
  import { createHash } from "node:crypto";
@@ -30,7 +30,7 @@ async function writeStateForConfig(config, state, snapshot, validate = () => {
30
30
  }) {
31
31
  validate();
32
32
  if (snapshot) {
33
- const { stageMergeBaseline } = await import("./merge-baseline-store-HL3VLMAM.ts");
33
+ const { stageMergeBaseline } = await import("./merge-baseline-store-65GKUMXI.ts");
34
34
  validate();
35
35
  await stageMergeBaseline(config, snapshot, state);
36
36
  validate();
@@ -58,4 +58,4 @@ export {
58
58
  lockPath,
59
59
  ensureStateDir
60
60
  };
61
- //# sourceMappingURL=chunk-73MDIVYJ.ts.map
61
+ //# sourceMappingURL=chunk-DN4IA7MR.ts.map
@@ -12,18 +12,18 @@ import {
12
12
  selectionForSnapshot,
13
13
  snapshotSelectionInclude,
14
14
  syncIncludeSelection
15
- } from "./chunk-DFJGTVPX.ts";
15
+ } from "./chunk-KYTT7KV4.ts";
16
16
  import {
17
17
  agentDir,
18
18
  configuredSessionDir,
19
19
  sessionStorageRoot
20
- } from "./chunk-DO55XUNU.ts";
20
+ } from "./chunk-CBLTWXAU.ts";
21
21
  import {
22
22
  isDeniedPath,
23
23
  posixJoin,
24
24
  safeJoin,
25
25
  toPosix
26
- } from "./chunk-YZ5BQNRZ.ts";
26
+ } from "./chunk-FHE2DCA2.ts";
27
27
 
28
28
  // src/snapshot/snapshot.ts
29
29
  import { createHash, randomUUID } from "node:crypto";
@@ -345,4 +345,4 @@ export {
345
345
  mergeRemotePreservedFiles,
346
346
  mergeRemoteSessionFiles
347
347
  };
348
- //# sourceMappingURL=chunk-PHANBTVM.ts.map
348
+ //# sourceMappingURL=chunk-ESKOPQVB.ts.map