@rigstate/cli 0.6.2 → 0.6.7
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 +1158 -980
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1157 -971
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/daemon.ts +129 -0
- package/src/commands/env.ts +116 -112
- package/src/commands/link.ts +72 -1
- package/src/commands/login.ts +46 -27
- package/src/commands/sync-rules.ts +77 -153
- package/src/daemon/file-watcher.ts +37 -14
- package/src/index.ts +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
#!/usr/bin/env node
|
|
3
2
|
"use strict";
|
|
4
3
|
var __create = Object.create;
|
|
5
4
|
var __defProp = Object.defineProperty;
|
|
@@ -42,6 +41,17 @@ var init_cjs_shims = __esm({
|
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
// src/utils/config.ts
|
|
44
|
+
var config_exports = {};
|
|
45
|
+
__export(config_exports, {
|
|
46
|
+
clearConfig: () => clearConfig,
|
|
47
|
+
config: () => config,
|
|
48
|
+
getApiKey: () => getApiKey,
|
|
49
|
+
getApiUrl: () => getApiUrl,
|
|
50
|
+
getProjectId: () => getProjectId,
|
|
51
|
+
setApiKey: () => setApiKey,
|
|
52
|
+
setApiUrl: () => setApiUrl,
|
|
53
|
+
setProjectId: () => setProjectId
|
|
54
|
+
});
|
|
45
55
|
function getApiKey() {
|
|
46
56
|
const apiKey = config.get("apiKey");
|
|
47
57
|
if (!apiKey) {
|
|
@@ -70,6 +80,12 @@ function getApiUrl() {
|
|
|
70
80
|
}
|
|
71
81
|
return "https://app.rigstate.com";
|
|
72
82
|
}
|
|
83
|
+
function setApiUrl(url) {
|
|
84
|
+
config.set("apiUrl", url);
|
|
85
|
+
}
|
|
86
|
+
function clearConfig() {
|
|
87
|
+
config.clear();
|
|
88
|
+
}
|
|
73
89
|
var import_conf, config;
|
|
74
90
|
var init_config = __esm({
|
|
75
91
|
"src/utils/config.ts"() {
|
|
@@ -85,6 +101,362 @@ var init_config = __esm({
|
|
|
85
101
|
}
|
|
86
102
|
});
|
|
87
103
|
|
|
104
|
+
// src/commands/env.ts
|
|
105
|
+
var env_exports = {};
|
|
106
|
+
__export(env_exports, {
|
|
107
|
+
createEnvPullCommand: () => createEnvPullCommand,
|
|
108
|
+
syncEnv: () => syncEnv
|
|
109
|
+
});
|
|
110
|
+
async function syncEnv(projectId, apiKey, apiUrl, silent = false) {
|
|
111
|
+
if (!silent) {
|
|
112
|
+
console.log("");
|
|
113
|
+
console.log(import_chalk2.default.bold.yellow("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
114
|
+
console.log(import_chalk2.default.bold.yellow("\u2551") + import_chalk2.default.bold.white(" \u{1F6E1}\uFE0F RIGSTATE SOVEREIGN VAULT SYNC \u{1F6E1}\uFE0F ") + import_chalk2.default.bold.yellow("\u2551"));
|
|
115
|
+
console.log(import_chalk2.default.bold.yellow("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
|
|
116
|
+
console.log("");
|
|
117
|
+
}
|
|
118
|
+
const spinner = (0, import_ora.default)("Fetching secrets from Vault...").start();
|
|
119
|
+
try {
|
|
120
|
+
const response = await import_axios.default.post(`${apiUrl}/api/v1/vault/sync`, {
|
|
121
|
+
project_id: projectId
|
|
122
|
+
}, {
|
|
123
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
124
|
+
});
|
|
125
|
+
if (!response.data.success) {
|
|
126
|
+
throw new Error(response.data.error || "Failed to fetch secrets");
|
|
127
|
+
}
|
|
128
|
+
const vaultContent = response.data.data.content || "";
|
|
129
|
+
const secretCount = response.data.data.count || 0;
|
|
130
|
+
if (secretCount === 0) {
|
|
131
|
+
spinner.info("No secrets found in Vault for this project.");
|
|
132
|
+
if (!silent) console.log(import_chalk2.default.dim(" Add secrets via the Rigstate web interface."));
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
spinner.succeed(`Retrieved ${import_chalk2.default.bold(secretCount)} secret(s)`);
|
|
136
|
+
const envFile = import_path.default.resolve(process.cwd(), ".env.local");
|
|
137
|
+
let existingContent = "";
|
|
138
|
+
let existingKeys = /* @__PURE__ */ new Set();
|
|
139
|
+
try {
|
|
140
|
+
existingContent = await import_promises.default.readFile(envFile, "utf-8");
|
|
141
|
+
existingContent.split("\n").forEach((line) => {
|
|
142
|
+
const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
|
|
143
|
+
if (match) existingKeys.add(match[1]);
|
|
144
|
+
});
|
|
145
|
+
} catch (e) {
|
|
146
|
+
}
|
|
147
|
+
const vaultKeys = /* @__PURE__ */ new Set();
|
|
148
|
+
vaultContent.split("\n").forEach((line) => {
|
|
149
|
+
const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
|
|
150
|
+
if (match) vaultKeys.add(match[1]);
|
|
151
|
+
});
|
|
152
|
+
let newCount = 0;
|
|
153
|
+
let updatedCount = 0;
|
|
154
|
+
vaultKeys.forEach((key) => {
|
|
155
|
+
if (!existingKeys.has(key)) {
|
|
156
|
+
newCount++;
|
|
157
|
+
} else {
|
|
158
|
+
updatedCount++;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
const unchangedCount = existingKeys.size - updatedCount;
|
|
162
|
+
spinner.start("Writing .env.local...");
|
|
163
|
+
const header = [
|
|
164
|
+
"# ==========================================",
|
|
165
|
+
"# RIGSTATE SOVEREIGN FOUNDATION",
|
|
166
|
+
"# Authenticated Environment Configuration",
|
|
167
|
+
`# Synced at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
168
|
+
`# Project: ${projectId}`,
|
|
169
|
+
"# ==========================================",
|
|
170
|
+
""
|
|
171
|
+
].join("\n");
|
|
172
|
+
await import_promises.default.writeFile(envFile, header + vaultContent + "\n");
|
|
173
|
+
spinner.succeed("Written to .env.local");
|
|
174
|
+
if (!silent) {
|
|
175
|
+
console.log("");
|
|
176
|
+
console.log(import_chalk2.default.bold.green("\u2705 Environment synchronized successfully"));
|
|
177
|
+
console.log("");
|
|
178
|
+
console.log(import_chalk2.default.dim(" Summary:"));
|
|
179
|
+
console.log(import_chalk2.default.green(` + ${newCount} new`));
|
|
180
|
+
console.log(import_chalk2.default.yellow(` ~ ${updatedCount} updated`));
|
|
181
|
+
console.log(import_chalk2.default.dim(` = ${unchangedCount} unchanged`));
|
|
182
|
+
console.log("");
|
|
183
|
+
console.log(import_chalk2.default.bold.yellow("\u26A0\uFE0F Security Reminder:"));
|
|
184
|
+
console.log(import_chalk2.default.dim(" - Never commit .env.local to version control."));
|
|
185
|
+
console.log(import_chalk2.default.dim(" - Ensure .gitignore includes .env.local"));
|
|
186
|
+
console.log("");
|
|
187
|
+
}
|
|
188
|
+
return true;
|
|
189
|
+
} catch (e) {
|
|
190
|
+
spinner.fail(import_chalk2.default.red(`Failed to fetch secrets: ${e.message}`));
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function createEnvPullCommand() {
|
|
195
|
+
const envPull = new import_commander2.Command("env");
|
|
196
|
+
envPull.command("pull").description("Pull environment variables from project vault").action(async () => {
|
|
197
|
+
let apiKey;
|
|
198
|
+
let projectId;
|
|
199
|
+
try {
|
|
200
|
+
apiKey = getApiKey();
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.error(import_chalk2.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
projectId = getProjectId();
|
|
206
|
+
if (!projectId) {
|
|
207
|
+
try {
|
|
208
|
+
const manifestPath = import_path.default.join(process.cwd(), ".rigstate");
|
|
209
|
+
const content = await import_promises.default.readFile(manifestPath, "utf-8");
|
|
210
|
+
const manifest = JSON.parse(content);
|
|
211
|
+
projectId = manifest.project_id;
|
|
212
|
+
} catch (e) {
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!projectId) {
|
|
216
|
+
console.error(import_chalk2.default.red('No project context. Run "rigstate link" first.'));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const apiUrl = getApiUrl();
|
|
220
|
+
await syncEnv(projectId, apiKey, apiUrl);
|
|
221
|
+
});
|
|
222
|
+
return envPull;
|
|
223
|
+
}
|
|
224
|
+
var import_commander2, import_chalk2, import_ora, import_promises, import_path, import_axios;
|
|
225
|
+
var init_env = __esm({
|
|
226
|
+
"src/commands/env.ts"() {
|
|
227
|
+
"use strict";
|
|
228
|
+
init_cjs_shims();
|
|
229
|
+
import_commander2 = require("commander");
|
|
230
|
+
import_chalk2 = __toESM(require("chalk"), 1);
|
|
231
|
+
import_ora = __toESM(require("ora"), 1);
|
|
232
|
+
import_promises = __toESM(require("fs/promises"), 1);
|
|
233
|
+
import_path = __toESM(require("path"), 1);
|
|
234
|
+
init_config();
|
|
235
|
+
import_axios = __toESM(require("axios"), 1);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// src/commands/sync-rules.ts
|
|
240
|
+
var sync_rules_exports = {};
|
|
241
|
+
__export(sync_rules_exports, {
|
|
242
|
+
createSyncRulesCommand: () => createSyncRulesCommand,
|
|
243
|
+
syncProjectRules: () => syncProjectRules
|
|
244
|
+
});
|
|
245
|
+
async function syncProjectRules(projectId, apiKey, apiUrl, dryRun = false) {
|
|
246
|
+
const spinner = (0, import_ora2.default)("\u{1F6E1}\uFE0F Frank Protocol: Initializing retroactive sync...").start();
|
|
247
|
+
let success = true;
|
|
248
|
+
try {
|
|
249
|
+
spinner.text = "Fetching project info...";
|
|
250
|
+
const projectRes = await import_axios2.default.get(`${apiUrl}/api/v1/projects`, {
|
|
251
|
+
params: { project_id: projectId },
|
|
252
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
253
|
+
});
|
|
254
|
+
if (!projectRes.data.success || !projectRes.data.data.projects?.length) {
|
|
255
|
+
throw new Error("Project not found");
|
|
256
|
+
}
|
|
257
|
+
const project = projectRes.data.data.projects[0];
|
|
258
|
+
spinner.text = `Syncing rules for ${project.name}...`;
|
|
259
|
+
if (dryRun) {
|
|
260
|
+
spinner.succeed(import_chalk3.default.yellow(` [DRY-RUN] Would sync: ${project.name}`));
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
const syncResponse = await import_axios2.default.post(`${apiUrl}/api/v1/rules/sync`, {
|
|
264
|
+
project_id: project.id
|
|
265
|
+
}, {
|
|
266
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
267
|
+
});
|
|
268
|
+
if (syncResponse.data.success) {
|
|
269
|
+
if (syncResponse.data.data.github_synced) {
|
|
270
|
+
spinner.succeed(import_chalk3.default.green(` \u2705 ${project.name} [${project.id}] \u2192 GitHub synced`));
|
|
271
|
+
} else {
|
|
272
|
+
spinner.info(import_chalk3.default.blue(` \u2139\uFE0F ${project.name} [${project.id}] \u2192 Rules generated (no GitHub)`));
|
|
273
|
+
}
|
|
274
|
+
const files = syncResponse.data.data.files;
|
|
275
|
+
if (files && Array.isArray(files)) {
|
|
276
|
+
const fs23 = await import("fs/promises");
|
|
277
|
+
const path23 = await import("path");
|
|
278
|
+
for (const file of files) {
|
|
279
|
+
const filePath = path23.join(process.cwd(), file.path);
|
|
280
|
+
await fs23.mkdir(path23.dirname(filePath), { recursive: true });
|
|
281
|
+
await fs23.writeFile(filePath, file.content, "utf-8");
|
|
282
|
+
}
|
|
283
|
+
console.log(import_chalk3.default.dim(` \u{1F4BE} Wrote ${files.length} rule files to local .cursor/rules/`));
|
|
284
|
+
}
|
|
285
|
+
console.log("");
|
|
286
|
+
console.log(import_chalk3.default.cyan("\u{1F6E1}\uFE0F Frank Protocol v1.0 has been injected into the rules engine."));
|
|
287
|
+
console.log(import_chalk3.default.dim(" All new chats will now boot with mandatory governance checks."));
|
|
288
|
+
} else {
|
|
289
|
+
spinner.warn(import_chalk3.default.yellow(` \u26A0\uFE0F ${project.name} \u2192 ${syncResponse.data.error || "Unknown error"}`));
|
|
290
|
+
success = false;
|
|
291
|
+
}
|
|
292
|
+
} catch (e) {
|
|
293
|
+
spinner.fail(import_chalk3.default.red(`Sync failed: ${e.message}`));
|
|
294
|
+
success = false;
|
|
295
|
+
}
|
|
296
|
+
return success;
|
|
297
|
+
}
|
|
298
|
+
function createSyncRulesCommand() {
|
|
299
|
+
const syncRules = new import_commander3.Command("sync-rules");
|
|
300
|
+
syncRules.description("\u{1F6E1}\uFE0F Push Frank Protocol v1.0 to all existing projects").option("--dry-run", "Preview changes without pushing to GitHub").option("--project <id>", "Sync a specific project only").action(async (options) => {
|
|
301
|
+
let apiKey;
|
|
302
|
+
try {
|
|
303
|
+
apiKey = getApiKey();
|
|
304
|
+
} catch (e) {
|
|
305
|
+
console.error(import_chalk3.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const apiUrl = getApiUrl();
|
|
309
|
+
if (options.project) {
|
|
310
|
+
await syncProjectRules(options.project, apiKey, apiUrl, options.dryRun);
|
|
311
|
+
} else {
|
|
312
|
+
console.log(import_chalk3.default.yellow("Use --project <id> for now. (Mass sync logic awaiting migration)"));
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
return syncRules;
|
|
316
|
+
}
|
|
317
|
+
var import_commander3, import_chalk3, import_ora2, import_axios2;
|
|
318
|
+
var init_sync_rules = __esm({
|
|
319
|
+
"src/commands/sync-rules.ts"() {
|
|
320
|
+
"use strict";
|
|
321
|
+
init_cjs_shims();
|
|
322
|
+
import_commander3 = require("commander");
|
|
323
|
+
import_chalk3 = __toESM(require("chalk"), 1);
|
|
324
|
+
import_ora2 = __toESM(require("ora"), 1);
|
|
325
|
+
init_config();
|
|
326
|
+
import_axios2 = __toESM(require("axios"), 1);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// src/commands/hooks.ts
|
|
331
|
+
var hooks_exports = {};
|
|
332
|
+
__export(hooks_exports, {
|
|
333
|
+
createHooksCommand: () => createHooksCommand
|
|
334
|
+
});
|
|
335
|
+
function createHooksCommand() {
|
|
336
|
+
const hooks = new import_commander4.Command("hooks").description("Manage git hooks for Guardian integration");
|
|
337
|
+
hooks.command("install").description("Install pre-commit hook to run Guardian checks").option("--strict [level]", 'Strict level: "all" or "critical" (default)', "critical").action(async (options) => {
|
|
338
|
+
try {
|
|
339
|
+
const gitDir = import_path2.default.join(process.cwd(), ".git");
|
|
340
|
+
try {
|
|
341
|
+
await import_promises2.default.access(gitDir);
|
|
342
|
+
} catch {
|
|
343
|
+
console.log(import_chalk4.default.red("\u274C Not a git repository."));
|
|
344
|
+
console.log(import_chalk4.default.dim(' Initialize with "git init" first.'));
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
const hooksDir = import_path2.default.join(gitDir, "hooks");
|
|
348
|
+
await import_promises2.default.mkdir(hooksDir, { recursive: true });
|
|
349
|
+
const preCommitPath = import_path2.default.join(hooksDir, "pre-commit");
|
|
350
|
+
let existingContent = "";
|
|
351
|
+
try {
|
|
352
|
+
existingContent = await import_promises2.default.readFile(preCommitPath, "utf-8");
|
|
353
|
+
if (existingContent.includes("rigstate")) {
|
|
354
|
+
console.log(import_chalk4.default.yellow("\u26A0 Rigstate pre-commit hook already installed."));
|
|
355
|
+
console.log(import_chalk4.default.dim(' Use "rigstate hooks uninstall" to remove first.'));
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
} catch {
|
|
359
|
+
}
|
|
360
|
+
let script = PRE_COMMIT_SCRIPT;
|
|
361
|
+
if (options.strict === "all") {
|
|
362
|
+
script = script.replace("--strict=critical", "--strict");
|
|
363
|
+
}
|
|
364
|
+
if (existingContent && !existingContent.includes("rigstate")) {
|
|
365
|
+
const combinedScript = existingContent + "\n\n" + script.replace("#!/bin/sh\n", "");
|
|
366
|
+
await import_promises2.default.writeFile(preCommitPath, combinedScript, { mode: 493 });
|
|
367
|
+
console.log(import_chalk4.default.green("\u2705 Rigstate hook appended to existing pre-commit."));
|
|
368
|
+
} else {
|
|
369
|
+
await import_promises2.default.writeFile(preCommitPath, script, { mode: 493 });
|
|
370
|
+
console.log(import_chalk4.default.green("\u2705 Pre-commit hook installed!"));
|
|
371
|
+
}
|
|
372
|
+
console.log(import_chalk4.default.dim(` Path: ${preCommitPath}`));
|
|
373
|
+
console.log(import_chalk4.default.dim(` Strict level: ${options.strict}`));
|
|
374
|
+
console.log("");
|
|
375
|
+
console.log(import_chalk4.default.cyan("Guardian will now check your code before each commit."));
|
|
376
|
+
console.log(import_chalk4.default.dim('Use "rigstate hooks uninstall" to remove the hook.'));
|
|
377
|
+
} catch (error) {
|
|
378
|
+
console.error(import_chalk4.default.red("Failed to install hook:"), error.message);
|
|
379
|
+
process.exit(1);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
hooks.command("uninstall").description("Remove Rigstate pre-commit hook").action(async () => {
|
|
383
|
+
try {
|
|
384
|
+
const preCommitPath = import_path2.default.join(process.cwd(), ".git", "hooks", "pre-commit");
|
|
385
|
+
try {
|
|
386
|
+
const content = await import_promises2.default.readFile(preCommitPath, "utf-8");
|
|
387
|
+
if (!content.includes("rigstate")) {
|
|
388
|
+
console.log(import_chalk4.default.yellow("\u26A0 No Rigstate hook found in pre-commit."));
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (content.includes("# Rigstate Guardian Pre-commit Hook") && content.trim().split("\n").filter((l) => l && !l.startsWith("#")).length <= 4) {
|
|
392
|
+
await import_promises2.default.unlink(preCommitPath);
|
|
393
|
+
console.log(import_chalk4.default.green("\u2705 Pre-commit hook removed."));
|
|
394
|
+
} else {
|
|
395
|
+
const lines = content.split("\n");
|
|
396
|
+
const filteredLines = [];
|
|
397
|
+
let inRigstateSection = false;
|
|
398
|
+
for (const line of lines) {
|
|
399
|
+
if (line.includes("Rigstate Guardian Pre-commit Hook")) {
|
|
400
|
+
inRigstateSection = true;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (inRigstateSection && line.includes("exit $?")) {
|
|
404
|
+
inRigstateSection = false;
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
if (!inRigstateSection && !line.includes("rigstate check")) {
|
|
408
|
+
filteredLines.push(line);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
await import_promises2.default.writeFile(preCommitPath, filteredLines.join("\n"), { mode: 493 });
|
|
412
|
+
console.log(import_chalk4.default.green("\u2705 Rigstate section removed from pre-commit hook."));
|
|
413
|
+
}
|
|
414
|
+
} catch {
|
|
415
|
+
console.log(import_chalk4.default.yellow("\u26A0 No pre-commit hook found."));
|
|
416
|
+
}
|
|
417
|
+
} catch (error) {
|
|
418
|
+
console.error(import_chalk4.default.red("Failed to uninstall hook:"), error.message);
|
|
419
|
+
process.exit(1);
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
return hooks;
|
|
423
|
+
}
|
|
424
|
+
var import_commander4, import_chalk4, import_promises2, import_path2, PRE_COMMIT_SCRIPT;
|
|
425
|
+
var init_hooks = __esm({
|
|
426
|
+
"src/commands/hooks.ts"() {
|
|
427
|
+
"use strict";
|
|
428
|
+
init_cjs_shims();
|
|
429
|
+
import_commander4 = require("commander");
|
|
430
|
+
import_chalk4 = __toESM(require("chalk"), 1);
|
|
431
|
+
import_promises2 = __toESM(require("fs/promises"), 1);
|
|
432
|
+
import_path2 = __toESM(require("path"), 1);
|
|
433
|
+
PRE_COMMIT_SCRIPT = `#!/bin/sh
|
|
434
|
+
# Rigstate Guardian Pre-commit Hook
|
|
435
|
+
# Installed by: rigstate hooks install
|
|
436
|
+
|
|
437
|
+
# 1. Silent Sentinel Check (Phase 5)
|
|
438
|
+
if [ -f .rigstate/guardian.lock ]; then
|
|
439
|
+
echo "\u{1F6D1} INTERVENTION ACTIVE: Commit blocked by Silent Sentinel."
|
|
440
|
+
echo " A critical violation ('HARD_LOCK') was detected by the Guardian Daemon."
|
|
441
|
+
echo " Please fix the violation to unlock the repo."
|
|
442
|
+
echo ""
|
|
443
|
+
if grep -q "HARD_LOCK_ACTIVE" .rigstate/guardian.lock; then
|
|
444
|
+
cat .rigstate/guardian.lock
|
|
445
|
+
fi
|
|
446
|
+
exit 1
|
|
447
|
+
fi
|
|
448
|
+
|
|
449
|
+
echo "\u{1F6E1}\uFE0F Running Guardian checks..."
|
|
450
|
+
|
|
451
|
+
# Run check with strict mode for critical violations
|
|
452
|
+
rigstate check --staged --strict=critical
|
|
453
|
+
|
|
454
|
+
# Exit with the same code as rigstate check
|
|
455
|
+
exit $?
|
|
456
|
+
`;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
88
460
|
// src/utils/skills-provisioner.ts
|
|
89
461
|
var skills_provisioner_exports = {};
|
|
90
462
|
__export(skills_provisioner_exports, {
|
|
@@ -95,7 +467,7 @@ __export(skills_provisioner_exports, {
|
|
|
95
467
|
async function provisionSkills(apiUrl, apiKey, projectId, rootDir) {
|
|
96
468
|
const skills = [];
|
|
97
469
|
try {
|
|
98
|
-
const response = await
|
|
470
|
+
const response = await import_axios5.default.get(`${apiUrl}/api/v1/skills`, {
|
|
99
471
|
params: { project_id: projectId },
|
|
100
472
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
101
473
|
});
|
|
@@ -113,18 +485,18 @@ async function provisionSkills(apiUrl, apiKey, projectId, rootDir) {
|
|
|
113
485
|
}
|
|
114
486
|
} catch (e) {
|
|
115
487
|
const msg = e.response?.data?.error || e.message;
|
|
116
|
-
console.log(
|
|
488
|
+
console.log(import_chalk8.default.dim(` (Skills API not available: ${msg}, using core library)`));
|
|
117
489
|
}
|
|
118
490
|
if (skills.length === 0) {
|
|
119
491
|
const { getRigstateStandardSkills } = await import("@rigstate/rules-engine");
|
|
120
492
|
const coreSkills = getRigstateStandardSkills();
|
|
121
493
|
skills.push(...coreSkills);
|
|
122
494
|
}
|
|
123
|
-
const skillsDir =
|
|
124
|
-
await
|
|
495
|
+
const skillsDir = import_path7.default.join(rootDir, ".agent", "skills");
|
|
496
|
+
await import_promises7.default.mkdir(skillsDir, { recursive: true });
|
|
125
497
|
for (const skill of skills) {
|
|
126
|
-
const skillDir =
|
|
127
|
-
await
|
|
498
|
+
const skillDir = import_path7.default.join(skillsDir, skill.name);
|
|
499
|
+
await import_promises7.default.mkdir(skillDir, { recursive: true });
|
|
128
500
|
const skillContent = `---
|
|
129
501
|
name: ${skill.name}
|
|
130
502
|
description: ${skill.description}
|
|
@@ -137,10 +509,10 @@ ${skill.content}
|
|
|
137
509
|
|
|
138
510
|
---
|
|
139
511
|
*Provisioned by Rigstate CLI. Do not modify manually.*`;
|
|
140
|
-
const skillPath =
|
|
141
|
-
await
|
|
512
|
+
const skillPath = import_path7.default.join(skillDir, "SKILL.md");
|
|
513
|
+
await import_promises7.default.writeFile(skillPath, skillContent, "utf-8");
|
|
142
514
|
}
|
|
143
|
-
console.log(
|
|
515
|
+
console.log(import_chalk8.default.green(` \u2705 Provisioned ${skills.length} skill(s) to .agent/skills/`));
|
|
144
516
|
return skills;
|
|
145
517
|
}
|
|
146
518
|
function generateSkillsDiscoveryBlock(skills) {
|
|
@@ -155,16 +527,16 @@ ${skillBlocks}
|
|
|
155
527
|
</available_skills>`;
|
|
156
528
|
}
|
|
157
529
|
async function jitProvisionSkill(skillId, apiUrl, apiKey, projectId, rootDir) {
|
|
158
|
-
const rulesPath =
|
|
530
|
+
const rulesPath = import_path7.default.join(rootDir, ".cursorrules");
|
|
159
531
|
let rulesContent = "";
|
|
160
532
|
try {
|
|
161
|
-
rulesContent = await
|
|
533
|
+
rulesContent = await import_promises7.default.readFile(rulesPath, "utf-8");
|
|
162
534
|
} catch (e) {
|
|
163
535
|
return false;
|
|
164
536
|
}
|
|
165
537
|
const isProvisioned = rulesContent.includes(`<name>${skillId}</name>`) || rulesContent.includes(`.agent/skills/${skillId}`);
|
|
166
538
|
if (isProvisioned) return false;
|
|
167
|
-
console.log(
|
|
539
|
+
console.log(import_chalk8.default.yellow(` \u26A1 JIT PROVISIONING: Injecting ${skillId}...`));
|
|
168
540
|
try {
|
|
169
541
|
const skills = await provisionSkills(apiUrl, apiKey, projectId, rootDir);
|
|
170
542
|
const skillsBlock = generateSkillsDiscoveryBlock(skills);
|
|
@@ -179,22 +551,22 @@ async function jitProvisionSkill(skillId, apiUrl, apiKey, projectId, rootDir) {
|
|
|
179
551
|
rulesContent = rulesContent.slice(0, insertPoint + 3) + "\n\n" + skillsBlock + "\n" + rulesContent.slice(insertPoint + 3);
|
|
180
552
|
}
|
|
181
553
|
}
|
|
182
|
-
await
|
|
554
|
+
await import_promises7.default.writeFile(rulesPath, rulesContent, "utf-8");
|
|
183
555
|
return true;
|
|
184
556
|
} catch (e) {
|
|
185
|
-
console.log(
|
|
557
|
+
console.log(import_chalk8.default.red(` Failed to provision skill: ${e.message}`));
|
|
186
558
|
return false;
|
|
187
559
|
}
|
|
188
560
|
}
|
|
189
|
-
var
|
|
561
|
+
var import_axios5, import_promises7, import_path7, import_chalk8;
|
|
190
562
|
var init_skills_provisioner = __esm({
|
|
191
563
|
"src/utils/skills-provisioner.ts"() {
|
|
192
564
|
"use strict";
|
|
193
565
|
init_cjs_shims();
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
566
|
+
import_axios5 = __toESM(require("axios"), 1);
|
|
567
|
+
import_promises7 = __toESM(require("fs/promises"), 1);
|
|
568
|
+
import_path7 = __toESM(require("path"), 1);
|
|
569
|
+
import_chalk8 = __toESM(require("chalk"), 1);
|
|
198
570
|
}
|
|
199
571
|
});
|
|
200
572
|
|
|
@@ -210,8 +582,8 @@ __export(governance_exports, {
|
|
|
210
582
|
});
|
|
211
583
|
async function getGovernanceConfig(rootDir = process.cwd()) {
|
|
212
584
|
try {
|
|
213
|
-
const configPath =
|
|
214
|
-
const content = await
|
|
585
|
+
const configPath = import_path8.default.join(rootDir, "rigstate.config.json");
|
|
586
|
+
const content = await import_promises8.default.readFile(configPath, "utf-8");
|
|
215
587
|
const userConfig = JSON.parse(content);
|
|
216
588
|
return {
|
|
217
589
|
governance: {
|
|
@@ -225,50 +597,50 @@ async function getGovernanceConfig(rootDir = process.cwd()) {
|
|
|
225
597
|
}
|
|
226
598
|
async function getSessionState(rootDir = process.cwd()) {
|
|
227
599
|
try {
|
|
228
|
-
const sessionPath =
|
|
229
|
-
const content = await
|
|
600
|
+
const sessionPath = import_path8.default.join(rootDir, ".rigstate", "session.json");
|
|
601
|
+
const content = await import_promises8.default.readFile(sessionPath, "utf-8");
|
|
230
602
|
return JSON.parse(content);
|
|
231
603
|
} catch (e) {
|
|
232
604
|
return DEFAULT_SESSION;
|
|
233
605
|
}
|
|
234
606
|
}
|
|
235
607
|
async function setSoftLock(reason, violationId, rootDir = process.cwd()) {
|
|
236
|
-
const sessionPath =
|
|
608
|
+
const sessionPath = import_path8.default.join(rootDir, ".rigstate", "session.json");
|
|
237
609
|
const state = {
|
|
238
610
|
status: "SOFT_LOCK",
|
|
239
611
|
active_violation: violationId,
|
|
240
612
|
lock_reason: reason,
|
|
241
613
|
last_updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
242
614
|
};
|
|
243
|
-
await
|
|
244
|
-
await
|
|
615
|
+
await import_promises8.default.mkdir(import_path8.default.dirname(sessionPath), { recursive: true });
|
|
616
|
+
await import_promises8.default.writeFile(sessionPath, JSON.stringify(state, null, 2), "utf-8");
|
|
245
617
|
}
|
|
246
618
|
async function clearSoftLock(rootDir = process.cwd()) {
|
|
247
|
-
const sessionPath =
|
|
619
|
+
const sessionPath = import_path8.default.join(rootDir, ".rigstate", "session.json");
|
|
248
620
|
const state = {
|
|
249
621
|
...DEFAULT_SESSION,
|
|
250
622
|
last_updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
251
623
|
};
|
|
252
|
-
await
|
|
253
|
-
await
|
|
624
|
+
await import_promises8.default.mkdir(import_path8.default.dirname(sessionPath), { recursive: true });
|
|
625
|
+
await import_promises8.default.writeFile(sessionPath, JSON.stringify(state, null, 2), "utf-8");
|
|
254
626
|
}
|
|
255
627
|
async function performOverride(violationId, reason, rootDir = process.cwd()) {
|
|
256
628
|
const config2 = await getGovernanceConfig(rootDir);
|
|
257
629
|
if (!config2.governance.allow_overrides) {
|
|
258
|
-
console.log(
|
|
630
|
+
console.log(import_chalk9.default.red("\u274C Overrides are disabled for this project."));
|
|
259
631
|
return false;
|
|
260
632
|
}
|
|
261
633
|
await clearSoftLock(rootDir);
|
|
262
634
|
return true;
|
|
263
635
|
}
|
|
264
|
-
var
|
|
636
|
+
var import_promises8, import_path8, import_chalk9, InterventionLevel, DEFAULT_CONFIG, DEFAULT_SESSION;
|
|
265
637
|
var init_governance = __esm({
|
|
266
638
|
"src/utils/governance.ts"() {
|
|
267
639
|
"use strict";
|
|
268
640
|
init_cjs_shims();
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
641
|
+
import_promises8 = __toESM(require("fs/promises"), 1);
|
|
642
|
+
import_path8 = __toESM(require("path"), 1);
|
|
643
|
+
import_chalk9 = __toESM(require("chalk"), 1);
|
|
272
644
|
InterventionLevel = /* @__PURE__ */ ((InterventionLevel2) => {
|
|
273
645
|
InterventionLevel2[InterventionLevel2["GHOST"] = 0] = "GHOST";
|
|
274
646
|
InterventionLevel2[InterventionLevel2["NUDGE"] = 1] = "NUDGE";
|
|
@@ -297,16 +669,16 @@ __export(watchdog_exports, {
|
|
|
297
669
|
});
|
|
298
670
|
async function countLines(filePath) {
|
|
299
671
|
try {
|
|
300
|
-
const content = await
|
|
672
|
+
const content = await import_promises9.default.readFile(filePath, "utf-8");
|
|
301
673
|
return content.split("\n").length;
|
|
302
674
|
} catch (e) {
|
|
303
675
|
return 0;
|
|
304
676
|
}
|
|
305
677
|
}
|
|
306
678
|
async function getFiles(dir, extension) {
|
|
307
|
-
const entries = await
|
|
679
|
+
const entries = await import_promises9.default.readdir(dir, { withFileTypes: true });
|
|
308
680
|
const files = await Promise.all(entries.map(async (entry) => {
|
|
309
|
-
const res =
|
|
681
|
+
const res = import_path9.default.resolve(dir, entry.name);
|
|
310
682
|
if (entry.isDirectory()) {
|
|
311
683
|
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === ".next" || entry.name === "dist") return [];
|
|
312
684
|
return getFiles(res, extension);
|
|
@@ -320,7 +692,7 @@ async function fetchRulesFromApi(projectId) {
|
|
|
320
692
|
try {
|
|
321
693
|
const apiUrl = getApiUrl();
|
|
322
694
|
const apiKey = getApiKey();
|
|
323
|
-
const response = await
|
|
695
|
+
const response = await import_axios6.default.get(`${apiUrl}/api/v1/guardian/rules`, {
|
|
324
696
|
params: { project_id: projectId },
|
|
325
697
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
326
698
|
timeout: 1e4
|
|
@@ -334,8 +706,8 @@ async function fetchRulesFromApi(projectId) {
|
|
|
334
706
|
}
|
|
335
707
|
} catch (error) {
|
|
336
708
|
try {
|
|
337
|
-
const cachePath =
|
|
338
|
-
const content = await
|
|
709
|
+
const cachePath = import_path9.default.join(process.cwd(), CACHE_FILE);
|
|
710
|
+
const content = await import_promises9.default.readFile(cachePath, "utf-8");
|
|
339
711
|
const cached = JSON.parse(content);
|
|
340
712
|
if (cached.settings) {
|
|
341
713
|
return {
|
|
@@ -354,7 +726,7 @@ async function fetchRulesFromApi(projectId) {
|
|
|
354
726
|
};
|
|
355
727
|
}
|
|
356
728
|
async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
357
|
-
console.log(
|
|
729
|
+
console.log(import_chalk10.default.bold("\n\u{1F6E1}\uFE0F Active Guardian Watchdog Initiated..."));
|
|
358
730
|
let lmax = settings.lmax || DEFAULT_LMAX;
|
|
359
731
|
let lmaxWarning = settings.lmax_warning || DEFAULT_LMAX_WARNING;
|
|
360
732
|
let ruleSource = settings.lmax ? "Settings (Passed)" : "Default";
|
|
@@ -364,47 +736,47 @@ async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
|
364
736
|
lmaxWarning = apiRules.lmaxWarning;
|
|
365
737
|
ruleSource = apiRules.source;
|
|
366
738
|
}
|
|
367
|
-
console.log(
|
|
739
|
+
console.log(import_chalk10.default.dim(`Governance Rules: L_max=${lmax}, L_max_warning=${lmaxWarning}, Source: ${ruleSource}`));
|
|
368
740
|
const targetExtensions = [".ts", ".tsx"];
|
|
369
741
|
let scanTarget = rootPath;
|
|
370
|
-
const webSrc =
|
|
742
|
+
const webSrc = import_path9.default.join(rootPath, "apps", "web", "src");
|
|
371
743
|
try {
|
|
372
|
-
await
|
|
744
|
+
await import_promises9.default.access(webSrc);
|
|
373
745
|
scanTarget = webSrc;
|
|
374
746
|
} catch {
|
|
375
747
|
}
|
|
376
|
-
console.log(
|
|
748
|
+
console.log(import_chalk10.default.dim(`Scanning target: ${import_path9.default.relative(process.cwd(), scanTarget)}`));
|
|
377
749
|
const files = await getFiles(scanTarget, targetExtensions);
|
|
378
750
|
let violations = 0;
|
|
379
751
|
let warnings = 0;
|
|
380
752
|
const results = [];
|
|
381
753
|
for (const file of files) {
|
|
382
754
|
const lines = await countLines(file);
|
|
383
|
-
const relPath =
|
|
755
|
+
const relPath = import_path9.default.relative(rootPath, file);
|
|
384
756
|
if (lines > lmax) {
|
|
385
757
|
results.push({ file: relPath, lines, status: "VIOLATION" });
|
|
386
758
|
violations++;
|
|
387
|
-
console.log(
|
|
759
|
+
console.log(import_chalk10.default.red(`[VIOLATION] ${relPath}: ${lines} lines (Limit: ${lmax})`));
|
|
388
760
|
} else if (lines > lmaxWarning) {
|
|
389
761
|
results.push({ file: relPath, lines, status: "WARNING" });
|
|
390
762
|
warnings++;
|
|
391
|
-
console.log(
|
|
763
|
+
console.log(import_chalk10.default.yellow(`[WARNING] ${relPath}: ${lines} lines (Threshold: ${lmaxWarning})`));
|
|
392
764
|
}
|
|
393
765
|
}
|
|
394
766
|
if (violations === 0 && warnings === 0) {
|
|
395
|
-
console.log(
|
|
767
|
+
console.log(import_chalk10.default.green(`\u2714 All ${files.length} files are within governance limits.`));
|
|
396
768
|
} else {
|
|
397
|
-
console.log("\n" +
|
|
398
|
-
console.log(
|
|
399
|
-
console.log(
|
|
769
|
+
console.log("\n" + import_chalk10.default.bold("Summary:"));
|
|
770
|
+
console.log(import_chalk10.default.red(`Violations: ${violations}`));
|
|
771
|
+
console.log(import_chalk10.default.yellow(`Warnings: ${warnings}`));
|
|
400
772
|
const { getGovernanceConfig: getGovernanceConfig2, setSoftLock: setSoftLock2, InterventionLevel: InterventionLevel2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
401
773
|
const { governance } = await getGovernanceConfig2(rootPath);
|
|
402
|
-
console.log(
|
|
774
|
+
console.log(import_chalk10.default.dim(`Intervention Level: ${InterventionLevel2[governance.intervention_level] || "UNKNOWN"} (${governance.intervention_level})`));
|
|
403
775
|
if (violations > 0) {
|
|
404
|
-
console.log(
|
|
776
|
+
console.log(import_chalk10.default.red.bold("\nCRITICAL: Governance violations detected. Immediate refactoring required."));
|
|
405
777
|
if (governance.intervention_level >= InterventionLevel2.SENTINEL) {
|
|
406
|
-
console.log(
|
|
407
|
-
console.log(
|
|
778
|
+
console.log(import_chalk10.default.red.bold("\u{1F6D1} SENTINEL MODE: Session SOFT_LOCKED until resolved."));
|
|
779
|
+
console.log(import_chalk10.default.red(' Run "rigstate override <id> --reason \\"...\\"" if this is an emergency.'));
|
|
408
780
|
await setSoftLock2("Sentinel Mode: Governance Violations Detected", "ARC-VIOLATION", rootPath);
|
|
409
781
|
}
|
|
410
782
|
}
|
|
@@ -420,28 +792,28 @@ async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
|
420
792
|
limitValue: lmax,
|
|
421
793
|
severity: "CRITICAL"
|
|
422
794
|
}));
|
|
423
|
-
await
|
|
795
|
+
await import_axios6.default.post(`${apiUrl}/api/v1/guardian/sync`, {
|
|
424
796
|
projectId,
|
|
425
797
|
violations: payloadViolations,
|
|
426
798
|
warnings
|
|
427
799
|
}, {
|
|
428
800
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
429
801
|
});
|
|
430
|
-
console.log(
|
|
802
|
+
console.log(import_chalk10.default.dim("\u2714 Violations synced to Rigstate Cloud."));
|
|
431
803
|
} catch (e) {
|
|
432
|
-
console.log(
|
|
804
|
+
console.log(import_chalk10.default.dim("\u26A0 Cloud sync skipped: " + (e.message || "Unknown")));
|
|
433
805
|
}
|
|
434
806
|
}
|
|
435
807
|
}
|
|
436
|
-
var
|
|
808
|
+
var import_promises9, import_path9, import_chalk10, import_axios6, DEFAULT_LMAX, DEFAULT_LMAX_WARNING, CACHE_FILE;
|
|
437
809
|
var init_watchdog = __esm({
|
|
438
810
|
"src/utils/watchdog.ts"() {
|
|
439
811
|
"use strict";
|
|
440
812
|
init_cjs_shims();
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
813
|
+
import_promises9 = __toESM(require("fs/promises"), 1);
|
|
814
|
+
import_path9 = __toESM(require("path"), 1);
|
|
815
|
+
import_chalk10 = __toESM(require("chalk"), 1);
|
|
816
|
+
import_axios6 = __toESM(require("axios"), 1);
|
|
445
817
|
init_config();
|
|
446
818
|
DEFAULT_LMAX = 400;
|
|
447
819
|
DEFAULT_LMAX_WARNING = 350;
|
|
@@ -475,6 +847,23 @@ function createLoginCommand() {
|
|
|
475
847
|
Your API key has been securely stored. You can now use "rigstate scan" to audit your code.`
|
|
476
848
|
)
|
|
477
849
|
);
|
|
850
|
+
console.log(import_chalk.default.bold("\n\u{1F916} Cursor MCP Configuration"));
|
|
851
|
+
console.log(import_chalk.default.dim("Copy and paste this into Cursor Settings -> Features -> MCP:"));
|
|
852
|
+
console.log(import_chalk.default.cyan(`
|
|
853
|
+
{
|
|
854
|
+
"mcpServers": {
|
|
855
|
+
"rigstate": {
|
|
856
|
+
"command": "npx",
|
|
857
|
+
"args": [
|
|
858
|
+
"-y",
|
|
859
|
+
"@rigstate/mcp@latest"
|
|
860
|
+
],
|
|
861
|
+
"env": {
|
|
862
|
+
"RIGSTATE_API_KEY": "${apiKey}"
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}`));
|
|
478
867
|
} catch (error) {
|
|
479
868
|
console.error(
|
|
480
869
|
import_chalk.default.red("\u274C Login failed:"),
|
|
@@ -487,64 +876,108 @@ Your API key has been securely stored. You can now use "rigstate scan" to audit
|
|
|
487
876
|
|
|
488
877
|
// src/commands/link.ts
|
|
489
878
|
init_cjs_shims();
|
|
490
|
-
var
|
|
491
|
-
var
|
|
492
|
-
var
|
|
493
|
-
var
|
|
879
|
+
var import_commander5 = require("commander");
|
|
880
|
+
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
881
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
882
|
+
var import_chalk5 = __toESM(require("chalk"), 1);
|
|
494
883
|
var import_os = __toESM(require("os"), 1);
|
|
495
884
|
function createLinkCommand() {
|
|
496
|
-
return new
|
|
885
|
+
return new import_commander5.Command("link").description("Link current directory to a Rigstate project").argument("<projectId>", "Project ID to link").action(async (projectId) => {
|
|
497
886
|
try {
|
|
498
|
-
const globalPath =
|
|
499
|
-
const globalData = await
|
|
887
|
+
const globalPath = import_path3.default.join(import_os.default.homedir(), ".rigstate", "config.json");
|
|
888
|
+
const globalData = await import_promises3.default.readFile(globalPath, "utf-8").catch(() => null);
|
|
500
889
|
if (globalData) {
|
|
501
890
|
const config2 = JSON.parse(globalData);
|
|
502
891
|
const cwd = process.cwd();
|
|
503
892
|
if (config2.overrides && config2.overrides[cwd]) {
|
|
504
893
|
const overrideId = config2.overrides[cwd];
|
|
505
894
|
if (overrideId !== projectId) {
|
|
506
|
-
console.warn(
|
|
895
|
+
console.warn(import_chalk5.default.yellow(`Global override detected. Enforcing project ID: ${overrideId}`));
|
|
507
896
|
projectId = overrideId;
|
|
508
897
|
}
|
|
509
898
|
}
|
|
510
899
|
}
|
|
511
900
|
} catch (e) {
|
|
512
901
|
}
|
|
513
|
-
const manifestPath =
|
|
902
|
+
const manifestPath = import_path3.default.join(process.cwd(), ".rigstate");
|
|
514
903
|
const content = {
|
|
515
904
|
project_id: projectId,
|
|
516
905
|
api_url: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
|
|
517
906
|
linked_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
518
907
|
};
|
|
519
908
|
try {
|
|
520
|
-
await
|
|
521
|
-
console.log(
|
|
522
|
-
console.log(
|
|
909
|
+
await import_promises3.default.writeFile(manifestPath, JSON.stringify(content, null, 2), "utf-8");
|
|
910
|
+
console.log(import_chalk5.default.green(`\u2714 Linked to project ID: ${projectId}`));
|
|
911
|
+
console.log(import_chalk5.default.dim(`Created local context manifest at .rigstate`));
|
|
912
|
+
console.log("");
|
|
913
|
+
console.log(import_chalk5.default.bold("\u{1F916} Rigstate Automation Detected"));
|
|
914
|
+
console.log("");
|
|
915
|
+
const { getApiKey: getApiKey2, getApiUrl: getApiUrl2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
916
|
+
const apiKey = getApiKey2();
|
|
917
|
+
const apiUrl = getApiUrl2();
|
|
918
|
+
if (apiKey) {
|
|
919
|
+
console.log(import_chalk5.default.blue("\u{1F510} Checking Vault for secrets..."));
|
|
920
|
+
const { syncEnv: syncEnv2 } = await Promise.resolve().then(() => (init_env(), env_exports));
|
|
921
|
+
await syncEnv2(projectId, apiKey, apiUrl, true);
|
|
922
|
+
console.log(import_chalk5.default.blue("\u{1F9E0} Syncing neural instructions..."));
|
|
923
|
+
const { syncProjectRules: syncProjectRules2 } = await Promise.resolve().then(() => (init_sync_rules(), sync_rules_exports));
|
|
924
|
+
await syncProjectRules2(projectId, apiKey, apiUrl);
|
|
925
|
+
console.log(import_chalk5.default.blue("\u{1F6E1}\uFE0F Checking immunity system..."));
|
|
926
|
+
await installHooks(process.cwd());
|
|
927
|
+
}
|
|
928
|
+
console.log("");
|
|
929
|
+
console.log(import_chalk5.default.bold.green("\u{1F680} Link Complete! Your environment is ready."));
|
|
523
930
|
} catch (error) {
|
|
524
|
-
|
|
931
|
+
if (error.message.includes("Not authenticated")) {
|
|
932
|
+
console.warn(import_chalk5.default.yellow('\u26A0\uFE0F Not authenticated. Run "rigstate login" to enable automation features.'));
|
|
933
|
+
} else {
|
|
934
|
+
console.error(import_chalk5.default.red(`Failed to link project: ${error.message}`));
|
|
935
|
+
}
|
|
525
936
|
}
|
|
526
937
|
});
|
|
527
938
|
}
|
|
939
|
+
async function installHooks(cwd) {
|
|
940
|
+
const fs23 = await import("fs/promises");
|
|
941
|
+
const path23 = await import("path");
|
|
942
|
+
try {
|
|
943
|
+
await fs23.access(path23.join(cwd, ".git"));
|
|
944
|
+
} catch {
|
|
945
|
+
console.log(import_chalk5.default.dim(" (Not a git repository, skipping hooks)"));
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const hooksDir = path23.join(cwd, ".husky");
|
|
949
|
+
try {
|
|
950
|
+
const { installHooks: runInstall } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
951
|
+
const preCommitPath = path23.join(cwd, ".git/hooks/pre-commit");
|
|
952
|
+
try {
|
|
953
|
+
await fs23.access(preCommitPath);
|
|
954
|
+
console.log(import_chalk5.default.green(" \u2714 Git hooks already active"));
|
|
955
|
+
} catch {
|
|
956
|
+
console.log(import_chalk5.default.yellow(' \u26A0\uFE0F Git hooks missing. Run "rigstate hooks install" to secure repo.'));
|
|
957
|
+
}
|
|
958
|
+
} catch (e) {
|
|
959
|
+
}
|
|
960
|
+
}
|
|
528
961
|
|
|
529
962
|
// src/commands/scan.ts
|
|
530
963
|
init_cjs_shims();
|
|
531
|
-
var
|
|
532
|
-
var
|
|
533
|
-
var
|
|
534
|
-
var
|
|
964
|
+
var import_commander6 = require("commander");
|
|
965
|
+
var import_chalk6 = __toESM(require("chalk"), 1);
|
|
966
|
+
var import_ora3 = __toESM(require("ora"), 1);
|
|
967
|
+
var import_axios3 = __toESM(require("axios"), 1);
|
|
535
968
|
var import_glob = require("glob");
|
|
536
|
-
var
|
|
537
|
-
var
|
|
969
|
+
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
970
|
+
var import_path5 = __toESM(require("path"), 1);
|
|
538
971
|
init_config();
|
|
539
972
|
|
|
540
973
|
// src/utils/files.ts
|
|
541
974
|
init_cjs_shims();
|
|
542
|
-
var
|
|
543
|
-
var
|
|
975
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
976
|
+
var import_path4 = __toESM(require("path"), 1);
|
|
544
977
|
async function readGitignore(dir) {
|
|
545
|
-
const gitignorePath =
|
|
978
|
+
const gitignorePath = import_path4.default.join(dir, ".gitignore");
|
|
546
979
|
try {
|
|
547
|
-
const content = await
|
|
980
|
+
const content = await import_promises4.default.readFile(gitignorePath, "utf-8");
|
|
548
981
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
549
982
|
} catch (error) {
|
|
550
983
|
return [];
|
|
@@ -606,40 +1039,40 @@ function isCodeFile(filePath) {
|
|
|
606
1039
|
".vue",
|
|
607
1040
|
".svelte"
|
|
608
1041
|
];
|
|
609
|
-
const ext =
|
|
1042
|
+
const ext = import_path4.default.extname(filePath).toLowerCase();
|
|
610
1043
|
return codeExtensions.includes(ext);
|
|
611
1044
|
}
|
|
612
1045
|
|
|
613
1046
|
// src/commands/scan.ts
|
|
614
1047
|
function createScanCommand() {
|
|
615
|
-
return new
|
|
616
|
-
const spinner = (0,
|
|
1048
|
+
return new import_commander6.Command("scan").description("Scan code files for security and quality issues").argument("[path]", "Directory or file to scan", ".").option("--json", "Output results as JSON").option("--project <id>", "Project ID to associate with this scan").action(async (targetPath, options) => {
|
|
1049
|
+
const spinner = (0, import_ora3.default)();
|
|
617
1050
|
try {
|
|
618
1051
|
const apiKey = getApiKey();
|
|
619
1052
|
const apiUrl = getApiUrl();
|
|
620
1053
|
const projectId = options.project || getProjectId();
|
|
621
1054
|
if (!projectId) {
|
|
622
1055
|
console.warn(
|
|
623
|
-
|
|
1056
|
+
import_chalk6.default.yellow(
|
|
624
1057
|
"\u26A0\uFE0F No project ID specified. Use --project <id> or set a default."
|
|
625
1058
|
)
|
|
626
1059
|
);
|
|
627
1060
|
}
|
|
628
|
-
const scanPath =
|
|
629
|
-
spinner.start(`Scanning ${
|
|
1061
|
+
const scanPath = import_path5.default.resolve(process.cwd(), targetPath);
|
|
1062
|
+
spinner.start(`Scanning ${import_chalk6.default.cyan(scanPath)}...`);
|
|
630
1063
|
const gitignorePatterns = await readGitignore(scanPath);
|
|
631
|
-
const pattern =
|
|
1064
|
+
const pattern = import_path5.default.join(scanPath, "**/*");
|
|
632
1065
|
const allFiles = await (0, import_glob.glob)(pattern, {
|
|
633
1066
|
nodir: true,
|
|
634
1067
|
dot: false,
|
|
635
1068
|
ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**"]
|
|
636
1069
|
});
|
|
637
1070
|
const codeFiles = allFiles.filter((file) => {
|
|
638
|
-
const relativePath =
|
|
1071
|
+
const relativePath = import_path5.default.relative(scanPath, file);
|
|
639
1072
|
return isCodeFile(file) && !shouldIgnore(relativePath, gitignorePatterns);
|
|
640
1073
|
});
|
|
641
1074
|
if (codeFiles.length === 0) {
|
|
642
|
-
spinner.warn(
|
|
1075
|
+
spinner.warn(import_chalk6.default.yellow("No code files found to scan."));
|
|
643
1076
|
return;
|
|
644
1077
|
}
|
|
645
1078
|
spinner.text = `Found ${codeFiles.length} files. Scanning...`;
|
|
@@ -648,11 +1081,11 @@ function createScanCommand() {
|
|
|
648
1081
|
const severityCounts = {};
|
|
649
1082
|
for (let i = 0; i < codeFiles.length; i++) {
|
|
650
1083
|
const filePath = codeFiles[i];
|
|
651
|
-
const relativePath =
|
|
1084
|
+
const relativePath = import_path5.default.relative(scanPath, filePath);
|
|
652
1085
|
spinner.text = `Scanning ${i + 1}/${codeFiles.length}: ${relativePath}`;
|
|
653
1086
|
try {
|
|
654
|
-
const content = await
|
|
655
|
-
const response = await
|
|
1087
|
+
const content = await import_promises5.default.readFile(filePath, "utf-8");
|
|
1088
|
+
const response = await import_axios3.default.post(
|
|
656
1089
|
`${apiUrl}/api/v1/audit`,
|
|
657
1090
|
{
|
|
658
1091
|
content,
|
|
@@ -686,16 +1119,16 @@ function createScanCommand() {
|
|
|
686
1119
|
});
|
|
687
1120
|
}
|
|
688
1121
|
} catch (fileError) {
|
|
689
|
-
if (
|
|
690
|
-
console.warn(
|
|
1122
|
+
if (import_axios3.default.isAxiosError(fileError)) {
|
|
1123
|
+
console.warn(import_chalk6.default.yellow(`
|
|
691
1124
|
\u26A0\uFE0F Skipping ${relativePath}: ${fileError.message}`));
|
|
692
1125
|
} else {
|
|
693
|
-
console.warn(
|
|
1126
|
+
console.warn(import_chalk6.default.yellow(`
|
|
694
1127
|
\u26A0\uFE0F Error reading ${relativePath}`));
|
|
695
1128
|
}
|
|
696
1129
|
}
|
|
697
1130
|
}
|
|
698
|
-
spinner.succeed(
|
|
1131
|
+
spinner.succeed(import_chalk6.default.green("\u2705 Scan completed!"));
|
|
699
1132
|
const aggregatedResponse = {
|
|
700
1133
|
results,
|
|
701
1134
|
summary: {
|
|
@@ -710,21 +1143,21 @@ function createScanCommand() {
|
|
|
710
1143
|
printPrettyResults(aggregatedResponse);
|
|
711
1144
|
}
|
|
712
1145
|
} catch (error) {
|
|
713
|
-
spinner.fail(
|
|
714
|
-
if (
|
|
1146
|
+
spinner.fail(import_chalk6.default.red("\u274C Scan failed"));
|
|
1147
|
+
if (import_axios3.default.isAxiosError(error)) {
|
|
715
1148
|
if (error.response) {
|
|
716
|
-
console.error(
|
|
1149
|
+
console.error(import_chalk6.default.red("API Error:"), error.response.data);
|
|
717
1150
|
} else if (error.request) {
|
|
718
1151
|
console.error(
|
|
719
|
-
|
|
1152
|
+
import_chalk6.default.red("Network Error:"),
|
|
720
1153
|
"Could not reach the API. Is the server running?"
|
|
721
1154
|
);
|
|
722
1155
|
} else {
|
|
723
|
-
console.error(
|
|
1156
|
+
console.error(import_chalk6.default.red("Error:"), error.message);
|
|
724
1157
|
}
|
|
725
1158
|
} else {
|
|
726
1159
|
console.error(
|
|
727
|
-
|
|
1160
|
+
import_chalk6.default.red("Error:"),
|
|
728
1161
|
error instanceof Error ? error.message : "Unknown error"
|
|
729
1162
|
);
|
|
730
1163
|
}
|
|
@@ -734,10 +1167,10 @@ function createScanCommand() {
|
|
|
734
1167
|
}
|
|
735
1168
|
function printPrettyResults(data) {
|
|
736
1169
|
const { results, summary } = data;
|
|
737
|
-
console.log("\n" +
|
|
738
|
-
console.log(
|
|
739
|
-
console.log(`Total Files Scanned: ${
|
|
740
|
-
console.log(`Total Issues Found: ${
|
|
1170
|
+
console.log("\n" + import_chalk6.default.bold("\u{1F4CA} Scan Summary"));
|
|
1171
|
+
console.log(import_chalk6.default.dim("\u2500".repeat(60)));
|
|
1172
|
+
console.log(`Total Files Scanned: ${import_chalk6.default.cyan(summary.total_files)}`);
|
|
1173
|
+
console.log(`Total Issues Found: ${import_chalk6.default.yellow(summary.total_issues)}`);
|
|
741
1174
|
if (summary.by_severity) {
|
|
742
1175
|
console.log("\nIssues by Severity:");
|
|
743
1176
|
Object.entries(summary.by_severity).forEach(([severity, count]) => {
|
|
@@ -746,88 +1179,88 @@ function printPrettyResults(data) {
|
|
|
746
1179
|
});
|
|
747
1180
|
}
|
|
748
1181
|
if (results && results.length > 0) {
|
|
749
|
-
console.log("\n" +
|
|
750
|
-
console.log(
|
|
1182
|
+
console.log("\n" + import_chalk6.default.bold("\u{1F50D} Detailed Results"));
|
|
1183
|
+
console.log(import_chalk6.default.dim("\u2500".repeat(60)));
|
|
751
1184
|
results.forEach((result) => {
|
|
752
1185
|
if (result.issues && result.issues.length > 0) {
|
|
753
1186
|
console.log(`
|
|
754
|
-
${
|
|
1187
|
+
${import_chalk6.default.bold(result.file_path)}`);
|
|
755
1188
|
result.issues.forEach((issue) => {
|
|
756
1189
|
const severityColor = getSeverityColor(issue.severity);
|
|
757
|
-
const lineInfo = issue.line ?
|
|
1190
|
+
const lineInfo = issue.line ? import_chalk6.default.dim(`:${issue.line}`) : "";
|
|
758
1191
|
console.log(
|
|
759
1192
|
` ${severityColor(`[${issue.severity.toUpperCase()}]`)} ${issue.type}${lineInfo}`
|
|
760
1193
|
);
|
|
761
|
-
console.log(` ${
|
|
1194
|
+
console.log(` ${import_chalk6.default.dim(issue.message)}`);
|
|
762
1195
|
});
|
|
763
1196
|
}
|
|
764
1197
|
});
|
|
765
1198
|
}
|
|
766
|
-
console.log("\n" +
|
|
1199
|
+
console.log("\n" + import_chalk6.default.dim("\u2500".repeat(60)));
|
|
767
1200
|
}
|
|
768
1201
|
function getSeverityColor(severity) {
|
|
769
1202
|
switch (severity.toLowerCase()) {
|
|
770
1203
|
case "critical":
|
|
771
|
-
return
|
|
1204
|
+
return import_chalk6.default.red.bold;
|
|
772
1205
|
case "high":
|
|
773
|
-
return
|
|
1206
|
+
return import_chalk6.default.red;
|
|
774
1207
|
case "medium":
|
|
775
|
-
return
|
|
1208
|
+
return import_chalk6.default.yellow;
|
|
776
1209
|
case "low":
|
|
777
|
-
return
|
|
1210
|
+
return import_chalk6.default.blue;
|
|
778
1211
|
case "info":
|
|
779
|
-
return
|
|
1212
|
+
return import_chalk6.default.gray;
|
|
780
1213
|
default:
|
|
781
|
-
return
|
|
1214
|
+
return import_chalk6.default.white;
|
|
782
1215
|
}
|
|
783
1216
|
}
|
|
784
1217
|
|
|
785
1218
|
// src/commands/fix.ts
|
|
786
1219
|
init_cjs_shims();
|
|
787
|
-
var
|
|
788
|
-
var
|
|
789
|
-
var
|
|
790
|
-
var
|
|
1220
|
+
var import_commander7 = require("commander");
|
|
1221
|
+
var import_chalk7 = __toESM(require("chalk"), 1);
|
|
1222
|
+
var import_ora4 = __toESM(require("ora"), 1);
|
|
1223
|
+
var import_axios4 = __toESM(require("axios"), 1);
|
|
791
1224
|
var import_glob2 = require("glob");
|
|
792
|
-
var
|
|
793
|
-
var
|
|
1225
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
1226
|
+
var import_path6 = __toESM(require("path"), 1);
|
|
794
1227
|
var import_inquirer = __toESM(require("inquirer"), 1);
|
|
795
1228
|
var Diff = __toESM(require("diff"), 1);
|
|
796
1229
|
init_config();
|
|
797
1230
|
function createFixCommand() {
|
|
798
|
-
return new
|
|
799
|
-
const spinner = (0,
|
|
1231
|
+
return new import_commander7.Command("fix").description("Scan and interactively FIX detected issues using Rigstate AI").argument("[path]", "Directory or file to scan", ".").option("--project <id>", "Project ID to context-aware audit").action(async (targetPath, options) => {
|
|
1232
|
+
const spinner = (0, import_ora4.default)();
|
|
800
1233
|
try {
|
|
801
1234
|
const apiKey = getApiKey();
|
|
802
1235
|
const apiUrl = getApiUrl();
|
|
803
1236
|
const projectId = options.project || getProjectId();
|
|
804
1237
|
if (!projectId) {
|
|
805
|
-
console.log(
|
|
1238
|
+
console.log(import_chalk7.default.yellow("\u26A0\uFE0F Project ID is required for fixing. Using default or pass --project <id>"));
|
|
806
1239
|
}
|
|
807
|
-
const scanPath =
|
|
1240
|
+
const scanPath = import_path6.default.resolve(process.cwd(), targetPath);
|
|
808
1241
|
const gitignorePatterns = await readGitignore(scanPath);
|
|
809
|
-
const pattern =
|
|
1242
|
+
const pattern = import_path6.default.join(scanPath, "**/*");
|
|
810
1243
|
const allFiles = await (0, import_glob2.glob)(pattern, { nodir: true, dot: false, ignore: ["**/node_modules/**", "**/.git/**"] });
|
|
811
1244
|
const codeFiles = allFiles.filter((file) => {
|
|
812
|
-
const relativePath =
|
|
1245
|
+
const relativePath = import_path6.default.relative(scanPath, file);
|
|
813
1246
|
return isCodeFile(file) && !shouldIgnore(relativePath, gitignorePatterns);
|
|
814
1247
|
});
|
|
815
1248
|
if (codeFiles.length === 0) {
|
|
816
|
-
console.log(
|
|
1249
|
+
console.log(import_chalk7.default.yellow("No code files found."));
|
|
817
1250
|
return;
|
|
818
1251
|
}
|
|
819
|
-
console.log(
|
|
1252
|
+
console.log(import_chalk7.default.bold(`
|
|
820
1253
|
\u{1F9E0} Rigstate Fix Mode`));
|
|
821
|
-
console.log(
|
|
1254
|
+
console.log(import_chalk7.default.dim(`Scanning ${codeFiles.length} files with Project Context...
|
|
822
1255
|
`));
|
|
823
1256
|
let fixedCount = 0;
|
|
824
1257
|
for (let i = 0; i < codeFiles.length; i++) {
|
|
825
1258
|
const filePath = codeFiles[i];
|
|
826
|
-
const relativePath =
|
|
1259
|
+
const relativePath = import_path6.default.relative(scanPath, filePath);
|
|
827
1260
|
spinner.start(`Analyzing ${relativePath}...`);
|
|
828
1261
|
try {
|
|
829
|
-
const content = await
|
|
830
|
-
const response = await
|
|
1262
|
+
const content = await import_promises6.default.readFile(filePath, "utf-8");
|
|
1263
|
+
const response = await import_axios4.default.post(
|
|
831
1264
|
`${apiUrl}/api/v1/audit`,
|
|
832
1265
|
{ content, file_path: relativePath, project_id: projectId },
|
|
833
1266
|
{ headers: { "Authorization": `Bearer ${apiKey}` }, timeout: 12e4 }
|
|
@@ -837,22 +1270,22 @@ function createFixCommand() {
|
|
|
837
1270
|
if (fixableIssues.length > 0) {
|
|
838
1271
|
spinner.stop();
|
|
839
1272
|
console.log(`
|
|
840
|
-
${
|
|
1273
|
+
${import_chalk7.default.bold(relativePath)}: Found ${fixableIssues.length} fixable issues.`);
|
|
841
1274
|
for (const issue of fixableIssues) {
|
|
842
|
-
console.log(
|
|
1275
|
+
console.log(import_chalk7.default.red(`
|
|
843
1276
|
[${issue.type}] ${issue.title}`));
|
|
844
|
-
console.log(
|
|
1277
|
+
console.log(import_chalk7.default.dim(issue.suggestion || issue.message));
|
|
845
1278
|
const diff = Diff.createTwoFilesPatch(relativePath, relativePath, content, issue.fixed_content, "Current", "Fixed");
|
|
846
1279
|
console.log("\n" + diff.split("\n").slice(0, 15).join("\n") + (diff.split("\n").length > 15 ? "\n..." : ""));
|
|
847
1280
|
const { apply } = await import_inquirer.default.prompt([{
|
|
848
1281
|
type: "confirm",
|
|
849
1282
|
name: "apply",
|
|
850
|
-
message: `Apply this fix to ${
|
|
1283
|
+
message: `Apply this fix to ${import_chalk7.default.cyan(relativePath)}?`,
|
|
851
1284
|
default: true
|
|
852
1285
|
}]);
|
|
853
1286
|
if (apply) {
|
|
854
|
-
await
|
|
855
|
-
console.log(
|
|
1287
|
+
await import_promises6.default.writeFile(filePath, issue.fixed_content);
|
|
1288
|
+
console.log(import_chalk7.default.green(`\u2705 Fixed applied!`));
|
|
856
1289
|
fixedCount++;
|
|
857
1290
|
if (issue.related_step_id) {
|
|
858
1291
|
const { completeStep } = await import_inquirer.default.prompt([{
|
|
@@ -863,20 +1296,20 @@ ${import_chalk4.default.bold(relativePath)}: Found ${fixableIssues.length} fixab
|
|
|
863
1296
|
}]);
|
|
864
1297
|
if (completeStep) {
|
|
865
1298
|
try {
|
|
866
|
-
await
|
|
1299
|
+
await import_axios4.default.post(
|
|
867
1300
|
`${apiUrl}/api/v1/roadmap/update-status`,
|
|
868
1301
|
{ step_id: issue.related_step_id, status: "COMPLETED", project_id: projectId },
|
|
869
1302
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
870
1303
|
);
|
|
871
|
-
console.log(
|
|
1304
|
+
console.log(import_chalk7.default.green(`\u{1F680} Roadmap updated! Mission Control is in sync.`));
|
|
872
1305
|
} catch (err) {
|
|
873
|
-
console.error(
|
|
1306
|
+
console.error(import_chalk7.default.yellow(`Failed to update roadmap: ${err.message}`));
|
|
874
1307
|
}
|
|
875
1308
|
}
|
|
876
1309
|
}
|
|
877
1310
|
break;
|
|
878
1311
|
} else {
|
|
879
|
-
console.log(
|
|
1312
|
+
console.log(import_chalk7.default.dim("Skipped."));
|
|
880
1313
|
}
|
|
881
1314
|
}
|
|
882
1315
|
} else {
|
|
@@ -886,11 +1319,11 @@ ${import_chalk4.default.bold(relativePath)}: Found ${fixableIssues.length} fixab
|
|
|
886
1319
|
}
|
|
887
1320
|
}
|
|
888
1321
|
spinner.stop();
|
|
889
|
-
console.log(
|
|
1322
|
+
console.log(import_chalk7.default.bold.green(`
|
|
890
1323
|
|
|
891
1324
|
\u{1F680} Fix session complete!`));
|
|
892
1325
|
console.log(`Frank fixed ${fixedCount} detected issues.`);
|
|
893
|
-
console.log(
|
|
1326
|
+
console.log(import_chalk7.default.dim(`Run 'rigstate scan' to verify remaining issues.`));
|
|
894
1327
|
} catch (error) {
|
|
895
1328
|
spinner.fail("Fix session failed");
|
|
896
1329
|
console.error(error.message);
|
|
@@ -900,17 +1333,17 @@ ${import_chalk4.default.bold(relativePath)}: Found ${fixableIssues.length} fixab
|
|
|
900
1333
|
|
|
901
1334
|
// src/commands/sync.ts
|
|
902
1335
|
init_cjs_shims();
|
|
903
|
-
var
|
|
904
|
-
var
|
|
905
|
-
var
|
|
1336
|
+
var import_commander8 = require("commander");
|
|
1337
|
+
var import_chalk11 = __toESM(require("chalk"), 1);
|
|
1338
|
+
var import_ora5 = __toESM(require("ora"), 1);
|
|
906
1339
|
init_config();
|
|
907
|
-
var
|
|
908
|
-
var
|
|
909
|
-
var
|
|
1340
|
+
var import_axios7 = __toESM(require("axios"), 1);
|
|
1341
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
1342
|
+
var import_path10 = __toESM(require("path"), 1);
|
|
910
1343
|
function createSyncCommand() {
|
|
911
|
-
const sync = new
|
|
1344
|
+
const sync = new import_commander8.Command("sync");
|
|
912
1345
|
sync.description("Synchronize local state with Rigstate Cloud").option("-p, --project <id>", "Specify Project ID (saves to config automatically)").action(async (options) => {
|
|
913
|
-
const spinner = (0,
|
|
1346
|
+
const spinner = (0, import_ora5.default)("Synchronizing project state...").start();
|
|
914
1347
|
try {
|
|
915
1348
|
let apiKey;
|
|
916
1349
|
try {
|
|
@@ -922,8 +1355,8 @@ function createSyncCommand() {
|
|
|
922
1355
|
let projectId = options.project;
|
|
923
1356
|
if (!projectId) {
|
|
924
1357
|
try {
|
|
925
|
-
const manifestPath =
|
|
926
|
-
const manifestContent = await
|
|
1358
|
+
const manifestPath = import_path10.default.join(process.cwd(), ".rigstate");
|
|
1359
|
+
const manifestContent = await import_promises10.default.readFile(manifestPath, "utf-8");
|
|
927
1360
|
const manifest = JSON.parse(manifestContent);
|
|
928
1361
|
if (manifest.project_id) projectId = manifest.project_id;
|
|
929
1362
|
} catch (e) {
|
|
@@ -938,7 +1371,7 @@ function createSyncCommand() {
|
|
|
938
1371
|
return;
|
|
939
1372
|
}
|
|
940
1373
|
const apiUrl = getApiUrl();
|
|
941
|
-
const response = await
|
|
1374
|
+
const response = await import_axios7.default.get(`${apiUrl}/api/v1/roadmap`, {
|
|
942
1375
|
params: { project_id: projectId },
|
|
943
1376
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
944
1377
|
});
|
|
@@ -947,31 +1380,31 @@ function createSyncCommand() {
|
|
|
947
1380
|
}
|
|
948
1381
|
const { roadmap, project } = response.data.data;
|
|
949
1382
|
const timestamp = response.data.timestamp;
|
|
950
|
-
const targetPath =
|
|
1383
|
+
const targetPath = import_path10.default.join(process.cwd(), "roadmap.json");
|
|
951
1384
|
const fileContent = JSON.stringify({
|
|
952
1385
|
project,
|
|
953
1386
|
last_synced: timestamp,
|
|
954
1387
|
roadmap
|
|
955
1388
|
}, null, 2);
|
|
956
|
-
await
|
|
1389
|
+
await import_promises10.default.writeFile(targetPath, fileContent, "utf-8");
|
|
957
1390
|
try {
|
|
958
|
-
const manifestPath =
|
|
1391
|
+
const manifestPath = import_path10.default.join(process.cwd(), ".rigstate");
|
|
959
1392
|
const manifestContent = {
|
|
960
1393
|
project_id: projectId,
|
|
961
1394
|
project_name: project,
|
|
962
1395
|
last_synced: timestamp,
|
|
963
1396
|
api_url: apiUrl
|
|
964
1397
|
};
|
|
965
|
-
await
|
|
1398
|
+
await import_promises10.default.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), "utf-8");
|
|
966
1399
|
} catch (e) {
|
|
967
1400
|
}
|
|
968
|
-
console.log(
|
|
1401
|
+
console.log(import_chalk11.default.bold("\n\u{1F9E0} Agent Skills Provisioning..."));
|
|
969
1402
|
try {
|
|
970
1403
|
const { provisionSkills: provisionSkills2, generateSkillsDiscoveryBlock: generateSkillsDiscoveryBlock2 } = await Promise.resolve().then(() => (init_skills_provisioner(), skills_provisioner_exports));
|
|
971
1404
|
const skills = await provisionSkills2(apiUrl, apiKey, projectId, process.cwd());
|
|
972
|
-
const cursorRulesPath =
|
|
1405
|
+
const cursorRulesPath = import_path10.default.join(process.cwd(), ".cursorrules");
|
|
973
1406
|
try {
|
|
974
|
-
let rulesContent = await
|
|
1407
|
+
let rulesContent = await import_promises10.default.readFile(cursorRulesPath, "utf-8");
|
|
975
1408
|
const skillsBlock = generateSkillsDiscoveryBlock2(skills);
|
|
976
1409
|
if (rulesContent.includes("<available_skills>")) {
|
|
977
1410
|
rulesContent = rulesContent.replace(
|
|
@@ -984,28 +1417,28 @@ function createSyncCommand() {
|
|
|
984
1417
|
rulesContent = rulesContent.slice(0, insertPoint + 3) + "\n\n" + skillsBlock + "\n" + rulesContent.slice(insertPoint + 3);
|
|
985
1418
|
}
|
|
986
1419
|
}
|
|
987
|
-
await
|
|
988
|
-
console.log(
|
|
1420
|
+
await import_promises10.default.writeFile(cursorRulesPath, rulesContent, "utf-8");
|
|
1421
|
+
console.log(import_chalk11.default.dim(` Updated .cursorrules with skills discovery block`));
|
|
989
1422
|
} catch (e) {
|
|
990
1423
|
}
|
|
991
1424
|
} catch (e) {
|
|
992
|
-
console.log(
|
|
1425
|
+
console.log(import_chalk11.default.yellow(` \u26A0 Skills provisioning skipped: ${e.message}`));
|
|
993
1426
|
}
|
|
994
1427
|
try {
|
|
995
|
-
const logPath =
|
|
1428
|
+
const logPath = import_path10.default.join(process.cwd(), ".rigstate", "logs", "last_execution.json");
|
|
996
1429
|
try {
|
|
997
|
-
const logContent = await
|
|
1430
|
+
const logContent = await import_promises10.default.readFile(logPath, "utf-8");
|
|
998
1431
|
const logData = JSON.parse(logContent);
|
|
999
1432
|
if (logData.task_summary) {
|
|
1000
|
-
await
|
|
1433
|
+
await import_axios7.default.post(`${apiUrl}/api/v1/execution-logs`, {
|
|
1001
1434
|
project_id: projectId,
|
|
1002
1435
|
...logData,
|
|
1003
1436
|
agent_role: process.env.RIGSTATE_MODE === "SUPERVISOR" ? "SUPERVISOR" : "WORKER"
|
|
1004
1437
|
}, {
|
|
1005
1438
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1006
1439
|
});
|
|
1007
|
-
await
|
|
1008
|
-
console.log(
|
|
1440
|
+
await import_promises10.default.unlink(logPath);
|
|
1441
|
+
console.log(import_chalk11.default.dim(`\u2714 Mission Report uploaded.`));
|
|
1009
1442
|
}
|
|
1010
1443
|
} catch (e) {
|
|
1011
1444
|
if (e.code !== "ENOENT") {
|
|
@@ -1013,14 +1446,14 @@ function createSyncCommand() {
|
|
|
1013
1446
|
}
|
|
1014
1447
|
} catch (e) {
|
|
1015
1448
|
}
|
|
1016
|
-
spinner.succeed(
|
|
1017
|
-
console.log(
|
|
1449
|
+
spinner.succeed(import_chalk11.default.green(`Synced ${roadmap.length} roadmap steps for project "${project}"`));
|
|
1450
|
+
console.log(import_chalk11.default.dim(`Local files updated: roadmap.json`));
|
|
1018
1451
|
const { runGuardianWatchdog: runGuardianWatchdog2 } = await Promise.resolve().then(() => (init_watchdog(), watchdog_exports));
|
|
1019
1452
|
const settings = response.data.data.settings || {};
|
|
1020
1453
|
await runGuardianWatchdog2(process.cwd(), settings, projectId);
|
|
1021
|
-
console.log(
|
|
1454
|
+
console.log(import_chalk11.default.bold("\n\u{1F4E1} Agent Bridge Heartbeat..."));
|
|
1022
1455
|
try {
|
|
1023
|
-
const bridgeResponse = await
|
|
1456
|
+
const bridgeResponse = await import_axios7.default.get(`${apiUrl}/api/v1/agent/bridge`, {
|
|
1024
1457
|
params: { project_id: projectId },
|
|
1025
1458
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1026
1459
|
});
|
|
@@ -1029,59 +1462,59 @@ function createSyncCommand() {
|
|
|
1029
1462
|
const pending = tasks.filter((t) => t.status === "PENDING");
|
|
1030
1463
|
const approved = tasks.filter((t) => t.status === "APPROVED");
|
|
1031
1464
|
if (pending.length > 0 || approved.length > 0) {
|
|
1032
|
-
console.log(
|
|
1033
|
-
console.log(
|
|
1465
|
+
console.log(import_chalk11.default.yellow(`\u26A0 Bridge Alert: ${pending.length} pending, ${approved.length} approved tasks found.`));
|
|
1466
|
+
console.log(import_chalk11.default.dim('Run "rigstate fix" to process these tasks or ensure your IDE MCP server is active.'));
|
|
1034
1467
|
} else {
|
|
1035
|
-
console.log(
|
|
1468
|
+
console.log(import_chalk11.default.green("\u2714 Heartbeat healthy. No pending bridge tasks."));
|
|
1036
1469
|
}
|
|
1037
1470
|
const pings = pending.filter((t) => t.proposal?.startsWith("ping"));
|
|
1038
1471
|
for (const ping of pings) {
|
|
1039
|
-
await
|
|
1472
|
+
await import_axios7.default.post(`${apiUrl}/api/v1/agent/bridge`, {
|
|
1040
1473
|
bridge_id: ping.id,
|
|
1041
1474
|
status: "COMPLETED",
|
|
1042
1475
|
summary: "Pong! CLI Sync Heartbeat confirmed."
|
|
1043
1476
|
}, {
|
|
1044
1477
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1045
1478
|
});
|
|
1046
|
-
console.log(
|
|
1479
|
+
console.log(import_chalk11.default.cyan(`\u{1F3D3} Pong! Acknowledged heartbeat signal [${ping.id}]`));
|
|
1047
1480
|
}
|
|
1048
1481
|
}
|
|
1049
1482
|
} catch (e) {
|
|
1050
|
-
console.log(
|
|
1483
|
+
console.log(import_chalk11.default.yellow(`\u26A0 Could not verify Bridge status: ${e.message}`));
|
|
1051
1484
|
}
|
|
1052
1485
|
if (options.project) {
|
|
1053
|
-
console.log(
|
|
1486
|
+
console.log(import_chalk11.default.blue(`Project context saved. Future commands will use this project.`));
|
|
1054
1487
|
}
|
|
1055
1488
|
try {
|
|
1056
|
-
const migrationDir =
|
|
1057
|
-
const files = await
|
|
1489
|
+
const migrationDir = import_path10.default.join(process.cwd(), "supabase", "migrations");
|
|
1490
|
+
const files = await import_promises10.default.readdir(migrationDir);
|
|
1058
1491
|
const sqlFiles = files.filter((f) => f.endsWith(".sql")).sort();
|
|
1059
1492
|
if (sqlFiles.length > 0) {
|
|
1060
1493
|
const latestMigration = sqlFiles[sqlFiles.length - 1];
|
|
1061
|
-
console.log(
|
|
1494
|
+
console.log(import_chalk11.default.dim(`
|
|
1062
1495
|
\u{1F6E1} Migration Guard:`));
|
|
1063
|
-
console.log(
|
|
1064
|
-
console.log(
|
|
1496
|
+
console.log(import_chalk11.default.dim(` Latest Local: ${latestMigration}`));
|
|
1497
|
+
console.log(import_chalk11.default.yellow(` \u26A0 Ensure DB schema matches this version. CLI cannot verify Remote RLS policies directly.`));
|
|
1065
1498
|
}
|
|
1066
1499
|
} catch (e) {
|
|
1067
1500
|
}
|
|
1068
1501
|
try {
|
|
1069
|
-
const vaultResponse = await
|
|
1502
|
+
const vaultResponse = await import_axios7.default.post(
|
|
1070
1503
|
`${apiUrl}/api/v1/vault/sync`,
|
|
1071
1504
|
{ project_id: projectId },
|
|
1072
1505
|
{ headers: { Authorization: `Bearer ${apiKey}` } }
|
|
1073
1506
|
);
|
|
1074
1507
|
if (vaultResponse.data.success) {
|
|
1075
1508
|
const vaultContent = vaultResponse.data.data.content || "";
|
|
1076
|
-
const localEnvPath =
|
|
1509
|
+
const localEnvPath = import_path10.default.join(process.cwd(), ".env.local");
|
|
1077
1510
|
let localContent = "";
|
|
1078
1511
|
try {
|
|
1079
|
-
localContent = await
|
|
1512
|
+
localContent = await import_promises10.default.readFile(localEnvPath, "utf-8");
|
|
1080
1513
|
} catch (e) {
|
|
1081
1514
|
}
|
|
1082
1515
|
if (vaultContent.trim() !== localContent.trim()) {
|
|
1083
|
-
console.log(
|
|
1084
|
-
console.log(
|
|
1516
|
+
console.log(import_chalk11.default.bold("\n\u{1F510} Sovereign Foundation (Vault):"));
|
|
1517
|
+
console.log(import_chalk11.default.yellow(" Status: Drift Detected / Update Available"));
|
|
1085
1518
|
const { syncVault } = await import("inquirer").then((m) => m.default.prompt([{
|
|
1086
1519
|
type: "confirm",
|
|
1087
1520
|
name: "syncVault",
|
|
@@ -1089,25 +1522,25 @@ function createSyncCommand() {
|
|
|
1089
1522
|
default: false
|
|
1090
1523
|
}]));
|
|
1091
1524
|
if (syncVault) {
|
|
1092
|
-
await
|
|
1093
|
-
console.log(
|
|
1525
|
+
await import_promises10.default.writeFile(localEnvPath, vaultContent, "utf-8");
|
|
1526
|
+
console.log(import_chalk11.default.green(" \u2705 .env.local synchronized with Vault."));
|
|
1094
1527
|
} else {
|
|
1095
|
-
console.log(
|
|
1528
|
+
console.log(import_chalk11.default.dim(" Skipped vault sync."));
|
|
1096
1529
|
}
|
|
1097
1530
|
} else {
|
|
1098
|
-
console.log(
|
|
1531
|
+
console.log(import_chalk11.default.dim("\n\u{1F510} Sovereign Foundation: Synced."));
|
|
1099
1532
|
}
|
|
1100
1533
|
}
|
|
1101
1534
|
} catch (e) {
|
|
1102
1535
|
}
|
|
1103
|
-
console.log(
|
|
1536
|
+
console.log(import_chalk11.default.dim("\n\u{1F6E1}\uFE0F System Integrity Check..."));
|
|
1104
1537
|
await checkSystemIntegrity(apiUrl, apiKey, projectId);
|
|
1105
1538
|
} catch (error) {
|
|
1106
|
-
if (
|
|
1539
|
+
if (import_axios7.default.isAxiosError(error)) {
|
|
1107
1540
|
const message = error.response?.data?.error || error.message;
|
|
1108
|
-
spinner.fail(
|
|
1541
|
+
spinner.fail(import_chalk11.default.red(`Sync failed: ${message}`));
|
|
1109
1542
|
} else {
|
|
1110
|
-
spinner.fail(
|
|
1543
|
+
spinner.fail(import_chalk11.default.red("Sync failed: " + (error.message || "Unknown error")));
|
|
1111
1544
|
}
|
|
1112
1545
|
}
|
|
1113
1546
|
});
|
|
@@ -1115,7 +1548,7 @@ function createSyncCommand() {
|
|
|
1115
1548
|
}
|
|
1116
1549
|
async function checkSystemIntegrity(apiUrl, apiKey, projectId) {
|
|
1117
1550
|
try {
|
|
1118
|
-
const response = await
|
|
1551
|
+
const response = await import_axios7.default.get(`${apiUrl}/api/v1/system/integrity`, {
|
|
1119
1552
|
params: { project_id: projectId },
|
|
1120
1553
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1121
1554
|
});
|
|
@@ -1123,57 +1556,57 @@ async function checkSystemIntegrity(apiUrl, apiKey, projectId) {
|
|
|
1123
1556
|
const { migrations, rls, guardian_violations } = response.data.data;
|
|
1124
1557
|
if (migrations) {
|
|
1125
1558
|
if (migrations.in_sync) {
|
|
1126
|
-
console.log(
|
|
1559
|
+
console.log(import_chalk11.default.green(` \u2705 Migrations synced (${migrations.count} versions)`));
|
|
1127
1560
|
} else {
|
|
1128
|
-
console.log(
|
|
1561
|
+
console.log(import_chalk11.default.red(` \u{1F6D1} CRITICAL: DB Schema out of sync! ${migrations.missing?.length || 0} migrations not applied.`));
|
|
1129
1562
|
if (migrations.missing?.length > 0) {
|
|
1130
|
-
console.log(
|
|
1563
|
+
console.log(import_chalk11.default.dim(` Missing: ${migrations.missing.slice(0, 3).join(", ")}${migrations.missing.length > 3 ? "..." : ""}`));
|
|
1131
1564
|
}
|
|
1132
|
-
console.log(
|
|
1565
|
+
console.log(import_chalk11.default.yellow(` Run 'supabase db push' or apply migrations immediately.`));
|
|
1133
1566
|
}
|
|
1134
1567
|
}
|
|
1135
1568
|
if (rls) {
|
|
1136
1569
|
if (rls.all_secured) {
|
|
1137
|
-
console.log(
|
|
1570
|
+
console.log(import_chalk11.default.green(` \u2705 RLS Audit Passed (${rls.table_count} tables secured)`));
|
|
1138
1571
|
} else {
|
|
1139
|
-
console.log(
|
|
1572
|
+
console.log(import_chalk11.default.red(` \u{1F6D1} CRITICAL: Security Vulnerability! ${rls.unsecured?.length || 0} tables have RLS disabled.`));
|
|
1140
1573
|
rls.unsecured?.forEach((table) => {
|
|
1141
|
-
console.log(
|
|
1574
|
+
console.log(import_chalk11.default.red(` - ${table}`));
|
|
1142
1575
|
});
|
|
1143
|
-
console.log(
|
|
1576
|
+
console.log(import_chalk11.default.yellow(' Enable RLS immediately: ALTER TABLE "table" ENABLE ROW LEVEL SECURITY;'));
|
|
1144
1577
|
}
|
|
1145
1578
|
}
|
|
1146
1579
|
if (guardian_violations) {
|
|
1147
1580
|
if (guardian_violations.count === 0) {
|
|
1148
|
-
console.log(
|
|
1581
|
+
console.log(import_chalk11.default.green(" \u2705 Guardian: No active violations"));
|
|
1149
1582
|
} else {
|
|
1150
|
-
console.log(
|
|
1151
|
-
console.log(
|
|
1583
|
+
console.log(import_chalk11.default.yellow(` \u26A0\uFE0F Guardian: ${guardian_violations.count} active violations`));
|
|
1584
|
+
console.log(import_chalk11.default.dim(' Run "rigstate check" for details.'));
|
|
1152
1585
|
}
|
|
1153
1586
|
}
|
|
1154
1587
|
}
|
|
1155
1588
|
} catch (e) {
|
|
1156
|
-
console.log(
|
|
1589
|
+
console.log(import_chalk11.default.dim(" (System integrity check skipped - API endpoint not available)"));
|
|
1157
1590
|
}
|
|
1158
1591
|
}
|
|
1159
1592
|
|
|
1160
1593
|
// src/commands/init.ts
|
|
1161
1594
|
init_cjs_shims();
|
|
1162
|
-
var
|
|
1163
|
-
var
|
|
1164
|
-
var
|
|
1165
|
-
var
|
|
1166
|
-
var
|
|
1595
|
+
var import_commander9 = require("commander");
|
|
1596
|
+
var import_chalk12 = __toESM(require("chalk"), 1);
|
|
1597
|
+
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
1598
|
+
var import_path12 = __toESM(require("path"), 1);
|
|
1599
|
+
var import_ora6 = __toESM(require("ora"), 1);
|
|
1167
1600
|
var import_child_process = require("child_process");
|
|
1168
1601
|
|
|
1169
1602
|
// src/utils/manifest.ts
|
|
1170
1603
|
init_cjs_shims();
|
|
1171
|
-
var
|
|
1172
|
-
var
|
|
1604
|
+
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
1605
|
+
var import_path11 = __toESM(require("path"), 1);
|
|
1173
1606
|
async function loadManifest() {
|
|
1174
1607
|
try {
|
|
1175
|
-
const manifestPath =
|
|
1176
|
-
const content = await
|
|
1608
|
+
const manifestPath = import_path11.default.join(process.cwd(), ".rigstate");
|
|
1609
|
+
const content = await import_promises11.default.readFile(manifestPath, "utf-8");
|
|
1177
1610
|
return JSON.parse(content);
|
|
1178
1611
|
} catch {
|
|
1179
1612
|
return null;
|
|
@@ -1182,15 +1615,15 @@ async function loadManifest() {
|
|
|
1182
1615
|
|
|
1183
1616
|
// src/commands/init.ts
|
|
1184
1617
|
init_config();
|
|
1185
|
-
var
|
|
1618
|
+
var import_axios8 = __toESM(require("axios"), 1);
|
|
1186
1619
|
function createInitCommand() {
|
|
1187
|
-
return new
|
|
1188
|
-
const spinner = (0,
|
|
1620
|
+
return new import_commander9.Command("init").description("Initialize or link a Rigstate project (interactive mode available)").argument("[project-id]", "ID of the project to link (optional, prompts if not provided)").option("-f, --force", "Overwrite existing .cursorrules file").option("--rules-only", "Only regenerate .cursorrules without interactive setup").action(async (projectIdArg, options) => {
|
|
1621
|
+
const spinner = (0, import_ora6.default)("Initializing Rigstate project...").start();
|
|
1189
1622
|
let apiKey;
|
|
1190
1623
|
try {
|
|
1191
1624
|
apiKey = getApiKey();
|
|
1192
1625
|
} catch (e) {
|
|
1193
|
-
spinner.fail(
|
|
1626
|
+
spinner.fail(import_chalk12.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
1194
1627
|
return;
|
|
1195
1628
|
}
|
|
1196
1629
|
const apiUrl = getApiUrl();
|
|
@@ -1212,7 +1645,7 @@ function createInitCommand() {
|
|
|
1212
1645
|
spinner.start("Fetching your projects...");
|
|
1213
1646
|
let projects = [];
|
|
1214
1647
|
try {
|
|
1215
|
-
const projectsResponse = await
|
|
1648
|
+
const projectsResponse = await import_axios8.default.get(`${apiUrl}/api/v1/projects`, {
|
|
1216
1649
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1217
1650
|
});
|
|
1218
1651
|
if (projectsResponse.data.success) {
|
|
@@ -1264,7 +1697,7 @@ function createInitCommand() {
|
|
|
1264
1697
|
spinner.start("Fetching organizations...");
|
|
1265
1698
|
let orgs = [];
|
|
1266
1699
|
try {
|
|
1267
|
-
const orgsResponse = await
|
|
1700
|
+
const orgsResponse = await import_axios8.default.get(`${apiUrl}/api/v1/organizations`, {
|
|
1268
1701
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1269
1702
|
});
|
|
1270
1703
|
orgs = orgsResponse.data.data?.organizations || [];
|
|
@@ -1287,25 +1720,25 @@ function createInitCommand() {
|
|
|
1287
1720
|
selectedOrgId = orgId;
|
|
1288
1721
|
}
|
|
1289
1722
|
if (!selectedOrgId) {
|
|
1290
|
-
console.log(
|
|
1723
|
+
console.log(import_chalk12.default.yellow("No organization available. Please create the project via the Rigstate dashboard."));
|
|
1291
1724
|
return;
|
|
1292
1725
|
}
|
|
1293
1726
|
spinner.start("Creating new project...");
|
|
1294
1727
|
try {
|
|
1295
|
-
const createResponse = await
|
|
1728
|
+
const createResponse = await import_axios8.default.post(`${apiUrl}/api/v1/projects`, {
|
|
1296
1729
|
name: newName,
|
|
1297
1730
|
organization_id: selectedOrgId
|
|
1298
1731
|
}, {
|
|
1299
1732
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1300
1733
|
});
|
|
1301
1734
|
if (!createResponse.data.success) {
|
|
1302
|
-
spinner.fail(
|
|
1735
|
+
spinner.fail(import_chalk12.default.red("Failed to create project: " + createResponse.data.error));
|
|
1303
1736
|
return;
|
|
1304
1737
|
}
|
|
1305
1738
|
projectId = createResponse.data.data.project.id;
|
|
1306
|
-
spinner.succeed(
|
|
1739
|
+
spinner.succeed(import_chalk12.default.green(`Created new project: ${newName}`));
|
|
1307
1740
|
} catch (e) {
|
|
1308
|
-
spinner.fail(
|
|
1741
|
+
spinner.fail(import_chalk12.default.red("Project creation API not available. Please create via dashboard."));
|
|
1309
1742
|
return;
|
|
1310
1743
|
}
|
|
1311
1744
|
} else {
|
|
@@ -1315,35 +1748,35 @@ function createInitCommand() {
|
|
|
1315
1748
|
spinner.start(`Linking to project ID: ${projectId}...`);
|
|
1316
1749
|
}
|
|
1317
1750
|
setProjectId(projectId);
|
|
1318
|
-
const manifestPath =
|
|
1751
|
+
const manifestPath = import_path12.default.join(process.cwd(), ".rigstate");
|
|
1319
1752
|
const manifestContent = {
|
|
1320
1753
|
project_id: projectId,
|
|
1321
1754
|
last_linked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1322
1755
|
api_url: apiUrl
|
|
1323
1756
|
};
|
|
1324
|
-
await
|
|
1757
|
+
await import_promises12.default.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), "utf-8");
|
|
1325
1758
|
try {
|
|
1326
|
-
await
|
|
1759
|
+
await import_promises12.default.access(".git");
|
|
1327
1760
|
} catch {
|
|
1328
1761
|
spinner.text = "Initializing git repository...";
|
|
1329
1762
|
(0, import_child_process.execSync)("git init", { stdio: "ignore" });
|
|
1330
1763
|
}
|
|
1331
|
-
spinner.succeed(
|
|
1764
|
+
spinner.succeed(import_chalk12.default.green(`\u2705 Linked to project: ${projectId}`));
|
|
1332
1765
|
await generateRules(apiUrl, apiKey, projectId, options.force, spinner);
|
|
1333
1766
|
console.log("");
|
|
1334
|
-
console.log(
|
|
1335
|
-
console.log(
|
|
1336
|
-
console.log(
|
|
1337
|
-
console.log(
|
|
1767
|
+
console.log(import_chalk12.default.blue("Next steps:"));
|
|
1768
|
+
console.log(import_chalk12.default.dim(" rigstate sync - Sync roadmap and context"));
|
|
1769
|
+
console.log(import_chalk12.default.dim(" rigstate watch - Start development loop"));
|
|
1770
|
+
console.log(import_chalk12.default.dim(" rigstate focus - Get current task"));
|
|
1338
1771
|
} catch (e) {
|
|
1339
|
-
spinner.fail(
|
|
1772
|
+
spinner.fail(import_chalk12.default.red("Initialization failed: " + e.message));
|
|
1340
1773
|
}
|
|
1341
1774
|
});
|
|
1342
1775
|
}
|
|
1343
1776
|
async function generateRules(apiUrl, apiKey, projectId, force, spinner) {
|
|
1344
1777
|
spinner.start("Generating AI rules (MDC + AGENTS.md)...");
|
|
1345
1778
|
try {
|
|
1346
|
-
const response = await
|
|
1779
|
+
const response = await import_axios8.default.post(`${apiUrl}/api/v1/rules/generate`, {
|
|
1347
1780
|
project_id: projectId
|
|
1348
1781
|
}, {
|
|
1349
1782
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
@@ -1351,67 +1784,67 @@ async function generateRules(apiUrl, apiKey, projectId, force, spinner) {
|
|
|
1351
1784
|
if (response.data.success || response.data.files) {
|
|
1352
1785
|
const files = response.data.files || [];
|
|
1353
1786
|
if (files.length === 0 && response.data.rules) {
|
|
1354
|
-
const rulesPath =
|
|
1355
|
-
await
|
|
1356
|
-
spinner.succeed(
|
|
1787
|
+
const rulesPath = import_path12.default.join(process.cwd(), ".cursorrules");
|
|
1788
|
+
await import_promises12.default.writeFile(rulesPath, response.data.rules, "utf-8");
|
|
1789
|
+
spinner.succeed(import_chalk12.default.green("\u2714 Generated .cursorrules (legacy mode)"));
|
|
1357
1790
|
return;
|
|
1358
1791
|
}
|
|
1359
1792
|
for (const file of files) {
|
|
1360
|
-
const targetPath =
|
|
1361
|
-
const targetDir =
|
|
1362
|
-
await
|
|
1793
|
+
const targetPath = import_path12.default.join(process.cwd(), file.path);
|
|
1794
|
+
const targetDir = import_path12.default.dirname(targetPath);
|
|
1795
|
+
await import_promises12.default.mkdir(targetDir, { recursive: true });
|
|
1363
1796
|
try {
|
|
1364
|
-
await
|
|
1797
|
+
await import_promises12.default.access(targetPath);
|
|
1365
1798
|
if (!force && !file.path.startsWith(".cursor/rules/")) {
|
|
1366
|
-
console.log(
|
|
1799
|
+
console.log(import_chalk12.default.dim(` ${file.path} already exists. Skipping.`));
|
|
1367
1800
|
continue;
|
|
1368
1801
|
}
|
|
1369
1802
|
} catch {
|
|
1370
1803
|
}
|
|
1371
|
-
await
|
|
1804
|
+
await import_promises12.default.writeFile(targetPath, file.content, "utf-8");
|
|
1372
1805
|
}
|
|
1373
1806
|
if (files.length > 0) {
|
|
1374
|
-
const legacyPath =
|
|
1807
|
+
const legacyPath = import_path12.default.join(process.cwd(), ".cursorrules");
|
|
1375
1808
|
try {
|
|
1376
|
-
const stats = await
|
|
1809
|
+
const stats = await import_promises12.default.stat(legacyPath);
|
|
1377
1810
|
if (stats.isFile()) {
|
|
1378
|
-
await
|
|
1379
|
-
console.log(
|
|
1811
|
+
await import_promises12.default.rename(legacyPath, `${legacyPath}.bak`);
|
|
1812
|
+
console.log(import_chalk12.default.dim(" Moved legacy .cursorrules to .cursorrules.bak"));
|
|
1380
1813
|
}
|
|
1381
1814
|
} catch (e) {
|
|
1382
1815
|
}
|
|
1383
1816
|
}
|
|
1384
|
-
spinner.succeed(
|
|
1817
|
+
spinner.succeed(import_chalk12.default.green(`\u2714 Generated ${files.length} rule files (v${response.data.version || "3.0"})`));
|
|
1385
1818
|
} else {
|
|
1386
|
-
spinner.info(
|
|
1819
|
+
spinner.info(import_chalk12.default.dim(" Rules generation skipped (API response invalid)"));
|
|
1387
1820
|
}
|
|
1388
1821
|
} catch (e) {
|
|
1389
|
-
spinner.info(
|
|
1822
|
+
spinner.info(import_chalk12.default.dim(` Rules generation failed: ${e.message}`));
|
|
1390
1823
|
}
|
|
1391
1824
|
}
|
|
1392
1825
|
|
|
1393
1826
|
// src/commands/check.ts
|
|
1394
1827
|
init_cjs_shims();
|
|
1395
|
-
var
|
|
1396
|
-
var
|
|
1397
|
-
var
|
|
1398
|
-
var
|
|
1828
|
+
var import_commander10 = require("commander");
|
|
1829
|
+
var import_chalk14 = __toESM(require("chalk"), 1);
|
|
1830
|
+
var import_ora7 = __toESM(require("ora"), 1);
|
|
1831
|
+
var import_axios9 = __toESM(require("axios"), 1);
|
|
1399
1832
|
var import_glob3 = require("glob");
|
|
1400
|
-
var
|
|
1401
|
-
var
|
|
1833
|
+
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
1834
|
+
var import_path14 = __toESM(require("path"), 1);
|
|
1402
1835
|
var import_child_process2 = require("child_process");
|
|
1403
1836
|
init_config();
|
|
1404
1837
|
|
|
1405
1838
|
// src/utils/rule-engine.ts
|
|
1406
1839
|
init_cjs_shims();
|
|
1407
|
-
var
|
|
1408
|
-
var
|
|
1409
|
-
var
|
|
1840
|
+
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
1841
|
+
var import_path13 = __toESM(require("path"), 1);
|
|
1842
|
+
var import_chalk13 = __toESM(require("chalk"), 1);
|
|
1410
1843
|
async function checkFile(filePath, rules, rootPath) {
|
|
1411
1844
|
const violations = [];
|
|
1412
|
-
const relativePath =
|
|
1845
|
+
const relativePath = import_path13.default.relative(rootPath, filePath);
|
|
1413
1846
|
try {
|
|
1414
|
-
const content = await
|
|
1847
|
+
const content = await import_promises13.default.readFile(filePath, "utf-8");
|
|
1415
1848
|
const lines = content.split("\n");
|
|
1416
1849
|
for (const rule of rules) {
|
|
1417
1850
|
const ruleViolations = await evaluateRule(rule, content, lines, relativePath);
|
|
@@ -1502,7 +1935,7 @@ async function evaluateRule(rule, content, lines, filePath) {
|
|
|
1502
1935
|
case "NAMING_CONVENTION": {
|
|
1503
1936
|
const value = rule.value;
|
|
1504
1937
|
const pattern = new RegExp(value.pattern);
|
|
1505
|
-
const fileName =
|
|
1938
|
+
const fileName = import_path13.default.basename(filePath);
|
|
1506
1939
|
if (filePath.includes(value.context) && !pattern.test(fileName)) {
|
|
1507
1940
|
violations.push({
|
|
1508
1941
|
file: filePath,
|
|
@@ -1561,12 +1994,12 @@ function checkFunctionLines(content, lines, filePath, rule, limit) {
|
|
|
1561
1994
|
}
|
|
1562
1995
|
function formatViolations(violations) {
|
|
1563
1996
|
for (const v of violations) {
|
|
1564
|
-
const severityColor = v.severity === "critical" ?
|
|
1565
|
-
const lineInfo = v.line ?
|
|
1997
|
+
const severityColor = v.severity === "critical" ? import_chalk13.default.red : v.severity === "warning" ? import_chalk13.default.yellow : import_chalk13.default.blue;
|
|
1998
|
+
const lineInfo = v.line ? import_chalk13.default.dim(`:${v.line}`) : "";
|
|
1566
1999
|
console.log(` ${severityColor(`[${v.severity.toUpperCase()}]`)} ${v.file}${lineInfo}`);
|
|
1567
2000
|
console.log(` ${v.message}`);
|
|
1568
2001
|
if (v.details) {
|
|
1569
|
-
console.log(` ${
|
|
2002
|
+
console.log(` ${import_chalk13.default.dim(v.details)}`);
|
|
1570
2003
|
}
|
|
1571
2004
|
}
|
|
1572
2005
|
}
|
|
@@ -1595,8 +2028,8 @@ var CACHE_FILE2 = ".rigstate/rules-cache.json";
|
|
|
1595
2028
|
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1596
2029
|
var CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
1597
2030
|
function createCheckCommand() {
|
|
1598
|
-
return new
|
|
1599
|
-
const spinner = (0,
|
|
2031
|
+
return new import_commander10.Command("check").description("Validate code against Guardian architectural rules").argument("[path]", "Directory or file to check", ".").option("--project <id>", "Project ID (or use .rigstate manifest)").option("--strict [level]", 'Exit 1 on violations. Level: "all" (default) or "critical"').option("--staged", "Only check git staged files (for pre-commit hooks)").option("--json", "Output results as JSON").option("--no-cache", "Skip rule cache and fetch fresh from API").action(async (targetPath, options) => {
|
|
2032
|
+
const spinner = (0, import_ora7.default)();
|
|
1600
2033
|
try {
|
|
1601
2034
|
let projectId = options.project;
|
|
1602
2035
|
let apiUrl = getApiUrl();
|
|
@@ -1611,15 +2044,15 @@ function createCheckCommand() {
|
|
|
1611
2044
|
projectId = getProjectId();
|
|
1612
2045
|
}
|
|
1613
2046
|
if (!projectId) {
|
|
1614
|
-
console.log(
|
|
1615
|
-
console.log(
|
|
2047
|
+
console.log(import_chalk14.default.red("\u274C No project context found."));
|
|
2048
|
+
console.log(import_chalk14.default.dim(' Run "rigstate link" or pass --project <id>'));
|
|
1616
2049
|
process.exit(2);
|
|
1617
2050
|
}
|
|
1618
2051
|
let apiKey;
|
|
1619
2052
|
try {
|
|
1620
2053
|
apiKey = getApiKey();
|
|
1621
2054
|
} catch {
|
|
1622
|
-
console.log(
|
|
2055
|
+
console.log(import_chalk14.default.red('\u274C Not authenticated. Run "rigstate login" first.'));
|
|
1623
2056
|
process.exit(2);
|
|
1624
2057
|
}
|
|
1625
2058
|
spinner.start("Fetching Guardian rules...");
|
|
@@ -1632,7 +2065,7 @@ function createCheckCommand() {
|
|
|
1632
2065
|
settings = cached.settings;
|
|
1633
2066
|
spinner.text = "Using cached rules...";
|
|
1634
2067
|
} else {
|
|
1635
|
-
const response = await
|
|
2068
|
+
const response = await import_axios9.default.get(`${apiUrl}/api/v1/guardian/rules`, {
|
|
1636
2069
|
params: { project_id: projectId },
|
|
1637
2070
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
1638
2071
|
timeout: 1e4
|
|
@@ -1647,17 +2080,17 @@ function createCheckCommand() {
|
|
|
1647
2080
|
} catch (apiError) {
|
|
1648
2081
|
const cached = await loadCachedRules(projectId);
|
|
1649
2082
|
if (cached && !isStale(cached.timestamp, CACHE_MAX_AGE_MS)) {
|
|
1650
|
-
spinner.warn(
|
|
2083
|
+
spinner.warn(import_chalk14.default.yellow("Using cached rules (API unavailable)"));
|
|
1651
2084
|
rules = cached.rules;
|
|
1652
2085
|
settings = cached.settings;
|
|
1653
2086
|
} else {
|
|
1654
|
-
spinner.fail(
|
|
1655
|
-
console.log(
|
|
2087
|
+
spinner.fail(import_chalk14.default.red("Failed to fetch rules and no valid cache"));
|
|
2088
|
+
console.log(import_chalk14.default.dim(` Error: ${apiError.message}`));
|
|
1656
2089
|
process.exit(2);
|
|
1657
2090
|
}
|
|
1658
2091
|
}
|
|
1659
2092
|
spinner.succeed(`Loaded ${rules.length} Guardian rules`);
|
|
1660
|
-
const scanPath =
|
|
2093
|
+
const scanPath = import_path14.default.resolve(process.cwd(), targetPath);
|
|
1661
2094
|
let filesToCheck;
|
|
1662
2095
|
if (options.staged) {
|
|
1663
2096
|
spinner.start("Getting staged files...");
|
|
@@ -1666,14 +2099,14 @@ function createCheckCommand() {
|
|
|
1666
2099
|
encoding: "utf-8",
|
|
1667
2100
|
cwd: process.cwd()
|
|
1668
2101
|
});
|
|
1669
|
-
filesToCheck = stagedOutput.split("\n").filter((f) => f.trim()).filter((f) => isCodeFile2(f)).map((f) =>
|
|
2102
|
+
filesToCheck = stagedOutput.split("\n").filter((f) => f.trim()).filter((f) => isCodeFile2(f)).map((f) => import_path14.default.resolve(process.cwd(), f));
|
|
1670
2103
|
} catch {
|
|
1671
2104
|
spinner.fail("Not a git repository or no staged files");
|
|
1672
2105
|
process.exit(2);
|
|
1673
2106
|
}
|
|
1674
2107
|
} else {
|
|
1675
|
-
spinner.start(`Scanning ${
|
|
1676
|
-
const pattern =
|
|
2108
|
+
spinner.start(`Scanning ${import_chalk14.default.cyan(targetPath)}...`);
|
|
2109
|
+
const pattern = import_path14.default.join(scanPath, "**/*");
|
|
1677
2110
|
const allFiles = await (0, import_glob3.glob)(pattern, {
|
|
1678
2111
|
nodir: true,
|
|
1679
2112
|
dot: false,
|
|
@@ -1689,7 +2122,7 @@ function createCheckCommand() {
|
|
|
1689
2122
|
filesToCheck = allFiles.filter((f) => isCodeFile2(f));
|
|
1690
2123
|
}
|
|
1691
2124
|
if (filesToCheck.length === 0) {
|
|
1692
|
-
spinner.warn(
|
|
2125
|
+
spinner.warn(import_chalk14.default.yellow("No code files found to check."));
|
|
1693
2126
|
outputResults([], !!options.json);
|
|
1694
2127
|
process.exit(0);
|
|
1695
2128
|
}
|
|
@@ -1698,7 +2131,7 @@ function createCheckCommand() {
|
|
|
1698
2131
|
const results = [];
|
|
1699
2132
|
for (let i = 0; i < filesToCheck.length; i++) {
|
|
1700
2133
|
const file = filesToCheck[i];
|
|
1701
|
-
spinner.text = `Checking ${i + 1}/${filesToCheck.length}: ${
|
|
2134
|
+
spinner.text = `Checking ${i + 1}/${filesToCheck.length}: ${import_path14.default.basename(file)}`;
|
|
1702
2135
|
const result = await checkFile(file, rules, process.cwd());
|
|
1703
2136
|
results.push(result);
|
|
1704
2137
|
}
|
|
@@ -1708,47 +2141,47 @@ function createCheckCommand() {
|
|
|
1708
2141
|
outputResults(results, true);
|
|
1709
2142
|
} else {
|
|
1710
2143
|
outputResults(results, false);
|
|
1711
|
-
console.log("\n" +
|
|
1712
|
-
console.log(
|
|
1713
|
-
console.log(`Files checked: ${
|
|
1714
|
-
console.log(`Total violations: ${summary.totalViolations > 0 ?
|
|
2144
|
+
console.log("\n" + import_chalk14.default.bold("\u{1F4CA} Summary"));
|
|
2145
|
+
console.log(import_chalk14.default.dim("\u2500".repeat(50)));
|
|
2146
|
+
console.log(`Files checked: ${import_chalk14.default.cyan(summary.totalFiles)}`);
|
|
2147
|
+
console.log(`Total violations: ${summary.totalViolations > 0 ? import_chalk14.default.red(summary.totalViolations) : import_chalk14.default.green(0)}`);
|
|
1715
2148
|
if (summary.totalViolations > 0) {
|
|
1716
|
-
console.log(` ${
|
|
1717
|
-
console.log(` ${
|
|
1718
|
-
console.log(` ${
|
|
2149
|
+
console.log(` ${import_chalk14.default.red("Critical:")} ${summary.criticalCount}`);
|
|
2150
|
+
console.log(` ${import_chalk14.default.yellow("Warning:")} ${summary.warningCount}`);
|
|
2151
|
+
console.log(` ${import_chalk14.default.blue("Info:")} ${summary.infoCount}`);
|
|
1719
2152
|
}
|
|
1720
|
-
console.log(
|
|
2153
|
+
console.log(import_chalk14.default.dim("\u2500".repeat(50)));
|
|
1721
2154
|
}
|
|
1722
2155
|
if (options.strict !== void 0) {
|
|
1723
2156
|
const strictLevel = typeof options.strict === "string" ? options.strict : "all";
|
|
1724
2157
|
if (strictLevel === "critical" && summary.criticalCount > 0) {
|
|
1725
|
-
console.log(
|
|
2158
|
+
console.log(import_chalk14.default.red("\n\u274C Check failed: Critical violations found"));
|
|
1726
2159
|
process.exit(1);
|
|
1727
2160
|
} else if (strictLevel === "all" && summary.totalViolations > 0) {
|
|
1728
|
-
console.log(
|
|
2161
|
+
console.log(import_chalk14.default.red("\n\u274C Check failed: Violations found"));
|
|
1729
2162
|
process.exit(1);
|
|
1730
2163
|
}
|
|
1731
2164
|
}
|
|
1732
2165
|
if (summary.totalViolations === 0) {
|
|
1733
|
-
console.log(
|
|
2166
|
+
console.log(import_chalk14.default.green("\n\u2705 All checks passed!"));
|
|
1734
2167
|
}
|
|
1735
2168
|
process.exit(0);
|
|
1736
2169
|
} catch (error) {
|
|
1737
|
-
spinner.fail(
|
|
1738
|
-
console.error(
|
|
2170
|
+
spinner.fail(import_chalk14.default.red("Check failed"));
|
|
2171
|
+
console.error(import_chalk14.default.red("Error:"), error.message);
|
|
1739
2172
|
process.exit(2);
|
|
1740
2173
|
}
|
|
1741
2174
|
});
|
|
1742
2175
|
}
|
|
1743
2176
|
function isCodeFile2(filePath) {
|
|
1744
2177
|
const codeExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
1745
|
-
const ext =
|
|
2178
|
+
const ext = import_path14.default.extname(filePath).toLowerCase();
|
|
1746
2179
|
return codeExtensions.includes(ext);
|
|
1747
2180
|
}
|
|
1748
2181
|
async function loadCachedRules(projectId) {
|
|
1749
2182
|
try {
|
|
1750
|
-
const cachePath =
|
|
1751
|
-
const content = await
|
|
2183
|
+
const cachePath = import_path14.default.join(process.cwd(), CACHE_FILE2);
|
|
2184
|
+
const content = await import_promises14.default.readFile(cachePath, "utf-8");
|
|
1752
2185
|
const cached = JSON.parse(content);
|
|
1753
2186
|
if (cached.projectId !== projectId) {
|
|
1754
2187
|
return null;
|
|
@@ -1760,16 +2193,16 @@ async function loadCachedRules(projectId) {
|
|
|
1760
2193
|
}
|
|
1761
2194
|
async function saveCachedRules(projectId, rules, settings) {
|
|
1762
2195
|
try {
|
|
1763
|
-
const cacheDir =
|
|
1764
|
-
await
|
|
2196
|
+
const cacheDir = import_path14.default.join(process.cwd(), ".rigstate");
|
|
2197
|
+
await import_promises14.default.mkdir(cacheDir, { recursive: true });
|
|
1765
2198
|
const cached = {
|
|
1766
2199
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1767
2200
|
projectId,
|
|
1768
2201
|
rules,
|
|
1769
2202
|
settings
|
|
1770
2203
|
};
|
|
1771
|
-
await
|
|
1772
|
-
|
|
2204
|
+
await import_promises14.default.writeFile(
|
|
2205
|
+
import_path14.default.join(cacheDir, "rules-cache.json"),
|
|
1773
2206
|
JSON.stringify(cached, null, 2)
|
|
1774
2207
|
);
|
|
1775
2208
|
} catch {
|
|
@@ -1782,212 +2215,111 @@ function isStale(timestamp, maxAge) {
|
|
|
1782
2215
|
function outputResults(results, json) {
|
|
1783
2216
|
if (json) {
|
|
1784
2217
|
console.log(JSON.stringify({
|
|
1785
|
-
results,
|
|
1786
|
-
summary: summarizeResults(results)
|
|
1787
|
-
}, null, 2));
|
|
1788
|
-
return;
|
|
1789
|
-
}
|
|
1790
|
-
const hasViolations = results.some((r) => r.violations.length > 0);
|
|
1791
|
-
if (!hasViolations) {
|
|
1792
|
-
return;
|
|
1793
|
-
}
|
|
1794
|
-
console.log("\n" +
|
|
1795
|
-
console.log(
|
|
1796
|
-
for (const result of results) {
|
|
1797
|
-
if (result.violations.length > 0) {
|
|
1798
|
-
formatViolations(result.violations);
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
|
|
1803
|
-
// src/commands/hooks.ts
|
|
1804
|
-
init_cjs_shims();
|
|
1805
|
-
var import_commander8 = require("commander");
|
|
1806
|
-
var import_chalk12 = __toESM(require("chalk"), 1);
|
|
1807
|
-
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
1808
|
-
var import_path13 = __toESM(require("path"), 1);
|
|
1809
|
-
var PRE_COMMIT_SCRIPT = `#!/bin/sh
|
|
1810
|
-
# Rigstate Guardian Pre-commit Hook
|
|
1811
|
-
# Installed by: rigstate hooks install
|
|
1812
|
-
|
|
1813
|
-
# 1. Silent Sentinel Check (Phase 5)
|
|
1814
|
-
if [ -f .rigstate/guardian.lock ]; then
|
|
1815
|
-
echo "\u{1F6D1} INTERVENTION ACTIVE: Commit blocked by Silent Sentinel."
|
|
1816
|
-
echo " A critical violation ('HARD_LOCK') was detected by the Guardian Daemon."
|
|
1817
|
-
echo " Please fix the violation to unlock the repo."
|
|
1818
|
-
echo ""
|
|
1819
|
-
if grep -q "HARD_LOCK_ACTIVE" .rigstate/guardian.lock; then
|
|
1820
|
-
cat .rigstate/guardian.lock
|
|
1821
|
-
fi
|
|
1822
|
-
exit 1
|
|
1823
|
-
fi
|
|
1824
|
-
|
|
1825
|
-
echo "\u{1F6E1}\uFE0F Running Guardian checks..."
|
|
1826
|
-
|
|
1827
|
-
# Run check with strict mode for critical violations
|
|
1828
|
-
rigstate check --staged --strict=critical
|
|
1829
|
-
|
|
1830
|
-
# Exit with the same code as rigstate check
|
|
1831
|
-
exit $?
|
|
1832
|
-
`;
|
|
1833
|
-
function createHooksCommand() {
|
|
1834
|
-
const hooks = new import_commander8.Command("hooks").description("Manage git hooks for Guardian integration");
|
|
1835
|
-
hooks.command("install").description("Install pre-commit hook to run Guardian checks").option("--strict [level]", 'Strict level: "all" or "critical" (default)', "critical").action(async (options) => {
|
|
1836
|
-
try {
|
|
1837
|
-
const gitDir = import_path13.default.join(process.cwd(), ".git");
|
|
1838
|
-
try {
|
|
1839
|
-
await import_promises13.default.access(gitDir);
|
|
1840
|
-
} catch {
|
|
1841
|
-
console.log(import_chalk12.default.red("\u274C Not a git repository."));
|
|
1842
|
-
console.log(import_chalk12.default.dim(' Initialize with "git init" first.'));
|
|
1843
|
-
process.exit(1);
|
|
1844
|
-
}
|
|
1845
|
-
const hooksDir = import_path13.default.join(gitDir, "hooks");
|
|
1846
|
-
await import_promises13.default.mkdir(hooksDir, { recursive: true });
|
|
1847
|
-
const preCommitPath = import_path13.default.join(hooksDir, "pre-commit");
|
|
1848
|
-
let existingContent = "";
|
|
1849
|
-
try {
|
|
1850
|
-
existingContent = await import_promises13.default.readFile(preCommitPath, "utf-8");
|
|
1851
|
-
if (existingContent.includes("rigstate")) {
|
|
1852
|
-
console.log(import_chalk12.default.yellow("\u26A0 Rigstate pre-commit hook already installed."));
|
|
1853
|
-
console.log(import_chalk12.default.dim(' Use "rigstate hooks uninstall" to remove first.'));
|
|
1854
|
-
return;
|
|
1855
|
-
}
|
|
1856
|
-
} catch {
|
|
1857
|
-
}
|
|
1858
|
-
let script = PRE_COMMIT_SCRIPT;
|
|
1859
|
-
if (options.strict === "all") {
|
|
1860
|
-
script = script.replace("--strict=critical", "--strict");
|
|
1861
|
-
}
|
|
1862
|
-
if (existingContent && !existingContent.includes("rigstate")) {
|
|
1863
|
-
const combinedScript = existingContent + "\n\n" + script.replace("#!/bin/sh\n", "");
|
|
1864
|
-
await import_promises13.default.writeFile(preCommitPath, combinedScript, { mode: 493 });
|
|
1865
|
-
console.log(import_chalk12.default.green("\u2705 Rigstate hook appended to existing pre-commit."));
|
|
1866
|
-
} else {
|
|
1867
|
-
await import_promises13.default.writeFile(preCommitPath, script, { mode: 493 });
|
|
1868
|
-
console.log(import_chalk12.default.green("\u2705 Pre-commit hook installed!"));
|
|
1869
|
-
}
|
|
1870
|
-
console.log(import_chalk12.default.dim(` Path: ${preCommitPath}`));
|
|
1871
|
-
console.log(import_chalk12.default.dim(` Strict level: ${options.strict}`));
|
|
1872
|
-
console.log("");
|
|
1873
|
-
console.log(import_chalk12.default.cyan("Guardian will now check your code before each commit."));
|
|
1874
|
-
console.log(import_chalk12.default.dim('Use "rigstate hooks uninstall" to remove the hook.'));
|
|
1875
|
-
} catch (error) {
|
|
1876
|
-
console.error(import_chalk12.default.red("Failed to install hook:"), error.message);
|
|
1877
|
-
process.exit(1);
|
|
1878
|
-
}
|
|
1879
|
-
});
|
|
1880
|
-
hooks.command("uninstall").description("Remove Rigstate pre-commit hook").action(async () => {
|
|
1881
|
-
try {
|
|
1882
|
-
const preCommitPath = import_path13.default.join(process.cwd(), ".git", "hooks", "pre-commit");
|
|
1883
|
-
try {
|
|
1884
|
-
const content = await import_promises13.default.readFile(preCommitPath, "utf-8");
|
|
1885
|
-
if (!content.includes("rigstate")) {
|
|
1886
|
-
console.log(import_chalk12.default.yellow("\u26A0 No Rigstate hook found in pre-commit."));
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
if (content.includes("# Rigstate Guardian Pre-commit Hook") && content.trim().split("\n").filter((l) => l && !l.startsWith("#")).length <= 4) {
|
|
1890
|
-
await import_promises13.default.unlink(preCommitPath);
|
|
1891
|
-
console.log(import_chalk12.default.green("\u2705 Pre-commit hook removed."));
|
|
1892
|
-
} else {
|
|
1893
|
-
const lines = content.split("\n");
|
|
1894
|
-
const filteredLines = [];
|
|
1895
|
-
let inRigstateSection = false;
|
|
1896
|
-
for (const line of lines) {
|
|
1897
|
-
if (line.includes("Rigstate Guardian Pre-commit Hook")) {
|
|
1898
|
-
inRigstateSection = true;
|
|
1899
|
-
continue;
|
|
1900
|
-
}
|
|
1901
|
-
if (inRigstateSection && line.includes("exit $?")) {
|
|
1902
|
-
inRigstateSection = false;
|
|
1903
|
-
continue;
|
|
1904
|
-
}
|
|
1905
|
-
if (!inRigstateSection && !line.includes("rigstate check")) {
|
|
1906
|
-
filteredLines.push(line);
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
await import_promises13.default.writeFile(preCommitPath, filteredLines.join("\n"), { mode: 493 });
|
|
1910
|
-
console.log(import_chalk12.default.green("\u2705 Rigstate section removed from pre-commit hook."));
|
|
1911
|
-
}
|
|
1912
|
-
} catch {
|
|
1913
|
-
console.log(import_chalk12.default.yellow("\u26A0 No pre-commit hook found."));
|
|
1914
|
-
}
|
|
1915
|
-
} catch (error) {
|
|
1916
|
-
console.error(import_chalk12.default.red("Failed to uninstall hook:"), error.message);
|
|
1917
|
-
process.exit(1);
|
|
2218
|
+
results,
|
|
2219
|
+
summary: summarizeResults(results)
|
|
2220
|
+
}, null, 2));
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
const hasViolations = results.some((r) => r.violations.length > 0);
|
|
2224
|
+
if (!hasViolations) {
|
|
2225
|
+
return;
|
|
2226
|
+
}
|
|
2227
|
+
console.log("\n" + import_chalk14.default.bold("\u{1F50D} Violations Found"));
|
|
2228
|
+
console.log(import_chalk14.default.dim("\u2500".repeat(50)));
|
|
2229
|
+
for (const result of results) {
|
|
2230
|
+
if (result.violations.length > 0) {
|
|
2231
|
+
formatViolations(result.violations);
|
|
1918
2232
|
}
|
|
1919
|
-
}
|
|
1920
|
-
return hooks;
|
|
2233
|
+
}
|
|
1921
2234
|
}
|
|
1922
2235
|
|
|
2236
|
+
// src/index.ts
|
|
2237
|
+
init_hooks();
|
|
2238
|
+
|
|
1923
2239
|
// src/commands/daemon.ts
|
|
1924
2240
|
init_cjs_shims();
|
|
1925
|
-
var
|
|
1926
|
-
var
|
|
1927
|
-
var
|
|
1928
|
-
var
|
|
1929
|
-
var
|
|
2241
|
+
var import_commander11 = require("commander");
|
|
2242
|
+
var import_chalk17 = __toESM(require("chalk"), 1);
|
|
2243
|
+
var import_ora8 = __toESM(require("ora"), 1);
|
|
2244
|
+
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
2245
|
+
var import_path19 = __toESM(require("path"), 1);
|
|
1930
2246
|
|
|
1931
2247
|
// src/daemon/factory.ts
|
|
1932
2248
|
init_cjs_shims();
|
|
1933
2249
|
|
|
1934
2250
|
// src/daemon/core.ts
|
|
1935
2251
|
init_cjs_shims();
|
|
1936
|
-
var
|
|
1937
|
-
var
|
|
2252
|
+
var import_chalk16 = __toESM(require("chalk"), 1);
|
|
2253
|
+
var fs17 = __toESM(require("fs/promises"), 1);
|
|
1938
2254
|
var import_events3 = require("events");
|
|
1939
2255
|
|
|
1940
2256
|
// src/daemon/file-watcher.ts
|
|
1941
2257
|
init_cjs_shims();
|
|
1942
2258
|
var chokidar = __toESM(require("chokidar"), 1);
|
|
1943
|
-
var
|
|
2259
|
+
var import_path15 = __toESM(require("path"), 1);
|
|
1944
2260
|
var import_events = require("events");
|
|
1945
2261
|
var CODE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
1946
2262
|
function isCodeFile3(filePath) {
|
|
1947
|
-
const ext =
|
|
2263
|
+
const ext = import_path15.default.extname(filePath).toLowerCase();
|
|
1948
2264
|
return CODE_EXTENSIONS.includes(ext);
|
|
1949
2265
|
}
|
|
1950
2266
|
function createFileWatcher(watchPath) {
|
|
1951
2267
|
const emitter = new import_events.EventEmitter();
|
|
1952
2268
|
let watcher = null;
|
|
1953
2269
|
emitter.start = () => {
|
|
1954
|
-
const absolutePath =
|
|
2270
|
+
const absolutePath = import_path15.default.resolve(process.cwd(), watchPath);
|
|
1955
2271
|
watcher = chokidar.watch(absolutePath, {
|
|
1956
|
-
ignored: (
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2272
|
+
ignored: (absolutePath2) => {
|
|
2273
|
+
const relPath = import_path15.default.relative(process.cwd(), absolutePath2);
|
|
2274
|
+
const ignoredDirs = /* @__PURE__ */ new Set([
|
|
2275
|
+
"node_modules",
|
|
2276
|
+
".git",
|
|
2277
|
+
".next",
|
|
2278
|
+
".turbo",
|
|
2279
|
+
"dist",
|
|
2280
|
+
"build",
|
|
2281
|
+
".rigstate",
|
|
2282
|
+
"coverage",
|
|
2283
|
+
".DS_Store",
|
|
2284
|
+
"tmp",
|
|
2285
|
+
"temp",
|
|
2286
|
+
"vendor",
|
|
2287
|
+
".cache",
|
|
2288
|
+
"public"
|
|
2289
|
+
// Usually static assets, not code
|
|
2290
|
+
]);
|
|
2291
|
+
const segments = relPath.split(import_path15.default.sep);
|
|
2292
|
+
if (segments.some((s) => ignoredDirs.has(s))) {
|
|
2293
|
+
return true;
|
|
2294
|
+
}
|
|
1964
2295
|
return false;
|
|
1965
2296
|
},
|
|
1966
2297
|
persistent: true,
|
|
1967
2298
|
ignoreInitial: true,
|
|
1968
|
-
|
|
2299
|
+
ignorePermissionErrors: true,
|
|
2300
|
+
// Don't crash on EPERM
|
|
2301
|
+
depth: 20,
|
|
1969
2302
|
awaitWriteFinish: {
|
|
1970
|
-
stabilityThreshold:
|
|
2303
|
+
stabilityThreshold: 300,
|
|
1971
2304
|
pollInterval: 100
|
|
1972
2305
|
},
|
|
1973
2306
|
usePolling: false,
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
binaryInterval: 1e3
|
|
2307
|
+
atomic: true
|
|
2308
|
+
// Handle atomic writes (like vim/saving) better
|
|
1977
2309
|
});
|
|
1978
2310
|
watcher.on("change", (filePath) => {
|
|
1979
2311
|
if (isCodeFile3(filePath)) {
|
|
1980
|
-
emitter.emit("change",
|
|
2312
|
+
emitter.emit("change", import_path15.default.relative(process.cwd(), filePath));
|
|
1981
2313
|
}
|
|
1982
2314
|
});
|
|
1983
2315
|
watcher.on("add", (filePath) => {
|
|
1984
2316
|
if (isCodeFile3(filePath)) {
|
|
1985
|
-
emitter.emit("add",
|
|
2317
|
+
emitter.emit("add", import_path15.default.relative(process.cwd(), filePath));
|
|
1986
2318
|
}
|
|
1987
2319
|
});
|
|
1988
2320
|
watcher.on("unlink", (filePath) => {
|
|
1989
2321
|
if (isCodeFile3(filePath)) {
|
|
1990
|
-
emitter.emit("unlink",
|
|
2322
|
+
emitter.emit("unlink", import_path15.default.relative(process.cwd(), filePath));
|
|
1991
2323
|
}
|
|
1992
2324
|
});
|
|
1993
2325
|
watcher.on("error", (error) => {
|
|
@@ -2008,10 +2340,10 @@ function createFileWatcher(watchPath) {
|
|
|
2008
2340
|
|
|
2009
2341
|
// src/daemon/heuristic-engine.ts
|
|
2010
2342
|
init_cjs_shims();
|
|
2011
|
-
var
|
|
2012
|
-
var
|
|
2013
|
-
var
|
|
2014
|
-
var
|
|
2343
|
+
var import_promises15 = require("fs/promises");
|
|
2344
|
+
var import_path16 = require("path");
|
|
2345
|
+
var import_path17 = __toESM(require("path"), 1);
|
|
2346
|
+
var import_axios10 = __toESM(require("axios"), 1);
|
|
2015
2347
|
var GLOBAL_HEURISTICS = [
|
|
2016
2348
|
{
|
|
2017
2349
|
skillId: "payment-expert",
|
|
@@ -2042,12 +2374,12 @@ var HeuristicEngine = class {
|
|
|
2042
2374
|
rules = [];
|
|
2043
2375
|
cachePath;
|
|
2044
2376
|
constructor() {
|
|
2045
|
-
this.cachePath =
|
|
2377
|
+
this.cachePath = import_path17.default.join(process.cwd(), ".rigstate", "cache", "heuristics.json");
|
|
2046
2378
|
this.loadRules();
|
|
2047
2379
|
}
|
|
2048
2380
|
async loadRules() {
|
|
2049
2381
|
try {
|
|
2050
|
-
const cached = await (0,
|
|
2382
|
+
const cached = await (0, import_promises15.readFile)(this.cachePath, "utf-8");
|
|
2051
2383
|
const data = JSON.parse(cached);
|
|
2052
2384
|
if (Array.isArray(data) && data.length > 0) {
|
|
2053
2385
|
this.rules = data;
|
|
@@ -2059,9 +2391,9 @@ var HeuristicEngine = class {
|
|
|
2059
2391
|
}
|
|
2060
2392
|
async refreshRules(projectId, apiUrl, apiKey) {
|
|
2061
2393
|
try {
|
|
2062
|
-
await (0,
|
|
2394
|
+
await (0, import_promises15.mkdir)((0, import_path16.dirname)(this.cachePath), { recursive: true });
|
|
2063
2395
|
const endpoint = `${apiUrl}/api/v1/skills/triggers`;
|
|
2064
|
-
const response = await
|
|
2396
|
+
const response = await import_axios10.default.get(endpoint, {
|
|
2065
2397
|
headers: {
|
|
2066
2398
|
"x-api-key": apiKey,
|
|
2067
2399
|
"Content-Type": "application/json"
|
|
@@ -2069,7 +2401,7 @@ var HeuristicEngine = class {
|
|
|
2069
2401
|
});
|
|
2070
2402
|
if (response.data && Array.isArray(response.data.triggers)) {
|
|
2071
2403
|
const cloudRules = response.data.triggers;
|
|
2072
|
-
await (0,
|
|
2404
|
+
await (0, import_promises15.writeFile)(this.cachePath, JSON.stringify(cloudRules, null, 2));
|
|
2073
2405
|
this.rules = cloudRules;
|
|
2074
2406
|
return true;
|
|
2075
2407
|
}
|
|
@@ -2079,7 +2411,7 @@ var HeuristicEngine = class {
|
|
|
2079
2411
|
}
|
|
2080
2412
|
async analyzeFile(filePath, metrics) {
|
|
2081
2413
|
try {
|
|
2082
|
-
const content = await (0,
|
|
2414
|
+
const content = await (0, import_promises15.readFile)(filePath, "utf-8");
|
|
2083
2415
|
const matches = [];
|
|
2084
2416
|
const activeRules = this.rules.length > 0 ? this.rules : GLOBAL_HEURISTICS;
|
|
2085
2417
|
for (const heuristic of activeRules) {
|
|
@@ -2157,9 +2489,9 @@ function createHeuristicEngine() {
|
|
|
2157
2489
|
|
|
2158
2490
|
// src/daemon/intervention-protocol.ts
|
|
2159
2491
|
init_cjs_shims();
|
|
2160
|
-
var
|
|
2161
|
-
var
|
|
2162
|
-
var
|
|
2492
|
+
var import_chalk15 = __toESM(require("chalk"), 1);
|
|
2493
|
+
var fs15 = __toESM(require("fs"), 1);
|
|
2494
|
+
var path17 = __toESM(require("path"), 1);
|
|
2163
2495
|
var InterventionProtocol = class {
|
|
2164
2496
|
activeViolators = /* @__PURE__ */ new Set();
|
|
2165
2497
|
/**
|
|
@@ -2182,18 +2514,18 @@ var InterventionProtocol = class {
|
|
|
2182
2514
|
}
|
|
2183
2515
|
syncLockFile() {
|
|
2184
2516
|
try {
|
|
2185
|
-
const lockDir =
|
|
2186
|
-
if (!
|
|
2187
|
-
const lockPath =
|
|
2517
|
+
const lockDir = path17.join(process.cwd(), ".rigstate");
|
|
2518
|
+
if (!fs15.existsSync(lockDir)) fs15.mkdirSync(lockDir, { recursive: true });
|
|
2519
|
+
const lockPath = path17.join(lockDir, "guardian.lock");
|
|
2188
2520
|
if (this.activeViolators.size > 0) {
|
|
2189
2521
|
const content = `HARD_LOCK_ACTIVE
|
|
2190
2522
|
Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
2191
2523
|
|
|
2192
2524
|
Blocking Files:
|
|
2193
2525
|
${Array.from(this.activeViolators).join("\n")}`;
|
|
2194
|
-
|
|
2526
|
+
fs15.writeFileSync(lockPath, content, "utf-8");
|
|
2195
2527
|
} else {
|
|
2196
|
-
if (
|
|
2528
|
+
if (fs15.existsSync(lockPath)) fs15.unlinkSync(lockPath);
|
|
2197
2529
|
}
|
|
2198
2530
|
} catch (e) {
|
|
2199
2531
|
console.error("Failed to sync guardian lock file:", e);
|
|
@@ -2247,11 +2579,11 @@ ${Array.from(this.activeViolators).join("\n")}`;
|
|
|
2247
2579
|
enforce(decision) {
|
|
2248
2580
|
if (decision.mode === "OPEN") return;
|
|
2249
2581
|
const icon = decision.mode === "HARD_LOCK" ? "\u{1F6AB}" : "\u26A0\uFE0F";
|
|
2250
|
-
const color = decision.mode === "HARD_LOCK" ?
|
|
2582
|
+
const color = decision.mode === "HARD_LOCK" ? import_chalk15.default.bgRed.white.bold : import_chalk15.default.yellow.bold;
|
|
2251
2583
|
console.log("\n" + color(` ${icon} [${decision.mode}] INTERVENTION `));
|
|
2252
|
-
console.log(
|
|
2584
|
+
console.log(import_chalk15.default.redBright(` ${decision.message}`));
|
|
2253
2585
|
if (decision.blockCommit) {
|
|
2254
|
-
console.log(
|
|
2586
|
+
console.log(import_chalk15.default.dim(" \u{1F512} Commit functionality is logically suspended until fixed."));
|
|
2255
2587
|
}
|
|
2256
2588
|
}
|
|
2257
2589
|
};
|
|
@@ -2261,9 +2593,9 @@ function createInterventionProtocol() {
|
|
|
2261
2593
|
|
|
2262
2594
|
// src/daemon/guardian-monitor.ts
|
|
2263
2595
|
init_cjs_shims();
|
|
2264
|
-
var
|
|
2265
|
-
var
|
|
2266
|
-
var
|
|
2596
|
+
var import_axios11 = __toESM(require("axios"), 1);
|
|
2597
|
+
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
2598
|
+
var import_path18 = __toESM(require("path"), 1);
|
|
2267
2599
|
var CACHE_FILE3 = ".rigstate/rules-cache.json";
|
|
2268
2600
|
var CACHE_TTL_MS2 = 5 * 60 * 1e3;
|
|
2269
2601
|
function createGuardianMonitor(projectId, apiUrl, apiKey) {
|
|
@@ -2274,7 +2606,7 @@ function createGuardianMonitor(projectId, apiUrl, apiKey) {
|
|
|
2274
2606
|
return;
|
|
2275
2607
|
}
|
|
2276
2608
|
try {
|
|
2277
|
-
const response = await
|
|
2609
|
+
const response = await import_axios11.default.get(`${apiUrl}/api/v1/guardian/rules`, {
|
|
2278
2610
|
params: { project_id: projectId },
|
|
2279
2611
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
2280
2612
|
timeout: 1e4
|
|
@@ -2304,7 +2636,7 @@ function createGuardianMonitor(projectId, apiUrl, apiKey) {
|
|
|
2304
2636
|
passed: true
|
|
2305
2637
|
};
|
|
2306
2638
|
}
|
|
2307
|
-
const absolutePath =
|
|
2639
|
+
const absolutePath = import_path18.default.resolve(process.cwd(), filePath);
|
|
2308
2640
|
return checkFile(absolutePath, rules, process.cwd());
|
|
2309
2641
|
};
|
|
2310
2642
|
const getRuleCount = () => rules.length;
|
|
@@ -2318,8 +2650,8 @@ function createGuardianMonitor(projectId, apiUrl, apiKey) {
|
|
|
2318
2650
|
}
|
|
2319
2651
|
async function loadCachedRules2(projectId) {
|
|
2320
2652
|
try {
|
|
2321
|
-
const cachePath =
|
|
2322
|
-
const content = await
|
|
2653
|
+
const cachePath = import_path18.default.join(process.cwd(), CACHE_FILE3);
|
|
2654
|
+
const content = await import_promises16.default.readFile(cachePath, "utf-8");
|
|
2323
2655
|
const cached = JSON.parse(content);
|
|
2324
2656
|
if (cached.projectId !== projectId) {
|
|
2325
2657
|
return null;
|
|
@@ -2331,16 +2663,16 @@ async function loadCachedRules2(projectId) {
|
|
|
2331
2663
|
}
|
|
2332
2664
|
async function saveCachedRules2(projectId, rules) {
|
|
2333
2665
|
try {
|
|
2334
|
-
const cacheDir =
|
|
2335
|
-
await
|
|
2666
|
+
const cacheDir = import_path18.default.join(process.cwd(), ".rigstate");
|
|
2667
|
+
await import_promises16.default.mkdir(cacheDir, { recursive: true });
|
|
2336
2668
|
const cached = {
|
|
2337
2669
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2338
2670
|
projectId,
|
|
2339
2671
|
rules,
|
|
2340
2672
|
settings: { lmax: 400, lmax_warning: 350 }
|
|
2341
2673
|
};
|
|
2342
|
-
await
|
|
2343
|
-
|
|
2674
|
+
await import_promises16.default.writeFile(
|
|
2675
|
+
import_path18.default.join(cacheDir, "rules-cache.json"),
|
|
2344
2676
|
JSON.stringify(cached, null, 2)
|
|
2345
2677
|
);
|
|
2346
2678
|
} catch {
|
|
@@ -2349,7 +2681,7 @@ async function saveCachedRules2(projectId, rules) {
|
|
|
2349
2681
|
|
|
2350
2682
|
// src/daemon/bridge-listener.ts
|
|
2351
2683
|
init_cjs_shims();
|
|
2352
|
-
var
|
|
2684
|
+
var import_axios12 = __toESM(require("axios"), 1);
|
|
2353
2685
|
var import_events2 = require("events");
|
|
2354
2686
|
var POLL_INTERVAL_MS = 5e3;
|
|
2355
2687
|
function createBridgeListener(projectId, apiUrl, apiKey) {
|
|
@@ -2359,7 +2691,7 @@ function createBridgeListener(projectId, apiUrl, apiKey) {
|
|
|
2359
2691
|
let lastCheckedId = null;
|
|
2360
2692
|
const checkBridge = async () => {
|
|
2361
2693
|
try {
|
|
2362
|
-
const response = await
|
|
2694
|
+
const response = await import_axios12.default.get(`${apiUrl}/api/v1/agent/bridge`, {
|
|
2363
2695
|
params: {
|
|
2364
2696
|
project_id: projectId,
|
|
2365
2697
|
action: "check"
|
|
@@ -2387,7 +2719,7 @@ function createBridgeListener(projectId, apiUrl, apiKey) {
|
|
|
2387
2719
|
};
|
|
2388
2720
|
const acknowledgePing = async (taskId) => {
|
|
2389
2721
|
try {
|
|
2390
|
-
await
|
|
2722
|
+
await import_axios12.default.post(`${apiUrl}/api/v1/agent/bridge`, {
|
|
2391
2723
|
project_id: projectId,
|
|
2392
2724
|
action: "update",
|
|
2393
2725
|
bridge_id: taskId,
|
|
@@ -2420,10 +2752,10 @@ function createBridgeListener(projectId, apiUrl, apiKey) {
|
|
|
2420
2752
|
|
|
2421
2753
|
// src/daemon/telemetry.ts
|
|
2422
2754
|
init_cjs_shims();
|
|
2423
|
-
var
|
|
2755
|
+
var import_axios13 = __toESM(require("axios"), 1);
|
|
2424
2756
|
async function trackSkillUsage(apiUrl, apiKey, projectId, skillId) {
|
|
2425
2757
|
try {
|
|
2426
|
-
await
|
|
2758
|
+
await import_axios13.default.post(`${apiUrl}/api/v1/skills/usage`, {
|
|
2427
2759
|
projectId,
|
|
2428
2760
|
skillName: skillId,
|
|
2429
2761
|
status: "ACTIVATED"
|
|
@@ -2458,7 +2790,7 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2458
2790
|
}
|
|
2459
2791
|
async start() {
|
|
2460
2792
|
if (this.state.isRunning) {
|
|
2461
|
-
console.log(
|
|
2793
|
+
console.log(import_chalk16.default.yellow("Daemon is already running."));
|
|
2462
2794
|
return;
|
|
2463
2795
|
}
|
|
2464
2796
|
this.printWelcome();
|
|
@@ -2468,7 +2800,7 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2468
2800
|
this.interventionProtocol = createInterventionProtocol();
|
|
2469
2801
|
this.guardianMonitor = createGuardianMonitor(this.config.projectId, this.config.apiUrl, this.config.apiKey);
|
|
2470
2802
|
await this.guardianMonitor.loadRules();
|
|
2471
|
-
console.log(
|
|
2803
|
+
console.log(import_chalk16.default.green(` \u2713 Loaded ${this.guardianMonitor.getRuleCount()} rules`));
|
|
2472
2804
|
await this.syncHeuristics();
|
|
2473
2805
|
if (this.config.checkOnChange) {
|
|
2474
2806
|
this.setupFileWatcher();
|
|
@@ -2480,34 +2812,34 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2480
2812
|
this.emit("started", this.state);
|
|
2481
2813
|
}
|
|
2482
2814
|
printWelcome() {
|
|
2483
|
-
console.log(
|
|
2484
|
-
console.log(
|
|
2485
|
-
console.log(
|
|
2486
|
-
console.log(
|
|
2815
|
+
console.log(import_chalk16.default.bold.blue("\n\u{1F6E1}\uFE0F Guardian Daemon Starting..."));
|
|
2816
|
+
console.log(import_chalk16.default.dim(`Project: ${this.config.projectId}`));
|
|
2817
|
+
console.log(import_chalk16.default.dim(`Watch Path: ${this.config.watchPath}`));
|
|
2818
|
+
console.log(import_chalk16.default.dim("\u2500".repeat(50)));
|
|
2487
2819
|
}
|
|
2488
2820
|
printActive() {
|
|
2489
|
-
console.log(
|
|
2490
|
-
console.log(
|
|
2491
|
-
console.log(
|
|
2821
|
+
console.log(import_chalk16.default.dim("\u2500".repeat(50)));
|
|
2822
|
+
console.log(import_chalk16.default.green.bold("\u2705 Guardian Daemon is now active"));
|
|
2823
|
+
console.log(import_chalk16.default.dim("Press Ctrl+C to stop\n"));
|
|
2492
2824
|
}
|
|
2493
2825
|
async syncHeuristics() {
|
|
2494
2826
|
if (!this.heuristicEngine) return;
|
|
2495
2827
|
const synced = await this.heuristicEngine.refreshRules(this.config.projectId, this.config.apiUrl, this.config.apiKey);
|
|
2496
|
-
if (synced) console.log(
|
|
2828
|
+
if (synced) console.log(import_chalk16.default.green(" \u2713 Synced heuristic rules"));
|
|
2497
2829
|
}
|
|
2498
2830
|
setupFileWatcher() {
|
|
2499
|
-
console.log(
|
|
2831
|
+
console.log(import_chalk16.default.dim("\u{1F4C2} Starting file watcher..."));
|
|
2500
2832
|
this.fileWatcher = createFileWatcher(this.config.watchPath);
|
|
2501
2833
|
this.fileWatcher.on("change", (path23) => this.handleFileChange(path23));
|
|
2502
2834
|
this.fileWatcher.start();
|
|
2503
|
-
console.log(
|
|
2835
|
+
console.log(import_chalk16.default.green(" \u2713 File watcher active"));
|
|
2504
2836
|
}
|
|
2505
2837
|
async handleFileChange(filePath) {
|
|
2506
2838
|
this.state.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
|
|
2507
|
-
if (this.config.verbose) console.log(
|
|
2839
|
+
if (this.config.verbose) console.log(import_chalk16.default.dim(` \u{1F4DD} File changed: ${filePath}`));
|
|
2508
2840
|
let lineCount = 0;
|
|
2509
2841
|
try {
|
|
2510
|
-
const content = await
|
|
2842
|
+
const content = await fs17.readFile(filePath, "utf-8");
|
|
2511
2843
|
lineCount = content.split("\n").length;
|
|
2512
2844
|
} catch (e) {
|
|
2513
2845
|
}
|
|
@@ -2517,8 +2849,8 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2517
2849
|
rules: this.guardianMonitor.getRules()
|
|
2518
2850
|
});
|
|
2519
2851
|
for (const match of matches) {
|
|
2520
|
-
console.log(
|
|
2521
|
-
console.log(
|
|
2852
|
+
console.log(import_chalk16.default.magenta(` \u{1F4A1} PREDICTIVE ACTIVATION: ${match.skillId}`));
|
|
2853
|
+
console.log(import_chalk16.default.dim(` Reason: ${match.reason}`));
|
|
2522
2854
|
const decision = this.interventionProtocol.evaluateTrigger(match.skillId, match.confidence);
|
|
2523
2855
|
this.interventionProtocol.enforce(decision);
|
|
2524
2856
|
await jitProvisionSkill(match.skillId, this.config.apiUrl, this.config.apiKey, this.config.projectId, process.cwd());
|
|
@@ -2534,7 +2866,7 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2534
2866
|
this.state.violationsFound += result.violations.length;
|
|
2535
2867
|
this.emit("violation", { file: filePath, violations: result.violations });
|
|
2536
2868
|
for (const v of result.violations) {
|
|
2537
|
-
const color = v.severity === "critical" ?
|
|
2869
|
+
const color = v.severity === "critical" ? import_chalk16.default.red : v.severity === "warning" ? import_chalk16.default.yellow : import_chalk16.default.blue;
|
|
2538
2870
|
console.log(color(` [${v.severity.toUpperCase()}] ${filePath}: ${v.message}`));
|
|
2539
2871
|
if (this.interventionProtocol) {
|
|
2540
2872
|
const decision = this.interventionProtocol.evaluateViolation(v.message, v.severity);
|
|
@@ -2546,25 +2878,25 @@ var GuardianDaemon = class extends import_events3.EventEmitter {
|
|
|
2546
2878
|
}
|
|
2547
2879
|
}
|
|
2548
2880
|
async setupBridge() {
|
|
2549
|
-
console.log(
|
|
2881
|
+
console.log(import_chalk16.default.dim("\u{1F309} Connecting to Agent Bridge..."));
|
|
2550
2882
|
this.bridgeListener = createBridgeListener(this.config.projectId, this.config.apiUrl, this.config.apiKey);
|
|
2551
2883
|
this.bridgeListener.on("task", (task) => {
|
|
2552
2884
|
this.state.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
|
|
2553
2885
|
this.state.tasksProcessed++;
|
|
2554
|
-
console.log(
|
|
2886
|
+
console.log(import_chalk16.default.cyan(`
|
|
2555
2887
|
\u{1F4E5} New task received: ${task.id}`));
|
|
2556
2888
|
this.emit("task", task);
|
|
2557
2889
|
});
|
|
2558
2890
|
await this.bridgeListener.connect();
|
|
2559
|
-
console.log(
|
|
2891
|
+
console.log(import_chalk16.default.green(" \u2713 Agent Bridge connected"));
|
|
2560
2892
|
}
|
|
2561
2893
|
async stop() {
|
|
2562
2894
|
if (!this.state.isRunning) return;
|
|
2563
|
-
console.log(
|
|
2895
|
+
console.log(import_chalk16.default.dim("\n\u{1F6D1} Stopping Guardian Daemon..."));
|
|
2564
2896
|
if (this.fileWatcher) await this.fileWatcher.stop();
|
|
2565
2897
|
if (this.bridgeListener) await this.bridgeListener.disconnect();
|
|
2566
2898
|
this.state.isRunning = false;
|
|
2567
|
-
console.log(
|
|
2899
|
+
console.log(import_chalk16.default.green("\u2713 Daemon stopped."));
|
|
2568
2900
|
this.emit("stopped", this.state);
|
|
2569
2901
|
}
|
|
2570
2902
|
getState() {
|
|
@@ -2605,18 +2937,26 @@ async function createDaemon(options) {
|
|
|
2605
2937
|
var PID_FILE = ".rigstate/daemon.pid";
|
|
2606
2938
|
var STATE_FILE = ".rigstate/daemon.state.json";
|
|
2607
2939
|
function createDaemonCommand() {
|
|
2608
|
-
const daemon = new
|
|
2940
|
+
const daemon = new import_commander11.Command("daemon").description("Start the Guardian daemon for continuous monitoring");
|
|
2609
2941
|
daemon.argument("[action]", "Action: start (default) or status", "start").option("--project <id>", "Project ID (or use .rigstate manifest)").option("--path <path>", "Path to watch", ".").option("--no-bridge", "Disable Agent Bridge connection").option("--verbose", "Enable verbose output").action(async (action, options) => {
|
|
2610
2942
|
if (action === "status") {
|
|
2611
2943
|
await showStatus();
|
|
2612
2944
|
return;
|
|
2613
2945
|
}
|
|
2614
|
-
|
|
2946
|
+
if (action === "enable") {
|
|
2947
|
+
await enableDaemon();
|
|
2948
|
+
return;
|
|
2949
|
+
}
|
|
2950
|
+
if (action === "disable") {
|
|
2951
|
+
await disableDaemon();
|
|
2952
|
+
return;
|
|
2953
|
+
}
|
|
2954
|
+
const spinner = (0, import_ora8.default)();
|
|
2615
2955
|
try {
|
|
2616
2956
|
if (await isRunning()) {
|
|
2617
|
-
console.log(
|
|
2618
|
-
console.log(
|
|
2619
|
-
console.log(
|
|
2957
|
+
console.log(import_chalk17.default.yellow("\u26A0 Another daemon instance may be running."));
|
|
2958
|
+
console.log(import_chalk17.default.dim(` Check ${PID_FILE} or run "rigstate daemon status"`));
|
|
2959
|
+
console.log(import_chalk17.default.dim(" Use Ctrl+C to stop the running daemon first.\n"));
|
|
2620
2960
|
}
|
|
2621
2961
|
spinner.start("Initializing Guardian Daemon...");
|
|
2622
2962
|
const daemonInstance = await createDaemon({
|
|
@@ -2628,7 +2968,7 @@ function createDaemonCommand() {
|
|
|
2628
2968
|
spinner.stop();
|
|
2629
2969
|
await writePidFile();
|
|
2630
2970
|
process.on("SIGINT", async () => {
|
|
2631
|
-
console.log(
|
|
2971
|
+
console.log(import_chalk17.default.dim("\n\nShutting down..."));
|
|
2632
2972
|
await daemonInstance.stop();
|
|
2633
2973
|
await cleanupPidFile();
|
|
2634
2974
|
process.exit(0);
|
|
@@ -2648,8 +2988,8 @@ function createDaemonCommand() {
|
|
|
2648
2988
|
await new Promise(() => {
|
|
2649
2989
|
});
|
|
2650
2990
|
} catch (error) {
|
|
2651
|
-
spinner.fail(
|
|
2652
|
-
console.error(
|
|
2991
|
+
spinner.fail(import_chalk17.default.red("Failed to start daemon"));
|
|
2992
|
+
console.error(import_chalk17.default.red("Error:"), error.message);
|
|
2653
2993
|
process.exit(1);
|
|
2654
2994
|
}
|
|
2655
2995
|
});
|
|
@@ -2657,14 +2997,14 @@ function createDaemonCommand() {
|
|
|
2657
2997
|
}
|
|
2658
2998
|
async function isRunning() {
|
|
2659
2999
|
try {
|
|
2660
|
-
const pidPath =
|
|
2661
|
-
const content = await
|
|
3000
|
+
const pidPath = import_path19.default.join(process.cwd(), PID_FILE);
|
|
3001
|
+
const content = await import_promises17.default.readFile(pidPath, "utf-8");
|
|
2662
3002
|
const pid = parseInt(content.trim(), 10);
|
|
2663
3003
|
try {
|
|
2664
3004
|
process.kill(pid, 0);
|
|
2665
3005
|
return true;
|
|
2666
3006
|
} catch {
|
|
2667
|
-
await
|
|
3007
|
+
await import_promises17.default.unlink(pidPath);
|
|
2668
3008
|
return false;
|
|
2669
3009
|
}
|
|
2670
3010
|
} catch {
|
|
@@ -2673,86 +3013,176 @@ async function isRunning() {
|
|
|
2673
3013
|
}
|
|
2674
3014
|
async function writePidFile() {
|
|
2675
3015
|
try {
|
|
2676
|
-
const dir =
|
|
2677
|
-
await
|
|
2678
|
-
await
|
|
3016
|
+
const dir = import_path19.default.join(process.cwd(), ".rigstate");
|
|
3017
|
+
await import_promises17.default.mkdir(dir, { recursive: true });
|
|
3018
|
+
await import_promises17.default.writeFile(import_path19.default.join(dir, "daemon.pid"), process.pid.toString());
|
|
2679
3019
|
} catch {
|
|
2680
3020
|
}
|
|
2681
3021
|
}
|
|
2682
3022
|
async function cleanupPidFile() {
|
|
2683
3023
|
try {
|
|
2684
|
-
await
|
|
2685
|
-
await
|
|
3024
|
+
await import_promises17.default.unlink(import_path19.default.join(process.cwd(), PID_FILE));
|
|
3025
|
+
await import_promises17.default.unlink(import_path19.default.join(process.cwd(), STATE_FILE));
|
|
2686
3026
|
} catch {
|
|
2687
3027
|
}
|
|
2688
3028
|
}
|
|
2689
3029
|
async function writeStateFile(state) {
|
|
2690
3030
|
try {
|
|
2691
|
-
const dir =
|
|
2692
|
-
await
|
|
2693
|
-
await
|
|
2694
|
-
|
|
3031
|
+
const dir = import_path19.default.join(process.cwd(), ".rigstate");
|
|
3032
|
+
await import_promises17.default.mkdir(dir, { recursive: true });
|
|
3033
|
+
await import_promises17.default.writeFile(
|
|
3034
|
+
import_path19.default.join(dir, "daemon.state.json"),
|
|
2695
3035
|
JSON.stringify(state, null, 2)
|
|
2696
3036
|
);
|
|
2697
3037
|
} catch {
|
|
2698
3038
|
}
|
|
2699
3039
|
}
|
|
2700
3040
|
async function showStatus() {
|
|
2701
|
-
console.log(
|
|
3041
|
+
console.log(import_chalk17.default.bold("\n\u{1F6E1}\uFE0F Guardian Daemon Status\n"));
|
|
2702
3042
|
const running = await isRunning();
|
|
2703
3043
|
if (!running) {
|
|
2704
|
-
console.log(
|
|
2705
|
-
console.log(
|
|
3044
|
+
console.log(import_chalk17.default.yellow("Status: Not running"));
|
|
3045
|
+
console.log(import_chalk17.default.dim('Use "rigstate daemon" to start.\n'));
|
|
2706
3046
|
return;
|
|
2707
3047
|
}
|
|
2708
|
-
console.log(
|
|
3048
|
+
console.log(import_chalk17.default.green("Status: Running"));
|
|
2709
3049
|
try {
|
|
2710
|
-
const statePath =
|
|
2711
|
-
const content = await
|
|
3050
|
+
const statePath = import_path19.default.join(process.cwd(), STATE_FILE);
|
|
3051
|
+
const content = await import_promises17.default.readFile(statePath, "utf-8");
|
|
2712
3052
|
const state = JSON.parse(content);
|
|
2713
|
-
console.log(
|
|
3053
|
+
console.log(import_chalk17.default.dim("\u2500".repeat(40)));
|
|
2714
3054
|
console.log(`Started at: ${state.startedAt || "Unknown"}`);
|
|
2715
3055
|
console.log(`Files checked: ${state.filesChecked || 0}`);
|
|
2716
3056
|
console.log(`Violations: ${state.violationsFound || 0}`);
|
|
2717
3057
|
console.log(`Tasks processed: ${state.tasksProcessed || 0}`);
|
|
2718
3058
|
console.log(`Last activity: ${state.lastActivity || "None"}`);
|
|
2719
|
-
console.log(
|
|
3059
|
+
console.log(import_chalk17.default.dim("\u2500".repeat(40)));
|
|
2720
3060
|
} catch {
|
|
2721
|
-
console.log(
|
|
3061
|
+
console.log(import_chalk17.default.dim("(State file not found)"));
|
|
2722
3062
|
}
|
|
2723
3063
|
try {
|
|
2724
|
-
const pidPath =
|
|
2725
|
-
const pid = await
|
|
2726
|
-
console.log(
|
|
3064
|
+
const pidPath = import_path19.default.join(process.cwd(), PID_FILE);
|
|
3065
|
+
const pid = await import_promises17.default.readFile(pidPath, "utf-8");
|
|
3066
|
+
console.log(import_chalk17.default.dim(`PID: ${pid.trim()}`));
|
|
2727
3067
|
} catch {
|
|
2728
3068
|
}
|
|
2729
3069
|
console.log("");
|
|
2730
3070
|
}
|
|
3071
|
+
async function enableDaemon() {
|
|
3072
|
+
console.log(import_chalk17.default.bold("\n\u2699\uFE0F Enabling Rigstate Background Service (macOS)\n"));
|
|
3073
|
+
if (process.platform !== "darwin") {
|
|
3074
|
+
console.error(import_chalk17.default.red("\u274C Currently only macOS is supported for auto-start."));
|
|
3075
|
+
console.error(import_chalk17.default.yellow("PRs welcome for Linux/Windows support!"));
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
const homeDir = process.env.HOME || "";
|
|
3079
|
+
if (!homeDir) {
|
|
3080
|
+
console.error(import_chalk17.default.red("\u274C Could not determine HOME directory."));
|
|
3081
|
+
return;
|
|
3082
|
+
}
|
|
3083
|
+
const agentsDir = import_path19.default.join(homeDir, "Library/LaunchAgents");
|
|
3084
|
+
const logDir = import_path19.default.join(homeDir, ".rigstate/logs");
|
|
3085
|
+
const plistPath = import_path19.default.join(agentsDir, "com.rigstate.daemon.plist");
|
|
3086
|
+
await import_promises17.default.mkdir(agentsDir, { recursive: true });
|
|
3087
|
+
await import_promises17.default.mkdir(logDir, { recursive: true });
|
|
3088
|
+
const scriptPath = import_path19.default.resolve(__dirname, "../index.js");
|
|
3089
|
+
const nodePath = process.execPath;
|
|
3090
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
3091
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3092
|
+
<plist version="1.0">
|
|
3093
|
+
<dict>
|
|
3094
|
+
<key>Label</key>
|
|
3095
|
+
<string>com.rigstate.daemon</string>
|
|
3096
|
+
<key>ProgramArguments</key>
|
|
3097
|
+
<array>
|
|
3098
|
+
<string>${nodePath}</string>
|
|
3099
|
+
<string>${scriptPath}</string>
|
|
3100
|
+
<string>daemon</string>
|
|
3101
|
+
<string>--no-bridge</string>
|
|
3102
|
+
</array>
|
|
3103
|
+
<key>WorkingDirectory</key>
|
|
3104
|
+
<string>${process.cwd()}</string>
|
|
3105
|
+
<key>StandardOutPath</key>
|
|
3106
|
+
<string>${import_path19.default.join(logDir, "daemon.out.log")}</string>
|
|
3107
|
+
<key>StandardErrorPath</key>
|
|
3108
|
+
<string>${import_path19.default.join(logDir, "daemon.err.log")}</string>
|
|
3109
|
+
<key>RunAtLoad</key>
|
|
3110
|
+
<true/>
|
|
3111
|
+
<key>KeepAlive</key>
|
|
3112
|
+
<true/>
|
|
3113
|
+
<key>EnvironmentVariables</key>
|
|
3114
|
+
<dict>
|
|
3115
|
+
<key>PATH</key>
|
|
3116
|
+
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${process.env.PATH}</string>
|
|
3117
|
+
</dict>
|
|
3118
|
+
</dict>
|
|
3119
|
+
</plist>`;
|
|
3120
|
+
try {
|
|
3121
|
+
await import_promises17.default.writeFile(plistPath, plistContent);
|
|
3122
|
+
console.log(import_chalk17.default.dim(`Created plist at: ${plistPath}`));
|
|
3123
|
+
try {
|
|
3124
|
+
await execShellCommand(`launchctl unload ${plistPath}`);
|
|
3125
|
+
} catch (e) {
|
|
3126
|
+
}
|
|
3127
|
+
await execShellCommand(`launchctl load ${plistPath}`);
|
|
3128
|
+
console.log(import_chalk17.default.green("\u2705 Successfully enabled background daemon!"));
|
|
3129
|
+
console.log(import_chalk17.default.dim(`Logs: ${logDir}`));
|
|
3130
|
+
console.log(import_chalk17.default.dim("The daemon will now restart automatically if it crashes or on reboot."));
|
|
3131
|
+
} catch (error) {
|
|
3132
|
+
console.error(import_chalk17.default.red("\u274C Failed to enable daemon:"), error.message);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
async function disableDaemon() {
|
|
3136
|
+
console.log(import_chalk17.default.bold("\n\u2699\uFE0F Disabling Rigstate Background Service\n"));
|
|
3137
|
+
const homeDir = process.env.HOME || "";
|
|
3138
|
+
const plistPath = import_path19.default.join(homeDir, "Library/LaunchAgents/com.rigstate.daemon.plist");
|
|
3139
|
+
try {
|
|
3140
|
+
await execShellCommand(`launchctl unload ${plistPath}`);
|
|
3141
|
+
await import_promises17.default.unlink(plistPath);
|
|
3142
|
+
console.log(import_chalk17.default.green("\u2705 Successfully disabled background daemon."));
|
|
3143
|
+
} catch (error) {
|
|
3144
|
+
if (error.code === "ENOENT") {
|
|
3145
|
+
console.log(import_chalk17.default.green("\u2705 Daemon was not enabled."));
|
|
3146
|
+
} else {
|
|
3147
|
+
console.error(import_chalk17.default.red("\u274C Failed to disable daemon:"), error.message);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
function execShellCommand(cmd) {
|
|
3152
|
+
const exec = require("child_process").exec;
|
|
3153
|
+
return new Promise((resolve, reject) => {
|
|
3154
|
+
exec(cmd, (error, stdout, stderr) => {
|
|
3155
|
+
if (error) {
|
|
3156
|
+
}
|
|
3157
|
+
resolve(stdout ? stdout : stderr);
|
|
3158
|
+
});
|
|
3159
|
+
});
|
|
3160
|
+
}
|
|
2731
3161
|
|
|
2732
3162
|
// src/commands/work.ts
|
|
2733
3163
|
init_cjs_shims();
|
|
2734
|
-
var
|
|
2735
|
-
var
|
|
2736
|
-
var
|
|
2737
|
-
var
|
|
3164
|
+
var import_commander12 = require("commander");
|
|
3165
|
+
var import_chalk18 = __toESM(require("chalk"), 1);
|
|
3166
|
+
var import_ora9 = __toESM(require("ora"), 1);
|
|
3167
|
+
var import_axios14 = __toESM(require("axios"), 1);
|
|
2738
3168
|
var import_inquirer2 = __toESM(require("inquirer"), 1);
|
|
2739
|
-
var
|
|
3169
|
+
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
2740
3170
|
init_config();
|
|
2741
3171
|
function createWorkCommand() {
|
|
2742
|
-
return new
|
|
2743
|
-
const spinner = (0,
|
|
3172
|
+
return new import_commander12.Command("work").alias("start").description("Select and execute a Roadmap Task (fetches IDE Prompt)").argument("[taskId]", "Optional Task ID (e.g., T-1021) to start immediately").option("--project <id>", "Project ID").action(async (taskId, options) => {
|
|
3173
|
+
const spinner = (0, import_ora9.default)();
|
|
2744
3174
|
try {
|
|
2745
3175
|
const apiKey = getApiKey();
|
|
2746
3176
|
const apiUrl = getApiUrl();
|
|
2747
3177
|
const projectId = options.project || getProjectId();
|
|
2748
3178
|
if (!projectId) {
|
|
2749
|
-
console.log(
|
|
3179
|
+
console.log(import_chalk18.default.red("\u274C Project ID is required. Run `rigstate link` or pass --project <id>"));
|
|
2750
3180
|
process.exit(1);
|
|
2751
3181
|
}
|
|
2752
3182
|
if (!taskId) {
|
|
2753
3183
|
spinner.start("Fetching active roadmap tasks...");
|
|
2754
3184
|
}
|
|
2755
|
-
const response = await
|
|
3185
|
+
const response = await import_axios14.default.get(
|
|
2756
3186
|
`${apiUrl}/api/v1/roadmap?project_id=${projectId}`,
|
|
2757
3187
|
{ headers: { "Authorization": `Bearer ${apiKey}` }, timeout: 1e4 }
|
|
2758
3188
|
);
|
|
@@ -2772,20 +3202,20 @@ function createWorkCommand() {
|
|
|
2772
3202
|
(t) => t.id === taskId || `T-${t.step_number}` === taskId || t.step_number.toString() === taskId
|
|
2773
3203
|
);
|
|
2774
3204
|
if (!selectedTask) {
|
|
2775
|
-
console.log(
|
|
3205
|
+
console.log(import_chalk18.default.red(`\u274C Task '${taskId}' not found in roadmap.`));
|
|
2776
3206
|
return;
|
|
2777
3207
|
}
|
|
2778
3208
|
} else {
|
|
2779
3209
|
if (actionableTasks.length === 0) {
|
|
2780
|
-
console.log(
|
|
3210
|
+
console.log(import_chalk18.default.yellow("No active or locked tasks found. The Roadmap is clear! \u{1F389}"));
|
|
2781
3211
|
return;
|
|
2782
3212
|
}
|
|
2783
3213
|
const choices = actionableTasks.map((t) => {
|
|
2784
3214
|
const id = `T-${t.step_number}`;
|
|
2785
3215
|
const statusIcon = t.status === "ACTIVE" ? "\u25B6\uFE0F" : "\u{1F512}";
|
|
2786
|
-
const priority = t.priority === "MVP" ?
|
|
3216
|
+
const priority = t.priority === "MVP" ? import_chalk18.default.magenta("[MVP]") : import_chalk18.default.blue(`[${t.priority}]`);
|
|
2787
3217
|
return {
|
|
2788
|
-
name: `${statusIcon} ${
|
|
3218
|
+
name: `${statusIcon} ${import_chalk18.default.bold(id)}: ${t.title} ${priority}`,
|
|
2789
3219
|
value: t,
|
|
2790
3220
|
short: `${id}: ${t.title}`
|
|
2791
3221
|
};
|
|
@@ -2799,13 +3229,13 @@ function createWorkCommand() {
|
|
|
2799
3229
|
}]);
|
|
2800
3230
|
selectedTask = answer.task;
|
|
2801
3231
|
}
|
|
2802
|
-
console.log("\n" +
|
|
2803
|
-
console.log(
|
|
3232
|
+
console.log("\n" + import_chalk18.default.bold.underline(`\u{1F680} WORK MODE: ${selectedTask.title}`));
|
|
3233
|
+
console.log(import_chalk18.default.dim(`ID: T-${selectedTask.step_number} | Status: ${selectedTask.status}`));
|
|
2804
3234
|
if (selectedTask.prompt_content) {
|
|
2805
|
-
console.log(
|
|
2806
|
-
console.log(
|
|
3235
|
+
console.log(import_chalk18.default.yellow.bold("\n\u{1F4CB} IDE EXECUTION SIGNAL (Prompt):"));
|
|
3236
|
+
console.log(import_chalk18.default.gray("--------------------------------------------------"));
|
|
2807
3237
|
console.log(selectedTask.prompt_content);
|
|
2808
|
-
console.log(
|
|
3238
|
+
console.log(import_chalk18.default.gray("--------------------------------------------------"));
|
|
2809
3239
|
const { action } = await import_inquirer2.default.prompt([{
|
|
2810
3240
|
type: "list",
|
|
2811
3241
|
name: "action",
|
|
@@ -2819,41 +3249,41 @@ function createWorkCommand() {
|
|
|
2819
3249
|
]
|
|
2820
3250
|
}]);
|
|
2821
3251
|
if (action === "cursorrules") {
|
|
2822
|
-
await
|
|
2823
|
-
console.log(
|
|
2824
|
-
console.log(
|
|
3252
|
+
await import_promises18.default.writeFile(".rigstate-prompt.md", selectedTask.prompt_content);
|
|
3253
|
+
console.log(import_chalk18.default.green(`\u2705 Prompt saved to ${import_chalk18.default.bold(".rigstate-prompt.md")}`));
|
|
3254
|
+
console.log(import_chalk18.default.dim("You can now reference this file in your IDE chat (@.rigstate-prompt.md)"));
|
|
2825
3255
|
} else if (action === "print") {
|
|
2826
3256
|
console.log("\n" + selectedTask.prompt_content + "\n");
|
|
2827
3257
|
} else if (action === "activate" && selectedTask.status !== "ACTIVE") {
|
|
2828
3258
|
try {
|
|
2829
|
-
await
|
|
3259
|
+
await import_axios14.default.post(
|
|
2830
3260
|
`${apiUrl}/api/v1/roadmap/update-status`,
|
|
2831
3261
|
{ step_id: selectedTask.id, status: "ACTIVE", project_id: projectId },
|
|
2832
3262
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
2833
3263
|
);
|
|
2834
|
-
console.log(
|
|
3264
|
+
console.log(import_chalk18.default.green(`\u2705 Task marked as ACTIVE.`));
|
|
2835
3265
|
} catch (e) {
|
|
2836
|
-
console.error(
|
|
3266
|
+
console.error(import_chalk18.default.red(`Failed to update status: ${e.message}`));
|
|
2837
3267
|
}
|
|
2838
3268
|
} else if (action === "complete") {
|
|
2839
3269
|
try {
|
|
2840
|
-
await
|
|
3270
|
+
await import_axios14.default.post(
|
|
2841
3271
|
`${apiUrl}/api/v1/roadmap/update-status`,
|
|
2842
3272
|
{ step_id: selectedTask.id, status: "COMPLETED", project_id: projectId },
|
|
2843
3273
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
2844
3274
|
);
|
|
2845
|
-
console.log(
|
|
3275
|
+
console.log(import_chalk18.default.green(`\u2705 Task marked as COMPLETED. Great job!`));
|
|
2846
3276
|
} catch (e) {
|
|
2847
|
-
console.error(
|
|
3277
|
+
console.error(import_chalk18.default.red(`Failed to update status: ${e.message}`));
|
|
2848
3278
|
}
|
|
2849
3279
|
}
|
|
2850
3280
|
} else {
|
|
2851
|
-
console.log(
|
|
2852
|
-
console.log(
|
|
3281
|
+
console.log(import_chalk18.default.yellow("\n\u26A0\uFE0F No specific IDE Prompt found for this task (Legacy Task?)."));
|
|
3282
|
+
console.log(import_chalk18.default.dim("Objective: " + (selectedTask.summary || selectedTask.description || "Check web UI for details.")));
|
|
2853
3283
|
}
|
|
2854
3284
|
} catch (error) {
|
|
2855
3285
|
spinner.stop();
|
|
2856
|
-
console.error(
|
|
3286
|
+
console.error(import_chalk18.default.red(`
|
|
2857
3287
|
Command failed: ${error.message}`));
|
|
2858
3288
|
}
|
|
2859
3289
|
});
|
|
@@ -2861,41 +3291,41 @@ Command failed: ${error.message}`));
|
|
|
2861
3291
|
|
|
2862
3292
|
// src/commands/watch.ts
|
|
2863
3293
|
init_cjs_shims();
|
|
2864
|
-
var
|
|
2865
|
-
var
|
|
2866
|
-
var
|
|
3294
|
+
var import_commander13 = require("commander");
|
|
3295
|
+
var import_chalk19 = __toESM(require("chalk"), 1);
|
|
3296
|
+
var import_ora10 = __toESM(require("ora"), 1);
|
|
2867
3297
|
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
2868
|
-
var
|
|
2869
|
-
var
|
|
3298
|
+
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
3299
|
+
var import_path20 = __toESM(require("path"), 1);
|
|
2870
3300
|
var import_child_process3 = require("child_process");
|
|
2871
3301
|
init_config();
|
|
2872
|
-
var
|
|
3302
|
+
var import_axios15 = __toESM(require("axios"), 1);
|
|
2873
3303
|
function createWatchCommand() {
|
|
2874
|
-
const watch2 = new
|
|
3304
|
+
const watch2 = new import_commander13.Command("watch");
|
|
2875
3305
|
watch2.description("Watch for changes and auto-verify roadmap tasks").option("--no-auto-commit", "Disable auto-commit on verification").option("--no-auto-push", "Disable auto-push after commit").option("--run-tests", "Run tests before committing").option("--test-command <cmd>", "Custom test command (default: npm test)").action(async (options) => {
|
|
2876
|
-
console.log(
|
|
2877
|
-
console.log(
|
|
3306
|
+
console.log(import_chalk19.default.bold.blue("\u{1F52D} Rigstate Watch Mode"));
|
|
3307
|
+
console.log(import_chalk19.default.dim("Monitoring for task completion..."));
|
|
2878
3308
|
console.log("");
|
|
2879
3309
|
let apiKey;
|
|
2880
3310
|
let projectId;
|
|
2881
3311
|
try {
|
|
2882
3312
|
apiKey = getApiKey();
|
|
2883
3313
|
} catch (e) {
|
|
2884
|
-
console.log(
|
|
3314
|
+
console.log(import_chalk19.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
2885
3315
|
return;
|
|
2886
3316
|
}
|
|
2887
3317
|
projectId = getProjectId();
|
|
2888
3318
|
if (!projectId) {
|
|
2889
3319
|
try {
|
|
2890
|
-
const manifestPath =
|
|
2891
|
-
const content = await
|
|
3320
|
+
const manifestPath = import_path20.default.join(process.cwd(), ".rigstate");
|
|
3321
|
+
const content = await import_promises19.default.readFile(manifestPath, "utf-8");
|
|
2892
3322
|
const manifest = JSON.parse(content);
|
|
2893
3323
|
projectId = manifest.project_id;
|
|
2894
3324
|
} catch (e) {
|
|
2895
3325
|
}
|
|
2896
3326
|
}
|
|
2897
3327
|
if (!projectId) {
|
|
2898
|
-
console.log(
|
|
3328
|
+
console.log(import_chalk19.default.red('No project context. Run "rigstate link" or "rigstate sync --project <id>" first.'));
|
|
2899
3329
|
return;
|
|
2900
3330
|
}
|
|
2901
3331
|
const apiUrl = getApiUrl();
|
|
@@ -2905,12 +3335,12 @@ function createWatchCommand() {
|
|
|
2905
3335
|
runTests: options.runTests || false,
|
|
2906
3336
|
testCommand: options.testCommand || "npm test"
|
|
2907
3337
|
};
|
|
2908
|
-
console.log(
|
|
2909
|
-
console.log(
|
|
3338
|
+
console.log(import_chalk19.default.dim(`Auto-commit: ${config2.autoCommit ? "ON" : "OFF"}`));
|
|
3339
|
+
console.log(import_chalk19.default.dim(`Auto-push: ${config2.autoPush ? "ON" : "OFF"}`));
|
|
2910
3340
|
console.log("");
|
|
2911
3341
|
const fetchActiveTask = async () => {
|
|
2912
3342
|
try {
|
|
2913
|
-
const response = await
|
|
3343
|
+
const response = await import_axios15.default.get(`${apiUrl}/api/v1/roadmap`, {
|
|
2914
3344
|
params: { project_id: projectId },
|
|
2915
3345
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2916
3346
|
});
|
|
@@ -2934,17 +3364,17 @@ function createWatchCommand() {
|
|
|
2934
3364
|
};
|
|
2935
3365
|
const checkCriteria = async (criteria) => {
|
|
2936
3366
|
try {
|
|
2937
|
-
const fullPath =
|
|
3367
|
+
const fullPath = import_path20.default.resolve(process.cwd(), criteria.path);
|
|
2938
3368
|
switch (criteria.type) {
|
|
2939
3369
|
case "file_exists":
|
|
2940
|
-
await
|
|
3370
|
+
await import_promises19.default.access(fullPath);
|
|
2941
3371
|
return true;
|
|
2942
3372
|
case "file_content":
|
|
2943
|
-
const content = await
|
|
3373
|
+
const content = await import_promises19.default.readFile(fullPath, "utf-8");
|
|
2944
3374
|
return content.length > 0;
|
|
2945
3375
|
case "content_match":
|
|
2946
3376
|
if (!criteria.match) return false;
|
|
2947
|
-
const fileContent = await
|
|
3377
|
+
const fileContent = await import_promises19.default.readFile(fullPath, "utf-8");
|
|
2948
3378
|
return fileContent.includes(criteria.match);
|
|
2949
3379
|
default:
|
|
2950
3380
|
return false;
|
|
@@ -2954,7 +3384,7 @@ function createWatchCommand() {
|
|
|
2954
3384
|
}
|
|
2955
3385
|
};
|
|
2956
3386
|
const completeTask = async (taskId, task) => {
|
|
2957
|
-
const spinner = (0,
|
|
3387
|
+
const spinner = (0, import_ora10.default)("Completing task...").start();
|
|
2958
3388
|
try {
|
|
2959
3389
|
if (config2.runTests) {
|
|
2960
3390
|
spinner.text = "Running tests...";
|
|
@@ -2966,14 +3396,14 @@ function createWatchCommand() {
|
|
|
2966
3396
|
return;
|
|
2967
3397
|
}
|
|
2968
3398
|
}
|
|
2969
|
-
await
|
|
3399
|
+
await import_axios15.default.post(`${apiUrl}/api/v1/roadmap/update-status`, {
|
|
2970
3400
|
project_id: projectId,
|
|
2971
3401
|
chunk_id: taskId,
|
|
2972
3402
|
status: "COMPLETED"
|
|
2973
3403
|
}, {
|
|
2974
3404
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2975
3405
|
});
|
|
2976
|
-
spinner.succeed(
|
|
3406
|
+
spinner.succeed(import_chalk19.default.green(`\u2705 Task #${task.step_number} completed: ${task.title}`));
|
|
2977
3407
|
if (config2.autoCommit) {
|
|
2978
3408
|
spinner.start("Committing changes...");
|
|
2979
3409
|
try {
|
|
@@ -2995,7 +3425,7 @@ function createWatchCommand() {
|
|
|
2995
3425
|
}
|
|
2996
3426
|
}
|
|
2997
3427
|
console.log("");
|
|
2998
|
-
console.log(
|
|
3428
|
+
console.log(import_chalk19.default.blue("Watching for next task..."));
|
|
2999
3429
|
} catch (e) {
|
|
3000
3430
|
spinner.fail(`Failed to complete task: ${e.message}`);
|
|
3001
3431
|
}
|
|
@@ -3008,7 +3438,7 @@ function createWatchCommand() {
|
|
|
3008
3438
|
const task = await fetchActiveTask();
|
|
3009
3439
|
if (!task) {
|
|
3010
3440
|
if (currentTask) {
|
|
3011
|
-
console.log(
|
|
3441
|
+
console.log(import_chalk19.default.green("\u{1F389} All tasks completed! Watching for new tasks..."));
|
|
3012
3442
|
currentTask = null;
|
|
3013
3443
|
}
|
|
3014
3444
|
isProcessing = false;
|
|
@@ -3017,10 +3447,10 @@ function createWatchCommand() {
|
|
|
3017
3447
|
if (!currentTask || currentTask.id !== task.id) {
|
|
3018
3448
|
currentTask = task;
|
|
3019
3449
|
console.log("");
|
|
3020
|
-
console.log(
|
|
3021
|
-
console.log(
|
|
3450
|
+
console.log(import_chalk19.default.bold.yellow(`\u{1F4CC} Active Task #${task.step_number}: ${task.title}`));
|
|
3451
|
+
console.log(import_chalk19.default.dim(`Status: ${task.status}`));
|
|
3022
3452
|
if (task.verification_criteria) {
|
|
3023
|
-
console.log(
|
|
3453
|
+
console.log(import_chalk19.default.dim("Verification: Auto-checking criteria..."));
|
|
3024
3454
|
}
|
|
3025
3455
|
}
|
|
3026
3456
|
if (task.verification_criteria && Array.isArray(task.verification_criteria)) {
|
|
@@ -3033,7 +3463,7 @@ function createWatchCommand() {
|
|
|
3033
3463
|
}
|
|
3034
3464
|
}
|
|
3035
3465
|
if (allPassed) {
|
|
3036
|
-
console.log(
|
|
3466
|
+
console.log(import_chalk19.default.green("\u2713 All verification criteria passed!"));
|
|
3037
3467
|
await completeTask(task.id, task);
|
|
3038
3468
|
currentTask = null;
|
|
3039
3469
|
}
|
|
@@ -3058,11 +3488,11 @@ function createWatchCommand() {
|
|
|
3058
3488
|
setTimeout(() => processActiveTask(), 500);
|
|
3059
3489
|
}
|
|
3060
3490
|
});
|
|
3061
|
-
console.log(
|
|
3491
|
+
console.log(import_chalk19.default.dim("Watching for file changes... (Ctrl+C to exit)"));
|
|
3062
3492
|
setInterval(() => processActiveTask(), 3e4);
|
|
3063
3493
|
process.on("SIGINT", () => {
|
|
3064
3494
|
console.log("");
|
|
3065
|
-
console.log(
|
|
3495
|
+
console.log(import_chalk19.default.dim("Watch mode stopped."));
|
|
3066
3496
|
watcher.close();
|
|
3067
3497
|
process.exit(0);
|
|
3068
3498
|
});
|
|
@@ -3072,43 +3502,43 @@ function createWatchCommand() {
|
|
|
3072
3502
|
|
|
3073
3503
|
// src/commands/focus.ts
|
|
3074
3504
|
init_cjs_shims();
|
|
3075
|
-
var
|
|
3076
|
-
var
|
|
3077
|
-
var
|
|
3505
|
+
var import_commander14 = require("commander");
|
|
3506
|
+
var import_chalk20 = __toESM(require("chalk"), 1);
|
|
3507
|
+
var import_ora11 = __toESM(require("ora"), 1);
|
|
3078
3508
|
init_config();
|
|
3079
|
-
var
|
|
3509
|
+
var import_axios16 = __toESM(require("axios"), 1);
|
|
3080
3510
|
var import_child_process4 = require("child_process");
|
|
3081
|
-
var
|
|
3082
|
-
var
|
|
3511
|
+
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
3512
|
+
var import_path21 = __toESM(require("path"), 1);
|
|
3083
3513
|
function createFocusCommand() {
|
|
3084
|
-
const focus = new
|
|
3514
|
+
const focus = new import_commander14.Command("focus");
|
|
3085
3515
|
focus.alias("task").description("Get the next active roadmap task and copy its prompt to clipboard").option("--no-copy", "Do not copy to clipboard").action(async (options) => {
|
|
3086
|
-
const spinner = (0,
|
|
3516
|
+
const spinner = (0, import_ora11.default)("Fetching next objective...").start();
|
|
3087
3517
|
let apiKey;
|
|
3088
3518
|
let projectId;
|
|
3089
3519
|
try {
|
|
3090
3520
|
apiKey = getApiKey();
|
|
3091
3521
|
} catch (e) {
|
|
3092
|
-
spinner.fail(
|
|
3522
|
+
spinner.fail(import_chalk20.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
3093
3523
|
return;
|
|
3094
3524
|
}
|
|
3095
3525
|
projectId = getProjectId();
|
|
3096
3526
|
if (!projectId) {
|
|
3097
3527
|
try {
|
|
3098
|
-
const manifestPath =
|
|
3099
|
-
const content = await
|
|
3528
|
+
const manifestPath = import_path21.default.join(process.cwd(), ".rigstate");
|
|
3529
|
+
const content = await import_promises20.default.readFile(manifestPath, "utf-8");
|
|
3100
3530
|
const manifest = JSON.parse(content);
|
|
3101
3531
|
projectId = manifest.project_id;
|
|
3102
3532
|
} catch (e) {
|
|
3103
3533
|
}
|
|
3104
3534
|
}
|
|
3105
3535
|
if (!projectId) {
|
|
3106
|
-
spinner.fail(
|
|
3536
|
+
spinner.fail(import_chalk20.default.red('No project context. Run "rigstate link" first.'));
|
|
3107
3537
|
return;
|
|
3108
3538
|
}
|
|
3109
3539
|
const apiUrl = getApiUrl();
|
|
3110
3540
|
try {
|
|
3111
|
-
const response = await
|
|
3541
|
+
const response = await import_axios16.default.get(`${apiUrl}/api/v1/roadmap`, {
|
|
3112
3542
|
params: { project_id: projectId },
|
|
3113
3543
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3114
3544
|
});
|
|
@@ -3134,188 +3564,72 @@ function createFocusCommand() {
|
|
|
3134
3564
|
const nextTask = activeTasks[0];
|
|
3135
3565
|
spinner.stop();
|
|
3136
3566
|
console.log("");
|
|
3137
|
-
console.log(
|
|
3138
|
-
const statusColor = nextTask.status === "IN_PROGRESS" ?
|
|
3139
|
-
console.log(
|
|
3140
|
-
console.log(
|
|
3567
|
+
console.log(import_chalk20.default.bold.blue(`\u{1F4CC} Task #${nextTask.step_number || "?"}: ${nextTask.title}`));
|
|
3568
|
+
const statusColor = nextTask.status === "IN_PROGRESS" ? import_chalk20.default.yellow : nextTask.status === "ACTIVE" ? import_chalk20.default.green : import_chalk20.default.dim;
|
|
3569
|
+
console.log(import_chalk20.default.dim("Status: ") + statusColor(nextTask.status));
|
|
3570
|
+
console.log(import_chalk20.default.dim("\u2500".repeat(60)));
|
|
3141
3571
|
if (nextTask.prompt_content) {
|
|
3142
|
-
console.log(
|
|
3143
|
-
console.log(
|
|
3572
|
+
console.log(import_chalk20.default.white(nextTask.prompt_content));
|
|
3573
|
+
console.log(import_chalk20.default.dim("\u2500".repeat(60)));
|
|
3144
3574
|
if (options.copy !== false) {
|
|
3145
3575
|
try {
|
|
3146
3576
|
if (process.platform === "darwin") {
|
|
3147
3577
|
(0, import_child_process4.execSync)("pbcopy", { input: nextTask.prompt_content });
|
|
3148
|
-
console.log(
|
|
3578
|
+
console.log(import_chalk20.default.green("\u2705 Prompt copied to clipboard! Ready to paste (Cmd+V)."));
|
|
3149
3579
|
} else if (process.platform === "linux") {
|
|
3150
3580
|
try {
|
|
3151
3581
|
(0, import_child_process4.execSync)("xclip -selection clipboard", { input: nextTask.prompt_content });
|
|
3152
|
-
console.log(
|
|
3582
|
+
console.log(import_chalk20.default.green("\u2705 Prompt copied to clipboard!"));
|
|
3153
3583
|
} catch (e) {
|
|
3154
|
-
console.log(
|
|
3584
|
+
console.log(import_chalk20.default.yellow("\u2139\uFE0F Copy prompt manually (xclip not available)"));
|
|
3155
3585
|
}
|
|
3156
3586
|
} else {
|
|
3157
|
-
console.log(
|
|
3587
|
+
console.log(import_chalk20.default.yellow("\u2139\uFE0F Copy prompt manually (Auto-copy not supported on this OS)"));
|
|
3158
3588
|
}
|
|
3159
3589
|
} catch (e) {
|
|
3160
3590
|
}
|
|
3161
3591
|
}
|
|
3162
3592
|
} else {
|
|
3163
|
-
console.log(
|
|
3593
|
+
console.log(import_chalk20.default.yellow("No prompt instructions available."));
|
|
3164
3594
|
if (nextTask.architectural_brief) {
|
|
3165
|
-
console.log(
|
|
3595
|
+
console.log(import_chalk20.default.bold("Brief:"));
|
|
3166
3596
|
console.log(nextTask.architectural_brief);
|
|
3167
3597
|
}
|
|
3168
3598
|
}
|
|
3169
3599
|
console.log("");
|
|
3170
3600
|
} catch (e) {
|
|
3171
|
-
spinner.fail(
|
|
3601
|
+
spinner.fail(import_chalk20.default.red(`Failed to fetch task: ${e.message}`));
|
|
3172
3602
|
}
|
|
3173
3603
|
});
|
|
3174
3604
|
return focus;
|
|
3175
3605
|
}
|
|
3176
3606
|
|
|
3177
|
-
// src/
|
|
3178
|
-
|
|
3179
|
-
var import_commander13 = require("commander");
|
|
3180
|
-
var import_chalk19 = __toESM(require("chalk"), 1);
|
|
3181
|
-
var import_ora10 = __toESM(require("ora"), 1);
|
|
3182
|
-
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
3183
|
-
var import_path21 = __toESM(require("path"), 1);
|
|
3184
|
-
init_config();
|
|
3185
|
-
var import_axios15 = __toESM(require("axios"), 1);
|
|
3186
|
-
function createEnvPullCommand() {
|
|
3187
|
-
const envPull = new import_commander13.Command("env");
|
|
3188
|
-
envPull.command("pull").description("Pull environment variables from project vault").action(async () => {
|
|
3189
|
-
console.log("");
|
|
3190
|
-
console.log(import_chalk19.default.bold.yellow("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
3191
|
-
console.log(import_chalk19.default.bold.yellow("\u2551") + import_chalk19.default.bold.white(" \u{1F6E1}\uFE0F RIGSTATE SOVEREIGN VAULT SYNC \u{1F6E1}\uFE0F ") + import_chalk19.default.bold.yellow("\u2551"));
|
|
3192
|
-
console.log(import_chalk19.default.bold.yellow("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
|
|
3193
|
-
console.log("");
|
|
3194
|
-
const spinner = (0, import_ora10.default)("Authenticating with Vault...").start();
|
|
3195
|
-
let apiKey;
|
|
3196
|
-
let projectId;
|
|
3197
|
-
try {
|
|
3198
|
-
apiKey = getApiKey();
|
|
3199
|
-
} catch (e) {
|
|
3200
|
-
spinner.fail(import_chalk19.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
3201
|
-
return;
|
|
3202
|
-
}
|
|
3203
|
-
spinner.succeed("Authenticated");
|
|
3204
|
-
spinner.start("Reading project configuration...");
|
|
3205
|
-
projectId = getProjectId();
|
|
3206
|
-
if (!projectId) {
|
|
3207
|
-
try {
|
|
3208
|
-
const manifestPath = import_path21.default.join(process.cwd(), ".rigstate");
|
|
3209
|
-
const content = await import_promises20.default.readFile(manifestPath, "utf-8");
|
|
3210
|
-
const manifest = JSON.parse(content);
|
|
3211
|
-
projectId = manifest.project_id;
|
|
3212
|
-
} catch (e) {
|
|
3213
|
-
}
|
|
3214
|
-
}
|
|
3215
|
-
if (!projectId) {
|
|
3216
|
-
spinner.fail(import_chalk19.default.red('No project context. Run "rigstate link" first.'));
|
|
3217
|
-
return;
|
|
3218
|
-
}
|
|
3219
|
-
spinner.succeed(`Project: ${import_chalk19.default.cyan(projectId.substring(0, 8))}...`);
|
|
3220
|
-
const apiUrl = getApiUrl();
|
|
3221
|
-
spinner.start("Fetching secrets from Vault...");
|
|
3222
|
-
try {
|
|
3223
|
-
const response = await import_axios15.default.post(`${apiUrl}/api/v1/vault/sync`, {
|
|
3224
|
-
project_id: projectId
|
|
3225
|
-
}, {
|
|
3226
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3227
|
-
});
|
|
3228
|
-
if (!response.data.success) {
|
|
3229
|
-
throw new Error(response.data.error || "Failed to fetch secrets");
|
|
3230
|
-
}
|
|
3231
|
-
const vaultContent = response.data.data.content || "";
|
|
3232
|
-
const secretCount = response.data.data.count || 0;
|
|
3233
|
-
if (secretCount === 0) {
|
|
3234
|
-
spinner.info("No secrets found in Vault for this project.");
|
|
3235
|
-
console.log(import_chalk19.default.dim(" Add secrets via the Rigstate web interface."));
|
|
3236
|
-
return;
|
|
3237
|
-
}
|
|
3238
|
-
spinner.succeed(`Retrieved ${import_chalk19.default.bold(secretCount)} secret(s)`);
|
|
3239
|
-
const envFile = import_path21.default.resolve(process.cwd(), ".env.local");
|
|
3240
|
-
let existingContent = "";
|
|
3241
|
-
let existingKeys = /* @__PURE__ */ new Set();
|
|
3242
|
-
try {
|
|
3243
|
-
existingContent = await import_promises20.default.readFile(envFile, "utf-8");
|
|
3244
|
-
existingContent.split("\n").forEach((line) => {
|
|
3245
|
-
const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
|
|
3246
|
-
if (match) existingKeys.add(match[1]);
|
|
3247
|
-
});
|
|
3248
|
-
} catch (e) {
|
|
3249
|
-
}
|
|
3250
|
-
const vaultKeys = /* @__PURE__ */ new Set();
|
|
3251
|
-
vaultContent.split("\n").forEach((line) => {
|
|
3252
|
-
const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
|
|
3253
|
-
if (match) vaultKeys.add(match[1]);
|
|
3254
|
-
});
|
|
3255
|
-
let newCount = 0;
|
|
3256
|
-
let updatedCount = 0;
|
|
3257
|
-
vaultKeys.forEach((key) => {
|
|
3258
|
-
if (!existingKeys.has(key)) {
|
|
3259
|
-
newCount++;
|
|
3260
|
-
} else {
|
|
3261
|
-
updatedCount++;
|
|
3262
|
-
}
|
|
3263
|
-
});
|
|
3264
|
-
const unchangedCount = existingKeys.size - updatedCount;
|
|
3265
|
-
spinner.start("Writing .env.local...");
|
|
3266
|
-
const header = [
|
|
3267
|
-
"# ==========================================",
|
|
3268
|
-
"# RIGSTATE SOVEREIGN FOUNDATION",
|
|
3269
|
-
"# Authenticated Environment Configuration",
|
|
3270
|
-
`# Synced at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
3271
|
-
`# Project: ${projectId}`,
|
|
3272
|
-
"# ==========================================",
|
|
3273
|
-
""
|
|
3274
|
-
].join("\n");
|
|
3275
|
-
await import_promises20.default.writeFile(envFile, header + vaultContent + "\n");
|
|
3276
|
-
spinner.succeed("Written to .env.local");
|
|
3277
|
-
console.log("");
|
|
3278
|
-
console.log(import_chalk19.default.bold.green("\u2705 Environment synchronized successfully"));
|
|
3279
|
-
console.log("");
|
|
3280
|
-
console.log(import_chalk19.default.dim(" Summary:"));
|
|
3281
|
-
console.log(import_chalk19.default.green(` + ${newCount} new`));
|
|
3282
|
-
console.log(import_chalk19.default.yellow(` ~ ${updatedCount} updated`));
|
|
3283
|
-
console.log(import_chalk19.default.dim(` = ${unchangedCount} unchanged`));
|
|
3284
|
-
console.log("");
|
|
3285
|
-
console.log(import_chalk19.default.bold.yellow("\u26A0\uFE0F Security Reminder:"));
|
|
3286
|
-
console.log(import_chalk19.default.dim(" - Never commit .env.local to version control."));
|
|
3287
|
-
console.log(import_chalk19.default.dim(" - Ensure .gitignore includes .env.local"));
|
|
3288
|
-
console.log("");
|
|
3289
|
-
} catch (e) {
|
|
3290
|
-
spinner.fail(import_chalk19.default.red(`Failed to fetch secrets: ${e.message}`));
|
|
3291
|
-
}
|
|
3292
|
-
});
|
|
3293
|
-
return envPull;
|
|
3294
|
-
}
|
|
3607
|
+
// src/index.ts
|
|
3608
|
+
init_env();
|
|
3295
3609
|
|
|
3296
3610
|
// src/commands/config.ts
|
|
3297
3611
|
init_cjs_shims();
|
|
3298
|
-
var
|
|
3299
|
-
var
|
|
3612
|
+
var import_commander15 = require("commander");
|
|
3613
|
+
var import_chalk21 = __toESM(require("chalk"), 1);
|
|
3300
3614
|
init_config();
|
|
3301
3615
|
function createConfigCommand() {
|
|
3302
|
-
const config2 = new
|
|
3616
|
+
const config2 = new import_commander15.Command("config");
|
|
3303
3617
|
config2.description("View or modify Rigstate configuration").argument("[key]", "Configuration key to view/set (api_key, project_id, api_url)").argument("[value]", "Value to set").action(async (key, value) => {
|
|
3304
3618
|
if (!key) {
|
|
3305
|
-
console.log(
|
|
3306
|
-
console.log(
|
|
3619
|
+
console.log(import_chalk21.default.bold("Rigstate Configuration"));
|
|
3620
|
+
console.log(import_chalk21.default.dim("\u2500".repeat(40)));
|
|
3307
3621
|
try {
|
|
3308
3622
|
const apiKey = getApiKey();
|
|
3309
|
-
console.log(`${
|
|
3623
|
+
console.log(`${import_chalk21.default.cyan("api_key")}: ${apiKey.substring(0, 20)}...`);
|
|
3310
3624
|
} catch (e) {
|
|
3311
|
-
console.log(`${
|
|
3625
|
+
console.log(`${import_chalk21.default.cyan("api_key")}: ${import_chalk21.default.dim("(not set)")}`);
|
|
3312
3626
|
}
|
|
3313
3627
|
const projectId = getProjectId();
|
|
3314
|
-
console.log(`${
|
|
3628
|
+
console.log(`${import_chalk21.default.cyan("project_id")}: ${projectId || import_chalk21.default.dim("(not set)")}`);
|
|
3315
3629
|
const apiUrl = getApiUrl();
|
|
3316
|
-
console.log(`${
|
|
3630
|
+
console.log(`${import_chalk21.default.cyan("api_url")}: ${apiUrl}`);
|
|
3317
3631
|
console.log("");
|
|
3318
|
-
console.log(
|
|
3632
|
+
console.log(import_chalk21.default.dim('Use "rigstate config <key> <value>" to set a value.'));
|
|
3319
3633
|
return;
|
|
3320
3634
|
}
|
|
3321
3635
|
if (!value) {
|
|
@@ -3325,36 +3639,36 @@ function createConfigCommand() {
|
|
|
3325
3639
|
const apiKey = getApiKey();
|
|
3326
3640
|
console.log(apiKey);
|
|
3327
3641
|
} catch (e) {
|
|
3328
|
-
console.log(
|
|
3642
|
+
console.log(import_chalk21.default.dim("(not set)"));
|
|
3329
3643
|
}
|
|
3330
3644
|
break;
|
|
3331
3645
|
case "project_id":
|
|
3332
|
-
console.log(getProjectId() ||
|
|
3646
|
+
console.log(getProjectId() || import_chalk21.default.dim("(not set)"));
|
|
3333
3647
|
break;
|
|
3334
3648
|
case "api_url":
|
|
3335
3649
|
console.log(getApiUrl());
|
|
3336
3650
|
break;
|
|
3337
3651
|
default:
|
|
3338
|
-
console.log(
|
|
3339
|
-
console.log(
|
|
3652
|
+
console.log(import_chalk21.default.red(`Unknown config key: ${key}`));
|
|
3653
|
+
console.log(import_chalk21.default.dim("Valid keys: api_key, project_id, api_url"));
|
|
3340
3654
|
}
|
|
3341
3655
|
return;
|
|
3342
3656
|
}
|
|
3343
3657
|
switch (key) {
|
|
3344
3658
|
case "api_key":
|
|
3345
3659
|
setApiKey(value);
|
|
3346
|
-
console.log(
|
|
3660
|
+
console.log(import_chalk21.default.green(`\u2705 api_key updated`));
|
|
3347
3661
|
break;
|
|
3348
3662
|
case "project_id":
|
|
3349
3663
|
setProjectId(value);
|
|
3350
|
-
console.log(
|
|
3664
|
+
console.log(import_chalk21.default.green(`\u2705 project_id updated`));
|
|
3351
3665
|
break;
|
|
3352
3666
|
case "api_url":
|
|
3353
|
-
console.log(
|
|
3667
|
+
console.log(import_chalk21.default.yellow("api_url is set via RIGSTATE_API_URL environment variable"));
|
|
3354
3668
|
break;
|
|
3355
3669
|
default:
|
|
3356
|
-
console.log(
|
|
3357
|
-
console.log(
|
|
3670
|
+
console.log(import_chalk21.default.red(`Unknown config key: ${key}`));
|
|
3671
|
+
console.log(import_chalk21.default.dim("Valid keys: api_key, project_id"));
|
|
3358
3672
|
}
|
|
3359
3673
|
});
|
|
3360
3674
|
return config2;
|
|
@@ -3362,24 +3676,24 @@ function createConfigCommand() {
|
|
|
3362
3676
|
|
|
3363
3677
|
// src/commands/mcp.ts
|
|
3364
3678
|
init_cjs_shims();
|
|
3365
|
-
var
|
|
3366
|
-
var
|
|
3679
|
+
var import_commander16 = require("commander");
|
|
3680
|
+
var import_chalk22 = __toESM(require("chalk"), 1);
|
|
3367
3681
|
var import_child_process5 = require("child_process");
|
|
3368
3682
|
var import_path22 = __toESM(require("path"), 1);
|
|
3369
3683
|
var import_fs = __toESM(require("fs"), 1);
|
|
3370
3684
|
var import_url = require("url");
|
|
3371
3685
|
var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
|
|
3372
|
-
var
|
|
3686
|
+
var __dirname2 = import_path22.default.dirname(__filename2);
|
|
3373
3687
|
function createMcpCommand() {
|
|
3374
|
-
const mcp = new
|
|
3688
|
+
const mcp = new import_commander16.Command("mcp");
|
|
3375
3689
|
mcp.description("Run the Rigstate MCP server for AI editors").action(async () => {
|
|
3376
3690
|
const possiblePaths = [
|
|
3377
3691
|
// From packages/cli -> packages/mcp (sibling package)
|
|
3378
|
-
import_path22.default.resolve(
|
|
3692
|
+
import_path22.default.resolve(__dirname2, "../../mcp/dist/index.js"),
|
|
3379
3693
|
// If installed globally or via npm
|
|
3380
|
-
import_path22.default.resolve(
|
|
3694
|
+
import_path22.default.resolve(__dirname2, "../../../mcp/dist/index.js"),
|
|
3381
3695
|
// Development path from packages/cli/dist
|
|
3382
|
-
import_path22.default.resolve(
|
|
3696
|
+
import_path22.default.resolve(__dirname2, "../../../packages/mcp/dist/index.js")
|
|
3383
3697
|
];
|
|
3384
3698
|
let serverPath = "";
|
|
3385
3699
|
for (const p of possiblePaths) {
|
|
@@ -3389,15 +3703,15 @@ function createMcpCommand() {
|
|
|
3389
3703
|
}
|
|
3390
3704
|
}
|
|
3391
3705
|
if (!serverPath) {
|
|
3392
|
-
console.error(
|
|
3393
|
-
console.error(
|
|
3394
|
-
console.error(
|
|
3706
|
+
console.error(import_chalk22.default.red("\u274C Error: Rigstate MCP Server binary not found."));
|
|
3707
|
+
console.error(import_chalk22.default.yellow("Please ensure that the mcp package is built:"));
|
|
3708
|
+
console.error(import_chalk22.default.white(" cd packages/mcp && npm run build"));
|
|
3395
3709
|
console.error("");
|
|
3396
|
-
console.error(
|
|
3397
|
-
console.error(
|
|
3710
|
+
console.error(import_chalk22.default.dim("Or run directly with:"));
|
|
3711
|
+
console.error(import_chalk22.default.white(" npx @rigstate/mcp"));
|
|
3398
3712
|
process.exit(1);
|
|
3399
3713
|
}
|
|
3400
|
-
console.log(
|
|
3714
|
+
console.log(import_chalk22.default.dim(`Starting MCP server from: ${serverPath}`));
|
|
3401
3715
|
if (process.env.VIBE_API_KEY && !process.env.RIGSTATE_API_KEY) {
|
|
3402
3716
|
process.env.RIGSTATE_API_KEY = process.env.VIBE_API_KEY;
|
|
3403
3717
|
}
|
|
@@ -3406,7 +3720,7 @@ function createMcpCommand() {
|
|
|
3406
3720
|
stdio: ["inherit", "inherit", "inherit"]
|
|
3407
3721
|
});
|
|
3408
3722
|
worker.on("error", (err) => {
|
|
3409
|
-
console.error(
|
|
3723
|
+
console.error(import_chalk22.default.red(`\u274C Failed to start MCP server: ${err.message}`));
|
|
3410
3724
|
process.exit(1);
|
|
3411
3725
|
});
|
|
3412
3726
|
worker.on("exit", (code) => {
|
|
@@ -3420,8 +3734,8 @@ function createMcpCommand() {
|
|
|
3420
3734
|
|
|
3421
3735
|
// src/commands/nexus.ts
|
|
3422
3736
|
init_cjs_shims();
|
|
3423
|
-
var
|
|
3424
|
-
var
|
|
3737
|
+
var import_commander17 = require("commander");
|
|
3738
|
+
var import_chalk25 = __toESM(require("chalk"), 1);
|
|
3425
3739
|
|
|
3426
3740
|
// src/nexus/dispatcher.ts
|
|
3427
3741
|
init_cjs_shims();
|
|
@@ -3430,7 +3744,7 @@ var import_uuid = require("uuid");
|
|
|
3430
3744
|
|
|
3431
3745
|
// src/hive/gateway.ts
|
|
3432
3746
|
init_cjs_shims();
|
|
3433
|
-
var
|
|
3747
|
+
var import_axios17 = __toESM(require("axios"), 1);
|
|
3434
3748
|
|
|
3435
3749
|
// src/hive/scrubber.ts
|
|
3436
3750
|
init_cjs_shims();
|
|
@@ -3489,7 +3803,7 @@ var HiveScrubber = class {
|
|
|
3489
3803
|
};
|
|
3490
3804
|
|
|
3491
3805
|
// src/hive/gateway.ts
|
|
3492
|
-
var
|
|
3806
|
+
var import_chalk23 = __toESM(require("chalk"), 1);
|
|
3493
3807
|
var HiveGateway = class {
|
|
3494
3808
|
client;
|
|
3495
3809
|
enabled;
|
|
@@ -3499,9 +3813,9 @@ var HiveGateway = class {
|
|
|
3499
3813
|
constructor(baseUrl, token) {
|
|
3500
3814
|
this.enabled = !!token;
|
|
3501
3815
|
if (!this.enabled) {
|
|
3502
|
-
console.log(
|
|
3816
|
+
console.log(import_chalk23.default.dim("\u26A0\uFE0F Hive Gateway disabled (No Token provided). Running in localized mode."));
|
|
3503
3817
|
}
|
|
3504
|
-
this.client =
|
|
3818
|
+
this.client = import_axios17.default.create({
|
|
3505
3819
|
baseURL: baseUrl,
|
|
3506
3820
|
headers: {
|
|
3507
3821
|
"Authorization": `Bearer ${token}`,
|
|
@@ -3519,23 +3833,23 @@ var HiveGateway = class {
|
|
|
3519
3833
|
if (!this.enabled) return false;
|
|
3520
3834
|
const now = Date.now();
|
|
3521
3835
|
if (now - this.lastSignalTime < this.MIN_INTERVAL_MS) {
|
|
3522
|
-
console.warn(
|
|
3836
|
+
console.warn(import_chalk23.default.yellow("\u23F3 Hive Gateway Throttled. Signal dropped to preventing spam."));
|
|
3523
3837
|
return false;
|
|
3524
3838
|
}
|
|
3525
3839
|
const scrubResult = HiveScrubber.scrub(signal.ruleContent);
|
|
3526
3840
|
if (scrubResult.riskScore > 20) {
|
|
3527
|
-
console.error(
|
|
3841
|
+
console.error(import_chalk23.default.red(`\u{1F6D1} HIVE BLOCKED: Signal contains sensitive data (Risk: ${scrubResult.riskScore})`));
|
|
3528
3842
|
return false;
|
|
3529
3843
|
}
|
|
3530
3844
|
try {
|
|
3531
|
-
console.log(
|
|
3845
|
+
console.log(import_chalk23.default.blue(`\u{1F4E1} Uplinking to Hive... [${signal.vector}]`));
|
|
3532
3846
|
const payload = { ...signal, ruleContent: scrubResult.sanitizedContent };
|
|
3533
3847
|
await this.client.post("/signal", payload);
|
|
3534
3848
|
this.lastSignalTime = now;
|
|
3535
|
-
console.log(
|
|
3849
|
+
console.log(import_chalk23.default.green("\u2705 Signal Received by Hive Core. Knowledge Shared."));
|
|
3536
3850
|
return true;
|
|
3537
3851
|
} catch (error) {
|
|
3538
|
-
console.error(
|
|
3852
|
+
console.error(import_chalk23.default.red(`\u274C Hive Transmission Failed: ${error.message}`));
|
|
3539
3853
|
return false;
|
|
3540
3854
|
}
|
|
3541
3855
|
}
|
|
@@ -3543,37 +3857,37 @@ var HiveGateway = class {
|
|
|
3543
3857
|
|
|
3544
3858
|
// src/utils/logger.ts
|
|
3545
3859
|
init_cjs_shims();
|
|
3546
|
-
var
|
|
3860
|
+
var import_chalk24 = __toESM(require("chalk"), 1);
|
|
3547
3861
|
var Logger = class {
|
|
3548
3862
|
static formatMessage(level, message, context) {
|
|
3549
3863
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3550
3864
|
let prefix = "";
|
|
3551
3865
|
switch (level) {
|
|
3552
3866
|
case "INFO" /* INFO */:
|
|
3553
|
-
prefix =
|
|
3867
|
+
prefix = import_chalk24.default.blue(`[${"INFO" /* INFO */}]`);
|
|
3554
3868
|
break;
|
|
3555
3869
|
case "WARN" /* WARN */:
|
|
3556
|
-
prefix =
|
|
3870
|
+
prefix = import_chalk24.default.yellow(`[${"WARN" /* WARN */}]`);
|
|
3557
3871
|
break;
|
|
3558
3872
|
case "ERROR" /* ERROR */:
|
|
3559
|
-
prefix =
|
|
3873
|
+
prefix = import_chalk24.default.red(`[${"ERROR" /* ERROR */}]`);
|
|
3560
3874
|
break;
|
|
3561
3875
|
case "DEBUG" /* DEBUG */:
|
|
3562
|
-
prefix =
|
|
3876
|
+
prefix = import_chalk24.default.gray(`[${"DEBUG" /* DEBUG */}]`);
|
|
3563
3877
|
break;
|
|
3564
3878
|
}
|
|
3565
|
-
let output = `${
|
|
3879
|
+
let output = `${import_chalk24.default.gray(timestamp)} ${prefix} ${message}`;
|
|
3566
3880
|
if (context) {
|
|
3567
3881
|
if (context instanceof Error) {
|
|
3568
3882
|
output += `
|
|
3569
|
-
${
|
|
3883
|
+
${import_chalk24.default.red(context.stack || context.message)}`;
|
|
3570
3884
|
} else if (typeof context === "object") {
|
|
3571
3885
|
try {
|
|
3572
3886
|
output += `
|
|
3573
|
-
${
|
|
3887
|
+
${import_chalk24.default.gray(JSON.stringify(context, null, 2))}`;
|
|
3574
3888
|
} catch (e) {
|
|
3575
3889
|
output += `
|
|
3576
|
-
${
|
|
3890
|
+
${import_chalk24.default.gray("[Circular or invalid object]")}`;
|
|
3577
3891
|
}
|
|
3578
3892
|
} else {
|
|
3579
3893
|
output += ` ${String(context)}`;
|
|
@@ -3691,12 +4005,12 @@ var NexusDispatcher = class extends import_events4.default {
|
|
|
3691
4005
|
// src/commands/nexus.ts
|
|
3692
4006
|
var import_inquirer3 = __toESM(require("inquirer"), 1);
|
|
3693
4007
|
function createNexusCommand() {
|
|
3694
|
-
const command = new
|
|
4008
|
+
const command = new import_commander17.Command("nexus");
|
|
3695
4009
|
command.description("Interact with The Multi-Agent Nexus (Phase 8)").argument("<intent>", "The natural language instruction for the swarm").option("--dry-run", "Enable Dry-Run mode (Kill-Switch Active)", true).option("--force", "Disable Dry-Run mode (DANGEROUS)", false).action(async (intent, options) => {
|
|
3696
|
-
console.log(
|
|
4010
|
+
console.log(import_chalk25.default.bold.magenta("\n\u{1F981} Welcome to The Nexus (Phase 8)\n"));
|
|
3697
4011
|
const dryRun = !options.force;
|
|
3698
4012
|
if (!dryRun) {
|
|
3699
|
-
console.log(
|
|
4013
|
+
console.log(import_chalk25.default.black.bgYellow(" WARNING ") + import_chalk25.default.yellow(" Dry-Run disabled! Eitri is authorized to write code."));
|
|
3700
4014
|
const { confirm } = await import_inquirer3.default.prompt([{
|
|
3701
4015
|
type: "confirm",
|
|
3702
4016
|
name: "confirm",
|
|
@@ -3717,169 +4031,33 @@ function createNexusCommand() {
|
|
|
3717
4031
|
};
|
|
3718
4032
|
const dispatcher = new NexusDispatcher(context);
|
|
3719
4033
|
dispatcher.on("order:created", (o) => {
|
|
3720
|
-
console.log(
|
|
4034
|
+
console.log(import_chalk25.default.blue(`\u{1F195} [${o.id.slice(0, 6)}] Order Created: `) + o.intent);
|
|
3721
4035
|
});
|
|
3722
4036
|
dispatcher.on("order:started", (o) => {
|
|
3723
|
-
console.log(
|
|
4037
|
+
console.log(import_chalk25.default.yellow(`\u23F3 [${o.id.slice(0, 6)}] Processing...`));
|
|
3724
4038
|
});
|
|
3725
4039
|
dispatcher.on("order:blocked", (o) => {
|
|
3726
|
-
console.log(
|
|
3727
|
-
console.log(
|
|
3728
|
-
console.log(
|
|
4040
|
+
console.log(import_chalk25.default.red(`\u{1F6D1} [${o.id.slice(0, 6)}] BLOCKED by Kill-Switch`));
|
|
4041
|
+
console.log(import_chalk25.default.dim(` Target: ${o.targetAgent} | Action: ${o.action}`));
|
|
4042
|
+
console.log(import_chalk25.default.dim(" Run with --force to execute automatically (NOT RECOMMENDED)."));
|
|
3729
4043
|
});
|
|
3730
|
-
dispatcher.on("agent:SINDRE", (o) => console.log(
|
|
3731
|
-
dispatcher.on("agent:EITRI", (o) => console.log(
|
|
3732
|
-
console.log(
|
|
4044
|
+
dispatcher.on("agent:SINDRE", (o) => console.log(import_chalk25.default.cyan(`\u{1F916} Sindre (Vault): I'm on it! (${o.action})`)));
|
|
4045
|
+
dispatcher.on("agent:EITRI", (o) => console.log(import_chalk25.default.green(`\u{1F477} Eitri (Smith): Ready to build! (${o.action})`)));
|
|
4046
|
+
console.log(import_chalk25.default.dim("\u{1F9E0} Frank is analyzing your intent..."));
|
|
3733
4047
|
await new Promise((r) => setTimeout(r, 800));
|
|
3734
4048
|
if (intent.toLowerCase().includes("db") || intent.toLowerCase().includes("database")) {
|
|
3735
4049
|
await dispatcher.dispatch("FRANK", "SINDRE", intent, "db.analyze", { raw: intent });
|
|
3736
4050
|
} else if (intent.toLowerCase().includes("create") || intent.toLowerCase().includes("code")) {
|
|
3737
4051
|
await dispatcher.dispatch("FRANK", "EITRI", intent, "fs.write", { path: "src/demo.ts", content: "// demo" });
|
|
3738
4052
|
} else {
|
|
3739
|
-
console.log(
|
|
4053
|
+
console.log(import_chalk25.default.gray("Frank didn't understand. Try 'create file' or 'check database'."));
|
|
3740
4054
|
}
|
|
3741
4055
|
});
|
|
3742
4056
|
return command;
|
|
3743
4057
|
}
|
|
3744
4058
|
|
|
3745
|
-
// src/
|
|
3746
|
-
|
|
3747
|
-
var import_commander17 = require("commander");
|
|
3748
|
-
var import_chalk25 = __toESM(require("chalk"), 1);
|
|
3749
|
-
var import_ora11 = __toESM(require("ora"), 1);
|
|
3750
|
-
init_config();
|
|
3751
|
-
var import_axios17 = __toESM(require("axios"), 1);
|
|
3752
|
-
function createSyncRulesCommand() {
|
|
3753
|
-
const syncRules = new import_commander17.Command("sync-rules");
|
|
3754
|
-
syncRules.description("\u{1F6E1}\uFE0F Push Frank Protocol v1.0 to all existing projects").option("--dry-run", "Preview changes without pushing to GitHub").option("--project <id>", "Sync a specific project only").action(async (options) => {
|
|
3755
|
-
const spinner = (0, import_ora11.default)("\u{1F6E1}\uFE0F Frank Protocol: Initializing retroactive sync...").start();
|
|
3756
|
-
const results = [];
|
|
3757
|
-
let apiKey;
|
|
3758
|
-
try {
|
|
3759
|
-
apiKey = getApiKey();
|
|
3760
|
-
} catch (e) {
|
|
3761
|
-
spinner.fail(import_chalk25.default.red('Not authenticated. Run "rigstate login" first.'));
|
|
3762
|
-
return;
|
|
3763
|
-
}
|
|
3764
|
-
const apiUrl = getApiUrl();
|
|
3765
|
-
try {
|
|
3766
|
-
spinner.text = "Fetching projects...";
|
|
3767
|
-
const projectsResponse = await import_axios17.default.get(`${apiUrl}/api/v1/projects`, {
|
|
3768
|
-
params: options.project ? { project_id: options.project } : {},
|
|
3769
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3770
|
-
});
|
|
3771
|
-
if (!projectsResponse.data.success) {
|
|
3772
|
-
throw new Error(projectsResponse.data.error || "Failed to fetch projects");
|
|
3773
|
-
}
|
|
3774
|
-
let projects = projectsResponse.data.data.projects || [];
|
|
3775
|
-
if (projects.length === 0) {
|
|
3776
|
-
spinner.fail(import_chalk25.default.red("No projects found."));
|
|
3777
|
-
return;
|
|
3778
|
-
}
|
|
3779
|
-
if (projects.length > 1 && !options.project) {
|
|
3780
|
-
spinner.stop();
|
|
3781
|
-
const inquirer4 = (await import("inquirer")).default;
|
|
3782
|
-
const { selectedProjectId } = await inquirer4.prompt([{
|
|
3783
|
-
type: "list",
|
|
3784
|
-
name: "selectedProjectId",
|
|
3785
|
-
message: "Multiple projects found. Which one do you want to sync?",
|
|
3786
|
-
choices: projects.map((p) => ({
|
|
3787
|
-
name: `${p.name} [${p.id}]`,
|
|
3788
|
-
value: p.id
|
|
3789
|
-
}))
|
|
3790
|
-
}]);
|
|
3791
|
-
projects = projects.filter((p) => p.id === selectedProjectId);
|
|
3792
|
-
options.project = selectedProjectId;
|
|
3793
|
-
try {
|
|
3794
|
-
const fs23 = await import("fs/promises");
|
|
3795
|
-
const path23 = await import("path");
|
|
3796
|
-
const envPath = path23.join(process.cwd(), ".env");
|
|
3797
|
-
const envLocalPath = path23.join(process.cwd(), ".env.local");
|
|
3798
|
-
let targetEnv = envLocalPath;
|
|
3799
|
-
try {
|
|
3800
|
-
await fs23.access(envLocalPath);
|
|
3801
|
-
} catch {
|
|
3802
|
-
try {
|
|
3803
|
-
await fs23.access(envPath);
|
|
3804
|
-
targetEnv = envPath;
|
|
3805
|
-
} catch {
|
|
3806
|
-
targetEnv = envPath;
|
|
3807
|
-
}
|
|
3808
|
-
}
|
|
3809
|
-
let content = "";
|
|
3810
|
-
try {
|
|
3811
|
-
content = await fs23.readFile(targetEnv, "utf-8");
|
|
3812
|
-
} catch {
|
|
3813
|
-
}
|
|
3814
|
-
if (!content.includes("RIGSTATE_PROJECT_ID")) {
|
|
3815
|
-
const newContent = content.endsWith("\n") || content === "" ? `${content}RIGSTATE_PROJECT_ID=${selectedProjectId}
|
|
3816
|
-
` : `${content}
|
|
3817
|
-
RIGSTATE_PROJECT_ID=${selectedProjectId}
|
|
3818
|
-
`;
|
|
3819
|
-
await fs23.writeFile(targetEnv, newContent, "utf-8");
|
|
3820
|
-
console.log(import_chalk25.default.dim(` \u{1F4BE} Saved default project to ${path23.basename(targetEnv)}`));
|
|
3821
|
-
}
|
|
3822
|
-
} catch (e) {
|
|
3823
|
-
}
|
|
3824
|
-
}
|
|
3825
|
-
spinner.succeed(`Syncing project: ${projects[0].name}`);
|
|
3826
|
-
for (const project of projects) {
|
|
3827
|
-
const projectSpinner = (0, import_ora11.default)(` Syncing: ${project.name}...`).start();
|
|
3828
|
-
try {
|
|
3829
|
-
if (options.dryRun) {
|
|
3830
|
-
projectSpinner.succeed(import_chalk25.default.yellow(` [DRY-RUN] Would sync: ${project.name}`));
|
|
3831
|
-
results.push({ projectId: project.id, projectName: project.name, status: "success" });
|
|
3832
|
-
continue;
|
|
3833
|
-
}
|
|
3834
|
-
const syncResponse = await import_axios17.default.post(`${apiUrl}/api/v1/rules/sync`, {
|
|
3835
|
-
project_id: project.id
|
|
3836
|
-
}, {
|
|
3837
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3838
|
-
});
|
|
3839
|
-
if (syncResponse.data.success) {
|
|
3840
|
-
if (syncResponse.data.data.github_synced) {
|
|
3841
|
-
projectSpinner.succeed(import_chalk25.default.green(` \u2705 ${project.name} [${project.id}] \u2192 GitHub synced`));
|
|
3842
|
-
} else {
|
|
3843
|
-
projectSpinner.info(import_chalk25.default.blue(` \u2139\uFE0F ${project.name} [${project.id}] \u2192 Rules generated (no GitHub)`));
|
|
3844
|
-
}
|
|
3845
|
-
const files = syncResponse.data.data.files;
|
|
3846
|
-
if (files && Array.isArray(files) && (projects.length === 1 || options.project)) {
|
|
3847
|
-
const fs23 = await import("fs/promises");
|
|
3848
|
-
const path23 = await import("path");
|
|
3849
|
-
for (const file of files) {
|
|
3850
|
-
const filePath = path23.join(process.cwd(), file.path);
|
|
3851
|
-
await fs23.mkdir(path23.dirname(filePath), { recursive: true });
|
|
3852
|
-
await fs23.writeFile(filePath, file.content, "utf-8");
|
|
3853
|
-
}
|
|
3854
|
-
console.log(import_chalk25.default.dim(` \u{1F4BE} Wrote ${files.length} rule files to local .cursor/rules/`));
|
|
3855
|
-
}
|
|
3856
|
-
results.push({ projectId: project.id, projectName: project.name, status: "success" });
|
|
3857
|
-
} else {
|
|
3858
|
-
projectSpinner.warn(import_chalk25.default.yellow(` \u26A0\uFE0F ${project.name} \u2192 ${syncResponse.data.error || "Unknown error"}`));
|
|
3859
|
-
results.push({ projectId: project.id, projectName: project.name, status: "failed", error: syncResponse.data.error });
|
|
3860
|
-
}
|
|
3861
|
-
} catch (e) {
|
|
3862
|
-
projectSpinner.fail(import_chalk25.default.red(` \u274C ${project.name}: ${e.message}`));
|
|
3863
|
-
results.push({ projectId: project.id, projectName: project.name, status: "failed", error: e.message });
|
|
3864
|
-
}
|
|
3865
|
-
}
|
|
3866
|
-
console.log("");
|
|
3867
|
-
console.log(import_chalk25.default.bold("\u{1F4CA} Sync Summary:"));
|
|
3868
|
-
const successful = results.filter((r) => r.status === "success").length;
|
|
3869
|
-
const failed = results.filter((r) => r.status === "failed").length;
|
|
3870
|
-
console.log(import_chalk25.default.green(` \u2705 Successful: ${successful}`));
|
|
3871
|
-
if (failed > 0) {
|
|
3872
|
-
console.log(import_chalk25.default.red(` \u274C Failed: ${failed}`));
|
|
3873
|
-
}
|
|
3874
|
-
console.log("");
|
|
3875
|
-
console.log(import_chalk25.default.cyan("\u{1F6E1}\uFE0F Frank Protocol v1.0 has been injected into the rules engine."));
|
|
3876
|
-
console.log(import_chalk25.default.dim(" All new chats will now boot with mandatory governance checks."));
|
|
3877
|
-
} catch (e) {
|
|
3878
|
-
spinner.fail(import_chalk25.default.red("Sync failed: " + e.message));
|
|
3879
|
-
}
|
|
3880
|
-
});
|
|
3881
|
-
return syncRules;
|
|
3882
|
-
}
|
|
4059
|
+
// src/index.ts
|
|
4060
|
+
init_sync_rules();
|
|
3883
4061
|
|
|
3884
4062
|
// src/commands/override.ts
|
|
3885
4063
|
init_cjs_shims();
|