@narumitw/pi-sync 0.54.2 → 0.56.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 (194) hide show
  1. package/README.md +40 -15
  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-IJ6VV6FN.ts → chunk-AAEEHR7H.ts} +31 -87
  14. package/dist/chunks/chunk-AAEEHR7H.ts.map +7 -0
  15. package/dist/chunks/{chunk-CHSIAC4N.ts → chunk-B4QZBDBT.ts} +2 -2
  16. package/dist/chunks/{chunk-CL7BZRRQ.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-VHXBCEVF.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-UQ3ALBIB.ts → chunk-GP5DU62N.ts} +8 -9
  27. package/dist/chunks/chunk-GP5DU62N.ts.map +7 -0
  28. package/dist/chunks/{chunk-5RZPINUQ.ts → chunk-GSNPASKB.ts} +2 -2
  29. package/dist/chunks/{chunk-QE7NZZWT.ts → chunk-IWZH5KYS.ts} +23 -7
  30. package/dist/chunks/chunk-IWZH5KYS.ts.map +7 -0
  31. package/dist/chunks/{chunk-5ZWQ33XL.ts → chunk-JJTARUSO.ts} +15 -14
  32. package/dist/chunks/chunk-JJTARUSO.ts.map +7 -0
  33. package/dist/chunks/{chunk-2DI6PDZV.ts → chunk-NLWS55B6.ts} +15 -2
  34. package/dist/chunks/chunk-NLWS55B6.ts.map +7 -0
  35. package/dist/chunks/{chunk-SDZCTCYQ.ts → chunk-OEWQVWLC.ts} +4 -4
  36. package/dist/chunks/{chunk-MYPSMJHJ.ts → chunk-OTZRCKYP.ts} +380 -510
  37. package/dist/chunks/chunk-OTZRCKYP.ts.map +7 -0
  38. package/dist/chunks/{chunk-WFKUKVCP.ts → chunk-OWBAZA6J.ts} +24 -12
  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-3B4Z2SKV.ts → chunk-QO333NM4.ts} +49 -21
  45. package/dist/chunks/chunk-QO333NM4.ts.map +7 -0
  46. package/dist/chunks/{chunk-4SBTAVFL.ts → chunk-QSHMOL3I.ts} +22 -24
  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-4QVPTIZB.ts → chunk-UPNVIUBN.ts} +3 -3
  57. package/dist/chunks/chunk-UZPMDLTL.ts +54 -0
  58. package/dist/chunks/chunk-UZPMDLTL.ts.map +7 -0
  59. package/dist/chunks/chunk-VJN7KU4J.ts +350 -0
  60. package/dist/chunks/chunk-VJN7KU4J.ts.map +7 -0
  61. package/dist/chunks/chunk-YHT4YTYG.ts +31 -0
  62. package/dist/chunks/chunk-YHT4YTYG.ts.map +7 -0
  63. package/dist/chunks/{chunk-V6VZ5TLG.ts → chunk-YK52VDXG.ts} +6 -5
  64. package/dist/chunks/chunk-YK52VDXG.ts.map +7 -0
  65. package/dist/chunks/config-KGIYTTXQ.ts +37 -0
  66. package/dist/chunks/{conflict-artifacts-BB2FZMIE.ts → conflict-artifacts-FXFIIBCB.ts} +8 -7
  67. package/dist/chunks/{conflict-review-4PLVLMRO.ts → conflict-review-6WIEQLXW.ts} +31 -24
  68. package/dist/chunks/{conflict-review-4PLVLMRO.ts.map → conflict-review-6WIEQLXW.ts.map} +1 -1
  69. package/dist/chunks/continuous-record-LFRVXQBD.ts +30 -0
  70. package/dist/chunks/continuous-sync-AWAAOXK2.ts +545 -0
  71. package/dist/chunks/continuous-sync-AWAAOXK2.ts.map +7 -0
  72. package/dist/chunks/{file-selection-WZX7HAY2.ts → file-selection-3JJYOVNR.ts} +5 -5
  73. package/dist/chunks/{git-backend-FD7AVSK6.ts → git-backend-KYDZ673X.ts} +28 -32
  74. package/dist/chunks/git-backend-KYDZ673X.ts.map +7 -0
  75. package/dist/chunks/{manager-result-dispatcher-6MQKFCWB.ts → manager-result-dispatcher-AGBBVDDS.ts} +10 -9
  76. package/dist/chunks/{manager-ui-IURS4WXY.ts → manager-ui-KRAW3NE2.ts} +464 -164
  77. package/dist/chunks/manager-ui-KRAW3NE2.ts.map +7 -0
  78. package/dist/chunks/{merge-baseline-store-EVQAAML6.ts → merge-baseline-store-RFCAH7KL.ts} +7 -5
  79. package/dist/chunks/{remote-selection-ui-6LJJ4IMQ.ts → remote-selection-ui-5725JDNC.ts} +9 -8
  80. package/dist/chunks/remote-selection-ui-5725JDNC.ts.map +7 -0
  81. package/dist/chunks/{s3-backend-AQGV6LFT.ts → s3-backend-Y7WSCLJI.ts} +38 -38
  82. package/dist/chunks/s3-backend-Y7WSCLJI.ts.map +7 -0
  83. package/dist/chunks/{setup-switch-KTUWL6DE.ts → setup-switch-E7PHKI6J.ts} +7 -6
  84. package/dist/chunks/setup-switch-E7PHKI6J.ts.map +7 -0
  85. package/dist/chunks/{setup-wizard-GSDPDFC4.ts → setup-wizard-65DROCIJ.ts} +14 -13
  86. package/dist/chunks/setup-wizard-65DROCIJ.ts.map +7 -0
  87. package/dist/chunks/{sync-inspection-K45QVLHB.ts → sync-inspection-XFJOAMJD.ts} +9 -8
  88. package/dist/chunks/sync-inspection-XFJOAMJD.ts.map +7 -0
  89. package/dist/chunks/{sync-operations-47OUX76C.ts → sync-operations-HDUDT5PD.ts} +188 -73
  90. package/dist/chunks/sync-operations-HDUDT5PD.ts.map +7 -0
  91. package/dist/chunks/{webdav-backend-TBILVEQK.ts → webdav-backend-6K26F6LT.ts} +39 -48
  92. package/dist/chunks/webdav-backend-6K26F6LT.ts.map +7 -0
  93. package/dist/index.ts +246 -131
  94. package/dist/index.ts.map +3 -3
  95. package/docs/agent-mode-verification.md +99 -0
  96. package/docs/continuous-sync-verification.md +87 -0
  97. package/docs/settings.md +131 -11
  98. package/docs/tui-contract.md +61 -0
  99. package/package.json +3 -2
  100. package/src/backends/git/git-backend.ts +1 -4
  101. package/src/backends/git/git-runner.ts +1 -5
  102. package/src/backends/s3/s3-backend.ts +3 -25
  103. package/src/backends/s3/s3-client.ts +14 -2
  104. package/src/backends/snapshot-pointer.ts +27 -0
  105. package/src/backends/webdav/webdav-backend.ts +3 -29
  106. package/src/backends/webdav/webdav-client.ts +11 -7
  107. package/src/commands/command-execution.ts +7 -3
  108. package/src/commands/command-handler.ts +15 -3
  109. package/src/commands/command-types.ts +10 -0
  110. package/src/commands/command.ts +4 -1
  111. package/src/settings/config.ts +20 -10
  112. package/src/settings/settings-store.ts +1 -34
  113. package/src/settings/settings-types.ts +10 -0
  114. package/src/settings/settings-validation.ts +4 -1
  115. package/src/snapshot/snapshot-codec.ts +1 -5
  116. package/src/state/lock.ts +13 -10
  117. package/src/state/merge-baseline-store.ts +19 -1
  118. package/src/state/state-directory.ts +8 -1
  119. package/src/sync/agent-candidate.ts +251 -0
  120. package/src/sync/agent-plan.ts +87 -0
  121. package/src/sync/agent-policy.ts +13 -0
  122. package/src/sync/agent-request.ts +17 -0
  123. package/src/sync/agent-runner.ts +188 -0
  124. package/src/sync/agent-store.ts +151 -0
  125. package/src/sync/agent-sync.ts +91 -0
  126. package/src/sync/apply-review.ts +63 -0
  127. package/src/sync/automatic-sync.ts +46 -33
  128. package/src/sync/continuous-errors.ts +85 -0
  129. package/src/sync/continuous-lease.ts +221 -0
  130. package/src/sync/continuous-record.ts +179 -0
  131. package/src/sync/continuous-storage.ts +55 -0
  132. package/src/sync/continuous-sync.ts +516 -0
  133. package/src/sync/continuous-watch.ts +59 -0
  134. package/src/sync/merged-sync.ts +268 -112
  135. package/src/sync/remote-snapshot.ts +2 -3
  136. package/src/sync/settings-merge.ts +19 -3
  137. package/src/sync/setup-switch.ts +1 -5
  138. package/src/sync/startup-check.ts +51 -29
  139. package/src/sync/startup-timings.ts +90 -0
  140. package/src/sync/sync-inspection.ts +16 -5
  141. package/src/sync/sync-mutations.ts +55 -28
  142. package/src/sync/sync-queries.ts +19 -3
  143. package/src/sync/text-merge.ts +3 -3
  144. package/src/sync-extension.ts +75 -19
  145. package/src/ui/agent-mode-setting.ts +91 -0
  146. package/src/ui/manager-state.ts +12 -6
  147. package/src/ui/manager-ui.ts +57 -7
  148. package/src/ui/merge-review.ts +3 -3
  149. package/src/ui/merged-sync-summary.ts +2 -18
  150. package/src/ui/remote-selection-ui.ts +5 -5
  151. package/src/ui/settings-frame.ts +55 -0
  152. package/src/ui/settings-ui.ts +223 -43
  153. package/src/ui/setup/s3-credentials-ui.ts +1 -5
  154. package/src/ui/setup/setup-name-ui.ts +2 -5
  155. package/src/ui/setup/setup-prompts.ts +4 -3
  156. package/src/ui/setup/setup-switcher.ts +2 -0
  157. package/src/ui/sync-behavior.ts +15 -0
  158. package/src/ui/sync-format.ts +69 -38
  159. package/src/ui/sync-setups-ui.ts +3 -5
  160. package/src/ui/transfer-changes.ts +33 -0
  161. package/src/ui/transfer-review.ts +27 -0
  162. package/dist/chunks/chunk-2DI6PDZV.ts.map +0 -7
  163. package/dist/chunks/chunk-3B4Z2SKV.ts.map +0 -7
  164. package/dist/chunks/chunk-4SBTAVFL.ts.map +0 -7
  165. package/dist/chunks/chunk-5ZWQ33XL.ts.map +0 -7
  166. package/dist/chunks/chunk-BVVP33U5.ts.map +0 -7
  167. package/dist/chunks/chunk-IJ6VV6FN.ts.map +0 -7
  168. package/dist/chunks/chunk-MYPSMJHJ.ts.map +0 -7
  169. package/dist/chunks/chunk-ORQRHEEO.ts +0 -362
  170. package/dist/chunks/chunk-ORQRHEEO.ts.map +0 -7
  171. package/dist/chunks/chunk-QE7NZZWT.ts.map +0 -7
  172. package/dist/chunks/chunk-UQ3ALBIB.ts.map +0 -7
  173. package/dist/chunks/chunk-V6VZ5TLG.ts.map +0 -7
  174. package/dist/chunks/chunk-WFKUKVCP.ts.map +0 -7
  175. package/dist/chunks/chunk-ZX2Q6THB.ts.map +0 -7
  176. package/dist/chunks/git-backend-FD7AVSK6.ts.map +0 -7
  177. package/dist/chunks/manager-ui-IURS4WXY.ts.map +0 -7
  178. package/dist/chunks/s3-backend-AQGV6LFT.ts.map +0 -7
  179. package/dist/chunks/setup-wizard-GSDPDFC4.ts.map +0 -7
  180. package/dist/chunks/sync-operations-47OUX76C.ts.map +0 -7
  181. package/dist/chunks/webdav-backend-TBILVEQK.ts.map +0 -7
  182. /package/dist/chunks/{conflict-artifacts-BB2FZMIE.ts.map → agent-candidate-3JN6DJKT.ts.map} +0 -0
  183. /package/dist/chunks/{chunk-CHSIAC4N.ts.map → chunk-B4QZBDBT.ts.map} +0 -0
  184. /package/dist/chunks/{chunk-CL7BZRRQ.ts.map → chunk-CRKTAPSL.ts.map} +0 -0
  185. /package/dist/chunks/{chunk-VHXBCEVF.ts.map → chunk-EUMINX7L.ts.map} +0 -0
  186. /package/dist/chunks/{chunk-5RZPINUQ.ts.map → chunk-GSNPASKB.ts.map} +0 -0
  187. /package/dist/chunks/{chunk-SDZCTCYQ.ts.map → chunk-OEWQVWLC.ts.map} +0 -0
  188. /package/dist/chunks/{chunk-4QVPTIZB.ts.map → chunk-UPNVIUBN.ts.map} +0 -0
  189. /package/dist/chunks/{manager-result-dispatcher-6MQKFCWB.ts.map → config-KGIYTTXQ.ts.map} +0 -0
  190. /package/dist/chunks/{merge-baseline-store-EVQAAML6.ts.map → conflict-artifacts-FXFIIBCB.ts.map} +0 -0
  191. /package/dist/chunks/{remote-selection-ui-6LJJ4IMQ.ts.map → continuous-record-LFRVXQBD.ts.map} +0 -0
  192. /package/dist/chunks/{file-selection-WZX7HAY2.ts.map → file-selection-3JJYOVNR.ts.map} +0 -0
  193. /package/dist/chunks/{setup-switch-KTUWL6DE.ts.map → manager-result-dispatcher-AGBBVDDS.ts.map} +0 -0
  194. /package/dist/chunks/{sync-inspection-K45QVLHB.ts.map → merge-baseline-store-RFCAH7KL.ts.map} +0 -0
