@ginkoai/cli 2.0.5 → 2.1.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 (91) hide show
  1. package/dist/commands/epic/index.d.ts +29 -0
  2. package/dist/commands/epic/index.d.ts.map +1 -0
  3. package/dist/commands/epic/index.js +94 -0
  4. package/dist/commands/epic/index.js.map +1 -0
  5. package/dist/commands/epic/status.d.ts +40 -0
  6. package/dist/commands/epic/status.d.ts.map +1 -0
  7. package/dist/commands/epic/status.js +244 -0
  8. package/dist/commands/epic/status.js.map +1 -0
  9. package/dist/commands/graph/api-client.d.ts +209 -0
  10. package/dist/commands/graph/api-client.d.ts.map +1 -1
  11. package/dist/commands/graph/api-client.js +125 -0
  12. package/dist/commands/graph/api-client.js.map +1 -1
  13. package/dist/commands/graph/load.d.ts.map +1 -1
  14. package/dist/commands/graph/load.js +40 -2
  15. package/dist/commands/graph/load.js.map +1 -1
  16. package/dist/commands/migrate/index.d.ts +27 -0
  17. package/dist/commands/migrate/index.d.ts.map +1 -0
  18. package/dist/commands/migrate/index.js +76 -0
  19. package/dist/commands/migrate/index.js.map +1 -0
  20. package/dist/commands/migrate/status-migration.d.ts +58 -0
  21. package/dist/commands/migrate/status-migration.d.ts.map +1 -0
  22. package/dist/commands/migrate/status-migration.js +323 -0
  23. package/dist/commands/migrate/status-migration.js.map +1 -0
  24. package/dist/commands/sprint/index.d.ts.map +1 -1
  25. package/dist/commands/sprint/index.js +4 -0
  26. package/dist/commands/sprint/index.js.map +1 -1
  27. package/dist/commands/sprint/status.d.ts +42 -0
  28. package/dist/commands/sprint/status.d.ts.map +1 -0
  29. package/dist/commands/sprint/status.js +278 -0
  30. package/dist/commands/sprint/status.js.map +1 -0
  31. package/dist/commands/start/start-reflection.d.ts +39 -0
  32. package/dist/commands/start/start-reflection.d.ts.map +1 -1
  33. package/dist/commands/start/start-reflection.js +311 -91
  34. package/dist/commands/start/start-reflection.js.map +1 -1
  35. package/dist/commands/sync/sprint-syncer.d.ts +19 -12
  36. package/dist/commands/sync/sprint-syncer.d.ts.map +1 -1
  37. package/dist/commands/sync/sprint-syncer.js +58 -140
  38. package/dist/commands/sync/sprint-syncer.js.map +1 -1
  39. package/dist/commands/sync/sync-command.d.ts.map +1 -1
  40. package/dist/commands/sync/sync-command.js +6 -18
  41. package/dist/commands/sync/sync-command.js.map +1 -1
  42. package/dist/commands/task/index.d.ts +25 -0
  43. package/dist/commands/task/index.d.ts.map +1 -0
  44. package/dist/commands/task/index.js +100 -0
  45. package/dist/commands/task/index.js.map +1 -0
  46. package/dist/commands/task/status.d.ts +43 -0
  47. package/dist/commands/task/status.d.ts.map +1 -0
  48. package/dist/commands/task/status.js +301 -0
  49. package/dist/commands/task/status.js.map +1 -0
  50. package/dist/index.js +12 -29
  51. package/dist/index.js.map +1 -1
  52. package/dist/lib/context-loader-events.d.ts +1 -0
  53. package/dist/lib/context-loader-events.d.ts.map +1 -1
  54. package/dist/lib/context-loader-events.js +28 -41
  55. package/dist/lib/context-loader-events.js.map +1 -1
  56. package/dist/lib/output-formatter.d.ts +12 -4
  57. package/dist/lib/output-formatter.d.ts.map +1 -1
  58. package/dist/lib/output-formatter.js +186 -14
  59. package/dist/lib/output-formatter.js.map +1 -1
  60. package/dist/lib/pending-updates.d.ts +148 -0
  61. package/dist/lib/pending-updates.d.ts.map +1 -0
  62. package/dist/lib/pending-updates.js +301 -0
  63. package/dist/lib/pending-updates.js.map +1 -0
  64. package/dist/lib/sprint-loader.d.ts +86 -14
  65. package/dist/lib/sprint-loader.d.ts.map +1 -1
  66. package/dist/lib/sprint-loader.js +293 -98
  67. package/dist/lib/sprint-loader.js.map +1 -1
  68. package/dist/lib/state-cache.d.ts +142 -0
  69. package/dist/lib/state-cache.d.ts.map +1 -0
  70. package/dist/lib/state-cache.js +259 -0
  71. package/dist/lib/state-cache.js.map +1 -0
  72. package/dist/lib/task-graph-sync.d.ts +105 -0
  73. package/dist/lib/task-graph-sync.d.ts.map +1 -0
  74. package/dist/lib/task-graph-sync.js +178 -0
  75. package/dist/lib/task-graph-sync.js.map +1 -0
  76. package/dist/lib/task-parser.d.ts +107 -0
  77. package/dist/lib/task-parser.d.ts.map +1 -0
  78. package/dist/lib/task-parser.js +384 -0
  79. package/dist/lib/task-parser.js.map +1 -0
  80. package/dist/templates/ai-instructions-template.d.ts.map +1 -1
  81. package/dist/templates/ai-instructions-template.js +7 -5
  82. package/dist/templates/ai-instructions-template.js.map +1 -1
  83. package/dist/templates/epic-template.md +0 -2
  84. package/dist/types/config.d.ts.map +1 -1
  85. package/dist/types/config.js +7 -5
  86. package/dist/types/config.js.map +1 -1
  87. package/dist/utils/synthesis.d.ts +4 -0
  88. package/dist/utils/synthesis.d.ts.map +1 -1
  89. package/dist/utils/synthesis.js +12 -18
  90. package/dist/utils/synthesis.js.map +1 -1
  91. package/package.json +1 -1
