@critical-path/core 0.15.2 → 0.16.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 (52) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +4 -0
  3. package/dist/domain/cpm.d.ts +10 -0
  4. package/dist/domain/cpm.d.ts.map +1 -0
  5. package/dist/domain/cpm.js +176 -0
  6. package/dist/domain/cpm.js.map +1 -0
  7. package/dist/domain/cpm.test.d.ts +2 -0
  8. package/dist/domain/cpm.test.d.ts.map +1 -0
  9. package/dist/domain/cpm.test.js +113 -0
  10. package/dist/domain/cpm.test.js.map +1 -0
  11. package/dist/domain/index.d.ts +2 -0
  12. package/dist/domain/index.d.ts.map +1 -1
  13. package/dist/domain/index.js +2 -0
  14. package/dist/domain/index.js.map +1 -1
  15. package/dist/domain/ladder.d.ts +16 -0
  16. package/dist/domain/ladder.d.ts.map +1 -0
  17. package/dist/domain/ladder.js +338 -0
  18. package/dist/domain/ladder.js.map +1 -0
  19. package/dist/domain/ladder.test.d.ts +2 -0
  20. package/dist/domain/ladder.test.d.ts.map +1 -0
  21. package/dist/domain/ladder.test.js +213 -0
  22. package/dist/domain/ladder.test.js.map +1 -0
  23. package/dist/engine/index.d.ts +5 -1
  24. package/dist/engine/index.d.ts.map +1 -1
  25. package/dist/engine/index.js +84 -1
  26. package/dist/engine/index.js.map +1 -1
  27. package/dist/store/firebase.d.ts +3 -1
  28. package/dist/store/firebase.d.ts.map +1 -1
  29. package/dist/store/firebase.js +1 -1
  30. package/dist/store/firebase.js.map +1 -1
  31. package/dist/store/index.d.ts +6 -2
  32. package/dist/store/index.d.ts.map +1 -1
  33. package/dist/store/index.js +1 -1
  34. package/dist/store/index.js.map +1 -1
  35. package/dist/store/sqlite.d.ts +3 -1
  36. package/dist/store/sqlite.d.ts.map +1 -1
  37. package/dist/store/sqlite.js +1 -1
  38. package/dist/store/sqlite.js.map +1 -1
  39. package/dist/types/index.d.ts +123 -0
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/domain/cpm.test.ts +128 -0
  43. package/src/domain/cpm.ts +215 -0
  44. package/src/domain/index.ts +3 -0
  45. package/src/domain/ladder.test.ts +251 -0
  46. package/src/domain/ladder.ts +437 -0
  47. package/src/engine/index.ts +110 -4
  48. package/src/store/firebase.ts +2 -2
  49. package/src/store/index.ts +3 -3
  50. package/src/store/sqlite.ts +2 -2
  51. package/src/types/index.ts +138 -0
  52. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @critical-path/core
2
2
 
3
+ ## 0.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e2a7eef: Introduce Bret Victor's Ladder of Abstraction and Critical Path Method (CPM) timeline synthesis to the framework data model:
8
+ - **Core Domain**: Multi-scale timeline synthesis model across Macro phase rollups, Standard CPM Gantt schedule (early/late bounds, float/slack calculation, bottleneck identification), and Concrete grounding (deliverables, file attachments, daily effort distribution, and reality deltas). Added `calculateCriticalPath`, `getTimelineLadder`, and `getTaskLadder` to `CriticalPathEngine`.
9
+ - **Server Router**: HTTP endpoints `GET /projects/:id/critical-path`, `GET /projects/:id/ladder`, and `GET /tasks/:id/ladder`.
10
+ - **Client SDK**: `CriticalPathClient` methods `calculateCriticalPath`, `getTimelineLadder`, and `getTaskLadder`.
11
+ - **MCP**: New AI tools `calculate_critical_path`, `get_timeline_ladder`, and `get_task_ladder`.
12
+ - **React**: Custom hooks `useTimelineLadder`, `useCriticalPath`, and `useTaskLadder`.
13
+ - **Svelte 5**: Svelte 5 Runes state classes `TimelineLadderState` and `CriticalPathState`.
14
+
3
15
  ## 0.15.2
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -32,6 +32,10 @@
32
32
  - `DeliverableEntity` aggregate with automatic delivery timestamps (`deliveredAt`) and URL registry (`outputUrls`).
33
33
  - `DEFAULT_CREATIVE_WORKFLOW` template tailored for creative agencies and content production pipelines.
34
34
  - Rollup calculations via `getDeliverableSummary()` delivering progress percentages, completed tasks, and total estimated/logged hours across assigned tasks.