@@ -1,45 +1,52 @@
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
3
  import {
4
- confirmMergeReview,
5
4
  mergeSync
6
- } from "./chunk-MYPSMJHJ.ts";
5
+ } from "./chunk-OTZRCKYP.ts";
6
+ import {
7
+ confirmMergeReview
8
+ } from "./chunk-5XZOC7FD.ts";
9
+ import "./chunk-YK52VDXG.ts";
10
+ import {
11
+ createSyncBackend
12
+ } from "./chunk-OEWQVWLC.ts";
7
13
  import {
8
14
  conflictArtifactFingerprint,
9
15
  readConflictArtifact
10
- } from "./chunk-ORQRHEEO.ts";
16
+ } from "./chunk-ED3TYIVW.ts";
17
+ import "./chunk-GNH73BJ5.ts";
11
18
  import "./chunk-BDB4IDM3.ts";
12
- import "./chunk-V6VZ5TLG.ts";
13
- import {
14
- createSyncBackend
15
- } from "./chunk-SDZCTCYQ.ts";
16
- import "./chunk-CL7BZRRQ.ts";
19
+ import "./chunk-CRKTAPSL.ts";
17
20
  import {
18
21
  captureMutationOwner
19
- } from "./chunk-IJ6VV6FN.ts";
20
- import "./chunk-PWMWOJP4.ts";
22
+ } from "./chunk-UOHR7LRO.ts";
21
23
  import {
22
24
  safeTerminalText
23
25
  } from "./chunk-AMJRUXFT.ts";