@@ -0,0 +1,301 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-19
5
+ * @tags: [offline, queue, sync, EPIC-015]
6
+ * @related: [state-cache.ts, api-client.ts]
7
+ * @priority: medium
8
+ * @complexity: medium
9
+ * @dependencies: [fs-extra, path]
10
+ */
11
+ /**
12
+ * Pending Updates Queue (EPIC-015 Sprint 2 Task 6)
13
+ *
14
+ * Provides offline queueing for status updates when API is unavailable:
15
+ * - Queue status updates when offline
16
+ * - Process queued updates when back online
17
+ * - "Local wins" conflict resolution (queued update takes precedence)
18
+ * - Max 3 retry attempts before permanent failure
19
+ *
20
+ * Queue location: .ginko/pending-updates.json
21
+ * Uses atomic writes (temp file + rename) to prevent partial writes.
22
+ */
23
+ import fs from 'fs-extra';
24
+ import path from 'path';
25
+ import { randomUUID } from 'crypto';
26
+ import { getGinkoDir } from '../utils/helpers.js';
27
+ // =============================================================================
28
+ // Constants
29
+ // =============================================================================
30
+ const QUEUE_FILE = 'pending-updates.json';
31
+ const QUEUE_VERSION = 1;
32
+ const MAX_ATTEMPTS = 3;
33
+ // =============================================================================
34
+ // Queue Management
35
+ // =============================================================================
36
+ /**
37
+ * Load pending updates from disk
38
+ *
39
+ * @returns Array of pending updates, empty array if no queue file exists
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const updates = await loadPendingUpdates();
44
+ * console.log(`${updates.length} updates pending`);
45
+ * ```
46
+ */
47
+ export async function loadPendingUpdates() {
48
+ try {
49
+ const queuePath = await getQueuePath();
50
+ if (!await fs.pathExists(queuePath)) {
51
+ return [];
52
+ }
53
+ const data = await fs.readJSON(queuePath);
54
+ // Validate queue structure
55
+ if (!isValidQueue(data)) {
56
+ return [];
57
+ }
58
+ return data.updates || [];
59
+ }
60
+ catch (error) {
61
+ // File doesn't exist, is invalid JSON, or other read error
62
+ return [];
63
+ }
64
+ }
65
+ /**
66
+ * Queue a status update for later sync
67
+ * Used when API call fails due to network error
68
+ *
69
+ * @param update - Update to queue (id, queued_at, attempts added automatically)
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * await queueUpdate({
74
+ * type: 'task_status',
75
+ * entity_id: 'e015_s02_t01',
76
+ * new_status: 'complete'
77
+ * });
78
+ * ```
79
+ */
80
+ export async function queueUpdate(update) {
81
+ const updates = await loadPendingUpdates();
82
+ // Check if there's already a pending update for this entity
83
+ // If so, replace it (latest update wins)
84
+ const existingIndex = updates.findIndex(u => u.entity_id === update.entity_id && u.type === update.type);
85
+ const newUpdate = {
86
+ id: randomUUID(),
87
+ ...update,
88
+ queued_at: new Date().toISOString(),
89
+ attempts: 0,
90
+ };
91
+ if (existingIndex >= 0) {
92
+ // Replace existing update for same entity
93
+ updates[existingIndex] = newUpdate;
94
+ }
95
+ else {
96
+ // Add new update
97
+ updates.push(newUpdate);
98
+ }
99
+ await saveQueue(updates);
100
+ }
101
+ /**
102
+ * Remove a specific update from the queue
103
+ *
104
+ * @param updateId - UUID of the update to remove
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * await removeUpdate('abc-123-def');
109
+ * ```
110
+ */
111
+ export async function removeUpdate(updateId) {
112
+ const updates = await loadPendingUpdates();
113
+ const filtered = updates.filter(u => u.id !== updateId);
114
+ if (filtered.length !== updates.length) {
115
+ await saveQueue(filtered);
116
+ }
117
+ }
118
+ /**
119
+ * Clear all pending updates from the queue
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * await clearPendingUpdates();
124
+ * ```
125
+ */
126
+ export async function clearPendingUpdates() {
127
+ try {
128
+ const queuePath = await getQueuePath();
129
+ if (await fs.pathExists(queuePath)) {
130
+ await fs.remove(queuePath);
131
+ }
132
+ }
133
+ catch (error) {
134
+ // Ignore errors when clearing queue
135
+ }
136
+ }
137
+ /**
138
+ * Check if there are pending updates
139
+ *
140
+ * @returns true if queue has at least one update
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * if (await hasPendingUpdates()) {
145
+ * console.log('Pending updates need to sync');
146
+ * }
147
+ * ```
148
+ */
149
+ export async function hasPendingUpdates() {
150
+ const updates = await loadPendingUpdates();
151
+ return updates.length > 0;
152
+ }
153
+ // =============================================================================
154
+ // Sync Processing
155
+ // =============================================================================
156
+ /**
157
+ * Process all pending updates, syncing them to the API
158
+ *
159
+ * Processing logic:
160
+ * - Iterates oldest-first (FIFO order)
161
+ * - On success: removes update from queue
162
+ * - On failure: increments attempts, keeps in queue (max 3 attempts)
163
+ * - Conflict resolution: "local wins" (queued update takes precedence)
164
+ *
165
+ * @param client - Authenticated GraphApiClient instance
166
+ * @returns Counts of succeeded and failed updates
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const client = new GraphApiClient();
171
+ * const result = await processPendingUpdates(client);
172
+ * console.log(`Synced ${result.succeeded}, failed ${result.failed}`);
173
+ * ```
174
+ */
175
+ export async function processPendingUpdates(client) {
176
+ const updates = await loadPendingUpdates();
177
+ if (updates.length === 0) {
178
+ return { succeeded: 0, failed: 0 };
179
+ }
180
+ let succeeded = 0;
181
+ let failed = 0;
182
+ const remaining = [];
183
+ // Get graph ID from environment
184
+ const graphId = process.env.GINKO_GRAPH_ID || '';
185
+ if (!graphId) {
186
+ // Can't process without graph ID, keep all updates
187
+ return { succeeded: 0, failed: updates.length };
188
+ }
189
+ // Sort by queued_at to process oldest first
190
+ const sortedUpdates = [...updates].sort((a, b) => new Date(a.queued_at).getTime() - new Date(b.queued_at).getTime());
191
+ for (const update of sortedUpdates) {
192
+ try {
193
+ await processUpdate(client, graphId, update);
194
+ succeeded++;
195
+ // Don't add to remaining - it was successful
196
+ }
197
+ catch (error) {
198
+ // Increment attempts
199
+ update.attempts++;
200
+ if (update.attempts >= MAX_ATTEMPTS) {
201
+ // Max attempts reached, count as failed and don't keep
202
+ failed++;
203
+ }
204
+ else {
205
+ // Keep in queue for retry
206
+ remaining.push(update);
207
+ failed++;
208
+ }
209
+ }
210
+ }
211
+ // Save remaining updates (excluding succeeded and permanently failed)
212
+ await saveQueue(remaining);
213
+ return { succeeded, failed };
214
+ }
215
+ /**
216
+ * Process a single update by calling the appropriate API method
217
+ */
218
+ async function processUpdate(client, graphId, update) {
219
+ switch (update.type) {
220
+ case 'task_status':
221
+ await client.updateTaskStatus(graphId, update.entity_id, update.new_status, update.reason);
222
+ break;
223
+ case 'sprint_status':
224
+ await client.updateSprintStatus(graphId, update.entity_id, update.new_status);
225
+ break;
226
+ case 'epic_status':
227
+ await client.updateEpicStatus(graphId, update.entity_id, update.new_status);
228
+ break;
229
+ default:
230
+ throw new Error(`Unknown update type: ${update.type}`);
231
+ }
232
+ }
233
+ // =============================================================================
234
+ // Helper Functions
235
+ // =============================================================================
236
+ /**
237
+ * Get the full path to the queue file
238
+ */
239
+ async function getQueuePath() {
240
+ const ginkoDir = await getGinkoDir();
241
+ return path.join(ginkoDir, QUEUE_FILE);
242
+ }
243
+ /**
244
+ * Save updates to queue file using atomic write
245
+ */
246
+ async function saveQueue(updates) {
247
+ const queuePath = await getQueuePath();
248
+ const queueDir = path.dirname(queuePath);
249
+ const tempPath = `${queuePath}.tmp.${Date.now()}`;
250
+ // Ensure .ginko directory exists
251
+ await fs.ensureDir(queueDir);
252
+ const queue = {
253
+ version: QUEUE_VERSION,
254
+ updates,
255
+ };
256
+ // Atomic write: write to temp file, then rename
257
+ try {
258
+ await fs.writeJSON(tempPath, queue, { spaces: 2 });
259
+ await fs.rename(tempPath, queuePath);
260
+ }
261
+ catch (error) {
262
+ // Clean up temp file if rename failed
263
+ try {
264
+ await fs.remove(tempPath);
265
+ }
266
+ catch {
267
+ // Ignore cleanup errors
268
+ }
269
+ throw error;
270
+ }
271
+ }
272
+ /**
273
+ * Validate that queue data has correct structure and version
274
+ */
275
+ function isValidQueue(data) {
276
+ if (!data || typeof data !== 'object') {
277
+ return false;
278
+ }
279
+ const queue = data;
280
+ // Check version
281
+ if (queue.version !== QUEUE_VERSION) {
282
+ return false;
283
+ }
284
+ // Check updates array exists
285
+ if (!Array.isArray(queue.updates)) {
286
+ return false;
287
+ }
288
+ return true;
289
+ }
290
+ // =============================================================================
291
+ // Exports for Testing
292
+ // =============================================================================
293
+ export const _internal = {
294
+ getQueuePath,
295
+ saveQueue,
296
+ isValidQueue,
297
+ processUpdate,
298
+ QUEUE_VERSION,
299
+ MAX_ATTEMPTS,
300
+ };
301
+ //# sourceMappingURL=pending-updates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-updates.js","sourceRoot":"","sources":["../../src/lib/pending-updates.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,49 @@
1
1
  /**
2
2
  * @fileType: utility
3
3
  * @status: current
4
- * @updated: 2025-11-21
5
- * @tags: [sprint, task-checklist, epic-001, session-context]
6
- * @related: [charter-loader.ts, start-reflection.ts, context-loader-events.ts]
4
+ * @updated: 2026-01-19
5
+ * @tags: [sprint, task-content, epic-015, session-context]
6
+ * @related: [charter-loader.ts, start-reflection.ts, context-loader-events.ts, task-extractor.ts]
7
7
  * @priority: high
8
8
  * @complexity: medium
9
9
  * @dependencies: [fs-extra, path]
10
10
  */
