@ginkoai/cli 2.0.0-beta.4 → 2.0.0-beta.5
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/start/start-reflection.d.ts +7 -0
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +32 -0
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/sync/index.d.ts +7 -4
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +10 -6
- package/dist/commands/sync/index.js.map +1 -1
- package/dist/commands/sync/sync-command.d.ts +3 -3
- package/dist/commands/sync/sync-command.d.ts.map +1 -1
- package/dist/commands/sync/sync-command.js +27 -4
- package/dist/commands/sync/sync-command.js.map +1 -1
- package/dist/commands/sync/types.d.ts +5 -3
- package/dist/commands/sync/types.d.ts.map +1 -1
- package/dist/commands/sync/types.js +3 -3
- package/dist/lib/staleness-detector.d.ts +88 -0
- package/dist/lib/staleness-detector.d.ts.map +1 -0
- package/dist/lib/staleness-detector.js +290 -0
- package/dist/lib/staleness-detector.js.map +1 -0
- package/dist/lib/team-sync-reporter.d.ts +110 -0
- package/dist/lib/team-sync-reporter.d.ts.map +1 -0
- package/dist/lib/team-sync-reporter.js +316 -0
- package/dist/lib/team-sync-reporter.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-01-03
|
|
5
|
+
* @tags: [staleness, detection, team, sync, EPIC-008]
|
|
6
|
+
* @related: [../commands/sync/team-sync.ts, ../commands/start/start-reflection.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [chalk]
|
|
10
|
+
*/
|
|
11
|
+
export interface StalenessConfig {
|
|
12
|
+
/** Days before showing warning (default: 1) */
|
|
13
|
+
warningThresholdDays: number;
|
|
14
|
+
/** Days before showing critical warning (default: 7) */
|
|
15
|
+
criticalThresholdDays: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ChangedSinceSync {
|
|
18
|
+
adrs: number;
|
|
19
|
+
patterns: number;
|
|
20
|
+
sprints: number;
|
|
21
|
+
total: number;
|
|
22
|
+
}
|
|
23
|
+
export interface StalenessResult {
|
|
24
|
+
/** Whether context is stale (exceeds warning threshold) */
|
|
25
|
+
isStale: boolean;
|
|
26
|
+
/** Severity level based on days since sync */
|
|
27
|
+
severity: 'none' | 'warning' | 'critical';
|
|
28
|
+
/** Number of days since last sync (Infinity if never synced) */
|
|
29
|
+
daysSinceSync: number;
|
|
30
|
+
/** ISO timestamp of last sync, null if never synced */
|
|
31
|
+
lastSyncAt: string | null;
|
|
32
|
+
/** Count of changes by category since last sync */
|
|
33
|
+
changedSinceSync: ChangedSinceSync;
|
|
34
|
+
/** Human-readable message describing staleness state */
|
|
35
|
+
message: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check staleness of team context for current user
|
|
39
|
+
*
|
|
40
|
+
* @param graphId - The graph ID to check
|
|
41
|
+
* @param token - Bearer token for authentication
|
|
42
|
+
* @param config - Optional staleness configuration
|
|
43
|
+
* @returns StalenessResult with severity, days since sync, and changes
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const result = await checkStaleness(graphId, token, {
|
|
48
|
+
* warningThresholdDays: 1,
|
|
49
|
+
* criticalThresholdDays: 7,
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* if (result.severity === 'critical') {
|
|
53
|
+
* console.log(chalk.red(result.message));
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function checkStaleness(graphId: string, token: string, config?: Partial<StalenessConfig>): Promise<StalenessResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Display staleness warning in CLI with appropriate styling
|
|
60
|
+
*
|
|
61
|
+
* @param result - The staleness check result
|
|
62
|
+
*/
|
|
63
|
+
export declare function displayStalenessWarning(result: StalenessResult): void;
|
|
64
|
+
/**
|
|
65
|
+
* Calculate number of days since last sync
|
|
66
|
+
*/
|
|
67
|
+
declare function calculateDaysSinceSync(lastSyncAt: string | null): number;
|
|
68
|
+
/**
|
|
69
|
+
* Determine severity based on days since sync and config thresholds
|
|
70
|
+
*/
|
|
71
|
+
declare function determineSeverity(daysSinceSync: number, config: StalenessConfig): 'none' | 'warning' | 'critical';
|
|
72
|
+
/**
|
|
73
|
+
* Format human-readable message based on staleness state
|
|
74
|
+
*/
|
|
75
|
+
declare function formatMessage(severity: 'none' | 'warning' | 'critical', daysSinceSync: number, lastSyncAt: string | null, changes: ChangedSinceSync): string;
|
|
76
|
+
/**
|
|
77
|
+
* Format relative time for display
|
|
78
|
+
*/
|
|
79
|
+
declare function formatRelativeTime(dateStr: string): string;
|
|
80
|
+
export declare const _internal: {
|
|
81
|
+
calculateDaysSinceSync: typeof calculateDaysSinceSync;
|
|
82
|
+
determineSeverity: typeof determineSeverity;
|
|
83
|
+
formatMessage: typeof formatMessage;
|
|
84
|
+
formatRelativeTime: typeof formatRelativeTime;
|
|
85
|
+
DEFAULT_CONFIG: StalenessConfig;
|
|
86
|
+
};
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=staleness-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness-detector.d.ts","sourceRoot":"","sources":["../../src/lib/staleness-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAoBH,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wDAAwD;IACxD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IAC1C,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAiBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAChC,OAAO,CAAC,eAAe,CAAC,CAwF1B;AAMD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAiCrE;AAMD;;GAEG;AACH,iBAAS,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAWjE;AAED;;GAEG;AACH,iBAAS,iBAAiB,CACxB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,eAAe,GACtB,MAAM,GAAG,SAAS,GAAG,UAAU,CAQjC;AA8CD;;GAEG;AACH,iBAAS,aAAa,CACpB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,EACzC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAqBR;AAED;;GAEG;AACH,iBAAS,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAanD;AAaD,eAAO,MAAM,SAAS;;;;;;CAMrB,CAAC"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-01-03
|
|
5
|
+
* @tags: [staleness, detection, team, sync, EPIC-008]
|
|
6
|
+
* @related: [../commands/sync/team-sync.ts, ../commands/start/start-reflection.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [chalk]
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Staleness Detection System (EPIC-008 Sprint 2)
|
|
13
|
+
*
|
|
14
|
+
* Provides comprehensive staleness detection for team context synchronization.
|
|
15
|
+
* Used by both CLI (ginko start) and Dashboard (StalenessWarning component).
|
|
16
|
+
*
|
|
17
|
+
* Key features:
|
|
18
|
+
* - Configurable warning/critical thresholds
|
|
19
|
+
* - Tracks changes since last sync (ADRs, Patterns, Sprints)
|
|
20
|
+
* - Human-readable messages for different severity levels
|
|
21
|
+
*/
|
|
22
|
+
import chalk from 'chalk';
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Constants
|
|
25
|
+
// =============================================================================
|
|
26
|
+
const API_BASE = process.env.GINKO_API_URL || 'https://app.ginkoai.com';
|
|
27
|
+
const DEFAULT_CONFIG = {
|
|
28
|
+
warningThresholdDays: 1,
|
|
29
|
+
criticalThresholdDays: 7,
|
|
30
|
+
};
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// Main API
|
|
33
|
+
// =============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Check staleness of team context for current user
|
|
36
|
+
*
|
|
37
|
+
* @param graphId - The graph ID to check
|
|
38
|
+
* @param token - Bearer token for authentication
|
|
39
|
+
* @param config - Optional staleness configuration
|
|
40
|
+
* @returns StalenessResult with severity, days since sync, and changes
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const result = await checkStaleness(graphId, token, {
|
|
45
|
+
* warningThresholdDays: 1,
|
|
46
|
+
* criticalThresholdDays: 7,
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* if (result.severity === 'critical') {
|
|
50
|
+
* console.log(chalk.red(result.message));
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export async function checkStaleness(graphId, token, config) {
|
|
55
|
+
const mergedConfig = {
|
|
56
|
+
...DEFAULT_CONFIG,
|
|
57
|
+
...config,
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
// Fetch membership status (includes last_sync_at)
|
|
61
|
+
const membershipUrl = new URL(`${API_BASE}/api/v1/graph/membership`);
|
|
62
|
+
membershipUrl.searchParams.set('graphId', graphId);
|
|
63
|
+
const membershipResponse = await fetch(membershipUrl.toString(), {
|
|
64
|
+
headers: {
|
|
65
|
+
Authorization: `Bearer ${token}`,
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
if (membershipResponse.status === 404) {
|
|
70
|
+
// User is not a team member - return non-stale (no team context to sync)
|
|
71
|
+
return createResult({
|
|
72
|
+
isStale: false,
|
|
73
|
+
severity: 'none',
|
|
74
|
+
daysSinceSync: 0,
|
|
75
|
+
lastSyncAt: null,
|
|
76
|
+
changedSinceSync: { adrs: 0, patterns: 0, sprints: 0, total: 0 },
|
|
77
|
+
message: 'Not a team member',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (!membershipResponse.ok) {
|
|
81
|
+
// API error - return safe default (non-stale to avoid blocking)
|
|
82
|
+
return createResult({
|
|
83
|
+
isStale: false,
|
|
84
|
+
severity: 'none',
|
|
85
|
+
daysSinceSync: 0,
|
|
86
|
+
lastSyncAt: null,
|
|
87
|
+
changedSinceSync: { adrs: 0, patterns: 0, sprints: 0, total: 0 },
|
|
88
|
+
message: 'Could not verify membership status',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const membershipData = await membershipResponse.json();
|
|
92
|
+
const lastSyncAt = membershipData.membership?.last_sync_at || null;
|
|
93
|
+
// Calculate days since sync
|
|
94
|
+
const daysSinceSync = calculateDaysSinceSync(lastSyncAt);
|
|
95
|
+
// Determine severity based on thresholds
|
|
96
|
+
const severity = determineSeverity(daysSinceSync, mergedConfig);
|
|
97
|
+
// If not stale, return early (skip expensive changes query)
|
|
98
|
+
if (severity === 'none') {
|
|
99
|
+
return createResult({
|
|
100
|
+
isStale: false,
|
|
101
|
+
severity: 'none',
|
|
102
|
+
daysSinceSync,
|
|
103
|
+
lastSyncAt,
|
|
104
|
+
changedSinceSync: { adrs: 0, patterns: 0, sprints: 0, total: 0 },
|
|
105
|
+
message: formatMessage(severity, daysSinceSync, lastSyncAt, { adrs: 0, patterns: 0, sprints: 0, total: 0 }),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Fetch changes since last sync
|
|
109
|
+
const changedSinceSync = await fetchChangesSinceSync(graphId, token, lastSyncAt);
|
|
110
|
+
// Generate human-readable message
|
|
111
|
+
const message = formatMessage(severity, daysSinceSync, lastSyncAt, changedSinceSync);
|
|
112
|
+
return createResult({
|
|
113
|
+
isStale: true,
|
|
114
|
+
severity,
|
|
115
|
+
daysSinceSync,
|
|
116
|
+
lastSyncAt,
|
|
117
|
+
changedSinceSync,
|
|
118
|
+
message,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
// Network error - return safe default
|
|
123
|
+
return createResult({
|
|
124
|
+
isStale: false,
|
|
125
|
+
severity: 'none',
|
|
126
|
+
daysSinceSync: 0,
|
|
127
|
+
lastSyncAt: null,
|
|
128
|
+
changedSinceSync: { adrs: 0, patterns: 0, sprints: 0, total: 0 },
|
|
129
|
+
message: 'Could not check staleness (offline?)',
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// =============================================================================
|
|
134
|
+
// CLI Display Helper
|
|
135
|
+
// =============================================================================
|
|
136
|
+
/**
|
|
137
|
+
* Display staleness warning in CLI with appropriate styling
|
|
138
|
+
*
|
|
139
|
+
* @param result - The staleness check result
|
|
140
|
+
*/
|
|
141
|
+
export function displayStalenessWarning(result) {
|
|
142
|
+
if (!result.isStale) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
console.log('');
|
|
146
|
+
if (result.severity === 'critical') {
|
|
147
|
+
console.log(chalk.red.bold('🚨 Team context is critically stale'));
|
|
148
|
+
console.log(chalk.red(` ${result.message}`));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log(chalk.yellow('⚠️ Team context may be stale'));
|
|
152
|
+
console.log(chalk.yellow(` ${result.message}`));
|
|
153
|
+
}
|
|
154
|
+
// Show changes breakdown if any
|
|
155
|
+
if (result.changedSinceSync.total > 0) {
|
|
156
|
+
console.log('');
|
|
157
|
+
console.log(chalk.dim(' Changes since last sync:'));
|
|
158
|
+
if (result.changedSinceSync.adrs > 0) {
|
|
159
|
+
console.log(chalk.dim(` - ${result.changedSinceSync.adrs} ADR${result.changedSinceSync.adrs === 1 ? '' : 's'}`));
|
|
160
|
+
}
|
|
161
|
+
if (result.changedSinceSync.patterns > 0) {
|
|
162
|
+
console.log(chalk.dim(` - ${result.changedSinceSync.patterns} Pattern${result.changedSinceSync.patterns === 1 ? '' : 's'}`));
|
|
163
|
+
}
|
|
164
|
+
if (result.changedSinceSync.sprints > 0) {
|
|
165
|
+
console.log(chalk.dim(` - ${result.changedSinceSync.sprints} Sprint${result.changedSinceSync.sprints === 1 ? '' : 's'}`));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(chalk.dim(' Run `ginko sync` to pull team updates.'));
|
|
170
|
+
console.log('');
|
|
171
|
+
}
|
|
172
|
+
// =============================================================================
|
|
173
|
+
// Helper Functions
|
|
174
|
+
// =============================================================================
|
|
175
|
+
/**
|
|
176
|
+
* Calculate number of days since last sync
|
|
177
|
+
*/
|
|
178
|
+
function calculateDaysSinceSync(lastSyncAt) {
|
|
179
|
+
if (!lastSyncAt) {
|
|
180
|
+
return Infinity;
|
|
181
|
+
}
|
|
182
|
+
const lastSync = new Date(lastSyncAt);
|
|
183
|
+
const now = new Date();
|
|
184
|
+
const diffMs = now.getTime() - lastSync.getTime();
|
|
185
|
+
const daysSinceSync = diffMs / (1000 * 60 * 60 * 24);
|
|
186
|
+
return Math.floor(daysSinceSync);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Determine severity based on days since sync and config thresholds
|
|
190
|
+
*/
|
|
191
|
+
function determineSeverity(daysSinceSync, config) {
|
|
192
|
+
if (daysSinceSync >= config.criticalThresholdDays) {
|
|
193
|
+
return 'critical';
|
|
194
|
+
}
|
|
195
|
+
if (daysSinceSync >= config.warningThresholdDays) {
|
|
196
|
+
return 'warning';
|
|
197
|
+
}
|
|
198
|
+
return 'none';
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Fetch count of changes since last sync from API
|
|
202
|
+
*/
|
|
203
|
+
async function fetchChangesSinceSync(graphId, token, lastSyncAt) {
|
|
204
|
+
try {
|
|
205
|
+
const url = new URL(`${API_BASE}/api/v1/graph/changes`);
|
|
206
|
+
url.searchParams.set('graphId', graphId);
|
|
207
|
+
if (lastSyncAt) {
|
|
208
|
+
url.searchParams.set('since', lastSyncAt);
|
|
209
|
+
}
|
|
210
|
+
const response = await fetch(url.toString(), {
|
|
211
|
+
headers: {
|
|
212
|
+
Authorization: `Bearer ${token}`,
|
|
213
|
+
'Content-Type': 'application/json',
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
if (!response.ok) {
|
|
217
|
+
// Fallback if endpoint not available
|
|
218
|
+
return { adrs: 0, patterns: 0, sprints: 0, total: 0 };
|
|
219
|
+
}
|
|
220
|
+
const data = await response.json();
|
|
221
|
+
// API returns { changes: { ADR: n, Pattern: n, Sprint: n, ... }, total: n }
|
|
222
|
+
return {
|
|
223
|
+
adrs: data.changes?.ADR || 0,
|
|
224
|
+
patterns: data.changes?.Pattern || 0,
|
|
225
|
+
sprints: data.changes?.Sprint || 0,
|
|
226
|
+
total: data.total || 0,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return { adrs: 0, patterns: 0, sprints: 0, total: 0 };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Format human-readable message based on staleness state
|
|
235
|
+
*/
|
|
236
|
+
function formatMessage(severity, daysSinceSync, lastSyncAt, changes) {
|
|
237
|
+
if (severity === 'none') {
|
|
238
|
+
if (!lastSyncAt) {
|
|
239
|
+
return 'No sync history';
|
|
240
|
+
}
|
|
241
|
+
return `Last synced ${formatRelativeTime(lastSyncAt)}`;
|
|
242
|
+
}
|
|
243
|
+
if (!lastSyncAt || daysSinceSync === Infinity) {
|
|
244
|
+
return 'Never synced - team context not loaded';
|
|
245
|
+
}
|
|
246
|
+
const changeInfo = changes.total > 0
|
|
247
|
+
? ` (${changes.total} change${changes.total === 1 ? '' : 's'})`
|
|
248
|
+
: '';
|
|
249
|
+
if (severity === 'critical') {
|
|
250
|
+
return `${daysSinceSync} days since last sync${changeInfo}. Team patterns and ADRs may be outdated.`;
|
|
251
|
+
}
|
|
252
|
+
return `${daysSinceSync} day${daysSinceSync === 1 ? '' : 's'} since last sync${changeInfo}.`;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Format relative time for display
|
|
256
|
+
*/
|
|
257
|
+
function formatRelativeTime(dateStr) {
|
|
258
|
+
const date = new Date(dateStr);
|
|
259
|
+
const now = new Date();
|
|
260
|
+
const diffMs = now.getTime() - date.getTime();
|
|
261
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
262
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
263
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
264
|
+
if (diffMins < 1)
|
|
265
|
+
return 'just now';
|
|
266
|
+
if (diffMins < 60)
|
|
267
|
+
return `${diffMins} minute${diffMins === 1 ? '' : 's'} ago`;
|
|
268
|
+
if (diffHours < 24)
|
|
269
|
+
return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;
|
|
270
|
+
if (diffDays < 7)
|
|
271
|
+
return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
|
|
272
|
+
return date.toLocaleDateString();
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Helper to create a StalenessResult with proper types
|
|
276
|
+
*/
|
|
277
|
+
function createResult(partial) {
|
|
278
|
+
return partial;
|
|
279
|
+
}
|
|
280
|
+
// =============================================================================
|
|
281
|
+
// Exports for Testing
|
|
282
|
+
// =============================================================================
|
|
283
|
+
export const _internal = {
|
|
284
|
+
calculateDaysSinceSync,
|
|
285
|
+
determineSeverity,
|
|
286
|
+
formatMessage,
|
|
287
|
+
formatRelativeTime,
|
|
288
|
+
DEFAULT_CONFIG,
|
|
289
|
+
};
|
|
290
|
+
//# sourceMappingURL=staleness-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness-detector.js","sourceRoot":"","sources":["../../src/lib/staleness-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-01-03
|
|
5
|
+
* @tags: [sync, team, reporting, changes, EPIC-008]
|
|
6
|
+
* @related: [../commands/sync/sync-command.ts, ../commands/sync/team-sync.ts, staleness-detector.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [chalk]
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Change details for a single node type
|
|
13
|
+
*/
|
|
14
|
+
export interface TypeChange {
|
|
15
|
+
type: string;
|
|
16
|
+
action: string;
|
|
17
|
+
count: number;
|
|
18
|
+
titles: string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Summary of changes for a single team member
|
|
22
|
+
*/
|
|
23
|
+
export interface MemberChangeSummary {
|
|
24
|
+
email: string;
|
|
25
|
+
displayName: string | null;
|
|
26
|
+
changes: TypeChange[];
|
|
27
|
+
totalChanges: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Summary of all team changes since last sync
|
|
31
|
+
*/
|
|
32
|
+
export interface TeamChangeSummary {
|
|
33
|
+
byMember: Map<string, MemberChangeSummary>;
|
|
34
|
+
totalChanges: number;
|
|
35
|
+
sinceSyncAt: string | null;
|
|
36
|
+
period: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Raw change record from API
|
|
40
|
+
*/
|
|
41
|
+
interface RawChangeRecord {
|
|
42
|
+
id: string;
|
|
43
|
+
type: string;
|
|
44
|
+
title: string;
|
|
45
|
+
action: 'created' | 'updated' | 'deleted';
|
|
46
|
+
editedBy: string;
|
|
47
|
+
editedByName?: string | null;
|
|
48
|
+
editedAt: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Fetch team changes since last sync
|
|
52
|
+
*
|
|
53
|
+
* @param graphId - The graph ID to query
|
|
54
|
+
* @param token - Bearer token for authentication
|
|
55
|
+
* @param lastSyncAt - ISO timestamp of last sync (null if never synced)
|
|
56
|
+
* @returns TeamChangeSummary with changes grouped by member
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const summary = await getTeamChangesSinceLast(graphId, token, '2026-01-01T00:00:00Z');
|
|
61
|
+
* if (summary.totalChanges > 0) {
|
|
62
|
+
* displayTeamChangeReport(summary);
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function getTeamChangesSinceLast(graphId: string, token: string, lastSyncAt: string | null): Promise<TeamChangeSummary>;
|
|
67
|
+
/**
|
|
68
|
+
* Aggregate raw changes into team summary
|
|
69
|
+
*/
|
|
70
|
+
declare function aggregateChanges(changes: RawChangeRecord[], lastSyncAt: string | null): TeamChangeSummary;
|
|
71
|
+
/**
|
|
72
|
+
* Create empty summary (used for error cases)
|
|
73
|
+
*/
|
|
74
|
+
declare function createEmptySummary(lastSyncAt: string | null): TeamChangeSummary;
|
|
75
|
+
/**
|
|
76
|
+
* Calculate human-readable period string
|
|
77
|
+
*/
|
|
78
|
+
declare function calculatePeriod(lastSyncAt: string | null): string;
|
|
79
|
+
/**
|
|
80
|
+
* Format team change report as string (for logging or testing)
|
|
81
|
+
*
|
|
82
|
+
* @param summary - The team change summary to format
|
|
83
|
+
* @returns Formatted string with colors stripped for logging
|
|
84
|
+
*/
|
|
85
|
+
export declare function formatTeamChangeReport(summary: TeamChangeSummary): string;
|
|
86
|
+
/**
|
|
87
|
+
* Display team change report to console with chalk colors
|
|
88
|
+
*
|
|
89
|
+
* @param summary - The team change summary to display
|
|
90
|
+
*/
|
|
91
|
+
export declare function displayTeamChangeReport(summary: TeamChangeSummary): void;
|
|
92
|
+
/**
|
|
93
|
+
* Display compact change summary (single line)
|
|
94
|
+
*
|
|
95
|
+
* @param summary - The team change summary
|
|
96
|
+
* @returns Single line summary string
|
|
97
|
+
*/
|
|
98
|
+
export declare function formatCompactSummary(summary: TeamChangeSummary): string;
|
|
99
|
+
/**
|
|
100
|
+
* Format email for display (truncate domain)
|
|
101
|
+
*/
|
|
102
|
+
declare function formatEmail(email: string): string;
|
|
103
|
+
export declare const _internal: {
|
|
104
|
+
aggregateChanges: typeof aggregateChanges;
|
|
105
|
+
calculatePeriod: typeof calculatePeriod;
|
|
106
|
+
formatEmail: typeof formatEmail;
|
|
107
|
+
createEmptySummary: typeof createEmptySummary;
|
|
108
|
+
};
|
|
109
|
+
export {};
|
|
110
|
+
//# sourceMappingURL=team-sync-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-sync-reporter.d.ts","sourceRoot":"","sources":["../../src/lib/team-sync-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqBH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,OAAO,CAAC,iBAAiB,CAAC,CAqC5B;AAiDD;;GAEG;AACH,iBAAS,gBAAgB,CACvB,OAAO,EAAE,eAAe,EAAE,EAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,iBAAiB,CAgDnB;AAED;;GAEG;AACH,iBAAS,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,CAOxE;AAED;;GAEG;AACH,iBAAS,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAiB1D;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAuCzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAgDxE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAOvE;AAMD;;GAEG;AACH,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAa1C;AAMD,eAAO,MAAM,SAAS;;;;;CAKrB,CAAC"}
|