@powerhousedao/network-admin 0.0.49 → 0.0.50

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 (96) hide show
  1. package/dist/document-models/builders/src/reducers/builders.d.ts.map +1 -1
  2. package/dist/document-models/builders/src/reducers/builders.js +2 -2
  3. package/dist/document-models/network-profile/gen/document-schema.d.ts +16 -16
  4. package/dist/document-models/network-profile/gen/document-schema.d.ts.map +1 -1
  5. package/dist/document-models/network-profile/gen/schema/types.d.ts +2 -2
  6. package/dist/document-models/network-profile/gen/schema/types.d.ts.map +1 -1
  7. package/dist/document-models/network-profile/src/reducers/network-profile-management.d.ts.map +1 -1
  8. package/dist/document-models/network-profile/src/reducers/network-profile-management.js +1 -1
  9. package/dist/document-models/payment-terms/gen/document-schema.d.ts +48 -48
  10. package/dist/document-models/payment-terms/gen/document-schema.d.ts.map +1 -1
  11. package/dist/document-models/payment-terms/gen/schema/types.d.ts +12 -12
  12. package/dist/document-models/payment-terms/gen/schema/types.d.ts.map +1 -1
  13. package/dist/document-models/payment-terms/src/reducers/clauses.d.ts.map +1 -1
  14. package/dist/document-models/payment-terms/src/reducers/clauses.js +10 -10
  15. package/dist/document-models/payment-terms/src/reducers/milestones.d.ts.map +1 -1
  16. package/dist/document-models/payment-terms/src/reducers/milestones.js +14 -11
  17. package/dist/document-models/payment-terms/src/reducers/terms.js +4 -4
  18. package/dist/document-models/request-for-proposals/gen/document-schema.d.ts +16 -16
  19. package/dist/document-models/request-for-proposals/gen/document-schema.d.ts.map +1 -1
  20. package/dist/document-models/request-for-proposals/gen/schema/types.d.ts +9 -9
  21. package/dist/document-models/request-for-proposals/gen/schema/types.d.ts.map +1 -1
  22. package/dist/document-models/request-for-proposals/src/reducers/contex-document.d.ts.map +1 -1
  23. package/dist/document-models/request-for-proposals/src/reducers/contex-document.js +3 -3
  24. package/dist/document-models/request-for-proposals/src/reducers/proposals.d.ts.map +1 -1
  25. package/dist/document-models/request-for-proposals/src/reducers/proposals.js +16 -12
  26. package/dist/document-models/request-for-proposals/src/reducers/rfp-state.d.ts.map +1 -1
  27. package/dist/document-models/request-for-proposals/src/reducers/rfp-state.js +7 -3
  28. package/dist/document-models/workstream/gen/document-schema.d.ts +16 -16
  29. package/dist/document-models/workstream/gen/document-schema.d.ts.map +1 -1
  30. package/dist/document-models/workstream/gen/schema/types.d.ts +6 -6
  31. package/dist/document-models/workstream/gen/schema/types.d.ts.map +1 -1
  32. package/dist/document-models/workstream/src/reducers/proposals.d.ts.map +1 -1
  33. package/dist/document-models/workstream/src/reducers/proposals.js +78 -0
  34. package/dist/editors/network-admin/components/builders.d.ts.map +1 -1
  35. package/dist/editors/network-admin/components/icons/PaymentIcon.d.ts.map +1 -1
  36. package/dist/editors/network-admin/components/icons/RfpIcon.d.ts.map +1 -1
  37. package/dist/editors/network-admin/components/icons/SowIcon.d.ts.map +1 -1
  38. package/dist/editors/network-admin/components/icons/WorkstreamIcon.d.ts.map +1 -1
  39. package/dist/editors/network-profile/editor.d.ts.map +1 -1
  40. package/dist/editors/payment-terms/components/clauses-section.d.ts +12 -0
  41. package/dist/editors/payment-terms/components/clauses-section.d.ts.map +1 -0
  42. package/dist/editors/payment-terms/components/clauses-section.js +269 -0
  43. package/dist/editors/payment-terms/components/escrow-section.d.ts +13 -0
  44. package/dist/editors/payment-terms/components/escrow-section.d.ts.map +1 -0
  45. package/dist/editors/payment-terms/components/escrow-section.js +72 -0
  46. package/dist/editors/payment-terms/components/evaluation-section.d.ts +13 -0
  47. package/dist/editors/payment-terms/components/evaluation-section.d.ts.map +1 -0
  48. package/dist/editors/payment-terms/components/evaluation-section.js +94 -0
  49. package/dist/editors/payment-terms/components/header-section.d.ts +16 -0
  50. package/dist/editors/payment-terms/components/header-section.d.ts.map +1 -0
  51. package/dist/editors/payment-terms/components/header-section.js +67 -0
  52. package/dist/editors/payment-terms/components/milestones-section.d.ts +11 -0
  53. package/dist/editors/payment-terms/components/milestones-section.d.ts.map +1 -0
  54. package/dist/editors/payment-terms/components/milestones-section.js +268 -0
  55. package/dist/editors/payment-terms/components/parties-section.d.ts +11 -0
  56. package/dist/editors/payment-terms/components/parties-section.d.ts.map +1 -0
  57. package/dist/editors/payment-terms/components/parties-section.js +36 -0
  58. package/dist/editors/payment-terms/components/payment-config-section.d.ts +11 -0
  59. package/dist/editors/payment-terms/components/payment-config-section.d.ts.map +1 -0
  60. package/dist/editors/payment-terms/components/payment-config-section.js +68 -0
  61. package/dist/editors/payment-terms/components/styles.d.ts +2 -0
  62. package/dist/editors/payment-terms/components/styles.d.ts.map +1 -0
  63. package/dist/editors/payment-terms/components/styles.js +741 -0
  64. package/dist/editors/payment-terms/components/time-materials-section.d.ts +11 -0
  65. package/dist/editors/payment-terms/components/time-materials-section.d.ts.map +1 -0
  66. package/dist/editors/payment-terms/components/time-materials-section.js +68 -0
  67. package/dist/editors/payment-terms/editor.d.ts +0 -2
  68. package/dist/editors/payment-terms/editor.d.ts.map +1 -1
  69. package/dist/editors/payment-terms/editor.js +36 -52
  70. package/dist/editors/payment-terms/evaluation-tab.d.ts +1 -1
  71. package/dist/editors/payment-terms/evaluation-tab.d.ts.map +1 -1
  72. package/dist/editors/payment-terms/evaluation-tab.js +17 -8
  73. package/dist/editors/payment-terms/milestones-tab.d.ts.map +1 -1
  74. package/dist/editors/payment-terms/milestones-tab.js +9 -1
  75. package/dist/editors/request-for-proposals/markdown-editor.d.ts.map +1 -1
  76. package/dist/editors/request-for-proposals/markdown-editor.js +3 -3
  77. package/dist/editors/workstream/editor.d.ts.map +1 -1
  78. package/dist/editors/workstream/editor.js +114 -26
  79. package/dist/processors/workstreams/index.d.ts +1 -0
  80. package/dist/processors/workstreams/index.d.ts.map +1 -1
  81. package/dist/processors/workstreams/index.js +91 -29
  82. package/dist/processors/workstreams/migrations.d.ts.map +1 -1
  83. package/dist/processors/workstreams/migrations.js +9 -10
  84. package/dist/scripts/sow-mirror/mirror_sow_state.d.ts +3 -0
  85. package/dist/scripts/sow-mirror/mirror_sow_state.d.ts.map +1 -0
  86. package/dist/scripts/sow-mirror/mirror_sow_state.js +446 -0
  87. package/dist/style.css +464 -232
  88. package/dist/subgraphs/networks/resolvers.d.ts.map +1 -1
  89. package/dist/subgraphs/networks/resolvers.js +4 -3
  90. package/dist/subgraphs/networks/schema.d.ts.map +1 -1
  91. package/dist/subgraphs/networks/schema.js +0 -1
  92. package/dist/subgraphs/workstreams/resolvers.d.ts.map +1 -1
  93. package/dist/subgraphs/workstreams/resolvers.js +17 -11
  94. package/dist/subgraphs/workstreams/schema.d.ts.map +1 -1
  95. package/dist/subgraphs/workstreams/schema.js +130 -27
  96. package/package.json +2 -2
