@rigstate/cli 0.7.34 → 0.7.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigstate/cli",
3
- "version": "0.7.34",
3
+ "version": "0.7.36",
4
4
  "description": "Rigstate CLI - Code audit, sync and supervision tool",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,6 @@
17
17
  "dependencies": {
18
18
  "@rigstate/rules-engine": "*",
19
19
  "@rigstate/shared": "*",
20
- "uuid": "^9.0.1",
21
20
  "@types/diff": "^7.0.2",
22
21
  "@types/inquirer": "^9.0.9",
23
22
  "axios": "^1.6.5",
@@ -29,7 +28,9 @@
29
28
  "dotenv": "^16.4.1",
30
29
  "glob": "^10.3.10",
31
30
  "inquirer": "^9.3.8",
32
- "ora": "^8.0.1"
31
+ "ora": "^8.0.1",
32
+ "simple-git": "^3.31.1",
33
+ "uuid": "^9.0.1"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@types/node": "^20.11.5",
@@ -50,4 +51,4 @@
50
51
  ],
51
52
  "author": "Rigstate",
52
53
  "license": "MIT"
53
- }
54
+ }
@@ -141,12 +141,9 @@ export function createEnvPullCommand() {
141
141
  projectId = getProjectId();
142
142
 
143
143
  if (!projectId) {
144
- try {
145
- const manifestPath = path.join(process.cwd(), '.rigstate');
146
- const content = await fs.readFile(manifestPath, 'utf-8');
147
- const manifest = JSON.parse(content);
148
- projectId = manifest.project_id;
149
- } catch (e) { }
144
+ const { loadManifest } = await import('../utils/manifest.js');
145
+ const manifest = await loadManifest();
146
+ if (manifest?.project_id) projectId = manifest.project_id;
150
147
  }
151
148
 
152
149
  if (!projectId) {
@@ -30,12 +30,9 @@ export function createFocusCommand() {
30
30
 
31
31
  projectId = getProjectId();
32
32
  if (!projectId) {
33
- try {
34
- const manifestPath = path.join(process.cwd(), '.rigstate');
35
- const content = await fs.readFile(manifestPath, 'utf-8');
36
- const manifest = JSON.parse(content);
37
- projectId = manifest.project_id;
38
- } catch (e) { }
33
+ const { loadManifest } = await import('../utils/manifest.js');
34
+ const manifest = await loadManifest();
35
+ if (manifest?.project_id) projectId = manifest.project_id;
39
36
  }
40
37
 
41
38
  if (!projectId) {
@@ -0,0 +1,305 @@
1
+ /* eslint-disable no-console */
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import ora from 'ora';
5
+ import axios from 'axios';
6
+ import { getApiKey, getApiUrl, getProjectId } from '../utils/config.js';
7
+
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ // Types
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ interface GenesisStep {
12
+ id: string;
13
+ title: string;
14
+ step_number: number;
15
+ icon: string;
16
+ verification_path?: string;
17
+ }
18
+
19
+ interface GenesisStatusResponse {
20
+ success: boolean;
21
+ data: {
22
+ genesis_complete: boolean;
23
+ genesis_steps: GenesisStep[];
24
+ genesis_count: number;
25
+ total_roadmap_steps: number;
26
+ detected_template: string;
27
+ detected_stack_key: string;
28
+ project_name: string;
29
+ };
30
+ error?: string;
31
+ }
32
+
33
+ interface GenesisTriggerResponse {
34
+ success: boolean;
35
+ data: {
36
+ project_name: string;
37
+ template: string;
38
+ stack_key: string;
39
+ steps_created: number;
40
+ steps: GenesisStep[];
41
+ existing_steps_shifted: number;
42
+ message: string;
43
+ };
44
+ error?: string;
45
+ }
46
+
47
+ // ─────────────────────────────────────────────────────────────────────────────
48
+ // Command Definition
49
+ // ─────────────────────────────────────────────────────────────────────────────
50
+ export function createGenesisCommand(): Command {
51
+ return new Command('genesis')
52
+ .description('Initialize project foundation (Phase 0). Detects stack and injects foundation steps.')
53
+ .option('--force', 'Re-run genesis even if already initialized (use with caution)')
54
+ .option('--status', 'Check genesis status without triggering')
55
+ .option('--project-id <id>', 'Override project ID (defaults to linked project)')
56
+ .action(async (options) => {
57
+ const apiKey = getApiKey();
58
+ const apiUrl = getApiUrl();
59
+ const projectId = options.projectId || getProjectId();
60
+
61
+ if (!projectId) {
62
+ console.error(chalk.red('❌ No project linked. Run: rigstate link'));
63
+ process.exit(1);
64
+ }
65
+
66
+ if (!apiKey) {
67
+ console.error(chalk.red('❌ Not authenticated. Run: rigstate login'));
68
+ process.exit(1);
69
+ }
70
+
71
+ if (options.status) {
72
+ await checkGenesisStatus(projectId, apiKey, apiUrl);
73
+ } else {
74
+ await triggerGenesis(projectId, apiKey, apiUrl, options.force ?? false);
75
+ }
76
+ });
77
+ }
78
+
79
+ // ─────────────────────────────────────────────────────────────────────────────
80
+ // Status Check
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+ export async function checkGenesisStatus(
83
+ projectId: string,
84
+ apiKey: string,
85
+ apiUrl: string
86
+ ): Promise<{ complete: boolean; stepCount: number }> {
87
+ // ── Offline-first: check local manifest cache ─────────────────────────────
88
+ try {
89
+ const { loadManifest } = await import('../utils/manifest.js');
90
+ const manifest = await loadManifest();
91
+ if (manifest?.genesis_complete) {
92
+ // Local cache hit — skip API call
93
+ return { complete: true, stepCount: 0 }; // stepCount not cached, but complete is enough
94
+ }
95
+ } catch {
96
+ // Ignore manifest read errors
97
+ }
98
+
99
+ const spinner = ora('Checking Genesis status...').start();
100
+
101
+ try {
102
+ const response = await axios.get<GenesisStatusResponse>(
103
+ `${apiUrl}/api/v1/genesis`,
104
+ {
105
+ params: { project_id: projectId },
106
+ headers: { Authorization: `Bearer ${apiKey}` },
107
+ timeout: 10000
108
+ }
109
+ );
110
+
111
+ spinner.stop();
112
+
113
+ if (!response.data.success) {
114
+ console.log(chalk.yellow(`⚠️ Could not check genesis status: ${response.data.error}`));
115
+ return { complete: false, stepCount: 0 };
116
+ }
117
+
118
+ const { data } = response.data;
119
+
120
+ console.log('');
121
+ console.log(chalk.bold('🏗️ GENESIS STATUS'));
122
+ console.log(chalk.dim('────────────────────────────────────────'));
123
+ console.log(`${chalk.bold('Project:')} ${chalk.cyan(data.project_name)}`);
124
+ console.log(`${chalk.bold('Stack:')} ${chalk.magenta(data.detected_template)}`);
125
+ console.log(`${chalk.bold('Genesis:')} ${data.genesis_complete ? chalk.green('✅ Complete') : chalk.yellow('⚠️ Pending')}`);
126
+ console.log(`${chalk.bold('Foundation:')} ${chalk.white(data.genesis_count)} steps`);
127
+ console.log(`${chalk.bold('Total Roadmap:')} ${chalk.white(data.total_roadmap_steps)} steps`);
128
+
129
+ if (data.genesis_complete && data.genesis_steps.length > 0) {
130
+ console.log('');
131
+ console.log(chalk.dim('Foundation Steps:'));
132
+ data.genesis_steps.forEach(step => {
133
+ console.log(` ${step.icon} ${chalk.bold(`T-${step.step_number}`)}: ${step.title}`);
134
+ });
135
+ } else if (!data.genesis_complete) {
136
+ console.log('');
137
+ console.log(chalk.yellow('⚡ Genesis not yet initialized.'));
138
+ console.log(chalk.dim(' Run: ') + chalk.white('rigstate genesis'));
139
+ }
140
+
141
+ console.log(chalk.dim('────────────────────────────────────────'));
142
+ console.log('');
143
+
144
+ return { complete: data.genesis_complete, stepCount: data.genesis_count };
145
+
146
+ } catch (err: any) {
147
+ spinner.stop();
148
+ if (err.response?.status === 422) {
149
+ console.log(chalk.yellow('⚠️ Genesis pending: Complete onboarding with Frank first.'));
150
+ console.log(chalk.dim(' Then run: rigstate genesis'));
151
+ }
152
+ return { complete: false, stepCount: 0 };
153
+ }
154
+ }
155
+
156
+
157
+ // ─────────────────────────────────────────────────────────────────────────────
158
+ // Trigger Genesis
159
+ // ─────────────────────────────────────────────────────────────────────────────
160
+ export async function triggerGenesis(
161
+ projectId: string,
162
+ apiKey: string,
163
+ apiUrl: string,
164
+ force = false
165
+ ): Promise<boolean> {
166
+ console.log('');
167
+ console.log(chalk.bold.blue('🏗️ GENESIS PROTOCOL'));
168
+ console.log(chalk.dim('Initializing project foundation...'));
169
+ console.log('');
170
+
171
+ const spinner = ora('Detecting tech stack...').start();
172
+
173
+ try {
174
+ // Step 1: Check status first (unless force)
175
+ if (!force) {
176
+ const statusRes = await axios.get<GenesisStatusResponse>(
177
+ `${apiUrl}/api/v1/genesis`,
178
+ {
179
+ params: { project_id: projectId },
180
+ headers: { Authorization: `Bearer ${apiKey}` },
181
+ timeout: 10000
182
+ }
183
+ );
184
+
185
+ if (statusRes.data.success && statusRes.data.data.genesis_complete) {
186
+ spinner.stop();
187
+ console.log(chalk.green('✅ Genesis already complete.'));
188
+ console.log(chalk.dim(` ${statusRes.data.data.genesis_count} foundation steps already in roadmap.`));
189
+ console.log(chalk.dim(' Use --force to re-initialize.'));
190
+ console.log('');
191
+ return true;
192
+ }
193
+
194
+ if (statusRes.data.success) {
195
+ spinner.text = `Stack detected: ${statusRes.data.data.detected_template}. Generating foundation...`;
196
+ }
197
+ } else {
198
+ spinner.text = 'Force mode: Re-generating foundation...';
199
+ }
200
+
201
+ // Step 2: Trigger Genesis
202
+ const response = await axios.post<GenesisTriggerResponse>(
203
+ `${apiUrl}/api/v1/genesis`,
204
+ { project_id: projectId, force },
205
+ {
206
+ headers: { Authorization: `Bearer ${apiKey}` },
207
+ timeout: 60000 // AI enrichment can take time
208
+ }
209
+ );
210
+
211
+ spinner.stop();
212
+
213
+ if (!response.data.success) {
214
+ // Handle specific error cases
215
+ if ((response as any).status === 409) {
216
+ console.log(chalk.yellow('⚠️ Genesis already initialized. Use --force to re-run.'));
217
+ return true;
218
+ }
219
+ if ((response as any).status === 422) {
220
+ console.log('');
221
+ console.log(chalk.yellow('⚠️ Cannot initialize Genesis yet.'));
222
+ console.log(chalk.dim(' Complete onboarding with Frank first to define your tech stack.'));
223
+ console.log(chalk.dim(' Then run: ') + chalk.white('rigstate genesis'));
224
+ console.log('');
225
+ return false;
226
+ }
227
+ console.error(chalk.red(`❌ Genesis failed: ${response.data.error}`));
228
+ return false;
229
+ }
230
+
231
+ const { data } = response.data;
232
+
233
+ // ── Success Output ────────────────────────────────────────────────────
234
+ console.log(chalk.bold.green('✅ GENESIS COMPLETE'));
235
+ console.log(chalk.dim('────────────────────────────────────────'));
236
+ console.log(`${chalk.bold('Project:')} ${chalk.cyan(data.project_name)}`);
237
+ console.log(`${chalk.bold('Stack:')} ${chalk.magenta(data.template)}`);
238
+ console.log(`${chalk.bold('Created:')} ${chalk.white(data.steps_created)} foundation steps`);
239
+
240
+ if (data.existing_steps_shifted > 0) {
241
+ console.log(`${chalk.bold('Shifted:')} ${chalk.dim(`${data.existing_steps_shifted} existing steps moved down`)}`);
242
+ }
243
+
244
+ console.log('');
245
+ console.log(chalk.bold('📋 Foundation Steps:'));
246
+ data.steps.forEach(step => {
247
+ console.log(` ${step.icon} ${chalk.bold(`T-${step.step_number}`)}: ${step.title}`);
248
+ if (step.verification_path) {
249
+ console.log(` ${chalk.dim(`Verify: ${step.verification_path}`)}`);
250
+ }
251
+ });
252
+
253
+ console.log('');
254
+ console.log(chalk.bold.yellow('⚡ NEXT MOVE:'));
255
+ if (data.steps.length > 0) {
256
+ const firstStep = data.steps[0];
257
+ console.log(` ${chalk.white(`> rigstate work start ${firstStep.id}`)} ${chalk.dim(`(Start: ${firstStep.title})`)}`);
258
+ }
259
+ console.log(chalk.dim('────────────────────────────────────────'));
260
+ console.log('');
261
+
262
+ // ── Persist genesis status to local manifest (enables offline checks) ──
263
+ try {
264
+ const { saveManifest } = await import('../utils/manifest.js');
265
+ await saveManifest({
266
+ genesis_complete: true,
267
+ genesis_template: data.template,
268
+ genesis_stack_key: data.stack_key,
269
+ genesis_initialized_at: new Date().toISOString()
270
+ });
271
+ } catch {
272
+ // Non-critical: local cache write failure doesn't break the flow
273
+ }
274
+
275
+ return true;
276
+
277
+
278
+ } catch (err: any) {
279
+ spinner.stop();
280
+
281
+ // Handle axios error responses
282
+ if (err.response?.status === 409) {
283
+ console.log(chalk.green('✅ Genesis already complete.'));
284
+ console.log(chalk.dim(' Use --force to re-initialize.'));
285
+ return true;
286
+ }
287
+
288
+ if (err.response?.status === 422) {
289
+ console.log('');
290
+ console.log(chalk.yellow('⚠️ Genesis pending: Onboarding not complete.'));
291
+ console.log(chalk.dim(' Finish the Frank conversation to define your tech stack.'));
292
+ console.log(chalk.dim(' Then run: ') + chalk.white('rigstate genesis'));
293
+ console.log('');
294
+ return false;
295
+ }
296
+
297
+ if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') {
298
+ console.log(chalk.dim(' (Genesis skipped: API unreachable)'));
299
+ return false;
300
+ }
301
+
302
+ console.error(chalk.red(`❌ Genesis error: ${err.response?.data?.error || err.message}`));
303
+ return false;
304
+ }
305
+ }
@@ -181,13 +181,12 @@ export function createInitCommand() {
181
181
  setProjectId(projectId);
182
182
 
183
183
  // Write local manifest
184
- const manifestPath = path.join(process.cwd(), '.rigstate');
185
- const manifestContent = {
184
+ const { saveManifest } = await import('../utils/manifest.js');
185
+ await saveManifest({
186
186
  project_id: projectId,
187
- last_linked: new Date().toISOString(),
187
+ linked_at: new Date().toISOString(),
188
188
  api_url: apiUrl
189
- };
190
- await fs.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), 'utf-8');
189
+ });
191
190
 
192
191
  // Initialize git if needed
193
192
  try {
@@ -74,33 +74,23 @@ export function createLinkCommand() {
74
74
  }
75
75
  }
76
76
 
77
- const manifestPath = path.join(process.cwd(), '.rigstate');
78
-
79
- const content: any = {
80
- project_id: projectId,
81
- linked_at: new Date().toISOString()
82
- };
83
-
84
- // Only store api_url locally if it's NOT the production default
85
- const currentUrl = getApiUrl();
86
- if (currentUrl !== 'https://app.rigstate.com') {
87
- content.api_url = currentUrl;
88
- }
89
-
77
+ const cwd = process.cwd();
90
78
  try {
91
- // Ensure .rigstate dir exists
92
- await fs.mkdir(path.dirname(manifestPath), { recursive: true });
79
+ const { saveManifest } = await import('../utils/manifest.js');
80
+ const targetFile = await saveManifest({
81
+ project_id: projectId,
82
+ linked_at: new Date().toISOString(),
83
+ api_url: getApiUrl() !== 'https://app.rigstate.com' ? getApiUrl() : undefined
84
+ });
93
85
 
94
- await fs.writeFile(manifestPath, JSON.stringify(content, null, 2), 'utf-8');
95
86
  console.log(chalk.green(`✔ Linked to project ID: ${projectId}`));
96
- console.log(chalk.dim(`Created local context manifest at .rigstate`));
87
+ console.log(chalk.dim(`Created local identity manifest at ${path.relative(cwd, targetFile)}`));
97
88
 
98
89
  // === SMART AUTOMATION ===
99
90
  console.log('');
100
91
  console.log(chalk.bold('🤖 Rigstate Automation Detected'));
101
92
  console.log('');
102
93
 
103
- const { getApiKey: _getApiKey, getApiUrl: _getApiUrl } = await import('../utils/config.js');
104
94
  const apiKey = getApiKey();
105
95
  const apiUrl = getApiUrl();
106
96
 
@@ -120,12 +110,28 @@ export function createLinkCommand() {
120
110
  await installHooks(process.cwd());
121
111
  await hardenGitIgnore(process.cwd());
122
112
 
113
+ // 4. Genesis Protocol (Smart Detection)
114
+ console.log(chalk.blue('🏗️ Checking Genesis status...'));
115
+ const { checkGenesisStatus, triggerGenesis } = await import('./genesis.js');
116
+ const genesisStatus = await checkGenesisStatus(projectId, apiKey, apiUrl);
117
+
118
+ if (!genesisStatus.complete) {
119
+ // Try to trigger automatically — will fail gracefully if spec not ready
120
+ const triggered = await triggerGenesis(projectId, apiKey, apiUrl, false);
121
+ if (!triggered) {
122
+ console.log(chalk.dim(' 💡 Run "rigstate genesis" after completing onboarding with Frank.'));
123
+ }
124
+ } else {
125
+ console.log(chalk.green(` ✔ Genesis complete (${genesisStatus.stepCount} foundation steps ready)`));
126
+ }
127
+
123
128
  console.log('');
124
129
  console.log(chalk.bold.green('🚀 Link Complete! Your environment is ready.'));
125
130
 
126
- // 4. Tactical Suggestion
131
+ // 5. Tactical Suggestion
127
132
  const { suggestNextMove } = await import('./suggest.js');
128
133
  await suggestNextMove(projectId, apiKey, apiUrl);
134
+
129
135
  } else {
130
136
  console.log('');
131
137
  console.log(chalk.bold.green('🚀 Link Complete!'));
@@ -43,9 +43,9 @@ export async function executePlan(taskId?: string) {
43
43
  const tasks: any[] = response.data.data.roadmap || [];
44
44
 
45
45
  const choices = tasks
46
- .filter(t => ['ACTIVE', 'IN_PROGRESS', 'PENDING'].includes(t.status))
46
+ .filter(t => ['ACTIVE', 'IN_PROGRESS', 'PENDING', 'LOCKED'].includes(t.status))
47
47
  .map(t => ({
48
- name: `T-${t.step_number}: ${t.title}`,
48
+ name: `${t.status === 'LOCKED' ? '🔒 ' : ''}T-${t.step_number}: ${t.title}${t.origin_id === 'GENESIS' ? chalk.dim(' [Foundation]') : ''}`,
49
49
  value: t
50
50
  }));
51
51
 
@@ -137,15 +137,32 @@ ${taskDescription}
137
137
  // 4. Update Status (Optional - maybe set to IN_PROGRESS?)
138
138
  // For now, let's keep it pure planning.
139
139
 
140
+ // 4. Trigger Bridge Task (Autonomous Bridge)
141
+ try {
142
+ spinner.start('📡 Signaling Frank to start drafting...');
143
+ await axios.post(`${apiUrl}/api/v1/agent/bridge`, {
144
+ project_id: projectId,
145
+ task_id: realId,
146
+ status: 'APPROVED',
147
+ proposal: `draft_plan:${taskId}`,
148
+ summary: `Requesting implementation plan for ${taskTitle}`
149
+ }, {
150
+ headers: { 'Authorization': `Bearer ${apiKey}` }
151
+ });
152
+ spinner.succeed('Signal sent to Agent Bridge.');
153
+ } catch (e) {
154
+ spinner.info(chalk.dim('Agent Bridge signal skipped (non-critical).'));
155
+ }
156
+
140
157
  console.log('');
141
158
  console.log(chalk.bold.blue('🚀 Planning Mode Activated'));
142
159
  console.log(chalk.dim('────────────────────────────────────────'));
143
160
  console.log(`1. Context loaded into: ${chalk.bold('.rigstate/CURRENT_CONTEXT.md')}`);
144
161
  console.log(`2. Plan template ready: ${chalk.bold('IMPLEMENTATION_PLAN.md')}`);
145
162
  console.log('');
146
- console.log(chalk.yellow('👉 NEXT STEP:'));
147
- console.log(` Open ${chalk.bold('IMPLEMENTATION_PLAN.md')} in your IDE.`);
148
- console.log(` Tell Frank: ${chalk.italic('"Read the context and draft the plan."')}`);
163
+ console.log(chalk.green(' FRANK IS ON IT!'));
164
+ console.log(chalk.dim(' He has received the bridge signal and will begin drafting shortly.'));
165
+ console.log(chalk.dim(' No further manual steps required once he wakes up.'));
149
166
  console.log('');
150
167
 
151
168
  } catch (e: any) {
@@ -30,12 +30,9 @@ export function createSyncCommand() {
30
30
 
31
31
  // Check local .rigstate manifest
32
32
  if (!projectId) {
33
- try {
34
- const manifestPath = path.join(process.cwd(), '.rigstate');
35
- const manifestContent = await fs.readFile(manifestPath, 'utf-8');
36
- const manifest = JSON.parse(manifestContent);
37
- if (manifest.project_id) projectId = manifest.project_id;
38
- } catch (e) { }
33
+ const { loadManifest } = await import('../utils/manifest.js');
34
+ const manifest = await loadManifest();
35
+ if (manifest?.project_id) projectId = manifest.project_id;
39
36
  }
40
37
 
41
38
  // Check global config
@@ -79,14 +76,12 @@ export function createSyncCommand() {
79
76
 
80
77
  // 4b. Write Context Manifest (.rigstate) - CONTEXT GUARD
81
78
  try {
82
- const manifestPath = path.join(process.cwd(), '.rigstate');
83
- const manifestContent = {
79
+ const { saveManifest } = await import('../utils/manifest.js');
80
+ await saveManifest({
84
81
  project_id: projectId,
85
- project_name: project,
86
- last_synced: timestamp,
82
+ linked_at: timestamp, // Using timestamp as linked_at for consistency
87
83
  api_url: apiUrl
88
- };
89
- await fs.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), 'utf-8');
84
+ });
90
85
  } catch (e) {
91
86
  // Fail silently
92
87
  }
@@ -42,13 +42,9 @@ export function createWatchCommand() {
42
42
 
43
43
  projectId = getProjectId();
44
44
  if (!projectId) {
45
- // Try to read from local manifest
46
- try {
47
- const manifestPath = path.join(process.cwd(), '.rigstate');
48
- const content = await fs.readFile(manifestPath, 'utf-8');
49
- const manifest = JSON.parse(content);
50
- projectId = manifest.project_id;
51
- } catch (e) { }
45
+ const { loadManifest } = await import('../utils/manifest.js');
46
+ const manifest = await loadManifest();
47
+ if (manifest?.project_id) projectId = manifest.project_id;
52
48
  }
53
49
 
54
50
  if (!projectId) {
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ import { createReleaseCommand } from './commands/release.js';
23
23
  import { createRoadmapCommand } from './commands/roadmap.js';
24
24
  import { createCouncilCommand } from './commands/council.js';
25
25
  import { createPlanCommand } from './commands/plan.js';
26
+ import { createGenesisCommand } from './commands/genesis.js';
26
27
  import { checkVersion } from './utils/version.js';
27
28
  import dotenv from 'dotenv';
28
29
 
@@ -63,6 +64,7 @@ program.addCommand(createReleaseCommand());
63
64
  program.addCommand(createRoadmapCommand());
64
65
  program.addCommand(createCouncilCommand());
65
66
  program.addCommand(createPlanCommand());
67
+ program.addCommand(createGenesisCommand());
66
68
 
67
69
  program.hook('preAction', async () => {
68
70
  await checkVersion();
@@ -79,6 +81,12 @@ program.on('--help', () => {
79
81
  console.log(chalk.cyan(' $ rigstate scan'));
80
82
  console.log(chalk.dim(' Scan the current directory'));
81
83
  console.log('');
84
+ console.log(chalk.cyan(' $ rigstate genesis'));
85
+ console.log(chalk.dim(' Initialize project foundation (auto-detects stack)'));
86
+ console.log('');
87
+ console.log(chalk.cyan(' $ rigstate genesis --status'));
88
+ console.log(chalk.dim(' Check genesis status without triggering'));
89
+ console.log('');
82
90
  console.log(chalk.cyan(' $ rigstate scan ./src --project abc123'));
83
91
  console.log(chalk.dim(' Scan a specific directory with project ID'));
84
92
  console.log('');