24
- import "./chunk-QE7NZZWT.ts";
25
- import "./chunk-76NB4R7U.ts";
26
- import {
27
- readStateForConfig,
28
- syncStateFingerprint
29
- } from "./chunk-4QVPTIZB.ts";
30
- import "./chunk-BVVP33U5.ts";
26
+ import "./chunk-UZPMDLTL.ts";
27
+ import "./chunk-UBV24CG4.ts";
28
+ import "./chunk-7D5SF7P3.ts";
31
29
  import {
32
30
  loadConfig,
33
31
  syncCheckConfigFingerprint
34
- } from "./chunk-3B4Z2SKV.ts";
35
- import "./chunk-2JZFHNLM.ts";
36
- import "./chunk-T2SJD3N7.ts";
37
- import "./chunk-YDVQYUHE.ts";
38
- import "./chunk-ZX2Q6THB.ts";
39
- import "./chunk-7D5SF7P3.ts";
32
+ } from "./chunk-QO333NM4.ts";
40
33
  import "./chunk-A6HU4ERM.ts";
34
+ import "./chunk-AAEEHR7H.ts";
35
+ import "./chunk-PWMWOJP4.ts";
36
+ import "./chunk-YDVQYUHE.ts";
37
+ import "./chunk-5Q5SSKNG.ts";
41
38
  import "./chunk-QOFMXPM5.ts";
39
+ import "./chunk-IWZH5KYS.ts";
40
+ import "./chunk-76NB4R7U.ts";
42
41
  import "./chunk-ZW5ZLGBI.ts";
42
+ import "./chunk-PRUEIIK7.ts";
43
+ import {
44
+ readStateForConfig,
45
+ syncStateFingerprint
46
+ } from "./chunk-UPNVIUBN.ts";
47
+ import "./chunk-SWRVXVFD.ts";
48
+ import "./chunk-2JZFHNLM.ts";
49
+ import "./chunk-T2SJD3N7.ts";
43
50
  import "./chunk-HUZ5CR4W.ts";
44
51
 
45
52
  // src/sync/conflict-review.ts
