amalgm 0.1.245 → 0.1.246

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 (157) hide show
  1. package/README.md +12 -0
  2. package/lib/cli.js +146 -8
  3. package/lib/layout.js +89 -4
  4. package/lib/shared-realtime-tunnel.js +384 -43
  5. package/lib/supervisor.js +0 -3
  6. package/package.json +2 -2
  7. package/runtime/scripts/amalgm-mcp/adapters/contract.js +197 -0
  8. package/runtime/scripts/amalgm-mcp/adapters/filesystem.js +135 -0
  9. package/runtime/scripts/amalgm-mcp/adapters/git.js +84 -0
  10. package/runtime/scripts/amalgm-mcp/adapters/index.js +43 -0
  11. package/runtime/scripts/amalgm-mcp/adapters/reference.js +31 -0
  12. package/runtime/scripts/amalgm-mcp/adapters/truth.js +19 -0
  13. package/runtime/scripts/amalgm-mcp/browser/cookie-jar.js +20 -68
  14. package/runtime/scripts/amalgm-mcp/index.js +4 -0
  15. package/runtime/scripts/amalgm-mcp/lib/layout.js +89 -4
  16. package/runtime/scripts/amalgm-mcp/observer/README.md +259 -0
  17. package/runtime/scripts/amalgm-mcp/observer/apply.js +150 -0
  18. package/runtime/scripts/amalgm-mcp/observer/continuity.js +111 -0
  19. package/runtime/scripts/amalgm-mcp/observer/edges.js +111 -0
  20. package/runtime/scripts/amalgm-mcp/observer/index.js +1146 -0
  21. package/runtime/scripts/amalgm-mcp/observer/scan.js +387 -0
  22. package/runtime/scripts/amalgm-mcp/observer/store.js +262 -0
  23. package/runtime/scripts/amalgm-mcp/observer/verify.js +200 -0
  24. package/runtime/scripts/amalgm-mcp/observer/watch.js +62 -0
  25. package/runtime/scripts/amalgm-mcp/project-context/store.js +19 -87
  26. package/runtime/scripts/amalgm-mcp/registration/classify.js +33 -0
  27. package/runtime/scripts/amalgm-mcp/registration/entity-cloud.js +456 -0
  28. package/runtime/scripts/amalgm-mcp/registration/entity-content.js +345 -0
  29. package/runtime/scripts/amalgm-mcp/registration/index.js +752 -0
  30. package/runtime/scripts/amalgm-mcp/registration/refusal.js +42 -0
  31. package/runtime/scripts/amalgm-mcp/registration/repo-followers.js +127 -0
  32. package/runtime/scripts/amalgm-mcp/registration/repo-states.js +109 -0
  33. package/runtime/scripts/amalgm-mcp/registration/service.js +310 -0
  34. package/runtime/scripts/amalgm-mcp/registration/tree.js +178 -0
  35. package/runtime/scripts/amalgm-mcp/registry/evidence.js +826 -0
  36. package/runtime/scripts/amalgm-mcp/registry/index.js +666 -0
  37. package/runtime/scripts/amalgm-mcp/registry/store.js +290 -0
  38. package/runtime/scripts/amalgm-mcp/repocard/README.md +103 -0
  39. package/runtime/scripts/amalgm-mcp/repocard/apply.js +111 -0
  40. package/runtime/scripts/amalgm-mcp/repocard/capture-worker.js +94 -0
  41. package/runtime/scripts/amalgm-mcp/repocard/capture.js +149 -0
  42. package/runtime/scripts/amalgm-mcp/repocard/follow.js +310 -0
  43. package/runtime/scripts/amalgm-mcp/repocard/git.js +48 -0
  44. package/runtime/scripts/amalgm-mcp/repocard/index.js +48 -0
  45. package/runtime/scripts/amalgm-mcp/server/local-service-router.js +2 -0
  46. package/runtime/scripts/amalgm-mcp/server/routes/entities.js +287 -0
  47. package/runtime/scripts/amalgm-mcp/server/routes/state.js +0 -13
  48. package/runtime/scripts/amalgm-mcp/state/attachments.js +11 -45
  49. package/runtime/scripts/amalgm-mcp/state/db.js +46 -215
  50. package/runtime/scripts/amalgm-mcp/state/docs.js +301 -1101
  51. package/runtime/scripts/amalgm-mcp/state/mutation-contracts.js +0 -99
  52. package/runtime/scripts/amalgm-mcp/state/mutations.js +130 -507
  53. package/runtime/scripts/amalgm-mcp/state/promotions.js +1 -21
  54. package/runtime/scripts/amalgm-mcp/state/replicas.js +13 -134
  55. package/runtime/scripts/amalgm-mcp/state/shared-rest.js +3 -46
  56. package/runtime/scripts/amalgm-mcp/tests/adapters.test.js +379 -0
  57. package/runtime/scripts/amalgm-mcp/tests/browser-cookie-cloud.test.js +0 -193
  58. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.life.test.js +449 -0
  59. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.rig.js +107 -0
  60. package/runtime/scripts/amalgm-mcp/tests/doorbell.matrix.watch.test.js +213 -0
  61. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/adapter.js +72 -0
  62. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/assert.js +497 -0
  63. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/bind.js +91 -0
  64. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/graph.js +1031 -0
  65. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/ledger.js +234 -0
  66. package/runtime/scripts/amalgm-mcp/tests/entity-oracle/referee.js +118 -0
  67. package/runtime/scripts/amalgm-mcp/tests/entity.oracle.test.js +1365 -0
  68. package/runtime/scripts/amalgm-mcp/tests/entity.registry.test.js +967 -0
  69. package/runtime/scripts/amalgm-mcp/tests/entity.rig.js +239 -0
  70. package/runtime/scripts/amalgm-mcp/tests/entity.storm.test.js +486 -0
  71. package/runtime/scripts/amalgm-mcp/tests/fake-watch.js +35 -0
  72. package/runtime/scripts/amalgm-mcp/tests/observer.links.test.js +289 -0
  73. package/runtime/scripts/amalgm-mcp/tests/observer.rig.js +103 -0
  74. package/runtime/scripts/amalgm-mcp/tests/observer.roots.test.js +505 -0
  75. package/runtime/scripts/amalgm-mcp/tests/observer.storm.test.js +389 -0
  76. package/runtime/scripts/amalgm-mcp/tests/observer.territory.test.js +845 -0
  77. package/runtime/scripts/amalgm-mcp/tests/observer.test.js +657 -0
  78. package/runtime/scripts/amalgm-mcp/tests/project-context.test.js +17 -32
  79. package/runtime/scripts/amalgm-mcp/tests/registration.service.test.js +256 -0
  80. package/runtime/scripts/amalgm-mcp/tests/registration.test.js +931 -0
  81. package/runtime/scripts/amalgm-mcp/tests/repocard.storm.test.js +284 -0
  82. package/runtime/scripts/amalgm-mcp/tests/repocard.test.js +371 -0
  83. package/runtime/scripts/amalgm-mcp/tests/repofollow.storm.test.js +435 -0
  84. package/runtime/scripts/amalgm-mcp/tests/repofollow.test.js +675 -0
  85. package/runtime/scripts/amalgm-mcp/tests/shared-tunnel-rehydration.test.js +0 -84
  86. package/runtime/scripts/amalgm-mcp/tests/state-docs.test.js +13 -376
  87. package/runtime/scripts/amalgm-mcp/tests/state-mutations.test.js +0 -309
  88. package/runtime/scripts/amalgm-mcp/tests/state-shared-replica.test.js +30 -758
  89. package/runtime/scripts/amalgm-mcp/tests/workspace-cards-store.test.js +3 -72
  90. package/runtime/scripts/amalgm-mcp/tests/workspace-cards.test.js +1 -89
  91. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint-reducer.test.js +24 -55
  92. package/runtime/scripts/amalgm-mcp/tests/workspace-checkpoint.test.js +141 -424
  93. package/runtime/scripts/amalgm-mcp/tests/workspace-object-tunnel.test.js +3 -171
  94. package/runtime/scripts/amalgm-mcp/tests/workspace-objects.test.js +7 -220
  95. package/runtime/scripts/amalgm-mcp/tests/workspace-publication-invariants.test.js +236 -179
  96. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer.test.js +326 -2228
  97. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-cloud.test.js +3 -5319
  98. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-core.test.js +1 -191
  99. package/runtime/scripts/amalgm-mcp/tests/workspace-tree-store.test.js +17 -3140
  100. package/runtime/scripts/amalgm-mcp/tests/workspace-wall.test.js +740 -137
  101. package/runtime/scripts/amalgm-mcp/workspace/access-store.js +1 -5
  102. package/runtime/scripts/amalgm-mcp/workspace/card.js +11 -35
  103. package/runtime/scripts/amalgm-mcp/workspace/cards.js +14 -39
  104. package/runtime/scripts/amalgm-mcp/workspace/checkpoint.js +147 -587
  105. package/runtime/scripts/amalgm-mcp/workspace/git.js +34 -406
  106. package/runtime/scripts/amalgm-mcp/workspace/merge.js +181 -102
  107. package/runtime/scripts/amalgm-mcp/workspace/objects.js +56 -221
  108. package/runtime/scripts/amalgm-mcp/workspace/reducer.js +538 -1964
  109. package/runtime/scripts/amalgm-mcp/workspace/rest.js +28 -49
  110. package/runtime/scripts/amalgm-mcp/workspace/store.js +4 -77
  111. package/runtime/scripts/amalgm-mcp/workspace/transition.js +192 -1734
  112. package/runtime/scripts/amalgm-mcp/workspace/tree/inclusion.js +1 -7
  113. package/runtime/scripts/amalgm-mcp/workspace/tree/local-state.js +61 -73
  114. package/runtime/scripts/amalgm-mcp/workspace/tree/reducer.js +6 -51
  115. package/runtime/scripts/amalgm-mcp/workspace/tree/snapshot.js +8 -79
  116. package/runtime/scripts/amalgm-mcp/workspace/tree-cloud.js +146 -3461
  117. package/runtime/scripts/amalgm-mcp/workspace/tree-store.js +71 -899
  118. package/runtime/scripts/amalgm-mcp/workspace/wall.js +538 -370
  119. package/runtime/scripts/local-gateway.js +1 -0
  120. package/runtime/scripts/amalgm-mcp/state/doc-disk.js +0 -550
  121. package/runtime/scripts/amalgm-mcp/tests/code-project-stream.test.js +0 -399
  122. package/runtime/scripts/amalgm-mcp/tests/fixtures/code-project-stream-v2.json +0 -1
  123. package/runtime/scripts/amalgm-mcp/tests/workspace-durable.test.js +0 -24
  124. package/runtime/scripts/amalgm-mcp/tests/workspace-local-intent.test.js +0 -1999
  125. package/runtime/scripts/amalgm-mcp/tests/workspace-native-file-transaction.test.js +0 -364
  126. package/runtime/scripts/amalgm-mcp/tests/workspace-provenance.test.js +0 -185
  127. package/runtime/scripts/amalgm-mcp/tests/workspace-reducer-liveness.test.js +0 -26
  128. package/runtime/scripts/amalgm-mcp/tests/workspace-sync-stats.test.js +0 -119
  129. package/runtime/scripts/amalgm-mcp/tests/workspace-transition.test.js +0 -1446
  130. package/runtime/scripts/amalgm-mcp/workspace/content.js +0 -32
  131. package/runtime/scripts/amalgm-mcp/workspace/durable.js +0 -45
  132. package/runtime/scripts/amalgm-mcp/workspace/intent.js +0 -535
  133. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/BUILD.md +0 -31
  134. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/darwin-arm64/amalgm-file-transaction +0 -0
  135. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/bin/linux-x64/amalgm-file-transaction +0 -0
  136. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/build.mjs +0 -72
  137. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/client.js +0 -165
  138. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.mod +0 -5
  139. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/go.sum +0 -2
  140. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/main.go +0 -2201
  141. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/manifest.json +0 -19
  142. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_darwin.go +0 -18
  143. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/move_linux.go +0 -18
  144. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_darwin.go +0 -33
  145. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/process_linux.go +0 -47
  146. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/verify.mjs +0 -43
  147. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_darwin.go +0 -114
  148. package/runtime/scripts/amalgm-mcp/workspace/native-file-transaction/writers_linux.go +0 -84
  149. package/runtime/scripts/amalgm-mcp/workspace/project-stream.js +0 -771
  150. package/runtime/scripts/amalgm-mcp/workspace/provenance.js +0 -240
  151. package/runtime/scripts/amalgm-mcp/workspace/sync-stats.js +0 -240
  152. package/runtime/scripts/amalgm-mcp/workspace/tree/floor.js +0 -100
  153. package/runtime/scripts/amalgm-mcp/workspace/tree/observation-holds.js +0 -127
  154. package/runtime/scripts/amalgm-mcp/workspace/tree/path-state.js +0 -12
  155. package/runtime/scripts/amalgm-mcp/workspace/tree/root-binding.js +0 -125
  156. package/runtime/scripts/amalgm-mcp/workspace/tree/symlinks.js +0 -76
  157. package/runtime/scripts/amalgm-mcp/workspace/tree-materialization.js +0 -3766
