@critical-path/core 0.18.0 → 0.19.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 (68) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +43 -0
  3. package/dist/domain/calendar.d.ts +53 -0
  4. package/dist/domain/calendar.d.ts.map +1 -0
  5. package/dist/domain/calendar.js +333 -0
  6. package/dist/domain/calendar.js.map +1 -0
  7. package/dist/domain/calendar.test.d.ts +2 -0
  8. package/dist/domain/calendar.test.d.ts.map +1 -0
  9. package/dist/domain/calendar.test.js +136 -0
  10. package/dist/domain/calendar.test.js.map +1 -0
  11. package/dist/domain/cpm.d.ts +8 -3
  12. package/dist/domain/cpm.d.ts.map +1 -1
  13. package/dist/domain/cpm.js +36 -3
  14. package/dist/domain/cpm.js.map +1 -1
  15. package/dist/domain/cpm.test.js +53 -0
  16. package/dist/domain/cpm.test.js.map +1 -1
  17. package/dist/domain/events.d.ts +10 -2
  18. package/dist/domain/events.d.ts.map +1 -1
  19. package/dist/domain/events.js.map +1 -1
  20. package/dist/domain/index.d.ts +1 -0
  21. package/dist/domain/index.d.ts.map +1 -1
  22. package/dist/domain/index.js +1 -0
  23. package/dist/domain/index.js.map +1 -1
  24. package/dist/domain/ladder.d.ts +3 -2
  25. package/dist/domain/ladder.d.ts.map +1 -1
  26. package/dist/domain/ladder.js +21 -3
  27. package/dist/domain/ladder.js.map +1 -1
  28. package/dist/domain/metrics.test.js +5 -4
  29. package/dist/domain/metrics.test.js.map +1 -1
  30. package/dist/domain/workload.d.ts.map +1 -1
  31. package/dist/domain/workload.js +60 -17
  32. package/dist/domain/workload.js.map +1 -1
  33. package/dist/domain/workload.test.js +60 -0
  34. package/dist/domain/workload.test.js.map +1 -1
  35. package/dist/engine/index.d.ts +3 -1
  36. package/dist/engine/index.d.ts.map +1 -1
  37. package/dist/engine/index.js +71 -4
  38. package/dist/engine/index.js.map +1 -1
  39. package/dist/store/sqlite.d.ts.map +1 -1
  40. package/dist/store/sqlite.js +9 -3
  41. package/dist/store/sqlite.js.map +1 -1
  42. package/dist/store/sqlite.test.js +15 -1
  43. package/dist/store/sqlite.test.js.map +1 -1
  44. package/dist/task-state.test.js +49 -0
  45. package/dist/task-state.test.js.map +1 -1
  46. package/dist/types/index.d.ts +44 -1
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/dist/utils/status.d.ts.map +1 -1
  49. package/dist/utils/status.js +5 -2
  50. package/dist/utils/status.js.map +1 -1
  51. package/package.json +1 -1
  52. package/src/domain/calendar.test.ts +164 -0
  53. package/src/domain/calendar.ts +457 -0
  54. package/src/domain/cpm.test.ts +61 -0
  55. package/src/domain/cpm.ts +47 -4
  56. package/src/domain/events.ts +11 -1
  57. package/src/domain/index.ts +1 -0
  58. package/src/domain/ladder.ts +25 -4
  59. package/src/domain/metrics.test.ts +6 -4
  60. package/src/domain/workload.test.ts +73 -0
  61. package/src/domain/workload.ts +73 -19
  62. package/src/engine/index.ts +79 -5
  63. package/src/store/sqlite.test.ts +17 -1
  64. package/src/store/sqlite.ts +11 -1
  65. package/src/task-state.test.ts +60 -1
  66. package/src/types/index.ts +48 -0
  67. package/src/utils/status.ts +7 -2
  68. package/tsconfig.tsbuildinfo +1 -1
@@ -33,6 +33,32 @@ export type TaskLifecycleState = TaskDerivedStatus;
33
33
 
34
34
  export type Role = 'admin' | 'project_manager' | 'contributor' | 'viewer';
35
35
 
