@rigstate/cli 0.7.35 → 0.7.37
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/index.cjs +1053 -6244
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4007 -9225
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/commands/genesis.ts +305 -0
- package/src/commands/link.ts +17 -1
- package/src/commands/plan.ts +2 -2
- package/src/commands/roadmap.ts +15 -9
- package/src/index.ts +8 -0
- package/src/utils/manifest.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigstate/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.37",
|
|
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
|
+
}
|
|
@@ -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
|
+
}
|
package/src/commands/link.ts
CHANGED
|
@@ -110,12 +110,28 @@ export function createLinkCommand() {
|
|
|
110
110
|
await installHooks(process.cwd());
|
|
111
111
|
await hardenGitIgnore(process.cwd());
|
|
112
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
|
+
|
|
113
128
|
console.log('');
|
|
114
129
|
console.log(chalk.bold.green('🚀 Link Complete! Your environment is ready.'));
|
|
115
130
|
|
|
116
|
-
//
|
|
131
|
+
// 5. Tactical Suggestion
|
|
117
132
|
const { suggestNextMove } = await import('./suggest.js');
|
|
118
133
|
await suggestNextMove(projectId, apiKey, apiUrl);
|
|
134
|
+
|
|
119
135
|
} else {
|
|
120
136
|
console.log('');
|
|
121
137
|
console.log(chalk.bold.green('🚀 Link Complete!'));
|
package/src/commands/plan.ts
CHANGED
|
@@ -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:
|
|
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
|
|
package/src/commands/roadmap.ts
CHANGED
|
@@ -4,6 +4,7 @@ import chalk from 'chalk';
|
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import axios from 'axios';
|
|
6
6
|
import { getApiKey, getApiUrl, getProjectId } from '../utils/config.js';
|
|
7
|
+
import { RoadmapChunk, ROADMAP_STATUS } from '@rigstate/shared';
|
|
7
8
|
|
|
8
9
|
export function createRoadmapCommand(): Command {
|
|
9
10
|
return new Command('roadmap')
|
|
@@ -30,7 +31,8 @@ export function createRoadmapCommand(): Command {
|
|
|
30
31
|
throw new Error(response.data.error || 'Failed to fetch roadmap');
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
const tasks: RoadmapChunk[] = response.data.data.roadmap || [];
|
|
34
36
|
spinner.stop();
|
|
35
37
|
|
|
36
38
|
if (tasks.length === 0) {
|
|
@@ -41,16 +43,20 @@ export function createRoadmapCommand(): Command {
|
|
|
41
43
|
console.log('\n' + chalk.bold.underline('🛰️ TACTICAL OVERVIEW: PROJECT ROADMAP'));
|
|
42
44
|
console.log(chalk.dim('──────────────────────────────────────────────'));
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
46
|
+
// Initialize columns based on shared status definitions (or subset used here)
|
|
47
|
+
const columns: Record<string, RoadmapChunk[]> = {
|
|
48
|
+
'IN_PROGRESS': [],
|
|
49
|
+
'ACTIVE': [],
|
|
50
|
+
'LOCKED': [],
|
|
51
|
+
'PENDING': [],
|
|
52
|
+
'TODO': [],
|
|
53
|
+
'COMPLETED': []
|
|
49
54
|
};
|
|
50
55
|
|
|
51
|
-
tasks.forEach((t
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
tasks.forEach((t) => {
|
|
57
|
+
const status = t.status as string; // until API returns exact enum
|
|
58
|
+
if (columns[status]) {
|
|
59
|
+
columns[status].push(t);
|
|
54
60
|
}
|
|
55
61
|
});
|
|
56
62
|
|
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('');
|
package/src/utils/manifest.ts
CHANGED
|
@@ -7,8 +7,14 @@ export interface RigstateManifest {
|
|
|
7
7
|
api_url?: string;
|
|
8
8
|
linked_at?: string;
|
|
9
9
|
api_key?: string;
|
|
10
|
+
// Genesis Protocol status (cached locally to avoid API calls)
|
|
11
|
+
genesis_complete?: boolean;
|
|
12
|
+
genesis_template?: string;
|
|
13
|
+
genesis_stack_key?: string;
|
|
14
|
+
genesis_initialized_at?: string;
|
|
10
15
|
}
|
|
11
16
|
|
|
17
|
+
|
|
12
18
|
export async function loadManifest(): Promise<RigstateManifest | null> {
|
|
13
19
|
const cwd = process.cwd();
|
|
14
20
|
const manifestPaths = [
|