@@ -14,9 +14,9 @@ const {
14
14
  renameWorkspace,
15
15
  upsertWorkspace,
16
16
  } = require('./store');
17
- const { listRepoCards, refreshRepoCards } = require('./cards');
17
+ const { listRepoCards, refreshRepoCards, repoCardServiceStats } = require('./cards');
18
18
  const { machineId } = require('./identity');
19
- const { readWall } = require('./wall');
19
+ const { readWall, wallStats } = require('./wall');
20
20
 
21
21
  const execFileAsync = promisify(execFile);
22
22
  const MAX_BUFFER = 10 * 1024 * 1024;
@@ -66,10 +66,6 @@ function enrollWorkspaceTree(workspace) {
66
66
  return require('./tree-store').enrollWorkspace(workspace.id);
67
67
  }
68
68
 
69
- function workspaceAfterTreeEnrollment(workspace) {
70
- return listWorkspaces().find((entry) => entry.id === workspace.id) || workspace;
71
- }
72
-
73
69
  async function uniqueProjectPath(workspaceRoot, requestedName) {
74
70
  const name = sanitizeProjectName(requestedName);
75
71
  let candidate = path.join(workspaceRoot, name);
@@ -220,20 +216,15 @@ async function handleProjectRegister(body, sendJson) {
220
216
  });
