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