11
11
  /**
12
- * Task state enumeration
12
+ * Task state enumeration (kept for backward compatibility)
13
+ * NOTE: As of EPIC-015 Sprint 2, status comes from the graph API.
14
+ * File parsing defaults all tasks to 'todo'. Merge with graph status at runtime.
13
15
  * - todo: [ ] Not started
14
16
  * - in_progress: [@] Currently being worked on
15
17
  * - paused: [Z] Temporarily on hold (sleeping)
16
18
  * - complete: [x] Finished
17
19
  */
18
20
  export type TaskState = 'todo' | 'in_progress' | 'paused' | 'complete';
21
+ /**
22
+ * Task content extracted from sprint markdown (no status)
23
+ * Status comes from graph API and is merged at runtime.
24
+ */
25
+ export interface TaskContent {
26
+ id: string;
27
+ title: string;
28
+ files?: string[];
29
+ effort?: string;
30
+ priority?: string;
31
+ relatedADRs?: string[];
32
+ relatedPatterns?: string[];
33
+ relatedGotchas?: string[];
34
+ acceptanceCriteria?: AcceptanceCriterion[];
35
+ dependsOn?: string[];
36
+ }
37
+ /**
38
+ * Sprint content extracted from markdown (no status-based progress)
39
+ * Status/progress comes from graph API and is merged at runtime.
40
+ */
41
+ export interface SprintContent {
42
+ name: string;
43
+ file: string;
44
+ tasks: TaskContent[];
45
+ dependencyWarnings?: string[];
46
+ }
19
47
  /**
20
48
  * Acceptance criterion type - auto-detected from description (EPIC-004 Sprint 3)
21
49
  * - test: Unit tests, specs, test suites
@@ -37,7 +65,9 @@ export interface AcceptanceCriterion {
37
65
  command?: string;
38
66
  }
39
67
  /**
40
- * Individual task from sprint checklist
68
+ * Individual task from sprint checklist (backward compatible interface)
69
+ * NOTE: As of EPIC-015 Sprint 2, state defaults to 'todo' from file parsing.
70
+ * Actual status should be merged from graph API at runtime.
41
71
  */