221
217
  ensureProjectMemory(workspace, 'workspace:register');
222
218
  const tree = enrollWorkspaceTree(workspace);
223
- const enrolledWorkspace = workspaceAfterTreeEnrollment(workspace);
224
219
 
225
220
  sendJson(200, {
226
221
  success: true,
227
- workspace: enrolledWorkspace,
222
+ workspace,
228
223
  path: workspace.path,
229
224
  name: workspace.name,
230
225
  uri: workspace.uri,
231
226
  workspaceRoot,
232
- tree: {
233
- nodes: tree.nodes.length,
234
- created: tree.created,
235
- observation: enrolledWorkspace.treeObservation,
236
- },
227
+ tree: { nodes: tree.nodes.length, created: tree.created },
237
228
  });
238
229
  } catch (error) {
239
230
  sendJson(500, {
@@ -360,19 +351,14 @@ async function handleImport(body, sendJson) {
360
351
  });
361
352
  ensureProjectMemory(workspace, 'workspace:import');
362
353
  const tree = enrollWorkspaceTree(workspace);
363
- const enrolledWorkspace = workspaceAfterTreeEnrollment(workspace);
364
354
  sendJson(200, {
365
355
  success: true,
366
356
  path: workspace.path,
367
357
  name: workspace.name,
368
- workspace: enrolledWorkspace,
358
+ workspace,
369
359
  workspaceRoot,
370
360
  alreadyInWorkspace: true,
371
- tree: {
372
- nodes: tree.nodes.length,
373
- created: tree.created,
374
- observation: enrolledWorkspace.treeObservation,
375
- },
361
+ tree: { nodes: tree.nodes.length, created: tree.created },
376
362
  });
377
363
  return;
378
364
  }
@@ -398,20 +384,15 @@ async function handleImport(body, sendJson) {
398
384
  });
