@ginkoai/cli 2.0.1 → 2.0.3
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.d.ts +4 -4
- package/dist/commands/epic.d.ts.map +1 -1
- package/dist/commands/epic.js +159 -7
- package/dist/commands/epic.js.map +1 -1
- package/dist/commands/graph/api-client.d.ts +47 -1
- package/dist/commands/graph/api-client.d.ts.map +1 -1
- package/dist/commands/graph/api-client.js +42 -0
- package/dist/commands/graph/api-client.js.map +1 -1
- package/dist/commands/graph/explore.d.ts.map +1 -1
- package/dist/commands/graph/explore.js +27 -1
- package/dist/commands/graph/explore.js.map +1 -1
- package/dist/commands/graph/index.d.ts +3 -3
- package/dist/commands/graph/index.d.ts.map +1 -1
- package/dist/commands/graph/index.js +39 -3
- package/dist/commands/graph/index.js.map +1 -1
- package/dist/commands/graph/load.d.ts.map +1 -1
- package/dist/commands/graph/load.js +10 -1
- package/dist/commands/graph/load.js.map +1 -1
- package/dist/commands/graph/migrations/009-epic-roadmap-properties.d.ts +41 -0
- package/dist/commands/graph/migrations/009-epic-roadmap-properties.d.ts.map +1 -0
- package/dist/commands/graph/migrations/009-epic-roadmap-properties.js +90 -0
- package/dist/commands/graph/migrations/009-epic-roadmap-properties.js.map +1 -0
- package/dist/commands/graph/migrations/010-epic-graph-id.d.ts +30 -0
- package/dist/commands/graph/migrations/010-epic-graph-id.d.ts.map +1 -0
- package/dist/commands/graph/migrations/010-epic-graph-id.js +67 -0
- package/dist/commands/graph/migrations/010-epic-graph-id.js.map +1 -0
- package/dist/commands/graph/migrations/011-sprint-epic-id.d.ts +32 -0
- package/dist/commands/graph/migrations/011-sprint-epic-id.d.ts.map +1 -0
- package/dist/commands/graph/migrations/011-sprint-epic-id.js +71 -0
- package/dist/commands/graph/migrations/011-sprint-epic-id.js.map +1 -0
- package/dist/commands/roadmap/index.d.ts +27 -0
- package/dist/commands/roadmap/index.d.ts.map +1 -0
- package/dist/commands/roadmap/index.js +208 -0
- package/dist/commands/roadmap/index.js.map +1 -0
- package/dist/commands/start/start-reflection.d.ts +4 -2
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +121 -59
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/sync/sprint-syncer.d.ts.map +1 -1
- package/dist/commands/sync/sprint-syncer.js +8 -0
- package/dist/commands/sync/sprint-syncer.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/output-formatter.d.ts +90 -0
- package/dist/lib/output-formatter.d.ts.map +1 -1
- package/dist/lib/output-formatter.js +244 -0
- package/dist/lib/output-formatter.js.map +1 -1
- package/dist/lib/roadmap/changelog-inference.d.ts +84 -0
- package/dist/lib/roadmap/changelog-inference.d.ts.map +1 -0
- package/dist/lib/roadmap/changelog-inference.js +163 -0
- package/dist/lib/roadmap/changelog-inference.js.map +1 -0
- package/dist/lib/sprint-loader.d.ts +25 -1
- package/dist/lib/sprint-loader.d.ts.map +1 -1
- package/dist/lib/sprint-loader.js +196 -2
- package/dist/lib/sprint-loader.js.map +1 -1
- package/dist/lib/user-sprint.d.ts +59 -0
- package/dist/lib/user-sprint.d.ts.map +1 -0
- package/dist/lib/user-sprint.js +147 -0
- package/dist/lib/user-sprint.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileType: command
|
|
3
|
+
* @status: current
|
|
4
|
+
* @updated: 2026-01-11
|
|
5
|
+
* @tags: [roadmap, cli, epic, product-management, ADR-056, now-next-later]
|
|
6
|
+
* @related: [../graph/api-client.ts, ADR-056]
|
|
7
|
+
* @priority: high
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [commander, chalk]
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import chalk from 'chalk';
|
|
13
|
+
import { GraphApiClient } from '../graph/api-client.js';
|
|
14
|
+
import { loadGraphConfig } from '../graph/config.js';
|
|
15
|
+
/**
|
|
16
|
+
* Get status icon based on roadmap_status
|
|
17
|
+
*/
|
|
18
|
+
function getStatusIcon(status) {
|
|
19
|
+
switch (status) {
|
|
20
|
+
case 'not_started':
|
|
21
|
+
return chalk.gray('○');
|
|
22
|
+
case 'in_progress':
|
|
23
|
+
return chalk.blue('◐');
|
|
24
|
+
case 'completed':
|
|
25
|
+
return chalk.green('●');
|
|
26
|
+
case 'cancelled':
|
|
27
|
+
return chalk.red('✗');
|
|
28
|
+
default:
|
|
29
|
+
return chalk.gray('?');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get lane header with icon
|
|
34
|
+
*/
|
|
35
|
+
function getLaneHeader(lane, count) {
|
|
36
|
+
switch (lane) {
|
|
37
|
+
case 'now':
|
|
38
|
+
return chalk.green(`⚡ Now`) + chalk.dim(` (${count})`);
|
|
39
|
+
case 'next':
|
|
40
|
+
return chalk.cyan(`📋 Next`) + chalk.dim(` (${count})`);
|
|
41
|
+
case 'later':
|
|
42
|
+
return chalk.yellow(`💭 Later`) + chalk.dim(` (${count})`);
|
|
43
|
+
case 'done':
|
|
44
|
+
return chalk.gray(`✓ Done`) + chalk.dim(` (${count})`);
|
|
45
|
+
case 'dropped':
|
|
46
|
+
return chalk.red(`✗ Dropped`) + chalk.dim(` (${count})`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Format decision factors as tags
|
|
51
|
+
*/
|
|
52
|
+
function formatDecisionFactors(factors) {
|
|
53
|
+
if (!factors || factors.length === 0)
|
|
54
|
+
return '';
|
|
55
|
+
return chalk.dim(`[${factors.slice(0, 2).join(', ')}]`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Display roadmap in CLI format
|
|
59
|
+
*/
|
|
60
|
+
function displayRoadmap(response, options) {
|
|
61
|
+
const { lanes, summary } = response;
|
|
62
|
+
// Header
|
|
63
|
+
console.log(chalk.bold('\n🗺️ Product Roadmap\n'));
|
|
64
|
+
// Summary line
|
|
65
|
+
const summaryParts = [];
|
|
66
|
+
if (summary.byLane.now > 0) {
|
|
67
|
+
summaryParts.push(chalk.green(`${summary.byLane.now} now`));
|
|
68
|
+
}
|
|
69
|
+
if (summary.byLane.next > 0) {
|
|
70
|
+
summaryParts.push(chalk.cyan(`${summary.byLane.next} next`));
|
|
71
|
+
}
|
|
72
|
+
if (options.all && summary.byLane.later > 0) {
|
|
73
|
+
summaryParts.push(chalk.yellow(`${summary.byLane.later} later`));
|
|
74
|
+
}
|
|
75
|
+
if (options.all && summary.byLane.done > 0) {
|
|
76
|
+
summaryParts.push(chalk.gray(`${summary.byLane.done} done`));
|
|
77
|
+
}
|
|
78
|
+
if (options.all && summary.byLane.dropped > 0) {
|
|
79
|
+
summaryParts.push(chalk.red(`${summary.byLane.dropped} dropped`));
|
|
80
|
+
}
|
|
81
|
+
if (summary.byStatus.in_progress) {
|
|
82
|
+
summaryParts.push(chalk.blue(`${summary.byStatus.in_progress} in progress`));
|
|
83
|
+
}
|
|
84
|
+
if (summaryParts.length > 0) {
|
|
85
|
+
console.log(chalk.dim(` ${summaryParts.join(' · ')}\n`));
|
|
86
|
+
}
|
|
87
|
+
// Check if empty
|
|
88
|
+
const hasContent = lanes.some(l => l.epics.length > 0);
|
|
89
|
+
if (!hasContent) {
|
|
90
|
+
console.log(chalk.yellow(' No epics found on the roadmap.\n'));
|
|
91
|
+
console.log(chalk.dim(' Tip: Run `ginko roadmap --all` to include Later items.'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// Display each lane
|
|
95
|
+
for (const laneGroup of lanes) {
|
|
96
|
+
if (laneGroup.epics.length === 0)
|
|
97
|
+
continue;
|
|
98
|
+
console.log(getLaneHeader(laneGroup.lane, laneGroup.epics.length));
|
|
99
|
+
console.log(chalk.dim(' ' + '─'.repeat(50)));
|
|
100
|
+
for (const epic of laneGroup.epics) {
|
|
101
|
+
const icon = getStatusIcon(epic.roadmap_status);
|
|
102
|
+
const title = epic.title;
|
|
103
|
+
const id = chalk.dim(`(${epic.id})`);
|
|
104
|
+
// Build extra info
|
|
105
|
+
const extras = [];
|
|
106
|
+
// Show decision factors for Later items
|
|
107
|
+
if (laneGroup.lane === 'later' && epic.decision_factors) {
|
|
108
|
+
extras.push(formatDecisionFactors(epic.decision_factors));
|
|
109
|
+
}
|
|
110
|
+
// Show tags if present
|
|
111
|
+
if (epic.tags && epic.tags.length > 0) {
|
|
112
|
+
extras.push(chalk.dim(epic.tags.slice(0, 2).join(', ')));
|
|
113
|
+
}
|
|
114
|
+
console.log(` ${icon} ${title} ${id}${extras.length ? ' ' + extras.join(' ') : ''}`);
|
|
115
|
+
}
|
|
116
|
+
console.log('');
|
|
117
|
+
}
|
|
118
|
+
// Footer - show hidden counts
|
|
119
|
+
if (!options.all) {
|
|
120
|
+
const hiddenCounts = [];
|
|
121
|
+
if (summary.byLane.later > 0)
|
|
122
|
+
hiddenCounts.push(`${summary.byLane.later} later`);
|
|
123
|
+
if (summary.byLane.done > 0)
|
|
124
|
+
hiddenCounts.push(`${summary.byLane.done} done`);
|
|
125
|
+
if (summary.byLane.dropped > 0)
|
|
126
|
+
hiddenCounts.push(`${summary.byLane.dropped} dropped`);
|
|
127
|
+
if (hiddenCounts.length > 0) {
|
|
128
|
+
console.log(chalk.dim(` ${hiddenCounts.join(', ')} hidden. Use --all to show.`));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
console.log(chalk.dim(' Tip: Use --lane or --status to filter'));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Main roadmap command
|
|
135
|
+
*/
|
|
136
|
+
export async function roadmapAction(options) {
|
|
137
|
+
try {
|
|
138
|
+
// Get graph config
|
|
139
|
+
const config = await loadGraphConfig();
|
|
140
|
+
if (!config || !config.graphId) {
|
|
141
|
+
console.log(chalk.red('\n✗ Graph not initialized. Run `ginko graph init` first.\n'));
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
// Build query params
|
|
145
|
+
const params = new URLSearchParams();
|
|
146
|
+
params.set('graphId', config.graphId);
|
|
147
|
+
if (options.all) {
|
|
148
|
+
params.set('all', 'true');
|
|
149
|
+
}
|
|
150
|
+
if (options.lane) {
|
|
151
|
+
params.set('lane', options.lane);
|
|
152
|
+
}
|
|
153
|
+
if (options.status) {
|
|
154
|
+
params.set('status', options.status);
|
|
155
|
+
}
|
|
156
|
+
// Call the API
|
|
157
|
+
const client = new GraphApiClient();
|
|
158
|
+
const response = await client.request('GET', `/api/v1/graph/roadmap?${params.toString()}`);
|
|
159
|
+
// Output
|
|
160
|
+
if (options.json) {
|
|
161
|
+
console.log(JSON.stringify(response, null, 2));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
displayRoadmap(response, options);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
169
|
+
console.log(chalk.red(`\n✗ Failed to load roadmap: ${message}\n`));
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Create the roadmap command
|
|
175
|
+
*/
|
|
176
|
+
export function roadmapCommand() {
|
|
177
|
+
const roadmap = new Command('roadmap')
|
|
178
|
+
.description('View product roadmap (Now/Next/Later priority lanes)')
|
|
179
|
+
.option('-a, --all', 'Include Later, Done, and Dropped items')
|
|
180
|
+
.option('-l, --lane <lane>', 'Filter by lane (now, next, later, done, dropped)')
|
|
181
|
+
.option('-s, --status <status>', 'Filter by status (not_started, in_progress, completed, cancelled)')
|
|
182
|
+
.option('--json', 'Output as JSON')
|
|
183
|
+
.addHelpText('after', `
|
|
184
|
+
${chalk.gray('Lanes (ADR-056):')}
|
|
185
|
+
${chalk.green('⚡ Now')} Fully planned, committed, ready for implementation
|
|
186
|
+
${chalk.cyan('📋 Next')} Committed but may need additional planning
|
|
187
|
+
${chalk.yellow('💭 Later')} Proposed but not yet committed (has decision factors)
|
|
188
|
+
${chalk.gray('✓ Done')} Completed work (hidden by default)
|
|
189
|
+
${chalk.red('✗ Dropped')} Cancelled/abandoned work (hidden by default)
|
|
190
|
+
|
|
191
|
+
${chalk.gray('Examples:')}
|
|
192
|
+
${chalk.green('ginko roadmap')} ${chalk.gray('# Show Now and Next lanes')}
|
|
193
|
+
${chalk.green('ginko roadmap --all')} ${chalk.gray('# Include Later, Done, Dropped')}
|
|
194
|
+
${chalk.green('ginko roadmap --lane now')} ${chalk.gray('# Show only Now lane')}
|
|
195
|
+
${chalk.green('ginko roadmap --lane done')} ${chalk.gray('# Show completed work')}
|
|
196
|
+
${chalk.green('ginko roadmap --status in_progress')} ${chalk.gray('# Show only in-progress epics')}
|
|
197
|
+
|
|
198
|
+
${chalk.gray('Status Icons:')}
|
|
199
|
+
${chalk.gray('○')} not_started ${chalk.blue('◐')} in_progress
|
|
200
|
+
${chalk.green('●')} completed ${chalk.red('✗')} cancelled
|
|
201
|
+
|
|
202
|
+
${chalk.gray('Decision Factors (for Later items):')}
|
|
203
|
+
planning, value, feasibility, architecture, design, risks, market-fit, dependencies
|
|
204
|
+
`)
|
|
205
|
+
.action(roadmapAction);
|
|
206
|
+
return roadmap;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/roadmap/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -115,8 +115,10 @@ export declare class StartReflectionCommand extends ReflectionCommand {
|
|
|
115
115
|
/**
|
|
116
116
|
* Display concise human output (TASK-11)
|
|
117
117
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
118
|
+
* Now uses table view by default (EPIC-012 Sprint 1).
|
|
119
|
+
* - Default: Table view with branding
|
|
120
|
+
* - --compact: Previous concise format without borders
|
|
121
|
+
* - --no-table: Plain text format for piping
|
|
120
122
|
*/
|
|
121
123
|
private displayConciseOutput;
|
|
122
124
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-reflection.d.ts","sourceRoot":"","sources":["../../../src/commands/start/start-reflection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"start-reflection.d.ts","sourceRoot":"","sources":["../../../src/commands/start/start-reflection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAqDrE;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,iBAAiB;IAC3D,OAAO,CAAC,cAAc,CAAuB;;IAQ7C;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;;OAGG;YACW,kBAAkB;IAmChC;;;;OAIG;IACH,OAAO,CAAC,6BAA6B;IA8ErC;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0V/D;;;;;OAKG;YACW,kBAAkB;IA6VhC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IA+BlC;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAsDlF;;OAEG;YACW,WAAW;IAuBzB;;OAEG;YACW,0BAA0B;IA2DxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;YACW,aAAa;IAM3B;;OAEG;YACW,iBAAiB;IAU/B;;OAEG;YACW,WAAW;IAKzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IA6BpC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4CzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA2B9B;;OAEG;IACG,aAAa,CAAC,YAAY,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAmCpD;;OAEG;IACH,OAAO,CAAC,mBAAmB,CAAC,CAI1B;IAEF;;;;;OAKG;YACW,iBAAiB;IAwI/B;;;;;OAKG;YACW,cAAc;IA+I5B;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;;;OAIG;YACW,cAAc;IAa5B;;OAEG;YACW,oBAAoB;IAuBlC;;;;;OAKG;YACW,kBAAkB;IA0BhC;;;;OAIG;YACW,oBAAoB;CAsDnC;AAGD,eAAe,sBAAsB,CAAC"}
|
|
@@ -21,8 +21,9 @@ import { SessionSynthesizer } from '../../utils/synthesis.js';
|
|
|
21
21
|
import { loadContextStrategic, formatContextSummary } from '../../utils/context-loader.js';
|
|
22
22
|
import { initializeQueue } from '../../lib/event-queue.js';
|
|
23
23
|
import { formatContextSummary as formatEventContextSummary } from '../../lib/context-loader-events.js';
|
|
24
|
-
import { loadSprintChecklist, formatSprintChecklist, formatCurrentTaskDetails } from '../../lib/sprint-loader.js';
|
|
25
|
-
import { formatHumanOutput, formatVerboseOutput, formatAIContextJSONL } from '../../lib/output-formatter.js';
|
|
24
|
+
import { loadSprintChecklist, formatSprintChecklist, formatCurrentTaskDetails, detectSprintProgression } from '../../lib/sprint-loader.js';
|
|
25
|
+
import { formatHumanOutput, formatVerboseOutput, formatAIContextJSONL, formatTableOutput, formatEpicComplete, formatSprintProgressionPrompt } from '../../lib/output-formatter.js';
|
|
26
|
+
import { getUserCurrentSprint, setUserCurrentSprint, createAssignmentFromFile, getSprintFileFromAssignment } from '../../lib/user-sprint.js';
|
|
26
27
|
import { GraphApiClient } from '../graph/api-client.js';
|
|
27
28
|
import { isGraphInitialized, getGraphId } from '../graph/config.js';
|
|
28
29
|
import { isAuthenticated } from '../../utils/auth-storage.js';
|
|
@@ -189,70 +190,96 @@ export class StartReflectionCommand extends ReflectionCommand {
|
|
|
189
190
|
const sessionDir = path.join(ginkoDir, 'sessions', userSlug);
|
|
190
191
|
const projectRoot = await getProjectRoot();
|
|
191
192
|
// Load sprint checklist for session context
|
|
192
|
-
// Strategy:
|
|
193
|
-
//
|
|
193
|
+
// Strategy: User sprint first, then local/graph
|
|
194
|
+
// EPIC-012: Per-user sprint tracking enables multiple users on different sprints
|
|
194
195
|
let sprintChecklist = null;
|
|
195
196
|
let sprintSource = 'local';
|
|
196
|
-
//
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (await isAuthenticated() && await isGraphInitialized()) {
|
|
197
|
+
// First, check if user has a specific sprint assignment
|
|
198
|
+
const userSprint = await getUserCurrentSprint();
|
|
199
|
+
let userSprintLoaded = false;
|
|
200
|
+
if (userSprint) {
|
|
201
201
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
const userSprintFile = await getSprintFileFromAssignment(userSprint);
|
|
203
|
+
if (await fs.pathExists(userSprintFile)) {
|
|
204
|
+
const userSprintChecklist = await loadSprintChecklist(projectRoot, userSprintFile);
|
|
205
|
+
if (userSprintChecklist) {
|
|
206
|
+
sprintChecklist = userSprintChecklist;
|
|
207
|
+
sprintSource = 'user';
|
|
208
|
+
userSprintLoaded = true;
|
|
209
|
+
}
|
|
208
210
|
}
|
|
209
211
|
}
|
|
210
|
-
catch
|
|
211
|
-
//
|
|
212
|
-
|
|
212
|
+
catch {
|
|
213
|
+
// User sprint file may have been deleted - clear the assignment
|
|
214
|
+
// We'll fall back to global sprint
|
|
213
215
|
}
|
|
214
216
|
}
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
217
|
+
// If no user sprint, load global sprint (CURRENT-SPRINT.md)
|
|
218
|
+
let localSprint = null;
|
|
219
|
+
if (!userSprintLoaded) {
|
|
220
|
+
localSprint = await loadSprintChecklist(projectRoot);
|
|
221
|
+
}
|
|
222
|
+
// Only check graph/local if user sprint wasn't already loaded
|
|
223
|
+
if (!userSprintLoaded) {
|
|
224
|
+
// Try to load from graph if authenticated
|
|
225
|
+
let graphSprint = null;
|
|
226
|
+
if (await isAuthenticated() && await isGraphInitialized()) {
|
|
227
|
+
try {
|
|
228
|
+
spinner.text = 'Checking graph for sprint updates...';
|
|
229
|
+
const graphId = await getGraphId();
|
|
230
|
+
if (graphId) {
|
|
231
|
+
const client = new GraphApiClient();
|
|
232
|
+
const graphResponse = await client.getActiveSprint(graphId);
|
|
233
|
+
graphSprint = this.convertGraphSprintToChecklist(graphResponse);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
// Graph unavailable - use local only
|
|
238
|
+
spinner.text = 'Graph unavailable, using local sprint file';
|
|
239
|
+
}
|
|
230
240
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
|
|
241
|
+
// Compare and choose the more complete/current sprint
|
|
242
|
+
// Priority: Local file is source of truth - it represents what the user is actively working on
|
|
243
|
+
// Graph data may be stale (e.g., still showing Sprint 1 when user moved to Sprint 2)
|
|
244
|
+
if (localSprint && graphSprint) {
|
|
245
|
+
// If the sprints are different (different names), always use local
|
|
246
|
+
// This handles the case where graph hasn't been synced with new sprint
|
|
247
|
+
const localName = localSprint.name?.toLowerCase() || '';
|
|
248
|
+
const graphName = graphSprint.name?.toLowerCase() || '';
|
|
249
|
+
const sprintsAreDifferent = localName !== graphName &&
|
|
250
|
+
!localName.includes(graphName) &&
|
|
251
|
+
!graphName.includes(localName);
|
|
252
|
+
if (sprintsAreDifferent) {
|
|
253
|
+
// Local file is the source of truth for which sprint we're on
|
|
239
254
|
sprintChecklist = localSprint;
|
|
240
255
|
sprintSource = 'local';
|
|
241
256
|
}
|
|
242
257
|
else {
|
|
243
|
-
|
|
244
|
-
|
|
258
|
+
// Same sprint - prefer local if it has more tasks OR higher completion count
|
|
259
|
+
// This handles case where graph has stale/test data
|
|
260
|
+
const localTotal = localSprint.progress?.total || 0;
|
|
261
|
+
const graphTotal = graphSprint.progress?.total || 0;
|
|
262
|
+
const localProgress = localSprint.progress?.complete || 0;
|
|
263
|
+
const graphProgress = graphSprint.progress?.complete || 0;
|
|
264
|
+
if (localTotal > graphTotal || localProgress > graphProgress) {
|
|
265
|
+
sprintChecklist = localSprint;
|
|
266
|
+
sprintSource = 'local';
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
sprintChecklist = graphSprint;
|
|
270
|
+
sprintSource = 'graph';
|
|
271
|
+
}
|
|
245
272
|
}
|
|
246
273
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
274
|
+
else if (localSprint) {
|
|
275
|
+
sprintChecklist = localSprint;
|
|
276
|
+
sprintSource = 'local';
|
|
277
|
+
}
|
|
278
|
+
else if (graphSprint) {
|
|
279
|
+
sprintChecklist = graphSprint;
|
|
280
|
+
sprintSource = 'graph';
|
|
281
|
+
}
|
|
282
|
+
} // end if (!userSprintLoaded)
|
|
256
283
|
// Load session log content before archiving
|
|
257
284
|
const previousSessionLog = await SessionLogManager.loadSessionLog(sessionDir);
|
|
258
285
|
const hasLog = previousSessionLog.length > 100; // Non-empty log
|
|
@@ -377,7 +404,29 @@ export class StartReflectionCommand extends ReflectionCommand {
|
|
|
377
404
|
const aiContext = await this.buildAIContext(context, activeSynthesis, strategyContext, eventContext, sprintChecklist, isFirstTimeMember);
|
|
378
405
|
// Store AI context for MCP/external access
|
|
379
406
|
await this.storeAIContext(aiContext, sessionDir);
|
|
380
|
-
// 12.
|
|
407
|
+
// 12. Check sprint progression and epic completion (EPIC-012 Sprint 1)
|
|
408
|
+
let sprintProgression = null;
|
|
409
|
+
if (sprintChecklist) {
|
|
410
|
+
sprintProgression = await detectSprintProgression(sprintChecklist, projectRoot);
|
|
411
|
+
// Display epic completion message if all sprints done
|
|
412
|
+
if (sprintProgression?.isEpicComplete && sprintProgression.epicName) {
|
|
413
|
+
console.log(formatEpicComplete(sprintProgression.epicName, sprintProgression.currentEpicId));
|
|
414
|
+
}
|
|
415
|
+
// Handle sprint progression (current sprint is 100% complete)
|
|
416
|
+
if (sprintProgression?.isSprintComplete && sprintProgression.nextSprintId && !sprintProgression.isEpicComplete) {
|
|
417
|
+
console.log(formatSprintProgressionPrompt(sprintProgression.currentSprintId, sprintProgression.nextSprintId, sprintProgression.nextSprintName || 'Next Sprint'));
|
|
418
|
+
// Auto-progress if flag is set
|
|
419
|
+
if (options.autoProgress && sprintProgression.nextSprintFile) {
|
|
420
|
+
spinner.text = 'Auto-advancing to next sprint...';
|
|
421
|
+
const assignment = await createAssignmentFromFile(sprintProgression.nextSprintFile, sprintProgression.nextSprintName || 'Next Sprint', 'auto');
|
|
422
|
+
if (assignment) {
|
|
423
|
+
await setUserCurrentSprint(assignment);
|
|
424
|
+
spinner.succeed(`Advanced to sprint: ${sprintProgression.nextSprintId}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// 13. Display output based on mode (TASK-P2: Table is now default)
|
|
381
430
|
if (options.verbose) {
|
|
382
431
|
// Verbose mode: Full session info (~80 lines)
|
|
383
432
|
await this.displaySessionInfo(context, contextLevel, activeSynthesis, strategyContext, eventContext, sprintChecklist);
|
|
@@ -386,8 +435,11 @@ export class StartReflectionCommand extends ReflectionCommand {
|
|
|
386
435
|
console.log(chalk.dim(formatContextSummary(strategyContext)));
|
|
387
436
|
}
|
|
388
437
|
else {
|
|
389
|
-
// Default mode:
|
|
390
|
-
this.displayConciseOutput(aiContext
|
|
438
|
+
// Default mode: Table view (use --compact for previous format)
|
|
439
|
+
this.displayConciseOutput(aiContext, {
|
|
440
|
+
compact: options.compact,
|
|
441
|
+
table: options.table
|
|
442
|
+
});
|
|
391
443
|
}
|
|
392
444
|
spinner.succeed('Session initialized with strategic context!');
|
|
393
445
|
// EPIC-008 Sprint 2: Check team context staleness
|
|
@@ -1323,12 +1375,22 @@ Example output structure:
|
|
|
1323
1375
|
/**
|
|
1324
1376
|
* Display concise human output (TASK-11)
|
|
1325
1377
|
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
1378
|
+
* Now uses table view by default (EPIC-012 Sprint 1).
|
|
1379
|
+
* - Default: Table view with branding
|
|
1380
|
+
* - --compact: Previous concise format without borders
|
|
1381
|
+
* - --no-table: Plain text format for piping
|
|
1328
1382
|
*/
|
|
1329
|
-
displayConciseOutput(aiContext) {
|
|
1383
|
+
displayConciseOutput(aiContext, options = {}) {
|
|
1330
1384
|
console.log('');
|
|
1331
|
-
|
|
1385
|
+
// Table view is now the default
|
|
1386
|
+
// --compact uses previous concise format
|
|
1387
|
+
// --no-table (table === false) uses concise format
|
|
1388
|
+
if (options.compact || options.table === false) {
|
|
1389
|
+
console.log(formatHumanOutput(aiContext, { workMode: aiContext.session.workMode }));
|
|
1390
|
+
}
|
|
1391
|
+
else {
|
|
1392
|
+
console.log(formatTableOutput(aiContext));
|
|
1393
|
+
}
|
|
1332
1394
|
console.log('');
|
|
1333
1395
|
}
|
|
1334
1396
|
/**
|