@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.
Files changed (60) hide show
  1. package/dist/commands/epic.d.ts +4 -4
  2. package/dist/commands/epic.d.ts.map +1 -1
  3. package/dist/commands/epic.js +159 -7
  4. package/dist/commands/epic.js.map +1 -1
  5. package/dist/commands/graph/api-client.d.ts +47 -1
  6. package/dist/commands/graph/api-client.d.ts.map +1 -1
  7. package/dist/commands/graph/api-client.js +42 -0
  8. package/dist/commands/graph/api-client.js.map +1 -1
  9. package/dist/commands/graph/explore.d.ts.map +1 -1
  10. package/dist/commands/graph/explore.js +27 -1
  11. package/dist/commands/graph/explore.js.map +1 -1
  12. package/dist/commands/graph/index.d.ts +3 -3
  13. package/dist/commands/graph/index.d.ts.map +1 -1
  14. package/dist/commands/graph/index.js +39 -3
  15. package/dist/commands/graph/index.js.map +1 -1
  16. package/dist/commands/graph/load.d.ts.map +1 -1
  17. package/dist/commands/graph/load.js +10 -1
  18. package/dist/commands/graph/load.js.map +1 -1
  19. package/dist/commands/graph/migrations/009-epic-roadmap-properties.d.ts +41 -0
  20. package/dist/commands/graph/migrations/009-epic-roadmap-properties.d.ts.map +1 -0
  21. package/dist/commands/graph/migrations/009-epic-roadmap-properties.js +90 -0
  22. package/dist/commands/graph/migrations/009-epic-roadmap-properties.js.map +1 -0
  23. package/dist/commands/graph/migrations/010-epic-graph-id.d.ts +30 -0
  24. package/dist/commands/graph/migrations/010-epic-graph-id.d.ts.map +1 -0
  25. package/dist/commands/graph/migrations/010-epic-graph-id.js +67 -0
  26. package/dist/commands/graph/migrations/010-epic-graph-id.js.map +1 -0
  27. package/dist/commands/graph/migrations/011-sprint-epic-id.d.ts +32 -0
  28. package/dist/commands/graph/migrations/011-sprint-epic-id.d.ts.map +1 -0
  29. package/dist/commands/graph/migrations/011-sprint-epic-id.js +71 -0
  30. package/dist/commands/graph/migrations/011-sprint-epic-id.js.map +1 -0
  31. package/dist/commands/roadmap/index.d.ts +27 -0
  32. package/dist/commands/roadmap/index.d.ts.map +1 -0
  33. package/dist/commands/roadmap/index.js +208 -0
  34. package/dist/commands/roadmap/index.js.map +1 -0
  35. package/dist/commands/start/start-reflection.d.ts +4 -2
  36. package/dist/commands/start/start-reflection.d.ts.map +1 -1
  37. package/dist/commands/start/start-reflection.js +121 -59
  38. package/dist/commands/start/start-reflection.js.map +1 -1
  39. package/dist/commands/sync/sprint-syncer.d.ts.map +1 -1
  40. package/dist/commands/sync/sprint-syncer.js +8 -0
  41. package/dist/commands/sync/sprint-syncer.js.map +1 -1
  42. package/dist/index.js +6 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/lib/output-formatter.d.ts +90 -0
  45. package/dist/lib/output-formatter.d.ts.map +1 -1
  46. package/dist/lib/output-formatter.js +244 -0
  47. package/dist/lib/output-formatter.js.map +1 -1
  48. package/dist/lib/roadmap/changelog-inference.d.ts +84 -0
  49. package/dist/lib/roadmap/changelog-inference.d.ts.map +1 -0
  50. package/dist/lib/roadmap/changelog-inference.js +163 -0
  51. package/dist/lib/roadmap/changelog-inference.js.map +1 -0
  52. package/dist/lib/sprint-loader.d.ts +25 -1
  53. package/dist/lib/sprint-loader.d.ts.map +1 -1
  54. package/dist/lib/sprint-loader.js +196 -2
  55. package/dist/lib/sprint-loader.js.map +1 -1
  56. package/dist/lib/user-sprint.d.ts +59 -0
  57. package/dist/lib/user-sprint.d.ts.map +1 -0
  58. package/dist/lib/user-sprint.js +147 -0
  59. package/dist/lib/user-sprint.js.map +1 -0
  60. 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
- * Shows only essential info for instant productivity (6-8 lines).
119
- * Used with --concise flag.
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;AAqCrE;;;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;IA0R/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;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;;;OAIG;YACW,cAAc;IAa5B;;OAEG;YACW,oBAAoB;IAuBlC;;;;;OAKG;YACW,kBAAkB;IA0BhC;;;;OAIG;YACW,oBAAoB;CAsDnC;AAGD,eAAe,sBAAsB,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: Load both local and graph, use the more complete/current one
193
- // Local file is authoritative for solo work; graph is authoritative for team collaboration
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
- // Always load local sprint first (fast, authoritative for file-based workflows)
197
- const localSprint = await loadSprintChecklist(projectRoot);
198
- // Try to load from graph if authenticated
199
- let graphSprint = null;
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
- spinner.text = 'Checking graph for sprint updates...';
203
- const graphId = await getGraphId();
204
- if (graphId) {
205
- const client = new GraphApiClient();
206
- const graphResponse = await client.getActiveSprint(graphId);
207
- graphSprint = this.convertGraphSprintToChecklist(graphResponse);
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 (error) {
211
- // Graph unavailable - use local only
212
- spinner.text = 'Graph unavailable, using local sprint file';
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
- // Compare and choose the more complete/current sprint
216
- // Priority: Local file is source of truth - it represents what the user is actively working on
217
- // Graph data may be stale (e.g., still showing Sprint 1 when user moved to Sprint 2)
218
- if (localSprint && graphSprint) {
219
- // If the sprints are different (different names), always use local
220
- // This handles the case where graph hasn't been synced with new sprint
221
- const localName = localSprint.name?.toLowerCase() || '';
222
- const graphName = graphSprint.name?.toLowerCase() || '';
223
- const sprintsAreDifferent = localName !== graphName &&
224
- !localName.includes(graphName) &&
225
- !graphName.includes(localName);
226
- if (sprintsAreDifferent) {
227
- // Local file is the source of truth for which sprint we're on
228
- sprintChecklist = localSprint;
229
- sprintSource = 'local';
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
- else {
232
- // Same sprint - prefer local if it has more tasks OR higher completion count
233
- // This handles case where graph has stale/test data
234
- const localTotal = localSprint.progress?.total || 0;
235
- const graphTotal = graphSprint.progress?.total || 0;
236
- const localProgress = localSprint.progress?.complete || 0;
237
- const graphProgress = graphSprint.progress?.complete || 0;
238
- if (localTotal > graphTotal || localProgress > graphProgress) {
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
- sprintChecklist = graphSprint;
244
- sprintSource = 'graph';
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
- else if (localSprint) {
249
- sprintChecklist = localSprint;
250
- sprintSource = 'local';
251
- }
252
- else if (graphSprint) {
253
- sprintChecklist = graphSprint;
254
- sprintSource = 'graph';
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. Display output based on mode (TASK-P2: Concise is now default)
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: Concise human-optimized output (≤20 lines)
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
- * Shows only essential info for instant productivity (6-8 lines).
1327
- * Used with --concise flag.
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
- console.log(formatHumanOutput(aiContext, { workMode: aiContext.session.workMode }));
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
  /**