@rigstate/cli 0.7.32 → 0.7.35
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 +831 -724
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +870 -765
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/env.ts +3 -6
- package/src/commands/focus.ts +3 -6
- package/src/commands/init.ts +4 -5
- package/src/commands/link.ts +8 -18
- package/src/commands/plan.ts +20 -3
- package/src/commands/sync-rules.ts +3 -4
- package/src/commands/sync.ts +7 -12
- package/src/commands/watch.ts +3 -7
- package/src/utils/config.ts +79 -4
- package/src/utils/manifest.ts +56 -5
- package/src/utils/version.ts +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigstate/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.35",
|
|
4
4
|
"description": "Rigstate CLI - Code audit, sync and supervision tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -50,4 +50,4 @@
|
|
|
50
50
|
],
|
|
51
51
|
"author": "Rigstate",
|
|
52
52
|
"license": "MIT"
|
|
53
|
-
}
|
|
53
|
+
}
|
package/src/commands/env.ts
CHANGED
|
@@ -141,12 +141,9 @@ export function createEnvPullCommand() {
|
|
|
141
141
|
projectId = getProjectId();
|
|
142
142
|
|
|
143
143
|
if (!projectId) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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) {
|
package/src/commands/focus.ts
CHANGED
|
@@ -30,12 +30,9 @@ export function createFocusCommand() {
|
|
|
30
30
|
|
|
31
31
|
projectId = getProjectId();
|
|
32
32
|
if (!projectId) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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) {
|
package/src/commands/init.ts
CHANGED
|
@@ -181,13 +181,12 @@ export function createInitCommand() {
|
|
|
181
181
|
setProjectId(projectId);
|
|
182
182
|
|
|
183
183
|
// Write local manifest
|
|
184
|
-
const
|
|
185
|
-
|
|
184
|
+
const { saveManifest } = await import('../utils/manifest.js');
|
|
185
|
+
await saveManifest({
|
|
186
186
|
project_id: projectId,
|
|
187
|
-
|
|
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 {
|
package/src/commands/link.ts
CHANGED
|
@@ -74,33 +74,23 @@ export function createLinkCommand() {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
const
|
|
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
|
-
|
|
92
|
-
await
|
|
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
|
|
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
|
|
package/src/commands/plan.ts
CHANGED
|
@@ -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.
|
|
147
|
-
console.log(
|
|
148
|
-
console.log(
|
|
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) {
|
|
@@ -3,8 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import { getApiKey, getApiUrl } from '../utils/config.js';
|
|
5
5
|
import axios from 'axios';
|
|
6
|
-
import {
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
6
|
+
import { CLI_VERSION } from '../utils/version.js';
|
|
8
7
|
|
|
9
8
|
interface SyncResult {
|
|
10
9
|
projectId: string;
|
|
@@ -14,7 +13,7 @@ interface SyncResult {
|
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
// Core Logic (Exported for re-use)
|
|
17
|
-
export async function syncProjectRules(projectId: string, apiKey: string, apiUrl: string, dryRun = false): Promise<boolean> {
|
|
16
|
+
export async function syncProjectRules(projectId: string, apiKey: string, apiUrl: string, dryRun = false, version: string = CLI_VERSION): Promise<boolean> {
|
|
18
17
|
const spinner = ora('🛡️ Frank Protocol: Initializing retroactive sync...').start();
|
|
19
18
|
let success = true;
|
|
20
19
|
|
|
@@ -87,7 +86,7 @@ export async function syncProjectRules(projectId: string, apiKey: string, apiUrl
|
|
|
87
86
|
|
|
88
87
|
const governanceBlock = `${START_MARKER}
|
|
89
88
|
# 🛡️ Rigstate Governance (Do not edit this block manually)
|
|
90
|
-
# The following rules are enforced by the Rigstate Daemon (v${
|
|
89
|
+
# The following rules are enforced by the Rigstate Daemon (v${version}).
|
|
91
90
|
# Failure to adhere to these rules will be flagged during the 'work' cycle.
|
|
92
91
|
|
|
93
92
|
# YOU MUST ADHERE TO THESE PROACTIVE RULES:
|
package/src/commands/sync.ts
CHANGED
|
@@ -30,12 +30,9 @@ export function createSyncCommand() {
|
|
|
30
30
|
|
|
31
31
|
// Check local .rigstate manifest
|
|
32
32
|
if (!projectId) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
83
|
-
|
|
79
|
+
const { saveManifest } = await import('../utils/manifest.js');
|
|
80
|
+
await saveManifest({
|
|
84
81
|
project_id: projectId,
|
|
85
|
-
|
|
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
|
}
|
package/src/commands/watch.ts
CHANGED
|
@@ -42,13 +42,9 @@ export function createWatchCommand() {
|
|
|
42
42
|
|
|
43
43
|
projectId = getProjectId();
|
|
44
44
|
if (!projectId) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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/utils/config.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
4
6
|
|
|
5
7
|
interface RigstateConfig {
|
|
6
8
|
apiKey?: string;
|
|
@@ -20,6 +22,29 @@ const config = new Conf<RigstateConfig>({
|
|
|
20
22
|
* @throws {Error} If no API key is found (user not logged in)
|
|
21
23
|
*/
|
|
22
24
|
export function getApiKey(): string {
|
|
25
|
+
// 1. Check local manifest first (Folder Affinity)
|
|
26
|
+
try {
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
const manifestPaths = [
|
|
29
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
30
|
+
path.join(cwd, '.rigstate')
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
for (const manifestPath of manifestPaths) {
|
|
34
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
35
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
36
|
+
const manifest = JSON.parse(content);
|
|
37
|
+
if (manifest.api_key) return manifest.api_key;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (e) { /* Fallback */ }
|
|
41
|
+
|
|
42
|
+
// 2. Check environment variable
|
|
43
|
+
if (process.env.RIGSTATE_API_KEY) {
|
|
44
|
+
return process.env.RIGSTATE_API_KEY;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Fall back to global config
|
|
23
48
|
const apiKey = config.get('apiKey');
|
|
24
49
|
if (!apiKey) {
|
|
25
50
|
throw new Error(
|
|
@@ -40,7 +65,40 @@ export function setApiKey(key: string): void {
|
|
|
40
65
|
* Get the default project ID (if set)
|
|
41
66
|
*/
|
|
42
67
|
export function getProjectId(): string | undefined {
|
|
43
|
-
|
|
68
|
+
// 1. Check local manifest first (Folder Affinity)
|
|
69
|
+
try {
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const manifestPaths = [
|
|
72
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
73
|
+
path.join(cwd, '.rigstate')
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
for (const manifestPath of manifestPaths) {
|
|
77
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
78
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
79
|
+
const manifest = JSON.parse(content);
|
|
80
|
+
if (manifest.project_id) {
|
|
81
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${manifest.project_id.substring(0, 8)}... (from ${path.basename(manifestPath)})`));
|
|
82
|
+
return manifest.project_id;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (e: any) {
|
|
87
|
+
console.log(chalk.red(` [Error] Failed to read context: ${e.message}`));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 2. Check environment variable
|
|
91
|
+
if (process.env.RIGSTATE_PROJECT_ID) {
|
|
92
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${process.env.RIGSTATE_PROJECT_ID.substring(0, 8)}... (from ENV)`));
|
|
93
|
+
return process.env.RIGSTATE_PROJECT_ID;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 3. Fall back to global config
|
|
97
|
+
const globalId = config.get('projectId');
|
|
98
|
+
if (globalId) {
|
|
99
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${globalId.substring(0, 8)}... (from GLOBAL CONFIG)`));
|
|
100
|
+
}
|
|
101
|
+
return globalId;
|
|
44
102
|
}
|
|
45
103
|
|
|
46
104
|
/**
|
|
@@ -55,16 +113,33 @@ export function setProjectId(projectId: string): void {
|
|
|
55
113
|
* Priority: Environment variable > Stored config > Production default
|
|
56
114
|
*/
|
|
57
115
|
export function getApiUrl(): string {
|
|
58
|
-
// 1. Check
|
|
116
|
+
// 1. Check local manifest first
|
|
117
|
+
try {
|
|
118
|
+
const cwd = process.cwd();
|
|
119
|
+
const manifestPaths = [
|
|
120
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
121
|
+
path.join(cwd, '.rigstate')
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
for (const manifestPath of manifestPaths) {
|
|
125
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
126
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
127
|
+
const manifest = JSON.parse(content);
|
|
128
|
+
if (manifest.api_url) return manifest.api_url;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} catch (e) { /* Fallback */ }
|
|
132
|
+
|
|
133
|
+
// 2. Check environment variable next
|
|
59
134
|
if (process.env.RIGSTATE_API_URL) {
|
|
60
135
|
return process.env.RIGSTATE_API_URL;
|
|
61
136
|
}
|
|
62
|
-
//
|
|
137
|
+
// 3. Check stored config
|
|
63
138
|
const storedUrl = config.get('apiUrl');
|
|
64
139
|
if (storedUrl) {
|
|
65
140
|
return storedUrl;
|
|
66
141
|
}
|
|
67
|
-
//
|
|
142
|
+
// 4. Default to production
|
|
68
143
|
return 'https://app.rigstate.com';
|
|
69
144
|
}
|
|
70
145
|
|
package/src/utils/manifest.ts
CHANGED
|
@@ -1,18 +1,69 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
+
import fsSync from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
|
|
4
5
|
export interface RigstateManifest {
|
|
5
6
|
project_id: string;
|
|
6
7
|
api_url?: string;
|
|
7
8
|
linked_at?: string;
|
|
9
|
+
api_key?: string;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export async function loadManifest(): Promise<RigstateManifest | null> {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const manifestPaths = [
|
|
15
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
16
|
+
path.join(cwd, '.rigstate')
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
for (const p of manifestPaths) {
|
|
20
|
+
try {
|
|
21
|
+
if (fsSync.existsSync(p) && fsSync.statSync(p).isFile()) {
|
|
22
|
+
const content = await fs.readFile(p, 'utf-8');
|
|
23
|
+
const data = JSON.parse(content);
|
|
24
|
+
|
|
25
|
+
// Handle both flat manifest and identity.json schema
|
|
26
|
+
return {
|
|
27
|
+
project_id: data.project?.id || data.project_id,
|
|
28
|
+
api_url: data.api_url,
|
|
29
|
+
linked_at: data.linked_at || data.project?.created_at,
|
|
30
|
+
api_key: data.api_key
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Saves project context to the local manifest.
|
|
42
|
+
* Prioritizes .rigstate/identity.json if the directory exists.
|
|
43
|
+
*/
|
|
44
|
+
export async function saveManifest(data: Partial<RigstateManifest>): Promise<string> {
|
|
45
|
+
const cwd = process.cwd();
|
|
46
|
+
const rigstatePath = path.join(cwd, '.rigstate');
|
|
47
|
+
let targetFile = rigstatePath;
|
|
48
|
+
|
|
11
49
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
50
|
+
const stats = await fs.stat(rigstatePath);
|
|
51
|
+
if (stats.isDirectory()) {
|
|
52
|
+
targetFile = path.join(rigstatePath, 'identity.json');
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
// Doesn't exist, will be created as file/dir below
|
|
17
56
|
}
|
|
57
|
+
|
|
58
|
+
// Load existing to merge
|
|
59
|
+
const existing = await loadManifest() || {} as RigstateManifest;
|
|
60
|
+
const merged = { ...existing, ...data };
|
|
61
|
+
|
|
62
|
+
// If we need to create a directory for identity.json
|
|
63
|
+
if (targetFile.endsWith('identity.json')) {
|
|
64
|
+
await fs.mkdir(rigstatePath, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await fs.writeFile(targetFile, JSON.stringify(merged, null, 2), 'utf-8');
|
|
68
|
+
return targetFile;
|
|
18
69
|
}
|
package/src/utils/version.ts
CHANGED