pushwork 1.0.0 → 1.0.3

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 (58) hide show
  1. package/README.md +23 -21
  2. package/dist/cli/commands.d.ts +6 -0
  3. package/dist/cli/commands.d.ts.map +1 -1
  4. package/dist/cli/commands.js +114 -4
  5. package/dist/cli/commands.js.map +1 -1
  6. package/dist/cli.js +27 -0
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/change-detection.d.ts.map +1 -1
  9. package/dist/core/change-detection.js +27 -9
  10. package/dist/core/change-detection.js.map +1 -1
  11. package/dist/core/move-detection.d.ts.map +1 -1
  12. package/dist/core/move-detection.js +8 -2
  13. package/dist/core/move-detection.js.map +1 -1
  14. package/dist/core/sync-engine.d.ts +4 -0
  15. package/dist/core/sync-engine.d.ts.map +1 -1
  16. package/dist/core/sync-engine.js +263 -7
  17. package/dist/core/sync-engine.js.map +1 -1
  18. package/dist/types/documents.d.ts +2 -0
  19. package/dist/types/documents.d.ts.map +1 -1
  20. package/dist/types/documents.js.map +1 -1
  21. package/dist/utils/fs.d.ts.map +1 -1
  22. package/dist/utils/fs.js +7 -1
  23. package/dist/utils/fs.js.map +1 -1
  24. package/dist/utils/network-sync.d.ts.map +1 -1
  25. package/dist/utils/network-sync.js +16 -3
  26. package/dist/utils/network-sync.js.map +1 -1
  27. package/package.json +30 -30
  28. package/src/cli/commands.ts +162 -8
  29. package/src/cli.ts +40 -0
  30. package/src/core/change-detection.ts +25 -12
  31. package/src/core/move-detection.ts +8 -2
  32. package/src/core/sync-engine.ts +270 -7
  33. package/src/types/documents.ts +2 -0
  34. package/src/utils/fs.ts +7 -3
  35. package/src/utils/network-sync.ts +19 -3
  36. package/test/integration/clone-test.sh +0 -0
  37. package/test/integration/conflict-resolution-test.sh +0 -0
  38. package/test/integration/debug-both-nested.sh +74 -0
  39. package/test/integration/debug-concurrent-nested.sh +87 -0
  40. package/test/integration/debug-nested.sh +73 -0
  41. package/test/integration/deletion-behavior-test.sh +0 -0
  42. package/test/integration/deletion-sync-test-simple.sh +0 -0
  43. package/test/integration/deletion-sync-test.sh +0 -0
  44. package/test/integration/full-integration-test.sh +0 -0
  45. package/test/integration/fuzzer.test.ts +865 -0
  46. package/test/integration/manual-sync-test.sh +84 -0
  47. package/test/run-tests.sh +0 -0
  48. package/test/unit/sync-convergence.test.ts +493 -0
  49. package/tools/browser-sync/README.md +0 -116
  50. package/tools/browser-sync/package.json +0 -44
  51. package/tools/browser-sync/patchwork.json +0 -1
  52. package/tools/browser-sync/pnpm-lock.yaml +0 -4202
  53. package/tools/browser-sync/src/components/BrowserSyncTool.tsx +0 -599
  54. package/tools/browser-sync/src/index.ts +0 -20
  55. package/tools/browser-sync/src/polyfills.ts +0 -31
  56. package/tools/browser-sync/src/styles.css +0 -290
  57. package/tools/browser-sync/src/types.ts +0 -27
  58. package/tools/browser-sync/vite.config.ts +0 -25