42
72
  export interface Task {
43
73
  id: string;
@@ -54,7 +84,9 @@ export interface Task {
54
84
  dependsOn?: string[];
55
85
  }
56
86
  /**
57
- * Sprint checklist with task states and progress
87
+ * Sprint checklist with task states and progress (backward compatible interface)
88
+ * NOTE: As of EPIC-015 Sprint 2, progress values will be zeroed from file parsing.
89
+ * Actual progress should be calculated from graph API status at runtime.
58
90
  */
59
91
  export interface SprintChecklist {
60
92
  name: string;
@@ -75,11 +107,12 @@ export interface SprintChecklist {
75
107
  * Find active sprint file
76
108
  *
77
109
  * Priority:
78
- * 1. Check CURRENT-SPRINT.md for "Between Sprints" status → return null
79
- * 2. Check CURRENT-SPRINT.md for sprint reference → return that file
80
- * 3. Fall back to scanning SPRINT-*.md files for first incomplete one
110
+ * 1. Scan SPRINT-*.md files for first incomplete one
81
111
  * - Respects frontmatter `status` field: active > not_started > (skip paused/complete)
82
112
  *
113
+ * EPIC-015 Sprint 3: CURRENT-SPRINT.md is deprecated. Sprint state now comes from
114
+ * the graph API, not from a local file. This function only scans actual sprint files.
115
+ *
83
116
  * Valid status values:
84
117
  * - active: Currently being worked on
85
118
  * - not_started: Planned but not yet started
@@ -93,25 +126,57 @@ export interface SprintChecklist {
93
126
  */
94
127
  export declare function findActiveSprint(projectRoot?: string): Promise<string | null>;
95
128
  /**
96
- * Parse sprint markdown into task checklist
129
+ * Parse sprint markdown into task checklist (backward compatible)
130
+ *
131
+ * EPIC-015 Sprint 2: Status parsing removed. All tasks default to 'todo'.
132
+ * Status should be merged from graph API at runtime.
97
133
  *
98
134
  * Looks for:
99
135
  * - Sprint name from title (# SPRINT: ...)
100
136
  * - Tasks from ## Sprint Tasks or ### TASK-N sections
101
- * - Checkbox states: [ ], [@], [Z], [x]
102
- * - Task metadata (files, priority, effort)
137
+ * - Task metadata (files, priority, effort, dependencies)
138
+ * - Related knowledge (ADRs, patterns, gotchas)
139
+ * - Acceptance criteria
103
140
  *
104
141
  * @param markdown - Sprint markdown content
105
142
  * @param filePath - Path to sprint file
106
- * @returns Parsed sprint checklist
143
+ * @returns Parsed sprint checklist (all tasks with state: 'todo')
107
144
  */
108
145
  export declare function parseSprintChecklist(markdown: string, filePath: string): SprintChecklist;
109
146
  /**
110
- * Load active sprint checklist
147
+ * Parse sprint markdown into content-only structure (no status)
148
+ *
149
+ * EPIC-015 Sprint 2: New content-focused parsing function.
150
+ * Extracts task content (ID, title, metadata, relationships) without status.
151
+ * Status should be fetched from graph API and merged separately.
152
+ *
153
+ * @param markdown - Sprint markdown content
154
+ * @param filePath - Path to sprint file
155
+ * @returns Parsed sprint content (no status information)
156
+ */
157
+ export declare function parseSprintContent(markdown: string, filePath: string): SprintContent;
158
+ /**
159
+ * Load active sprint content (no status)
160
+ *
161
+ * EPIC-015 Sprint 2: New content-focused loading function.
162
+ * Finds active sprint file and parses content without status.
163
+ * Status should be fetched from graph API and merged separately.
164
+ *
165
+ * @param projectRoot - Project root directory (defaults to git root)
166
+ * @param sprintFilePath - Optional specific sprint file path
167
+ * @returns Parsed sprint content or null if no sprint found
168
+ */
169
+ export declare function loadSprintContent(projectRoot?: string, sprintFilePath?: string): Promise<SprintContent | null>;
170
+ /**
171
+ * Load active sprint checklist (backward compatible)
172
+ *
173
+ * EPIC-015 Sprint 2: This function maintained for backward compatibility.
174
+ * All tasks will have state: 'todo'. Merge with graph API status at runtime.
111
175
  *
112
176
  * Finds active sprint file and parses into structured checklist
113
177
  *
114
178
  * @param projectRoot - Project root directory (defaults to git root)
179
+ * @param sprintFilePath - Optional specific sprint file path
115
180
  * @returns Parsed sprint checklist or null if no sprint found
116
181
  */
117
182
  export declare function loadSprintChecklist(projectRoot?: string, sprintFilePath?: string): Promise<SprintChecklist | null>;
@@ -146,6 +211,13 @@ export interface SprintProgressionInfo {
146
211
  totalSprints: number;
147
212
  completedSprints: number;
148
213
  }
214
+ /**
215
+ * Find sprint file by ID
216
+ * @param sprintId - Sprint ID (e.g., 'e011_s01' or 'e016_s03')
217
+ * @param projectRoot - Project root directory
218
+ * @returns Path to sprint file or null if not found
219
+ */
220
+ export declare function findSprintFileById(sprintId: string, projectRoot: string): Promise<string | null>;
149
221
  /**
150
222
  * Detect sprint progression and epic completion status
151
223
  *
@@ -1 +1 @@
1
- {"version":3,"file":"sprint-loader.d.ts","sourceRoot":"","sources":["../../src/lib/sprint-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sprint-loader.d.ts","sourceRoot":"","sources":["../../src/lib/sprint-loader.ts"],"names":[],"mappings":"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"}