@narumitw/pi-sync 0.54.3 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +38 -11
  2. package/dist/chunks/agent-candidate-3JN6DJKT.ts +26 -0
  3. package/dist/chunks/agent-plan-QCUJWBP4.ts +99 -0
  4. package/dist/chunks/agent-plan-QCUJWBP4.ts.map +7 -0
  5. package/dist/chunks/agent-runner-E2JU2VZ6.ts +182 -0
  6. package/dist/chunks/agent-runner-E2JU2VZ6.ts.map +7 -0
  7. package/dist/chunks/agent-store-A3F6IYWZ.ts +152 -0
  8. package/dist/chunks/agent-store-A3F6IYWZ.ts.map +7 -0
  9. package/dist/chunks/chunk-5Q5SSKNG.ts +128 -0
  10. package/dist/chunks/chunk-5Q5SSKNG.ts.map +7 -0
  11. package/dist/chunks/chunk-5XZOC7FD.ts +215 -0
  12. package/dist/chunks/chunk-5XZOC7FD.ts.map +7 -0
  13. package/dist/chunks/{chunk-GC3QOL6J.ts → chunk-AAEEHR7H.ts} +31 -87
  14. package/dist/chunks/chunk-AAEEHR7H.ts.map +7 -0
  15. package/dist/chunks/{chunk-R35N4CL3.ts → chunk-B4QZBDBT.ts} +2 -2
  16. package/dist/chunks/{chunk-KGE47GCZ.ts → chunk-CRKTAPSL.ts} +8 -8
  17. package/dist/chunks/chunk-DT7M4VQS.ts +69 -0
  18. package/dist/chunks/chunk-DT7M4VQS.ts.map +7 -0
  19. package/dist/chunks/chunk-ED3TYIVW.ts +229 -0
  20. package/dist/chunks/chunk-ED3TYIVW.ts.map +7 -0
  21. package/dist/chunks/{chunk-HMXUKU43.ts → chunk-EUMINX7L.ts} +6 -6
  22. package/dist/chunks/chunk-FQOSHGJ7.ts +215 -0
  23. package/dist/chunks/chunk-FQOSHGJ7.ts.map +7 -0
  24. package/dist/chunks/chunk-GNH73BJ5.ts +153 -0
  25. package/dist/chunks/chunk-GNH73BJ5.ts.map +7 -0
  26. package/dist/chunks/{chunk-YTHQEW35.ts → chunk-GP5DU62N.ts} +8 -9
  27. package/dist/chunks/chunk-GP5DU62N.ts.map +7 -0
  28. package/dist/chunks/{chunk-AAZDBIBJ.ts → chunk-GSNPASKB.ts} +2 -2
  29. package/dist/chunks/{chunk-E6ONFG57.ts → chunk-IWZH5KYS.ts} +11 -8
  30. package/dist/chunks/chunk-IWZH5KYS.ts.map +7 -0
  31. package/dist/chunks/{chunk-CAGJOKB7.ts → chunk-JJTARUSO.ts} +15 -14
  32. package/dist/chunks/chunk-JJTARUSO.ts.map +7 -0
  33. package/dist/chunks/{chunk-ITFR6NNQ.ts → chunk-NLWS55B6.ts} +2 -1
  34. package/dist/chunks/{chunk-ITFR6NNQ.ts.map → chunk-NLWS55B6.ts.map} +2 -2
  35. package/dist/chunks/{chunk-2FETCGGT.ts → chunk-OEWQVWLC.ts} +4 -4
  36. package/dist/chunks/{chunk-35GM6XKM.ts → chunk-OTZRCKYP.ts} +128 -382
  37. package/dist/chunks/chunk-OTZRCKYP.ts.map +7 -0
  38. package/dist/chunks/{chunk-XU2VXGQV.ts → chunk-OWBAZA6J.ts} +14 -8
  39. package/dist/chunks/chunk-OWBAZA6J.ts.map +7 -0
  40. package/dist/chunks/chunk-PRUEIIK7.ts +24 -0
  41. package/dist/chunks/chunk-PRUEIIK7.ts.map +7 -0
  42. package/dist/chunks/chunk-QGK445K7.ts +21 -0
  43. package/dist/chunks/chunk-QGK445K7.ts.map +7 -0
  44. package/dist/chunks/{chunk-KATKRR3D.ts → chunk-QO333NM4.ts} +32 -11
  45. package/dist/chunks/chunk-QO333NM4.ts.map +7 -0
  46. package/dist/chunks/{chunk-I4JYVFUS.ts → chunk-QSHMOL3I.ts} +21 -22
  47. package/dist/chunks/chunk-QSHMOL3I.ts.map +7 -0
  48. package/dist/chunks/chunk-S2FMH5FT.ts +97 -0
  49. package/dist/chunks/chunk-S2FMH5FT.ts.map +7 -0
  50. package/dist/chunks/{chunk-BVVP33U5.ts → chunk-SWRVXVFD.ts} +12 -9
  51. package/dist/chunks/chunk-SWRVXVFD.ts.map +7 -0
  52. package/dist/chunks/{chunk-ZX2Q6THB.ts → chunk-UBV24CG4.ts} +4 -5
  53. package/dist/chunks/chunk-UBV24CG4.ts.map +7 -0
  54. package/dist/chunks/chunk-UOHR7LRO.ts +70 -0
  55. package/dist/chunks/chunk-UOHR7LRO.ts.map +7 -0
  56. package/dist/chunks/{chunk-VCL7TZYW.ts → chunk-UPNVIUBN.ts} +3 -3
  57. package/dist/chunks/chunk-VJN7KU4J.ts +350 -0
  58. package/dist/chunks/chunk-VJN7KU4J.ts.map +7 -0
  59. package/dist/chunks/chunk-YHT4YTYG.ts +31 -0
  60. package/dist/chunks/chunk-YHT4YTYG.ts.map +7 -0
  61. package/dist/chunks/{chunk-A3TFXY4O.ts → chunk-YK52VDXG.ts} +6 -5
  62. package/dist/chunks/chunk-YK52VDXG.ts.map +7 -0
  63. package/dist/chunks/config-KGIYTTXQ.ts +37 -0
  64. package/dist/chunks/{conflict-artifacts-4CZFB7WI.ts → conflict-artifacts-FXFIIBCB.ts} +8 -7
  65. package/dist/chunks/{conflict-review-ZOTOHL2E.ts → conflict-review-6WIEQLXW.ts} +31 -25
  66. package/dist/chunks/{conflict-review-ZOTOHL2E.ts.map → conflict-review-6WIEQLXW.ts.map} +1 -1
  67. package/dist/chunks/continuous-record-LFRVXQBD.ts +30 -0
  68. package/dist/chunks/continuous-sync-AWAAOXK2.ts +545 -0
  69. package/dist/chunks/continuous-sync-AWAAOXK2.ts.map +7 -0
  70. package/dist/chunks/{file-selection-UNHBVVON.ts → file-selection-3JJYOVNR.ts} +5 -5
  71. package/dist/chunks/{git-backend-FD7AVSK6.ts → git-backend-KYDZ673X.ts} +28 -32
  72. package/dist/chunks/git-backend-KYDZ673X.ts.map +7 -0
  73. package/dist/chunks/{manager-result-dispatcher-HVRTPEVK.ts → manager-result-dispatcher-AGBBVDDS.ts} +10 -9
  74. package/dist/chunks/{manager-ui-ZIN4BUSF.ts → manager-ui-KRAW3NE2.ts} +184 -45
  75. package/dist/chunks/manager-ui-KRAW3NE2.ts.map +7 -0
  76. package/dist/chunks/{merge-baseline-store-ICXVTCML.ts → merge-baseline-store-RFCAH7KL.ts} +5 -5
  77. package/dist/chunks/{remote-selection-ui-H6AEVA3Q.ts → remote-selection-ui-5725JDNC.ts} +9 -8
  78. package/dist/chunks/remote-selection-ui-5725JDNC.ts.map +7 -0
  79. package/dist/chunks/{s3-backend-Y4P3O5B5.ts → s3-backend-Y7WSCLJI.ts} +38 -38
  80. package/dist/chunks/s3-backend-Y7WSCLJI.ts.map +7 -0
  81. package/dist/chunks/{setup-switch-ZMW5C4M7.ts → setup-switch-E7PHKI6J.ts} +7 -6
  82. package/dist/chunks/setup-switch-E7PHKI6J.ts.map +7 -0
  83. package/dist/chunks/{setup-wizard-VW7F3JN4.ts → setup-wizard-65DROCIJ.ts} +14 -13
  84. package/dist/chunks/setup-wizard-65DROCIJ.ts.map +7 -0
  85. package/dist/chunks/{sync-inspection-3EMS2J5B.ts → sync-inspection-XFJOAMJD.ts} +8 -8
  86. package/dist/chunks/sync-inspection-XFJOAMJD.ts.map +7 -0
  87. package/dist/chunks/{sync-operations-2CWST333.ts → sync-operations-HDUDT5PD.ts} +62 -63
  88. package/dist/chunks/sync-operations-HDUDT5PD.ts.map +7 -0
  89. package/dist/chunks/{webdav-backend-TBILVEQK.ts → webdav-backend-6K26F6LT.ts} +39 -48
  90. package/dist/chunks/webdav-backend-6K26F6LT.ts.map +7 -0
  91. package/dist/index.ts +165 -85
  92. package/dist/index.ts.map +3 -3
  93. package/docs/agent-mode-verification.md +99 -0
  94. package/docs/continuous-sync-verification.md +87 -0
  95. package/docs/settings.md +32 -247
  96. package/package.json +11 -5
  97. package/skills/configure-pi-sync/SKILL.md +54 -0
  98. package/skills/configure-pi-sync/references/configuration.md +650 -0
  99. package/src/backends/git/git-backend.ts +1 -4
  100. package/src/backends/git/git-runner.ts +1 -5
  101. package/src/backends/s3/s3-backend.ts +3 -25
  102. package/src/backends/s3/s3-client.ts +14 -2
  103. package/src/backends/snapshot-pointer.ts +27 -0
  104. package/src/backends/webdav/webdav-backend.ts +3 -29
  105. package/src/backends/webdav/webdav-client.ts +11 -7
  106. package/src/commands/command-execution.ts +5 -2
  107. package/src/commands/command-handler.ts +15 -3
  108. package/src/commands/command-types.ts +6 -0
  109. package/src/commands/command.ts +1 -0
  110. package/src/settings/config.ts +7 -0
  111. package/src/settings/settings-store.ts +0 -34
  112. package/src/settings/settings-types.ts +8 -0
  113. package/src/settings/settings-validation.ts +1 -1
  114. package/src/snapshot/snapshot-codec.ts +1 -5
  115. package/src/state/lock.ts +13 -10
  116. package/src/state/merge-baseline-store.ts +2 -2
  117. package/src/state/state-directory.ts +8 -1
  118. package/src/sync/agent-candidate.ts +251 -0
  119. package/src/sync/agent-plan.ts +87 -0
  120. package/src/sync/agent-policy.ts +13 -0
  121. package/src/sync/agent-request.ts +17 -0
  122. package/src/sync/agent-runner.ts +188 -0
  123. package/src/sync/agent-store.ts +151 -0
  124. package/src/sync/agent-sync.ts +91 -0
  125. package/src/sync/automatic-sync.ts +2 -1
  126. package/src/sync/continuous-errors.ts +85 -0
  127. package/src/sync/continuous-lease.ts +221 -0
  128. package/src/sync/continuous-record.ts +179 -0
  129. package/src/sync/continuous-storage.ts +55 -0
  130. package/src/sync/continuous-sync.ts +516 -0
  131. package/src/sync/continuous-watch.ts +59 -0
  132. package/src/sync/merged-sync.ts +70 -12
  133. package/src/sync/remote-snapshot.ts +2 -3
  134. package/src/sync/settings-merge.ts +19 -3
  135. package/src/sync/setup-switch.ts +1 -5
  136. package/src/sync/startup-check.ts +15 -11
  137. package/src/sync/sync-inspection.ts +8 -1
  138. package/src/sync/sync-mutations.ts +6 -17
  139. package/src/sync/sync-queries.ts +5 -0
  140. package/src/sync/text-merge.ts +3 -3
  141. package/src/sync-extension.ts +75 -19
  142. package/src/ui/agent-mode-setting.ts +91 -0
  143. package/src/ui/manager-state.ts +2 -0
  144. package/src/ui/remote-selection-ui.ts +5 -5
  145. package/src/ui/settings-ui.ts +83 -1
  146. package/src/ui/setup/s3-credentials-ui.ts +1 -5
  147. package/src/ui/setup/setup-name-ui.ts +2 -5
  148. package/src/ui/setup/setup-switcher.ts +2 -0
  149. package/src/ui/sync-setups-ui.ts +3 -5
  150. package/dist/chunks/chunk-26PMXY7E.ts +0 -362
  151. package/dist/chunks/chunk-26PMXY7E.ts.map +0 -7
  152. package/dist/chunks/chunk-35GM6XKM.ts.map +0 -7
  153. package/dist/chunks/chunk-A3TFXY4O.ts.map +0 -7
  154. package/dist/chunks/chunk-BVVP33U5.ts.map +0 -7
  155. package/dist/chunks/chunk-CAGJOKB7.ts.map +0 -7
  156. package/dist/chunks/chunk-E6ONFG57.ts.map +0 -7
  157. package/dist/chunks/chunk-GC3QOL6J.ts.map +0 -7
  158. package/dist/chunks/chunk-I4JYVFUS.ts.map +0 -7
  159. package/dist/chunks/chunk-KATKRR3D.ts.map +0 -7
  160. package/dist/chunks/chunk-XU2VXGQV.ts.map +0 -7
  161. package/dist/chunks/chunk-YTHQEW35.ts.map +0 -7
  162. package/dist/chunks/chunk-ZX2Q6THB.ts.map +0 -7
  163. package/dist/chunks/git-backend-FD7AVSK6.ts.map +0 -7
  164. package/dist/chunks/manager-ui-ZIN4BUSF.ts.map +0 -7
  165. package/dist/chunks/s3-backend-Y4P3O5B5.ts.map +0 -7
  166. package/dist/chunks/setup-wizard-VW7F3JN4.ts.map +0 -7
  167. package/dist/chunks/sync-operations-2CWST333.ts.map +0 -7
  168. package/dist/chunks/webdav-backend-TBILVEQK.ts.map +0 -7
  169. /package/dist/chunks/{conflict-artifacts-4CZFB7WI.ts.map → agent-candidate-3JN6DJKT.ts.map} +0 -0
  170. /package/dist/chunks/{chunk-R35N4CL3.ts.map → chunk-B4QZBDBT.ts.map} +0 -0
  171. /package/dist/chunks/{chunk-KGE47GCZ.ts.map → chunk-CRKTAPSL.ts.map} +0 -0
  172. /package/dist/chunks/{chunk-HMXUKU43.ts.map → chunk-EUMINX7L.ts.map} +0 -0
  173. /package/dist/chunks/{chunk-AAZDBIBJ.ts.map → chunk-GSNPASKB.ts.map} +0 -0
  174. /package/dist/chunks/{chunk-2FETCGGT.ts.map → chunk-OEWQVWLC.ts.map} +0 -0
  175. /package/dist/chunks/{chunk-VCL7TZYW.ts.map → chunk-UPNVIUBN.ts.map} +0 -0
  176. /package/dist/chunks/{manager-result-dispatcher-HVRTPEVK.ts.map → config-KGIYTTXQ.ts.map} +0 -0
  177. /package/dist/chunks/{merge-baseline-store-ICXVTCML.ts.map → conflict-artifacts-FXFIIBCB.ts.map} +0 -0
  178. /package/dist/chunks/{remote-selection-ui-H6AEVA3Q.ts.map → continuous-record-LFRVXQBD.ts.map} +0 -0
  179. /package/dist/chunks/{file-selection-UNHBVVON.ts.map → file-selection-3JJYOVNR.ts.map} +0 -0
  180. /package/dist/chunks/{setup-switch-ZMW5C4M7.ts.map → manager-result-dispatcher-AGBBVDDS.ts.map} +0 -0
  181. /package/dist/chunks/{sync-inspection-3EMS2J5B.ts.map → merge-baseline-store-RFCAH7KL.ts.map} +0 -0