@@ -0,0 +1,446 @@
1
+ #!/usr/bin/env bun
2
+ // Parse command line arguments
3
+ const args = process.argv.slice(2);
4
+ if (args.length !== 6) {
5
+ console.error("Usage: bun mirror_sow_state.ts <remote-mcp-url> <remote-sow-id> <remote-drive-id> <local-mcp-url> <local-sow-id> <local-drive-id>");
6
+ console.error("");
7
+ console.error("Example:");
8
+ console.error(" bun mirror_sow_state.ts \\");
9
+ console.error(" https://switchboard-dev.powerhouse.xyz/mcp \\");
10
+ console.error(" 65f3e7e8-500d-4c42-9e73-8cd5d7966cd8 \\");
11
+ console.error(" powerhouse-network-admin \\");
12
+ console.error(" http://localhost:4001/mcp \\");
13
+ console.error(" 3471233d-c481-4214-afe3-c196b5a7778f \\");
14
+ console.error(" bai-network-admin");
15
+ process.exit(1);
16
+ }
17
+ const [REMOTE_MCP_URL, REMOTE_DOC_ID, REMOTE_DRIVE_ID, LOCAL_MCP_URL, LOCAL_DOC_ID, LOCAL_DRIVE_ID,] = args;
18
+ // Helper function to make MCP requests
19
+ async function mcpRequest(url, payload) {
20
+ const response = await fetch(url, {
21
+ method: "POST",
22
+ headers: {
23
+ "Content-Type": "application/json",
24
+ Accept: "application/json, text/event-stream",
25
+ },
26
+ body: JSON.stringify(payload),
27
+ });
28
+ const text = await response.text();
29
+ // Handle SSE format (event: message\ndata: {...})
30
+ if (text.includes("event: message")) {
31
+ const lines = text.split("\n");
32
+ const dataLine = lines.find((line) => line.startsWith("data: "));
33
+ if (dataLine) {
34
+ const jsonData = dataLine.substring(6);
35
+ return JSON.parse(jsonData);
36
+ }
37
+ throw new Error("No data line found in SSE response");
38
+ }
39
+ return JSON.parse(text);
40
+ }
41
+ // Fetch remote document
42
+ async function getRemoteDocument() {
43
+ console.log(`Fetching remote document (${REMOTE_DOC_ID}) from drive "${REMOTE_DRIVE_ID}"...`);
44
+ const payload = {
45
+ jsonrpc: "2.0",
46
+ method: "tools/call",
47
+ params: {
48
+ name: "getDocument",
49
+ arguments: { id: REMOTE_DOC_ID },
50
+ },
51
+ id: 1,
52
+ };
53
+ const response = await mcpRequest(REMOTE_MCP_URL, payload);
54
+ if (response.error) {
55
+ throw new Error(`Remote fetch error: ${JSON.stringify(response.error)}`);
56
+ }
57
+ return response.result.structuredContent.document;
58
+ }
59
+ // Get current local document state
60
+ async function getLocalDocument() {
61
+ console.log(`Fetching local document (${LOCAL_DOC_ID}) from drive "${LOCAL_DRIVE_ID}"...`);
62
+ const payload = {
63
+ jsonrpc: "2.0",
64
+ method: "tools/call",
65
+ params: {
66
+ name: "getDocument",
67
+ arguments: { id: LOCAL_DOC_ID },
68
+ },
69
+ id: 2,
70
+ };
71
+ const response = await mcpRequest(LOCAL_MCP_URL, payload);
72
+ if (response.error) {
73
+ throw new Error(`Local fetch error: ${JSON.stringify(response.error)}`);
74
+ }
75
+ return response.result.structuredContent.document;
76
+ }
77
+ // Generate actions to mirror remote state
78
+ function generateActions(remoteState, localState) {
79
+ const actions = [];
80
+ // 1. Update basic scope of work details
81
+ if (remoteState.title !== localState.title ||
82
+ remoteState.description !== localState.description ||
83
+ remoteState.status !== localState.status) {
84
+ actions.push({
85
+ type: "EDIT_SCOPE_OF_WORK",
86
+ scope: "global",
87
+ input: {
88
+ title: remoteState.title,
89
+ description: remoteState.description,
90
+ status: remoteState.status,
91
+ },
92
+ });
93
+ }
94
+ // 2. Add missing contributors
95
+ const localContributorIds = new Set(localState.contributors.map((c) => c.id));
96
+ remoteState.contributors.forEach((contributor) => {
97
+ if (!localContributorIds.has(contributor.id)) {
98
+ const input = {
99
+ id: contributor.id,
100
+ name: contributor.name,
101
+ };
102
+ if (contributor.icon)
103
+ input.icon = contributor.icon;
104
+ if (contributor.description)
105
+ input.description = contributor.description;
106
+ actions.push({
107
+ type: "ADD_AGENT",
108
+ scope: "global",
109
+ input,
110
+ });
111
+ }
112
+ });
113
+ // 3. Add missing deliverables with all their data
114
+ const localDeliverableIds = new Set(localState.deliverables.map((d) => d.id));
115
+ remoteState.deliverables.forEach((deliverable) => {
116
+ if (!localDeliverableIds.has(deliverable.id)) {
117
+ // Add deliverable
118
+ actions.push({
119
+ type: "ADD_DELIVERABLE",
120
+ scope: "global",
121
+ input: {
122
+ id: deliverable.id,
123
+ owner: deliverable.owner || undefined,
124
+ title: deliverable.title,
125
+ code: deliverable.code,
126
+ description: deliverable.description,
127
+ status: deliverable.status,
128
+ },
129
+ });
130
+ // Set work progress
131
+ if (deliverable.workProgress) {
132
+ const progressInput = {};
133
+ if (deliverable.workProgress.value !== undefined) {
134
+ progressInput.percentage = deliverable.workProgress.value;
135
+ }
136
+ else if (deliverable.workProgress.total !== undefined) {
137
+ progressInput.storyPoints = {
138
+ total: deliverable.workProgress.total,
139
+ completed: deliverable.workProgress.completed,
140
+ };
141
+ }
142
+ else if (deliverable.workProgress.done !== undefined) {
143
+ progressInput.done = deliverable.workProgress.done;
144
+ }
145
+ if (Object.keys(progressInput).length > 0) {
146
+ actions.push({
147
+ type: "SET_DELIVERABLE_PROGRESS",
148
+ scope: "global",
149
+ input: {
150
+ id: deliverable.id,
151
+ workProgress: progressInput,
152
+ },
153
+ });
154
+ }
155
+ }
156
+ // Add key results
157
+ if (deliverable.keyResults && deliverable.keyResults.length > 0) {
158
+ deliverable.keyResults.forEach((kr) => {
159
+ actions.push({
160
+ type: "ADD_KEY_RESULT",
161
+ scope: "global",
162
+ input: {
163
+ id: kr.id,
164
+ deliverableId: deliverable.id,
165
+ title: kr.title,
166
+ link: kr.link,
167
+ },
168
+ });
169
+ });
170
+ }
171
+ // Set budget anchor if exists
172
+ if (deliverable.budgetAnchor && deliverable.budgetAnchor.project) {
173
+ actions.push({
174
+ type: "SET_DELIVERABLE_BUDGET_ANCHOR_PROJECT",
175
+ scope: "global",
176
+ input: {
177
+ deliverableId: deliverable.id,
178
+ project: deliverable.budgetAnchor.project,
179
+ unit: deliverable.budgetAnchor.unit,
180
+ unitCost: deliverable.budgetAnchor.unitCost,
181
+ quantity: deliverable.budgetAnchor.quantity,
182
+ margin: deliverable.budgetAnchor.margin,
183
+ },
184
+ });
185
+ }
186
+ }
187
+ });
188
+ // 4. Add projects if any
189
+ if (remoteState.projects && remoteState.projects.length > 0) {
190
+ const localProjectsMap = new Map(localState.projects.map((p) => [p.id, p]));
191
+ remoteState.projects.forEach((project) => {
192
+ const localProject = localProjectsMap.get(project.id);
193
+ if (!localProject) {
194
+ // Project doesn't exist, add it
195
+ actions.push({
196
+ type: "ADD_PROJECT",
197
+ scope: "global",
198
+ input: {
199
+ id: project.id,
200
+ code: project.code,
201
+ title: project.title,
202
+ projectOwner: project.projectOwner || undefined,
203
+ abstract: project.abstract || undefined,
204
+ imageUrl: project.imageUrl || undefined,
205
+ budgetType: project.budgetType || undefined,
206
+ currency: project.currency || undefined,
207
+ budget: project.budget || 0,
208
+ },
209
+ });
210
+ }
211
+ // Add missing deliverables to project scope
212
+ if (project.scope &&
213
+ project.scope.deliverables &&
214
+ project.scope.deliverables.length > 0) {
215
+ const localDeliverables = new Set(localProject?.scope?.deliverables || []);
216
+ project.scope.deliverables.forEach((deliverableId) => {
217
+ if (!localDeliverables.has(deliverableId)) {
218
+ const deliverable = remoteState.deliverables.find((d) => d.id === deliverableId);
219
+ if (deliverable) {
220
+ actions.push({
221
+ type: "ADD_DELIVERABLE_IN_SET",
222
+ scope: "global",
223
+ input: {
224
+ projectId: project.id,
225
+ deliverableId: deliverableId,
226
+ },
227
+ });
228
+ }
229
+ }
230
+ });
231
+ // Set project scope metadata (status and deliverablesCompleted)
232
+ if (project.scope.status || project.scope.deliverablesCompleted) {
233
+ actions.push({
234
+ type: "EDIT_DELIVERABLES_SET",
235
+ scope: "global",
236
+ input: {
237
+ projectId: project.id,
238
+ status: project.scope.status || undefined,
239
+ deliverablesCompleted: project.scope.deliverablesCompleted || undefined,
240
+ },
241
+ });
242
+ }
243
+ }
244
+ });
245
+ }
246
+ // 5. Add roadmaps if any
247
+ if (remoteState.roadmaps && remoteState.roadmaps.length > 0) {
248
+ const localRoadmapIds = new Set(localState.roadmaps.map((r) => r.id));
249
+ const localRoadmapsMap = new Map(localState.roadmaps.map((r) => [r.id, r]));
250
+ remoteState.roadmaps.forEach((roadmap) => {
251
+ const localRoadmap = localRoadmapsMap.get(roadmap.id);
252
+ if (!localRoadmap) {
253
+ actions.push({
254
+ type: "ADD_ROADMAP",
255
+ scope: "global",
256
+ input: {
257
+ id: roadmap.id,
258
+ title: roadmap.title,
259
+ slug: roadmap.slug || undefined,
260
+ description: roadmap.description || undefined,
261
+ },
262
+ });
263
+ }
264
+ // Add milestones for this roadmap
265
+ if (roadmap.milestones && roadmap.milestones.length > 0) {
266
+ const localMilestonesMap = new Map((localRoadmap?.milestones || []).map((m) => [m.id, m]));
267
+ roadmap.milestones.forEach((milestone) => {
268
+ const localMilestone = localMilestonesMap.get(milestone.id);
269
+ if (!localMilestone) {
270
+ actions.push({
271
+ type: "ADD_MILESTONE",
272
+ scope: "global",
273
+ input: {
274
+ id: milestone.id,
275
+ roadmapId: roadmap.id,
276
+ sequenceCode: milestone.sequenceCode || undefined,
277
+ title: milestone.title,
278
+ description: milestone.description || undefined,
279
+ deliveryTarget: milestone.deliveryTarget || undefined,
280
+ },
281
+ });
282
+ }
283
+ // Add coordinators for milestone
284
+ if (milestone.coordinators && milestone.coordinators.length > 0) {
285
+ const localCoordinators = new Set(localMilestone?.coordinators || []);
286
+ milestone.coordinators.forEach((coordinatorId) => {
287
+ if (!localCoordinators.has(coordinatorId)) {
288
+ actions.push({
289
+ type: "ADD_COORDINATOR",
290
+ scope: "global",
291
+ input: {
292
+ id: coordinatorId,
293
+ milestoneId: milestone.id,
294
+ },
295
+ });
296
+ }
297
+ });
298
+ }
299
+ // Add deliverables to milestone
300
+ if (milestone.scope &&
301
+ milestone.scope.deliverables &&
302
+ milestone.scope.deliverables.length > 0) {
303
+ const localMilestoneDeliverables = new Set(localMilestone?.scope?.deliverables || []);
304
+ milestone.scope.deliverables.forEach((deliverableId) => {
305
+ if (!localMilestoneDeliverables.has(deliverableId)) {
306
+ actions.push({
307
+ type: "ADD_DELIVERABLE_IN_SET",
308
+ scope: "global",
309
+ input: {
310
+ milestoneId: milestone.id,
311
+ deliverableId: deliverableId,
312
+ },
313
+ });
314
+ }
315
+ });
316
+ // Set milestone scope metadata
317
+ if (milestone.scope.status ||
318
+ milestone.scope.deliverablesCompleted) {
319
+ actions.push({
320
+ type: "EDIT_DELIVERABLES_SET",
321
+ scope: "global",
322
+ input: {
323
+ milestoneId: milestone.id,
324
+ status: milestone.scope.status || undefined,
325
+ deliverablesCompleted: milestone.scope.deliverablesCompleted || undefined,
326
+ },
327
+ });
328
+ }
329
+ }
330
+ });
331
+ }
332
+ });
333
+ }
334
+ return actions;
335
+ }
336
+ // Send actions in batches
337
+ async function sendActions(actions) {
338
+ const BATCH_SIZE = 50;
339
+ const batches = [];
340
+ for (let i = 0; i < actions.length; i += BATCH_SIZE) {
341
+ batches.push(actions.slice(i, i + BATCH_SIZE));
342
+ }
343
+ console.log(`\nSending ${actions.length} actions in ${batches.length} batches...`);
344
+ for (let i = 0; i < batches.length; i++) {
345
+ const batch = batches[i];
346
+ console.log(`\nBatch ${i + 1}/${batches.length} (${batch.length} actions)...`);
347
+ const payload = {
348
+ jsonrpc: "2.0",
349
+ method: "tools/call",
350
+ params: {
351
+ name: "addActions",
352
+ arguments: {
353
+ documentId: LOCAL_DOC_ID,
354
+ actions: batch,
355
+ },
356
+ },
357
+ id: 1000 + i,
358
+ };
359
+ try {
360
+ const response = await mcpRequest(LOCAL_MCP_URL, payload);
361
+ if (response.error) {
362
+ console.error(`Error in batch ${i + 1}:`, JSON.stringify(response.error, null, 2));
363
+ throw new Error(`Batch ${i + 1} failed`);
364
+ }
365
+ console.log(`✓ Batch ${i + 1} completed successfully`);
366
+ }
367
+ catch (error) {
368
+ console.error(`Failed to send batch ${i + 1}:`, error);
369
+ throw error;
370
+ }
371
+ }
372
+ }
373
+ // Main function
374
+ async function main() {
375
+ try {
376
+ console.log("=".repeat(70));
377
+ console.log("Scope of Work State-Based Mirror Script");
378
+ console.log("=".repeat(70));
379
+ console.log("\nConfiguration:");
380
+ console.log(` Remote MCP: ${REMOTE_MCP_URL}`);
381
+ console.log(` Remote Drive: ${REMOTE_DRIVE_ID}`);
382
+ console.log(` Remote SoW ID: ${REMOTE_DOC_ID}`);
383
+ console.log(` Local MCP: ${LOCAL_MCP_URL}`);
384
+ console.log(` Local Drive: ${LOCAL_DRIVE_ID}`);
385
+ console.log(` Local SoW ID: ${LOCAL_DOC_ID}`);
386
+ console.log("");
387
+ // Fetch remote document
388
+ const remoteDoc = await getRemoteDocument();
389
+ const remoteState = remoteDoc.state.global;
390
+ console.log(`✓ Remote document fetched: "${remoteState.title}"`);
391
+ console.log(` - Status: ${remoteState.status}`);
392
+ console.log(` - Contributors: ${remoteState.contributors.length}`);
393
+ console.log(` - Deliverables: ${remoteState.deliverables.length}`);
394
+ console.log(` - Projects: ${remoteState.projects.length}`);
395
+ console.log(` - Roadmaps: ${remoteState.roadmaps.length}`);
396
+ // Fetch local document
397
+ const localDoc = await getLocalDocument();
398
+ const localState = localDoc.state.global;
399
+ console.log(`\n✓ Local document fetched: "${localState.title}"`);
400
+ console.log(` - Status: ${localState.status}`);
401
+ console.log(` - Contributors: ${localState.contributors.length}`);
402
+ console.log(` - Deliverables: ${localState.deliverables.length}`);
403
+ console.log(` - Projects: ${localState.projects.length}`);
404
+ console.log(` - Roadmaps: ${localState.roadmaps.length}`);
405
+ // Generate actions
406
+ console.log("\nGenerating actions to mirror remote state...");
407
+ const actions = generateActions(remoteState, localState);
408
+ console.log(`✓ Generated ${actions.length} actions`);
409
+ if (actions.length === 0) {
410
+ console.log("\n✓ Documents are already in sync!");
411
+ return;
412
+ }
413
+ // Show action summary
414
+ const actionTypes = {};
415
+ actions.forEach((action) => {
416
+ actionTypes[action.type] = (actionTypes[action.type] || 0) + 1;
417
+ });
418
+ console.log("\nAction summary:");
419
+ Object.entries(actionTypes).forEach(([type, count]) => {
420
+ console.log(` - ${type}: ${count}`);
421
+ });
422
+ // Send actions
423
+ await sendActions(actions);
424
+ // Verify final state
425
+ console.log("\nVerifying final state...");
426
+ const finalLocalDoc = await getLocalDocument();
427
+ const finalLocalState = finalLocalDoc.state.global;
428
+ console.log(`✓ Final local document state:`);
429
+ console.log(` - Title: "${finalLocalState.title}"`);
430
+ console.log(` - Status: ${finalLocalState.status}`);
431
+ console.log(` - Contributors: ${finalLocalState.contributors.length}`);
432
+ console.log(` - Deliverables: ${finalLocalState.deliverables.length}`);
433
+ console.log(` - Projects: ${finalLocalState.projects.length}`);
434
+ console.log(` - Roadmaps: ${finalLocalState.roadmaps.length}`);
435
+ console.log("\n" + "=".repeat(70));
436
+ console.log("✓ Mirror complete!");
437
+ console.log("=".repeat(70));
438
+ }
439
+ catch (error) {
440
+ console.error("\n✗ Error:", error);
441
+ process.exit(1);
442
+ }
443
+ }
444
+ // Run the script
445
+ main();
446
+ export {};