@@ -172,4 +179,4 @@ async function showConflicts(ctx, options, factory = createSyncBackend) {
172
179
  export {
173
180
  showConflicts
174
181
  };
175
- //# sourceMappingURL=conflict-review-4PLVLMRO.ts.map
182
+ //# sourceMappingURL=conflict-review-6WIEQLXW.ts.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/sync/conflict-review.ts", "../../src/sync/conflict-preview.ts"],
4
4
  "sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncCheckConfigFingerprint } from \"../settings/config.js\";\nimport { readStateForConfig, syncStateFingerprint } from \"../state/sync-state-store.js\";\nimport { confirmMergeReview } from \"../ui/merge-review.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { conflictArtifactFingerprint, readConflictArtifact } from \"./conflict-artifacts.js\";\nimport { conflictPreview } from \"./conflict-preview.js\";\nimport { mergeSync } from \"./merged-sync.js\";\nimport { captureMutationOwner } from \"./sync-local.js\";\nexport async function showConflicts(\n ctx: ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validate = captureMutationOwner(ctx, options.signal);\n const config = await loadConfig(options.setup);\n validate();\n const state = await readStateForConfig(config);\n validate();\n if (!state.unresolved?.length) {\n ctx.ui.notify(\"No recorded unresolved conflict groups.\", \"info\");\n return;\n }\n if (!ctx.hasUI) {\n ctx.ui.notify(\n `${state.unresolved.length} conflict groups remain unresolved. Review with TUI/RPC; no transfer performed.`,\n \"warning\",\n );\n return;\n }\n const backend = await factory(config);\n validate();\n const labels = state.unresolved.map(\n (group, index) =>\n `${index + 1}: ${group.paths.length} paths \u00B7 ${group.paths\n .slice(0, 3)\n .map((value) => truncateToWidth(safeTerminalText(value), 80))\n .join(\", \")}${group.paths.length > 3 ? \", \u2026\" : \"\"}`,\n );\n const choice = await ctx.ui.select(\"Review unresolved dependency group\", [...labels, \"Keep all unresolved\"], {\n signal: options.signal,\n });\n validate();\n const index = labels.indexOf(choice ?? \"\");\n if (index < 0) return;\n const reference = state.unresolved[index];\n if (!reference) return;\n const artifact = await readConflictArtifact(config, backend.identity, reference.artifact);\n validate();\n const groupIndex = artifact.groups.findIndex(\n (group) => JSON.stringify(group.paths) === JSON.stringify(reference.paths),\n );\n if (groupIndex < 0) throw new Error(\"Conflict reference is stale; refresh sync.\");\n const body = conflictPreview(artifact, reference.paths, backend.destination);\n if (\n !(await confirmMergeReview(\n ctx,\n \"Review private conflict versions\",\n body,\n options.signal,\n () => {\n try {\n validate();\n return true;\n } catch {\n return false;\n }\n },\n \"Continue to resolution choices\",\n ))\n )\n return;\n validate();\n const decision = await ctx.ui.select(\n \"Resolve the entire reviewed group\",\n [\"Keep unresolved\", \"Use local group\", \"Use remote group\"],\n { signal: options.signal },\n );\n validate();\n if (decision !== \"Use local group\" && decision !== \"Use remote group\") return;\n if (syncCheckConfigFingerprint(config) !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during conflict review.\");\n validate();\n await mergeSync(ctx, { ...options, yes: false, auto: false }, factory, {\n token: reference.artifact,\n group: groupIndex,\n source: decision === \"Use local group\" ? \"local\" : \"remote\",\n stateIdentity: syncStateFingerprint(state),\n artifactIdentity: conflictArtifactFingerprint(artifact),\n });\n validate();\n}\n", "import type { SnapshotFile } from \"../snapshot/snapshot-types.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport type { ConflictArtifact } from \"./conflict-artifacts.js\";\n\nexport const CONFLICT_DISPLAY_BYTES = 2 * 1024 * 1024;\nconst tooLarge = () =>\n new Error(\n \"Conflict review exceeds the 2 MiB display bound; inspect private evidence and use a reviewed explicit direction.\",\n );\n\n/** Index once and refuse a version before decoding if it cannot fit the remaining display budget. */\nexport function conflictPreview(artifact: ConflictArtifact, paths: readonly string[], destination: string) {\n const index = (files: SnapshotFile[]) => new Map(files.map((file) => [file.path, file]));\n const ancestors = index(artifact.ancestors ?? []);\n const local = index(artifact.local.files);\n const remote = index(artifact.remote.files);\n const parts: string[] = [];\n let size = 0;\n const remaining = () => CONFLICT_DISPLAY_BYTES - size - (parts.length ? 1 : 0);\n const append = (value: string, prefix = \"\") => {\n if (Buffer.byteLength(value) + Buffer.byteLength(prefix) > remaining()) throw tooLarge();\n // Sanitize at the display boundary, retaining line endings and raw evidence unchanged.\n parts.push(prefix + value.split(\"\\n\").map(safeTerminalText).join(\"\\n\"));\n size += Buffer.byteLength(prefix) + Buffer.byteLength(value) + (parts.length > 1 ? 1 : 0);\n };\n const version = (files: Map<string, SnapshotFile>, filePath: string) => {\n const file = files.get(filePath);\n if (!file) return append(\"(absent)\");\n append(file.sha256, \"sha256: \");\n if (Buffer.byteLength(file.contentBase64, \"base64\") > remaining()) throw tooLarge();\n const bytes = Buffer.from(file.contentBase64, \"base64\");\n let value: string;\n try {\n value = new TextDecoder(\"utf-8\", { fatal: true, ignoreBOM: true }).decode(bytes);\n } catch {\n return append(file.contentBase64, \"base64: \");\n }\n append(value);\n };\n append(safeTerminalText(destination), \"Storage: \");\n append(\n \"Private conflict versions. Historical artifact is not authority for changed bytes/head. No automatic activation.\",\n );\n for (const filePath of paths) {\n append(safeTerminalText(filePath), \"Path: \");\n append(\"Base:\");\n const hash = artifact.state.lastFileHashes[filePath];\n if (hash && !ancestors.has(filePath)) append(`(verified ancestor unavailable; sha256: ${hash})`);\n else version(ancestors, filePath);\n append(\"Local:\");\n version(local, filePath);\n append(\"Remote:\");\n version(remote, filePath);\n }\n return parts.join(\"\\n\");\n}\n"],