399
385
  ensureProjectMemory(workspace, 'workspace:import');
400
386
  const tree = enrollWorkspaceTree(workspace);
401
- const enrolledWorkspace = workspaceAfterTreeEnrollment(workspace);
402
387
 
403
388
  sendJson(200, {
404
389
  success: true,
405
390
  path: workspace.path,
406
391
  name: workspace.name,
407
- workspace: enrolledWorkspace,
392
+ workspace,
408
393
  workspaceRoot,
409
394
  alreadyInWorkspace: false,
410
- tree: {
411
- nodes: tree.nodes.length,
412
- created: tree.created,
413
- observation: enrolledWorkspace.treeObservation,
414
- },
395
+ tree: { nodes: tree.nodes.length, created: tree.created },
415
396
  });
416
397
  } catch (error) {
417
398
  sendJson(500, {
@@ -452,18 +433,13 @@ async function handleClone(body, sendJson) {
452
433
  });
453
434
  ensureProjectMemory(workspace, 'workspace:clone');
454
435
  const tree = enrollWorkspaceTree(workspace);
455
- const enrolledWorkspace = workspaceAfterTreeEnrollment(workspace);
456
436
  sendJson(200, {
457
437
  success: true,
458
438
  path: workspace.path,
459
- workspace: enrolledWorkspace,
439
+ workspace,
460
440
  workspaceRoot,
461
441
  alreadyExists: true,
462
- tree: {
463
- nodes: tree.nodes.length,
464
- created: tree.created,
465
- observation: enrolledWorkspace.treeObservation,
466
- },
442
+ tree: { nodes: tree.nodes.length, created: tree.created },
467
443
  });
468
444
  return;
469
445
  }
@@ -501,19 +477,14 @@ async function handleClone(body, sendJson) {
501
477
  });