35
+ - **Bret Victor's Ladder of Abstraction & Critical Path Method (CPM)**:
36
+ - Multi-scale timeline synthesis: Macro bird's-eye phase rollups (`getTimelineLadder({ level: 'macro' })`), Standard Gantt view with topological CPM forward/backward passes and total float/slack, and Concrete grounding (attachments, deliverables, checklist items, daily effort histograms, and reality deltas).
37
+ - Single-task contextual drilldown via `getTaskLadder(taskId)`.
38
+ - Comprehensive CPM analysis via `calculateCriticalPath(projectId)` identifying project bottleneck tasks and critical path duration.
35
39
 
36
40
  ---
37
41
 
@@ -0,0 +1,10 @@
1
+ import type { Task, TaskDependency, CriticalPathAnalysis } from '../types/index.js';
2
+ export declare function getTaskDurationHours(task: Task): number;
3
+ /**
4
+ * Calculates the Critical Path Method (CPM) schedule for a set of tasks and their dependencies.
5
+ * - Forward Pass: computes earlyStart and earlyFinish
6
+ * - Backward Pass: computes lateStart, lateFinish, and totalSlack
7
+ * - Identifies critical tasks (totalSlack === 0) that dictate the minimum project duration.
8
+ */
9
+ export declare function calculateCPM(projectId: string, tasks: Task[], dependencies: TaskDependency[]): CriticalPathAnalysis;
10
+ //# sourceMappingURL=cpm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpm.d.ts","sourceRoot":"","sources":["../../src/domain/cpm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EAEd,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAYvD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,IAAI,EAAE,EACb,YAAY,EAAE,cAAc,EAAE,GAC7B,oBAAoB,CAuLtB"}
@@ -0,0 +1,176 @@
1
+ export function getTaskDurationHours(task) {
2
+ if (typeof task.estimatedHours === 'number' && task.estimatedHours >= 0) {
3
+ return task.estimatedHours;
4
+ }
5
+ if (typeof task.estimatedDurationMinutes === 'number' && task.estimatedDurationMinutes >= 0) {
6
+ return task.estimatedDurationMinutes / 60;
7
+ }
8
+ if (typeof task.actualHours === 'number' && task.actualHours > 0) {
9
+ return task.actualHours;
10
+ }
11
+ // Default to 1 hour for non-empty tasks without explicit estimate
12
+ return 1;
13
+ }
14
+ /**
15
+ * Calculates the Critical Path Method (CPM) schedule for a set of tasks and their dependencies.
16
+ * - Forward Pass: computes earlyStart and earlyFinish
17
+ * - Backward Pass: computes lateStart, lateFinish, and totalSlack
18
+ * - Identifies critical tasks (totalSlack === 0) that dictate the minimum project duration.
19
+ */
20
+ export function calculateCPM(projectId, tasks, dependencies) {
21
+ const calculatedAt = new Date().toISOString();
22
+ if (tasks.length === 0) {
23
+ return {
24
+ projectId,
25
+ calculatedAt,
26
+ totalDurationHours: 0,
27
+ criticalTaskIds: [],
28
+ tasks: []
29
+ };
30
+ }
31
+ const taskMap = new Map(tasks.map((t) => [t.id, t]));
32
+ const taskIds = Array.from(taskMap.keys());
33
+ // Build adjacency graph:
34
+ // prerequisites[v] = tasks that v depends on (must finish before v starts)
35
+ // successors[u] = tasks that depend on u (can only start after u finishes)
36
+ const prerequisites = new Map();
37
+ const successors = new Map();
38
+ for (const id of taskIds) {
39
+ prerequisites.set(id, new Set());
40
+ successors.set(id, new Set());
41
+ }
42
+ for (const dep of dependencies) {
43
+ let sourceId = null;
44
+ let targetId = null;
45
+ if (dep.type === 'blocking') {
46
+ // taskId depends on dependsOnTaskId (dependsOnTaskId -> taskId)
47
+ sourceId = dep.dependsOnTaskId;
48
+ targetId = dep.taskId;
49
+ }
50
+ else if (dep.type === 'blocked_by') {
51
+ // dependsOnTaskId is blocked by taskId (taskId -> dependsOnTaskId)
52
+ sourceId = dep.taskId;
53
+ targetId = dep.dependsOnTaskId;
54
+ }
55
+ if (sourceId && targetId && taskMap.has(sourceId) && taskMap.has(targetId) && sourceId !== targetId) {
56
+ prerequisites.get(targetId).add(sourceId);
57
+ successors.get(sourceId).add(targetId);
58
+ }
59
+ }
60
+ // Topological sorting via Kahn's algorithm
61
+ const inDegree = new Map();
62
+ for (const id of taskIds) {
63
+ inDegree.set(id, prerequisites.get(id).size);
64
+ }
65
+ const queue = [];
66
+ for (const [id, deg] of inDegree.entries()) {
67
+ if (deg === 0) {
68
+ queue.push(id);
69
+ }
70
+ }
71
+ const topoOrder = [];
72
+ while (queue.length > 0) {
73
+ const current = queue.shift();
74
+ topoOrder.push(current);
75
+ for (const next of successors.get(current)) {
76
+ const updatedDeg = inDegree.get(next) - 1;
77
+ inDegree.set(next, updatedDeg);
78
+ if (updatedDeg === 0) {
79
+ queue.push(next);
80
+ }
81
+ }
82
+ }
83
+ // If there's a cycle or disconnected nodes not processed in topoOrder, append them
84
+ if (topoOrder.length < taskIds.length) {
85
+ for (const id of taskIds) {
86
+ if (!topoOrder.includes(id)) {
87
+ topoOrder.push(id);
88
+ }
89
+ }
90
+ }
91
+ // --- FORWARD PASS ---
92
+ const earlyStart = new Map();
93
+ const earlyFinish = new Map();
94
+ for (const id of topoOrder) {
95
+ const task = taskMap.get(id);
96
+ const duration = getTaskDurationHours(task);
97
+ const prereqs = prerequisites.get(id) || new Set();
98
+ let maxPrereqFinish = 0;
99
+ for (const p of prereqs) {
100
+ const pFinish = earlyFinish.get(p) ?? 0;
101
+ if (pFinish > maxPrereqFinish) {
102
+ maxPrereqFinish = pFinish;
103
+ }
104
+ }
105
+ const es = maxPrereqFinish;
106
+ const ef = es + duration;
107
+ earlyStart.set(id, es);
108
+ earlyFinish.set(id, ef);
109
+ }
110
+ // Total project duration
111
+ let totalDurationHours = 0;
112
+ for (const ef of earlyFinish.values()) {
113
+ if (ef > totalDurationHours) {
114
+ totalDurationHours = ef;
115
+ }
116
+ }
117
+ // --- BACKWARD PASS ---
118
+ const lateStart = new Map();
119
+ const lateFinish = new Map();
120
+ // Process in reverse topological order
121
+ for (let i = topoOrder.length - 1; i >= 0; i--) {
122
+ const id = topoOrder[i];
123
+ const task = taskMap.get(id);
124
+ const duration = getTaskDurationHours(task);
125
+ const succs = successors.get(id) || new Set();
126
+ let minSuccLateStart = totalDurationHours;
127
+ if (succs.size > 0) {
128
+ minSuccLateStart = Infinity;
129
+ for (const s of succs) {
130
+ const sLateStart = lateStart.get(s);
131
+ if (sLateStart !== undefined && sLateStart < minSuccLateStart) {
132
+ minSuccLateStart = sLateStart;
133
+ }
134
+ }
135
+ if (!Number.isFinite(minSuccLateStart)) {
136
+ minSuccLateStart = totalDurationHours;
137
+ }
138
+ }
139
+ const lf = minSuccLateStart;
140
+ const ls = lf - duration;
141
+ lateFinish.set(id, lf);
142
+ lateStart.set(id, ls);
143
+ }
144
+ // --- SLACK & CRITICAL PATH ---
145
+ const schedules = [];
146
+ const criticalTaskIds = [];
147
+ for (const id of taskIds) {
148
+ const es = earlyStart.get(id) ?? 0;
149
+ const ef = earlyFinish.get(id) ?? 0;
150
+ const ls = lateStart.get(id) ?? 0;
151
+ const lf = lateFinish.get(id) ?? 0;
152
+ const rawSlack = lf - ef;
153
+ const totalSlack = Math.round(rawSlack * 100) / 100;
154
+ const isCritical = totalSlack <= 0.001;
155
+ if (isCritical) {
156
+ criticalTaskIds.push(id);
157
+ }
158
+ schedules.push({
159
+ taskId: id,
160
+ earlyStart: Math.round(es * 100) / 100,
161
+ earlyFinish: Math.round(ef * 100) / 100,
162
+ lateStart: Math.round(ls * 100) / 100,
163
+ lateFinish: Math.round(lf * 100) / 100,
164
+ totalSlack,
165
+ isCritical
166
+ });
167
+ }
168
+ return {
169
+ projectId,
170
+ calculatedAt,
171
+ totalDurationHours: Math.round(totalDurationHours * 100) / 100,
172
+ criticalTaskIds,
173
+ tasks: schedules
174
+ };
175
+ }
176
+ //# sourceMappingURL=cpm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpm.js","sourceRoot":"","sources":["../../src/domain/cpm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cpm.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpm.test.d.ts","sourceRoot":"","sources":["../../src/domain/cpm.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,113 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { calculateCPM, getTaskDurationHours } from './cpm.js';
3
+ describe('Critical Path Method (CPM)', () => {
4
+ it('returns empty analysis for empty tasks array', () => {
5
+ const analysis = calculateCPM('proj-1', [], []);
6
+ expect(analysis.projectId).toBe('proj-1');
7
+ expect(analysis.totalDurationHours).toBe(0);
8
+ expect(analysis.criticalTaskIds).toEqual([]);
9
+ expect(analysis.tasks).toEqual([]);
10
+ });
11
+ it('calculates duration, slack, and critical path for sequential linear tasks', () => {
12
+ const now = new Date().toISOString();
13
+ const tasks = [
14
+ {
15
+ id: 'task-1',
16
+ projectId: 'proj-1',
17
+ title: 'Task 1',
18
+ status: 'todo',
19
+ priority: 'medium',
20
+ estimatedHours: 2,
21
+ createdAt: now,
22
+ updatedAt: now
23
+ },
24
+ {
25
+ id: 'task-2',
26
+ projectId: 'proj-1',
27
+ title: 'Task 2',
28
+ status: 'todo',
29
+ priority: 'medium',
30
+ estimatedHours: 3,
31
+ createdAt: now,
32
+ updatedAt: now
33
+ },
34
+ {
35
+ id: 'task-3',
36
+ projectId: 'proj-1',
37
+ title: 'Task 3',
38
+ status: 'todo',
39
+ priority: 'medium',
40
+ estimatedHours: 1,
41
+ createdAt: now,
42
+ updatedAt: now
43
+ }
44
+ ];
45
+ const dependencies = [
46
+ { id: 'dep-1', taskId: 'task-2', dependsOnTaskId: 'task-1', type: 'blocking' },
47
+ { id: 'dep-2', taskId: 'task-3', dependsOnTaskId: 'task-2', type: 'blocking' }
48
+ ];
49
+ const result = calculateCPM('proj-1', tasks, dependencies);
50
+ expect(result.totalDurationHours).toBe(6);
51
+ expect(result.criticalTaskIds).toEqual(['task-1', 'task-2', 'task-3']);
52
+ const sched1 = result.tasks.find((t) => t.taskId === 'task-1');
53
+ expect(sched1.earlyStart).toBe(0);
54
+ expect(sched1.earlyFinish).toBe(2);
55
+ expect(sched1.lateStart).toBe(0);
56
+ expect(sched1.lateFinish).toBe(2);
57
+ expect(sched1.totalSlack).toBe(0);
58
+ expect(sched1.isCritical).toBe(true);
59
+ const sched2 = result.tasks.find((t) => t.taskId === 'task-2');
60
+ expect(sched2.earlyStart).toBe(2);
61
+ expect(sched2.earlyFinish).toBe(5);
62
+ expect(sched2.totalSlack).toBe(0);
63
+ expect(sched2.isCritical).toBe(true);
64
+ const sched3 = result.tasks.find((t) => t.taskId === 'task-3');
65
+ expect(sched3.earlyStart).toBe(5);
66
+ expect(sched3.earlyFinish).toBe(6);
67
+ expect(sched3.totalSlack).toBe(0);
68
+ expect(sched3.isCritical).toBe(true);
69
+ });
70
+ it('correctly identifies bottleneck critical path vs non-critical slack in parallel branches', () => {
71
+ // A (1h) -> B (4h) -> D (1h) => Path length = 6h (CRITICAL)
72
+ // A (1h) -> C (2h) -> D (1h) => Path length = 4h (Non-critical, C has 2h slack)
73
+ const now = new Date().toISOString();
74
+ const tasks = [
75
+ { id: 'A', projectId: 'p1', title: 'A', status: 'todo', priority: 'medium', estimatedHours: 1, createdAt: now, updatedAt: now },
76
+ { id: 'B', projectId: 'p1', title: 'B', status: 'todo', priority: 'medium', estimatedHours: 4, createdAt: now, updatedAt: now },
77
+ { id: 'C', projectId: 'p1', title: 'C', status: 'todo', priority: 'medium', estimatedHours: 2, createdAt: now, updatedAt: now },
78
+ { id: 'D', projectId: 'p1', title: 'D', status: 'todo', priority: 'medium', estimatedHours: 1, createdAt: now, updatedAt: now }
79
+ ];
80
+ const dependencies = [
81
+ { id: 'd1', taskId: 'B', dependsOnTaskId: 'A', type: 'blocking' },
82
+ { id: 'd2', taskId: 'C', dependsOnTaskId: 'A', type: 'blocking' },
83
+ { id: 'd3', taskId: 'D', dependsOnTaskId: 'B', type: 'blocking' },
84
+ { id: 'd4', taskId: 'D', dependsOnTaskId: 'C', type: 'blocking' }
85
+ ];
86
+ const result = calculateCPM('p1', tasks, dependencies);
87
+ expect(result.totalDurationHours).toBe(6);
88
+ expect(result.criticalTaskIds).toEqual(['A', 'B', 'D']);
89
+ const schedC = result.tasks.find((t) => t.taskId === 'C');
90
+ expect(schedC.earlyStart).toBe(1);
91
+ expect(schedC.earlyFinish).toBe(3);
92
+ expect(schedC.lateStart).toBe(3);
93
+ expect(schedC.lateFinish).toBe(5);
94
+ expect(schedC.totalSlack).toBe(2);
95
+ expect(schedC.isCritical).toBe(false);
96
+ const schedB = result.tasks.find((t) => t.taskId === 'B');
97
+ expect(schedB.totalSlack).toBe(0);
98
+ expect(schedB.isCritical).toBe(true);
99
+ });
100
+ it('falls back gracefully to 1 hour duration if no estimate or minutes are set', () => {
101
+ const task = {
102
+ id: 'no-est',
103
+ projectId: 'p1',
104
+ title: 'Unestimated Task',
105
+ status: 'todo',
106
+ priority: 'none',
107
+ createdAt: '',
108
+ updatedAt: ''
109
+ };
110
+ expect(getTaskDurationHours(task)).toBe(1);
111
+ });
112
+ });
113
+ //# sourceMappingURL=cpm.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpm.test.js","sourceRoot":"","sources":["../../src/domain/cpm.test.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,6 @@ export * from './events.js';
2
2
  export * from './custom-fields.js';
