@runfusion/fusion 0.24.0 → 0.26.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 (167) hide show
  1. package/README.md +6 -0
  2. package/dist/bin.js +18646 -15669
  3. package/dist/client/assets/AgentDetailView-Cv-vgOj3.js +18 -0
  4. package/dist/client/assets/{AgentsView-BkB9FiMT.js → AgentsView-D6Zi5zfP.js} +4 -4
  5. package/dist/client/assets/ChatView-CAHjY9uO.js +1 -0
  6. package/dist/client/assets/{DevServerView-BkvtjZBa.js → DevServerView--_WBvIDQ.js} +1 -1
  7. package/dist/client/assets/{DirectoryPicker-BK-KbnhP.js → DirectoryPicker-xedtR-Rd.js} +1 -1
  8. package/dist/client/assets/{DocumentsView-BEg1CQAk.js → DocumentsView-Bg2oaZks.js} +1 -1
  9. package/dist/client/assets/{EvalsView-Berf9bQm.js → EvalsView-B3uOCXfr.js} +1 -1
  10. package/dist/client/assets/{ExperimentalAgentOnboardingModal-jcInE50G.js → ExperimentalAgentOnboardingModal-Bx6yXVS5.js} +1 -1
  11. package/dist/client/assets/{InsightsView-BX5bSF1J.js → InsightsView-Q1zvtF4F.js} +1 -1
  12. package/dist/client/assets/MemoryView-xcN_eouf.js +2 -0
  13. package/dist/client/assets/MemoryView-zaXewZzi.css +1 -0
  14. package/dist/client/assets/{NodesView-DLUOBLf6.js → NodesView-RxXg58_Q.js} +1 -1
  15. package/dist/client/assets/{PiExtensionsManager-COlJf0Kx.js → PiExtensionsManager-Cc8aAZXg.js} +2 -2
  16. package/dist/client/assets/PluginManager-BEkyBajl.js +1 -0
  17. package/dist/client/assets/{ResearchView-BzCcDAS4.css → ResearchView-BEI4ZSGs.css} +1 -1
  18. package/dist/client/assets/ResearchView-CERNf7sJ.js +1 -0
  19. package/dist/client/assets/{SettingsModal-yRqM4DV8.js → SettingsModal-B1r0yASu.js} +1 -1
  20. package/dist/client/assets/SettingsModal-BLsac7CJ.js +31 -0
  21. package/dist/client/assets/SettingsModal-Cis-4Lot.css +1 -0
  22. package/dist/client/assets/{SetupWizardModal-uUZk3TKT.js → SetupWizardModal-D1q548_L.js} +1 -1
  23. package/dist/client/assets/{SkillsView-CP8JX0P_.js → SkillsView-ClLM6u6p.js} +1 -1
  24. package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +1 -0
  25. package/dist/client/assets/StashRecoveryView-ze0pEZ5U.js +1 -0
  26. package/dist/client/assets/{TodoView-DCRIkDZ-.js → TodoView-CTmIfy2M.js} +1 -1
  27. package/dist/client/assets/{dashboard-view-lR7YYmSC.js → dashboard-view-4xAN3yO5.js} +2 -2
  28. package/dist/client/assets/{folder-open-DHjELt8-.js → folder-open-BZuKESeq.js} +1 -1
  29. package/dist/client/assets/index-Bdw6llW6.js +692 -0
  30. package/dist/client/assets/index-CZGlyJuS.css +1 -0
  31. package/dist/client/assets/{star-DYesq1AV.js → star-D75YKEq-.js} +1 -1
  32. package/dist/client/assets/{upload-DTWF3Db5.js → upload-BYYTgWFj.js} +1 -1
  33. package/dist/client/assets/{users--syrel4l.js → users-RS90Aii3.js} +1 -1
  34. package/dist/client/index.html +2 -2
  35. package/dist/client/version.json +1 -1
  36. package/dist/droid-cli/package.json +1 -1
  37. package/dist/extension.js +5640 -3618
  38. package/dist/pi-claude-cli/package.json +1 -1
  39. package/dist/plugins/fusion-plugin-cli-printing-press/manifest.json +6 -0
  40. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +26 -0
  41. package/dist/plugins/fusion-plugin-cli-printing-press/src/__tests__/manifest.test.ts +20 -0
  42. package/dist/plugins/fusion-plugin-cli-printing-press/src/index.ts +14 -0
  43. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +9 -11
  44. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +30 -0
  46. package/dist/plugins/fusion-plugin-dependency-graph/package.json +3 -28
  47. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +899 -895
  48. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +68 -71
  50. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  51. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +47 -50
  52. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  53. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +155 -109
  54. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  55. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  56. package/dist/plugins/fusion-plugin-reports/src/index.ts +49 -3
  57. package/dist/plugins/fusion-plugin-reports/src/report-schema.ts +38 -0
  58. package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-schema.test.ts +66 -0
  59. package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-store.test.ts +177 -0
  60. package/dist/plugins/fusion-plugin-reports/src/store/report-store.ts +341 -0
  61. package/dist/plugins/fusion-plugin-reports/src/store/report-types.ts +77 -0
  62. package/dist/plugins/fusion-plugin-roadmap/{src/dashboard/RoadmapsView.css → bundled.css} +13 -219
  63. package/dist/plugins/fusion-plugin-roadmap/bundled.js +29535 -0
  64. package/dist/plugins/fusion-plugin-roadmap/package.json +4 -41
  65. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  66. package/package.json +2 -3
  67. package/dist/client/assets/AgentDetailView-gy_5SUj2.js +0 -18
  68. package/dist/client/assets/ChatView-B_-B8fqu.js +0 -1
  69. package/dist/client/assets/MemoryView-CKElJY_3.js +0 -2
  70. package/dist/client/assets/MemoryView-DiajLXby.css +0 -1
  71. package/dist/client/assets/PluginManager-CfW55BF4.js +0 -1
  72. package/dist/client/assets/ResearchView-B256Lr8I.js +0 -1
  73. package/dist/client/assets/SettingsModal-BeA_nQtW.js +0 -31
  74. package/dist/client/assets/SettingsModal-DzsLquBu.css +0 -1
  75. package/dist/client/assets/index-CQyVRLOb.js +0 -692
  76. package/dist/client/assets/index-CxA2Nn0_.css +0 -1
  77. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.css +0 -58
  78. package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.tsx +0 -301
  79. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphHighlight.css +0 -27
  80. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.css +0 -157
  81. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx +0 -126
  82. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.css +0 -35
  83. package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.tsx +0 -36
  84. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.highlighting.test.tsx +0 -112
  85. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.persistence.test.tsx +0 -115
  86. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.test.tsx +0 -128
  87. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.drag.test.tsx +0 -82
  88. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.test.tsx +0 -307
  89. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphToolbar.test.tsx +0 -60
  90. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/edges.test.tsx +0 -75
  91. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filtering.test.tsx +0 -62
  92. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filters.test.ts +0 -78
  93. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/graphPositionStorage.test.ts +0 -95
  94. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/host-integration.test.ts +0 -74
  95. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/index.test.ts +0 -58
  96. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/interactions.test.tsx +0 -121
  97. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/layout.test.ts +0 -70
  98. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/persistence.test.tsx +0 -89
  99. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts +0 -86
  100. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphInteraction.test.ts +0 -167
  101. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphPositions.test.ts +0 -66
  102. package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useNodeDrag.test.ts +0 -81
  103. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-interop.d.ts +0 -35
  104. package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx +0 -19
  105. package/dist/plugins/fusion-plugin-dependency-graph/src/edges.tsx +0 -70
  106. package/dist/plugins/fusion-plugin-dependency-graph/src/filters.ts +0 -8
  107. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/__tests__/useDependencyChain.test.ts +0 -53
  108. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useDependencyChain.ts +0 -60
  109. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useGraphPositions.ts +0 -45
  110. package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useNodeDrag.ts +0 -114
  111. package/dist/plugins/fusion-plugin-dependency-graph/src/index.ts +0 -24
  112. package/dist/plugins/fusion-plugin-dependency-graph/src/layout.ts +0 -91
  113. package/dist/plugins/fusion-plugin-dependency-graph/src/styles/drag.css +0 -15
  114. package/dist/plugins/fusion-plugin-dependency-graph/src/types.ts +0 -21
  115. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphData.ts +0 -17
  116. package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphInteraction.ts +0 -292
  117. package/dist/plugins/fusion-plugin-dependency-graph/src/utils/graphPositionStorage.ts +0 -65
  118. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/api-client.test.ts +0 -101
  119. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/index.test.ts +0 -92
  120. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-routes.test.ts +0 -48
  121. package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-suggestions.test.ts +0 -31
  122. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.tsx +0 -2559
  123. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/RoadmapsView.test.tsx +0 -1144
  124. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/useRoadmaps.test.ts +0 -1756
  125. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/api.ts +0 -70
  126. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/test-setup.ts +0 -7
  127. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/types.ts +0 -1
  128. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useConfirm.ts +0 -8
  129. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useRoadmaps.ts +0 -1188
  130. package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useViewportMode.ts +0 -20
  131. package/dist/plugins/fusion-plugin-roadmap/src/dashboard-view.tsx +0 -6
  132. package/dist/plugins/fusion-plugin-roadmap/src/index.ts +0 -74
  133. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-routes.ts +0 -1
  134. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-schema.ts +0 -41
  135. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.d.ts +0 -15
  136. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.ts +0 -15
  137. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts +0 -283
  138. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts.map +0 -1
  139. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js +0 -21
  140. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js.map +0 -1
  141. package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.ts +0 -310
  142. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts +0 -5
  143. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts.map +0 -1
  144. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js +0 -361
  145. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js.map +0 -1
  146. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.ts +0 -408
  147. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts +0 -68
  148. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts.map +0 -1
  149. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js +0 -300
  150. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js.map +0 -1
  151. package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.ts +0 -381
  152. package/dist/plugins/fusion-plugin-roadmap/src/server/index.d.ts +0 -3
  153. package/dist/plugins/fusion-plugin-roadmap/src/server/index.ts +0 -1
  154. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-handoff.test.ts +0 -445
  155. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-ordering.test.ts +0 -334
  156. package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-store.test.ts +0 -1318
  157. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-handoff.ts +0 -163
  158. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts +0 -37
  159. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts.map +0 -1
  160. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js +0 -188
  161. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js.map +0 -1
  162. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.ts +0 -311
  163. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts +0 -299
  164. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts.map +0 -1
  165. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js +0 -765
  166. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js.map +0 -1
  167. package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.ts +0 -1001
