@critical-path/core 0.11.0 → 0.13.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 (49) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +39 -0
  3. package/dist/deliverables.test.d.ts +2 -0
  4. package/dist/deliverables.test.d.ts.map +1 -0
  5. package/dist/deliverables.test.js +232 -0
  6. package/dist/deliverables.test.js.map +1 -0
  7. package/dist/domain/entities.d.ts +25 -1
  8. package/dist/domain/entities.d.ts.map +1 -1
  9. package/dist/domain/entities.js +153 -0
  10. package/dist/domain/entities.js.map +1 -1
  11. package/dist/domain/events.d.ts +31 -3
  12. package/dist/domain/events.d.ts.map +1 -1
  13. package/dist/domain/events.js.map +1 -1
  14. package/dist/engine/index.d.ts +9 -1
  15. package/dist/engine/index.d.ts.map +1 -1
  16. package/dist/engine/index.js +173 -2
  17. package/dist/engine/index.js.map +1 -1
  18. package/dist/index.test.js +28 -0
  19. package/dist/index.test.js.map +1 -1
  20. package/dist/store/firebase.d.ts +6 -1
  21. package/dist/store/firebase.d.ts.map +1 -1
  22. package/dist/store/firebase.js +41 -0
  23. package/dist/store/firebase.js.map +1 -1
  24. package/dist/store/index.d.ts +15 -2
  25. package/dist/store/index.d.ts.map +1 -1
  26. package/dist/store/index.js +38 -0
  27. package/dist/store/index.js.map +1 -1
  28. package/dist/store/sqlite.d.ts +7 -1
  29. package/dist/store/sqlite.d.ts.map +1 -1
  30. package/dist/store/sqlite.js +103 -6
  31. package/dist/store/sqlite.js.map +1 -1
  32. package/dist/types/index.d.ts +41 -1
  33. package/dist/types/index.d.ts.map +1 -1
  34. package/dist/utils/workflow.d.ts +2 -0
  35. package/dist/utils/workflow.d.ts.map +1 -1
  36. package/dist/utils/workflow.js +64 -0
  37. package/dist/utils/workflow.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/deliverables.test.ts +284 -0
  40. package/src/domain/entities.ts +185 -2
  41. package/src/domain/events.ts +28 -3
  42. package/src/engine/index.ts +197 -2
  43. package/src/index.test.ts +33 -0
  44. package/src/store/firebase.ts +47 -1
  45. package/src/store/index.ts +54 -1
  46. package/src/store/sqlite.ts +146 -5
  47. package/src/types/index.ts +60 -1
  48. package/src/utils/workflow.ts +77 -0
  49. package/tsconfig.tsbuildinfo +1 -1
@@ -12,7 +12,9 @@ import type {
12
12
  Activity,
13
13
  Webhook,
14
14
  TaskDependency,
15
- Workflow
15
+ Workflow,
16
+ Deliverable,
17
+ CreateDeliverableInput
16
18
  } from '../types/index.js';
17
19
  import { generateProjectKey } from '../utils/key.js';
18
20
 