@@ -1,362 +0,0 @@
1
- // @generated by scripts/build-runtime.mjs; do not edit.
2
- // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
- import {
4
- fileHashMap,
5
- sameHashes
6
- } from "./chunk-BDB4IDM3.ts";
7
- import {
8
- mergePathIdentity,
9
- planFileMerge
10
- } from "./chunk-76NB4R7U.ts";
11
- import {
12
- statePathForConfig,
13
- syncStateFingerprint
14
- } from "./chunk-VCL7TZYW.ts";
15
- import {
16
- portableSnapshot,
17
- sameLocalFields,
18
- validatePortableSnapshot,
19
- validateSnapshotFieldPolicy
20
- } from "./chunk-A6HU4ERM.ts";
21
- import {
22
- readJsonIfExists,
23
- syncDirectory,
24
- writeJson
25
- } from "./chunk-HUZ5CR4W.ts";
26
-
27
- // src/sync/conflict-artifacts.ts
28
- import { createHash, randomUUID as randomUUID2 } from "node:crypto";
29
- import fs2 from "node:fs/promises";
30
- import path2 from "node:path";
31
-
32
- // src/sync/conflict-groups.ts
33
- function conflictGroups(plan, config) {
34
- const paths = plan.decisions.map((item) => item.path);
35
- const parents = paths.map((_, index) => index);
36
- const ranks = paths.map(() => 0);
37
- const find = (index) => {
38
- while (parents[index] !== index) {
39
- parents[index] = parents[parents[index] ?? index] ?? index;
40
- index = parents[index] ?? index;
41
- }
42
- return index;
43
- };
44
- const join = (left, right) => {
45
- let a = find(left);
46
- let b = find(right);
47
- if (a === b) return;
48
- if ((ranks[a] ?? 0) < (ranks[b] ?? 0)) [a, b] = [b, a];
49
- parents[b] = a;
50
- if (ranks[a] === ranks[b]) ranks[a] = (ranks[a] ?? 0) + 1;
51
- };
52
- const identities = paths.map(mergePathIdentity);
53
- const byIdentity = /* @__PURE__ */ new Map();
54
- const byPath = new Map(paths.map((value, index) => [value, index]));
55
- identities.forEach((value, index) => {
56
- const previous = byIdentity.get(value);
57
- if (previous !== void 0) join(index, previous);
58
- else byIdentity.set(value, index);
59
- });
60
- const includes = new Set(
61
- config.include.filter((value) => !["settings.json", "AGENTS.md", "sessions"].includes(value)).map(mergePathIdentity)
62
- );
63
- const buckets = /* @__PURE__ */ new Map();
64
- const bucket = (key, index) => {
65
- const previous = buckets.get(key);
66
- if (previous === void 0) buckets.set(key, index);
67
- else join(index, previous);
68
- };
69
- paths.forEach((value, index) => {
70
- const root = value.split("/")[0] ?? "";
71
- if (["extensions", "themes", "skills", "prompts"].includes(root)) bucket(`resource:${root}`, index);
72
- const segments = (identities[index] ?? "").split("/");
73
- let ancestor = "";
74
- for (let length = 0; length < segments.length - 1; length++) {
75
- ancestor = ancestor ? `${ancestor}/${segments[length]}` : segments[length] ?? "";
76
- const parent = byIdentity.get(ancestor);
77
- if (parent !== void 0) join(index, parent);
78
- if (includes.has(ancestor)) bucket(`include:${ancestor}`, index);
79
- }
80
- });
81
- const groups = /* @__PURE__ */ new Map();
82
- for (const conflict of plan.conflicts) {
83
- const index = byPath.get(conflict.path);
84
- if (index === void 0) throw new Error("Conflict is missing from managed decisions.");
85
- const key = find(index);
86
- const group = groups.get(key) ?? { paths: [], reasons: [] };
87
- if (!group.reasons.includes(conflict.reason)) group.reasons.push(conflict.reason);
88
- groups.set(key, group);
89
- }
90
- paths.forEach((value, index) => {
91
- groups.get(find(index))?.paths.push(value);
92
- });
93
- return [...groups.values()].map((group) => ({ ...group, paths: group.paths.sort() }));
94
- }
95
-
96
- // src/sync/merge-journal.ts
97
- import { randomUUID } from "node:crypto";
98
- import fs from "node:fs/promises";
99
- import path from "node:path";
100
- function mergeJournalIdentity(config, backendIdentity) {
101
- return JSON.stringify([config.setupName, backendIdentity, [...config.include].sort(), config.localFields ?? null]);
102
- }
103
- function mergeJournalPath(config) {
104
- return `${statePathForConfig(config)}.merge-journal.json`;
105
- }
106
- async function readMergeJournal(config) {
107
- let journal;
108
- try {
109
- const stat = await fs.lstat(mergeJournalPath(config));
110
- if (!stat.isFile() || stat.size > 384 * 1024 * 1024) throw new Error("Unsafe or oversized journal.");
111
- journal = await readJsonIfExists(mergeJournalPath(config));
112
- } catch (error) {
113
- if (error.code === "ENOENT") return;
114
- throw new Error("Cannot read the private merge journal; preserve it and review recovery.");
115
- }
116
- if (!journal) return;
117
- if (journal.version !== 1 || typeof journal.identity !== "string" || typeof journal.backup !== "string" || typeof journal.stateIdentity !== "string" || journal.applyOnly !== void 0 && (journal.applyOnly !== true || !journal.committedHead || journal.committedHead.revision !== journal.expectedHead?.revision || journal.committedHead.snapshotId !== journal.expectedHead?.snapshotId || journal.upload?.id !== journal.expectedHead?.snapshotId) || journal.sessionRoot !== void 0 && (typeof journal.sessionRoot !== "string" || !path.isAbsolute(journal.sessionRoot) || path.resolve(journal.sessionRoot) !== journal.sessionRoot) || journal.warnings !== void 0 && (!Array.isArray(journal.warnings) || journal.warnings.length > 64 || journal.warnings.some((item) => typeof item !== "string")) || !journal.expectedHead || typeof journal.expectedHead.revision !== "string" || !journal.before || !journal.after || !journal.upload || !Array.isArray(journal.before.files) || !Array.isArray(journal.after.files) || !Array.isArray(journal.upload.files))
118
- throw new Error("Unsupported or damaged merge journal; preserve it and review recovery before syncing.");
119
- try {
120
- const pinnedPaths = new Set(journal.progress?.groups.flatMap((group) => group.paths) ?? []);
121
- for (const snapshot of [
122
- journal.before,
123
- journal.after,
124
- journal.upload,
125
- ...journal.accepted ? [journal.accepted] : []
126
- ]) {
127
- validateSnapshotFieldPolicy(snapshot);
128
- if (snapshot.version !== 1 && snapshot.version !== 2 && snapshot.version !== 3 || typeof snapshot.id !== "string" || typeof snapshot.profile !== "string" || snapshot.files.length > 16384 || snapshot.files.reduce(
129
- (bytes, file) => bytes + (typeof file?.contentBase64 === "string" ? file.contentBase64.length * 0.75 : Infinity),
130
- 0
131
- ) > 64 * 1024 * 1024)
132
- throw new Error("Invalid journal input.");
133
- const plan = planFileMerge({ baseline: {}, local: snapshot.files, remote: [], selectionCompatible: true });
134
- if (plan.kind !== "planned" || plan.conflicts.some((conflict) => conflict.reason !== "path-collision" || !pinnedPaths.has(conflict.path)))
135
- throw new Error("Invalid journal collision group.");
136
- }
137
- validatePortableSnapshot(journal.upload);
138
- if ((journal.upload.version === 2 || journal.upload.version === 3) && !journal.accepted)
139
- throw new Error("Portable merge journal requires an explicit accepted projection.");
140
- if (journal.accepted) validatePortableSnapshot(journal.accepted);
141
- } catch {
142
- throw new Error("Invalid merge journal paths, metadata, or bytes; preserve evidence for review.");
143
- }
144
- try {
145
- if (journal.accepted && (!sameLocalFields(journal.accepted.localFields, journal.upload.localFields) || !sameHashes(
146
- fileHashMap(portableSnapshot(journal.after, journal.upload.localFields)),
147
- fileHashMap(portableSnapshot(journal.accepted, journal.upload.localFields))
148
- )))
149
- throw new Error("Projection mismatch.");
150
- } catch {
151
- throw new Error("Invalid accepted merge projection; preserve journal evidence.");
152
- }
153
- if (journal.progress) {
154
- const known = /* @__PURE__ */ new Set([
155
- ...Object.keys(journal.progress.previous?.lastFileHashes ?? {}),
156
- ...[...journal.before.files, ...journal.after.files, ...journal.upload.files].map((file) => file.path)
157
- ]);
158
- const progress = journal.progress;
159
- if (!config.partialSync || !progress.previous || syncStateFingerprint(progress.previous) !== journal.stateIdentity || !Array.isArray(progress.groups) || progress.groups.length > 16384 || progress.groups.some(
160
- (group) => !Array.isArray(group.paths) || !group.paths.length || group.paths.length > 16384 || group.paths.some((filePath) => !known.has(filePath)) || !/^[a-f0-9-]{36}$/u.test(group.artifact)
161
- ))
162
- throw new Error("Invalid partial acceptance metadata; preserve journal evidence.");
163
- }
164
- if (journal.progress) {
165
- const before = fileHashMap(journal.before);
166
- const after = fileHashMap(journal.after);
167
- const { readConflictArtifact: readConflictArtifact2 } = await import("./conflict-artifacts-4CZFB7WI.ts");
168
- const backendIdentity = JSON.parse(journal.identity)[1];
169
- if (typeof backendIdentity !== "string") throw new Error("Invalid partial backend identity.");
170
- const byArtifact = /* @__PURE__ */ new Map();
171
- for (const group of journal.progress.groups) {
172
- const groups = byArtifact.get(group.artifact) ?? [];
173
- groups.push(group);
174
- byArtifact.set(group.artifact, groups);
175
- }
176
- for (const [token, groups] of byArtifact) {
177
- const artifact = await readConflictArtifact2(config, backendIdentity, token);
178
- const retainedGroups = new Set(artifact.groups.map((group) => JSON.stringify(group.paths)));
179
- const remote = fileHashMap(artifact.remote);
180
- const upload = fileHashMap(journal.upload);
181
- for (const group of groups) {
182
- if (!retainedGroups.has(JSON.stringify(group.paths)))
183
- throw new Error("Partial group does not match retained artifact evidence.");
184
- for (const filePath of group.paths)
185
- if (before[filePath] !== after[filePath] || remote[filePath] !== upload[filePath] || journal.progress.previous.lastFileHashes[filePath] !== artifact.state.lastFileHashes[filePath])
186
- throw new Error("Withheld version changed in journal; preserve evidence.");
187
- }
188
- }
189
- }
190
- return journal;
191
- }
192
- async function writeMergeJournal(config, journal) {
193
- await writeJson(mergeJournalPath(config), journal, { maxBytes: 384 * 1024 * 1024 });
194
- }
195
- async function clearMergeJournal(config) {
196
- await fs.rm(mergeJournalPath(config), { force: true });
197
- await syncDirectory(path.dirname(mergeJournalPath(config)));
198
- }
199
- async function retireMergeJournal(config) {
200
- if (!await readMergeJournal(config)) return;
201
- const file = mergeJournalPath(config);
202
- await fs.rename(file, `${file}.${randomUUID()}.resolved`);
203
- await syncDirectory(path.dirname(file));
204
- }
205
- async function requireNoMergeJournal(config, options = {}) {
206
- const journal = await readMergeJournal(config);
207
- if (options.force || !journal) return;
208
- if (journal) {
209
- throw new Error(
210
- "A merged transfer needs recovery. Run /sync sync to reconcile it. If newer local edits or remote revisions prevent recovery, review /sync diff and explicitly choose push --force or pull --force; the selected directional result will archive the old journal, not restore old bytes. Keep its backup; do not downgrade while recovery is pending."
211
- );
212
- }
213
- }
214
-
215
- // src/sync/conflict-artifacts.ts
216
- var LIMIT = 192 * 1024 * 1024;
217
- function conflictArtifactFingerprint(artifact) {
218
- return createHash("sha256").update(JSON.stringify(artifact)).digest("hex");
219
- }
220
- function conflictDirectory(config) {
221
- return `${statePathForConfig(config)}.conflicts`;
222
- }
223
- async function directory(config, create = false) {
224
- const target = conflictDirectory(config);
225
- if (create) await fs2.mkdir(target, { recursive: true, mode: 448 });
226
- const stat = await fs2.lstat(target);
227
- if (!stat.isDirectory() || stat.isSymbolicLink() || process.platform !== "win32" && (stat.mode & 63) !== 0)
228
- throw new Error("Unsafe private conflict directory.");
229
- return target;
230
- }
231
- function tokenPath(config, token) {
232
- if (!/^[a-f0-9-]{36}$/u.test(token)) throw new Error("Invalid conflict token.");
233
- return path2.join(conflictDirectory(config), `${token}.json`);
234
- }
235
- async function saveConflictArtifact(config, backend, artifact, validate, onCreated) {
236
- validate();
237
- const identity = mergeJournalIdentity(config, backend);
238
- const local = Object.fromEntries(artifact.local.files.map((file) => [file.path, file.sha256]));
239
- const remote = Object.fromEntries(artifact.remote.files.map((file) => [file.path, file.sha256]));
240
- const fingerprint = createHash("sha256").update(
241
- JSON.stringify([
242
- identity,
243
- artifact.groups.map(
244
- (group) => group.paths.map((filePath) => [
245
- filePath,
246
- artifact.state.lastFileHashes[filePath] ?? null,
247
- local[filePath] ?? null,
248
- remote[filePath] ?? null
249
- ])
250
- )
251
- ])
252
- ).digest("hex").slice(0, 32);
253
- const token = `${fingerprint.slice(0, 8)}-${fingerprint.slice(8, 12)}-${fingerprint.slice(12, 16)}-${fingerprint.slice(16, 20)}-${fingerprint.slice(20)}`;
254
- await directory(config, true);
255
- validate();
256
- const reuse = async () => {
257
- const existing = await readConflictArtifact(config, backend, token);
258
- validate();
259
- const oldLocal = Object.fromEntries(existing.local.files.map((file) => [file.path, file.sha256]));
260
- const oldRemote = Object.fromEntries(existing.remote.files.map((file) => [file.path, file.sha256]));
261
- if (JSON.stringify(existing.groups.map((group) => group.paths)) !== JSON.stringify(artifact.groups.map((group) => group.paths)) || artifact.groups.some(
262
- (group) => group.paths.some(
263
- (filePath) => existing.state.lastFileHashes[filePath] !== artifact.state.lastFileHashes[filePath] || oldLocal[filePath] !== local[filePath] || oldRemote[filePath] !== remote[filePath]
264
- )
265
- ))
266
- throw new Error("Conflict identity does not match retained immutable evidence.");
267
- return token;
268
- };
269
- const target = tokenPath(config, token);
270
- try {
271
- await fs2.lstat(target);
272
- validate();
273
- return await reuse();
274
- } catch (error) {
275
- if (error.code !== "ENOENT") throw error;
276
- }
277
- const temporary = `${target}.${randomUUID2()}.pending`;
278
- const candidate = { version: 1, identity, ...artifact };
279
- try {
280
- await writeJson(temporary, candidate, { maxBytes: LIMIT });
281
- validate();
282
- const stat = await fs2.lstat(temporary);
283
- validate();
284
- try {
285
- await fs2.link(temporary, target);
286
- } catch (error) {
287
- if (error.code !== "EEXIST") throw error;
288
- validate();
289
- return await reuse();
290
- }
291
- onCreated?.({
292
- token,
293
- target,
294
- dev: stat.dev,
295
- ino: stat.ino,
296
- size: stat.size,
297
- fingerprint: conflictArtifactFingerprint(candidate)
298
- });
299
- validate();
300
- await syncDirectory(path2.dirname(target));
301
- validate();
302
- await syncDirectory(path2.dirname(conflictDirectory(config)));
303
- validate();
304
- return token;
305
- } finally {
306
- await fs2.rm(temporary, { force: true });
307
- }
308
- }
309
- async function readConflictArtifact(config, backend, token) {
310
- try {
311
- await directory(config);
312
- const target = tokenPath(config, token);
313
- const stat = await fs2.lstat(target);
314
- if (!stat.isFile() || stat.size > LIMIT || process.platform !== "win32" && (stat.mode & 63) !== 0)
315
- throw new Error("Unsafe conflict artifact.");
316
- const artifact = JSON.parse(await fs2.readFile(target, "utf8"));
317
- if (artifact.version !== 1 || artifact.identity !== mergeJournalIdentity(config, backend) || !Array.isArray(artifact.groups) || artifact.groups.length > 16384 || artifact.groups.some(
318
- (group) => !Array.isArray(group.paths) || !group.paths.length || group.paths.length > 16384 || !Array.isArray(group.reasons)
319
- ))
320
- throw new Error("Invalid conflict artifact.");
321
- const plan = planFileMerge({
322
- baseline: artifact.state.lastFileHashes,
323
- local: artifact.local.files,
324
- remote: artifact.remote.files,
325
- selectionCompatible: true
326
- });
327
- if (plan.kind !== "planned") throw new Error("Invalid conflict versions.");
328
- const known = new Set(plan.decisions.map((item) => item.path));
329
- if (artifact.groups.some((group) => group.paths.some((value) => !known.has(value))))
330
- throw new Error("Invalid conflict paths.");
331
- if (artifact.ancestors) {
332
- if (!Array.isArray(artifact.ancestors) || artifact.ancestors.length > 16384 || artifact.ancestors.some((file) => artifact.state.lastFileHashes[file.path] !== file.sha256))
333
- throw new Error("Invalid artifact ancestor.");
334
- const basePlan = planFileMerge({
335
- baseline: {},
336
- local: artifact.ancestors,
337
- remote: [],
338
- selectionCompatible: true
339
- });
340
- if (basePlan.kind !== "planned" || basePlan.conflicts.length) throw new Error("Invalid ancestor bytes.");
341
- }
342
- syncStateFingerprint(artifact.state);
343
- return artifact;
344
- } catch {
345
- throw new Error("Cannot verify private conflict artifact; preserve evidence and review a fresh sync.");
346
- }
347
- }
348
-
349
- export {
350
- conflictGroups,
351
- mergeJournalIdentity,
352
- readMergeJournal,
353
- writeMergeJournal,
354
- clearMergeJournal,
355
- retireMergeJournal,
356
- requireNoMergeJournal,
357
- conflictArtifactFingerprint,
358
- conflictDirectory,
359
- saveConflictArtifact,
360
- readConflictArtifact
361
- };
362
- //# sourceMappingURL=chunk-26PMXY7E.ts.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/sync/conflict-artifacts.ts", "../../src/sync/conflict-groups.ts", "../../src/sync/merge-journal.ts"],
4
- "sourcesContent": ["import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot, SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport { syncDirectory, writeJson } from \"../state/json-file.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { statePathForConfig, syncStateFingerprint } from \"../state/sync-state-store.js\";\nimport { planFileMerge } from \"./file-merge-planner.js\";\n\nexport { conflictGroups } from \"./conflict-groups.js\";\n\nimport { mergeJournalIdentity } from \"./merge-journal.js\";\nexport interface ConflictArtifact {\n version: 1;\n identity: string;\n ancestors?: SnapshotFile[];\n state: SyncState;\n local: Snapshot;\n remote: Snapshot;\n groups: { paths: string[]; reasons: string[] }[];\n observed: { snapshotId: string; revision: string };\n}\nconst LIMIT = 192 * 1024 * 1024;\nexport function conflictArtifactFingerprint(artifact: ConflictArtifact) {\n return createHash(\"sha256\").update(JSON.stringify(artifact)).digest(\"hex\");\n}\nexport function conflictDirectory(config: AnySyncConfig) {\n return `${statePathForConfig(config)}.conflicts`;\n}\nasync function directory(config: AnySyncConfig, create = false) {\n const target = conflictDirectory(config);\n if (create) await fs.mkdir(target, { recursive: true, mode: 0o700 });\n const stat = await fs.lstat(target);\n if (!stat.isDirectory() || stat.isSymbolicLink() || (process.platform !== \"win32\" && (stat.mode & 0o077) !== 0))\n throw new Error(\"Unsafe private conflict directory.\");\n return target;\n}\nfunction tokenPath(config: AnySyncConfig, token: string) {\n if (!/^[a-f0-9-]{36}$/u.test(token)) throw new Error(\"Invalid conflict token.\");\n return path.join(conflictDirectory(config), `${token}.json`);\n}\nexport interface CreatedConflictArtifact {\n token: string;\n target: string;\n dev: number;\n ino: number;\n size: number;\n fingerprint: string;\n}\nexport async function saveConflictArtifact(\n config: AnySyncConfig,\n backend: string,\n artifact: Omit<ConflictArtifact, \"version\" | \"identity\">,\n validate: () => void,\n onCreated?: (created: CreatedConflictArtifact) => void,\n) {\n validate();\n const identity = mergeJournalIdentity(config, backend);\n const local = Object.fromEntries(artifact.local.files.map((file) => [file.path, file.sha256]));\n const remote = Object.fromEntries(artifact.remote.files.map((file) => [file.path, file.sha256]));\n const fingerprint = createHash(\"sha256\")\n .update(\n JSON.stringify([\n identity,\n artifact.groups.map((group) =>\n group.paths.map((filePath) => [\n filePath,\n artifact.state.lastFileHashes[filePath] ?? null,\n local[filePath] ?? null,\n remote[filePath] ?? null,\n ]),\n ),\n ]),\n )\n .digest(\"hex\")\n .slice(0, 32);\n const token = `${fingerprint.slice(0, 8)}-${fingerprint.slice(8, 12)}-${fingerprint.slice(12, 16)}-${fingerprint.slice(16, 20)}-${fingerprint.slice(20)}`;\n await directory(config, true);\n validate();\n const reuse = async () => {\n const existing = await readConflictArtifact(config, backend, token);\n validate();\n const oldLocal = Object.fromEntries(existing.local.files.map((file) => [file.path, file.sha256]));\n const oldRemote = Object.fromEntries(existing.remote.files.map((file) => [file.path, file.sha256]));\n if (\n JSON.stringify(existing.groups.map((group) => group.paths)) !==\n JSON.stringify(artifact.groups.map((group) => group.paths)) ||\n artifact.groups.some((group) =>\n group.paths.some(\n (filePath) =>\n existing.state.lastFileHashes[filePath] !== artifact.state.lastFileHashes[filePath] ||\n oldLocal[filePath] !== local[filePath] ||\n oldRemote[filePath] !== remote[filePath],\n ),\n )\n )\n throw new Error(\"Conflict identity does not match retained immutable evidence.\");\n return token;\n };\n const target = tokenPath(config, token);\n try {\n await fs.lstat(target);\n validate();\n return await reuse();\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n const temporary = `${target}.${randomUUID()}.pending`;\n const candidate: ConflictArtifact = { version: 1, identity, ...artifact };\n try {\n await writeJson(temporary, candidate, { maxBytes: LIMIT });\n validate();\n const stat = await fs.lstat(temporary);\n validate();\n try {\n // Publish immutable evidence without replacing a concurrent/pre-existing owner.\n await fs.link(temporary, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n validate();\n return await reuse();\n }\n // Register ownership before any cancellation or durability await can fail.\n onCreated?.({\n token,\n target,\n dev: stat.dev,\n ino: stat.ino,\n size: stat.size,\n fingerprint: conflictArtifactFingerprint(candidate),\n });\n validate();\n await syncDirectory(path.dirname(target));\n validate();\n await syncDirectory(path.dirname(conflictDirectory(config)));\n validate();\n return token;\n } finally {\n await fs.rm(temporary, { force: true });\n }\n}\nexport async function readConflictArtifact(config: AnySyncConfig, backend: string, token: string) {\n try {\n await directory(config);\n const target = tokenPath(config, token);\n const stat = await fs.lstat(target);\n if (!stat.isFile() || stat.size > LIMIT || (process.platform !== \"win32\" && (stat.mode & 0o077) !== 0))\n throw new Error(\"Unsafe conflict artifact.\");\n const artifact = JSON.parse(await fs.readFile(target, \"utf8\")) as ConflictArtifact;\n if (\n artifact.version !== 1 ||\n artifact.identity !== mergeJournalIdentity(config, backend) ||\n !Array.isArray(artifact.groups) ||\n artifact.groups.length > 16_384 ||\n artifact.groups.some(\n (group) =>\n !Array.isArray(group.paths) ||\n !group.paths.length ||\n group.paths.length > 16_384 ||\n !Array.isArray(group.reasons),\n )\n )\n throw new Error(\"Invalid conflict artifact.\");\n const plan = planFileMerge({\n baseline: artifact.state.lastFileHashes,\n local: artifact.local.files,\n remote: artifact.remote.files,\n selectionCompatible: true,\n });\n if (plan.kind !== \"planned\") throw new Error(\"Invalid conflict versions.\");\n const known = new Set(plan.decisions.map((item) => item.path));\n if (artifact.groups.some((group) => group.paths.some((value) => !known.has(value))))\n throw new Error(\"Invalid conflict paths.\");\n if (artifact.ancestors) {\n if (\n !Array.isArray(artifact.ancestors) ||\n artifact.ancestors.length > 16_384 ||\n artifact.ancestors.some((file) => artifact.state.lastFileHashes[file.path] !== file.sha256)\n )\n throw new Error(\"Invalid artifact ancestor.\");\n const basePlan = planFileMerge({\n baseline: {},\n local: artifact.ancestors,\n remote: [],\n selectionCompatible: true,\n });\n if (basePlan.kind !== \"planned\" || basePlan.conflicts.length) throw new Error(\"Invalid ancestor bytes.\");\n }\n syncStateFingerprint(artifact.state);\n return artifact;\n } catch {\n throw new Error(\"Cannot verify private conflict artifact; preserve evidence and review a fresh sync.\");\n }\n}\n", "import type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { type FileMergePlan, mergePathIdentity } from \"./file-merge-planner.js\";\n\n/** Indexed connected closure; path relationships are identical to the conservative merge policy. */\nexport function conflictGroups(plan: Extract<FileMergePlan, { kind: \"planned\" }>, config: AnySyncConfig) {\n const paths = plan.decisions.map((item) => item.path);\n const parents = paths.map((_, index) => index);\n const ranks = paths.map(() => 0);\n const find = (index: number): number => {\n while (parents[index] !== index) {\n parents[index] = parents[parents[index] ?? index] ?? index;\n index = parents[index] ?? index;\n }\n return index;\n };\n const join = (left: number, right: number) => {\n let a = find(left);\n let b = find(right);\n if (a === b) return;\n if ((ranks[a] ?? 0) < (ranks[b] ?? 0)) [a, b] = [b, a];\n parents[b] = a;\n if (ranks[a] === ranks[b]) ranks[a] = (ranks[a] ?? 0) + 1;\n };\n const identities = paths.map(mergePathIdentity);\n const byIdentity = new Map<string, number>();\n const byPath = new Map(paths.map((value, index) => [value, index]));\n identities.forEach((value, index) => {\n const previous = byIdentity.get(value);\n if (previous !== undefined) join(index, previous);\n else byIdentity.set(value, index);\n });\n const includes = new Set(\n config.include\n .filter((value) => ![\"settings.json\", \"AGENTS.md\", \"sessions\"].includes(value))\n .map(mergePathIdentity),\n );\n const buckets = new Map<string, number>();\n const bucket = (key: string, index: number) => {\n const previous = buckets.get(key);\n if (previous === undefined) buckets.set(key, index);\n else join(index, previous);\n };\n paths.forEach((value, index) => {\n const root = value.split(\"/\")[0] ?? \"\";\n if ([\"extensions\", \"themes\", \"skills\", \"prompts\"].includes(root)) bucket(`resource:${root}`, index);\n const segments = (identities[index] ?? \"\").split(\"/\");\n let ancestor = \"\";\n for (let length = 0; length < segments.length - 1; length++) {\n ancestor = ancestor ? `${ancestor}/${segments[length]}` : (segments[length] ?? \"\");\n const parent = byIdentity.get(ancestor);\n if (parent !== undefined) join(index, parent);\n if (includes.has(ancestor)) bucket(`include:${ancestor}`, index);\n }\n });\n const groups = new Map<number, { paths: string[]; reasons: string[] }>();\n for (const conflict of plan.conflicts) {\n const index = byPath.get(conflict.path);\n if (index === undefined) throw new Error(\"Conflict is missing from managed decisions.\");\n const key = find(index);\n const group = groups.get(key) ?? { paths: [], reasons: [] };\n if (!group.reasons.includes(conflict.reason)) group.reasons.push(conflict.reason);\n groups.set(key, group);\n }\n paths.forEach((value, index) => {\n groups.get(find(index))?.paths.push(value);\n });\n return [...groups.values()].map((group) => ({ ...group, paths: group.paths.sort() }));\n}\n", "import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { RemoteHead } from \"../backends/sync-backend.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { readJsonIfExists, syncDirectory, writeJson } from \"../state/json-file.js\";\nimport { statePathForConfig, syncStateFingerprint } from \"../state/sync-state-store.js\";\nimport { planFileMerge } from \"./file-merge-planner.js\";\nimport {\n portableSnapshot,\n sameLocalFields,\n validatePortableSnapshot,\n validateSnapshotFieldPolicy,\n} from \"./local-fields.js\";\nimport type { PartialProgress } from \"./partial-progress.js\";\nimport { fileHashMap, sameHashes } from \"./sync-state.js\";\n\nexport interface MergeJournal {\n version: 1;\n identity: string;\n before: Snapshot;\n after: Snapshot;\n accepted?: Snapshot;\n progress?: PartialProgress;\n upload: Snapshot;\n expectedHead: RemoteHead;\n committedHead?: RemoteHead;\n /** No remote publication was attempted; a stale candidate can retire if local preimages remain intact. */\n applyOnly?: boolean;\n backup: string;\n stateIdentity: string;\n /** Effective collection/apply root; absent legacy evidence cannot authorize session recovery. */\n sessionRoot?: string;\n warnings?: string[];\n}\n\nexport function mergeJournalIdentity(config: AnySyncConfig, backendIdentity: string) {\n return JSON.stringify([config.setupName, backendIdentity, [...config.include].sort(), config.localFields ?? null]);\n}\n\nexport function mergeJournalPath(config: AnySyncConfig) {\n return `${statePathForConfig(config)}.merge-journal.json`;\n}\n\nexport async function readMergeJournal(config: AnySyncConfig): Promise<MergeJournal | undefined> {\n let journal: MergeJournal | undefined;\n try {\n const stat = await fs.lstat(mergeJournalPath(config));\n if (!stat.isFile() || stat.size > 384 * 1024 * 1024) throw new Error(\"Unsafe or oversized journal.\");\n journal = await readJsonIfExists<MergeJournal>(mergeJournalPath(config));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n // A JSON parser error may quote sensitive journal contents; do not retain it in a public error.\n throw new Error(\"Cannot read the private merge journal; preserve it and review recovery.\");\n }\n if (!journal) return;\n if (\n journal.version !== 1 ||\n typeof journal.identity !== \"string\" ||\n typeof journal.backup !== \"string\" ||\n typeof journal.stateIdentity !== \"string\" ||\n (journal.applyOnly !== undefined &&\n (journal.applyOnly !== true ||\n !journal.committedHead ||\n journal.committedHead.revision !== journal.expectedHead?.revision ||\n journal.committedHead.snapshotId !== journal.expectedHead?.snapshotId ||\n journal.upload?.id !== journal.expectedHead?.snapshotId)) ||\n (journal.sessionRoot !== undefined &&\n (typeof journal.sessionRoot !== \"string\" ||\n !path.isAbsolute(journal.sessionRoot) ||\n path.resolve(journal.sessionRoot) !== journal.sessionRoot)) ||\n (journal.warnings !== undefined &&\n (!Array.isArray(journal.warnings) ||\n journal.warnings.length > 64 ||\n journal.warnings.some((item) => typeof item !== \"string\"))) ||\n !journal.expectedHead ||\n typeof journal.expectedHead.revision !== \"string\" ||\n !journal.before ||\n !journal.after ||\n !journal.upload ||\n !Array.isArray(journal.before.files) ||\n !Array.isArray(journal.after.files) ||\n !Array.isArray(journal.upload.files)\n )\n throw new Error(\"Unsupported or damaged merge journal; preserve it and review recovery before syncing.\");\n // Verify every path and byte, including the unmanaged remote files retained for publication.\n try {\n const pinnedPaths = new Set(journal.progress?.groups.flatMap((group) => group.paths) ?? []);\n for (const snapshot of [\n journal.before,\n journal.after,\n journal.upload,\n ...(journal.accepted ? [journal.accepted] : []),\n ]) {\n validateSnapshotFieldPolicy(snapshot);\n if (\n (snapshot.version !== 1 && snapshot.version !== 2 && snapshot.version !== 3) ||\n typeof snapshot.id !== \"string\" ||\n typeof snapshot.profile !== \"string\" ||\n snapshot.files.length > 16_384 ||\n snapshot.files.reduce(\n (bytes, file) =>\n bytes + (typeof file?.contentBase64 === \"string\" ? file.contentBase64.length * 0.75 : Infinity),\n 0,\n ) >\n 64 * 1024 * 1024\n )\n throw new Error(\"Invalid journal input.\");\n const plan = planFileMerge({ baseline: {}, local: snapshot.files, remote: [], selectionCompatible: true });\n if (\n plan.kind !== \"planned\" ||\n plan.conflicts.some((conflict) => conflict.reason !== \"path-collision\" || !pinnedPaths.has(conflict.path))\n )\n throw new Error(\"Invalid journal collision group.\");\n }\n validatePortableSnapshot(journal.upload);\n if ((journal.upload.version === 2 || journal.upload.version === 3) && !journal.accepted)\n throw new Error(\"Portable merge journal requires an explicit accepted projection.\");\n if (journal.accepted) validatePortableSnapshot(journal.accepted);\n } catch {\n throw new Error(\"Invalid merge journal paths, metadata, or bytes; preserve evidence for review.\");\n }\n // Integrity is intrinsic to the recorded transaction, not the user's current recovery policy.\n // completeJournal separately checks that the recorded policy matches the current setup.\n try {\n if (\n journal.accepted &&\n (!sameLocalFields(journal.accepted.localFields, journal.upload.localFields) ||\n !sameHashes(\n fileHashMap(portableSnapshot(journal.after, journal.upload.localFields)),\n fileHashMap(portableSnapshot(journal.accepted, journal.upload.localFields)),\n ))\n )\n throw new Error(\"Projection mismatch.\");\n } catch {\n throw new Error(\"Invalid accepted merge projection; preserve journal evidence.\");\n }\n if (journal.progress) {\n const known = new Set([\n ...Object.keys(journal.progress.previous?.lastFileHashes ?? {}),\n ...[...journal.before.files, ...journal.after.files, ...journal.upload.files].map((file) => file.path),\n ]);\n const progress = journal.progress;\n if (\n !config.partialSync ||\n !progress.previous ||\n syncStateFingerprint(progress.previous) !== journal.stateIdentity ||\n !Array.isArray(progress.groups) ||\n progress.groups.length > 16_384 ||\n progress.groups.some(\n (group) =>\n !Array.isArray(group.paths) ||\n !group.paths.length ||\n group.paths.length > 16_384 ||\n group.paths.some((filePath) => !known.has(filePath)) ||\n !/^[a-f0-9-]{36}$/u.test(group.artifact),\n )\n )\n throw new Error(\"Invalid partial acceptance metadata; preserve journal evidence.\");\n }\n if (journal.progress) {\n const before = fileHashMap(journal.before);\n const after = fileHashMap(journal.after);\n const { readConflictArtifact } = await import(\"./conflict-artifacts.js\");\n const backendIdentity = (JSON.parse(journal.identity) as unknown[])[1];\n if (typeof backendIdentity !== \"string\") throw new Error(\"Invalid partial backend identity.\");\n const byArtifact = new Map<string, typeof journal.progress.groups>();\n for (const group of journal.progress.groups) {\n const groups = byArtifact.get(group.artifact) ?? [];\n groups.push(group);\n byArtifact.set(group.artifact, groups);\n }\n for (const [token, groups] of byArtifact) {\n const artifact = await readConflictArtifact(config, backendIdentity, token);\n const retainedGroups = new Set(artifact.groups.map((group) => JSON.stringify(group.paths)));\n const remote = fileHashMap(artifact.remote);\n const upload = fileHashMap(journal.upload);\n for (const group of groups) {\n if (!retainedGroups.has(JSON.stringify(group.paths)))\n throw new Error(\"Partial group does not match retained artifact evidence.\");\n for (const filePath of group.paths)\n if (\n before[filePath] !== after[filePath] ||\n remote[filePath] !== upload[filePath] ||\n journal.progress.previous.lastFileHashes[filePath] !== artifact.state.lastFileHashes[filePath]\n )\n throw new Error(\"Withheld version changed in journal; preserve evidence.\");\n }\n }\n }\n return journal;\n}\n\nexport async function writeMergeJournal(config: AnySyncConfig, journal: MergeJournal) {\n await writeJson(mergeJournalPath(config), journal, { maxBytes: 384 * 1024 * 1024 });\n}\n\nexport async function clearMergeJournal(config: AnySyncConfig) {\n await fs.rm(mergeJournalPath(config), { force: true });\n await syncDirectory(path.dirname(mergeJournalPath(config)));\n}\n\nexport async function retireMergeJournal(config: AnySyncConfig) {\n if (!(await readMergeJournal(config))) return;\n const file = mergeJournalPath(config);\n await fs.rename(file, `${file}.${randomUUID()}.resolved`);\n await syncDirectory(path.dirname(file));\n}\n\nexport async function requireNoMergeJournal(config: AnySyncConfig, options: { force?: boolean } = {}) {\n const journal = await readMergeJournal(config);\n if (options.force || !journal) return;\n if (journal) {\n throw new Error(\n \"A merged transfer needs recovery. Run /sync sync to reconcile it. If newer local edits or remote revisions prevent recovery, review /sync diff and explicitly choose push --force or pull --force; the selected directional result will archive the old journal, not restore old bytes. Keep its backup; do not downgrade while recovery is pending.\",\n );\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["randomUUID", "fs", "path", "readConflictArtifact", "fs", "path", "randomUUID"]
7
- }