@critical-path/core 0.15.2 → 0.17.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/CHANGELOG.md +24 -0
- package/README.md +25 -0
- package/dist/domain/cpm.d.ts +10 -0
- package/dist/domain/cpm.d.ts.map +1 -0
- package/dist/domain/cpm.js +176 -0
- package/dist/domain/cpm.js.map +1 -0
- package/dist/domain/cpm.test.d.ts +2 -0
- package/dist/domain/cpm.test.d.ts.map +1 -0
- package/dist/domain/cpm.test.js +113 -0
- package/dist/domain/cpm.test.js.map +1 -0
- package/dist/domain/entities.d.ts.map +1 -1
- package/dist/domain/entities.js +5 -0
- package/dist/domain/entities.js.map +1 -1
- package/dist/domain/index.d.ts +3 -0
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +3 -0
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/ladder.d.ts +16 -0
- package/dist/domain/ladder.d.ts.map +1 -0
- package/dist/domain/ladder.js +352 -0
- package/dist/domain/ladder.js.map +1 -0
- package/dist/domain/ladder.test.d.ts +2 -0
- package/dist/domain/ladder.test.d.ts.map +1 -0
- package/dist/domain/ladder.test.js +213 -0
- package/dist/domain/ladder.test.js.map +1 -0
- package/dist/domain/metrics.d.ts +29 -0
- package/dist/domain/metrics.d.ts.map +1 -0
- package/dist/domain/metrics.js +403 -0
- package/dist/domain/metrics.js.map +1 -0
- package/dist/domain/metrics.test.d.ts +2 -0
- package/dist/domain/metrics.test.d.ts.map +1 -0
- package/dist/domain/metrics.test.js +251 -0
- package/dist/domain/metrics.test.js.map +1 -0
- package/dist/engine/index.d.ts +8 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +124 -1
- package/dist/engine/index.js.map +1 -1
- package/dist/store/firebase.d.ts +3 -1
- package/dist/store/firebase.d.ts.map +1 -1
- package/dist/store/firebase.js +1 -1
- package/dist/store/firebase.js.map +1 -1
- package/dist/store/index.d.ts +6 -2
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/sqlite.d.ts +3 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +1 -1
- package/dist/store/sqlite.js.map +1 -1
- package/dist/types/index.d.ts +177 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/domain/cpm.test.ts +128 -0
- package/src/domain/cpm.ts +215 -0
- package/src/domain/entities.ts +6 -0
- package/src/domain/index.ts +4 -0
- package/src/domain/ladder.test.ts +251 -0
- package/src/domain/ladder.ts +453 -0
- package/src/domain/metrics.test.ts +286 -0
- package/src/domain/metrics.ts +484 -0
- package/src/engine/index.ts +169 -4
- package/src/store/firebase.ts +2 -2
- package/src/store/index.ts +3 -3
- package/src/store/sqlite.ts +2 -2
- package/src/types/index.ts +206 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/store/firebase.ts
CHANGED
|
@@ -536,9 +536,9 @@ export class FirebaseStore implements StorageAdapter {
|
|
|
536
536
|
return snap.docs.map((doc) => ({ ...doc.data(), id: doc.id }));
|
|
537
537
|
}
|
|
538
538
|
|
|
539
|
-
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'>): Promise<TimeEntry> {
|
|
539
|
+
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'> & { loggedAt?: string }): Promise<TimeEntry> {
|
|
540
540
|
const docRef = this.db.collection('time_entries').doc();
|
|
541
|
-
const now = new Date().toISOString();
|
|
541
|
+
const now = entry.loggedAt || new Date().toISOString();
|
|
542
542
|
const newEntry: TimeEntry = { ...entry, id: docRef.id, loggedAt: now };
|
|
543
543
|
await docRef.set(sanitizeFirestoreData(newEntry));
|
|
544
544
|
return newEntry;
|
package/src/store/index.ts
CHANGED
|
@@ -91,7 +91,7 @@ export interface ActivityRepository {
|
|
|
91
91
|
|
|
92
92
|
export interface TimeEntryRepository {
|
|
93
93
|
getTimeEntries(taskId: string): Promise<TimeEntry[]>;
|
|
94
|
-
logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'>): Promise<TimeEntry>;
|
|
94
|
+
logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'> & { loggedAt?: string }): Promise<TimeEntry>;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
export interface DependencyRepository {
|
|
@@ -512,9 +512,9 @@ export class InMemoryStore implements StorageAdapter {
|
|
|
512
512
|
return Array.from(this.timeEntries.values()).filter((e) => e.taskId === taskId);
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'>): Promise<TimeEntry> {
|
|
515
|
+
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'> & { loggedAt?: string }): Promise<TimeEntry> {
|
|
516
516
|
const id = `time_${Math.random().toString(36).substring(2, 9)}`;
|
|
517
|
-
const newEntry: TimeEntry = { ...entry, id, loggedAt: new Date().toISOString() };
|
|
517
|
+
const newEntry: TimeEntry = { ...entry, id, loggedAt: entry.loggedAt || new Date().toISOString() };
|
|
518
518
|
this.timeEntries.set(id, newEntry);
|
|
519
519
|
return newEntry;
|
|
520
520
|
}
|
package/src/store/sqlite.ts
CHANGED
|
@@ -1084,9 +1084,9 @@ export class SQLiteStore implements StorageAdapter {
|
|
|
1084
1084
|
return rows.map((r) => ({ ...r, isBillable: r.isBillable !== null ? Boolean(r.isBillable) : undefined }));
|
|
1085
1085
|
}
|
|
1086
1086
|
|
|
1087
|
-
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'>): Promise<TimeEntry> {
|
|
1087
|
+
async logTime(entry: Omit<TimeEntry, 'id' | 'loggedAt'> & { loggedAt?: string }): Promise<TimeEntry> {
|
|
1088
1088
|
const id = `time_${Math.random().toString(36).substring(2, 9)}`;
|
|
1089
|
-
const now = new Date().toISOString();
|
|
1089
|
+
const now = entry.loggedAt || new Date().toISOString();
|
|
1090
1090
|
const newEntry: TimeEntry = { ...entry, id, loggedAt: now };
|
|
1091
1091
|
|
|
1092
1092
|
const stmt = this.db.prepare(`
|
package/src/types/index.ts
CHANGED
|
@@ -424,3 +424,209 @@ export interface CriticalPathConfig {
|
|
|
424
424
|
deliverables?: Deliverable[];
|
|
425
425
|
};
|
|
426
426
|
}
|
|
427
|
+
|
|
428
|
+
// ==========================================
|
|
429
|
+
// Ladder of Abstraction Types
|
|
430
|
+
// ==========================================
|
|
431
|
+
|
|
432
|
+
export type AbstractionLevel = 'macro' | 'standard' | 'concrete' | 'all';
|
|
433
|
+
|
|
434
|
+
export type MacroPhaseHealth = 'on_track' | 'at_risk' | 'blocked' | 'overdue' | 'completed';
|
|
435
|
+
|
|
436
|
+
export interface MacroPhaseRollup {
|
|
437
|
+
id: string; // containerId, iterationId, deliverableId, or 'unassigned'
|
|
438
|
+
type: 'container' | 'iteration' | 'deliverable' | 'phase';
|
|
439
|
+
name: string;
|
|
440
|
+
description?: string;
|
|
441
|
+
startDate?: string;
|
|
442
|
+
endDate?: string;
|
|
443
|
+
durationHours: number;
|
|
444
|
+
totalTasks: number;
|
|
445
|
+
completedTasks: number;
|
|
446
|
+
inProgressTasks: number;
|
|
447
|
+
blockedTasks: number;
|
|
448
|
+
progressPercentage: number;
|
|
449
|
+
totalEstimatedHours: number;
|
|
450
|
+
totalLoggedHours: number;
|
|
451
|
+
isCritical: boolean;
|
|
452
|
+
criticalTaskCount: number;
|
|
453
|
+
health: MacroPhaseHealth;
|
|
454
|
+
taskIds: string[];
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export interface MacroTimelineSummary {
|
|
458
|
+
projectId: string;
|
|
459
|
+
projectName: string;
|
|
460
|
+
overallStartDate?: string;
|
|
461
|
+
overallEndDate?: string;
|
|
462
|
+
projectedFinishDate?: string;
|
|
463
|
+
totalDurationHours: number;
|
|
464
|
+
criticalPathDurationHours: number;
|
|
465
|
+
overallProgressPercentage: number;
|
|
466
|
+
health: MacroPhaseHealth;
|
|
467
|
+
totalTasks: number;
|
|
468
|
+
completedTasks: number;
|
|
469
|
+
inProgressTasks: number;
|
|
470
|
+
blockedTasks: number;
|
|
471
|
+
totalEstimatedHours: number;
|
|
472
|
+
totalLoggedHours: number;
|
|
473
|
+
phases: MacroPhaseRollup[];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export interface TaskCriticalPathSchedule {
|
|
477
|
+
taskId: string;
|
|
478
|
+
earlyStart: number;
|
|
479
|
+
earlyFinish: number;
|
|
480
|
+
lateStart: number;
|
|
481
|
+
lateFinish: number;
|
|
482
|
+
totalSlack: number;
|
|
483
|
+
isCritical: boolean;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
export interface CriticalPathAnalysis {
|
|
487
|
+
projectId: string;
|
|
488
|
+
calculatedAt: string;
|
|
489
|
+
totalDurationHours: number;
|
|
490
|
+
criticalTaskIds: string[];
|
|
491
|
+
tasks: TaskCriticalPathSchedule[];
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export interface ConcreteEvidenceSummary {
|
|
495
|
+
attachmentCount: number;
|
|
496
|
+
deliverableCount: number;
|
|
497
|
+
todoCount: number;
|
|
498
|
+
completedTodoCount: number;
|
|
499
|
+
timeEntryCount: number;
|
|
500
|
+
totalLoggedHours: number;
|
|
501
|
+
hasVisualAsset: boolean;
|
|
502
|
+
lastActivityAt?: string;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export interface StandardTaskTimelineItem extends Task {
|
|
506
|
+
cpm?: TaskCriticalPathSchedule;
|
|
507
|
+
blockingTaskIds: string[];
|
|
508
|
+
dependentTaskIds: string[];
|
|
509
|
+
childTaskIds: string[];
|
|
510
|
+
concreteEvidenceSummary: ConcreteEvidenceSummary;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export interface RealityDelta {
|
|
514
|
+
plannedStartDate?: string;
|
|
515
|
+
actualStartDate?: string;
|
|
516
|
+
dueDate?: string;
|
|
517
|
+
actualEndDate?: string;
|
|
518
|
+
estimatedHours: number;
|
|
519
|
+
loggedHours: number;
|
|
520
|
+
varianceHours: number; // loggedHours - estimatedHours
|
|
521
|
+
effortVarianceHours?: number; // loggedHours - estimatedHours (effort variance)
|
|
522
|
+
durationVarianceHours?: number; // actual duration hours - planned duration hours
|
|
523
|
+
scheduleVarianceDays?: number; // days difference between planned/due vs actual
|
|
524
|
+
accuracyRatio?: number; // loggedHours / estimatedHours (estimation accuracy ratio)
|
|
525
|
+
isOverdue: boolean;
|
|
526
|
+
isOverEstimate: boolean;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export type ProgressInferenceSource = 'explicit' | 'todos' | 'time_effort' | 'schedule_elapsed' | 'blended';
|
|
530
|
+
|
|
531
|
+
export interface TaskProgressInference {
|
|
532
|
+
progressPercentage: number;
|
|
533
|
+
source: ProgressInferenceSource;
|
|
534
|
+
isExplicit: boolean;
|
|
535
|
+
breakdown: {
|
|
536
|
+
explicitProgress?: number;
|
|
537
|
+
todoProgress?: number;
|
|
538
|
+
effortProgress?: number;
|
|
539
|
+
scheduleProgress?: number;
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export type ProgressCurveProfile =
|
|
544
|
+
| 'linear'
|
|
545
|
+
| 's_curve'
|
|
546
|
+
| 'early_surge'
|
|
547
|
+
| 'late_rush'
|
|
548
|
+
| 'stalled'
|
|
549
|
+
| 'insufficient_data';
|
|
550
|
+
|
|
551
|
+
export interface TaskProgressHistoryPoint {
|
|
552
|
+
timestamp: string;
|
|
553
|
+
progress: number;
|
|
554
|
+
inferredProgress?: number;
|
|
555
|
+
status: TaskStatus;
|
|
556
|
+
semanticStatus?: SemanticStatus;
|
|
557
|
+
action: string;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export interface TaskProgressHistory {
|
|
561
|
+
taskId: string;
|
|
562
|
+
points: TaskProgressHistoryPoint[];
|
|
563
|
+
curveProfile: ProgressCurveProfile;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export interface TaskEVM {
|
|
567
|
+
plannedValue: number; // PV (expected hours)
|
|
568
|
+
earnedValue: number; // EV (earned hours)
|
|
569
|
+
actualCost: number; // AC (logged hours)
|
|
570
|
+
costVariance: number; // CV = EV - AC
|
|
571
|
+
scheduleVariance: number; // SV = EV - PV
|
|
572
|
+
costPerformanceIndex: number; // CPI = EV / AC
|
|
573
|
+
schedulePerformanceIndex: number; // SPI = EV / PV
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export interface TaskInferredActuals {
|
|
577
|
+
actualStartDate?: string;
|
|
578
|
+
actualEndDate?: string;
|
|
579
|
+
isStartDateInferred: boolean;
|
|
580
|
+
isEndDateInferred: boolean;
|
|
581
|
+
activeWorkingHours?: number;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
export interface TaskMetrics {
|
|
585
|
+
taskId: string;
|
|
586
|
+
inferredActuals: TaskInferredActuals;
|
|
587
|
+
realityDelta: RealityDelta;
|
|
588
|
+
progress: TaskProgressInference;
|
|
589
|
+
evm: TaskEVM;
|
|
590
|
+
progressHistory: TaskProgressHistory;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export interface ConcreteTaskEvidence {
|
|
594
|
+
taskId: string;
|
|
595
|
+
attachments: Attachment[];
|
|
596
|
+
deliverables: Deliverable[];
|
|
597
|
+
todos: TaskTodoItem[];
|
|
598
|
+
timeEntries: TimeEntry[];
|
|
599
|
+
dailyEffortDistribution: Array<{ date: string; hours: number }>;
|
|
600
|
+
activities: Activity[];
|
|
601
|
+
realityDelta: RealityDelta;
|
|
602
|
+
evidenceSummary: ConcreteEvidenceSummary;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
export interface TimelineLadderOptions {
|
|
606
|
+
level?: AbstractionLevel;
|
|
607
|
+
containerId?: string;
|
|
608
|
+
iterationId?: string;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export interface TimelineLadder {
|
|
612
|
+
projectId: string;
|
|
613
|
+
generatedAt: string;
|
|
614
|
+
level: AbstractionLevel;
|
|
615
|
+
macro?: MacroTimelineSummary;
|
|
616
|
+
standard?: {
|
|
617
|
+
tasks: StandardTaskTimelineItem[];
|
|
618
|
+
criticalPathTaskIds: string[];
|
|
619
|
+
dependencies: TaskDependency[];
|
|
620
|
+
totalDurationHours: number;
|
|
621
|
+
};
|
|
622
|
+
concrete?: Record<string, ConcreteTaskEvidence>;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export interface TaskLadderView {
|
|
626
|
+
taskId: string;
|
|
627
|
+
macroPhase?: MacroPhaseRollup;
|
|
628
|
+
standard: StandardTaskTimelineItem;
|
|
629
|
+
concrete: ConcreteTaskEvidence;
|
|
630
|
+
metrics?: TaskMetrics;
|
|
631
|
+
}
|
|
632
|
+
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -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/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/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/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/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"}
|