@@ -111,11 +113,13 @@ export class SQLiteStore implements StorageAdapter {
111
113
  priority TEXT NOT NULL,
112
114
  taskType TEXT,
113
115
  assigneeId TEXT,
116
+ assignees TEXT,
114
117
  reporterId TEXT,
115
118
  reviewerId TEXT,
116
119
  iterationId TEXT,
117
120
  teamId TEXT,
118
121
  containerId TEXT,
122
+ deliverableId TEXT,
119
123
  plannedStartDate TEXT,
120
124
  actualStartDate TEXT,
121
125
  actualEndDate TEXT,
@@ -135,6 +139,24 @@ export class SQLiteStore implements StorageAdapter {
135
139
  updatedAt TEXT NOT NULL
136
140
  );
137
141
 
142
+ CREATE TABLE IF NOT EXISTS deliverables (
143
+ id TEXT PRIMARY KEY,
144
+ projectId TEXT NOT NULL,
145
+ title TEXT NOT NULL,
146
+ description TEXT,
147
+ status TEXT NOT NULL,
148
+ format TEXT,
149
+ specs TEXT,
150
+ leadId TEXT,
151
+ reviewerId TEXT,
152
+ dueDate TEXT,
153
+ deliveredAt TEXT,
154
+ outputUrls TEXT,
155
+ customFields TEXT,
156
+ createdAt TEXT NOT NULL,
157
+ updatedAt TEXT NOT NULL
158
+ );
159
+
138
160
  CREATE TABLE IF NOT EXISTS iterations (
139
161
  id TEXT PRIMARY KEY,
140
162
  projectId TEXT NOT NULL,
@@ -226,6 +248,18 @@ export class SQLiteStore implements StorageAdapter {
226
248
  } catch {
227
249
  // Column may already exist
228
250
  }
251
+
252
+ try {
253
+ this.db.exec('ALTER TABLE tasks ADD COLUMN assignees TEXT');
254
+ } catch {
255
+ // Column may already exist
256
+ }
257
+
258
+ try {
259
+ this.db.exec('ALTER TABLE tasks ADD COLUMN deliverableId TEXT');
260
+ } catch {
261
+ // Column may already exist
262
+ }
229
263
  }
230
264
 
231
265
  // --- Projects ---
@@ -503,6 +537,98 @@ export class SQLiteStore implements StorageAdapter {
503
537
  return (result.changes ?? 0) > 0;
504
538
  }
505
539
 
540
+ // --- Deliverables ---
541
+ async getDeliverables(projectId: string): Promise<Deliverable[]> {
542
+ const stmt = this.db.prepare('SELECT * FROM deliverables WHERE projectId = ?');
543
+ const rows = stmt.all(projectId) as any[];
544
+ return rows.map((r) => this.mapDeliverable(r));
545
+ }
546
+
547
+ async getDeliverable(id: string): Promise<Deliverable | null> {
548
+ const stmt = this.db.prepare('SELECT * FROM deliverables WHERE id = ?');
549
+ const row = stmt.get(id) as any;
550
+ return row ? this.mapDeliverable(row) : null;
551
+ }
552
+
553
+ async createDeliverable(deliverable: CreateDeliverableInput): Promise<Deliverable> {
554
+ const id = `deliv_${Math.random().toString(36).substring(2, 9)}`;
555
+ const now = new Date().toISOString();
556
+ const newDeliverable: Deliverable = {
557
+ ...deliverable,
558
+ id,
559
+ status: deliverable.status || 'planned',
560
+ outputUrls: deliverable.outputUrls ? [...deliverable.outputUrls] : [],
561
+ customFields: deliverable.customFields ? { ...deliverable.customFields } : {},
562
+ createdAt: now,
563
+ updatedAt: now
564
+ };
565
+
566
+ const stmt = this.db.prepare(`
567
+ INSERT INTO deliverables (
568
+ id, projectId, title, description, status, format, specs, leadId, reviewerId,
569
+ dueDate, deliveredAt, outputUrls, customFields, createdAt, updatedAt
570
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
571
+ `);
572
+ stmt.run(
573
+ newDeliverable.id,
574
+ newDeliverable.projectId,
575
+ newDeliverable.title,
576
+ newDeliverable.description || null,
577
+ newDeliverable.status,
578
+ newDeliverable.format || null,
579
+ newDeliverable.specs ? JSON.stringify(newDeliverable.specs) : null,
580
+ newDeliverable.leadId || null,
581
+ newDeliverable.reviewerId || null,
582
+ newDeliverable.dueDate || null,
583
+ newDeliverable.deliveredAt || null,
584
+ JSON.stringify(newDeliverable.outputUrls || []),
585
+ JSON.stringify(newDeliverable.customFields || {}),
586
+ newDeliverable.createdAt,
587
+ newDeliverable.updatedAt
588
+ );
589
+ return newDeliverable;
590
+ }
591
+
592
+ async updateDeliverable(id: string, updates: Partial<Deliverable>): Promise<Deliverable | null> {
593
+ const existing = await this.getDeliverable(id);
594
+ if (!existing) return null;
595
+
596
+ const updated: Deliverable = {
597
+ ...existing,
598
+ ...updates,
599
+ updatedAt: new Date().toISOString()
600
+ };
601
+
602
+ const stmt = this.db.prepare(`
603
+ UPDATE deliverables SET
604
+ title = ?, description = ?, status = ?, format = ?, specs = ?, leadId = ?, reviewerId = ?,
605
+ dueDate = ?, deliveredAt = ?, outputUrls = ?, customFields = ?, updatedAt = ?
606
+ WHERE id = ?
607
+ `);
608
+ stmt.run(
609
+ updated.title,
610
+ updated.description || null,
611
+ updated.status,
612
+ updated.format || null,
613
+ updated.specs ? JSON.stringify(updated.specs) : null,
614
+ updated.leadId || null,
615
+ updated.reviewerId || null,
616
+ updated.dueDate || null,
617
+ updated.deliveredAt || null,
618
+ JSON.stringify(updated.outputUrls || []),
619
+ JSON.stringify(updated.customFields || {}),
620
+ updated.updatedAt,
621
+ id
622
+ );
623
+ return updated;
624
+ }
625
+
626
+ async deleteDeliverable(id: string): Promise<boolean> {
627
+ const stmt = this.db.prepare('DELETE FROM deliverables WHERE id = ?');
628
+ const result = stmt.run(id);
629
+ return (result.changes ?? 0) > 0;
630
+ }
631
+
506
632
  // --- Tasks ---
507
633
  async getTasks(projectId?: string): Promise<Task[]> {
508
634
  let rows: any[];
@@ -529,12 +655,12 @@ export class SQLiteStore implements StorageAdapter {
529
655
 
530
656
  const stmt = this.db.prepare(`
531
657
  INSERT INTO tasks (
532
- id, projectId, title, description, status, priority, taskType, assigneeId, reporterId,
533
- reviewerId, iterationId, teamId, containerId, plannedStartDate, actualStartDate, actualEndDate,
658
+ id, projectId, title, description, status, priority, taskType, assigneeId, assignees, reporterId,
659
+ reviewerId, iterationId, teamId, containerId, deliverableId, plannedStartDate, actualStartDate, actualEndDate,
534
660
  dueDate, estimatedHours, loggedHours, actualHours, billableHours,
535
661
  estimatedDurationMinutes, actualDurationMinutes, billableDurationMinutes, progress,
536
662
  tags, customFields, parentId, createdAt, updatedAt
537
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
663
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
538
664
  `);
539
665
  stmt.run(
540
666
  newTask.id,
@@ -545,11 +671,13 @@ export class SQLiteStore implements StorageAdapter {
545
671
  newTask.priority,
546
672
  newTask.taskType || null,
547
673
  newTask.assigneeId || null,
674
+ newTask.assignees ? JSON.stringify(newTask.assignees) : null,
548
675
  newTask.reporterId || null,
549
676
  newTask.reviewerId || null,
550
677
  newTask.iterationId || null,
551
678
  newTask.teamId || null,
552
679
  newTask.containerId || null,
680
+ newTask.deliverableId || null,
553
681
  newTask.plannedStartDate || null,
554
682
  newTask.actualStartDate || null,
555
683
  newTask.actualEndDate || null,
@@ -584,7 +712,7 @@ export class SQLiteStore implements StorageAdapter {
584
712
  const stmt = this.db.prepare(`
585
713
  UPDATE tasks SET
586
714
  projectId = ?, title = ?, description = ?, status = ?, priority = ?, taskType = ?,
587
- assigneeId = ?, reporterId = ?, reviewerId = ?, iterationId = ?, teamId = ?, containerId = ?,
715
+ assigneeId = ?, assignees = ?, reporterId = ?, reviewerId = ?, iterationId = ?, teamId = ?, containerId = ?, deliverableId = ?,
588
716
  plannedStartDate = ?, actualStartDate = ?, actualEndDate = ?, dueDate = ?,
589
717
  estimatedHours = ?, loggedHours = ?, actualHours = ?, billableHours = ?,
590
718
  estimatedDurationMinutes = ?, actualDurationMinutes = ?, billableDurationMinutes = ?, progress = ?,
@@ -599,11 +727,13 @@ export class SQLiteStore implements StorageAdapter {
599
727
  updated.priority,
600
728
  updated.taskType || null,
601
729
  updated.assigneeId || null,
730
+ updated.assignees ? JSON.stringify(updated.assignees) : null,
602
731
  updated.reporterId || null,
603
732
  updated.reviewerId || null,
604
733
  updated.iterationId || null,
605
734
  updated.teamId || null,
606
735
  updated.containerId || null,
736
+ updated.deliverableId || null,
607
737
  updated.plannedStartDate || null,
608
738
  updated.actualStartDate || null,
609
739
  updated.actualEndDate || null,
@@ -1059,7 +1189,18 @@ export class SQLiteStore implements StorageAdapter {
1059
1189
  return {
1060
1190
  ...row,
1061
1191
  taskType: row.taskType || undefined,
1192
+ deliverableId: row.deliverableId || undefined,
1062
1193
  tags: row.tags ? JSON.parse(row.tags) : [],
1194
+ assignees: row.assignees ? JSON.parse(row.assignees) : undefined,
1195
+ customFields: row.customFields ? JSON.parse(row.customFields) : {}
1196
+ };
1197
+ }
1198
+
1199
+ private mapDeliverable(row: any): Deliverable {
1200
+ return {
1201
+ ...row,
1202
+ specs: row.specs ? JSON.parse(row.specs) : undefined,
1203
+ outputUrls: row.outputUrls ? JSON.parse(row.outputUrls) : [],
1063
1204
  customFields: row.customFields ? JSON.parse(row.customFields) : {}
1064
1205
  };
1065
1206
  }
@@ -127,6 +127,14 @@ export interface TaskTodoItem {
127
127
  completedAt?: string;
128
128
  }
129
129
 
130
+ export interface TaskAssignee {
131
+ id: string;
132
+ name?: string;
133
+ role?: string;
134
+ type?: 'user' | 'agent' | 'team';
135
+ avatarUrl?: string;
136
+ }
137
+
130
138
  export interface Task {
131
139
  id: string;
132
140
  projectId: string;
@@ -137,11 +145,13 @@ export interface Task {
137
145
  priority: Priority;
138
146
  taskType?: string; // e.g. "bug", "feature", "task", "epic"
139
147
  assigneeId?: string;
148
+ assignees?: TaskAssignee[];
140
149
  reporterId?: string;
141
150
  reviewerId?: string;
142
151
  iterationId?: string;
143
152
  teamId?: string;
144
153
  containerId?: string;
154
+ deliverableId?: string; // Direct link to parent deliverable
145
155
  plannedStartDate?: string;
146
156
  actualStartDate?: string;
147
157
  actualEndDate?: string;
@@ -169,6 +179,50 @@ export type CreateTaskInput = Omit<Task, 'id' | 'createdAt' | 'updatedAt' | 'sta
169
179
  priority?: Priority;
170
180
  };
171
181
 
182
+ export type DeliverableStatus =
183
+ | 'draft'
184
+ | 'planned'
185
+ | 'in_production'
186
+ | 'internal_review'
187
+ | 'client_review'
188
+ | 'revision_requested'
189
+ | 'approved'
190
+ | 'delivered'
191
+ | 'canceled'
192
+ | (string & {});
193
+
194
+ export interface Deliverable {
195
+ id: string;
196
+ projectId: string;
197
+ title: string;
198
+ description?: string;
199
+ status: DeliverableStatus;
200
+ format?: string; // e.g., '16:9 4K ProRes', 'Figma', 'PDF'
201
+ specs?: Record<string, unknown>; // Technical specifications (resolution, frame rate, etc.)
202
+ leadId?: string; // Creative director or lead creator
203
+ reviewerId?: string; // Approver or client reviewer
204
+ dueDate?: string;
205
+ deliveredAt?: string;
206
+ outputUrls?: string[]; // Links to final rendered assets, exports, or storage keys
207
+ customFields?: Record<string, unknown>;
208
+ createdAt: string;
209
+ updatedAt: string;
210
+ }
211
+
212
+ export interface DeliverableSummary {
213
+ deliverable: Deliverable;
214
+ totalTasks: number;
215
+ completedTasks: number;
216
+ activeTasks: number;
217
+ progressPercentage: number;
218
+ estimatedHours: number;
219
+ loggedHours: number;
220
+ }
221
+
222
+ export type CreateDeliverableInput = Omit<Deliverable, 'id' | 'createdAt' | 'updatedAt' | 'status'> & {
223
+ status?: DeliverableStatus;
224
+ };
225
+
172
226
  export type CreateProjectInput = Omit<Project, 'id' | 'createdAt' | 'updatedAt'>;
173
227
 
174
228
  export interface Iteration {
@@ -309,7 +363,11 @@ export type WebhookEvent =
309
363
  | 'container.created'
310
364
  | 'workflow.created'
311
365
  | 'workflow.updated'
312
- | 'workflow.deleted';
366
+ | 'workflow.deleted'
367
+ | 'deliverable.created'
368
+ | 'deliverable.updated'
369
+ | 'deliverable.deleted'
370
+ | 'deliverable.status_changed';
313
371
 
314
372
  export interface PluginHooks {
315
373
  beforeTaskCreate?: (task: Partial<Task>) => Promise<Partial<Task>> | Partial<Task>;
@@ -343,5 +401,6 @@ export interface CriticalPathConfig {
343
401
  teams?: Team[];
344
402
  containers?: TaskContainer[];
345
403
  workflows?: Workflow[];
404
+ deliverables?: Deliverable[];
346
405
  };
347
406
  }
@@ -117,6 +117,44 @@ export const DEFAULT_VFX_WORKFLOW: Workflow = {
117
117
  updatedAt: '2026-01-01T00:00:00.000Z'
118
118
  };
119
119
 
120
+ export const DEFAULT_CREATIVE_WORKFLOW: Workflow = {
121
+ id: 'wf_creative_default',
122
+ name: 'Creative Production Workflow',
123
+ description: 'Production pipeline for creative deliverables from briefing and concepts to internal review, client feedback, and final delivery.',
124
+ statuses: [
125
+ { key: 'briefing', label: 'Briefing & Scoping', completionState: 'not_done', executionState: 'inactive' },
126
+ { key: 'concept', label: 'Concept & Storyboarding', completionState: 'not_done', executionState: 'active' },
127
+ { key: 'in_production', label: 'In Production', completionState: 'not_done', executionState: 'active' },
128
+ { key: 'internal_review', label: 'Internal Review', completionState: 'not_done', executionState: 'active' },
129
+ { key: 'client_review', label: 'Client Review', completionState: 'not_done', executionState: 'active' },
130
+ { key: 'revision_requested', label: 'Revision Requested', completionState: 'not_done', executionState: 'active' },
131
+ { key: 'approved', label: 'Approved', completionState: 'done', executionState: 'inactive' },
132
+ { key: 'delivered', label: 'Delivered', completionState: 'done', executionState: 'inactive' },
133
+ DEFAULT_STATUS_DEFINITIONS.canceled
134
+ ],
135
+ transitions: [
136
+ { name: 'Start Concepts', fromStatusKey: 'briefing', toStatusKey: 'concept' },
137
+ { name: 'Approve Concept for Production', fromStatusKey: 'concept', toStatusKey: 'in_production' },
138
+ { name: 'Submit for Internal Review', fromStatusKey: 'in_production', toStatusKey: 'internal_review' },
139
+ { name: 'Submit for Client Review', fromStatusKey: 'internal_review', toStatusKey: 'client_review' },
140
+ { name: 'Request Revisions (Internal)', fromStatusKey: 'internal_review', toStatusKey: 'revision_requested' },
141
+ { name: 'Request Revisions (Client)', fromStatusKey: 'client_review', toStatusKey: 'revision_requested' },
142
+ { name: 'Address Revisions', fromStatusKey: 'revision_requested', toStatusKey: 'in_production' },
143
+ { name: 'Approve Work', fromStatusKey: 'client_review', toStatusKey: 'approved' },
144
+ { name: 'Deliver Final Assets', fromStatusKey: 'approved', toStatusKey: 'delivered' },
145
+ { name: 'Cancel', fromStatusKey: '*', toStatusKey: 'canceled' }
146
+ ],
147
+ taskTypes: [
148
+ { key: 'deliverable', label: 'Deliverable', description: 'Finished asset, cutdown, or packaged export', icon: 'package' },
149
+ { key: 'creative_task', label: 'Creative Task', description: 'Production task (e.g. Design, Copy, Editing, Color)', icon: 'pen-tool' },
150
+ { key: 'review', label: 'Review Gate', description: 'Internal or external client sign-off', icon: 'check-circle' }
151
+ ],
152
+ defaultStatusKey: 'briefing',
153
+ isDefault: false,
154
+ createdAt: '2026-01-01T00:00:00.000Z',
155
+ updatedAt: '2026-01-01T00:00:00.000Z'
156
+ };
157
+
120
158
  export function validateTransition(
121
159
  workflow: Workflow | undefined,
122
160
  fromStatus: string,
@@ -162,3 +200,42 @@ export function getAllowedNextStatuses(
162
200
 
163
201
  return Array.from(allowed);
164
202
  }
203
+
204
+ export function getAllowedPreviousStatuses(
205
+ workflow: Workflow | undefined,
206
+ currentStatus: string
207
+ ): string[] {
208
+ if (!workflow || !workflow.statuses || workflow.statuses.length === 0) {
209
+ return [];
210
+ }
211
+
212
+ const allStatusKeys = workflow.statuses.map((s) => s.key);
213
+ const currentIndex = allStatusKeys.indexOf(currentStatus);
214
+ if (currentIndex <= 0) {
215
+ return [];
216
+ }
217
+
218
+ const previousStatusKeys = allStatusKeys.slice(0, currentIndex);
219
+
220
+ if (workflow.transitions && workflow.transitions.length > 0) {
221
+ const matches = workflow.transitions.filter(
222
+ (t) => t.fromStatusKey === '*' || t.fromStatusKey === currentStatus
223
+ );
224
+
225
+ const allowed = new Set<string>();
226
+ for (const t of matches) {
227
+ if (t.toStatusKey === '*') {
228
+ return previousStatusKeys;
229
+ }
230
+ if (previousStatusKeys.includes(t.toStatusKey)) {
231
+ allowed.add(t.toStatusKey);
232
+ }
233
+ }
234
+
235
+ if (allowed.size > 0) {
236
+ return Array.from(allowed);
237
+ }
238
+ }
239
+
240
+ return [allStatusKeys[currentIndex - 1]];
241
+ }
@@ -1 +1 @@
1
- {"root":["./src/index.test.ts","./src/index.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/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"}