@ginkoai/cli 2.0.6 → 2.1.1
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/dist/commands/epic/index.d.ts +29 -0
- package/dist/commands/epic/index.d.ts.map +1 -0
- package/dist/commands/epic/index.js +94 -0
- package/dist/commands/epic/index.js.map +1 -0
- package/dist/commands/epic/status.d.ts +40 -0
- package/dist/commands/epic/status.d.ts.map +1 -0
- package/dist/commands/epic/status.js +244 -0
- package/dist/commands/epic/status.js.map +1 -0
- package/dist/commands/graph/api-client.d.ts +221 -1
- package/dist/commands/graph/api-client.d.ts.map +1 -1
- package/dist/commands/graph/api-client.js +141 -2
- package/dist/commands/graph/api-client.js.map +1 -1
- package/dist/commands/graph/load.d.ts.map +1 -1
- package/dist/commands/graph/load.js +40 -2
- package/dist/commands/graph/load.js.map +1 -1
- package/dist/commands/handoff.d.ts +3 -3
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +32 -3
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/migrate/index.d.ts +27 -0
- package/dist/commands/migrate/index.d.ts.map +1 -0
- package/dist/commands/migrate/index.js +76 -0
- package/dist/commands/migrate/index.js.map +1 -0
- package/dist/commands/migrate/status-migration.d.ts +58 -0
- package/dist/commands/migrate/status-migration.d.ts.map +1 -0
- package/dist/commands/migrate/status-migration.js +323 -0
- package/dist/commands/migrate/status-migration.js.map +1 -0
- package/dist/commands/nudging/index.d.ts +24 -0
- package/dist/commands/nudging/index.d.ts.map +1 -0
- package/dist/commands/nudging/index.js +175 -0
- package/dist/commands/nudging/index.js.map +1 -0
- package/dist/commands/sprint/create.d.ts +26 -0
- package/dist/commands/sprint/create.d.ts.map +1 -0
- package/dist/commands/sprint/create.js +269 -0
- package/dist/commands/sprint/create.js.map +1 -0
- package/dist/commands/sprint/index.d.ts.map +1 -1
- package/dist/commands/sprint/index.js +28 -0
- package/dist/commands/sprint/index.js.map +1 -1
- package/dist/commands/sprint/quick-fix.d.ts +25 -0
- package/dist/commands/sprint/quick-fix.d.ts.map +1 -0
- package/dist/commands/sprint/quick-fix.js +151 -0
- package/dist/commands/sprint/quick-fix.js.map +1 -0
- package/dist/commands/sprint/sprint-pipeline-enhanced.d.ts.map +1 -1
- package/dist/commands/sprint/sprint-pipeline-enhanced.js +37 -0
- package/dist/commands/sprint/sprint-pipeline-enhanced.js.map +1 -1
- package/dist/commands/sprint/status.d.ts +42 -0
- package/dist/commands/sprint/status.d.ts.map +1 -0
- package/dist/commands/sprint/status.js +298 -0
- package/dist/commands/sprint/status.js.map +1 -0
- package/dist/commands/start/start-reflection.d.ts +53 -0
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +464 -71
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/sync/sprint-syncer.d.ts +19 -12
- package/dist/commands/sync/sprint-syncer.d.ts.map +1 -1
- package/dist/commands/sync/sprint-syncer.js +58 -140
- package/dist/commands/sync/sprint-syncer.js.map +1 -1
- package/dist/commands/sync/sync-command.d.ts.map +1 -1
- package/dist/commands/sync/sync-command.js +6 -18
- package/dist/commands/sync/sync-command.js.map +1 -1
- package/dist/commands/task/index.d.ts +25 -0
- package/dist/commands/task/index.d.ts.map +1 -0
- package/dist/commands/task/index.js +100 -0
- package/dist/commands/task/index.js.map +1 -0
- package/dist/commands/task/status.d.ts +46 -0
- package/dist/commands/task/status.d.ts.map +1 -0
- package/dist/commands/task/status.js +348 -0
- package/dist/commands/task/status.js.map +1 -0
- package/dist/commands/team/index.d.ts +5 -0
- package/dist/commands/team/index.d.ts.map +1 -1
- package/dist/commands/team/index.js +28 -0
- package/dist/commands/team/index.js.map +1 -1
- package/dist/commands/team/status.d.ts +16 -0
- package/dist/commands/team/status.d.ts.map +1 -0
- package/dist/commands/team/status.js +180 -0
- package/dist/commands/team/status.js.map +1 -0
- package/dist/index.js +21 -32
- package/dist/index.js.map +1 -1
- package/dist/lib/adoption-score.d.ts +69 -0
- package/dist/lib/adoption-score.d.ts.map +1 -0
- package/dist/lib/adoption-score.js +206 -0
- package/dist/lib/adoption-score.js.map +1 -0
- package/dist/lib/coaching-level.d.ts +127 -0
- package/dist/lib/coaching-level.d.ts.map +1 -0
- package/dist/lib/coaching-level.js +406 -0
- package/dist/lib/coaching-level.js.map +1 -0
- package/dist/lib/context-loader-events.d.ts.map +1 -1
- package/dist/lib/context-loader-events.js +7 -26
- package/dist/lib/context-loader-events.js.map +1 -1
- package/dist/lib/event-logger.d.ts +42 -0
- package/dist/lib/event-logger.d.ts.map +1 -1
- package/dist/lib/event-logger.js +77 -0
- package/dist/lib/event-logger.js.map +1 -1
- package/dist/lib/output-formatter.d.ts +8 -2
- package/dist/lib/output-formatter.d.ts.map +1 -1
- package/dist/lib/output-formatter.js +98 -18
- package/dist/lib/output-formatter.js.map +1 -1
- package/dist/lib/pending-updates.d.ts +148 -0
- package/dist/lib/pending-updates.d.ts.map +1 -0
- package/dist/lib/pending-updates.js +301 -0
- package/dist/lib/pending-updates.js.map +1 -0
- package/dist/lib/planning-menu.d.ts +69 -0
- package/dist/lib/planning-menu.d.ts.map +1 -0
- package/dist/lib/planning-menu.js +342 -0
- package/dist/lib/planning-menu.js.map +1 -0
- package/dist/lib/sprint-loader.d.ts +86 -14
- package/dist/lib/sprint-loader.d.ts.map +1 -1
- package/dist/lib/sprint-loader.js +293 -98
- package/dist/lib/sprint-loader.js.map +1 -1
- package/dist/lib/state-cache.d.ts +142 -0
- package/dist/lib/state-cache.d.ts.map +1 -0
- package/dist/lib/state-cache.js +259 -0
- package/dist/lib/state-cache.js.map +1 -0
- package/dist/lib/targeted-coaching.d.ts +71 -0
- package/dist/lib/targeted-coaching.d.ts.map +1 -0
- package/dist/lib/targeted-coaching.js +318 -0
- package/dist/lib/targeted-coaching.js.map +1 -0
- package/dist/lib/task-graph-sync.d.ts +105 -0
- package/dist/lib/task-graph-sync.d.ts.map +1 -0
- package/dist/lib/task-graph-sync.js +178 -0
- package/dist/lib/task-graph-sync.js.map +1 -0
- package/dist/lib/task-parser.d.ts +109 -0
- package/dist/lib/task-parser.d.ts.map +1 -0
- package/dist/lib/task-parser.js +407 -0
- package/dist/lib/task-parser.js.map +1 -0
- package/dist/lib/user-sprint.d.ts +53 -0
- package/dist/lib/user-sprint.d.ts.map +1 -1
- package/dist/lib/user-sprint.js +137 -2
- package/dist/lib/user-sprint.js.map +1 -1
- package/dist/lib/work-reconciliation.d.ts +59 -0
- package/dist/lib/work-reconciliation.d.ts.map +1 -0
- package/dist/lib/work-reconciliation.js +267 -0
- package/dist/lib/work-reconciliation.js.map +1 -0
- package/dist/templates/ai-instructions-template.d.ts.map +1 -1
- package/dist/templates/ai-instructions-template.js +7 -5
- package/dist/templates/ai-instructions-template.js.map +1 -1
- package/dist/templates/epic-template.md +0 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +7 -5
- package/dist/types/config.js.map +1 -1
- package/dist/utils/synthesis.d.ts +4 -0
- package/dist/utils/synthesis.d.ts.map +1 -1
- package/dist/utils/synthesis.js +12 -18
- package/dist/utils/synthesis.js.map +1 -1
- package/dist/utils/version-check.d.ts +26 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +186 -0
- package/dist/utils/version-check.js.map +1 -0
- package/package.json +2 -2
|
@@ -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,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-01-26
|
|
5
|
+
* @tags: [coaching, insights, targeted, adaptive, epic-016-s05]
|
|
6
|
+
* @related: [coaching-level.ts, start-reflection.ts, handoff.ts]
|
|
7
|
+
* @priority: medium
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [fs-extra, path]
|
|
10
|
+
*/
|
|
11
|
+
import { CoachingContext } from './coaching-level.js';
|
|
12
|
+
export type MetricType = 'sessionEfficiency' | 'patternAdoption' | 'collaborationQuality' | 'antiPatterns';
|
|
13
|
+
export type CoachingContext_Type = 'start' | 'handoff' | 'task_complete' | 'planning';
|
|
14
|
+
export interface CoachingTip {
|
|
15
|
+
id: string;
|
|
16
|
+
metric: MetricType;
|
|
17
|
+
context: CoachingContext_Type[];
|
|
18
|
+
message: string;
|
|
19
|
+
action?: string;
|
|
20
|
+
priority: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ShownTipsRecord {
|
|
23
|
+
sessionId: string;
|
|
24
|
+
shownTipIds: string[];
|
|
25
|
+
lastUpdated: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* All available coaching tips organized by metric
|
|
29
|
+
*/
|
|
30
|
+
export declare const COACHING_TIPS: CoachingTip[];
|
|
31
|
+
declare function loadShownTips(): Promise<ShownTipsRecord>;
|
|
32
|
+
declare function saveShownTips(record: ShownTipsRecord): Promise<void>;
|
|
33
|
+
declare function markTipAsShown(tipId: string): Promise<void>;
|
|
34
|
+
declare function isTipShown(tipId: string): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Get applicable tips for a given context and coaching context
|
|
37
|
+
*
|
|
38
|
+
* @param coachingCtx - Coaching context with metric scores
|
|
39
|
+
* @param context - Current context (start, handoff, etc.)
|
|
40
|
+
* @param limit - Maximum number of tips to return
|
|
41
|
+
* @returns Array of applicable tips, prioritized
|
|
42
|
+
*/
|
|
43
|
+
export declare function getApplicableTips(coachingCtx: CoachingContext, context: CoachingContext_Type, limit?: number): Promise<CoachingTip[]>;
|
|
44
|
+
declare function getMetricValue(ctx: CoachingContext, metric: MetricType): number;
|
|
45
|
+
/**
|
|
46
|
+
* Display a coaching tip to the console
|
|
47
|
+
*/
|
|
48
|
+
export declare function displayTip(tip: CoachingTip): void;
|
|
49
|
+
/**
|
|
50
|
+
* Show targeted coaching tips for the current context
|
|
51
|
+
*
|
|
52
|
+
* @param coachingCtx - Coaching context with metric scores
|
|
53
|
+
* @param context - Current context
|
|
54
|
+
* @returns Number of tips shown
|
|
55
|
+
*/
|
|
56
|
+
export declare function showTargetedCoaching(coachingCtx: CoachingContext, context: CoachingContext_Type): Promise<number>;
|
|
57
|
+
/**
|
|
58
|
+
* Get coaching tip for a specific metric (for inline use)
|
|
59
|
+
*/
|
|
60
|
+
export declare function getTipForMetric(coachingCtx: CoachingContext, metric: MetricType, context: CoachingContext_Type): Promise<string | null>;
|
|
61
|
+
export declare const METRIC_DISPLAY_NAMES: Record<MetricType, string>;
|
|
62
|
+
export declare const __testing: {
|
|
63
|
+
LOW_THRESHOLD: number;
|
|
64
|
+
loadShownTips: typeof loadShownTips;
|
|
65
|
+
saveShownTips: typeof saveShownTips;
|
|
66
|
+
markTipAsShown: typeof markTipAsShown;
|
|
67
|
+
isTipShown: typeof isTipShown;
|
|
68
|
+
getMetricValue: typeof getMetricValue;
|
|
69
|
+
};
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=targeted-coaching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"targeted-coaching.d.ts","sourceRoot":"","sources":["../../src/lib/targeted-coaching.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyBH,OAAO,EAAE,eAAe,EAAe,MAAM,qBAAqB,CAAC;AAOnE,MAAM,MAAM,UAAU,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,sBAAsB,GAAG,cAAc,CAAC;AAC3G,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,UAAU,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AASD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,EAmGtC,CAAC;AAaF,iBAAe,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CA0BvD;AAED,iBAAe,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnE;AAMD,iBAAe,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1D;AAED,iBAAe,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGzD;AAMD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,WAAW,EAAE,CAAC,CAiCxB;AAED,iBAAS,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAWxE;AAMD;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAQjD;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,eAAe,EAC5B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAmBD,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAK3D,CAAC;AAMF,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC"}
|