@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.
- package/README.md +6 -0
- package/dist/bin.js +18646 -15669
- package/dist/client/assets/AgentDetailView-Cv-vgOj3.js +18 -0
- package/dist/client/assets/{AgentsView-BkB9FiMT.js → AgentsView-D6Zi5zfP.js} +4 -4
- package/dist/client/assets/ChatView-CAHjY9uO.js +1 -0
- package/dist/client/assets/{DevServerView-BkvtjZBa.js → DevServerView--_WBvIDQ.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BK-KbnhP.js → DirectoryPicker-xedtR-Rd.js} +1 -1
- package/dist/client/assets/{DocumentsView-BEg1CQAk.js → DocumentsView-Bg2oaZks.js} +1 -1
- package/dist/client/assets/{EvalsView-Berf9bQm.js → EvalsView-B3uOCXfr.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-jcInE50G.js → ExperimentalAgentOnboardingModal-Bx6yXVS5.js} +1 -1
- package/dist/client/assets/{InsightsView-BX5bSF1J.js → InsightsView-Q1zvtF4F.js} +1 -1
- package/dist/client/assets/MemoryView-xcN_eouf.js +2 -0
- package/dist/client/assets/MemoryView-zaXewZzi.css +1 -0
- package/dist/client/assets/{NodesView-DLUOBLf6.js → NodesView-RxXg58_Q.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-COlJf0Kx.js → PiExtensionsManager-Cc8aAZXg.js} +2 -2
- package/dist/client/assets/PluginManager-BEkyBajl.js +1 -0
- package/dist/client/assets/{ResearchView-BzCcDAS4.css → ResearchView-BEI4ZSGs.css} +1 -1
- package/dist/client/assets/ResearchView-CERNf7sJ.js +1 -0
- package/dist/client/assets/{SettingsModal-yRqM4DV8.js → SettingsModal-B1r0yASu.js} +1 -1
- package/dist/client/assets/SettingsModal-BLsac7CJ.js +31 -0
- package/dist/client/assets/SettingsModal-Cis-4Lot.css +1 -0
- package/dist/client/assets/{SetupWizardModal-uUZk3TKT.js → SetupWizardModal-D1q548_L.js} +1 -1
- package/dist/client/assets/{SkillsView-CP8JX0P_.js → SkillsView-ClLM6u6p.js} +1 -1
- package/dist/client/assets/StashRecoveryView-B_8WIQEo.css +1 -0
- package/dist/client/assets/StashRecoveryView-ze0pEZ5U.js +1 -0
- package/dist/client/assets/{TodoView-DCRIkDZ-.js → TodoView-CTmIfy2M.js} +1 -1
- package/dist/client/assets/{dashboard-view-lR7YYmSC.js → dashboard-view-4xAN3yO5.js} +2 -2
- package/dist/client/assets/{folder-open-DHjELt8-.js → folder-open-BZuKESeq.js} +1 -1
- package/dist/client/assets/index-Bdw6llW6.js +692 -0
- package/dist/client/assets/index-CZGlyJuS.css +1 -0
- package/dist/client/assets/{star-DYesq1AV.js → star-D75YKEq-.js} +1 -1
- package/dist/client/assets/{upload-DTWF3Db5.js → upload-BYYTgWFj.js} +1 -1
- package/dist/client/assets/{users--syrel4l.js → users-RS90Aii3.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +5640 -3618
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/manifest.json +6 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +26 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/src/__tests__/manifest.test.ts +20 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/src/index.ts +14 -0
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +9 -11
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +30 -0
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +3 -28
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +899 -895
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +68 -71
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +47 -50
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +155 -109
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/src/index.ts +49 -3
- package/dist/plugins/fusion-plugin-reports/src/report-schema.ts +38 -0
- package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-schema.test.ts +66 -0
- package/dist/plugins/fusion-plugin-reports/src/store/__tests__/report-store.test.ts +177 -0
- package/dist/plugins/fusion-plugin-reports/src/store/report-store.ts +341 -0
- package/dist/plugins/fusion-plugin-reports/src/store/report-types.ts +77 -0
- package/dist/plugins/fusion-plugin-roadmap/{src/dashboard/RoadmapsView.css → bundled.css} +13 -219
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +29535 -0
- package/dist/plugins/fusion-plugin-roadmap/package.json +4 -41
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +2 -3
- package/dist/client/assets/AgentDetailView-gy_5SUj2.js +0 -18
- package/dist/client/assets/ChatView-B_-B8fqu.js +0 -1
- package/dist/client/assets/MemoryView-CKElJY_3.js +0 -2
- package/dist/client/assets/MemoryView-DiajLXby.css +0 -1
- package/dist/client/assets/PluginManager-CfW55BF4.js +0 -1
- package/dist/client/assets/ResearchView-B256Lr8I.js +0 -1
- package/dist/client/assets/SettingsModal-BeA_nQtW.js +0 -31
- package/dist/client/assets/SettingsModal-DzsLquBu.css +0 -1
- package/dist/client/assets/index-CQyVRLOb.js +0 -692
- package/dist/client/assets/index-CxA2Nn0_.css +0 -1
- package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.css +0 -58
- package/dist/plugins/fusion-plugin-dependency-graph/src/DependencyGraph.tsx +0 -301
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphHighlight.css +0 -27
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.css +0 -157
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx +0 -126
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.css +0 -35
- package/dist/plugins/fusion-plugin-dependency-graph/src/GraphToolbar.tsx +0 -36
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.highlighting.test.tsx +0 -112
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.persistence.test.tsx +0 -115
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/DependencyGraph.test.tsx +0 -128
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.drag.test.tsx +0 -82
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphTaskNode.test.tsx +0 -307
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/GraphToolbar.test.tsx +0 -60
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/edges.test.tsx +0 -75
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filtering.test.tsx +0 -62
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/filters.test.ts +0 -78
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/graphPositionStorage.test.ts +0 -95
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/host-integration.test.ts +0 -74
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/index.test.ts +0 -58
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/interactions.test.tsx +0 -121
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/layout.test.ts +0 -70
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/persistence.test.tsx +0 -89
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphData.test.ts +0 -86
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphInteraction.test.ts +0 -167
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useGraphPositions.test.ts +0 -66
- package/dist/plugins/fusion-plugin-dependency-graph/src/__tests__/useNodeDrag.test.ts +0 -81
- package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-interop.d.ts +0 -35
- package/dist/plugins/fusion-plugin-dependency-graph/src/dashboard-view.tsx +0 -19
- package/dist/plugins/fusion-plugin-dependency-graph/src/edges.tsx +0 -70
- package/dist/plugins/fusion-plugin-dependency-graph/src/filters.ts +0 -8
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/__tests__/useDependencyChain.test.ts +0 -53
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useDependencyChain.ts +0 -60
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useGraphPositions.ts +0 -45
- package/dist/plugins/fusion-plugin-dependency-graph/src/hooks/useNodeDrag.ts +0 -114
- package/dist/plugins/fusion-plugin-dependency-graph/src/index.ts +0 -24
- package/dist/plugins/fusion-plugin-dependency-graph/src/layout.ts +0 -91
- package/dist/plugins/fusion-plugin-dependency-graph/src/styles/drag.css +0 -15
- package/dist/plugins/fusion-plugin-dependency-graph/src/types.ts +0 -21
- package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphData.ts +0 -17
- package/dist/plugins/fusion-plugin-dependency-graph/src/useGraphInteraction.ts +0 -292
- package/dist/plugins/fusion-plugin-dependency-graph/src/utils/graphPositionStorage.ts +0 -65
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/api-client.test.ts +0 -101
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/index.test.ts +0 -92
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-routes.test.ts +0 -48
- package/dist/plugins/fusion-plugin-roadmap/src/__tests__/roadmap-suggestions.test.ts +0 -31
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/RoadmapsView.tsx +0 -2559
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/RoadmapsView.test.tsx +0 -1144
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/__tests__/useRoadmaps.test.ts +0 -1756
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/api.ts +0 -70
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/test-setup.ts +0 -7
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/types.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useConfirm.ts +0 -8
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useRoadmaps.ts +0 -1188
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard/useViewportMode.ts +0 -20
- package/dist/plugins/fusion-plugin-roadmap/src/dashboard-view.tsx +0 -6
- package/dist/plugins/fusion-plugin-roadmap/src/index.ts +0 -74
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-routes.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-schema.ts +0 -41
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.d.ts +0 -15
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-suggestions.ts +0 -15
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts +0 -283
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js +0 -21
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/roadmap-types.ts +0 -310
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts +0 -5
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js +0 -361
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-routes.ts +0 -408
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts +0 -68
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js +0 -300
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/routes/roadmap-suggestions.ts +0 -381
- package/dist/plugins/fusion-plugin-roadmap/src/server/index.d.ts +0 -3
- package/dist/plugins/fusion-plugin-roadmap/src/server/index.ts +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-handoff.test.ts +0 -445
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-ordering.test.ts +0 -334
- package/dist/plugins/fusion-plugin-roadmap/src/store/__tests__/roadmap-store.test.ts +0 -1318
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-handoff.ts +0 -163
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts +0 -37
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js +0 -188
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-ordering.ts +0 -311
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts +0 -299
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.d.ts.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js +0 -765
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.js.map +0 -1
- package/dist/plugins/fusion-plugin-roadmap/src/store/roadmap-store.ts +0 -1001
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for roadmap handoff mapping helpers.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect } from "vitest";
|
|
6
|
-
import {
|
|
7
|
-
mapFeatureToTaskHandoff,
|
|
8
|
-
mapRoadmapToMissionHandoff,
|
|
9
|
-
mapRoadmapWithHierarchyToMissionHandoff,
|
|
10
|
-
mapAllFeaturesToTaskHandoffs,
|
|
11
|
-
} from "../roadmap-handoff.js";
|
|
12
|
-
import { normalizeRoadmapMilestoneOrder } from "../roadmap-ordering.js";
|
|
13
|
-
import type {
|
|
14
|
-
Roadmap,
|
|
15
|
-
RoadmapMilestone,
|
|
16
|
-
RoadmapFeature,
|
|
17
|
-
RoadmapWithHierarchy,
|
|
18
|
-
RoadmapFeatureTaskPlanningHandoff,
|
|
19
|
-
RoadmapMissionPlanningHandoff,
|
|
20
|
-
} from "../../roadmap-types.js";
|
|
21
|
-
|
|
22
|
-
// ── Test Fixtures ─────────────────────────────────────────────────────────────
|
|
23
|
-
|
|
24
|
-
function createRoadmap(overrides: Partial<Roadmap> = {}): Roadmap {
|
|
25
|
-
return {
|
|
26
|
-
id: "RM-001",
|
|
27
|
-
title: "Test Roadmap",
|
|
28
|
-
description: "A test roadmap",
|
|
29
|
-
createdAt: "2024-01-01T00:00:00.000Z",
|
|
30
|
-
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
31
|
-
...overrides,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createMilestone(id: string, roadmapId: string, orderIndex: number, overrides: Partial<RoadmapMilestone> = {}): RoadmapMilestone {
|
|
36
|
-
return {
|
|
37
|
-
id,
|
|
38
|
-
roadmapId,
|
|
39
|
-
title: `Milestone ${id}`,
|
|
40
|
-
description: `Description for ${id}`,
|
|
41
|
-
orderIndex,
|
|
42
|
-
createdAt: "2024-01-01T00:00:00.000Z",
|
|
43
|
-
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
44
|
-
...overrides,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function createFeature(id: string, milestoneId: string, orderIndex: number, overrides: Partial<RoadmapFeature> = {}): RoadmapFeature {
|
|
49
|
-
return {
|
|
50
|
-
id,
|
|
51
|
-
milestoneId,
|
|
52
|
-
title: `Feature ${id}`,
|
|
53
|
-
description: `Description for ${id}`,
|
|
54
|
-
orderIndex,
|
|
55
|
-
createdAt: "2024-01-01T00:00:00.000Z",
|
|
56
|
-
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
57
|
-
...overrides,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// ── Tests for mapFeatureToTaskHandoff ─────────────────────────────────────────
|
|
62
|
-
|
|
63
|
-
describe("mapFeatureToTaskHandoff", () => {
|
|
64
|
-
it("maps a feature to a task planning handoff with all fields", () => {
|
|
65
|
-
const roadmap = createRoadmap();
|
|
66
|
-
const milestone = createMilestone("MS-001", "RM-001", 0);
|
|
67
|
-
const feature = createFeature("F-001", "MS-001", 0);
|
|
68
|
-
|
|
69
|
-
const handoff = mapFeatureToTaskHandoff(roadmap, milestone, feature);
|
|
70
|
-
|
|
71
|
-
expect(handoff.title).toBe("Feature F-001");
|
|
72
|
-
expect(handoff.description).toBe("Description for F-001");
|
|
73
|
-
expect(handoff.source.roadmapId).toBe("RM-001");
|
|
74
|
-
expect(handoff.source.milestoneId).toBe("MS-001");
|
|
75
|
-
expect(handoff.source.featureId).toBe("F-001");
|
|
76
|
-
expect(handoff.source.roadmapTitle).toBe("Test Roadmap");
|
|
77
|
-
expect(handoff.source.milestoneTitle).toBe("Milestone MS-001");
|
|
78
|
-
expect(handoff.source.milestoneOrderIndex).toBe(0);
|
|
79
|
-
expect(handoff.source.featureOrderIndex).toBe(0);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("handles features without descriptions", () => {
|
|
83
|
-
const roadmap = createRoadmap();
|
|
84
|
-
const milestone = createMilestone("MS-001", "RM-001", 0);
|
|
85
|
-
const feature = createFeature("F-001", "MS-001", 0, { description: undefined });
|
|
86
|
-
|
|
87
|
-
const handoff = mapFeatureToTaskHandoff(roadmap, milestone, feature);
|
|
88
|
-
|
|
89
|
-
expect(handoff.title).toBe("Feature F-001");
|
|
90
|
-
expect(handoff.description).toBeUndefined();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("preserves exact IDs from source entities", () => {
|
|
94
|
-
const roadmap = createRoadmap({ id: "RM-SPECIAL-123" });
|
|
95
|
-
const milestone = createMilestone("RMS-SPECIAL-456", "RM-SPECIAL-123", 5);
|
|
96
|
-
const feature = createFeature("RF-SPECIAL-789", "RMS-SPECIAL-456", 3);
|
|
97
|
-
|
|
98
|
-
const handoff = mapFeatureToTaskHandoff(roadmap, milestone, feature);
|
|
99
|
-
|
|
100
|
-
expect(handoff.source.roadmapId).toBe("RM-SPECIAL-123");
|
|
101
|
-
expect(handoff.source.milestoneId).toBe("RMS-SPECIAL-456");
|
|
102
|
-
expect(handoff.source.featureId).toBe("RF-SPECIAL-789");
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// ── Tests for mapRoadmapToMissionHandoff ─────────────────────────────────────
|
|
107
|
-
|
|
108
|
-
describe("mapRoadmapToMissionHandoff", () => {
|
|
109
|
-
it("maps a roadmap with milestones and features to mission handoff", () => {
|
|
110
|
-
const roadmap = createRoadmap({ title: "Q1 Planning", description: "Quarterly goals" });
|
|
111
|
-
const milestones = [
|
|
112
|
-
createMilestone("MS-001", "RM-001", 0, { title: "Phase 1" }),
|
|
113
|
-
createMilestone("MS-002", "RM-001", 1, { title: "Phase 2" }),
|
|
114
|
-
];
|
|
115
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
116
|
-
["MS-001", [
|
|
117
|
-
createFeature("F-001", "MS-001", 0, { title: "Auth Feature" }),
|
|
118
|
-
createFeature("F-002", "MS-001", 1, { title: "Dashboard Feature" }),
|
|
119
|
-
]],
|
|
120
|
-
["MS-002", [
|
|
121
|
-
createFeature("F-003", "MS-002", 0, { title: "Reporting Feature" }),
|
|
122
|
-
]],
|
|
123
|
-
]);
|
|
124
|
-
|
|
125
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
126
|
-
|
|
127
|
-
expect(handoff.sourceRoadmapId).toBe("RM-001");
|
|
128
|
-
expect(handoff.title).toBe("Q1 Planning");
|
|
129
|
-
expect(handoff.description).toBe("Quarterly goals");
|
|
130
|
-
expect(handoff.milestones).toHaveLength(2);
|
|
131
|
-
|
|
132
|
-
// Verify milestone ordering
|
|
133
|
-
expect(handoff.milestones[0].title).toBe("Phase 1");
|
|
134
|
-
expect(handoff.milestones[0].orderIndex).toBe(0);
|
|
135
|
-
expect(handoff.milestones[1].title).toBe("Phase 2");
|
|
136
|
-
expect(handoff.milestones[1].orderIndex).toBe(1);
|
|
137
|
-
|
|
138
|
-
// Verify feature ordering within milestones
|
|
139
|
-
expect(handoff.milestones[0].features).toHaveLength(2);
|
|
140
|
-
expect(handoff.milestones[0].features[0].title).toBe("Auth Feature");
|
|
141
|
-
expect(handoff.milestones[0].features[0].orderIndex).toBe(0);
|
|
142
|
-
expect(handoff.milestones[0].features[1].title).toBe("Dashboard Feature");
|
|
143
|
-
expect(handoff.milestones[0].features[1].orderIndex).toBe(1);
|
|
144
|
-
|
|
145
|
-
expect(handoff.milestones[1].features).toHaveLength(1);
|
|
146
|
-
expect(handoff.milestones[1].features[0].title).toBe("Reporting Feature");
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("handles empty milestones array", () => {
|
|
150
|
-
const roadmap = createRoadmap();
|
|
151
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
152
|
-
|
|
153
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, [], featuresByMilestoneId);
|
|
154
|
-
|
|
155
|
-
expect(handoff.sourceRoadmapId).toBe("RM-001");
|
|
156
|
-
expect(handoff.milestones).toHaveLength(0);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("handles milestones with empty features", () => {
|
|
160
|
-
const roadmap = createRoadmap();
|
|
161
|
-
const milestones = [
|
|
162
|
-
createMilestone("MS-001", "RM-001", 0),
|
|
163
|
-
];
|
|
164
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
165
|
-
|
|
166
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
167
|
-
|
|
168
|
-
expect(handoff.milestones).toHaveLength(1);
|
|
169
|
-
expect(handoff.milestones[0].features).toHaveLength(0);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("normalizes deterministic ordering when order indices are out of sequence", () => {
|
|
173
|
-
const roadmap = createRoadmap();
|
|
174
|
-
// Simulate out-of-sequence order indices
|
|
175
|
-
const milestones = [
|
|
176
|
-
createMilestone("MS-001", "RM-001", 10), // Out of sequence
|
|
177
|
-
createMilestone("MS-002", "RM-001", 5), // Out of sequence
|
|
178
|
-
createMilestone("MS-003", "RM-001", 20), // Out of sequence
|
|
179
|
-
];
|
|
180
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
181
|
-
|
|
182
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
183
|
-
|
|
184
|
-
// Should be normalized to 0, 1, 2
|
|
185
|
-
expect(handoff.milestones[0].orderIndex).toBe(0);
|
|
186
|
-
expect(handoff.milestones[1].orderIndex).toBe(1);
|
|
187
|
-
expect(handoff.milestones[2].orderIndex).toBe(2);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// ── Tests for mapRoadmapWithHierarchyToMissionHandoff ────────────────────────
|
|
192
|
-
|
|
193
|
-
describe("mapRoadmapWithHierarchyToMissionHandoff", () => {
|
|
194
|
-
it("maps RoadmapWithHierarchy to mission handoff", () => {
|
|
195
|
-
const roadmapWithHierarchy: RoadmapWithHierarchy = {
|
|
196
|
-
id: "RM-001",
|
|
197
|
-
title: "Hierarchy Roadmap",
|
|
198
|
-
description: "With full hierarchy",
|
|
199
|
-
createdAt: "2024-01-01T00:00:00.000Z",
|
|
200
|
-
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
201
|
-
milestones: [
|
|
202
|
-
{
|
|
203
|
-
...createMilestone("MS-001", "RM-001", 0, { title: "Alpha Phase" }),
|
|
204
|
-
features: [
|
|
205
|
-
createFeature("F-001", "MS-001", 0, { title: "Alpha Feature 1" }),
|
|
206
|
-
createFeature("F-002", "MS-001", 1, { title: "Alpha Feature 2" }),
|
|
207
|
-
],
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
...createMilestone("MS-002", "RM-001", 1, { title: "Beta Phase" }),
|
|
211
|
-
features: [
|
|
212
|
-
createFeature("F-003", "MS-002", 0, { title: "Beta Feature" }),
|
|
213
|
-
],
|
|
214
|
-
},
|
|
215
|
-
],
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
const handoff = mapRoadmapWithHierarchyToMissionHandoff(roadmapWithHierarchy);
|
|
219
|
-
|
|
220
|
-
expect(handoff.sourceRoadmapId).toBe("RM-001");
|
|
221
|
-
expect(handoff.title).toBe("Hierarchy Roadmap");
|
|
222
|
-
expect(handoff.milestones).toHaveLength(2);
|
|
223
|
-
expect(handoff.milestones[0].title).toBe("Alpha Phase");
|
|
224
|
-
expect(handoff.milestones[0].features).toHaveLength(2);
|
|
225
|
-
expect(handoff.milestones[1].title).toBe("Beta Phase");
|
|
226
|
-
expect(handoff.milestones[1].features).toHaveLength(1);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it("handles empty milestone hierarchy", () => {
|
|
230
|
-
const roadmapWithHierarchy: RoadmapWithHierarchy = {
|
|
231
|
-
...createRoadmap(),
|
|
232
|
-
milestones: [],
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
const handoff = mapRoadmapWithHierarchyToMissionHandoff(roadmapWithHierarchy);
|
|
236
|
-
|
|
237
|
-
expect(handoff.milestones).toHaveLength(0);
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// ── Tests for mapAllFeaturesToTaskHandoffs ────────────────────────────────────
|
|
242
|
-
|
|
243
|
-
describe("mapAllFeaturesToTaskHandoffs", () => {
|
|
244
|
-
it("flattens all features from a roadmap into individual handoffs", () => {
|
|
245
|
-
const roadmap = createRoadmap();
|
|
246
|
-
const milestones = [
|
|
247
|
-
createMilestone("MS-001", "RM-001", 0),
|
|
248
|
-
createMilestone("MS-002", "RM-001", 1),
|
|
249
|
-
];
|
|
250
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
251
|
-
["MS-001", [
|
|
252
|
-
createFeature("F-001", "MS-001", 0),
|
|
253
|
-
createFeature("F-002", "MS-001", 1),
|
|
254
|
-
]],
|
|
255
|
-
["MS-002", [
|
|
256
|
-
createFeature("F-003", "MS-002", 0),
|
|
257
|
-
]],
|
|
258
|
-
]);
|
|
259
|
-
|
|
260
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
261
|
-
|
|
262
|
-
expect(handoffs).toHaveLength(3);
|
|
263
|
-
expect(handoffs[0].source.featureId).toBe("F-001");
|
|
264
|
-
expect(handoffs[0].source.milestoneOrderIndex).toBe(0);
|
|
265
|
-
expect(handoffs[0].source.featureOrderIndex).toBe(0);
|
|
266
|
-
expect(handoffs[1].source.featureId).toBe("F-002");
|
|
267
|
-
expect(handoffs[1].source.milestoneOrderIndex).toBe(0);
|
|
268
|
-
expect(handoffs[1].source.featureOrderIndex).toBe(1);
|
|
269
|
-
expect(handoffs[2].source.featureId).toBe("F-003");
|
|
270
|
-
expect(handoffs[2].source.milestoneOrderIndex).toBe(1);
|
|
271
|
-
expect(handoffs[2].source.featureOrderIndex).toBe(0);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it("returns empty array when no milestones exist", () => {
|
|
275
|
-
const roadmap = createRoadmap();
|
|
276
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
277
|
-
|
|
278
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, [], featuresByMilestoneId);
|
|
279
|
-
|
|
280
|
-
expect(handoffs).toHaveLength(0);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it("returns empty array when milestones have no features", () => {
|
|
284
|
-
const roadmap = createRoadmap();
|
|
285
|
-
const milestones = [createMilestone("MS-001", "RM-001", 0)];
|
|
286
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
287
|
-
|
|
288
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
289
|
-
|
|
290
|
-
expect(handoffs).toHaveLength(0);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it("preserves feature titles and descriptions", () => {
|
|
294
|
-
const roadmap = createRoadmap();
|
|
295
|
-
const milestones = [createMilestone("MS-001", "RM-001", 0)];
|
|
296
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
297
|
-
["MS-001", [
|
|
298
|
-
createFeature("F-001", "MS-001", 0, { title: "Core Feature", description: "Main functionality" }),
|
|
299
|
-
createFeature("F-002", "MS-001", 1, { title: "Secondary Feature", description: undefined }),
|
|
300
|
-
]],
|
|
301
|
-
]);
|
|
302
|
-
|
|
303
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
304
|
-
|
|
305
|
-
expect(handoffs[0].title).toBe("Core Feature");
|
|
306
|
-
expect(handoffs[0].description).toBe("Main functionality");
|
|
307
|
-
expect(handoffs[1].title).toBe("Secondary Feature");
|
|
308
|
-
expect(handoffs[1].description).toBeUndefined();
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it("normalizes ordering when feature order indices are out of sequence", () => {
|
|
312
|
-
const roadmap = createRoadmap();
|
|
313
|
-
const milestones = [createMilestone("MS-001", "RM-001", 0)];
|
|
314
|
-
// Simulate out-of-sequence feature order indices
|
|
315
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
316
|
-
["MS-001", [
|
|
317
|
-
createFeature("F-001", "MS-001", 100),
|
|
318
|
-
createFeature("F-002", "MS-001", 50),
|
|
319
|
-
createFeature("F-003", "MS-001", 75),
|
|
320
|
-
]],
|
|
321
|
-
]);
|
|
322
|
-
|
|
323
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
324
|
-
|
|
325
|
-
expect(handoffs).toHaveLength(3);
|
|
326
|
-
// Should be normalized to 0, 1, 2
|
|
327
|
-
expect(handoffs[0].source.featureOrderIndex).toBe(0);
|
|
328
|
-
expect(handoffs[1].source.featureOrderIndex).toBe(1);
|
|
329
|
-
expect(handoffs[2].source.featureOrderIndex).toBe(2);
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
it("skips features from unknown milestone IDs", () => {
|
|
333
|
-
const roadmap = createRoadmap();
|
|
334
|
-
const milestones = [createMilestone("MS-001", "RM-001", 0)];
|
|
335
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
336
|
-
["MS-001", [createFeature("F-001", "MS-001", 0)]],
|
|
337
|
-
// MS-999 is not in milestones, so its features should be ignored
|
|
338
|
-
["MS-999", [createFeature("F-999", "MS-999", 0)]],
|
|
339
|
-
]);
|
|
340
|
-
|
|
341
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
342
|
-
|
|
343
|
-
expect(handoffs).toHaveLength(1);
|
|
344
|
-
expect(handoffs[0].source.featureId).toBe("F-001");
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// ── Deterministic Ordering Tests ───────────────────────────────────────────────
|
|
349
|
-
|
|
350
|
-
describe("deterministic ordering", () => {
|
|
351
|
-
it("uses stable ordering when order indices are equal", () => {
|
|
352
|
-
const roadmap = createRoadmap();
|
|
353
|
-
// Same order index for all milestones - should sort by createdAt then id
|
|
354
|
-
const rawMilestones = [
|
|
355
|
-
createMilestone("MS-001", "RM-001", 0, { createdAt: "2024-01-01T00:00:00.000Z" }),
|
|
356
|
-
createMilestone("MS-002", "RM-001", 0, { createdAt: "2024-01-01T00:00:00.000Z" }),
|
|
357
|
-
createMilestone("MS-003", "RM-001", 0, { createdAt: "2024-01-02T00:00:00.000Z" }),
|
|
358
|
-
];
|
|
359
|
-
// Normalize before passing to handoff function (mirrors store behavior)
|
|
360
|
-
const milestones = normalizeRoadmapMilestoneOrder(rawMilestones);
|
|
361
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>();
|
|
362
|
-
|
|
363
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
364
|
-
|
|
365
|
-
// MS-001 and MS-002 have same orderIndex and createdAt, so should sort by id
|
|
366
|
-
// MS-003 has later createdAt
|
|
367
|
-
expect(handoff.milestones[0].sourceMilestoneId).toBe("MS-001");
|
|
368
|
-
expect(handoff.milestones[1].sourceMilestoneId).toBe("MS-002");
|
|
369
|
-
expect(handoff.milestones[2].sourceMilestoneId).toBe("MS-003");
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
it("produces consistent output across multiple calls with same input", () => {
|
|
373
|
-
const roadmap = createRoadmap({ id: "RM-STABLE" });
|
|
374
|
-
const milestones = [
|
|
375
|
-
createMilestone("MS-001", "RM-STABLE", 1),
|
|
376
|
-
createMilestone("MS-002", "RM-STABLE", 0),
|
|
377
|
-
];
|
|
378
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
379
|
-
["MS-001", [createFeature("F-001", "MS-001", 1)]],
|
|
380
|
-
["MS-002", [createFeature("F-002", "MS-002", 0)]],
|
|
381
|
-
]);
|
|
382
|
-
|
|
383
|
-
const first = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
384
|
-
const second = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
385
|
-
|
|
386
|
-
expect(first).toEqual(second);
|
|
387
|
-
expect(first.milestones[0].sourceMilestoneId).toBe(second.milestones[0].sourceMilestoneId);
|
|
388
|
-
expect(first.milestones[1].sourceMilestoneId).toBe(second.milestones[1].sourceMilestoneId);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// ── Source Lineage Preservation Tests ─────────────────────────────────────────
|
|
393
|
-
|
|
394
|
-
describe("source lineage preservation", () => {
|
|
395
|
-
it("preserves roadmap context in all feature handoffs", () => {
|
|
396
|
-
const roadmap = createRoadmap({ id: "RM-LINEAGE", title: "Lineage Test" });
|
|
397
|
-
const milestones = [createMilestone("MS-LINEAGE", "RM-LINEAGE", 0)];
|
|
398
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
399
|
-
["MS-LINEAGE", [createFeature("F-LINEAGE", "MS-LINEAGE", 0)]],
|
|
400
|
-
]);
|
|
401
|
-
|
|
402
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
403
|
-
|
|
404
|
-
expect(handoffs[0].source.roadmapId).toBe("RM-LINEAGE");
|
|
405
|
-
expect(handoffs[0].source.roadmapTitle).toBe("Lineage Test");
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
it("preserves milestone context in all feature handoffs", () => {
|
|
409
|
-
const roadmap = createRoadmap();
|
|
410
|
-
const milestones = [
|
|
411
|
-
createMilestone("MS-ALPHA", "RM-001", 0, { title: "Alpha Milestone" }),
|
|
412
|
-
createMilestone("MS-BETA", "RM-001", 1, { title: "Beta Milestone" }),
|
|
413
|
-
];
|
|
414
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
415
|
-
["MS-ALPHA", [createFeature("F-001", "MS-ALPHA", 0)]],
|
|
416
|
-
["MS-BETA", [createFeature("F-002", "MS-BETA", 0)]],
|
|
417
|
-
]);
|
|
418
|
-
|
|
419
|
-
const handoffs = mapAllFeaturesToTaskHandoffs(roadmap, milestones, featuresByMilestoneId);
|
|
420
|
-
|
|
421
|
-
expect(handoffs).toHaveLength(2);
|
|
422
|
-
expect(handoffs[0].source.milestoneId).toBe("MS-ALPHA");
|
|
423
|
-
expect(handoffs[0].source.milestoneTitle).toBe("Alpha Milestone");
|
|
424
|
-
expect(handoffs[1].source.milestoneId).toBe("MS-BETA");
|
|
425
|
-
expect(handoffs[1].source.milestoneTitle).toBe("Beta Milestone");
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
it("mission handoff preserves source IDs on all entities", () => {
|
|
429
|
-
const roadmap = createRoadmap({ id: "RM-MISSION" });
|
|
430
|
-
const milestones = [
|
|
431
|
-
createMilestone("MS-MISSION-1", "RM-MISSION", 0, { title: "First Phase" }),
|
|
432
|
-
];
|
|
433
|
-
const featuresByMilestoneId = new Map<string, readonly RoadmapFeature[]>([
|
|
434
|
-
["MS-MISSION-1", [
|
|
435
|
-
createFeature("RF-MISSION-1", "MS-MISSION-1", 0, { title: "Mission Feature" }),
|
|
436
|
-
]],
|
|
437
|
-
]);
|
|
438
|
-
|
|
439
|
-
const handoff = mapRoadmapToMissionHandoff(roadmap, milestones, featuresByMilestoneId);
|
|
440
|
-
|
|
441
|
-
expect(handoff.sourceRoadmapId).toBe("RM-MISSION");
|
|
442
|
-
expect(handoff.milestones[0].sourceMilestoneId).toBe("MS-MISSION-1");
|
|
443
|
-
expect(handoff.milestones[0].features[0].sourceFeatureId).toBe("RF-MISSION-1");
|
|
444
|
-
});
|
|
445
|
-
});
|