@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,142 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-19
5
+ * @tags: [cache, offline, state, EPIC-015]
6
+ * @related: [staleness-detector.ts, user-sprint.ts, start-reflection.ts]
7
+ * @priority: high
8
+ * @complexity: medium
9
+ * @dependencies: [fs-extra, path]
10
+ */
11
+ /**
12
+ * Data about the active sprint for display
13
+ */
14
+ export interface ActiveSprintData {
15
+ sprintId: string;
16
+ sprintName: string;
17
+ epicId: string;
18
+ epicName?: string;
19
+ progress: {
20
+ completed: number;
21
+ total: number;
22
+ percentage: number;
23
+ };
24
+ currentTask?: {
25
+ taskId: string;
26
+ taskName: string;
27
+ status: 'pending' | 'in_progress' | 'completed';
28
+ };
29
+ nextTask?: {
30
+ taskId: string;
31
+ taskName: string;
32
+ };
33
+ }
34
+ /**
35
+ * Cached state structure
36
+ */
37
+ export interface StateCache {
38
+ version: 1;
39
+ fetched_at: string;
40
+ graph_id: string;
41
+ active_sprint: ActiveSprintData;
42
+ }
43
+ /**
44
+ * Result of checking cache staleness
45
+ */
46
+ export interface CacheStalenessResult {
47
+ level: 'fresh' | 'stale' | 'expired';
48
+ age: number;
49
+ ageHuman: string;
50
+ isFresh: boolean;
51
+ showWarning: boolean;
52
+ }
53
+ /**
54
+ * Load cached state from disk
55
+ *
56
+ * @returns StateCache if valid cache exists, null otherwise
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const cache = await loadStateCache();
61
+ * if (cache) {
62
+ * console.log(`Sprint: ${cache.active_sprint.sprintName}`);
63
+ * }
64
+ * ```
65
+ */
66
+ export declare function loadStateCache(): Promise<StateCache | null>;
67
+ /**
68
+ * Save state data to cache
69
+ * Uses atomic write (temp file + rename) to prevent partial writes
70
+ *
71
+ * @param data - Active sprint data to cache
72
+ * @param graphId - The graph ID this data belongs to
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * await saveStateCache(sprintData, 'graph-123');
77
+ * ```
78
+ */
79
+ export declare function saveStateCache(data: ActiveSprintData, graphId: string): Promise<void>;
80
+ /**
81
+ * Clear the state cache
82
+ * Called when cache should be invalidated (e.g., logout, graph switch)
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * await clearStateCache();
87
+ * ```
88
+ */
89
+ export declare function clearStateCache(): Promise<void>;
90
+ /**
91
+ * Check staleness of cached state
92
+ *
93
+ * Staleness levels:
94
+ * - fresh: < 5 minutes old
95
+ * - stale: 5 minutes to 24 hours old
96
+ * - expired: > 24 hours old
97
+ *
98
+ * @param cache - The cached state to check
99
+ * @returns Staleness result with level, age, and display info
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const cache = await loadStateCache();
104
+ * if (cache) {
105
+ * const staleness = checkCacheStaleness(cache);
106
+ * if (staleness.showWarning) {
107
+ * console.log(`Cache is ${staleness.level}: ${staleness.ageHuman}`);
108
+ * }
109
+ * }
110
+ * ```
111
+ */
112
+ export declare function checkCacheStaleness(cache: StateCache): CacheStalenessResult;
113
+ /**
114
+ * Format cache age for human-readable display
115
+ *
116
+ * @param fetchedAt - ISO timestamp string
117
+ * @returns Human-readable age string (e.g., "15 min ago", "2 hours ago")
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * const age = formatCacheAge('2026-01-19T10:00:00.000Z');
122
+ * // Returns something like "15 min ago"
123
+ * ```
124
+ */
125
+ export declare function formatCacheAge(fetchedAt: string): string;
126
+ /**
127
+ * Get the full path to the cache file
128
+ */
129
+ declare function getCachePath(): Promise<string>;
130
+ /**
131
+ * Validate that cache data has correct structure and version
132
+ */
133
+ declare function isValidCache(data: unknown): data is StateCache;
134
+ export declare const _internal: {
135
+ getCachePath: typeof getCachePath;
136
+ isValidCache: typeof isValidCache;
137
+ FRESH_THRESHOLD_MS: number;
138
+ EXPIRED_THRESHOLD_MS: number;
139
+ CACHE_VERSION: number;
140
+ };
141
+ export {};
142
+ //# sourceMappingURL=state-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-cache.d.ts","sourceRoot":"","sources":["../../src/lib/state-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;KACjD,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,gBAAgB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;CACtB;AAiBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoBjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAUrD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,CAsB3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAwBxD;AAMD;;GAEG;AACH,iBAAe,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAG7C;AAED;;GAEG;AACH,iBAAS,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,UAAU,CAsCvD;AAMD,eAAO,MAAM,SAAS;;;;;;CAMrB,CAAC"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-19
5
+ * @tags: [cache, offline, state, EPIC-015]
6
+ * @related: [staleness-detector.ts, user-sprint.ts, start-reflection.ts]
7
+ * @priority: high
8
+ * @complexity: medium
9
+ * @dependencies: [fs-extra, path]
10
+ */
11
+ /**
12
+ * Local State Cache (EPIC-015 Sprint 2)
13
+ *
14
+ * Provides local caching for API state data to enable:
15
+ * - Offline operation when API is unavailable
16
+ * - Faster startup by avoiding API calls for fresh data
17
+ * - Graceful degradation with staleness indicators
18
+ *
19
+ * Cache location: .ginko/state-cache.json
20
+ * Uses atomic writes (temp file + rename) to prevent partial writes.
21
+ */
22
+ import fs from 'fs-extra';
23
+ import path from 'path';
24
+ import { getGinkoDir } from '../utils/helpers.js';
25
+ // =============================================================================
26
+ // Constants
27
+ // =============================================================================
28
+ const CACHE_FILE = 'state-cache.json';
29
+ const CACHE_VERSION = 1;
30
+ // Staleness thresholds in milliseconds
31
+ const FRESH_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes
32
+ const EXPIRED_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
33
+ // =============================================================================
34
+ // Main API
35
+ // =============================================================================
36
+ /**
37
+ * Load cached state from disk
38
+ *
39
+ * @returns StateCache if valid cache exists, null otherwise
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const cache = await loadStateCache();
44
+ * if (cache) {
45
+ * console.log(`Sprint: ${cache.active_sprint.sprintName}`);
46
+ * }
47
+ * ```
48
+ */
49
+ export async function loadStateCache() {
50
+ try {
51
+ const cachePath = await getCachePath();
52
+ if (!await fs.pathExists(cachePath)) {
53
+ return null;
54
+ }
55
+ const data = await fs.readJSON(cachePath);
56
+ // Validate cache version and required fields
57
+ if (!isValidCache(data)) {
58
+ return null;
59
+ }
60
+ return data;
61
+ }
62
+ catch (error) {
63
+ // File doesn't exist, is invalid JSON, or other read error
64
+ return null;
65
+ }
66
+ }
67
+ /**
68
+ * Save state data to cache
69
+ * Uses atomic write (temp file + rename) to prevent partial writes
70
+ *
71
+ * @param data - Active sprint data to cache
72
+ * @param graphId - The graph ID this data belongs to
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * await saveStateCache(sprintData, 'graph-123');
77
+ * ```
78
+ */
79
+ export async function saveStateCache(data, graphId) {
80
+ const cachePath = await getCachePath();
81
+ const cacheDir = path.dirname(cachePath);
82
+ const tempPath = `${cachePath}.tmp.${Date.now()}`;
83
+ // Ensure .ginko directory exists
84
+ await fs.ensureDir(cacheDir);
85
+ const cache = {
86
+ version: CACHE_VERSION,
87
+ fetched_at: new Date().toISOString(),
88
+ graph_id: graphId,
89
+ active_sprint: data,
90
+ };
91
+ // Atomic write: write to temp file, then rename
92
+ try {
93
+ await fs.writeJSON(tempPath, cache, { spaces: 2 });
94
+ await fs.rename(tempPath, cachePath);
95
+ }
96
+ catch (error) {
97
+ // Clean up temp file if rename failed
98
+ try {
99
+ await fs.remove(tempPath);
100
+ }
101
+ catch {
102
+ // Ignore cleanup errors
103
+ }
104
+ throw error;
105
+ }
106
+ }
107
+ /**
108
+ * Clear the state cache
109
+ * Called when cache should be invalidated (e.g., logout, graph switch)
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * await clearStateCache();
114
+ * ```
115
+ */
116
+ export async function clearStateCache() {
117
+ try {
118
+ const cachePath = await getCachePath();
119
+ if (await fs.pathExists(cachePath)) {
120
+ await fs.remove(cachePath);
121
+ }
122
+ }
123
+ catch (error) {
124
+ // Ignore errors when clearing cache
125
+ }
126
+ }
127
+ /**
128
+ * Check staleness of cached state
129
+ *
130
+ * Staleness levels:
131
+ * - fresh: < 5 minutes old
132
+ * - stale: 5 minutes to 24 hours old
133
+ * - expired: > 24 hours old
134
+ *
135
+ * @param cache - The cached state to check
136
+ * @returns Staleness result with level, age, and display info
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * const cache = await loadStateCache();
141
+ * if (cache) {
142
+ * const staleness = checkCacheStaleness(cache);
143
+ * if (staleness.showWarning) {
144
+ * console.log(`Cache is ${staleness.level}: ${staleness.ageHuman}`);
145
+ * }
146
+ * }
147
+ * ```
148
+ */
149
+ export function checkCacheStaleness(cache) {
150
+ const fetchedAt = new Date(cache.fetched_at);
151
+ const now = new Date();
152
+ const ageMs = now.getTime() - fetchedAt.getTime();
153
+ let level;
154
+ if (ageMs < FRESH_THRESHOLD_MS) {
155
+ level = 'fresh';
156
+ }
157
+ else if (ageMs < EXPIRED_THRESHOLD_MS) {
158
+ level = 'stale';
159
+ }
160
+ else {
161
+ level = 'expired';
162
+ }
163
+ return {
164
+ level,
165
+ age: ageMs,
166
+ ageHuman: formatCacheAge(cache.fetched_at),
167
+ isFresh: level === 'fresh',
168
+ showWarning: level !== 'fresh',
169
+ };
170
+ }
171
+ /**
172
+ * Format cache age for human-readable display
173
+ *
174
+ * @param fetchedAt - ISO timestamp string
175
+ * @returns Human-readable age string (e.g., "15 min ago", "2 hours ago")
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const age = formatCacheAge('2026-01-19T10:00:00.000Z');
180
+ * // Returns something like "15 min ago"
181
+ * ```
182
+ */
183
+ export function formatCacheAge(fetchedAt) {
184
+ const date = new Date(fetchedAt);
185
+ const now = new Date();
186
+ const diffMs = now.getTime() - date.getTime();
187
+ const diffSecs = Math.floor(diffMs / 1000);
188
+ const diffMins = Math.floor(diffMs / (1000 * 60));
189
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
190
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
191
+ if (diffSecs < 60) {
192
+ return 'just now';
193
+ }
194
+ if (diffMins < 60) {
195
+ return `${diffMins} min ago`;
196
+ }
197
+ if (diffHours < 24) {
198
+ return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;
199
+ }
200
+ if (diffDays < 7) {
201
+ return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
202
+ }
203
+ return date.toLocaleDateString();
204
+ }
205
+ // =============================================================================
206
+ // Helper Functions
207
+ // =============================================================================
208
+ /**
209
+ * Get the full path to the cache file
210
+ */
211
+ async function getCachePath() {
212
+ const ginkoDir = await getGinkoDir();
213
+ return path.join(ginkoDir, CACHE_FILE);
214
+ }
215
+ /**
216
+ * Validate that cache data has correct structure and version
217
+ */
218
+ function isValidCache(data) {
219
+ if (!data || typeof data !== 'object') {
220
+ return false;
221
+ }
222
+ const cache = data;
223
+ // Check version
224
+ if (cache.version !== CACHE_VERSION) {
225
+ return false;
226
+ }
227
+ // Check required fields
228
+ if (!cache.fetched_at || typeof cache.fetched_at !== 'string') {
229
+ return false;
230
+ }
231
+ if (!cache.graph_id || typeof cache.graph_id !== 'string') {
232
+ return false;
233
+ }
234
+ if (!cache.active_sprint || typeof cache.active_sprint !== 'object') {
235
+ return false;
236
+ }
237
+ // Validate active_sprint structure
238
+ const sprint = cache.active_sprint;
239
+ if (!sprint.sprintId || !sprint.sprintName || !sprint.epicId) {
240
+ return false;
241
+ }
242
+ if (!sprint.progress || typeof sprint.progress.completed !== 'number' ||
243
+ typeof sprint.progress.total !== 'number' ||
244
+ typeof sprint.progress.percentage !== 'number') {
245
+ return false;
246
+ }
247
+ return true;
248
+ }
249
+ // =============================================================================
250
+ // Exports for Testing
251
+ // =============================================================================
252
+ export const _internal = {
253
+ getCachePath,
254
+ isValidCache,
255
+ FRESH_THRESHOLD_MS,
256
+ EXPIRED_THRESHOLD_MS,
257
+ CACHE_VERSION,
258
+ };
259
+ //# sourceMappingURL=state-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-cache.js","sourceRoot":"","sources":["../../src/lib/state-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @fileType: utility
3
+ * @status: current
4
+ * @updated: 2026-01-19
5
+ * @tags: [task-sync, graph, neo4j, epic-015, sprint-0a]
6
+ * @related: [task-parser.ts, ../commands/graph/api-client.ts]
7
+ * @priority: high
8
+ * @complexity: medium
9
+ * @dependencies: [api-client]
10
+ */
11
+ /**
12
+ * Task Graph Sync (EPIC-015 Sprint 0a Tasks 2-3)
13
+ *
14
+ * Syncs parsed tasks to Neo4j graph via the dashboard API.
15
+ * Creates Task nodes and BELONGS_TO relationships.
16
+ *
17
+ * Key principle (ADR-060): Content from Git, State from Graph.
18
+ * - On CREATE: Uses initial_status from markdown
19
+ * - On UPDATE: Preserves existing status (graph-authoritative)
20
+ */
21
+ import { GraphApiClient } from '../commands/graph/api-client.js';
22
+ import { ParsedTask, SprintParseResult } from './task-parser.js';
23
+ /**
24
+ * Response from task sync API
25
+ */
26
+ export interface TaskSyncResponse {
27
+ success: boolean;
28
+ created: number;
29
+ updated: number;
30
+ relationships: number;
31
+ tasks: string[];
32
+ }
33
+ /**
34
+ * Options for task sync
35
+ */
36
+ export interface TaskSyncOptions {
37
+ /** Create BELONGS_TO relationships (default: true) */
38
+ createRelationships?: boolean;
39
+ /** Batch size for API calls (default: 50) */
40
+ batchSize?: number;
41
+ /** Progress callback */
42
+ onProgress?: (synced: number, total: number) => void;
43
+ }
44
+ /**
45
+ * Result of syncing multiple sprints
46
+ */
47
+ export interface BatchSyncResult {
48
+ success: boolean;
49
+ totalTasks: number;
50
+ created: number;
51
+ updated: number;
52
+ relationships: number;
53
+ errors: string[];
54
+ }
55
+ /**
56
+ * Sync tasks to graph via API
57
+ *
58
+ * @param tasks - Array of parsed tasks
59
+ * @param graphId - Graph namespace ID
60
+ * @param client - GraphApiClient instance
61
+ * @param options - Sync options
62
+ * @returns TaskSyncResponse
63
+ */
64
+ export declare function syncTasksToGraph(tasks: ParsedTask[], graphId: string, client: GraphApiClient, options?: TaskSyncOptions): Promise<TaskSyncResponse>;
65
+ /**
66
+ * Sync a single sprint's tasks to graph
67
+ *
68
+ * @param sprintResult - Parsed sprint with tasks
69
+ * @param client - GraphApiClient instance (optional, will create if not provided)
70
+ * @param options - Sync options
71
+ * @returns TaskSyncResponse
72
+ */
73
+ export declare function syncSprintTasksToGraph(sprintResult: SprintParseResult, client?: GraphApiClient, options?: TaskSyncOptions): Promise<TaskSyncResponse>;
74
+ /**
75
+ * Sync multiple sprints' tasks to graph
76
+ *
77
+ * @param sprintResults - Array of parsed sprints with tasks
78
+ * @param options - Sync options
79
+ * @returns BatchSyncResult
80
+ */
81
+ export declare function syncAllSprintTasksToGraph(sprintResults: SprintParseResult[], options?: TaskSyncOptions): Promise<BatchSyncResult>;
82
+ /**
83
+ * Get task sync status from graph
84
+ *
85
+ * @param graphId - Graph namespace ID
86
+ * @param sprintId - Optional sprint ID filter
87
+ * @param epicId - Optional epic ID filter
88
+ * @param client - GraphApiClient instance
89
+ * @returns Array of task status objects
90
+ */
91
+ export declare function getTasksFromGraph(graphId: string, client: GraphApiClient, filters?: {
92
+ sprintId?: string;
93
+ epicId?: string;
94
+ }): Promise<Array<{
95
+ id: string;
96
+ title: string;
97
+ status: string;
98
+ priority: string;
99
+ sprint_id: string;
100
+ epic_id: string;
101
+ estimate: string | null;
102
+ assignee: string | null;
103
+ synced_at: string | null;
104
+ }>>;
105
+ //# sourceMappingURL=task-graph-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-graph-sync.d.ts","sourceRoot":"","sources":["../../src/lib/task-graph-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA+C3B;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,iBAAiB,EAC/B,MAAM,CAAC,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,aAAa,EAAE,iBAAiB,EAAE,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,eAAe,CAAC,CAqE1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAAC,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC,CAAC,CAEF"}