36
+ export interface WorkingHoursRange {
37
+ start: string; // "09:00" (HH:MM 24-hour format)
38
+ end: string; // "17:00"
39
+ }
40
+
41
+ export interface DaySchedule {
42
+ dayOfWeek: number; // 0 = Sunday, 1 = Monday, ..., 6 = Saturday
43
+ isWorkingDay: boolean;
44
+ hours?: WorkingHoursRange[];
45
+ }
46
+
47
+ export interface Holiday {
48
+ date: string; // "YYYY-MM-DD"
49
+ name?: string;
50
+ halfDay?: boolean; // if true, counts as 50% working hours
51
+ }
52
+
53
+ export interface WorkSchedule {
54
+ id?: string;
55
+ name?: string;
56
+ timezone?: string; // Informational (e.g. "UTC", "America/New_York")
57
+ defaultHoursPerDay?: number; // Default: 8
58
+ days: DaySchedule[];
59
+ holidays?: Holiday[];
60
+ }
61
+
36
62
  export interface User {
37
63
  id: string;
38
64
  name: string;
@@ -40,6 +66,7 @@ export interface User {
40
66
  avatarUrl?: string;
41
67
  role: Role;
42
68
  weeklyCapacityHours?: number;
69
+ schedule?: WorkSchedule;
43
70
  createdAt: string;
44
71
  }
45
72
 
@@ -50,6 +77,7 @@ export interface Team {
50
77
  leaderId?: string;
51
78
  memberIds: string[];
52
79
  weeklyCapacityHours?: number;
80
+ schedule?: WorkSchedule;
53
81
  createdAt: string;
54
82
  updatedAt: string;
55
83
  }
@@ -107,6 +135,9 @@ export interface Project {
107
135
  statusDefinitions?: StatusDefinition[];
108
136
  priorityDefinitions?: Array<{ key: string; label: string; level?: number }>;
109
137
  customFieldDefinitions?: CustomFieldDefinition[];
138
+ schedule?: WorkSchedule;
139
+ startDate?: string;
140
+ targetEndDate?: string;
110
141
  createdAt: string;
111
142
  updatedAt: string;
112
143
  }
@@ -185,6 +216,8 @@ export interface Task {
185
216
  billableDurationMinutes?: number;
186
217
  // Progress (0 to 100 percentage)
187
218
  progress?: number;
219
+ isBlocked?: boolean;
220
+ blockedReason?: string | null;
188
221
  tags?: string[];
189
222
  todos?: TaskTodoItem[];
190
223
  customFields?: Record<string, unknown>;
@@ -371,6 +404,7 @@ export type WebhookEvent =
371
404
  | 'task.updated'
372
405
  | 'task.deleted'
373
406
  | 'task.status_changed'
407
+ | 'task.blocked'
374
408
  | 'task.unblocked'
375
409
  | 'comment.created'
376
410
  | 'comment.updated'
@@ -415,6 +449,7 @@ export interface CriticalPathConfig {
415
449
  fileStorage?: FileStorageAdapter;
416
450
  plugins?: CriticalPathPlugin[];
417
451
  webhooks?: Omit<Webhook, 'id' | 'createdAt'>[];
452
+ defaultSchedule?: WorkSchedule;
418
453
  initialData?: {
419
454
  projects?: Project[];
420
455
  tasks?: Task[];
@@ -483,12 +518,21 @@ export interface TaskCriticalPathSchedule {
483
518
  lateFinish: number;
484
519
  totalSlack: number;
485
520
  isCritical: boolean;
521
+ durationHours?: number;
522
+ earlyStartDate?: string;
523
+ earlyFinishDate?: string;
524
+ lateStartDate?: string;
525
+ lateFinishDate?: string;
526
+ slackWorkingHours?: number;
486
527
  }
487
528
 
488
529
  export interface CriticalPathAnalysis {
489
530
  projectId: string;
490
531
  calculatedAt: string;
491
532
  totalDurationHours: number;
533
+ totalWorkingHours?: number;
534
+ projectStartDate?: string;
535
+ projectEndDate?: string;
492
536
  criticalTaskIds: string[];
493
537
  tasks: TaskCriticalPathSchedule[];
494
538
  }
@@ -523,6 +567,7 @@ export interface RealityDelta {
523
567
  effortVarianceHours?: number; // loggedHours - estimatedHours (effort variance)
524
568
  durationVarianceHours?: number; // actual duration hours - planned duration hours
525
569
  scheduleVarianceDays?: number; // days difference between planned/due vs actual
570
+ scheduleVarianceWorkingDays?: number; // working days difference between planned/due vs actual
526
571
  accuracyRatio?: number; // loggedHours / estimatedHours (estimation accuracy ratio)
527
572
  isOverdue: boolean;
528
573
  isOverEstimate: boolean;
@@ -669,5 +714,8 @@ export interface WorkloadDistributionOptions {
669
714
  metric?: WorkloadMetric; // default: 'blended'
670
715
  defaultWeeklyCapacityHours?: number; // default: 40
671
716
  capacityOverrides?: Record<string, number>; // e.g. { [assigneeOrTeamId]: weeklyCapacityHours }
717
+ schedule?: WorkSchedule;
718
+ userSchedules?: Record<string, WorkSchedule>;
719
+ teamSchedules?: Record<string, WorkSchedule>;
672
720
  }
673
721
 
@@ -88,8 +88,13 @@ export function deriveTaskLifecycleState(
88
88
  return upstreamDef.category !== 'completed';
89
89
  });
90
90
  const blockingTaskIds = blockingTasks.map((t) => t.id);
91
- const isBlocked = !isDone && blockingTaskIds.length > 0;
92
- const isReady = semanticStatus === 'not_started' && blockingTaskIds.length === 0;
91
+ const isExplicitlyBlocked = Boolean(
92
+ task.isBlocked === true ||
93
+ task.customFields?.isBlocked === true ||
94
+ task.status === 'blocked'
95
+ );
96
+ const isBlocked = !isDone && (blockingTaskIds.length > 0 || isExplicitlyBlocked);
97
+ const isReady = semanticStatus === 'not_started' && !isBlocked;
93
98
 
94
99
  // Time & Schedule Indicators
95
100
  let isOverdue = false;
@@ -1 +1 @@
1
- {"root":["./src/deliverables.test.ts","./src/index.test.ts","./src/index.ts","./src/status.test.ts","./src/task-state.test.ts","./src/use-case-validation.test.ts","./src/domain/cpm.test.ts","./src/domain/cpm.ts","./src/domain/custom-fields.ts","./src/domain/ddd.test.ts","./src/domain/entities.ts","./src/domain/events.ts","./src/domain/graph.ts","./src/domain/index.ts","./src/domain/ladder.test.ts","./src/domain/ladder.ts","./src/domain/metrics.test.ts","./src/domain/metrics.ts","./src/domain/workload.test.ts","./src/domain/workload.ts","./src/engine/index.ts","./src/plugins/index.ts","./src/storage/file-storage.ts","./src/storage/firebase-storage.ts","./src/storage/index.ts","./src/storage/s3.ts","./src/storage/storage.test.ts","./src/store/firebase.test.ts","./src/store/firebase.ts","./src/store/index.ts","./src/store/sqlite.test.ts","./src/store/sqlite.ts","./src/types/index.ts","./src/utils/index.ts","./src/utils/key.test.ts","./src/utils/key.ts","./src/utils/mentions.test.ts","./src/utils/mentions.ts","./src/utils/status.ts","./src/utils/workflow.ts"],"version":"5.9.3"}
1
+ {"root":["./src/deliverables.test.ts","./src/index.test.ts","./src/index.ts","./src/status.test.ts","./src/task-state.test.ts","./src/use-case-validation.test.ts","./src/domain/calendar.test.ts","./src/domain/calendar.ts","./src/domain/cpm.test.ts","./src/domain/cpm.ts","./src/domain/custom-fields.ts","./src/domain/ddd.test.ts","./src/domain/entities.ts","./src/domain/events.ts","./src/domain/graph.ts","./src/domain/index.ts","./src/domain/ladder.test.ts","./src/domain/ladder.ts","./src/domain/metrics.test.ts","./src/domain/metrics.ts","./src/domain/workload.test.ts","./src/domain/workload.ts","./src/engine/index.ts","./src/plugins/index.ts","./src/storage/file-storage.ts","./src/storage/firebase-storage.ts","./src/storage/index.ts","./src/storage/s3.ts","./src/storage/storage.test.ts","./src/store/firebase.test.ts","./src/store/firebase.ts","./src/store/index.ts","./src/store/sqlite.test.ts","./src/store/sqlite.ts","./src/types/index.ts","./src/utils/index.ts","./src/utils/key.test.ts","./src/utils/key.ts","./src/utils/mentions.test.ts","./src/utils/mentions.ts","./src/utils/status.ts","./src/utils/workflow.ts"],"version":"5.9.3"}