@ginkoai/cli 1.4.13 → 1.6.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.
- package/dist/commands/graph/api-client.d.ts +16 -1
- package/dist/commands/graph/api-client.d.ts.map +1 -1
- package/dist/commands/graph/api-client.js +79 -4
- package/dist/commands/graph/api-client.js.map +1 -1
- package/dist/commands/graph/health.d.ts +22 -0
- package/dist/commands/graph/health.d.ts.map +1 -0
- package/dist/commands/graph/health.js +37 -0
- package/dist/commands/graph/health.js.map +1 -0
- package/dist/commands/graph/index.d.ts.map +1 -1
- package/dist/commands/graph/index.js +8 -0
- package/dist/commands/graph/index.js.map +1 -1
- package/dist/commands/handoff.d.ts +7 -1
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +8 -0
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/log.d.ts +5 -4
- package/dist/commands/log.d.ts.map +1 -1
- package/dist/commands/log.js +197 -216
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/start/start-reflection.d.ts +22 -0
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +249 -30
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/lib/charter-loader.d.ts +74 -0
- package/dist/lib/charter-loader.d.ts.map +1 -0
- package/dist/lib/charter-loader.js +328 -0
- package/dist/lib/charter-loader.js.map +1 -0
- package/dist/lib/context-loader-events.d.ts +49 -0
- package/dist/lib/context-loader-events.d.ts.map +1 -1
- package/dist/lib/context-loader-events.js +280 -34
- package/dist/lib/context-loader-events.js.map +1 -1
- package/dist/lib/event-logger.d.ts +8 -5
- package/dist/lib/event-logger.d.ts.map +1 -1
- package/dist/lib/event-logger.js +54 -14
- package/dist/lib/event-logger.js.map +1 -1
- package/dist/lib/event-task-linker.d.ts +81 -0
- package/dist/lib/event-task-linker.d.ts.map +1 -0
- package/dist/lib/event-task-linker.js +132 -0
- package/dist/lib/event-task-linker.js.map +1 -0
- package/dist/lib/output-formatter.d.ts +172 -0
- package/dist/lib/output-formatter.d.ts.map +1 -0
- package/dist/lib/output-formatter.js +219 -0
- package/dist/lib/output-formatter.js.map +1 -0
- package/dist/lib/session-cursor.d.ts +12 -5
- package/dist/lib/session-cursor.d.ts.map +1 -1
- package/dist/lib/session-cursor.js +12 -5
- package/dist/lib/session-cursor.js.map +1 -1
- package/dist/lib/sprint-loader.d.ts +91 -0
- package/dist/lib/sprint-loader.d.ts.map +1 -0
- package/dist/lib/sprint-loader.js +296 -0
- package/dist/lib/sprint-loader.js.map +1 -0
- package/dist/lib/sprint-parser.d.ts +79 -0
- package/dist/lib/sprint-parser.d.ts.map +1 -0
- package/dist/lib/sprint-parser.js +346 -0
- package/dist/lib/sprint-parser.js.map +1 -0
- package/dist/lib/write-dispatcher/adapters/local-adapter.d.ts.map +1 -1
- package/dist/lib/write-dispatcher/adapters/local-adapter.js +8 -2
- package/dist/lib/write-dispatcher/adapters/local-adapter.js.map +1 -1
- package/dist/utils/command-helpers.d.ts +76 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/command-helpers.js +314 -0
- package/dist/utils/command-helpers.js.map +1 -0
- package/dist/utils/graph-health-monitor.d.ts +75 -0
- package/dist/utils/graph-health-monitor.d.ts.map +1 -0
- package/dist/utils/graph-health-monitor.js +108 -0
- package/dist/utils/graph-health-monitor.js.map +1 -0
- package/dist/utils/synthesis.d.ts.map +1 -1
- package/dist/utils/synthesis.js +17 -9
- package/dist/utils/synthesis.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-11-21
|
|
5
|
+
* @tags: [event-linking, task-detection, graph-relationships, epic-001]
|
|
6
|
+
* @related: [event-logger.ts, sprint-parser.ts, event-queue.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Event-Task Linker (EPIC-001 TASK-4)
|
|
13
|
+
*
|
|
14
|
+
* Extracts task mentions (TASK-XXX patterns) from event descriptions
|
|
15
|
+
* to enable hot/cold task detection via RECENT_ACTIVITY relationships.
|
|
16
|
+
*
|
|
17
|
+
* Usage in graph sync:
|
|
18
|
+
* 1. Extract task IDs from event description
|
|
19
|
+
* 2. Create (Task)<-[:RECENT_ACTIVITY]-(Event) relationships
|
|
20
|
+
* 3. Query recent activity to determine task "hotness"
|
|
21
|
+
*
|
|
22
|
+
* Enables momentum awareness:
|
|
23
|
+
* - Hot tasks: Many recent events (actively being worked on)
|
|
24
|
+
* - Cold tasks: No recent events (stale, needs attention)
|
|
25
|
+
* - Priority surfacing: Show hot tasks first in sprint views
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Extract task IDs from text
|
|
29
|
+
*
|
|
30
|
+
* Matches patterns like:
|
|
31
|
+
* - "TASK-1"
|
|
32
|
+
* - "TASK-123"
|
|
33
|
+
* - "task-5" (case insensitive)
|
|
34
|
+
* - "Completed TASK-4, started TASK-5"
|
|
35
|
+
*
|
|
36
|
+
* @param text - Event description or any text content
|
|
37
|
+
* @returns Array of unique task IDs (normalized to uppercase)
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* extractTaskMentions("Completed TASK-4, started TASK-5")
|
|
41
|
+
* // Returns: ["TASK-4", "TASK-5"]
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractTaskMentions(text: string): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Check if text mentions any tasks
|
|
46
|
+
*
|
|
47
|
+
* @param text - Event description or any text content
|
|
48
|
+
* @returns True if text contains at least one task mention
|
|
49
|
+
*/
|
|
50
|
+
export declare function hasTasksMentions(text: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Calculate task hotness score based on recent activity
|
|
53
|
+
*
|
|
54
|
+
* Hotness formula:
|
|
55
|
+
* - Events in last 4h: Weight 3x
|
|
56
|
+
* - Events in last 24h: Weight 2x
|
|
57
|
+
* - Events in last 7d: Weight 1x
|
|
58
|
+
*
|
|
59
|
+
* @param events - Array of event timestamps (ISO format)
|
|
60
|
+
* @param now - Current timestamp (for testing)
|
|
61
|
+
* @returns Hotness score (0-100)
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* calculateHotness([
|
|
65
|
+
* "2025-11-21T10:00:00Z", // 2h ago
|
|
66
|
+
* "2025-11-21T08:00:00Z", // 4h ago
|
|
67
|
+
* "2025-11-20T10:00:00Z" // 1d ago
|
|
68
|
+
* ])
|
|
69
|
+
* // Returns: ~85 (high hotness)
|
|
70
|
+
*/
|
|
71
|
+
export declare function calculateHotness(events: Array<{
|
|
72
|
+
timestamp: string;
|
|
73
|
+
}>, now?: Date): number;
|
|
74
|
+
/**
|
|
75
|
+
* Classify hotness level for UI display
|
|
76
|
+
*
|
|
77
|
+
* @param hotness - Hotness score (0-100)
|
|
78
|
+
* @returns Level classification
|
|
79
|
+
*/
|
|
80
|
+
export declare function getHotnessLevel(hotness: number): 'cold' | 'warm' | 'hot' | 'blazing';
|
|
81
|
+
//# sourceMappingURL=event-task-linker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-task-linker.d.ts","sourceRoot":"","sources":["../../src/lib/event-task-linker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB1D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,EACpC,GAAG,GAAE,IAAiB,GACrB,MAAM,CAiCR;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAKpF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-11-21
|
|
5
|
+
* @tags: [event-linking, task-detection, graph-relationships, epic-001]
|
|
6
|
+
* @related: [event-logger.ts, sprint-parser.ts, event-queue.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: low
|
|
9
|
+
* @dependencies: []
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Event-Task Linker (EPIC-001 TASK-4)
|
|
13
|
+
*
|
|
14
|
+
* Extracts task mentions (TASK-XXX patterns) from event descriptions
|
|
15
|
+
* to enable hot/cold task detection via RECENT_ACTIVITY relationships.
|
|
16
|
+
*
|
|
17
|
+
* Usage in graph sync:
|
|
18
|
+
* 1. Extract task IDs from event description
|
|
19
|
+
* 2. Create (Task)<-[:RECENT_ACTIVITY]-(Event) relationships
|
|
20
|
+
* 3. Query recent activity to determine task "hotness"
|
|
21
|
+
*
|
|
22
|
+
* Enables momentum awareness:
|
|
23
|
+
* - Hot tasks: Many recent events (actively being worked on)
|
|
24
|
+
* - Cold tasks: No recent events (stale, needs attention)
|
|
25
|
+
* - Priority surfacing: Show hot tasks first in sprint views
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Extract task IDs from text
|
|
29
|
+
*
|
|
30
|
+
* Matches patterns like:
|
|
31
|
+
* - "TASK-1"
|
|
32
|
+
* - "TASK-123"
|
|
33
|
+
* - "task-5" (case insensitive)
|
|
34
|
+
* - "Completed TASK-4, started TASK-5"
|
|
35
|
+
*
|
|
36
|
+
* @param text - Event description or any text content
|
|
37
|
+
* @returns Array of unique task IDs (normalized to uppercase)
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* extractTaskMentions("Completed TASK-4, started TASK-5")
|
|
41
|
+
* // Returns: ["TASK-4", "TASK-5"]
|
|
42
|
+
*/
|
|
43
|
+
export function extractTaskMentions(text) {
|
|
44
|
+
if (!text || typeof text !== 'string') {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
// Match TASK-XXX pattern (case insensitive)
|
|
48
|
+
const taskPattern = /TASK-(\d+)/gi;
|
|
49
|
+
const matches = text.matchAll(taskPattern);
|
|
50
|
+
// Extract unique task IDs, normalize to uppercase
|
|
51
|
+
const taskIds = new Set();
|
|
52
|
+
for (const match of matches) {
|
|
53
|
+
const taskId = `TASK-${match[1]}`;
|
|
54
|
+
taskIds.add(taskId);
|
|
55
|
+
}
|
|
56
|
+
return Array.from(taskIds);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if text mentions any tasks
|
|
60
|
+
*
|
|
61
|
+
* @param text - Event description or any text content
|
|
62
|
+
* @returns True if text contains at least one task mention
|
|
63
|
+
*/
|
|
64
|
+
export function hasTasksMentions(text) {
|
|
65
|
+
return extractTaskMentions(text).length > 0;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculate task hotness score based on recent activity
|
|
69
|
+
*
|
|
70
|
+
* Hotness formula:
|
|
71
|
+
* - Events in last 4h: Weight 3x
|
|
72
|
+
* - Events in last 24h: Weight 2x
|
|
73
|
+
* - Events in last 7d: Weight 1x
|
|
74
|
+
*
|
|
75
|
+
* @param events - Array of event timestamps (ISO format)
|
|
76
|
+
* @param now - Current timestamp (for testing)
|
|
77
|
+
* @returns Hotness score (0-100)
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* calculateHotness([
|
|
81
|
+
* "2025-11-21T10:00:00Z", // 2h ago
|
|
82
|
+
* "2025-11-21T08:00:00Z", // 4h ago
|
|
83
|
+
* "2025-11-20T10:00:00Z" // 1d ago
|
|
84
|
+
* ])
|
|
85
|
+
* // Returns: ~85 (high hotness)
|
|
86
|
+
*/
|
|
87
|
+
export function calculateHotness(events, now = new Date()) {
|
|
88
|
+
if (!events || events.length === 0) {
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
const nowMs = now.getTime();
|
|
92
|
+
const hour4Ms = 4 * 60 * 60 * 1000;
|
|
93
|
+
const hour24Ms = 24 * 60 * 60 * 1000;
|
|
94
|
+
const day7Ms = 7 * 24 * 60 * 60 * 1000;
|
|
95
|
+
let score = 0;
|
|
96
|
+
for (const event of events) {
|
|
97
|
+
const eventTime = new Date(event.timestamp).getTime();
|
|
98
|
+
const ageMs = nowMs - eventTime;
|
|
99
|
+
if (ageMs < 0) {
|
|
100
|
+
// Future event (clock skew), ignore
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (ageMs <= hour4Ms) {
|
|
104
|
+
score += 30; // Very recent: 3x weight
|
|
105
|
+
}
|
|
106
|
+
else if (ageMs <= hour24Ms) {
|
|
107
|
+
score += 20; // Recent: 2x weight
|
|
108
|
+
}
|
|
109
|
+
else if (ageMs <= day7Ms) {
|
|
110
|
+
score += 10; // This week: 1x weight
|
|
111
|
+
}
|
|
112
|
+
// Events older than 7 days don't contribute
|
|
113
|
+
}
|
|
114
|
+
// Cap at 100
|
|
115
|
+
return Math.min(score, 100);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Classify hotness level for UI display
|
|
119
|
+
*
|
|
120
|
+
* @param hotness - Hotness score (0-100)
|
|
121
|
+
* @returns Level classification
|
|
122
|
+
*/
|
|
123
|
+
export function getHotnessLevel(hotness) {
|
|
124
|
+
if (hotness === 0)
|
|
125
|
+
return 'cold';
|
|
126
|
+
if (hotness < 30)
|
|
127
|
+
return 'warm';
|
|
128
|
+
if (hotness < 70)
|
|
129
|
+
return 'hot';
|
|
130
|
+
return 'blazing';
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=event-task-linker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-task-linker.js","sourceRoot":"","sources":["../../src/lib/event-task-linker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,4CAA4C;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE3C,kDAAkD;IAClD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAoC,EACpC,MAAY,IAAI,IAAI,EAAE;IAEtB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACnC,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACrC,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAEvC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;QAEhC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,oCAAoC;YACpC,SAAS;QACX,CAAC;QAED,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;YACrB,KAAK,IAAI,EAAE,CAAC,CAAC,yBAAyB;QACxC,CAAC;aAAM,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,KAAK,IAAI,EAAE,CAAC,CAAC,oBAAoB;QACnC,CAAC;aAAM,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,IAAI,EAAE,CAAC,CAAC,uBAAuB;QACtC,CAAC;QACD,4CAA4C;IAC9C,CAAC;IAED,aAAa;IACb,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,OAAO,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACjC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,MAAM,CAAC;IAChC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-11-24
|
|
5
|
+
* @tags: [output, formatting, human-ux, ai-ux, task-11, dual-output]
|
|
6
|
+
* @related: [start-reflection.ts, context-loader-events.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [chalk]
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Session output containing both human and AI formats
|
|
13
|
+
*/
|
|
14
|
+
export interface SessionOutput {
|
|
15
|
+
/** Concise console display for humans (6-8 lines) */
|
|
16
|
+
humanOutput: string;
|
|
17
|
+
/** Rich structured data for AI context */
|
|
18
|
+
aiContext: AISessionContext;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Full AI context structure - everything the AI needs to understand the session
|
|
22
|
+
*/
|
|
23
|
+
export interface AISessionContext {
|
|
24
|
+
/** Session metadata */
|
|
25
|
+
session: {
|
|
26
|
+
id: string;
|
|
27
|
+
branch: string;
|
|
28
|
+
startedAt: string;
|
|
29
|
+
flowScore: number;
|
|
30
|
+
flowState: string;
|
|
31
|
+
workMode: string;
|
|
32
|
+
};
|
|
33
|
+
/** Project charter (mission, goals, success criteria) */
|
|
34
|
+
charter?: {
|
|
35
|
+
purpose: string;
|
|
36
|
+
goals: string[];
|
|
37
|
+
successCriteria: string[];
|
|
38
|
+
scope?: {
|
|
39
|
+
inScope: string[];
|
|
40
|
+
outOfScope: string[];
|
|
41
|
+
tbd: string[];
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/** Team activity from last 7 days */
|
|
45
|
+
teamActivity?: {
|
|
46
|
+
decisions: Array<{
|
|
47
|
+
user: string;
|
|
48
|
+
description: string;
|
|
49
|
+
timestamp: string;
|
|
50
|
+
impact?: string;
|
|
51
|
+
}>;
|
|
52
|
+
achievements: Array<{
|
|
53
|
+
user: string;
|
|
54
|
+
description: string;
|
|
55
|
+
timestamp: string;
|
|
56
|
+
}>;
|
|
57
|
+
};
|
|
58
|
+
/** Relevant patterns and gotchas */
|
|
59
|
+
patterns?: Array<{
|
|
60
|
+
title: string;
|
|
61
|
+
content: string;
|
|
62
|
+
tags: string[];
|
|
63
|
+
category?: string;
|
|
64
|
+
}>;
|
|
65
|
+
/** Current sprint context */
|
|
66
|
+
sprint?: {
|
|
67
|
+
id: string;
|
|
68
|
+
name: string;
|
|
69
|
+
goal: string;
|
|
70
|
+
progress: number;
|
|
71
|
+
currentTask?: {
|
|
72
|
+
id: string;
|
|
73
|
+
title: string;
|
|
74
|
+
status: string;
|
|
75
|
+
files: string[];
|
|
76
|
+
priority: string;
|
|
77
|
+
};
|
|
78
|
+
tasks: Array<{
|
|
79
|
+
id: string;
|
|
80
|
+
title: string;
|
|
81
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
82
|
+
}>;
|
|
83
|
+
};
|
|
84
|
+
/** Recent work synthesis */
|
|
85
|
+
synthesis?: {
|
|
86
|
+
completedWork: string[];
|
|
87
|
+
inProgressWork: string[];
|
|
88
|
+
blockedItems: string[];
|
|
89
|
+
keyDecisions: string[];
|
|
90
|
+
gotchas: string[];
|
|
91
|
+
resumePoint?: string;
|
|
92
|
+
nextAction?: string;
|
|
93
|
+
suggestedCommand?: string;
|
|
94
|
+
};
|
|
95
|
+
/** Git status */
|
|
96
|
+
git: {
|
|
97
|
+
branch: string;
|
|
98
|
+
commitsAhead: number;
|
|
99
|
+
uncommittedChanges: {
|
|
100
|
+
modified: string[];
|
|
101
|
+
created: string[];
|
|
102
|
+
untracked: string[];
|
|
103
|
+
};
|
|
104
|
+
warnings: string[];
|
|
105
|
+
};
|
|
106
|
+
/** Context loading metrics */
|
|
107
|
+
metrics: {
|
|
108
|
+
eventsLoaded: number;
|
|
109
|
+
documentsLoaded: number;
|
|
110
|
+
tokenEstimate: number;
|
|
111
|
+
tokenReduction?: string;
|
|
112
|
+
loadTimeMs: number;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Configuration for output formatting
|
|
117
|
+
*/
|
|
118
|
+
export interface OutputConfig {
|
|
119
|
+
/** Show verbose AI context in console */
|
|
120
|
+
verbose?: boolean;
|
|
121
|
+
/** Minimal output for quick starts */
|
|
122
|
+
minimal?: boolean;
|
|
123
|
+
/** Disable colors (for piping) */
|
|
124
|
+
noColor?: boolean;
|
|
125
|
+
/** Work mode affects output verbosity */
|
|
126
|
+
workMode?: 'hack-ship' | 'think-build' | 'full-planning';
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Format session output for both human and AI consumers
|
|
130
|
+
*
|
|
131
|
+
* Human output is concise (6-8 lines), AI context is rich (full JSON)
|
|
132
|
+
*/
|
|
133
|
+
export declare function formatSessionOutput(context: AISessionContext, config?: OutputConfig): SessionOutput;
|
|
134
|
+
/**
|
|
135
|
+
* Format concise human-readable output (6-8 lines max)
|
|
136
|
+
*
|
|
137
|
+
* Focuses on: What mode? What task? What to do next? Any blockers?
|
|
138
|
+
*/
|
|
139
|
+
export declare function formatHumanOutput(context: AISessionContext, config?: OutputConfig): string;
|
|
140
|
+
/**
|
|
141
|
+
* Format verbose output showing AI context (for debugging)
|
|
142
|
+
*/
|
|
143
|
+
export declare function formatVerboseOutput(context: AISessionContext): string;
|
|
144
|
+
/**
|
|
145
|
+
* Format AI context as JSON for file storage or MCP
|
|
146
|
+
*/
|
|
147
|
+
export declare function formatAIContextJSON(context: AISessionContext): string;
|
|
148
|
+
/**
|
|
149
|
+
* Format AI context as compact JSONL (for append-only logs)
|
|
150
|
+
*/
|
|
151
|
+
export declare function formatAIContextJSONL(context: AISessionContext): string;
|
|
152
|
+
/**
|
|
153
|
+
* Format list of items with optional limit
|
|
154
|
+
*/
|
|
155
|
+
export declare function formatList(items: string[], options?: {
|
|
156
|
+
limit?: number;
|
|
157
|
+
prefix?: string;
|
|
158
|
+
emptyMessage?: string;
|
|
159
|
+
}): string;
|
|
160
|
+
/**
|
|
161
|
+
* Format success message
|
|
162
|
+
*/
|
|
163
|
+
export declare function formatSuccess(message: string, details?: string): string;
|
|
164
|
+
/**
|
|
165
|
+
* Format error message
|
|
166
|
+
*/
|
|
167
|
+
export declare function formatError(message: string, details?: string): string;
|
|
168
|
+
/**
|
|
169
|
+
* Format warning message
|
|
170
|
+
*/
|
|
171
|
+
export declare function formatWarning(message: string): string;
|
|
172
|
+
//# sourceMappingURL=output-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-formatter.d.ts","sourceRoot":"","sources":["../../src/lib/output-formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: utility
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2025-11-24
|
|
5
|
+
* @tags: [output, formatting, human-ux, ai-ux, task-11, dual-output]
|
|
6
|
+
* @related: [start-reflection.ts, context-loader-events.ts]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [chalk]
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Dual Output Formatter (TASK-11)
|
|
13
|
+
*
|
|
14
|
+
* Separates human-readable console output from AI-optimized context data.
|
|
15
|
+
*
|
|
16
|
+
* Key Principles (AI-UX):
|
|
17
|
+
* 1. Human output: Concise, scannable, action-oriented (6-8 lines max)
|
|
18
|
+
* 2. AI context: Rich, structured, complete (JSON with full details)
|
|
19
|
+
* 3. Both outputs reflect the SAME underlying data
|
|
20
|
+
* 4. --verbose flag shows AI context in console for debugging
|
|
21
|
+
*/
|
|
22
|
+
import chalk from 'chalk';
|
|
23
|
+
/**
|
|
24
|
+
* Format session output for both human and AI consumers
|
|
25
|
+
*
|
|
26
|
+
* Human output is concise (6-8 lines), AI context is rich (full JSON)
|
|
27
|
+
*/
|
|
28
|
+
export function formatSessionOutput(context, config = {}) {
|
|
29
|
+
const humanOutput = formatHumanOutput(context, config);
|
|
30
|
+
const aiContext = context;
|
|
31
|
+
return { humanOutput, aiContext };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format concise human-readable output (6-8 lines max)
|
|
35
|
+
*
|
|
36
|
+
* Focuses on: What mode? What task? What to do next? Any blockers?
|
|
37
|
+
*/
|
|
38
|
+
export function formatHumanOutput(context, config = {}) {
|
|
39
|
+
const lines = [];
|
|
40
|
+
const { minimal = false, workMode = 'think-build' } = config;
|
|
41
|
+
// Line 1: Work Mode + Flow State
|
|
42
|
+
const flowEmoji = getFlowEmoji(context.session.flowScore);
|
|
43
|
+
lines.push(`${flowEmoji} ${chalk.cyan(context.session.workMode)} | Flow: ${context.session.flowScore}/10 | ${chalk.dim(context.session.branch)}`);
|
|
44
|
+
// Line 2-3: Sprint Progress (if active)
|
|
45
|
+
if (context.sprint && !minimal) {
|
|
46
|
+
const progress = typeof context.sprint.progress === 'number' ? context.sprint.progress : 0;
|
|
47
|
+
const progressBar = formatProgressBar(progress, 20);
|
|
48
|
+
const sprintName = context.sprint.name || 'Active Sprint';
|
|
49
|
+
lines.push(`📋 ${sprintName}: ${progressBar} ${progress}%`);
|
|
50
|
+
if (context.sprint.currentTask) {
|
|
51
|
+
lines.push(` ${chalk.yellow('[@]')} ${context.sprint.currentTask.id}: ${context.sprint.currentTask.title}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Line 4: Resume Point / Next Action (CRITICAL - most important)
|
|
55
|
+
if (context.synthesis?.resumePoint) {
|
|
56
|
+
const resumeShort = truncate(context.synthesis.resumePoint, 70);
|
|
57
|
+
lines.push(`⚡ ${chalk.green('Resume:')} ${resumeShort}`);
|
|
58
|
+
}
|
|
59
|
+
if (context.synthesis?.suggestedCommand) {
|
|
60
|
+
lines.push(` ${chalk.dim('$')} ${chalk.cyan(context.synthesis.suggestedCommand)}`);
|
|
61
|
+
}
|
|
62
|
+
// Line 5: Blockers (if any - IMPORTANT)
|
|
63
|
+
if (context.synthesis?.blockedItems && context.synthesis.blockedItems.length > 0) {
|
|
64
|
+
lines.push(chalk.red(`🚫 Blocked: ${context.synthesis.blockedItems[0]}`));
|
|
65
|
+
}
|
|
66
|
+
// Line 6: Git warnings (if any)
|
|
67
|
+
if (context.git.warnings.length > 0) {
|
|
68
|
+
lines.push(chalk.yellow(`⚠️ ${context.git.warnings[0]}`));
|
|
69
|
+
}
|
|
70
|
+
else if (context.git.uncommittedChanges.modified.length > 0) {
|
|
71
|
+
const totalChanges = context.git.uncommittedChanges.modified.length +
|
|
72
|
+
context.git.uncommittedChanges.created.length +
|
|
73
|
+
context.git.uncommittedChanges.untracked.length;
|
|
74
|
+
lines.push(chalk.dim(`📝 ${totalChanges} uncommitted changes`));
|
|
75
|
+
}
|
|
76
|
+
// Final line: Ready message
|
|
77
|
+
lines.push('');
|
|
78
|
+
lines.push(chalk.green('Ready to build!') + chalk.dim(' Use ginko log to capture insights'));
|
|
79
|
+
return lines.join('\n');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format verbose output showing AI context (for debugging)
|
|
83
|
+
*/
|
|
84
|
+
export function formatVerboseOutput(context) {
|
|
85
|
+
const lines = [];
|
|
86
|
+
lines.push(chalk.cyan.bold('\n📊 AI Context (--verbose mode)\n'));
|
|
87
|
+
// Charter
|
|
88
|
+
if (context.charter) {
|
|
89
|
+
lines.push(chalk.yellow('📜 Charter:'));
|
|
90
|
+
lines.push(` Purpose: ${truncate(context.charter.purpose, 100)}`);
|
|
91
|
+
lines.push(` Goals: ${context.charter.goals.length} defined`);
|
|
92
|
+
lines.push('');
|
|
93
|
+
}
|
|
94
|
+
// Team Activity
|
|
95
|
+
if (context.teamActivity) {
|
|
96
|
+
const decisions = context.teamActivity.decisions?.length || 0;
|
|
97
|
+
const achievements = context.teamActivity.achievements?.length || 0;
|
|
98
|
+
lines.push(chalk.yellow('👥 Team Activity (7d):'));
|
|
99
|
+
lines.push(` Decisions: ${decisions}, Achievements: ${achievements}`);
|
|
100
|
+
lines.push('');
|
|
101
|
+
}
|
|
102
|
+
// Patterns
|
|
103
|
+
if (context.patterns && context.patterns.length > 0) {
|
|
104
|
+
lines.push(chalk.yellow('🧠 Patterns:'));
|
|
105
|
+
for (const pattern of context.patterns.slice(0, 3)) {
|
|
106
|
+
lines.push(` - ${pattern.title} [${pattern.tags.join(', ')}]`);
|
|
107
|
+
}
|
|
108
|
+
lines.push('');
|
|
109
|
+
}
|
|
110
|
+
// Synthesis Details
|
|
111
|
+
if (context.synthesis) {
|
|
112
|
+
lines.push(chalk.yellow('📝 Synthesis:'));
|
|
113
|
+
lines.push(` Completed: ${context.synthesis.completedWork?.length || 0} items`);
|
|
114
|
+
lines.push(` In Progress: ${context.synthesis.inProgressWork?.length || 0} items`);
|
|
115
|
+
lines.push(` Decisions: ${context.synthesis.keyDecisions?.length || 0}`);
|
|
116
|
+
lines.push(` Gotchas: ${context.synthesis.gotchas?.length || 0}`);
|
|
117
|
+
lines.push('');
|
|
118
|
+
}
|
|
119
|
+
// Metrics
|
|
120
|
+
lines.push(chalk.yellow('📈 Metrics:'));
|
|
121
|
+
lines.push(` Events: ${context.metrics.eventsLoaded}`);
|
|
122
|
+
lines.push(` Documents: ${context.metrics.documentsLoaded}`);
|
|
123
|
+
lines.push(` Tokens: ${context.metrics.tokenEstimate.toLocaleString()}`);
|
|
124
|
+
if (context.metrics.tokenReduction) {
|
|
125
|
+
lines.push(` Reduction: ${context.metrics.tokenReduction}`);
|
|
126
|
+
}
|
|
127
|
+
lines.push(` Load time: ${context.metrics.loadTimeMs}ms`);
|
|
128
|
+
return lines.join('\n');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Format AI context as JSON for file storage or MCP
|
|
132
|
+
*/
|
|
133
|
+
export function formatAIContextJSON(context) {
|
|
134
|
+
return JSON.stringify(context, null, 2);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Format AI context as compact JSONL (for append-only logs)
|
|
138
|
+
*/
|
|
139
|
+
export function formatAIContextJSONL(context) {
|
|
140
|
+
return JSON.stringify({
|
|
141
|
+
timestamp: new Date().toISOString(),
|
|
142
|
+
type: 'session-context',
|
|
143
|
+
...context,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Helper Functions
|
|
148
|
+
// ============================================================================
|
|
149
|
+
/**
|
|
150
|
+
* Get flow state emoji based on score
|
|
151
|
+
*/
|
|
152
|
+
function getFlowEmoji(score) {
|
|
153
|
+
if (score >= 8)
|
|
154
|
+
return '🔥'; // Hot
|
|
155
|
+
if (score >= 6)
|
|
156
|
+
return '⚡'; // Energized
|
|
157
|
+
if (score >= 4)
|
|
158
|
+
return '🌊'; // Flowing
|
|
159
|
+
if (score >= 2)
|
|
160
|
+
return '🌱'; // Growing
|
|
161
|
+
return '❄️'; // Cold
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Format a progress bar
|
|
165
|
+
*/
|
|
166
|
+
function formatProgressBar(progress, width = 20) {
|
|
167
|
+
const filled = Math.round((progress / 100) * width);
|
|
168
|
+
const empty = width - filled;
|
|
169
|
+
return chalk.green('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Truncate string with ellipsis
|
|
173
|
+
*/
|
|
174
|
+
function truncate(str, maxLength) {
|
|
175
|
+
if (str.length <= maxLength)
|
|
176
|
+
return str;
|
|
177
|
+
return str.substring(0, maxLength - 3) + '...';
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Format list of items with optional limit
|
|
181
|
+
*/
|
|
182
|
+
export function formatList(items, options = {}) {
|
|
183
|
+
const { limit = 5, prefix = ' - ', emptyMessage = '(none)' } = options;
|
|
184
|
+
if (items.length === 0)
|
|
185
|
+
return emptyMessage;
|
|
186
|
+
const displayed = items.slice(0, limit);
|
|
187
|
+
const lines = displayed.map((item) => `${prefix}${item}`);
|
|
188
|
+
if (items.length > limit) {
|
|
189
|
+
lines.push(chalk.dim(`${prefix}... and ${items.length - limit} more`));
|
|
190
|
+
}
|
|
191
|
+
return lines.join('\n');
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Format success message
|
|
195
|
+
*/
|
|
196
|
+
export function formatSuccess(message, details) {
|
|
197
|
+
let output = chalk.green(`✓ ${message}`);
|
|
198
|
+
if (details) {
|
|
199
|
+
output += '\n' + chalk.dim(` ${details}`);
|
|
200
|
+
}
|
|
201
|
+
return output;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Format error message
|
|
205
|
+
*/
|
|
206
|
+
export function formatError(message, details) {
|
|
207
|
+
let output = chalk.red(`✗ ${message}`);
|
|
208
|
+
if (details) {
|
|
209
|
+
output += '\n' + chalk.dim(` ${details}`);
|
|
210
|
+
}
|
|
211
|
+
return output;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Format warning message
|
|
215
|
+
*/
|
|
216
|
+
export function formatWarning(message) {
|
|
217
|
+
return chalk.yellow(`⚠️ ${message}`);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=output-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-formatter.js","sourceRoot":"","sources":["../../src/lib/output-formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: utility
|
|
3
|
-
* @status:
|
|
4
|
-
* @updated: 2025-11-
|
|
5
|
-
* @tags: [session, cursor, event-stream, adr-043, multi-context]
|
|
6
|
-
* @related: [commands/start/index.ts, utils/helpers.ts, lib/write-dispatcher/write-dispatcher.ts]
|
|
7
|
-
* @priority:
|
|
3
|
+
* @status: deprecated
|
|
4
|
+
* @updated: 2025-11-19
|
|
5
|
+
* @tags: [session, cursor, event-stream, adr-043, multi-context, deprecated]
|
|
6
|
+
* @related: [commands/start/index.ts, utils/helpers.ts, lib/write-dispatcher/write-dispatcher.ts, context-loader-events.ts]
|
|
7
|
+
* @priority: low
|
|
8
8
|
* @complexity: medium
|
|
9
9
|
* @dependencies: [fs-extra, simple-git]
|
|
10
|
+
*
|
|
11
|
+
* @deprecated TASK-011: Cursors are over-engineered for our use case.
|
|
12
|
+
* We only need "last N events" queries, not stateful cursor tracking.
|
|
13
|
+
* Use loadRecentEvents() from context-loader-events.ts instead.
|
|
14
|
+
*
|
|
15
|
+
* Kept for backward compatibility during transition period.
|
|
16
|
+
* Will be removed in a future version after cloud-first refactor is complete.
|
|
10
17
|
*/
|
|
11
18
|
/**
|
|
12
19
|
* Session cursor interface (ADR-043)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-cursor.d.ts","sourceRoot":"","sources":["../../src/lib/session-cursor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session-cursor.d.ts","sourceRoot":"","sources":["../../src/lib/session-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,IAAI,CAAC;IACd,WAAW,EAAE,IAAI,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,gBAAgB,CAAC,EAAE,GAAG,CAAC;CACxB;AA4GD;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,GAAG,CAAC;CACvB,GAAG,OAAO,CAAC,aAAa,CAAC,CAqBzB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAe3E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC9B,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA6BhC;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAO3E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CA2BrD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAwBhC"}
|