@@ -1 +1 @@
1
- {"version":3,"file":"move-detection.d.ts","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AAEhE;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAO;IAE/C;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,cAAc,EAAE,EACzB,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,gBAAgB,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC;IA8E1E;;OAEG;YACW,qBAAqB;IAWnC;;OAEG;IACH,sBAAsB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QAC9C,SAAS,EAAE,aAAa,EAAE,CAAC;QAC3B,WAAW,EAAE,aAAa,EAAE,CAAC;QAC7B,kBAAkB,EAAE,aAAa,EAAE,CAAC;KACrC;IAQD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACrC,UAAU,EAAE,aAAa,EAAE,CAAC;QAC5B,SAAS,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IA4CD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE;IAwBxD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI7C;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI9C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAKvC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACtC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;KAC3B;CASF"}
1
+ {"version":3,"file":"move-detection.d.ts","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,aAAa,EAGd,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,cAAc,EAAc,MAAM,oBAAoB,CAAC;AAEhE;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAO;IAE/C;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,cAAc,EAAE,EACzB,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAAC,gBAAgB,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC;IAoF1E;;OAEG;YACW,qBAAqB;IAWnC;;OAEG;IACH,sBAAsB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QAC9C,SAAS,EAAE,aAAa,EAAE,CAAC;QAC3B,WAAW,EAAE,aAAa,EAAE,CAAC;QAC7B,kBAAkB,EAAE,aAAa,EAAE,CAAC;KACrC;IAQD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACrC,UAAU,EAAE,aAAa,EAAE,CAAC;QAC5B,SAAS,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,aAAa,EAAE,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IA4CD;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE;IAwBxD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI7C;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO;IAI9C;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM;IAKvC;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG;QACtC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;KAC3B;CASF"}
@@ -25,13 +25,17 @@ class MoveDetector {
25
25
  // Find potential moves by comparing content
26
26
  for (const deletedFile of deletedFiles) {
27
27
  const deletedContent = await this.getDeletedFileContent(deletedFile, snapshot);
28
- if (!deletedContent)
28
+ // CRITICAL: Check for null explicitly, not falsy values
29
+ // Empty strings "" are valid file content!
30
+ if (deletedContent === null)
29
31
  continue;
30
32
  let bestMatch = null;
31
33
  for (const createdFile of createdFiles) {
32
34
  if (usedCreations.has(createdFile.path))
33
35
  continue;
34
- if (!createdFile.localContent)
36
+ // CRITICAL: Check for null explicitly, not falsy values
37
+ // Empty strings "" are valid file content!
38
+ if (createdFile.localContent === null)
35
39
  continue;
36
40
  const similarity = await utils_1.ContentSimilarity.calculateSimilarity(deletedContent, createdFile.localContent);
37
41
  if (similarity >= MoveDetector.PROMPT_THRESHOLD) {
@@ -48,6 +52,8 @@ class MoveDetector {
48
52
  toPath: bestMatch.file.path,
49
53
  similarity: bestMatch.similarity,
50
54
  confidence,
55
+ // Capture new content (may include modifications)
56
+ newContent: bestMatch.file.localContent || undefined,
51
57
  });
52
58
  // Only consume the deletion/creation pair when we would auto-apply the move.
53
59
  // If we only want to prompt, leave the original changes in place so
@@ -1 +1 @@
1
- {"version":3,"file":"move-detection.js","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"move-detection.js","sourceRoot":"","sources":["../../src/core/move-detection.ts"],"names":[],"mappings":"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"}
@@ -106,5 +106,9 @@ export declare class SyncEngine {
106
106
  * Generate human-readable summary of changes
107
107
  */
108
108
  private generateChangeSummary;
109
+ /**
110
+ * Update the lastSyncAt timestamp on the root directory document
111
+ */
112
+ private touchRootDirectory;
109
113
  }
110
114
  //# sourceMappingURL=sync-engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/core/sync-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,IAAI,EAIL,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,YAAY,EACZ,UAAU,EAQV,aAAa,EACd,MAAM,UAAU,CAAC;AAgBlB,OAAO,EAAkB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpE;;GAEG;AACH,qBAAa,UAAU;IASnB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;IATlB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,kBAAkB,CAAiB;IAC3C,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,mBAAmB,CAAC,CAAS;gBAG3B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EACxB,eAAe,GAAE,MAAM,EAAO,EAC9B,kBAAkB,GAAE,OAAc,EAClC,mBAAmB,CAAC,EAAE,MAAM;IAS9B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACG,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3D;;OAEG;IACG,WAAW,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAsFtD;;OAEG;IACG,IAAI,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAiH/C;;OAEG;YACW,gBAAgB;IA+D9B;;OAEG;YACW,iBAAiB;IAwC/B;;OAEG;YACW,wBAAwB;IA2DtC;;OAEG;YACW,wBAAwB;IAmEtC;;OAEG;YACW,iBAAiB;IAmE/B;;OAEG;YACW,gBAAgB;IAoC9B;;OAEG;YACW,gBAAgB;IA+C9B;;OAEG;YACW,gBAAgB;IA4B9B;;OAEG;YACW,kBAAkB;IA8DhC;;;OAGG;YACW,uBAAuB;IA8HrC;;OAEG;YACW,uBAAuB;IAwErC;;OAEG;YACW,4BAA4B;IAkD1C;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAS/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;QAC9B,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;KACvB,CAAC;IAsBF;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAC9B,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,KAAK,EAAE,aAAa,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAsBF;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAgD9B"}
1
+ {"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/core/sync-engine.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,IAAI,EAIL,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,YAAY,EACZ,UAAU,EAQV,aAAa,EACd,MAAM,UAAU,CAAC;AAgBlB,OAAO,EAAkB,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpE;;GAEG;AACH,qBAAa,UAAU;IASnB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;IATlB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,kBAAkB,CAAiB;IAC3C,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,mBAAmB,CAAC,CAAS;gBAG3B,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EACxB,eAAe,GAAE,MAAM,EAAO,EAC9B,kBAAkB,GAAE,OAAc,EAClC,mBAAmB,CAAC,EAAE,MAAM;IAS9B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACG,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3D;;OAEG;IACG,WAAW,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IA6FtD;;OAEG;IACG,IAAI,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IA8N/C;;OAEG;YACW,gBAAgB;IA+D9B;;OAEG;YACW,iBAAiB;IAwC/B;;OAEG;YACW,wBAAwB;IAyFtC;;OAEG;YACW,wBAAwB;IAqEtC;;OAEG;YACW,iBAAiB;IAyF/B;;OAEG;YACW,gBAAgB;IAsC9B;;OAEG;YACW,gBAAgB;IA+D9B;;OAEG;YACW,gBAAgB;IA4B9B;;OAEG;YACW,kBAAkB;IAoEhC;;;OAGG;YACW,uBAAuB;IAqIrC;;OAEG;YACW,uBAAuB;IAkFrC;;OAEG;YACW,4BAA4B;IAkD1C;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAS/B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;QAC9B,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;KACvB,CAAC;IAsBF;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAC9B,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,KAAK,EAAE,aAAa,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAsBF;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiD7B;;OAEG;YACW,kBAAkB;CA8CjC"}
@@ -1,7 +1,42 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.SyncEngine = void 0;
37
+ const myers = require("myers-diff");
4
38
  const automerge_repo_1 = require("@automerge/automerge-repo");
39
+ const A = __importStar(require("@automerge/automerge"));
5
40
  const types_1 = require("../types");
6
41
  const utils_1 = require("../utils");
7
42
  const content_1 = require("../utils/content");
@@ -91,6 +126,11 @@ class SyncEngine {
91
126
  result.directoriesChanged += commitResult.directoriesChanged;
92
127
  result.errors.push(...commitResult.errors);
93
128
  result.warnings.push(...commitResult.warnings);
129
+ // Touch root directory if any changes were made
130
+ const hasChanges = result.filesChanged > 0 || result.directoriesChanged > 0;
131
+ if (hasChanges) {
132
+ await this.touchRootDirectory(snapshot, dryRun);
133
+ }
94
134
  // Save updated snapshot if not dry run
95
135
  if (!dryRun) {
96
136
  await this.snapshotManager.save(snapshot);
@@ -115,6 +155,8 @@ class SyncEngine {
115
155
  * Run full bidirectional sync
116
156
  */
117
157
  async sync(dryRun = false) {
158
+ const syncStartTime = Date.now();
159
+ const timings = {};
118
160
  const result = {
119
161
  success: false,
120
162
  filesChanged: 0,
@@ -126,29 +168,40 @@ class SyncEngine {
126
168
  this.handlesToWaitOn = [];
127
169
  try {
128
170
  // Load current snapshot
171
+ const t0 = Date.now();
129
172
  let snapshot = await this.snapshotManager.load();
173
+ timings["load_snapshot"] = Date.now() - t0;
130
174
  if (!snapshot) {
131
175
  snapshot = this.snapshotManager.createEmpty();
132
176
  }
133
177
  // Backup snapshot before starting
178
+ const t1 = Date.now();
134
179
  if (!dryRun) {
135
180
  await this.snapshotManager.backup();
136
181
  }
182
+ timings["backup_snapshot"] = Date.now() - t1;
137
183
  // Detect all changes
184
+ const t2 = Date.now();
138
185
  const changes = await this.changeDetector.detectChanges(snapshot);
186
+ timings["detect_changes"] = Date.now() - t2;
139
187
  // Detect moves
188
+ const t3 = Date.now();
140
189
  const { moves, remainingChanges } = await this.moveDetector.detectMoves(changes, snapshot, this.rootPath);
190
+ timings["detect_moves"] = Date.now() - t3;
141
191
  if (changes.length > 0) {
142
192
  console.log(`🔄 Syncing ${changes.length} changes...`);
143
193
  }
144
194
  // Phase 1: Push local changes to remote
195
+ const t4 = Date.now();
145
196
  const phase1Result = await this.pushLocalChanges(remainingChanges, moves, snapshot, dryRun);
197
+ timings["phase1_push"] = Date.now() - t4;
146
198
  result.filesChanged += phase1Result.filesChanged;
147
199
  result.directoriesChanged += phase1Result.directoriesChanged;
148
200
  result.errors.push(...phase1Result.errors);
149
201
  result.warnings.push(...phase1Result.warnings);
150
202
  // Always wait for network sync when enabled (not just when local changes exist)
151
203
  // This is critical for clone scenarios where we need to pull remote changes
204
+ const t5 = Date.now();
152
205
  if (!dryRun && this.networkSyncEnabled) {
153
206
  try {
154
207
  // If we have a root directory URL, wait for it to sync
@@ -157,7 +210,22 @@ class SyncEngine {
157
210
  this.handlesToWaitOn.push(rootHandle);
158
211
  }
159
212
  if (this.handlesToWaitOn.length > 0) {
213
+ const tWaitStart = Date.now();
160
214
  await (0, network_sync_1.waitForSync)(this.handlesToWaitOn, (0, network_sync_1.getSyncServerStorageId)(this.syncServerStorageId));
215
+ timings["network_sync"] = Date.now() - tWaitStart;
216
+ // CRITICAL: Wait a bit after our changes reach the server to allow
217
+ // time for WebSocket to deliver OTHER peers' changes to us.
218
+ // waitForSync only ensures OUR changes reached the server, not that
219
+ // we've RECEIVED changes from other peers. This delay allows the
220
+ // WebSocket protocol to propagate peer changes before we re-detect.
221
+ // Without this, concurrent operations on different peers can miss
222
+ // each other due to timing races.
223
+ //
224
+ // Optimization: Only wait if we pushed changes (shorter delay if no changes)
225
+ const tDelayStart = Date.now();
226
+ const delayMs = phase1Result.filesChanged > 0 ? 200 : 100;
227
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
228
+ timings["post_sync_delay"] = Date.now() - tDelayStart;
161
229
  }
162
230
  }
163
231
  catch (error) {
@@ -165,21 +233,91 @@ class SyncEngine {
165
233
  result.warnings.push(`Network sync failed: ${error}`);
166
234
  }
167
235
  }
236
+ timings["total_network"] = Date.now() - t5;
168
237
  // Re-detect remote changes after network sync to ensure fresh state
169
238
  // This fixes race conditions where we detect changes before server propagation
239
+ // NOTE: We DON'T update snapshot heads yet - that would prevent detecting remote changes!
240
+ const t6 = Date.now();
170
241
  const freshChanges = await this.changeDetector.detectChanges(snapshot);
171
242
  const freshRemoteChanges = freshChanges.filter((c) => c.changeType === types_1.ChangeType.REMOTE_ONLY ||
172
243
  c.changeType === types_1.ChangeType.BOTH_CHANGED);
244
+ timings["redetect_changes"] = Date.now() - t6;
173
245
  // Phase 2: Pull remote changes to local using fresh detection
246
+ const t7 = Date.now();
174
247
  const phase2Result = await this.pullRemoteChanges(freshRemoteChanges, snapshot, dryRun);
248
+ timings["phase2_pull"] = Date.now() - t7;
175
249
  result.filesChanged += phase2Result.filesChanged;
176
250
  result.directoriesChanged += phase2Result.directoriesChanged;
177
251
  result.errors.push(...phase2Result.errors);
178
252
  result.warnings.push(...phase2Result.warnings);
253
+ // CRITICAL FIX: Update snapshot heads AFTER pulling remote changes
254
+ // This ensures that change detection can find remote changes, and we only
255
+ // update the snapshot after the filesystem is in sync with the documents
256
+ const t8 = Date.now();
257
+ if (!dryRun) {
258
+ // Update file document heads
259
+ for (const [filePath, snapshotEntry] of snapshot.files.entries()) {
260
+ try {
261
+ const handle = await this.repo.find(snapshotEntry.url);
262
+ const currentHeads = handle.heads();
263
+ if (!A.equals(currentHeads, snapshotEntry.head)) {
264
+ // Update snapshot with current heads after pulling changes
265
+ snapshot.files.set(filePath, {
266
+ ...snapshotEntry,
267
+ head: currentHeads,
268
+ });
269
+ }
270
+ }
271
+ catch (error) {
272
+ // Handle might not exist if file was deleted, skip
273
+ console.warn(`Could not update heads for ${filePath}: ${error}`);
274
+ }
275
+ }
276
+ // Update directory document heads
277
+ for (const [dirPath, snapshotEntry] of snapshot.directories.entries()) {
278
+ try {
279
+ const handle = await this.repo.find(snapshotEntry.url);
280
+ const currentHeads = handle.heads();
281
+ if (!A.equals(currentHeads, snapshotEntry.head)) {
282
+ // Update snapshot with current heads after pulling changes
283
+ snapshot.directories.set(dirPath, {
284
+ ...snapshotEntry,
285
+ head: currentHeads,
286
+ });
287
+ }
288
+ }
289
+ catch (error) {
290
+ // Handle might not exist if directory was deleted, skip
291
+ console.warn(`Could not update heads for directory ${dirPath}: ${error}`);
292
+ }
293
+ }
294
+ }
295
+ timings["update_snapshot_heads"] = Date.now() - t8;
296
+ // Touch root directory if any changes were made during sync
297
+ const t9 = Date.now();
298
+ const hasChanges = result.filesChanged > 0 || result.directoriesChanged > 0;
299
+ if (hasChanges) {
300
+ await this.touchRootDirectory(snapshot, dryRun);
301
+ }
302
+ timings["touch_root"] = Date.now() - t9;
179
303
  // Save updated snapshot if not dry run
304
+ const t10 = Date.now();
180
305
  if (!dryRun) {
181
306
  await this.snapshotManager.save(snapshot);
182
307
  }
308
+ timings["save_snapshot"] = Date.now() - t10;
309
+ // Output timing breakdown if enabled via environment variable
310
+ if (process.env.PUSHWORK_TIMING === "1") {
311
+ const totalTime = Date.now() - syncStartTime;
312
+ console.error("\n⏱️ Sync Timing Breakdown:");
313
+ for (const [key, ms] of Object.entries(timings)) {
314
+ const pct = ((ms / totalTime) * 100).toFixed(1);
315
+ console.error(` ${key.padEnd(25)} ${ms.toString().padStart(5)}ms (${pct}%)`);
316
+ }
317
+ console.error(` ${"TOTAL".padEnd(25)} ${totalTime
318
+ .toString()
319
+ .padStart(5)}ms (100.0%)\n`);
320
+ }
183
321
  result.success = result.errors.length === 0;
184
322
  return result;
185
323
  }
@@ -282,7 +420,9 @@ class SyncEngine {
282
420
  */
283
421
  async applyLocalChangeToRemote(change, snapshot, dryRun) {
284
422
  const snapshotEntry = snapshot.files.get(change.path);
285
- if (!change.localContent) {
423
+ // CRITICAL: Check for null explicitly, not falsy values
424
+ // Empty strings "" and empty Uint8Array are valid file content!
425
+ if (change.localContent === null) {
286
426
  // File was deleted locally
287
427
  if (snapshotEntry) {
288
428
  console.log(`🗑️ ${change.path}`);
@@ -301,6 +441,8 @@ class SyncEngine {
301
441
  const handle = await this.createRemoteFile(change, dryRun);
302
442
  if (!dryRun && handle) {
303
443
  await this.addFileToDirectory(snapshot, change.path, handle.url, dryRun);
444
+ // CRITICAL FIX: Update snapshot with heads AFTER adding to directory
445
+ // The addFileToDirectory call above may have changed the document heads
304
446
  this.snapshotManager.updateFileEntry(snapshot, change.path, {
305
447
  path: (0, utils_1.normalizePath)(this.rootPath + "/" + change.path),
306
448
  url: handle.url,
@@ -313,6 +455,28 @@ class SyncEngine {
313
455
  else {
314
456
  // Update existing file
315
457
  console.log(`📝 ${change.path}`);
458
+ // log the change in detail for debugging
459
+ // split out remotea nd local content so we don't overwhelm the logs
460
+ const { remoteContent, localContent, ...rest } = change;
461
+ console.log(`🔍 Change in detail:`, rest);
462
+ // compare the local and remote content and make a diff so we can
463
+ // see what happened between the two
464
+ const { diff, changed } = require("myers-diff");
465
+ const lhs = change.remoteContent ? change.remoteContent.toString() : "";
466
+ const rhs = change.localContent ? change.localContent.toString() : "";
467
+ const changes = diff(lhs, rhs, { compare: "chars" });
468
+ for (const change of changes) {
469
+ if (changed(change.lhs)) {
470
+ // deleted
471
+ const { pos, text, del, length } = change.lhs;
472
+ console.log(`🔍 Deleted:`, { pos, text, del, length });
473
+ }
474
+ if (changed(change.rhs)) {
475
+ // added
476
+ const { pos, text, add, length } = change.rhs;
477
+ console.log(`🔍 Added:`, { pos, text, add, length });
478
+ }
479
+ }
316
480
  await this.updateRemoteFile(snapshotEntry.url, change.localContent, dryRun, snapshot, change.path);
317
481
  }
318
482
  }
@@ -322,9 +486,11 @@ class SyncEngine {
322
486
  async applyRemoteChangeToLocal(change, snapshot, dryRun) {
323
487
  const localPath = (0, utils_1.normalizePath)(this.rootPath + "/" + change.path);
324
488
  if (!change.remoteHead) {
325
- throw new Error(`No remote head found for remote change to${change.path}`);
489
+ throw new Error(`No remote head found for remote change to ${change.path}`);
326
490
  }
327
- if (!change.remoteContent) {
491
+ // CRITICAL: Check for null explicitly, not falsy values
492
+ // Empty strings "" and empty Uint8Array are valid file content!
493
+ if (change.remoteContent === null) {
328
494
  // File was deleted remotely
329
495
  console.log(`🗑️ ${change.path}`);
330
496
  if (!dryRun) {
@@ -393,18 +559,39 @@ class SyncEngine {
393
559
  // 2) Ensure destination directory document exists and add file entry there
394
560
  const destDirUrl = await this.ensureDirectoryDocument(snapshot, toDirPath, dryRun);
395
561
  await this.addFileToDirectory(snapshot, move.toPath, fromEntry.url, dryRun);
396
- // 3) Update the FileDocument name to match new basename
562
+ // 3) Update the FileDocument name and content to match new location/state
397
563
  try {
398
564
  const handle = await this.repo.find(fromEntry.url);
399
565
  const heads = fromEntry.head;
566
+ // Update both name and content (if content changed during move)
400
567
  if (heads && heads.length > 0) {
401
568
  handle.changeAt(heads, (doc) => {
402
569
  doc.name = toFileName;
570
+ // If new content is provided, update it (handles move + modification case)
571
+ if (move.newContent !== undefined) {
572
+ const isText = this.isTextContent(move.newContent);
573
+ if (isText && typeof move.newContent === "string") {
574
+ (0, automerge_repo_1.updateText)(doc, ["content"], move.newContent);
575
+ }
576
+ else {
577
+ doc.content = move.newContent;
578
+ }
579
+ }
403
580
  });
404
581
  }
405
582
  else {
406
583
  handle.change((doc) => {
407
584
  doc.name = toFileName;
585
+ // If new content is provided, update it (handles move + modification case)
586
+ if (move.newContent !== undefined) {
587
+ const isText = this.isTextContent(move.newContent);
588
+ if (isText && typeof move.newContent === "string") {
589
+ (0, automerge_repo_1.updateText)(doc, ["content"], move.newContent);
590
+ }
591
+ else {
592
+ doc.content = move.newContent;
593
+ }
594
+ }
408
595
  });
409
596
  }
410
597
  // Track file handle for network sync
@@ -426,7 +613,9 @@ class SyncEngine {
426
613
  * Create new remote file document
427
614
  */
428
615
  async createRemoteFile(change, dryRun) {
429
- if (dryRun || !change.localContent)
616
+ // CRITICAL: Check for null explicitly, not falsy values
617
+ // Empty strings "" and empty Uint8Array are valid file content!
618
+ if (dryRun || change.localContent === null)
430
619
  return null;
431
620
  const isText = this.isTextContent(change.localContent);
432
621
  // Create initial document structure
@@ -463,10 +652,22 @@ class SyncEngine {
463
652
  const doc = await handle.doc();
464
653
  const currentContent = doc?.content;
465
654
  const contentChanged = !(0, content_1.isContentEqual)(content, currentContent);
655
+ // CRITICAL FIX: Always update snapshot heads, even when content is identical
656
+ // This prevents stale head issues that cause false change detection
657
+ const snapshotEntry = snapshot.files.get(filePath);
658
+ if (snapshotEntry) {
659
+ // Update snapshot with current document heads
660
+ snapshot.files.set(filePath, {
661
+ ...snapshotEntry,
662
+ head: handle.heads(),
663
+ });
664
+ }
466
665
  if (!contentChanged) {
666
+ // Content is identical, but we've updated the snapshot heads above
667
+ // This prevents fresh change detection from seeing stale heads
668
+ console.log(`🔍 Content is identical, but we've updated the snapshot heads above`);
467
669
  return;
468
670
  }
469
- const snapshotEntry = snapshot.files.get(filePath);
470
671
  const heads = snapshotEntry?.head;
471
672
  if (!heads) {
472
673
  throw new Error(`No heads found for ${url}`);
@@ -480,7 +681,8 @@ class SyncEngine {
480
681
  doc.content = content;
481
682
  }
482
683
  });
483
- if (!dryRun) {
684
+ // Update snapshot with new heads after content change
685
+ if (!dryRun && snapshotEntry) {
484
686
  snapshot.files.set(filePath, {
485
687
  ...snapshotEntry,
486
688
  head: handle.heads(),
@@ -559,6 +761,11 @@ class SyncEngine {
559
761
  }
560
762
  if (didChange) {
561
763
  this.handlesToWaitOn.push(dirHandle);
764
+ // CRITICAL FIX: Update snapshot with new directory heads immediately
765
+ // This prevents stale head issues that cause convergence problems
766
+ if (snapshotEntry) {
767
+ snapshotEntry.head = dirHandle.heads();
768
+ }
562
769
  }
563
770
  }
564
771
  /**
@@ -640,6 +847,12 @@ class SyncEngine {
640
847
  this.handlesToWaitOn.push(dirHandle);
641
848
  if (didChange) {
642
849
  this.handlesToWaitOn.push(parentHandle);
850
+ // CRITICAL FIX: Update parent directory heads in snapshot immediately
851
+ // This prevents stale head issues when parent directory is modified
852
+ const parentSnapshotEntry = snapshot.directories.get(parentPath);
853
+ if (parentSnapshotEntry) {
854
+ parentSnapshotEntry.head = parentHandle.heads();
855
+ }
643
856
  }
644
857
  // Update snapshot with new directory
645
858
  this.snapshotManager.updateDirectoryEntry(snapshot, directoryPath, {
@@ -679,11 +892,13 @@ class SyncEngine {
679
892
  this.handlesToWaitOn.push(dirHandle);
680
893
  const snapshotEntry = snapshot.directories.get(directoryPath);
681
894
  const heads = snapshotEntry?.head;
895
+ let didChange = false;
682
896
  if (heads) {
683
897
  dirHandle.changeAt(heads, (doc) => {
684
898
  const indexToRemove = doc.docs.findIndex((entry) => entry.name === fileName && entry.type === "file");
685
899
  if (indexToRemove !== -1) {
686
900
  doc.docs.splice(indexToRemove, 1);
901
+ didChange = true;
687
902
  console.log(`🗑️ Removed ${fileName} from directory ${directoryPath || "root"}`);
688
903
  }
689
904
  });
@@ -693,10 +908,16 @@ class SyncEngine {
693
908
  const indexToRemove = doc.docs.findIndex((entry) => entry.name === fileName && entry.type === "file");
694
909
  if (indexToRemove !== -1) {
695
910
  doc.docs.splice(indexToRemove, 1);
911
+ didChange = true;
696
912
  console.log(`🗑️ Removed ${fileName} from directory ${directoryPath || "root"}`);
697
913
  }
698
914
  });
699
915
  }
916
+ // CRITICAL FIX: Update snapshot with new directory heads immediately
917
+ // This prevents stale head issues that cause convergence problems
918
+ if (didChange && snapshotEntry) {
919
+ snapshotEntry.head = dirHandle.heads();
920
+ }
700
921
  }
701
922
  catch (error) {
702
923
  console.warn(`Failed to remove ${fileName} from directory ${directoryPath || "root"}: ${error}`);
@@ -812,6 +1033,41 @@ class SyncEngine {
812
1033
  }
813
1034
  return parts.join(", ");
814
1035
  }
1036
+ /**
1037
+ * Update the lastSyncAt timestamp on the root directory document
1038
+ */
1039
+ async touchRootDirectory(snapshot, dryRun) {
1040
+ if (dryRun || !snapshot.rootDirectoryUrl) {
1041
+ return;
1042
+ }
1043
+ try {
1044
+ const rootHandle = await this.repo.find(snapshot.rootDirectoryUrl);
1045
+ const snapshotEntry = snapshot.directories.get("");
1046
+ const heads = snapshotEntry?.head;
1047
+ const timestamp = Date.now();
1048
+ if (heads) {
1049
+ rootHandle.changeAt(heads, (doc) => {
1050
+ doc.lastSyncAt = timestamp;
1051
+ });
1052
+ }
1053
+ else {
1054
+ rootHandle.change((doc) => {
1055
+ doc.lastSyncAt = timestamp;
1056
+ });
1057
+ }
1058
+ // Track root directory for network sync
1059
+ this.handlesToWaitOn.push(rootHandle);
1060
+ // CRITICAL FIX: Update root directory heads in snapshot immediately
1061
+ // This prevents stale head issues when root directory is modified
1062
+ if (snapshotEntry) {
1063
+ snapshotEntry.head = rootHandle.heads();
1064
+ }
1065
+ console.log(`🕒 Updated root directory lastSyncAt to ${new Date(timestamp).toISOString()}`);
1066
+ }
1067
+ catch (error) {
1068
+ console.warn(`Failed to update root directory lastSyncAt: ${error}`);
1069
+ }
1070
+ }
815
1071
  }
816
1072
  exports.SyncEngine = SyncEngine;
817
1073
  //# sourceMappingURL=sync-engine.js.map