5
- "mappings": "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",
5
+ "mappings": "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",
6
6
  "names": ["index"]
7
7
  }
@@ -0,0 +1,30 @@
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
+ REQUEST_WINDOW_MS,
5
+ continuousStatusLines,
6
+ normalizeContinuousClock,
7
+ readContinuousRecord,
8
+ reserveContinuousRequest,
9
+ updateContinuousRecord,
10
+ validateContinuousRecord
11
+ } from "./chunk-VJN7KU4J.ts";
12
+ import "./chunk-AAEEHR7H.ts";
13
+ import "./chunk-PWMWOJP4.ts";
14
+ import "./chunk-DT7M4VQS.ts";
15
+ import "./chunk-YDVQYUHE.ts";
16
+ import "./chunk-UPNVIUBN.ts";
17
+ import "./chunk-SWRVXVFD.ts";
18
+ import "./chunk-2JZFHNLM.ts";
19
+ import "./chunk-T2SJD3N7.ts";
20
+ import "./chunk-HUZ5CR4W.ts";
21
+ export {
22
+ REQUEST_WINDOW_MS,
23
+ continuousStatusLines,
24
+ normalizeContinuousClock,
25
+ readContinuousRecord,
26
+ reserveContinuousRequest,
27
+ updateContinuousRecord,
28
+ validateContinuousRecord
29
+ };
30
+ //# sourceMappingURL=continuous-record-LFRVXQBD.ts.map
@@ -0,0 +1,545 @@
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
+ acquireContinuousLease,
5
+ continuousBinding,
6
+ hashContinuous,
7
+ normalizeContinuousClock,
8
+ readContinuousRecord,
9
+ reserveContinuousRequest,
10
+ updateContinuousRecord
11
+ } from "./chunk-VJN7KU4J.ts";
12
+ import {
13
+ readMergeJournal
14
+ } from "./chunk-GNH73BJ5.ts";
15
+ import {
16
+ fileHashMap
17
+ } from "./chunk-BDB4IDM3.ts";
18
+ import {
19
+ withAgentSyncLock
20
+ } from "./chunk-S2FMH5FT.ts";
21
+ import {
22
+ captureMutationOwner
23
+ } from "./chunk-UOHR7LRO.ts";
24
+ import {
25
+ setSyncStatus
26
+ } from "./chunk-K3RIEL6J.ts";
27
+ import "./chunk-UBV24CG4.ts";
28
+ import "./chunk-QGK445K7.ts";
29
+ import {
30
+ loadConfigForCheck,
31
+ syncCheckConfigFingerprint
32
+ } from "./chunk-QO333NM4.ts";
33
+ import "./chunk-A6HU4ERM.ts";
34
+ import {
35
+ withLock
36
+ } from "./chunk-AAEEHR7H.ts";
37
+ import "./chunk-PWMWOJP4.ts";
38
+ import {
39
+ ContinuousError,
40
+ continuousFailure
41
+ } from "./chunk-DT7M4VQS.ts";
42
+ import "./chunk-YDVQYUHE.ts";
43
+ import {
44
+ snapshotOptionsForContext
45
+ } from "./chunk-QOFMXPM5.ts";
46
+ import "./chunk-76NB4R7U.ts";
47
+ import "./chunk-ZW5ZLGBI.ts";
48
+ import "./chunk-PRUEIIK7.ts";
49
+ import {
50
+ readStateForConfig
51
+ } from "./chunk-UPNVIUBN.ts";
52
+ import {
53
+ withStateDirectoryAccess
54
+ } from "./chunk-SWRVXVFD.ts";
55
+ import "./chunk-2JZFHNLM.ts";
56
+ import "./chunk-T2SJD3N7.ts";
57
+ import {
58
+ isDeniedPath
59
+ } from "./chunk-HUZ5CR4W.ts";
60
+
61
+ // src/sync/continuous-watch.ts
62
+ import { watch } from "node:fs";
63
+ import fs from "node:fs/promises";
64
+ import path from "node:path";
65
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
66
+ async function watchContinuous(config, changed) {
67
+ const root = getAgentDir();
68
+ const watchers = [];
69
+ const selected = config.include.map((item) => path.resolve(root, item));
70
+ const relevant = (target) => selected.some(
71
+ (item) => target === item || target.startsWith(`${item}${path.sep}`) || item.startsWith(`${target}${path.sep}`)
72
+ );
73
+ const add = (directory, recursive) => {
74
+ try {
75
+ const watcher = watch(directory, { recursive, persistent: false }, (_event, file) => {
76
+ if (!file) return;
77
+ const target = path.resolve(directory, String(file));
78
+ if (target === path.join(root, "pi-sync.json")) changed(true);
79
+ else if (isDeniedPath(path.relative(root, target))) return;
80
+ else if (relevant(target)) changed(false);
81
+ });
82
+ watcher.on("error", () => watcher.close());
83
+ watchers.push(watcher);
84
+ } catch {
85
+ }
86
+ };
87
+ add(root, false);
88
+ const directories = /* @__PURE__ */ new Set();
89
+ try {
90
+ for (const target of selected) {
91
+ try {
92
+ const stat = await fs.lstat(target);
93
+ if (stat.isSymbolicLink()) continue;
94
+ const directory = stat.isDirectory() ? target : path.dirname(target);
95
+ if (directory === root || directories.has(directory)) continue;
96
+ directories.add(directory);
97
+ add(directory, stat.isDirectory());
98
+ } catch (error) {
99
+ if (error.code !== "ENOENT") continue;
100
+ }
101
+ }
102
+ return () => {
103
+ for (const watcher of watchers) watcher.close();
104
+ };
105
+ } catch (error) {
106
+ for (const watcher of watchers) watcher.close();
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ // src/sync/continuous-sync.ts
112
+ function continuousEnabled(config) {
113
+ return Boolean(config.continuous && config.agentMode);
114
+ }
115
+ var systemClock = {
116
+ now: () => Date.now(),
117
+ random: () => Math.random(),
118
+ schedule: (ms, run) => {
119
+ const timer = setTimeout(run, ms);
120
+ timer.unref?.();
121
+ return () => clearTimeout(timer);
122
+ }
123
+ };
124
+ var LOCAL_CHECK_MS = 5e3;
125
+ var POLL_MS = 6e4;
126
+ var DEBOUNCE_MS = 1e3;
127
+ function createContinuousSync(loaders, clock = systemClock) {
128
+ const repairNotices = /* @__PURE__ */ new WeakSet();
129
+ let task;
130
+ return {
131
+ start(ctx, sessionSignal, explicitRetry = false) {
132
+ if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc" || sessionSignal.aborted || task) return;
133
+ const controller = new AbortController();
134
+ const signal = AbortSignal.any([sessionSignal, controller.signal]);
135
+ const validateContext = captureMutationOwner(ctx);
136
+ const current = {
137
+ owner: ctx.sessionManager,
138
+ controller,
139
+ promise: Promise.resolve(),
140
+ clear: () => {
141
+ try {
142
+ validateContext();
143
+ setSyncStatus(ctx, void 0);
144
+ } catch {
145
+ }
146
+ }
147
+ };
148
+ task = current;
149
+ current.promise = (async () => {
150
+ let explicit = explicitRetry;
151
+ while (!signal.aborted) {
152
+ try {
153
+ await run(ctx, signal, explicit);
154
+ return;
155
+ } catch {
156
+ if (signal.aborted) return;
157
+ try {
158
+ validateContext();
159
+ setSyncStatus(ctx, "sync blocked: private state or settings need repair");
160
+ if (!repairNotices.has(ctx.sessionManager)) {
161
+ repairNotices.add(ctx.sessionManager);
162
+ ctx.ui.notify(
163
+ "Continuous sync blocked: private state or settings need repair. Use /sync. Evidence was retained.",
164
+ "warning"
165
+ );
166
+ }
167
+ } catch {
168
+ return;
169
+ }
170
+ }
171
+ explicit = false;
172
+ await wait(clock, LOCAL_CHECK_MS, signal);
173
+ }
174
+ })().catch(() => {
175
+ }).finally(() => {
176
+ if (task === current) task = void 0;
177
+ });
178
+ },
179
+ async stop(owner) {
180
+ const current = task;
181
+ if (!current || owner && current.owner !== owner) return;
182
+ current.controller.abort(new DOMException("Continuous sync interrupted", "AbortError"));
183
+ current.clear();
184
+ await current.promise;
185
+ }
186
+ };
187
+ async function run(ctx, signal, explicitRetry) {
188
+ const validateOwner = captureMutationOwner(ctx, signal);
189
+ try {
190
+ while (!signal.aborted) {
191
+ validateOwner();
192
+ const config = await loadConfigForCheck();
193
+ validateOwner();
194
+ if (!continuousEnabled(config)) return;
195
+ try {
196
+ if (ctx.isIdle()) {
197
+ let lease;
198
+ let binding = "";
199
+ try {
200
+ await withStateDirectoryAccess(async () => {
201
+ validateOwner();
202
+ binding = await continuousBinding(config);
203
+ validateOwner();
204
+ lease = await acquireContinuousLease(binding);
205
+ validateOwner();
206
+ });
207
+ if (lease) {
208
+ await monitor(ctx, config, binding, lease, signal, explicitRetry);
209
+ explicitRetry = false;
210
+ } else setSyncStatus(ctx, "sync waiting: another local owner");
211
+ } finally {
212
+ await lease?.release();
213
+ }
214
+ }
215
+ } catch (error) {
216
+ if (signal.aborted) return;
217
+ const failure = continuousFailure(error);
218
+ if (!failure.retry && !(error instanceof Error && error.name === "AbortError")) throw error;
219
+ setSyncStatus(ctx, `sync retry scheduled: ${failure.kind}`);
220
+ }
221
+ validateOwner();
222
+ if (!continuousEnabled(await loadConfigForCheck())) return;
223
+ validateOwner();
224
+ await wait(clock, LOCAL_CHECK_MS, signal);
225
+ }
226
+ } finally {
227
+ if (!signal.aborted) {
228
+ try {
229
+ validateOwner();
230
+ setSyncStatus(ctx, void 0);
231
+ } catch {
232
+ }
233
+ }
234
+ }
235
+ }
236
+ async function monitor(ctx, initial, binding, lease, parent, explicitRetry) {
237
+ const signal = AbortSignal.any([parent, lease.signal]);
238
+ const validateOwner = captureMutationOwner(ctx, signal);
239
+ let config = initial;
240
+ let closeWatch = () => {
241
+ };
242
+ let wake = () => {
243
+ };
244
+ let dirtyAt;
245
+ let cycle;
246
+ const changed = (settings) => {
247
+ dirtyAt = clock.now();
248
+ if (settings) cycle?.abort(new DOMException("Continuous settings changed", "AbortError"));
249
+ wake();
250
+ };
251
+ const validate = () => {
252
+ validateOwner();
253
+ lease.assert();
254
+ if (!ctx.isIdle()) throw new DOMException("Owning session became busy", "AbortError");
255
+ };
256
+ const stopWatch = () => {
257
+ closeWatch();
258
+ wake();
259
+ };
260
+ signal.addEventListener("abort", stopWatch, { once: true });
261
+ let pollDue = 0;
262
+ try {
263
+ closeWatch = await watchContinuous(config, changed);
264
+ validate();
265
+ while (!signal.aborted && ctx.isIdle()) {
266
+ validate();
267
+ const latest = await loadConfigForCheck();
268
+ validate();
269
+ if (!continuousEnabled(latest) || await continuousBinding(latest) !== binding) return;
270
+ validate();
271
+ if (syncCheckConfigFingerprint(latest) !== syncCheckConfigFingerprint(config)) {
272
+ closeWatch();
273
+ config = latest;
274
+ closeWatch = await watchContinuous(config, changed);
275
+ validate();
276
+ pollDue = 0;
277
+ }
278
+ const record = await readContinuousRecord(binding);
279
+ validate();
280
+ const now = clock.now();
281
+ const oldClock = JSON.stringify([record.next, record.calls]);
282
+ normalizeContinuousClock(record, now);
283
+ if (oldClock !== JSON.stringify([record.next, record.calls])) {
284
+ await updateContinuousRecord(binding, lease, (current) => normalizeContinuousClock(current, now));
285
+ validate();
286
+ }
287
+ const configuration = hashContinuous([{ ...config, showStatus: void 0, debug: void 0 }, ctx.model]);
288
+ const controlChanged = record.configuration !== configuration;
289
+ if (controlChanged || explicitRetry) {
290
+ record.next = 0;
291
+ pollDue = 0;
292
+ }
293
+ const hintDue = dirtyAt === void 0 ? Number.POSITIVE_INFINITY : dirtyAt + DEBOUNCE_MS;
294
+ const due = Math.max(record.error === "budget" ? 0 : record.next, Math.min(pollDue, hintDue));
295
+ if (now >= due) {
296
+ const force = explicitRetry || controlChanged;
297
+ explicitRetry = false;
298
+ const expectedModel = hashContinuous(ctx.model);
299
+ const expectedConfig = syncCheckConfigFingerprint(config);
300
+ dirtyAt = void 0;
301
+ cycle = new AbortController();
302
+ const cancelDeadline = clock.schedule(
303
+ 3e4,
304
+ () => cycle?.abort(new DOMException("Continuous cycle timed out", "TimeoutError"))
305
+ );
306
+ const guard = new AbortController();
307
+ const guardSignal = AbortSignal.any([signal, cycle.signal, guard.signal]);
308
+ const activeCycle = cycle;
309
+ const validateCycle = (latest2) => {
310
+ validate();
311
+ if (latest2 && syncCheckConfigFingerprint(latest2) !== expectedConfig || hashContinuous(ctx.model) !== expectedModel)
312
+ activeCycle.abort(new DOMException("Continuous authorization changed", "AbortError"));
313
+ activeCycle.signal.throwIfAborted();
314
+ };
315
+ const guardTask = (async () => {
316
+ while (!guardSignal.aborted) {
317
+ await wait(clock, LOCAL_CHECK_MS, guardSignal, void 0, "authorization");
318
+ if (guardSignal.aborted) return;
319
+ try {
320
+ validate();
321
+ const latest2 = await loadConfigForCheck();
322
+ if (guardSignal.aborted) return;
323
+ validateCycle(latest2);
324
+ } catch {
325
+ activeCycle.abort(new DOMException("Continuous authorization unavailable", "AbortError"));
326
+ }
327
+ }
328
+ })().catch(() => {
329
+ });
330
+ try {
331
+ await performCycle(
332
+ ctx,
333
+ config,
334
+ binding,
335
+ lease,
336
+ AbortSignal.any([signal, cycle.signal]),
337
+ validateCycle,
338
+ configuration,
339
+ force
340
+ );
341
+ } catch (error) {
342
+ if (signal.aborted || !ctx.isIdle()) return;
343
+ if (cycle.signal.aborted && cycle.signal.reason?.name !== "TimeoutError") {
344
+ pollDue = 0;
345
+ continue;
346
+ }
347
+ const failure = continuousFailure(error);
348
+ let announce = false;
349
+ await updateContinuousRecord(binding, lease, (current) => {
350
+ const now2 = clock.now();
351
+ normalizeContinuousClock(current, now2);
352
+ const notice = hashContinuous([failure.kind, current.evidence, configuration]);
353
+ announce = current.notice !== notice;
354
+ if (!failure.retry) current.notice = notice;
355
+ current.configuration = configuration;
356
+ current.pending = true;
357
+ current.error = failure.kind;
358
+ current.phase = failure.retry ? "retry" : "blocked";
359
+ current.failures = Math.min(30, current.failures + 1);
360
+ const base = Math.min(3e5, 5e3 * 2 ** Math.min(6, current.failures - 1));
361
+ const delay = Math.min(3e5, base + Math.floor(clock.random() * base * 0.2));
362
+ current.next = now2 + Math.max(delay, failure.delay ?? 0);
363
+ });
364
+ validate();
365
+ if (announce && !failure.retry)
366
+ ctx.ui.notify(
367
+ `Continuous sync blocked (${failure.kind}). Review /sync or repair the setup. Evidence was retained.`,
368
+ "warning"
369
+ );
370
+ } finally {
371
+ cancelDeadline();
372
+ guard.abort();
373
+ await guardTask;
374
+ cycle = void 0;
375
+ }
376
+ pollDue = clock.now() + POLL_MS + Math.floor(clock.random() * 6e3);
377
+ closeWatch();
378
+ closeWatch = () => {
379
+ };
380
+ closeWatch = await watchContinuous(config, changed);
381
+ validate();
382
+ }
383
+ validate();
384
+ const state = await readContinuousRecord(binding);
385
+ validate();
386
+ setSyncStatus(
387
+ ctx,
388
+ state.phase === "blocked" ? `sync blocked: ${state.error}` : state.phase === "retry" ? `sync retry scheduled: ${state.error}` : "sync waiting for changes"
389
+ );
390
+ if (state.phase === "retry") pollDue = Math.min(pollDue, state.next);
391
+ const next = Math.max(
392
+ state.error === "budget" ? 0 : state.next,
393
+ Math.min(pollDue, dirtyAt === void 0 ? Number.POSITIVE_INFINITY : dirtyAt + DEBOUNCE_MS)
394
+ );
395
+ await wait(clock, Math.max(1, Math.min(LOCAL_CHECK_MS, next - clock.now())), signal, (callback) => {
396
+ wake = callback;
397
+ });
398
+ }
399
+ } finally {
400
+ signal.removeEventListener("abort", stopWatch);
401
+ closeWatch();
402
+ cycle?.abort();
403
+ }
404
+ }
405
+ async function performCycle(ctx, config, binding, lease, signal, validateOwner, configuration, force) {
406
+ const validate = (latest) => {
407
+ signal.throwIfAborted();
408
+ validateOwner(latest);
409
+ };
410
+ validate();
411
+ const current = await readContinuousRecord(binding);
412
+ validate();
413
+ const pending = await guardedLock("continuous-journal", () => readMergeJournal(config));
414
+ validate();
415
+ if (!force && !pending && current.phase === "blocked" && ["authentication", "storage", "unknown"].includes(current.error ?? ""))
416
+ return;
417
+ setSyncStatus(ctx, "sync checking");
418
+ const inspectionModule = await loaders.inspection();
419
+ validate();
420
+ const observed = await guardedLock("continuous-check", async () => {
421
+ validate();
422
+ const inspection = await inspectionModule.inspectSync(config, snapshotOptionsForContext(ctx, config), signal);
423
+ validate();
424
+ let localIdentity = inspection.localIdentity;
425
+ if (!localIdentity) {
426
+ const snapshotModule = await loaders.snapshot();
427
+ validate();
428
+ const local = await snapshotModule.createSnapshot(config.snapshotIdentity, {
429
+ ...snapshotOptionsForContext(ctx, config),
430
+ signal
431
+ });
432
+ validate();
433
+ localIdentity = hashContinuous(fileHashMap(local));
434
+ }
435
+ const journal = await readMergeJournal(config);
436
+ validate();
437
+ return { inspection, journal, localIdentity };
438
+ });
439
+ validate();
440
+ const evidence = hashContinuous([
441
+ configuration,
442
+ observed.localIdentity,
443
+ observed.inspection.head?.revision,
444
+ observed.inspection.stateIdentity
445
+ ]);
446
+ const recovery = observed.journal ? hashContinuous([evidence, observed.journal]) : void 0;
447
+ const blocked = !force && current.evidence === evidence && (current.phase === "blocked" && (!recovery || recovery === current.recovery) || current.error === "budget" && current.next > clock.now() && !observed.journal);
448
+ await updateContinuousRecord(binding, lease, (record) => {
449
+ if (record.configuration !== configuration) {
450
+ record.failures = 0;
451
+ record.next = 0;
452
+ }
453
+ record.configuration = configuration;
454
+ record.checked = clock.now();
455
+ record.evidence = evidence;
456
+ if (!blocked) {
457
+ if (record.phase !== "blocked") record.phase = "syncing";
458
+ record.pending = true;
459
+ if (recovery) record.recovery = recovery;
460
+ }
461
+ });
462
+ validate();
463
+ if (blocked) return;
464
+ if (!observed.journal && (observed.inspection.firstSync || !observed.inspection.head || observed.inspection.selectionState?.kind !== "same"))
465
+ throw new ContinuousError("unsafe", "Continuous sync needs an accepted baseline and matching remote selection.");
466
+ let transferred = false;
467
+ if (observed.journal || observed.inspection.localChanged || observed.inspection.remoteChanged) {
468
+ const operations = await loaders.operations();
469
+ validate();
470
+ setSyncStatus(ctx, "sync syncing");
471
+ const result = await withStateDirectoryAccess(
472
+ () => withAgentSyncLock(
473
+ ctx,
474
+ {
475
+ args: [],
476
+ yes: true,
477
+ force: false,
478
+ stale: false,
479
+ silent: true,
480
+ reload: false,
481
+ auto: true,
482
+ signal,
483
+ background: {
484
+ validate,
485
+ reserve: (key) => reserveContinuousRequest(binding, lease, key, () => clock.now())
486
+ }
487
+ },
488
+ (options) => operations.syncBoth(ctx, options)
489
+ )
490
+ );
491
+ validate();
492
+ transferred = result === "applied";
493
+ }
494
+ const state = await guardedLock("continuous-result", () => readStateForConfig(config));
495
+ validate();
496
+ const unresolved = state.unresolved;
497
+ let announcePartial = false;
498
+ await updateContinuousRecord(binding, lease, (record) => {
499
+ record.phase = unresolved?.length ? "blocked" : "waiting";
500
+ record.pending = Boolean(unresolved?.length);
501
+ record.failures = 0;
502
+ record.next = 0;
503
+ if (unresolved?.length) {
504
+ record.error = "unsafe";
505
+ const notice = hashContinuous(["partial", unresolved, configuration]);
506
+ announcePartial = record.notice !== notice;
507
+ record.notice = notice;
508
+ } else {
509
+ delete record.error;
510
+ delete record.notice;
511
+ }
512
+ if (transferred) record.transferred = clock.now();
513
+ });
514
+ validate();
515
+ if (announcePartial)
516
+ ctx.ui.notify(
517
+ "Continuous sync retained unresolved groups. Review /sync conflicts; independent partial progress was preserved.",
518
+ "warning"
519
+ );
520
+ }
521
+ }
522
+ function guardedLock(command, run) {
523
+ return withStateDirectoryAccess(() => withLock(command, run));
524
+ }
525
+ function wait(clock, ms, signal, expose, kind = "wait") {
526
+ signal.throwIfAborted();
527
+ return new Promise((resolve) => {
528
+ const done = () => {
529
+ cancel();
530
+ signal.removeEventListener("abort", done);
531
+ expose?.(() => {
532
+ });
533
+ resolve();
534
+ };
535
+ const cancel = clock.schedule(ms, done, kind);
536
+ signal.addEventListener("abort", done, { once: true });
537
+ expose?.(done);
538
+ if (signal.aborted) done();
539
+ });
540
+ }
541
+ export {
542
+ continuousEnabled,
543
+ createContinuousSync
544
+ };
545
+ //# sourceMappingURL=continuous-sync-AWAAOXK2.ts.map