@@ -1,311 +0,0 @@
1
- import type {
2
- RoadmapFeature,
3
- RoadmapFeatureMoveInput,
4
- RoadmapFeatureMoveResult,
5
- RoadmapFeatureReorderInput,
6
- RoadmapMilestone,
7
- RoadmapMilestoneReorderInput,
8
- } from "../roadmap-types.js";
9
-
10
- /**
11
- * Pure ordering helpers for the standalone roadmap model.
12
- *
13
- * Ordering invariants enforced by this module:
14
- * - helpers operate on scoped arrays (single roadmap for milestones, single
15
- * milestone for feature reorders, source+target milestones for feature moves)
16
- * - normalized `orderIndex` values are always contiguous + 0-based
17
- * - when stored order data is conflicting, helpers repair deterministically via
18
- * `orderIndex ASC`, `createdAt ASC`, `id ASC`
19
- * - explicit reorder helpers reject partial or duplicate ID lists instead of
20
- * guessing user intent
21
- */
22
-
23
- interface OrderedEntity {
24
- id: string;
25
- orderIndex: number;
26
- createdAt: string;
27
- }
28
-
29
- function compareOrderedEntities<T extends OrderedEntity>(a: T, b: T): number {
30
- if (a.orderIndex !== b.orderIndex) {
31
- return a.orderIndex - b.orderIndex;
32
- }
33
-
34
- if (a.createdAt !== b.createdAt) {
35
- return a.createdAt.localeCompare(b.createdAt);
36
- }
37
-
38
- return a.id.localeCompare(b.id);
39
- }
40
-
41
- function clampInsertionIndex(targetIndex: number, length: number): number {
42
- if (!Number.isFinite(targetIndex)) {
43
- return length;
44
- }
45
-
46
- const normalized = Math.trunc(targetIndex);
47
- if (normalized < 0) {
48
- return 0;
49
- }
50
- if (normalized > length) {
51
- return length;
52
- }
53
- return normalized;
54
- }
55
-
56
- function assertScopedRoadmapMilestones(
57
- milestones: readonly RoadmapMilestone[],
58
- roadmapId: string,
59
- ): void {
60
- for (const milestone of milestones) {
61
- if (milestone.roadmapId !== roadmapId) {
62
- throw new Error(
63
- `Milestone ${milestone.id} does not belong to roadmap ${roadmapId}`,
64
- );
65
- }
66
- }
67
- }
68
-
69
- function assertScopedMilestoneFeatures(
70
- features: readonly RoadmapFeature[],
71
- milestoneId: string,
72
- ): void {
73
- for (const feature of features) {
74
- if (feature.milestoneId !== milestoneId) {
75
- throw new Error(
76
- `Feature ${feature.id} does not belong to milestone ${milestoneId}`,
77
- );
78
- }
79
- }
80
- }
81
-
82
- function assertScopedMoveFeatures(
83
- features: readonly RoadmapFeature[],
84
- fromMilestoneId: string,
85
- toMilestoneId: string,
86
- ): void {
87
- const validMilestoneIds = new Set([fromMilestoneId, toMilestoneId]);
88
-
89
- for (const feature of features) {
90
- if (!validMilestoneIds.has(feature.milestoneId)) {
91
- throw new Error(
92
- `Feature ${feature.id} is outside the affected milestone scope (${fromMilestoneId} → ${toMilestoneId})`,
93
- );
94
- }
95
- }
96
- }
97
-
98
- function assertExactIdSet(
99
- entityLabel: string,
100
- actualIds: readonly string[],
101
- orderedIds: readonly string[],
102
- ): void {
103
- const requestedIds = new Set<string>();
104
-
105
- for (const id of orderedIds) {
106
- if (requestedIds.has(id)) {
107
- throw new Error(`Duplicate ${entityLabel} id in requested order: ${id}`);
108
- }
109
- requestedIds.add(id);
110
- }
111
-
112
- if (actualIds.length !== orderedIds.length) {
113
- throw new Error(
114
- `Expected ${actualIds.length} ${entityLabel} ids but received ${orderedIds.length}`,
115
- );
116
- }
117
-
118
- const actualIdSet = new Set(actualIds);
119
-
120
- for (const id of orderedIds) {
121
- if (!actualIdSet.has(id)) {
122
- throw new Error(`${capitalize(entityLabel)} ${id} not found in scoped list`);
123
- }
124
- }
125
-
126
- for (const id of actualIds) {
127
- if (!requestedIds.has(id)) {
128
- throw new Error(`Missing ${entityLabel} id in requested order: ${id}`);
129
- }
130
- }
131
- }
132
-
133
- function capitalize(value: string): string {
134
- return value.charAt(0).toUpperCase() + value.slice(1);
135
- }
136
-
137
- function assignContiguousOrder<T extends OrderedEntity>(items: readonly T[]): T[] {
138
- return items.map((item, orderIndex) => {
139
- if (item.orderIndex === orderIndex) {
140
- return { ...item };
141
- }
142
-
143
- return {
144
- ...item,
145
- orderIndex,
146
- };
147
- });
148
- }
149
-
150
- /**
151
- * Repairs milestone ordering for a single roadmap scope.
152
- *
153
- * Deterministic repair order is `orderIndex ASC`, `createdAt ASC`, then `id ASC`.
154
- */
155
- export function normalizeRoadmapMilestoneOrder(
156
- milestones: readonly RoadmapMilestone[],
157
- ): RoadmapMilestone[] {
158
- if (milestones.length === 0) {
159
- return [];
160
- }
161
-
162
- assertScopedRoadmapMilestones(milestones, milestones[0].roadmapId);
163
-
164
- return assignContiguousOrder(
165
- [...milestones].sort(compareOrderedEntities),
166
- );
167
- }
168
-
169
- /**
170
- * Applies an explicit milestone reorder for a single roadmap scope.
171
- *
172
- * The caller must provide the complete milestone ID set exactly once. Partial
173
- * or duplicate lists are rejected to keep reorders deterministic.
174
- */
175
- export function applyRoadmapMilestoneReorder(
176
- milestones: readonly RoadmapMilestone[],
177
- input: RoadmapMilestoneReorderInput,
178
- ): RoadmapMilestone[] {
179
- assertScopedRoadmapMilestones(milestones, input.roadmapId);
180
-
181
- const normalized = normalizeRoadmapMilestoneOrder(milestones);
182
- const ids = normalized.map((milestone) => milestone.id);
183
- assertExactIdSet("milestone", ids, input.orderedMilestoneIds);
184
-
185
- const byId = new Map(normalized.map((milestone) => [milestone.id, milestone]));
186
- return assignContiguousOrder(
187
- input.orderedMilestoneIds.map((id) => byId.get(id)!),
188
- );
189
- }
190
-
191
- /**
192
- * Repairs feature ordering for a single milestone scope.
193
- *
194
- * Deterministic repair order is `orderIndex ASC`, `createdAt ASC`, then `id ASC`.
195
- */
196
- export function normalizeRoadmapFeatureOrder(
197
- features: readonly RoadmapFeature[],
198
- ): RoadmapFeature[] {
199
- if (features.length === 0) {
200
- return [];
201
- }
202
-
203
- assertScopedMilestoneFeatures(features, features[0].milestoneId);
204
-
205
- return assignContiguousOrder(
206
- [...features].sort(compareOrderedEntities),
207
- );
208
- }
209
-
210
- /**
211
- * Applies an explicit feature reorder for a single milestone scope.
212
- *
213
- * The caller must provide the complete feature ID set exactly once. Partial or
214
- * duplicate lists are rejected to keep reorder behavior deterministic.
215
- */
216
- export function applyRoadmapFeatureReorder(
217
- features: readonly RoadmapFeature[],
218
- input: RoadmapFeatureReorderInput,
219
- ): RoadmapFeature[] {
220
- assertScopedMilestoneFeatures(features, input.milestoneId);
221
-
222
- const normalized = normalizeRoadmapFeatureOrder(features);
223
- const ids = normalized.map((feature) => feature.id);
224
- assertExactIdSet("feature", ids, input.orderedFeatureIds);
225
-
226
- const byId = new Map(normalized.map((feature) => [feature.id, feature]));
227
- return assignContiguousOrder(
228
- input.orderedFeatureIds.map((id) => byId.get(id)!),
229
- );
230
- }
231
-
232
- /**
233
- * Moves a feature within the affected milestone scope and deterministically
234
- * normalizes both source and destination order.
235
- *
236
- * For cross-milestone moves, pass the combined feature list from the source and
237
- * target milestones. For within-milestone moves, pass the current milestone's
238
- * feature list. `targetOrderIndex` is clamped into the destination range.
239
- */
240
- export function moveRoadmapFeature(
241
- features: readonly RoadmapFeature[],
242
- input: RoadmapFeatureMoveInput,
243
- ): RoadmapFeatureMoveResult {
244
- assertScopedMoveFeatures(features, input.fromMilestoneId, input.toMilestoneId);
245
-
246
- const existingFeature = features.find((feature) => feature.id === input.featureId);
247
- if (!existingFeature) {
248
- throw new Error(`Feature ${input.featureId} not found in affected milestone scope`);
249
- }
250
-
251
- if (existingFeature.milestoneId !== input.fromMilestoneId) {
252
- throw new Error(
253
- `Feature ${input.featureId} does not belong to milestone ${input.fromMilestoneId}`,
254
- );
255
- }
256
-
257
- const sourceFeatures = normalizeRoadmapFeatureOrder(
258
- features.filter((feature) => feature.milestoneId === input.fromMilestoneId),
259
- );
260
- const sourceWithoutFeature = sourceFeatures.filter(
261
- (feature) => feature.id !== input.featureId,
262
- );
263
-
264
- if (input.fromMilestoneId === input.toMilestoneId) {
265
- const insertionIndex = clampInsertionIndex(
266
- input.targetOrderIndex,
267
- sourceWithoutFeature.length,
268
- );
269
- const reordered = [...sourceWithoutFeature];
270
- reordered.splice(insertionIndex, 0, {
271
- ...existingFeature,
272
- milestoneId: input.toMilestoneId,
273
- orderIndex: insertionIndex,
274
- });
275
-
276
- const normalized = assignContiguousOrder(reordered);
277
- const movedFeature = normalized.find((feature) => feature.id === input.featureId)!;
278
-
279
- return {
280
- movedFeature,
281
- affectedFeatures: normalized,
282
- sourceMilestoneFeatures: normalized,
283
- targetMilestoneFeatures: normalized,
284
- };
285
- }
286
-
287
- const targetFeatures = normalizeRoadmapFeatureOrder(
288
- features.filter((feature) => feature.milestoneId === input.toMilestoneId),
289
- );
290
- const insertionIndex = clampInsertionIndex(
291
- input.targetOrderIndex,
292
- targetFeatures.length,
293
- );
294
- const targetWithInsertedFeature = [...targetFeatures];
295
- targetWithInsertedFeature.splice(insertionIndex, 0, {
296
- ...existingFeature,
297
- milestoneId: input.toMilestoneId,
298
- orderIndex: insertionIndex,
299
- });
300
-
301
- const normalizedSource = assignContiguousOrder(sourceWithoutFeature);
302
- const normalizedTarget = assignContiguousOrder(targetWithInsertedFeature);
303
- const movedFeature = normalizedTarget.find((feature) => feature.id === input.featureId)!;
304
-
305
- return {
306
- movedFeature,
307
- affectedFeatures: [...normalizedSource, ...normalizedTarget],
308
- sourceMilestoneFeatures: normalizedSource,
309
- targetMilestoneFeatures: normalizedTarget,
310
- };
311
- }
@@ -1,299 +0,0 @@
1
- /**
2
- * RoadmapStore - Data layer for standalone roadmap persistence.
3
- *
4
- * Manages CRUD operations for roadmaps, milestones, and features.
5
- * Provides deterministic ordering via covering indexes and atomic reorder/move operations.
6
- *
7
- * Ordering invariants:
8
- * - milestone ordering is scoped to a single roadmap and must be contiguous + 0-based
9
- * - feature ordering is scoped to a single milestone and must be contiguous + 0-based
10
- * - all list/read queries use deterministic ordering: ORDER BY orderIndex ASC, createdAt ASC, id ASC
11
- * - cross-milestone feature moves atomically renumber both affected milestone scopes
12
- */
13
- import { EventEmitter } from "node:events";
14
- import type { Database } from "@fusion/core";
15
- import type { Roadmap, RoadmapMilestone, RoadmapFeature, RoadmapCreateInput, RoadmapUpdateInput, RoadmapMilestoneCreateInput, RoadmapMilestoneUpdateInput, RoadmapFeatureCreateInput, RoadmapFeatureUpdateInput, RoadmapMilestoneReorderInput, RoadmapFeatureReorderInput, RoadmapFeatureMoveInput, RoadmapMilestoneWithFeatures, RoadmapWithHierarchy, RoadmapExportBundle, RoadmapMissionPlanningHandoff, RoadmapFeatureTaskPlanningHandoff } from "../roadmap-types.js";
16
- export interface RoadmapStoreEvents {
17
- /** Emitted when a roadmap is created */
18
- "roadmap:created": [Roadmap];
19
- /** Emitted when a roadmap is updated */
20
- "roadmap:updated": [Roadmap];
21
- /** Emitted when a roadmap is deleted */
22
- "roadmap:deleted": [string];
23
- /** Emitted when a milestone is created */
24
- "milestone:created": [RoadmapMilestone];
25
- /** Emitted when a milestone is updated */
26
- "milestone:updated": [RoadmapMilestone];
27
- /** Emitted when a milestone is deleted */
28
- "milestone:deleted": [string];
29
- /** Emitted when a milestone is reordered */
30
- "milestone:reordered": [{
31
- roadmapId: string;
32
- milestones: RoadmapMilestone[];
33
- }];
34
- /** Emitted when a feature is created */
35
- "feature:created": [RoadmapFeature];
36
- /** Emitted when a feature is updated */
37
- "feature:updated": [RoadmapFeature];
38
- /** Emitted when a feature is deleted */
39
- "feature:deleted": [RoadmapFeature];
40
- /** Emitted when features are reordered within a milestone */
41
- "feature:reordered": [{
42
- milestoneId: string;
43
- features: RoadmapFeature[];
44
- }];
45
- /** Emitted when a feature is moved (including cross-milestone moves) */
46
- "feature:moved": [{
47
- feature: RoadmapFeature;
48
- fromMilestoneId: string;
49
- toMilestoneId: string;
50
- }];
51
- }
52
- export declare class RoadmapStore extends EventEmitter<RoadmapStoreEvents> {
53
- private db;
54
- /**
55
- * Creates a new RoadmapStore instance.
56
- *
57
- * @param db - Shared Database instance (same instance used by TaskStore)
58
- */
59
- constructor(db: Database);
60
- private ensureSchema;
61
- private generateRoadmapId;
62
- private generateMilestoneId;
63
- private generateFeatureId;
64
- private rowToRoadmap;
65
- private rowToMilestone;
66
- private rowToFeature;
67
- /**
68
- * Create a new roadmap.
69
- *
70
- * @param input - Roadmap creation input
71
- * @returns The created roadmap
72
- */
73
- createRoadmap(input: RoadmapCreateInput): Roadmap;
74
- /**
75
- * Get a roadmap by ID.
76
- *
77
- * @param id - Roadmap ID
78
- * @returns The roadmap, or undefined if not found
79
- */
80
- getRoadmap(id: string): Roadmap | undefined;
81
- /**
82
- * List all roadmaps, ordered by creation date (newest first).
83
- *
84
- * @returns Array of roadmaps
85
- */
86
- listRoadmaps(): Roadmap[];
87
- /**
88
- * Update a roadmap.
89
- *
90
- * @param id - Roadmap ID
91
- * @param updates - Partial roadmap updates
92
- * @returns The updated roadmap
93
- * @throws Error if roadmap not found
94
- */
95
- updateRoadmap(id: string, updates: RoadmapUpdateInput): Roadmap;
96
- /**
97
- * Delete a roadmap and all its milestones/features (cascading).
98
- *
99
- * @param id - Roadmap ID
100
- * @throws Error if roadmap not found
101
- */
102
- deleteRoadmap(id: string): void;
103
- /**
104
- * Add a milestone to a roadmap.
105
- * Automatically computes the orderIndex (max + 1).
106
- *
107
- * @param roadmapId - Parent roadmap ID
108
- * @param input - Milestone creation input
109
- * @returns The created milestone
110
- * @throws Error if roadmap not found
111
- */
112
- createMilestone(roadmapId: string, input: RoadmapMilestoneCreateInput): RoadmapMilestone;
113
- /**
114
- * Get a milestone by ID.
115
- *
116
- * @param id - Milestone ID
117
- * @returns The milestone, or undefined if not found
118
- */
119
- getMilestone(id: string): RoadmapMilestone | undefined;
120
- /**
121
- * List milestones for a roadmap, ordered deterministically.
122
- *
123
- * Uses deterministic ordering: ORDER BY orderIndex ASC, createdAt ASC, id ASC
124
- * to ensure consistent results when stored order data is incomplete or conflicting.
125
- *
126
- * @param roadmapId - Roadmap ID
127
- * @returns Array of milestones in deterministic order
128
- */
129
- listMilestones(roadmapId: string): RoadmapMilestone[];
130
- /**
131
- * Update a milestone.
132
- *
133
- * @param id - Milestone ID
134
- * @param updates - Partial milestone updates
135
- * @returns The updated milestone
136
- * @throws Error if milestone not found
137
- */
138
- updateMilestone(id: string, updates: RoadmapMilestoneUpdateInput): RoadmapMilestone;
139
- /**
140
- * Delete a milestone and all its features (cascading).
141
- *
142
- * @param id - Milestone ID
143
- * @throws Error if milestone not found
144
- */
145
- deleteMilestone(id: string): void;
146
- /**
147
- * Add a feature to a milestone.
148
- * Automatically computes the orderIndex (max + 1).
149
- *
150
- * @param milestoneId - Parent milestone ID
151
- * @param input - Feature creation input
152
- * @returns The created feature
153
- * @throws Error if milestone not found
154
- */
155
- createFeature(milestoneId: string, input: RoadmapFeatureCreateInput): RoadmapFeature;
156
- /**
157
- * Get a feature by ID.
158
- *
159
- * @param id - Feature ID
160
- * @returns The feature, or undefined if not found
161
- */
162
- getFeature(id: string): RoadmapFeature | undefined;
163
- /**
164
- * List features for a milestone, ordered deterministically.
165
- *
166
- * Uses deterministic ordering: ORDER BY orderIndex ASC, createdAt ASC, id ASC
167
- * to ensure consistent results when stored order data is incomplete or conflicting.
168
- *
169
- * @param milestoneId - Milestone ID
170
- * @returns Array of features in deterministic order
171
- */
172
- listFeatures(milestoneId: string): RoadmapFeature[];
173
- /**
174
- * Update a feature.
175
- *
176
- * @param id - Feature ID
177
- * @param updates - Partial feature updates
178
- * @returns The updated feature
179
- * @throws Error if feature not found
180
- */
181
- updateFeature(id: string, updates: RoadmapFeatureUpdateInput): RoadmapFeature;
182
- /**
183
- * Delete a feature.
184
- *
185
- * @param id - Feature ID
186
- * @throws Error if feature not found
187
- */
188
- deleteFeature(id: string): void;
189
- /**
190
- * Reorder milestones within a roadmap.
191
- *
192
- * Applies an explicit reorder input and persists the full normalized order.
193
- * The input must contain all milestone IDs exactly once.
194
- *
195
- * @param input - Reorder input with complete milestone ID list
196
- * @returns The reordered milestones in their new order
197
- * @throws Error if milestone set is incomplete, duplicate, or not found
198
- */
199
- reorderMilestones(input: RoadmapMilestoneReorderInput): RoadmapMilestone[];
200
- /**
201
- * Reorder features within a milestone.
202
- *
203
- * Applies an explicit reorder input and persists the full normalized order.
204
- * The input must contain all feature IDs for the milestone exactly once.
205
- *
206
- * @param input - Reorder input with complete feature ID list
207
- * @returns The reordered features in their new order
208
- * @throws Error if feature set is incomplete, duplicate, or not found
209
- */
210
- reorderFeatures(input: RoadmapFeatureReorderInput): RoadmapFeature[];
211
- /**
212
- * Move a feature, including cross-milestone moves.
213
- *
214
- * Atomically renumbers both the source and destination milestone scopes.
215
- *
216
- * @param input - Move input with source/destination milestone info
217
- * @returns The moved feature and both affected milestone feature lists
218
- * @throws Error if feature or milestone not found, or scope validation fails
219
- */
220
- moveFeature(input: RoadmapFeatureMoveInput): {
221
- movedFeature: RoadmapFeature;
222
- sourceMilestoneFeatures: RoadmapFeature[];
223
- targetMilestoneFeatures: RoadmapFeature[];
224
- };
225
- /**
226
- * Get a milestone with all of its features in deterministic order.
227
- *
228
- * @param id - Milestone ID
229
- * @returns The milestone with features, or undefined if not found
230
- */
231
- getMilestoneWithFeatures(id: string): RoadmapMilestoneWithFeatures | undefined;
232
- /**
233
- * Get a roadmap with its full hierarchy (milestones → features).
234
- *
235
- * @param id - Roadmap ID
236
- * @returns The roadmap with hierarchy, or undefined if not found
237
- */
238
- getRoadmapWithHierarchy(id: string): RoadmapWithHierarchy | undefined;
239
- /**
240
- * Get a flat export bundle for a roadmap.
241
- *
242
- * Returns all roadmap data in a flat structure suitable for persistence,
243
- * APIs, import/export, and sync jobs. Entities are separated so downstream
244
- * persistence layers can upsert by table/collection.
245
- *
246
- * @param roadmapId - Roadmap ID
247
- * @returns The export bundle with ordered entities
248
- * @throws Error if roadmap not found
249
- */
250
- getRoadmapExport(roadmapId: string): RoadmapExportBundle;
251
- /**
252
- * Get a mission planning handoff payload for a roadmap.
253
- *
254
- * Converts the roadmap into a mission planning structure while preserving
255
- * source IDs and deterministic order. Does not couple to MissionStore internals.
256
- *
257
- * @param roadmapId - Roadmap ID
258
- * @returns The mission planning handoff payload
259
- * @throws Error if roadmap not found
260
- */
261
- getRoadmapMissionHandoff(roadmapId: string): RoadmapMissionPlanningHandoff;
262
- /**
263
- * Get a task planning handoff payload for a single roadmap feature.
264
- *
265
- * Returns a self-contained handoff payload for converting a roadmap feature
266
- * into task planning flows without coupling to MissionStore internals.
267
- *
268
- * @param roadmapId - Parent roadmap ID (for validation)
269
- * @param milestoneId - Parent milestone ID (for validation)
270
- * @param featureId - Feature ID to generate handoff for
271
- * @returns The task planning handoff payload
272
- * @throws Error if any entity is not found or if ownership validation fails
273
- */
274
- getRoadmapFeatureHandoff(roadmapId: string, milestoneId: string, featureId: string): RoadmapFeatureTaskPlanningHandoff;
275
- /**
276
- * Get a mission planning handoff payload for a roadmap.
277
- *
278
- * Alias for getRoadmapMissionHandoff() for API consistency.
279
- * Converts the roadmap into a mission planning structure while preserving
280
- * source IDs and deterministic order.
281
- *
282
- * @param roadmapId - Roadmap ID
283
- * @returns The mission planning handoff payload
284
- * @throws Error if roadmap not found
285
- */
286
- getMissionPlanningHandoff(roadmapId: string): RoadmapMissionPlanningHandoff;
287
- /**
288
- * List all task planning handoff payloads for a roadmap.
289
- *
290
- * Returns a flat list of all feature handoffs in deterministic order
291
- * (milestone order index, then feature order index).
292
- *
293
- * @param roadmapId - Roadmap ID
294
- * @returns Array of task planning handoff payloads for all features
295
- * @throws Error if roadmap not found
296
- */
297
- listFeatureTaskPlanningHandoffs(roadmapId: string): RoadmapFeatureTaskPlanningHandoff[];
298
- }
299
- //# sourceMappingURL=roadmap-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"roadmap-store.d.ts","sourceRoot":"","sources":["roadmap-store.ts"],"names":[],"mappings":"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"}