502
478
  ensureProjectMemory(workspace, 'workspace:clone');
503
479
  const tree = enrollWorkspaceTree(workspace);
504
- const enrolledWorkspace = workspaceAfterTreeEnrollment(workspace);
505
480
 
506
481
  sendJson(200, {
507
482
  success: true,
508
483
  path: workspace.path,
509
- workspace: enrolledWorkspace,
484
+ workspace,
510
485
  workspaceRoot,
511
486
  alreadyExists: false,
512
- tree: {
513
- nodes: tree.nodes.length,
514
- created: tree.created,
515
- observation: enrolledWorkspace.treeObservation,
516
- },
487
+ tree: { nodes: tree.nodes.length, created: tree.created },
517
488
  });
518
489
  }
519
490
 
@@ -743,7 +714,17 @@ async function handleRepoCardsRefresh(sendJson) {
743
714
 
744
715
  function handleWorkspaceSyncStats(sendJson) {
745
716
  try {
746
- sendJson(200, require('./sync-stats').workspaceSyncStats());
717
+ const cards = listRepoCards();
718
+ const health = { healthy: 0, missing: 0, broken: 0, inaccessible: 0 };
719
+ for (const card of cards) health[card.health] = (health[card.health] || 0) + 1;
720
+ sendJson(200, {
721
+ machine: machineId(),
722
+ cards: { total: cards.length, ...health },
723
+ service: repoCardServiceStats(),
724
+ wall: wallStats(),
725
+ checkpoints: require('./checkpoint').checkpointStats(),
726
+ reducer: require('./reducer').reducerStats(),
727
+ });
747
728
  } catch (error) {
748
729
  sendJson(500, { error: error instanceof Error ? error.message : 'Failed to read sync stats' });
749
730
  }
@@ -751,14 +732,8 @@ function handleWorkspaceSyncStats(sendJson) {
751
732
 
752
733
  function handleCodeProjectJoin(body, sendJson) {
753
734
  try {
754
- const keys = Object.keys(body || {}).sort();
755
- if (
756
- keys.length !== 3
757
- || keys[0] !== 'ownerUserId'
758
- || keys[1] !== 'path'
759
- || keys[2] !== 'resourceId'
760
- ) throw new Error('code project join requires exactly resourceId, path, and ownerUserId');
761
735
  const project = require('./wall').bindProject(
736
+ body?.repoKey,
762
737
  body?.resourceId,
763
738
  body?.ownerUserId,
764
739
  body?.path,
@@ -845,8 +820,12 @@ function handleTreeMutation(body, sendJson) {
845
820
  const actorUserId = require('./identity').userId();
846
821
  if (!actorUserId) throw Object.assign(new Error('this runtime is not enrolled to a user'), { statusCode: 401 });
847
822
  const operation = body?.operation || body;
823
+ const accessNodeId = operation?.kind === 'tree.create' ? operation?.parentId : operation?.nodeId;
824
+ const access = require('./access-store').resolveAccess(accessNodeId, actorUserId);
825
+ if (!access?.role) throw Object.assign(new Error('tree operation is forbidden'), { statusCode: 403 });
848
826
  sendJson(200, require('./tree-store').commitTreeOperation(operation, {
849
827
  mutationId: body?.mutationId,
828
+ role: access.role,
850
829
  source: 'workspace-tree:api',
851
830
  }));
852
831
  } catch (error) {
@@ -135,17 +135,11 @@ function ensureWorkspaceIdentityRows(database, workspace, options = {}) {
135
135
  }
136
136
  }
137
137
 
138
- function rowToWorkspace(row, database = openLocalDb()) {
138
+ function rowToWorkspace(row) {
139
139
  if (!row) return null;
140
140
  const parsed = parseJson(row.workspace_json, {});
141
141
  const resolvedPath = row.path ? canonicalProjectPath(row.path) : row.path;
142
142
  const legacyManagedPath = row.path ? isLegacyManagedWorkspacePath(row.path) : false;
143
- const syncHolds = require('./tree/observation-holds').list(row.id, database);
144
- const status = syncHolds.length
145
- ? 'held'
146
- : resolvedPath && fs.existsSync(resolvedPath)
147
- ? 'ready'
148
- : row.status;
149
143
  return {
150
144
  ...parsed,
151
145
  id: row.id,
@@ -157,13 +151,7 @@ function rowToWorkspace(row, database = openLocalDb()) {
157
151
  computerId: row.computer_id || parsed.computerId || null,
158
152
  source: legacyManagedPath ? 'computer' : row.source,
159
153
  managed: legacyManagedPath ? false : row.managed === 1,
160
- status,
161
- treeObservation: syncHolds.length ? {
162
- state: 'held',
163
- owner: 'workspace-tree',
164
- retry: { kind: 'automatic' },
165
- holds: syncHolds,
166
- } : null,
154
+ status: resolvedPath && fs.existsSync(resolvedPath) ? 'ready' : row.status,
167
155
  createdAt: row.created_at,
168
156
  updatedAt: row.updated_at,
169
157
  };
@@ -194,71 +182,13 @@ function publishEvents(events) {
194
182
  }
195
183
 
196
184
  function listWorkspaces() {
197
- const database = openLocalDb();
198
- return database
185
+ return openLocalDb()
199
186
  .prepare('SELECT * FROM workspaces ORDER BY lower(name), path')
200
187
  .all()
201
- .map((row) => rowToWorkspace(row, database))
188
+ .map(rowToWorkspace)
202
189
  .filter(Boolean);
203
190
  }
204
191
 
205
- function replaceTreeObservationInTransaction(
206
- workspaceId,
207
- holds,
208
- options = {},
209
- ) {
210
- const database = options.database || openLocalDb();
211
- const changed = require('./tree/observation-holds').replace(
212
- workspaceId,
213
- holds,
214
- database,
215
- {
216
- ownerKind: options.ownerKind,
217
- ownerId: options.ownerId,
218
- },
219
- );
220
- if (!changed) return { changed, events: [] };
221
- const row = workspaceRow(database, workspaceId);
222
- if (!row) return { changed, events: [] };
223
- const workspace = rowToWorkspace(row, database);
224
- return {
225
- changed,
226
- events: publishWorkspaceEvents(
227
- database,
228
- 'update',
229
- workspace,
230
- options.source || 'workspace-tree:observation-hold',
231
- ),
232
- };
233
- }
234
-
235
- function publishTreeObservationCommit(result) {
236
- publishEvents(result?.events || []);
237
- }
238
-
239
- function commitCompletedTreeObservation(workspaceId, holds, options = {}) {
240
- const database = options.database || openLocalDb();
241
- let result = { changed: false, events: [] };
242
- database.transaction(() => {
243
- if (typeof options.mutate === 'function') options.mutate();
244
- result = replaceTreeObservationInTransaction(
245
- workspaceId,
246
- holds,
247
- {
248
- database,
249
- ownerKind: options.ownerKind,
250
- ownerId: options.ownerId,
251
- source: options.source,
252
- },
253
- );
254
- })();
255
- publishTreeObservationCommit(result);
256
- return {
257
- changed: result.changed,
258
- holds: require('./tree/observation-holds').list(workspaceId, database),
259
- };
260
- }
261
-
262
192
  function upsertWorkspace(input, options = {}) {
263
193
  const db = openLocalDb();
264
194
  let workspace;
@@ -383,9 +313,6 @@ function removeWorkspace(identifier, options = {}) {
383
313
  }
384
314
 
385
315
  module.exports = {
386
- commitCompletedTreeObservation,
387
- publishTreeObservationCommit,
388
- replaceTreeObservationInTransaction,
389
316
  listWorkspaces,
390
317
  normalizeWorkspaceRecord,
391
318
  removeWorkspace,