3
3
  export * from './graph.js';
4
4
  export * from './entities.js';
5
+ export * from './cpm.js';
6
+ export * from './ladder.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
@@ -2,4 +2,6 @@ export * from './events.js';
2
2
  export * from './custom-fields.js';
3
3
  export * from './graph.js';
4
4
  export * from './entities.js';
5
+ export * from './cpm.js';
6
+ export * from './ladder.js';
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/domain/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Project, Task, TaskDependency, TaskContainer, Iteration, Deliverable, Attachment, TimeEntry, Activity, TimelineLadder, TimelineLadderOptions, MacroPhaseRollup, ConcreteTaskEvidence } from '../types/index.js';
2
+ export interface LadderContext {
3
+ project: Project;
4
+ tasks: Task[];
5
+ dependencies: TaskDependency[];
6
+ containers?: TaskContainer[];
7
+ iterations?: Iteration[];
8
+ deliverables?: Deliverable[];
9
+ attachments?: Attachment[];
10
+ timeEntries?: TimeEntry[];
11
+ activities?: Activity[];
12
+ }
13
+ export declare function aggregateConcreteEvidenceForTask(task: Task, attachments?: Attachment[], deliverables?: Deliverable[], timeEntries?: TimeEntry[], activities?: Activity[]): ConcreteTaskEvidence;
14
+ export declare function computeMacroPhases(tasks: Task[], containers: TaskContainer[] | undefined, iterations: Iteration[] | undefined, criticalTaskIds: Set<string>): MacroPhaseRollup[];
15
+ export declare function buildTimelineLadder(context: LadderContext, options?: TimelineLadderOptions): TimelineLadder;
16
+ //# sourceMappingURL=ladder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ladder.d.ts","sourceRoot":"","sources":["../../src/domain/ladder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,IAAI,EACJ,cAAc,EACd,aAAa,EACb,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,cAAc,EACd,qBAAqB,EAErB,gBAAgB,EAGhB,oBAAoB,EAIrB,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,IAAI,EACV,WAAW,GAAE,UAAU,EAAO,EAC9B,YAAY,GAAE,WAAW,EAAO,EAChC,WAAW,GAAE,SAAS,EAAO,EAC7B,UAAU,GAAE,QAAQ,EAAO,GAC1B,oBAAoB,CAsFtB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,IAAI,EAAE,EACb,UAAU,EAAE,aAAa,EAAE,YAAK,EAChC,UAAU,EAAE,SAAS,EAAE,YAAK,EAC5B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,GAC3B,gBAAgB,EAAE,CAsJpB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAmJhB"}