@ginkoai/cli 2.0.0-beta.7 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/commands/join/index.d.ts +5 -4
- package/dist/commands/join/index.d.ts.map +1 -1
- package/dist/commands/join/index.js +73 -8
- package/dist/commands/join/index.js.map +1 -1
- package/dist/commands/login.d.ts +13 -13
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +80 -103
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/start/start-reflection.d.ts +2 -2
- package/dist/commands/start/start-reflection.d.ts.map +1 -1
- package/dist/commands/start/start-reflection.js +9 -4
- package/dist/commands/start/start-reflection.js.map +1 -1
- package/dist/commands/sync/sync-command.d.ts +2 -2
- package/dist/commands/sync/sync-command.d.ts.map +1 -1
- package/dist/commands/sync/sync-command.js +124 -51
- package/dist/commands/sync/sync-command.js.map +1 -1
- package/dist/lib/output-formatter.d.ts +8 -2
- package/dist/lib/output-formatter.d.ts.map +1 -1
- package/dist/lib/output-formatter.js +28 -3
- package/dist/lib/output-formatter.js.map +1 -1
- package/dist/templates/ai-instructions-template.d.ts.map +1 -1
- package/dist/templates/ai-instructions-template.js +22 -20
- package/dist/templates/ai-instructions-template.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,6 +99,33 @@ Enable multiple AI agents to collaborate on complex projects.
|
|
|
99
99
|
|
|
100
100
|
See [Multi-Agent Orchestration Guide](../../docs/guides/MULTI-AGENT-ORCHESTRATION.md) for details.
|
|
101
101
|
|
|
102
|
+
### Team Collaboration (EPIC-008)
|
|
103
|
+
Enable teams to share knowledge while keeping sessions private.
|
|
104
|
+
|
|
105
|
+
- `ginko invite` - Invite collaborators to your team
|
|
106
|
+
- `<email>` - Invite by email address
|
|
107
|
+
- `--role <role>` - Assign role: owner, admin, member
|
|
108
|
+
- `--list` - List pending invitations
|
|
109
|
+
- `--revoke <code>` - Cancel an invitation
|
|
110
|
+
- `ginko join` - Join a team using an invitation code
|
|
111
|
+
- `<code>` - Accept invitation
|
|
112
|
+
- `--yes` - Skip confirmation prompt
|
|
113
|
+
- `ginko teams` - Manage teams
|
|
114
|
+
- `create <name>` - Create a new team
|
|
115
|
+
- `list` - List your teams
|
|
116
|
+
- `add-member <team> <user>` - Add member by GitHub username
|
|
117
|
+
- `remove-member <team> <user>` - Remove a team member
|
|
118
|
+
- `list-members <team>` - List team members
|
|
119
|
+
- `add-to-project <team> <project>` - Grant team access
|
|
120
|
+
- `remove-from-project <team> <project>` - Revoke access
|
|
121
|
+
- `ginko sync` - Pull dashboard edits to local git
|
|
122
|
+
- `--dry-run` - Preview what would be synced
|
|
123
|
+
- `--force` - Overwrite local files
|
|
124
|
+
- `--type <type>` - Sync only: ADR, PRD, Pattern, Gotcha, Charter, Sprint
|
|
125
|
+
- `--no-commit` - Skip auto-commit
|
|
126
|
+
|
|
127
|
+
See [Team Collaboration Guide](../../docs/guides/team-collaboration.md) for details.
|
|
128
|
+
|
|
102
129
|
## Features
|
|
103
130
|
|
|
104
131
|
### Privacy First
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated: 2026-01-
|
|
5
|
-
* @tags: [join, team, collaboration, epic-008]
|
|
6
|
-
* @related: [../invite/index.ts, ../team/index.ts]
|
|
4
|
+
* @updated: 2026-01-05
|
|
5
|
+
* @tags: [join, team, collaboration, epic-008, onboarding-optimization]
|
|
6
|
+
* @related: [../invite/index.ts, ../team/index.ts, ../sync/sync-command.ts]
|
|
7
7
|
* @priority: high
|
|
8
8
|
* @complexity: medium
|
|
9
9
|
* @dependencies: [commander, chalk, ora, prompts]
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Join Command (EPIC-008 Sprint 1)
|
|
13
13
|
*
|
|
14
|
-
* CLI command for users to join a team via invitation code
|
|
14
|
+
* CLI command for users to join a team via invitation code.
|
|
15
|
+
* Automatically syncs team context after successful join (e008_s03_t03).
|
|
15
16
|
*/
|
|
16
17
|
import { Command } from 'commander';
|
|
17
18
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/join/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/join/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8OpC;;GAEG;AACH,wBAAgB,WAAW,YA2C1B;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated: 2026-01-
|
|
5
|
-
* @tags: [join, team, collaboration, epic-008]
|
|
6
|
-
* @related: [../invite/index.ts, ../team/index.ts]
|
|
4
|
+
* @updated: 2026-01-05
|
|
5
|
+
* @tags: [join, team, collaboration, epic-008, onboarding-optimization]
|
|
6
|
+
* @related: [../invite/index.ts, ../team/index.ts, ../sync/sync-command.ts]
|
|
7
7
|
* @priority: high
|
|
8
8
|
* @complexity: medium
|
|
9
9
|
* @dependencies: [commander, chalk, ora, prompts]
|
|
@@ -11,13 +11,46 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Join Command (EPIC-008 Sprint 1)
|
|
13
13
|
*
|
|
14
|
-
* CLI command for users to join a team via invitation code
|
|
14
|
+
* CLI command for users to join a team via invitation code.
|
|
15
|
+
* Automatically syncs team context after successful join (e008_s03_t03).
|
|
15
16
|
*/
|
|
16
17
|
import { Command } from 'commander';
|
|
17
18
|
import chalk from 'chalk';
|
|
18
19
|
import ora from 'ora';
|
|
19
20
|
import prompts from 'prompts';
|
|
21
|
+
import { existsSync } from 'fs';
|
|
22
|
+
import { join } from 'path';
|
|
20
23
|
import { api } from '../../utils/api-client.js';
|
|
24
|
+
import { syncCommand } from '../sync/sync-command.js';
|
|
25
|
+
/**
|
|
26
|
+
* Check if current directory is a project directory (has .git)
|
|
27
|
+
*/
|
|
28
|
+
function isProjectDirectory() {
|
|
29
|
+
const gitDir = join(process.cwd(), '.git');
|
|
30
|
+
return existsSync(gitDir);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Show error when not in a project directory
|
|
34
|
+
*/
|
|
35
|
+
function showNotInProjectError(code) {
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(chalk.red('✗ Not in a project directory'));
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(chalk.dim(' To join a team, first clone the project repository:'));
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(chalk.cyan(' git clone <repo-url>'));
|
|
42
|
+
console.log(chalk.cyan(' cd <project-name>'));
|
|
43
|
+
console.log('');
|
|
44
|
+
if (code) {
|
|
45
|
+
console.log(chalk.dim(' Then run:'));
|
|
46
|
+
console.log(chalk.cyan(` ginko join ${code}`));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log(chalk.dim(' Then run:'));
|
|
50
|
+
console.log(chalk.cyan(' ginko join <invitation-code>'));
|
|
51
|
+
}
|
|
52
|
+
console.log('');
|
|
53
|
+
}
|
|
21
54
|
/**
|
|
22
55
|
* Validate and preview invitation
|
|
23
56
|
*/
|
|
@@ -61,9 +94,33 @@ async function acceptInvitation(code) {
|
|
|
61
94
|
console.log('');
|
|
62
95
|
console.log(chalk.yellow(' Note: Invitation was sent to a different email.'));
|
|
63
96
|
}
|
|
97
|
+
// Step 3: Auto-sync team context with elapsed-time indicator (e008_s03_t03)
|
|
98
|
+
console.log(chalk.dim('\nStep 3/3: Syncing team context...'));
|
|
99
|
+
const syncSpinner = ora('Syncing team context... (this may take 10-30s)').start();
|
|
100
|
+
const startTime = Date.now();
|
|
101
|
+
// Update spinner with elapsed time every second
|
|
102
|
+
const updateInterval = setInterval(() => {
|
|
103
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
104
|
+
syncSpinner.text = `Syncing team context... (${elapsed}s elapsed)`;
|
|
105
|
+
}, 1000);
|
|
106
|
+
try {
|
|
107
|
+
await syncCommand({
|
|
108
|
+
skipMembershipCheck: true, // We just joined, skip membership check
|
|
109
|
+
force: false,
|
|
110
|
+
dryRun: false,
|
|
111
|
+
});
|
|
112
|
+
clearInterval(updateInterval);
|
|
113
|
+
syncSpinner.succeed('Team context synced');
|
|
114
|
+
}
|
|
115
|
+
catch (syncError) {
|
|
116
|
+
clearInterval(updateInterval);
|
|
117
|
+
syncSpinner.warn('Could not auto-sync team context');
|
|
118
|
+
console.log(chalk.dim(` ${syncError.message || 'Unknown error'}`));
|
|
119
|
+
console.log(chalk.dim(' You can sync manually with: ginko sync'));
|
|
120
|
+
}
|
|
64
121
|
console.log('');
|
|
65
122
|
console.log(chalk.dim('Next steps:'));
|
|
66
|
-
console.log(chalk.green(` ginko
|
|
123
|
+
console.log(chalk.green(` ginko start ${chalk.dim('# Begin development session')}`));
|
|
67
124
|
console.log(chalk.green(` ginko teams list-members ${chalk.dim('# See your teammates')}`));
|
|
68
125
|
}
|
|
69
126
|
catch (error) {
|
|
@@ -93,10 +150,11 @@ async function interactiveJoin() {
|
|
|
93
150
|
await joinTeam(response.code);
|
|
94
151
|
}
|
|
95
152
|
/**
|
|
96
|
-
* Main join flow
|
|
153
|
+
* Main join flow with step indicators (e008_s03_t03)
|
|
97
154
|
*/
|
|
98
155
|
async function joinTeam(code) {
|
|
99
|
-
//
|
|
156
|
+
// Step 1: Validate invitation
|
|
157
|
+
console.log(chalk.dim('\nStep 1/3: Validating invitation...'));
|
|
100
158
|
const preview = await previewInvitation(code);
|
|
101
159
|
if (!preview) {
|
|
102
160
|
process.exit(1);
|
|
@@ -131,8 +189,10 @@ async function joinTeam(code) {
|
|
|
131
189
|
console.log(chalk.yellow('Cancelled'));
|
|
132
190
|
return;
|
|
133
191
|
}
|
|
134
|
-
//
|
|
192
|
+
// Step 2: Join team
|
|
193
|
+
console.log(chalk.dim('\nStep 2/3: Joining team...'));
|
|
135
194
|
await acceptInvitation(code);
|
|
195
|
+
// Note: Step 3 (syncing) is handled inside acceptInvitation
|
|
136
196
|
}
|
|
137
197
|
/**
|
|
138
198
|
* Main join command
|
|
@@ -158,6 +218,11 @@ ${chalk.gray('Example:')}
|
|
|
158
218
|
.argument('[code]', 'Invitation code')
|
|
159
219
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
160
220
|
.action(async (code, options) => {
|
|
221
|
+
// Check if we're in a project directory first
|
|
222
|
+
if (!isProjectDirectory()) {
|
|
223
|
+
showNotInProjectError(code);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
161
226
|
if (code) {
|
|
162
227
|
if (options.yes) {
|
|
163
228
|
// Skip preview confirmation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/join/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/join/index.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated:
|
|
5
|
-
* @tags: [cli, auth,
|
|
6
|
-
* @related: [logout.ts, auth-storage.ts, api/auth/
|
|
4
|
+
* @updated: 2026-01-06
|
|
5
|
+
* @tags: [cli, auth, device-flow, login, github, production]
|
|
6
|
+
* @related: [logout.ts, auth-storage.ts, api/auth/device/*]
|
|
7
7
|
* @priority: critical
|
|
8
|
-
* @complexity:
|
|
9
|
-
* @dependencies: [open, chalk, ora
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [open, chalk, ora]
|
|
10
10
|
*/
|
|
11
11
|
interface LoginOptions {
|
|
12
12
|
force?: boolean;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Login command - Authenticate CLI with
|
|
15
|
+
* Login command - Authenticate CLI with Device Code Flow
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
* 1.
|
|
19
|
-
* 2.
|
|
20
|
-
* 3.
|
|
21
|
-
* 4.
|
|
22
|
-
* 5.
|
|
23
|
-
* 6.
|
|
17
|
+
* Device Code Flow (like GitHub CLI):
|
|
18
|
+
* 1. CLI requests device code from API
|
|
19
|
+
* 2. Display code to user
|
|
20
|
+
* 3. Open browser to verification page
|
|
21
|
+
* 4. User logs in (if needed) and enters code
|
|
22
|
+
* 5. CLI polls for authorization
|
|
23
|
+
* 6. Receive API key when authorized
|
|
24
24
|
*/
|
|
25
25
|
export declare function loginCommand(options?: LoginOptions): Promise<void>;
|
|
26
26
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoBD;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsG5E"}
|
package/dist/commands/login.js
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated:
|
|
5
|
-
* @tags: [cli, auth,
|
|
6
|
-
* @related: [logout.ts, auth-storage.ts, api/auth/
|
|
4
|
+
* @updated: 2026-01-06
|
|
5
|
+
* @tags: [cli, auth, device-flow, login, github, production]
|
|
6
|
+
* @related: [logout.ts, auth-storage.ts, api/auth/device/*]
|
|
7
7
|
* @priority: critical
|
|
8
|
-
* @complexity:
|
|
9
|
-
* @dependencies: [open, chalk, ora
|
|
8
|
+
* @complexity: medium
|
|
9
|
+
* @dependencies: [open, chalk, ora]
|
|
10
10
|
*/
|
|
11
|
-
import { randomUUID } from 'crypto';
|
|
12
11
|
import open from 'open';
|
|
13
12
|
import chalk from 'chalk';
|
|
14
13
|
import ora from 'ora';
|
|
15
14
|
import { saveAuthSession, isAuthenticated, getCurrentUser } from '../utils/auth-storage.js';
|
|
16
15
|
/**
|
|
17
|
-
* Login command - Authenticate CLI with
|
|
16
|
+
* Login command - Authenticate CLI with Device Code Flow
|
|
18
17
|
*
|
|
19
|
-
*
|
|
20
|
-
* 1.
|
|
21
|
-
* 2.
|
|
22
|
-
* 3.
|
|
23
|
-
* 4.
|
|
24
|
-
* 5.
|
|
25
|
-
* 6.
|
|
18
|
+
* Device Code Flow (like GitHub CLI):
|
|
19
|
+
* 1. CLI requests device code from API
|
|
20
|
+
* 2. Display code to user
|
|
21
|
+
* 3. Open browser to verification page
|
|
22
|
+
* 4. User logs in (if needed) and enters code
|
|
23
|
+
* 5. CLI polls for authorization
|
|
24
|
+
* 6. Receive API key when authorized
|
|
26
25
|
*/
|
|
27
26
|
export async function loginCommand(options = {}) {
|
|
28
27
|
// Check if already authenticated
|
|
@@ -35,31 +34,48 @@ export async function loginCommand(options = {}) {
|
|
|
35
34
|
process.exit(0);
|
|
36
35
|
}
|
|
37
36
|
console.log(chalk.cyan('🔐 Authenticating Ginko CLI\n'));
|
|
38
|
-
const spinner = ora('
|
|
37
|
+
const spinner = ora('Initializing device authentication...').start();
|
|
39
38
|
try {
|
|
40
|
-
// Generate unique session ID for this login attempt
|
|
41
|
-
const sessionId = randomUUID();
|
|
42
39
|
const apiUrl = process.env.GINKO_API_URL || 'https://app.ginkoai.com';
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
// Step 1: Request device code
|
|
41
|
+
const initResponse = await fetch(`${apiUrl}/api/auth/device/init`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'Content-Type': 'application/json' }
|
|
44
|
+
});
|
|
45
|
+
if (!initResponse.ok) {
|
|
46
|
+
const errorData = await initResponse.json().catch(() => ({ error: 'Failed to initialize' }));
|
|
47
|
+
throw new Error(errorData.error || 'Failed to initialize device authentication');
|
|
48
|
+
}
|
|
49
|
+
const deviceData = await initResponse.json();
|
|
50
|
+
spinner.succeed('Device code generated');
|
|
51
|
+
// Step 2: Display code to user
|
|
52
|
+
console.log('\n' + chalk.bold(' Enter this code in your browser:\n'));
|
|
53
|
+
console.log(chalk.bgWhite.black.bold(` ${deviceData.user_code} `));
|
|
54
|
+
console.log();
|
|
55
|
+
// Step 3: Open browser
|
|
56
|
+
spinner.start('Opening browser...');
|
|
57
|
+
await open(deviceData.verification_uri);
|
|
48
58
|
spinner.succeed('Browser opened');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Poll
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
console.log(chalk.dim(`\n Verification URL: ${deviceData.verification_uri}`));
|
|
60
|
+
console.log();
|
|
61
|
+
// Step 4: Poll for authorization
|
|
62
|
+
spinner.start('Waiting for authorization...');
|
|
63
|
+
const authResult = await pollForAuthorization(deviceData.device_id, apiUrl, deviceData.expires_in, spinner);
|
|
64
|
+
// Step 5: Save credentials
|
|
65
|
+
const session = {
|
|
66
|
+
api_key: authResult.api_key,
|
|
67
|
+
user: {
|
|
68
|
+
id: authResult.user.id,
|
|
69
|
+
email: authResult.user.email || '',
|
|
70
|
+
github_username: authResult.user.github_username
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
await saveAuthSession(session);
|
|
58
74
|
spinner.succeed(chalk.green('Authentication successful!'));
|
|
59
75
|
console.log(chalk.green('\n✓ Successfully authenticated'));
|
|
60
|
-
console.log(chalk.dim(` User: ${
|
|
61
|
-
if (
|
|
62
|
-
console.log(chalk.dim(` GitHub: @${
|
|
76
|
+
console.log(chalk.dim(` User: ${session.user.email || session.user.github_username}`));
|
|
77
|
+
if (session.user.github_username) {
|
|
78
|
+
console.log(chalk.dim(` GitHub: @${session.user.github_username}`));
|
|
63
79
|
}
|
|
64
80
|
console.log(chalk.dim(' Your credentials are stored in ~/.ginko/auth.json'));
|
|
65
81
|
console.log('\n' + chalk.bold('Next step: ') + chalk.cyan('ginko init'));
|
|
@@ -70,13 +86,13 @@ export async function loginCommand(options = {}) {
|
|
|
70
86
|
catch (error) {
|
|
71
87
|
spinner.fail('Authentication failed');
|
|
72
88
|
if (error instanceof Error) {
|
|
73
|
-
if (error.message.includes('timeout')) {
|
|
89
|
+
if (error.message.includes('timeout') || error.message.includes('expired')) {
|
|
74
90
|
console.error(chalk.red('\n✗ Authentication timed out'));
|
|
75
|
-
console.error(chalk.dim(' Please try again and complete authentication within
|
|
91
|
+
console.error(chalk.dim(' Please try again and complete authentication within 10 minutes'));
|
|
76
92
|
}
|
|
77
|
-
else if (error.message.includes('
|
|
78
|
-
console.error(chalk.red('\n✗ Authentication was
|
|
79
|
-
console.error(chalk.dim(' You
|
|
93
|
+
else if (error.message.includes('denied')) {
|
|
94
|
+
console.error(chalk.red('\n✗ Authentication was denied'));
|
|
95
|
+
console.error(chalk.dim(' You or someone else denied the authorization request'));
|
|
80
96
|
}
|
|
81
97
|
else {
|
|
82
98
|
console.error(chalk.red(`\n✗ ${error.message}`));
|
|
@@ -89,48 +105,39 @@ export async function loginCommand(options = {}) {
|
|
|
89
105
|
}
|
|
90
106
|
}
|
|
91
107
|
/**
|
|
92
|
-
* Poll
|
|
93
|
-
*
|
|
94
|
-
* Polls every 2 seconds for up to 5 minutes
|
|
108
|
+
* Poll for device authorization status
|
|
95
109
|
*/
|
|
96
|
-
async function
|
|
110
|
+
async function pollForAuthorization(deviceId, apiUrl, expiresIn, spinner) {
|
|
97
111
|
const pollInterval = 2000; // 2 seconds
|
|
98
|
-
const maxAttempts =
|
|
112
|
+
const maxAttempts = Math.floor((expiresIn * 1000) / pollInterval);
|
|
99
113
|
let attempts = 0;
|
|
100
114
|
while (attempts < maxAttempts) {
|
|
101
115
|
attempts++;
|
|
102
116
|
try {
|
|
103
|
-
const response = await fetch(`${apiUrl}/api/auth/
|
|
104
|
-
if (response.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Session not ready yet, continue polling
|
|
110
|
-
const timeRemaining = Math.floor((maxAttempts - attempts) * pollInterval / 1000);
|
|
111
|
-
spinner.text = `Waiting for authentication... (${timeRemaining}s remaining)`;
|
|
112
|
-
await sleep(pollInterval);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (response.status === 410) {
|
|
116
|
-
// Session expired or denied
|
|
117
|
-
const error = await response.json().catch(() => ({ error: 'Session expired' }));
|
|
118
|
-
throw new Error(error.error || 'Session expired');
|
|
119
|
-
}
|
|
120
|
-
// Other error - log details for debugging
|
|
121
|
-
const errorBody = await response.text();
|
|
122
|
-
console.error(`\nDebug: HTTP ${response.status} from ${apiUrl}/api/auth/cli/session`);
|
|
123
|
-
console.error(`Response: ${errorBody}`);
|
|
124
|
-
let errorMessage = 'Failed to retrieve session';
|
|
125
|
-
try {
|
|
126
|
-
const errorJson = JSON.parse(errorBody);
|
|
127
|
-
errorMessage = errorJson.error || errorMessage;
|
|
117
|
+
const response = await fetch(`${apiUrl}/api/auth/device/status?device_id=${deviceId}`);
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
if (response.status === 404) {
|
|
120
|
+
throw new Error('Device request not found. Please start over.');
|
|
121
|
+
}
|
|
122
|
+
throw new Error('Failed to check authorization status');
|
|
128
123
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
switch (data.status) {
|
|
126
|
+
case 'authorized':
|
|
127
|
+
return data;
|
|
128
|
+
case 'pending':
|
|
129
|
+
const timeRemaining = Math.floor((maxAttempts - attempts) * pollInterval / 1000);
|
|
130
|
+
spinner.text = `Waiting for authorization... (${timeRemaining}s remaining)`;
|
|
131
|
+
await sleep(pollInterval);
|
|
132
|
+
continue;
|
|
133
|
+
case 'expired':
|
|
134
|
+
throw new Error('Authorization code expired. Please try again.');
|
|
135
|
+
case 'denied':
|
|
136
|
+
throw new Error('Authorization was denied.');
|
|
137
|
+
default:
|
|
138
|
+
await sleep(pollInterval);
|
|
139
|
+
continue;
|
|
132
140
|
}
|
|
133
|
-
throw new Error(errorMessage);
|
|
134
141
|
}
|
|
135
142
|
catch (error) {
|
|
136
143
|
if (error instanceof Error && error.message.includes('fetch')) {
|
|
@@ -143,36 +150,6 @@ async function pollForSession(sessionId, apiUrl, spinner) {
|
|
|
143
150
|
}
|
|
144
151
|
throw new Error('Authentication timeout - please try again');
|
|
145
152
|
}
|
|
146
|
-
/**
|
|
147
|
-
* Generate long-lived API key from OAuth session
|
|
148
|
-
*/
|
|
149
|
-
async function generateApiKey(accessToken, apiUrl, user) {
|
|
150
|
-
const url = `${apiUrl}/api/generate-api-key`;
|
|
151
|
-
const response = await fetch(url, {
|
|
152
|
-
method: 'POST',
|
|
153
|
-
headers: {
|
|
154
|
-
'Authorization': `Bearer ${accessToken}`,
|
|
155
|
-
'Content-Type': 'application/json',
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
if (!response.ok) {
|
|
159
|
-
const errorBody = await response.text();
|
|
160
|
-
let errorMessage = 'Failed to generate API key';
|
|
161
|
-
try {
|
|
162
|
-
const errorJson = JSON.parse(errorBody);
|
|
163
|
-
errorMessage = errorJson.error || errorMessage;
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
167
|
-
}
|
|
168
|
-
throw new Error(errorMessage);
|
|
169
|
-
}
|
|
170
|
-
const data = await response.json();
|
|
171
|
-
return {
|
|
172
|
-
api_key: data.api_key,
|
|
173
|
-
user,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
153
|
/**
|
|
177
154
|
* Sleep helper
|
|
178
155
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAiB,MAAM,KAAK,CAAC;AACpC,OAAO,EACL,eAAe,EACf,eAAe,EACf,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAwBlC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAwB,EAAE;IAC3D,iCAAiC;IACjC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,eAAe,EAAE,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,eAAe,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QACvF,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAEzD,MAAM,OAAO,GAAG,GAAG,CAAC,uCAAuC,CAAC,CAAC,KAAK,EAAE,CAAC;IAErE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,yBAAyB,CAAC;QAEtE,8BAA8B;QAC9B,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,uBAAuB,EAAE;YACjE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAsB,CAAC;YAClH,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,4CAA4C,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,EAAwB,CAAC;QAEnE,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAEzC,+BAA+B;QAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,UAAU,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,uBAAuB;QACvB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,MAAM,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;QACxC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAElC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,iCAAiC;QACjC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAE9C,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAC3C,UAAU,CAAC,SAAS,EACpB,MAAM,EACN,UAAU,CAAC,UAAU,EACrB,OAAO,CACR,CAAC;QAEF,2BAA2B;QAC3B,MAAM,OAAO,GAAgB;YAC3B,OAAO,EAAE,UAAU,CAAC,OAAQ;YAC5B,IAAI,EAAE;gBACJ,EAAE,EAAE,UAAU,CAAC,IAAK,CAAC,EAAE;gBACvB,KAAK,EAAE,UAAU,CAAC,IAAK,CAAC,KAAK,IAAI,EAAE;gBACnC,eAAe,EAAE,UAAU,CAAC,IAAK,CAAC,eAAe;aAClD;SACF,CAAC;QAEF,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;QAE/B,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAE3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QACxF,IAAI,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC,CAAC;QAE9E,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;QAEnE,+CAA+C;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAElB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAEtC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBACzD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC,CAAC;YAC/F,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;gBAC1D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC,CAAC;YACrF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,oBAAoB,CACjC,QAAgB,EAChB,MAAc,EACd,SAAiB,EACjB,OAAY;IAEZ,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,YAAY;IACvC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;IAClE,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,OAAO,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC9B,QAAQ,EAAE,CAAC;QAEX,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,MAAM,qCAAqC,QAAQ,EAAE,CACzD,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBAClE,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA0B,CAAC;YAE3D,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpB,KAAK,YAAY;oBACf,OAAO,IAAI,CAAC;gBAEd,KAAK,SAAS;oBACZ,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,QAAQ,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC,CAAC;oBACjF,OAAO,CAAC,IAAI,GAAG,iCAAiC,aAAa,cAAc,CAAC;oBAC5E,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;oBAC1B,SAAS;gBAEX,KAAK,SAAS;oBACZ,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;gBAEnE,KAAK,QAAQ;oBACX,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBAE/C;oBACE,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;oBAC1B,SAAS;YACb,CAAC;QAEH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9D,kCAAkC;gBAClC,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;gBAC1B,SAAS;YACX,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC/D,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated:
|
|
5
|
-
* @tags: [start, reflection, session, initialization, context]
|
|
4
|
+
* @updated: 2026-01-05
|
|
5
|
+
* @tags: [start, reflection, session, initialization, context, onboarding-optimization]
|
|
6
6
|
* @related: [../../core/reflection-pattern.ts, ../handoff/handoff-reflection.ts]
|
|
7
7
|
* @priority: critical
|
|
8
8
|
* @complexity: high
|
|
@@ -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;
|
|
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,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileType: command
|
|
3
3
|
* @status: current
|
|
4
|
-
* @updated:
|
|
5
|
-
* @tags: [start, reflection, session, initialization, context]
|
|
4
|
+
* @updated: 2026-01-05
|
|
5
|
+
* @tags: [start, reflection, session, initialization, context, onboarding-optimization]
|
|
6
6
|
* @related: [../../core/reflection-pattern.ts, ../handoff/handoff-reflection.ts]
|
|
7
7
|
* @priority: critical
|
|
8
8
|
* @complexity: high
|
|
@@ -353,6 +353,10 @@ export class StartReflectionCommand extends ReflectionCommand {
|
|
|
353
353
|
}
|
|
354
354
|
// Use event-based synthesis if available (ADR-043), otherwise fall back to session log synthesis
|
|
355
355
|
const activeSynthesis = eventSynthesis || synthesis;
|
|
356
|
+
// Detect first-time member (e008_s03_t03 onboarding optimization)
|
|
357
|
+
// First-time = no previous session log AND no/few events from this user
|
|
358
|
+
const myEventsCount = eventContext?.myEvents?.length || 0;
|
|
359
|
+
const isFirstTimeMember = !hasLog && myEventsCount < 3;
|
|
356
360
|
// 9. Load initial context using ActiveContextManager (legacy compatibility)
|
|
357
361
|
const sessionData = {
|
|
358
362
|
userSlug: context.userSlug || 'unknown',
|
|
@@ -370,7 +374,7 @@ export class StartReflectionCommand extends ReflectionCommand {
|
|
|
370
374
|
}
|
|
371
375
|
// 11. Build AI context for dual output system (TASK-11)
|
|
372
376
|
// Now async due to graph API enrichment (EPIC-002 Sprint 3 completion)
|
|
373
|
-
const aiContext = await this.buildAIContext(context, activeSynthesis, strategyContext, eventContext, sprintChecklist);
|
|
377
|
+
const aiContext = await this.buildAIContext(context, activeSynthesis, strategyContext, eventContext, sprintChecklist, isFirstTimeMember);
|
|
374
378
|
// Store AI context for MCP/external access
|
|
375
379
|
await this.storeAIContext(aiContext, sessionDir);
|
|
376
380
|
// 12. Display output based on mode (TASK-P2: Concise is now default)
|
|
@@ -1196,7 +1200,7 @@ Example output structure:
|
|
|
1196
1200
|
* Creates a rich, structured context object that AI partners can parse.
|
|
1197
1201
|
* This is the "AI UX" side of the dual output system.
|
|
1198
1202
|
*/
|
|
1199
|
-
async buildAIContext(context, synthesis, strategyContext, eventContext, sprintChecklist) {
|
|
1203
|
+
async buildAIContext(context, synthesis, strategyContext, eventContext, sprintChecklist, isFirstTimeMember = false) {
|
|
1200
1204
|
const workMode = context.workMode || 'Think & Build';
|
|
1201
1205
|
// Build sprint object
|
|
1202
1206
|
let sprint;
|
|
@@ -1276,6 +1280,7 @@ Example output structure:
|
|
|
1276
1280
|
flowScore: synthesis?.flowState?.score || 5,
|
|
1277
1281
|
flowState: synthesis?.flowState?.energy || 'neutral',
|
|
1278
1282
|
workMode: workMode,
|
|
1283
|
+
isFirstTimeMember,
|
|
1279
1284
|
},
|
|
1280
1285
|
charter: eventContext?.strategicContext?.charter,
|
|
1281
1286
|
teamActivity: eventContext?.strategicContext?.teamActivity ? {
|