@rigstate/cli 0.7.25 → 0.7.29
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 +967 -751
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +964 -748
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/link.ts +99 -14
- package/src/commands/plan.ts +165 -0
- package/src/commands/work.ts +6 -0
- package/src/daemon/core.ts +28 -11
- package/src/index.ts +3 -0
- package/.rigstate/daemon.state.json +0 -8
package/dist/index.js
CHANGED
|
@@ -286,12 +286,12 @@ async function syncProjectRules(projectId, apiKey, apiUrl, dryRun = false) {
|
|
|
286
286
|
}
|
|
287
287
|
const files = syncResponse.data.data.files;
|
|
288
288
|
if (files && Array.isArray(files)) {
|
|
289
|
-
const
|
|
290
|
-
const
|
|
289
|
+
const fs25 = await import("fs/promises");
|
|
290
|
+
const path28 = await import("path");
|
|
291
291
|
for (const file of files) {
|
|
292
|
-
const filePath =
|
|
293
|
-
await
|
|
294
|
-
await
|
|
292
|
+
const filePath = path28.join(process.cwd(), file.path);
|
|
293
|
+
await fs25.mkdir(path28.dirname(filePath), { recursive: true });
|
|
294
|
+
await fs25.writeFile(filePath, file.content, "utf-8");
|
|
295
295
|
}
|
|
296
296
|
console.log(chalk3.dim(` \u{1F4BE} Wrote ${files.length} rule files to local .cursor/rules/`));
|
|
297
297
|
}
|
|
@@ -335,142 +335,12 @@ var init_sync_rules = __esm({
|
|
|
335
335
|
}
|
|
336
336
|
});
|
|
337
337
|
|
|
338
|
-
// src/commands/hooks.ts
|
|
339
|
-
var hooks_exports = {};
|
|
340
|
-
__export(hooks_exports, {
|
|
341
|
-
createHooksCommand: () => createHooksCommand
|
|
342
|
-
});
|
|
343
|
-
import { Command as Command4 } from "commander";
|
|
344
|
-
import chalk4 from "chalk";
|
|
345
|
-
import fs2 from "fs/promises";
|
|
346
|
-
import path3 from "path";
|
|
347
|
-
function createHooksCommand() {
|
|
348
|
-
const hooks = new Command4("hooks").description("Manage git hooks for Guardian integration");
|
|
349
|
-
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) => {
|
|
350
|
-
try {
|
|
351
|
-
const gitDir = path3.join(process.cwd(), ".git");
|
|
352
|
-
try {
|
|
353
|
-
await fs2.access(gitDir);
|
|
354
|
-
} catch {
|
|
355
|
-
console.log(chalk4.red("\u274C Not a git repository."));
|
|
356
|
-
console.log(chalk4.dim(' Initialize with "git init" first.'));
|
|
357
|
-
process.exit(1);
|
|
358
|
-
}
|
|
359
|
-
const hooksDir = path3.join(gitDir, "hooks");
|
|
360
|
-
await fs2.mkdir(hooksDir, { recursive: true });
|
|
361
|
-
const preCommitPath = path3.join(hooksDir, "pre-commit");
|
|
362
|
-
let existingContent = "";
|
|
363
|
-
try {
|
|
364
|
-
existingContent = await fs2.readFile(preCommitPath, "utf-8");
|
|
365
|
-
if (existingContent.includes("rigstate")) {
|
|
366
|
-
console.log(chalk4.yellow("\u26A0 Rigstate pre-commit hook already installed."));
|
|
367
|
-
console.log(chalk4.dim(' Use "rigstate hooks uninstall" to remove first.'));
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
} catch {
|
|
371
|
-
}
|
|
372
|
-
let script = PRE_COMMIT_SCRIPT;
|
|
373
|
-
if (options.strict === "all") {
|
|
374
|
-
script = script.replace("--strict=critical", "--strict");
|
|
375
|
-
}
|
|
376
|
-
if (existingContent && !existingContent.includes("rigstate")) {
|
|
377
|
-
const combinedScript = existingContent + "\n\n" + script.replace("#!/bin/sh\n", "");
|
|
378
|
-
await fs2.writeFile(preCommitPath, combinedScript, { mode: 493 });
|
|
379
|
-
console.log(chalk4.green("\u2705 Rigstate hook appended to existing pre-commit."));
|
|
380
|
-
} else {
|
|
381
|
-
await fs2.writeFile(preCommitPath, script, { mode: 493 });
|
|
382
|
-
console.log(chalk4.green("\u2705 Pre-commit hook installed!"));
|
|
383
|
-
}
|
|
384
|
-
console.log(chalk4.dim(` Path: ${preCommitPath}`));
|
|
385
|
-
console.log(chalk4.dim(` Strict level: ${options.strict}`));
|
|
386
|
-
console.log("");
|
|
387
|
-
console.log(chalk4.cyan("Guardian will now check your code before each commit."));
|
|
388
|
-
console.log(chalk4.dim('Use "rigstate hooks uninstall" to remove the hook.'));
|
|
389
|
-
} catch (error) {
|
|
390
|
-
console.error(chalk4.red("Failed to install hook:"), error.message);
|
|
391
|
-
process.exit(1);
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
hooks.command("uninstall").description("Remove Rigstate pre-commit hook").action(async () => {
|
|
395
|
-
try {
|
|
396
|
-
const preCommitPath = path3.join(process.cwd(), ".git", "hooks", "pre-commit");
|
|
397
|
-
try {
|
|
398
|
-
const content = await fs2.readFile(preCommitPath, "utf-8");
|
|
399
|
-
if (!content.includes("rigstate")) {
|
|
400
|
-
console.log(chalk4.yellow("\u26A0 No Rigstate hook found in pre-commit."));
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
if (content.includes("# Rigstate Guardian Pre-commit Hook") && content.trim().split("\n").filter((l) => l && !l.startsWith("#")).length <= 4) {
|
|
404
|
-
await fs2.unlink(preCommitPath);
|
|
405
|
-
console.log(chalk4.green("\u2705 Pre-commit hook removed."));
|
|
406
|
-
} else {
|
|
407
|
-
const lines = content.split("\n");
|
|
408
|
-
const filteredLines = [];
|
|
409
|
-
let inRigstateSection = false;
|
|
410
|
-
for (const line of lines) {
|
|
411
|
-
if (line.includes("Rigstate Guardian Pre-commit Hook")) {
|
|
412
|
-
inRigstateSection = true;
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (inRigstateSection && line.includes("exit $?")) {
|
|
416
|
-
inRigstateSection = false;
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
if (!inRigstateSection && !line.includes("rigstate check")) {
|
|
420
|
-
filteredLines.push(line);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
await fs2.writeFile(preCommitPath, filteredLines.join("\n"), { mode: 493 });
|
|
424
|
-
console.log(chalk4.green("\u2705 Rigstate section removed from pre-commit hook."));
|
|
425
|
-
}
|
|
426
|
-
} catch {
|
|
427
|
-
console.log(chalk4.yellow("\u26A0 No pre-commit hook found."));
|
|
428
|
-
}
|
|
429
|
-
} catch (error) {
|
|
430
|
-
console.error(chalk4.red("Failed to uninstall hook:"), error.message);
|
|
431
|
-
process.exit(1);
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
return hooks;
|
|
435
|
-
}
|
|
436
|
-
var PRE_COMMIT_SCRIPT;
|
|
437
|
-
var init_hooks = __esm({
|
|
438
|
-
"src/commands/hooks.ts"() {
|
|
439
|
-
"use strict";
|
|
440
|
-
init_esm_shims();
|
|
441
|
-
PRE_COMMIT_SCRIPT = `#!/bin/sh
|
|
442
|
-
# Rigstate Guardian Pre-commit Hook
|
|
443
|
-
# Installed by: rigstate hooks install
|
|
444
|
-
|
|
445
|
-
# 1. Silent Sentinel Check (Phase 5)
|
|
446
|
-
if [ -f .rigstate/guardian.lock ]; then
|
|
447
|
-
echo "\u{1F6D1} INTERVENTION ACTIVE: Commit blocked by Silent Sentinel."
|
|
448
|
-
echo " A critical violation ('HARD_LOCK') was detected by the Guardian Daemon."
|
|
449
|
-
echo " Please fix the violation to unlock the repo."
|
|
450
|
-
echo ""
|
|
451
|
-
if grep -q "HARD_LOCK_ACTIVE" .rigstate/guardian.lock; then
|
|
452
|
-
cat .rigstate/guardian.lock
|
|
453
|
-
fi
|
|
454
|
-
exit 1
|
|
455
|
-
fi
|
|
456
|
-
|
|
457
|
-
echo "\u{1F6E1}\uFE0F Running Guardian checks..."
|
|
458
|
-
|
|
459
|
-
# Run check with strict mode for critical violations
|
|
460
|
-
rigstate check --staged --strict=critical
|
|
461
|
-
|
|
462
|
-
# Exit with the same code as rigstate check
|
|
463
|
-
exit $?
|
|
464
|
-
`;
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
|
|
468
338
|
// src/commands/suggest.ts
|
|
469
339
|
var suggest_exports = {};
|
|
470
340
|
__export(suggest_exports, {
|
|
471
341
|
suggestNextMove: () => suggestNextMove
|
|
472
342
|
});
|
|
473
|
-
import
|
|
343
|
+
import chalk4 from "chalk";
|
|
474
344
|
import axios3 from "axios";
|
|
475
345
|
async function suggestNextMove(projectId, apiKey, apiUrl) {
|
|
476
346
|
try {
|
|
@@ -490,18 +360,18 @@ async function suggestNextMove(projectId, apiKey, apiUrl) {
|
|
|
490
360
|
if (tasks.length === 0) return;
|
|
491
361
|
const nextTask = tasks[0];
|
|
492
362
|
console.log("");
|
|
493
|
-
console.log(
|
|
494
|
-
console.log(
|
|
495
|
-
console.log(`${
|
|
496
|
-
console.log(`${
|
|
363
|
+
console.log(chalk4.bold("\u{1F3AF} TACTICAL INTELLIGENCE"));
|
|
364
|
+
console.log(chalk4.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
365
|
+
console.log(`${chalk4.bold("Active Phase:")} Implementation`);
|
|
366
|
+
console.log(`${chalk4.bold("Next Mission:")} ${chalk4.cyan(nextTask.title)}`);
|
|
497
367
|
if (nextTask.role) {
|
|
498
|
-
console.log(`${
|
|
368
|
+
console.log(`${chalk4.bold("Required Role:")} ${chalk4.magenta(nextTask.role)}`);
|
|
499
369
|
}
|
|
500
370
|
console.log("");
|
|
501
|
-
console.log(
|
|
502
|
-
console.log(
|
|
503
|
-
console.log(
|
|
504
|
-
console.log(
|
|
371
|
+
console.log(chalk4.yellow("SUGGESTED NEXT MOVE:"));
|
|
372
|
+
console.log(chalk4.white(`> rigstate work start ${nextTask.id} `) + chalk4.dim("(Start this task)"));
|
|
373
|
+
console.log(chalk4.white(`> rigstate chat "How do I solve T-${nextTask.step_number}?" `) + chalk4.dim("(Ask Architect)"));
|
|
374
|
+
console.log(chalk4.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
505
375
|
console.log("");
|
|
506
376
|
} catch (e) {
|
|
507
377
|
}
|
|
@@ -521,9 +391,9 @@ __export(skills_provisioner_exports, {
|
|
|
521
391
|
provisionSkills: () => provisionSkills
|
|
522
392
|
});
|
|
523
393
|
import axios6 from "axios";
|
|
524
|
-
import
|
|
525
|
-
import
|
|
526
|
-
import
|
|
394
|
+
import fs6 from "fs/promises";
|
|
395
|
+
import path7 from "path";
|
|
396
|
+
import chalk8 from "chalk";
|
|
527
397
|
async function provisionSkills(apiUrl, apiKey, projectId, rootDir) {
|
|
528
398
|
const skills = [];
|
|
529
399
|
try {
|
|
@@ -545,18 +415,18 @@ async function provisionSkills(apiUrl, apiKey, projectId, rootDir) {
|
|
|
545
415
|
}
|
|
546
416
|
} catch (e) {
|
|
547
417
|
const msg = e.response?.data?.error || e.message;
|
|
548
|
-
console.log(
|
|
418
|
+
console.log(chalk8.dim(` (Skills API not available: ${msg}, using core library)`));
|
|
549
419
|
}
|
|
550
420
|
if (skills.length === 0) {
|
|
551
421
|
const { getRigstateStandardSkills } = await import("@rigstate/rules-engine");
|
|
552
422
|
const coreSkills = getRigstateStandardSkills();
|
|
553
423
|
skills.push(...coreSkills);
|
|
554
424
|
}
|
|
555
|
-
const skillsDir =
|
|
556
|
-
await
|
|
425
|
+
const skillsDir = path7.join(rootDir, ".agent", "skills");
|
|
426
|
+
await fs6.mkdir(skillsDir, { recursive: true });
|
|
557
427
|
for (const skill of skills) {
|
|
558
|
-
const skillDir =
|
|
559
|
-
await
|
|
428
|
+
const skillDir = path7.join(skillsDir, skill.name);
|
|
429
|
+
await fs6.mkdir(skillDir, { recursive: true });
|
|
560
430
|
const skillContent = `---
|
|
561
431
|
name: ${skill.name}
|
|
562
432
|
description: ${skill.description}
|
|
@@ -569,10 +439,10 @@ ${skill.content}
|
|
|
569
439
|
|
|
570
440
|
---
|
|
571
441
|
*Provisioned by Rigstate CLI. Do not modify manually.*`;
|
|
572
|
-
const skillPath =
|
|
573
|
-
await
|
|
442
|
+
const skillPath = path7.join(skillDir, "SKILL.md");
|
|
443
|
+
await fs6.writeFile(skillPath, skillContent, "utf-8");
|
|
574
444
|
}
|
|
575
|
-
console.log(
|
|
445
|
+
console.log(chalk8.green(` \u2705 Provisioned ${skills.length} skill(s) to .agent/skills/`));
|
|
576
446
|
return skills;
|
|
577
447
|
}
|
|
578
448
|
function generateSkillsDiscoveryBlock(skills) {
|
|
@@ -587,16 +457,16 @@ ${skillBlocks}
|
|
|
587
457
|
</available_skills>`;
|
|
588
458
|
}
|
|
589
459
|
async function jitProvisionSkill(skillId, apiUrl, apiKey, projectId, rootDir) {
|
|
590
|
-
const rulesPath =
|
|
460
|
+
const rulesPath = path7.join(rootDir, ".cursorrules");
|
|
591
461
|
let rulesContent = "";
|
|
592
462
|
try {
|
|
593
|
-
rulesContent = await
|
|
463
|
+
rulesContent = await fs6.readFile(rulesPath, "utf-8");
|
|
594
464
|
} catch (e) {
|
|
595
465
|
return false;
|
|
596
466
|
}
|
|
597
467
|
const isProvisioned = rulesContent.includes(`<name>${skillId}</name>`) || rulesContent.includes(`.agent/skills/${skillId}`);
|
|
598
468
|
if (isProvisioned) return false;
|
|
599
|
-
console.log(
|
|
469
|
+
console.log(chalk8.yellow(` \u26A1 JIT PROVISIONING: Injecting ${skillId}...`));
|
|
600
470
|
try {
|
|
601
471
|
const skills = await provisionSkills(apiUrl, apiKey, projectId, rootDir);
|
|
602
472
|
const skillsBlock = generateSkillsDiscoveryBlock(skills);
|
|
@@ -611,10 +481,10 @@ async function jitProvisionSkill(skillId, apiUrl, apiKey, projectId, rootDir) {
|
|
|
611
481
|
rulesContent = rulesContent.slice(0, insertPoint + 3) + "\n\n" + skillsBlock + "\n" + rulesContent.slice(insertPoint + 3);
|
|
612
482
|
}
|
|
613
483
|
}
|
|
614
|
-
await
|
|
484
|
+
await fs6.writeFile(rulesPath, rulesContent, "utf-8");
|
|
615
485
|
return true;
|
|
616
486
|
} catch (e) {
|
|
617
|
-
console.log(
|
|
487
|
+
console.log(chalk8.red(` Failed to provision skill: ${e.message}`));
|
|
618
488
|
return false;
|
|
619
489
|
}
|
|
620
490
|
}
|
|
@@ -635,13 +505,13 @@ __export(governance_exports, {
|
|
|
635
505
|
performOverride: () => performOverride,
|
|
636
506
|
setSoftLock: () => setSoftLock
|
|
637
507
|
});
|
|
638
|
-
import
|
|
639
|
-
import
|
|
640
|
-
import
|
|
508
|
+
import fs7 from "fs/promises";
|
|
509
|
+
import path8 from "path";
|
|
510
|
+
import chalk9 from "chalk";
|
|
641
511
|
async function getGovernanceConfig(rootDir = process.cwd()) {
|
|
642
512
|
try {
|
|
643
|
-
const configPath =
|
|
644
|
-
const content = await
|
|
513
|
+
const configPath = path8.join(rootDir, "rigstate.config.json");
|
|
514
|
+
const content = await fs7.readFile(configPath, "utf-8");
|
|
645
515
|
const userConfig = JSON.parse(content);
|
|
646
516
|
return {
|
|
647
517
|
governance: {
|
|
@@ -655,37 +525,37 @@ async function getGovernanceConfig(rootDir = process.cwd()) {
|
|
|
655
525
|
}
|
|
656
526
|
async function getSessionState(rootDir = process.cwd()) {
|
|
657
527
|
try {
|
|
658
|
-
const sessionPath =
|
|
659
|
-
const content = await
|
|
528
|
+
const sessionPath = path8.join(rootDir, ".rigstate", "session.json");
|
|
529
|
+
const content = await fs7.readFile(sessionPath, "utf-8");
|
|
660
530
|
return JSON.parse(content);
|
|
661
531
|
} catch (e) {
|
|
662
532
|
return DEFAULT_SESSION;
|
|
663
533
|
}
|
|
664
534
|
}
|
|
665
535
|
async function setSoftLock(reason, violationId, rootDir = process.cwd()) {
|
|
666
|
-
const sessionPath =
|
|
536
|
+
const sessionPath = path8.join(rootDir, ".rigstate", "session.json");
|
|
667
537
|
const state = {
|
|
668
538
|
status: "SOFT_LOCK",
|
|
669
539
|
active_violation: violationId,
|
|
670
540
|
lock_reason: reason,
|
|
671
541
|
last_updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
672
542
|
};
|
|
673
|
-
await
|
|
674
|
-
await
|
|
543
|
+
await fs7.mkdir(path8.dirname(sessionPath), { recursive: true });
|
|
544
|
+
await fs7.writeFile(sessionPath, JSON.stringify(state, null, 2), "utf-8");
|
|
675
545
|
}
|
|
676
546
|
async function clearSoftLock(rootDir = process.cwd()) {
|
|
677
|
-
const sessionPath =
|
|
547
|
+
const sessionPath = path8.join(rootDir, ".rigstate", "session.json");
|
|
678
548
|
const state = {
|
|
679
549
|
...DEFAULT_SESSION,
|
|
680
550
|
last_updated: (/* @__PURE__ */ new Date()).toISOString()
|
|
681
551
|
};
|
|
682
|
-
await
|
|
683
|
-
await
|
|
552
|
+
await fs7.mkdir(path8.dirname(sessionPath), { recursive: true });
|
|
553
|
+
await fs7.writeFile(sessionPath, JSON.stringify(state, null, 2), "utf-8");
|
|
684
554
|
}
|
|
685
555
|
async function performOverride(violationId, reason, rootDir = process.cwd()) {
|
|
686
556
|
const config2 = await getGovernanceConfig(rootDir);
|
|
687
557
|
if (!config2.governance.allow_overrides) {
|
|
688
|
-
console.log(
|
|
558
|
+
console.log(chalk9.red("\u274C Overrides are disabled for this project."));
|
|
689
559
|
return false;
|
|
690
560
|
}
|
|
691
561
|
await clearSoftLock(rootDir);
|
|
@@ -722,22 +592,22 @@ var watchdog_exports = {};
|
|
|
722
592
|
__export(watchdog_exports, {
|
|
723
593
|
runGuardianWatchdog: () => runGuardianWatchdog
|
|
724
594
|
});
|
|
725
|
-
import
|
|
726
|
-
import
|
|
727
|
-
import
|
|
595
|
+
import fs8 from "fs/promises";
|
|
596
|
+
import path9 from "path";
|
|
597
|
+
import chalk10 from "chalk";
|
|
728
598
|
import axios7 from "axios";
|
|
729
599
|
async function countLines(filePath) {
|
|
730
600
|
try {
|
|
731
|
-
const content = await
|
|
601
|
+
const content = await fs8.readFile(filePath, "utf-8");
|
|
732
602
|
return content.split("\n").length;
|
|
733
603
|
} catch (e) {
|
|
734
604
|
return 0;
|
|
735
605
|
}
|
|
736
606
|
}
|
|
737
607
|
async function getFiles(dir, extension) {
|
|
738
|
-
const entries = await
|
|
608
|
+
const entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
739
609
|
const files = await Promise.all(entries.map(async (entry) => {
|
|
740
|
-
const res =
|
|
610
|
+
const res = path9.resolve(dir, entry.name);
|
|
741
611
|
if (entry.isDirectory()) {
|
|
742
612
|
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === ".next" || entry.name === "dist") return [];
|
|
743
613
|
return getFiles(res, extension);
|
|
@@ -765,8 +635,8 @@ async function fetchRulesFromApi(projectId) {
|
|
|
765
635
|
}
|
|
766
636
|
} catch (error) {
|
|
767
637
|
try {
|
|
768
|
-
const cachePath =
|
|
769
|
-
const content = await
|
|
638
|
+
const cachePath = path9.join(process.cwd(), CACHE_FILE);
|
|
639
|
+
const content = await fs8.readFile(cachePath, "utf-8");
|
|
770
640
|
const cached = JSON.parse(content);
|
|
771
641
|
if (cached.settings) {
|
|
772
642
|
return {
|
|
@@ -785,7 +655,7 @@ async function fetchRulesFromApi(projectId) {
|
|
|
785
655
|
};
|
|
786
656
|
}
|
|
787
657
|
async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
788
|
-
console.log(
|
|
658
|
+
console.log(chalk10.bold("\n\u{1F6E1}\uFE0F Active Guardian Watchdog Initiated..."));
|
|
789
659
|
let lmax = settings.lmax || DEFAULT_LMAX;
|
|
790
660
|
let lmaxWarning = settings.lmax_warning || DEFAULT_LMAX_WARNING;
|
|
791
661
|
let ruleSource = settings.lmax ? "Settings (Passed)" : "Default";
|
|
@@ -795,47 +665,47 @@ async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
|
795
665
|
lmaxWarning = apiRules.lmaxWarning;
|
|
796
666
|
ruleSource = apiRules.source;
|
|
797
667
|
}
|
|
798
|
-
console.log(
|
|
668
|
+
console.log(chalk10.dim(`Governance Rules: L_max=${lmax}, L_max_warning=${lmaxWarning}, Source: ${ruleSource}`));
|
|
799
669
|
const targetExtensions = [".ts", ".tsx"];
|
|
800
670
|
let scanTarget = rootPath;
|
|
801
|
-
const webSrc =
|
|
671
|
+
const webSrc = path9.join(rootPath, "apps", "web", "src");
|
|
802
672
|
try {
|
|
803
|
-
await
|
|
673
|
+
await fs8.access(webSrc);
|
|
804
674
|
scanTarget = webSrc;
|
|
805
675
|
} catch {
|
|
806
676
|
}
|
|
807
|
-
console.log(
|
|
677
|
+
console.log(chalk10.dim(`Scanning target: ${path9.relative(process.cwd(), scanTarget)}`));
|
|
808
678
|
const files = await getFiles(scanTarget, targetExtensions);
|
|
809
679
|
let violations = 0;
|
|
810
680
|
let warnings = 0;
|
|
811
681
|
const results = [];
|
|
812
682
|
for (const file of files) {
|
|
813
683
|
const lines = await countLines(file);
|
|
814
|
-
const relPath =
|
|
684
|
+
const relPath = path9.relative(rootPath, file);
|
|
815
685
|
if (lines > lmax) {
|
|
816
686
|
results.push({ file: relPath, lines, status: "VIOLATION" });
|
|
817
687
|
violations++;
|
|
818
|
-
console.log(
|
|
688
|
+
console.log(chalk10.red(`[VIOLATION] ${relPath}: ${lines} lines (Limit: ${lmax})`));
|
|
819
689
|
} else if (lines > lmaxWarning) {
|
|
820
690
|
results.push({ file: relPath, lines, status: "WARNING" });
|
|
821
691
|
warnings++;
|
|
822
|
-
console.log(
|
|
692
|
+
console.log(chalk10.yellow(`[WARNING] ${relPath}: ${lines} lines (Threshold: ${lmaxWarning})`));
|
|
823
693
|
}
|
|
824
694
|
}
|
|
825
695
|
if (violations === 0 && warnings === 0) {
|
|
826
|
-
console.log(
|
|
696
|
+
console.log(chalk10.green(`\u2714 All ${files.length} files are within governance limits.`));
|
|
827
697
|
} else {
|
|
828
|
-
console.log("\n" +
|
|
829
|
-
console.log(
|
|
830
|
-
console.log(
|
|
698
|
+
console.log("\n" + chalk10.bold("Summary:"));
|
|
699
|
+
console.log(chalk10.red(`Violations: ${violations}`));
|
|
700
|
+
console.log(chalk10.yellow(`Warnings: ${warnings}`));
|
|
831
701
|
const { getGovernanceConfig: getGovernanceConfig2, setSoftLock: setSoftLock2, InterventionLevel: InterventionLevel2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
832
702
|
const { governance } = await getGovernanceConfig2(rootPath);
|
|
833
|
-
console.log(
|
|
703
|
+
console.log(chalk10.dim(`Intervention Level: ${InterventionLevel2[governance.intervention_level] || "UNKNOWN"} (${governance.intervention_level})`));
|
|
834
704
|
if (violations > 0) {
|
|
835
|
-
console.log(
|
|
705
|
+
console.log(chalk10.red.bold("\nCRITICAL: Governance violations detected. Immediate refactoring required."));
|
|
836
706
|
if (governance.intervention_level >= InterventionLevel2.SENTINEL) {
|
|
837
|
-
console.log(
|
|
838
|
-
console.log(
|
|
707
|
+
console.log(chalk10.red.bold("\u{1F6D1} SENTINEL MODE: Session SOFT_LOCKED until resolved."));
|
|
708
|
+
console.log(chalk10.red(' Run "rigstate override <id> --reason \\"...\\"" if this is an emergency.'));
|
|
839
709
|
await setSoftLock2("Sentinel Mode: Governance Violations Detected", "ARC-VIOLATION", rootPath);
|
|
840
710
|
}
|
|
841
711
|
}
|
|
@@ -858,9 +728,9 @@ async function runGuardianWatchdog(rootPath, settings = {}, projectId) {
|
|
|
858
728
|
}, {
|
|
859
729
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
860
730
|
});
|
|
861
|
-
console.log(
|
|
731
|
+
console.log(chalk10.dim("\u2714 Violations synced to Rigstate Cloud."));
|
|
862
732
|
} catch (e) {
|
|
863
|
-
console.log(
|
|
733
|
+
console.log(chalk10.dim("\u26A0 Cloud sync skipped: " + (e.message || "Unknown")));
|
|
864
734
|
}
|
|
865
735
|
}
|
|
866
736
|
}
|
|
@@ -1663,10 +1533,10 @@ var require_src2 = __commonJS({
|
|
|
1663
1533
|
var fs_1 = __require("fs");
|
|
1664
1534
|
var debug_1 = __importDefault(require_src());
|
|
1665
1535
|
var log = debug_1.default("@kwsites/file-exists");
|
|
1666
|
-
function check(
|
|
1667
|
-
log(`checking %s`,
|
|
1536
|
+
function check(path28, isFile, isDirectory) {
|
|
1537
|
+
log(`checking %s`, path28);
|
|
1668
1538
|
try {
|
|
1669
|
-
const stat = fs_1.statSync(
|
|
1539
|
+
const stat = fs_1.statSync(path28);
|
|
1670
1540
|
if (stat.isFile() && isFile) {
|
|
1671
1541
|
log(`[OK] path represents a file`);
|
|
1672
1542
|
return true;
|
|
@@ -1686,8 +1556,8 @@ var require_src2 = __commonJS({
|
|
|
1686
1556
|
throw e;
|
|
1687
1557
|
}
|
|
1688
1558
|
}
|
|
1689
|
-
function exists2(
|
|
1690
|
-
return check(
|
|
1559
|
+
function exists2(path28, type = exports.READABLE) {
|
|
1560
|
+
return check(path28, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
|
|
1691
1561
|
}
|
|
1692
1562
|
exports.exists = exists2;
|
|
1693
1563
|
exports.FILE = 1;
|
|
@@ -1757,7 +1627,7 @@ var require_package = __commonJS({
|
|
|
1757
1627
|
"package.json"(exports, module) {
|
|
1758
1628
|
module.exports = {
|
|
1759
1629
|
name: "@rigstate/cli",
|
|
1760
|
-
version: "0.7.
|
|
1630
|
+
version: "0.7.29",
|
|
1761
1631
|
description: "Rigstate CLI - Code audit, sync and supervision tool",
|
|
1762
1632
|
type: "module",
|
|
1763
1633
|
main: "./dist/index.js",
|
|
@@ -1813,8 +1683,8 @@ var require_package = __commonJS({
|
|
|
1813
1683
|
|
|
1814
1684
|
// src/index.ts
|
|
1815
1685
|
init_esm_shims();
|
|
1816
|
-
import { Command as
|
|
1817
|
-
import
|
|
1686
|
+
import { Command as Command24 } from "commander";
|
|
1687
|
+
import chalk35 from "chalk";
|
|
1818
1688
|
|
|
1819
1689
|
// src/commands/login.ts
|
|
1820
1690
|
init_esm_shims();
|
|
@@ -1867,30 +1737,68 @@ Your API key has been securely stored. You can now use "rigstate scan" to audit
|
|
|
1867
1737
|
// src/commands/link.ts
|
|
1868
1738
|
init_esm_shims();
|
|
1869
1739
|
init_config();
|
|
1870
|
-
import { Command as
|
|
1871
|
-
import
|
|
1872
|
-
import
|
|
1873
|
-
import
|
|
1740
|
+
import { Command as Command4 } from "commander";
|
|
1741
|
+
import fs2 from "fs/promises";
|
|
1742
|
+
import path3 from "path";
|
|
1743
|
+
import chalk5 from "chalk";
|
|
1874
1744
|
import os from "os";
|
|
1875
1745
|
function createLinkCommand() {
|
|
1876
|
-
return new
|
|
1746
|
+
return new Command4("link").description("Link current directory to a Rigstate project").argument("[projectId]", "Project ID to link").action(async (projectId) => {
|
|
1877
1747
|
try {
|
|
1878
|
-
const globalPath =
|
|
1879
|
-
const globalData = await
|
|
1748
|
+
const globalPath = path3.join(os.homedir(), ".rigstate", "config.json");
|
|
1749
|
+
const globalData = await fs2.readFile(globalPath, "utf-8").catch(() => null);
|
|
1880
1750
|
if (globalData) {
|
|
1881
1751
|
const config2 = JSON.parse(globalData);
|
|
1882
1752
|
const cwd = process.cwd();
|
|
1883
1753
|
if (config2.overrides && config2.overrides[cwd]) {
|
|
1884
1754
|
const overrideId = config2.overrides[cwd];
|
|
1885
|
-
|
|
1886
|
-
|
|
1755
|
+
console.warn(chalk5.yellow(`Global override detected. Enforcing project ID: ${overrideId}`));
|
|
1756
|
+
if (!projectId) projectId = overrideId;
|
|
1757
|
+
else if (projectId !== overrideId) {
|
|
1758
|
+
console.warn(chalk5.red(`Ignoring provided ID ${projectId}. Using override.`));
|
|
1887
1759
|
projectId = overrideId;
|
|
1888
1760
|
}
|
|
1889
1761
|
}
|
|
1890
1762
|
}
|
|
1891
1763
|
} catch (e) {
|
|
1892
1764
|
}
|
|
1893
|
-
|
|
1765
|
+
if (!projectId) {
|
|
1766
|
+
try {
|
|
1767
|
+
const inquirer8 = (await import("inquirer")).default;
|
|
1768
|
+
const { getApiKey: _getApiKey, getApiUrl: _getApiUrl } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1769
|
+
const apiKey = getApiKey();
|
|
1770
|
+
const apiUrl = getApiUrl();
|
|
1771
|
+
if (!apiKey) {
|
|
1772
|
+
console.error(chalk5.red('Not authenticated. Please run "rigstate login" or provide a Project ID.'));
|
|
1773
|
+
process.exit(1);
|
|
1774
|
+
}
|
|
1775
|
+
console.log(chalk5.dim("Fetching your projects..."));
|
|
1776
|
+
const axios23 = (await import("axios")).default;
|
|
1777
|
+
const response = await axios23.get(`${apiUrl}/api/v1/projects`, {
|
|
1778
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
1779
|
+
});
|
|
1780
|
+
if (!response.data.success || !response.data.data.projects?.length) {
|
|
1781
|
+
console.error(chalk5.yellow("No projects found. Create one at https://app.rigstate.com"));
|
|
1782
|
+
process.exit(1);
|
|
1783
|
+
}
|
|
1784
|
+
const choices = response.data.data.projects.map((p) => ({
|
|
1785
|
+
name: `${p.name} (${p.id})`,
|
|
1786
|
+
value: p.id
|
|
1787
|
+
}));
|
|
1788
|
+
const answer = await inquirer8.prompt([{
|
|
1789
|
+
type: "list",
|
|
1790
|
+
name: "id",
|
|
1791
|
+
message: "Select project to link:",
|
|
1792
|
+
choices
|
|
1793
|
+
}]);
|
|
1794
|
+
projectId = answer.id;
|
|
1795
|
+
} catch (e) {
|
|
1796
|
+
console.error(chalk5.red(`Failed to fetch projects: ${e.message}`));
|
|
1797
|
+
console.error("Please provide project ID manually: rigstate link <id>");
|
|
1798
|
+
process.exit(1);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
const manifestPath = path3.join(process.cwd(), ".rigstate");
|
|
1894
1802
|
const content = {
|
|
1895
1803
|
project_id: projectId,
|
|
1896
1804
|
linked_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1900,60 +1808,96 @@ function createLinkCommand() {
|
|
|
1900
1808
|
content.api_url = currentUrl;
|
|
1901
1809
|
}
|
|
1902
1810
|
try {
|
|
1903
|
-
await
|
|
1904
|
-
|
|
1905
|
-
console.log(
|
|
1811
|
+
await fs2.mkdir(path3.dirname(manifestPath), { recursive: true });
|
|
1812
|
+
await fs2.writeFile(manifestPath, JSON.stringify(content, null, 2), "utf-8");
|
|
1813
|
+
console.log(chalk5.green(`\u2714 Linked to project ID: ${projectId}`));
|
|
1814
|
+
console.log(chalk5.dim(`Created local context manifest at .rigstate`));
|
|
1906
1815
|
console.log("");
|
|
1907
|
-
console.log(
|
|
1816
|
+
console.log(chalk5.bold("\u{1F916} Rigstate Automation Detected"));
|
|
1908
1817
|
console.log("");
|
|
1909
1818
|
const { getApiKey: _getApiKey, getApiUrl: _getApiUrl } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
1910
1819
|
const apiKey = getApiKey();
|
|
1911
1820
|
const apiUrl = getApiUrl();
|
|
1912
1821
|
if (apiKey) {
|
|
1913
|
-
console.log(
|
|
1822
|
+
console.log(chalk5.blue("\u{1F510} Checking Vault for secrets..."));
|
|
1914
1823
|
const { syncEnv: syncEnv2 } = await Promise.resolve().then(() => (init_env(), env_exports));
|
|
1915
1824
|
await syncEnv2(projectId, apiKey, apiUrl, true);
|
|
1916
|
-
console.log(
|
|
1825
|
+
console.log(chalk5.blue("\u{1F9E0} Syncing neural instructions..."));
|
|
1917
1826
|
const { syncProjectRules: syncProjectRules2 } = await Promise.resolve().then(() => (init_sync_rules(), sync_rules_exports));
|
|
1918
1827
|
await syncProjectRules2(projectId, apiKey, apiUrl);
|
|
1919
|
-
console.log(
|
|
1920
|
-
const { createHooksCommand: createHooksCommand2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
1828
|
+
console.log(chalk5.blue("\u{1F6E1}\uFE0F Injecting Guardian hooks & Safety nets..."));
|
|
1921
1829
|
await installHooks(process.cwd());
|
|
1830
|
+
await hardenGitIgnore(process.cwd());
|
|
1922
1831
|
console.log("");
|
|
1923
|
-
console.log(
|
|
1832
|
+
console.log(chalk5.bold.green("\u{1F680} Link Complete! Your environment is ready."));
|
|
1924
1833
|
const { suggestNextMove: suggestNextMove2 } = await Promise.resolve().then(() => (init_suggest(), suggest_exports));
|
|
1925
1834
|
await suggestNextMove2(projectId, apiKey, apiUrl);
|
|
1926
1835
|
} else {
|
|
1927
1836
|
console.log("");
|
|
1928
|
-
console.log(
|
|
1837
|
+
console.log(chalk5.bold.green("\u{1F680} Link Complete!"));
|
|
1929
1838
|
}
|
|
1930
1839
|
} catch (error) {
|
|
1931
|
-
if (error.message
|
|
1932
|
-
console.warn(
|
|
1840
|
+
if (error.message?.includes("Not authenticated")) {
|
|
1841
|
+
console.warn(chalk5.yellow('\u26A0\uFE0F Not authenticated. Run "rigstate login" to enable automation features.'));
|
|
1933
1842
|
} else {
|
|
1934
|
-
console.error(
|
|
1843
|
+
console.error(chalk5.red(`Failed to link project: ${error.message}`));
|
|
1935
1844
|
}
|
|
1936
1845
|
}
|
|
1937
1846
|
});
|
|
1938
1847
|
}
|
|
1848
|
+
async function hardenGitIgnore(cwd) {
|
|
1849
|
+
const fs25 = await import("fs/promises");
|
|
1850
|
+
const path28 = await import("path");
|
|
1851
|
+
const ignorePath = path28.join(cwd, ".gitignore");
|
|
1852
|
+
const REQUIRED_IGNORES = [
|
|
1853
|
+
"# Rigstate - Runtime Artifacts (Do not commit)",
|
|
1854
|
+
".rigstate/ACTIVE_VIOLATIONS.md",
|
|
1855
|
+
".rigstate/CURRENT_CONTEXT.md",
|
|
1856
|
+
".rigstate/daemon.pid",
|
|
1857
|
+
".rigstate/daemon.state.json",
|
|
1858
|
+
".rigstate/*.log",
|
|
1859
|
+
".rigstate/*.bak",
|
|
1860
|
+
"# Keep identity tracked",
|
|
1861
|
+
"!.rigstate/identity.json"
|
|
1862
|
+
];
|
|
1863
|
+
try {
|
|
1864
|
+
let content = "";
|
|
1865
|
+
try {
|
|
1866
|
+
content = await fs25.readFile(ignorePath, "utf-8");
|
|
1867
|
+
} catch {
|
|
1868
|
+
content = "";
|
|
1869
|
+
}
|
|
1870
|
+
const missing = REQUIRED_IGNORES.filter((line) => !content.includes(line) && !line.startsWith("#"));
|
|
1871
|
+
if (missing.length > 0) {
|
|
1872
|
+
console.log(chalk5.dim(" Configuring .gitignore for Rigstate safety..."));
|
|
1873
|
+
const toAppend = "\n\n" + REQUIRED_IGNORES.join("\n") + "\n";
|
|
1874
|
+
await fs25.writeFile(ignorePath, content + toAppend, "utf-8");
|
|
1875
|
+
console.log(chalk5.green(" \u2714 .gitignore updated (Artifacts protected)"));
|
|
1876
|
+
} else {
|
|
1877
|
+
console.log(chalk5.green(" \u2714 .gitignore already hardened"));
|
|
1878
|
+
}
|
|
1879
|
+
} catch (e) {
|
|
1880
|
+
console.warn(chalk5.yellow(` Could not update .gitignore: ${e.message}`));
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1939
1883
|
async function installHooks(cwd) {
|
|
1940
|
-
const
|
|
1941
|
-
const
|
|
1884
|
+
const fs25 = await import("fs/promises");
|
|
1885
|
+
const path28 = await import("path");
|
|
1942
1886
|
try {
|
|
1943
|
-
await
|
|
1887
|
+
await fs25.access(path28.join(cwd, ".git"));
|
|
1944
1888
|
} catch {
|
|
1945
|
-
console.log(
|
|
1889
|
+
console.log(chalk5.dim(" (Not a git repository, skipping hooks)"));
|
|
1946
1890
|
return;
|
|
1947
1891
|
}
|
|
1948
|
-
const hooksDir =
|
|
1892
|
+
const hooksDir = path28.join(cwd, ".husky");
|
|
1949
1893
|
try {
|
|
1950
|
-
const preCommitPath =
|
|
1894
|
+
const preCommitPath = path28.join(cwd, ".git/hooks/pre-commit");
|
|
1951
1895
|
let shouldInstall = false;
|
|
1952
1896
|
try {
|
|
1953
|
-
await
|
|
1954
|
-
const content = await
|
|
1897
|
+
await fs25.access(preCommitPath);
|
|
1898
|
+
const content = await fs25.readFile(preCommitPath, "utf-8");
|
|
1955
1899
|
if (content.includes("rigstate")) {
|
|
1956
|
-
console.log(
|
|
1900
|
+
console.log(chalk5.green(" \u2714 Git hooks already active"));
|
|
1957
1901
|
} else {
|
|
1958
1902
|
shouldInstall = true;
|
|
1959
1903
|
}
|
|
@@ -1975,23 +1919,23 @@ echo "\u{1F6E1}\uFE0F Running Guardian checks..."
|
|
|
1975
1919
|
rigstate check --staged --strict=critical
|
|
1976
1920
|
exit $?
|
|
1977
1921
|
`;
|
|
1978
|
-
await
|
|
1922
|
+
await fs25.mkdir(path28.dirname(preCommitPath), { recursive: true });
|
|
1979
1923
|
if (await fileExists(preCommitPath)) {
|
|
1980
|
-
const existing = await
|
|
1981
|
-
await
|
|
1924
|
+
const existing = await fs25.readFile(preCommitPath, "utf-8");
|
|
1925
|
+
await fs25.writeFile(preCommitPath, existing + "\n\n" + PRE_COMMIT_SCRIPT2.replace("#!/bin/sh\n", ""), { mode: 493 });
|
|
1982
1926
|
} else {
|
|
1983
|
-
await
|
|
1927
|
+
await fs25.writeFile(preCommitPath, PRE_COMMIT_SCRIPT2, { mode: 493 });
|
|
1984
1928
|
}
|
|
1985
|
-
console.log(
|
|
1929
|
+
console.log(chalk5.green(" \u2714 Applied Guardian protection (git-hooks)"));
|
|
1986
1930
|
}
|
|
1987
1931
|
} catch (e) {
|
|
1988
|
-
console.log(
|
|
1932
|
+
console.log(chalk5.dim(" (Skipped hooks: " + e.message + ")"));
|
|
1989
1933
|
}
|
|
1990
1934
|
}
|
|
1991
|
-
async function fileExists(
|
|
1992
|
-
const
|
|
1935
|
+
async function fileExists(path28) {
|
|
1936
|
+
const fs25 = await import("fs/promises");
|
|
1993
1937
|
try {
|
|
1994
|
-
await
|
|
1938
|
+
await fs25.access(path28);
|
|
1995
1939
|
return true;
|
|
1996
1940
|
} catch {
|
|
1997
1941
|
return false;
|
|
@@ -2001,22 +1945,22 @@ async function fileExists(path27) {
|
|
|
2001
1945
|
// src/commands/scan.ts
|
|
2002
1946
|
init_esm_shims();
|
|
2003
1947
|
init_config();
|
|
2004
|
-
import { Command as
|
|
2005
|
-
import
|
|
1948
|
+
import { Command as Command5 } from "commander";
|
|
1949
|
+
import chalk6 from "chalk";
|
|
2006
1950
|
import ora3 from "ora";
|
|
2007
1951
|
import axios4 from "axios";
|
|
2008
1952
|
import { glob } from "glob";
|
|
2009
|
-
import
|
|
2010
|
-
import
|
|
1953
|
+
import fs4 from "fs/promises";
|
|
1954
|
+
import path5 from "path";
|
|
2011
1955
|
|
|
2012
1956
|
// src/utils/files.ts
|
|
2013
1957
|
init_esm_shims();
|
|
2014
|
-
import
|
|
2015
|
-
import
|
|
1958
|
+
import fs3 from "fs/promises";
|
|
1959
|
+
import path4 from "path";
|
|
2016
1960
|
async function readGitignore(dir) {
|
|
2017
|
-
const gitignorePath =
|
|
1961
|
+
const gitignorePath = path4.join(dir, ".gitignore");
|
|
2018
1962
|
try {
|
|
2019
|
-
const content = await
|
|
1963
|
+
const content = await fs3.readFile(gitignorePath, "utf-8");
|
|
2020
1964
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
2021
1965
|
} catch (error) {
|
|
2022
1966
|
return [];
|
|
@@ -2078,13 +2022,13 @@ function isCodeFile(filePath) {
|
|
|
2078
2022
|
".vue",
|
|
2079
2023
|
".svelte"
|
|
2080
2024
|
];
|
|
2081
|
-
const ext =
|
|
2025
|
+
const ext = path4.extname(filePath).toLowerCase();
|
|
2082
2026
|
return codeExtensions.includes(ext);
|
|
2083
2027
|
}
|
|
2084
2028
|
|
|
2085
2029
|
// src/commands/scan.ts
|
|
2086
2030
|
function createScanCommand() {
|
|
2087
|
-
return new
|
|
2031
|
+
return new Command5("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) => {
|
|
2088
2032
|
const spinner = ora3();
|
|
2089
2033
|
try {
|
|
2090
2034
|
const apiKey = getApiKey();
|
|
@@ -2092,26 +2036,26 @@ function createScanCommand() {
|
|
|
2092
2036
|
const projectId = options.project || getProjectId();
|
|
2093
2037
|
if (!projectId) {
|
|
2094
2038
|
console.warn(
|
|
2095
|
-
|
|
2039
|
+
chalk6.yellow(
|
|
2096
2040
|
"\u26A0\uFE0F No project ID specified. Use --project <id> or set a default."
|
|
2097
2041
|
)
|
|
2098
2042
|
);
|
|
2099
2043
|
}
|
|
2100
|
-
const scanPath =
|
|
2101
|
-
spinner.start(`Scanning ${
|
|
2044
|
+
const scanPath = path5.resolve(process.cwd(), targetPath);
|
|
2045
|
+
spinner.start(`Scanning ${chalk6.cyan(scanPath)}...`);
|
|
2102
2046
|
const gitignorePatterns = await readGitignore(scanPath);
|
|
2103
|
-
const pattern =
|
|
2047
|
+
const pattern = path5.join(scanPath, "**/*");
|
|
2104
2048
|
const allFiles = await glob(pattern, {
|
|
2105
2049
|
nodir: true,
|
|
2106
2050
|
dot: false,
|
|
2107
2051
|
ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/build/**"]
|
|
2108
2052
|
});
|
|
2109
2053
|
const codeFiles = allFiles.filter((file) => {
|
|
2110
|
-
const relativePath =
|
|
2054
|
+
const relativePath = path5.relative(scanPath, file);
|
|
2111
2055
|
return isCodeFile(file) && !shouldIgnore(relativePath, gitignorePatterns);
|
|
2112
2056
|
});
|
|
2113
2057
|
if (codeFiles.length === 0) {
|
|
2114
|
-
spinner.warn(
|
|
2058
|
+
spinner.warn(chalk6.yellow("No code files found to scan."));
|
|
2115
2059
|
return;
|
|
2116
2060
|
}
|
|
2117
2061
|
spinner.text = `Found ${codeFiles.length} files. Scanning...`;
|
|
@@ -2120,10 +2064,10 @@ function createScanCommand() {
|
|
|
2120
2064
|
const severityCounts = {};
|
|
2121
2065
|
for (let i = 0; i < codeFiles.length; i++) {
|
|
2122
2066
|
const filePath = codeFiles[i];
|
|
2123
|
-
const relativePath =
|
|
2067
|
+
const relativePath = path5.relative(scanPath, filePath);
|
|
2124
2068
|
spinner.text = `Scanning ${i + 1}/${codeFiles.length}: ${relativePath}`;
|
|
2125
2069
|
try {
|
|
2126
|
-
const content = await
|
|
2070
|
+
const content = await fs4.readFile(filePath, "utf-8");
|
|
2127
2071
|
const response = await axios4.post(
|
|
2128
2072
|
`${apiUrl}/api/v1/audit`,
|
|
2129
2073
|
{
|
|
@@ -2159,15 +2103,15 @@ function createScanCommand() {
|
|
|
2159
2103
|
}
|
|
2160
2104
|
} catch (fileError) {
|
|
2161
2105
|
if (axios4.isAxiosError(fileError)) {
|
|
2162
|
-
console.warn(
|
|
2106
|
+
console.warn(chalk6.yellow(`
|
|
2163
2107
|
\u26A0\uFE0F Skipping ${relativePath}: ${fileError.message}`));
|
|
2164
2108
|
} else {
|
|
2165
|
-
console.warn(
|
|
2109
|
+
console.warn(chalk6.yellow(`
|
|
2166
2110
|
\u26A0\uFE0F Error reading ${relativePath}`));
|
|
2167
2111
|
}
|
|
2168
2112
|
}
|
|
2169
2113
|
}
|
|
2170
|
-
spinner.succeed(
|
|
2114
|
+
spinner.succeed(chalk6.green("\u2705 Scan completed!"));
|
|
2171
2115
|
const aggregatedResponse = {
|
|
2172
2116
|
results,
|
|
2173
2117
|
summary: {
|
|
@@ -2182,21 +2126,21 @@ function createScanCommand() {
|
|
|
2182
2126
|
printPrettyResults(aggregatedResponse);
|
|
2183
2127
|
}
|
|
2184
2128
|
} catch (error) {
|
|
2185
|
-
spinner.fail(
|
|
2129
|
+
spinner.fail(chalk6.red("\u274C Scan failed"));
|
|
2186
2130
|
if (axios4.isAxiosError(error)) {
|
|
2187
2131
|
if (error.response) {
|
|
2188
|
-
console.error(
|
|
2132
|
+
console.error(chalk6.red("API Error:"), error.response.data);
|
|
2189
2133
|
} else if (error.request) {
|
|
2190
2134
|
console.error(
|
|
2191
|
-
|
|
2135
|
+
chalk6.red("Network Error:"),
|
|
2192
2136
|
"Could not reach the API. Is the server running?"
|
|
2193
2137
|
);
|
|
2194
2138
|
} else {
|
|
2195
|
-
console.error(
|
|
2139
|
+
console.error(chalk6.red("Error:"), error.message);
|
|
2196
2140
|
}
|
|
2197
2141
|
} else {
|
|
2198
2142
|
console.error(
|
|
2199
|
-
|
|
2143
|
+
chalk6.red("Error:"),
|
|
2200
2144
|
error instanceof Error ? error.message : "Unknown error"
|
|
2201
2145
|
);
|
|
2202
2146
|
}
|
|
@@ -2206,10 +2150,10 @@ function createScanCommand() {
|
|
|
2206
2150
|
}
|
|
2207
2151
|
function printPrettyResults(data) {
|
|
2208
2152
|
const { results, summary } = data;
|
|
2209
|
-
console.log("\n" +
|
|
2210
|
-
console.log(
|
|
2211
|
-
console.log(`Total Files Scanned: ${
|
|
2212
|
-
console.log(`Total Issues Found: ${
|
|
2153
|
+
console.log("\n" + chalk6.bold("\u{1F4CA} Scan Summary"));
|
|
2154
|
+
console.log(chalk6.dim("\u2500".repeat(60)));
|
|
2155
|
+
console.log(`Total Files Scanned: ${chalk6.cyan(summary.total_files)}`);
|
|
2156
|
+
console.log(`Total Issues Found: ${chalk6.yellow(summary.total_issues)}`);
|
|
2213
2157
|
if (summary.by_severity) {
|
|
2214
2158
|
console.log("\nIssues by Severity:");
|
|
2215
2159
|
Object.entries(summary.by_severity).forEach(([severity, count]) => {
|
|
@@ -2218,87 +2162,87 @@ function printPrettyResults(data) {
|
|
|
2218
2162
|
});
|
|
2219
2163
|
}
|
|
2220
2164
|
if (results && results.length > 0) {
|
|
2221
|
-
console.log("\n" +
|
|
2222
|
-
console.log(
|
|
2165
|
+
console.log("\n" + chalk6.bold("\u{1F50D} Detailed Results"));
|
|
2166
|
+
console.log(chalk6.dim("\u2500".repeat(60)));
|
|
2223
2167
|
results.forEach((result) => {
|
|
2224
2168
|
if (result.issues && result.issues.length > 0) {
|
|
2225
2169
|
console.log(`
|
|
2226
|
-
${
|
|
2170
|
+
${chalk6.bold(result.file_path)}`);
|
|
2227
2171
|
result.issues.forEach((issue) => {
|
|
2228
2172
|
const severityColor = getSeverityColor(issue.severity);
|
|
2229
|
-
const lineInfo = issue.line ?
|
|
2173
|
+
const lineInfo = issue.line ? chalk6.dim(`:${issue.line}`) : "";
|
|
2230
2174
|
console.log(
|
|
2231
2175
|
` ${severityColor(`[${issue.severity.toUpperCase()}]`)} ${issue.type}${lineInfo}`
|
|
2232
2176
|
);
|
|
2233
|
-
console.log(` ${
|
|
2177
|
+
console.log(` ${chalk6.dim(issue.message)}`);
|
|
2234
2178
|
});
|
|
2235
2179
|
}
|
|
2236
2180
|
});
|
|
2237
2181
|
}
|
|
2238
|
-
console.log("\n" +
|
|
2182
|
+
console.log("\n" + chalk6.dim("\u2500".repeat(60)));
|
|
2239
2183
|
}
|
|
2240
2184
|
function getSeverityColor(severity) {
|
|
2241
2185
|
switch (severity.toLowerCase()) {
|
|
2242
2186
|
case "critical":
|
|
2243
|
-
return
|
|
2187
|
+
return chalk6.red.bold;
|
|
2244
2188
|
case "high":
|
|
2245
|
-
return
|
|
2189
|
+
return chalk6.red;
|
|
2246
2190
|
case "medium":
|
|
2247
|
-
return
|
|
2191
|
+
return chalk6.yellow;
|
|
2248
2192
|
case "low":
|
|
2249
|
-
return
|
|
2193
|
+
return chalk6.blue;
|
|
2250
2194
|
case "info":
|
|
2251
|
-
return
|
|
2195
|
+
return chalk6.gray;
|
|
2252
2196
|
default:
|
|
2253
|
-
return
|
|
2197
|
+
return chalk6.white;
|
|
2254
2198
|
}
|
|
2255
2199
|
}
|
|
2256
2200
|
|
|
2257
2201
|
// src/commands/fix.ts
|
|
2258
2202
|
init_esm_shims();
|
|
2259
2203
|
init_config();
|
|
2260
|
-
import { Command as
|
|
2261
|
-
import
|
|
2204
|
+
import { Command as Command6 } from "commander";
|
|
2205
|
+
import chalk7 from "chalk";
|
|
2262
2206
|
import ora4 from "ora";
|
|
2263
2207
|
import axios5 from "axios";
|
|
2264
2208
|
import { glob as glob2 } from "glob";
|
|
2265
|
-
import
|
|
2266
|
-
import
|
|
2209
|
+
import fs5 from "fs/promises";
|
|
2210
|
+
import path6 from "path";
|
|
2267
2211
|
import inquirer from "inquirer";
|
|
2268
2212
|
import * as Diff from "diff";
|
|
2269
2213
|
function createFixCommand() {
|
|
2270
|
-
return new
|
|
2214
|
+
return new Command6("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) => {
|
|
2271
2215
|
const spinner = ora4();
|
|
2272
2216
|
try {
|
|
2273
2217
|
const apiKey = getApiKey();
|
|
2274
2218
|
const apiUrl = getApiUrl();
|
|
2275
2219
|
const projectId = options.project || getProjectId();
|
|
2276
2220
|
if (!projectId) {
|
|
2277
|
-
console.log(
|
|
2221
|
+
console.log(chalk7.yellow("\u26A0\uFE0F Project ID is required for fixing. Using default or pass --project <id>"));
|
|
2278
2222
|
}
|
|
2279
|
-
const scanPath =
|
|
2223
|
+
const scanPath = path6.resolve(process.cwd(), targetPath);
|
|
2280
2224
|
const gitignorePatterns = await readGitignore(scanPath);
|
|
2281
|
-
const pattern =
|
|
2225
|
+
const pattern = path6.join(scanPath, "**/*");
|
|
2282
2226
|
const allFiles = await glob2(pattern, { nodir: true, dot: false, ignore: ["**/node_modules/**", "**/.git/**"] });
|
|
2283
2227
|
const codeFiles = allFiles.filter((file) => {
|
|
2284
|
-
const relativePath =
|
|
2228
|
+
const relativePath = path6.relative(scanPath, file);
|
|
2285
2229
|
return isCodeFile(file) && !shouldIgnore(relativePath, gitignorePatterns);
|
|
2286
2230
|
});
|
|
2287
2231
|
if (codeFiles.length === 0) {
|
|
2288
|
-
console.log(
|
|
2232
|
+
console.log(chalk7.yellow("No code files found."));
|
|
2289
2233
|
return;
|
|
2290
2234
|
}
|
|
2291
|
-
console.log(
|
|
2235
|
+
console.log(chalk7.bold(`
|
|
2292
2236
|
\u{1F9E0} Rigstate Fix Mode`));
|
|
2293
|
-
console.log(
|
|
2237
|
+
console.log(chalk7.dim(`Scanning ${codeFiles.length} files with Project Context...
|
|
2294
2238
|
`));
|
|
2295
2239
|
let fixedCount = 0;
|
|
2296
2240
|
for (let i = 0; i < codeFiles.length; i++) {
|
|
2297
2241
|
const filePath = codeFiles[i];
|
|
2298
|
-
const relativePath =
|
|
2242
|
+
const relativePath = path6.relative(scanPath, filePath);
|
|
2299
2243
|
spinner.start(`Analyzing ${relativePath}...`);
|
|
2300
2244
|
try {
|
|
2301
|
-
const content = await
|
|
2245
|
+
const content = await fs5.readFile(filePath, "utf-8");
|
|
2302
2246
|
const response = await axios5.post(
|
|
2303
2247
|
`${apiUrl}/api/v1/audit`,
|
|
2304
2248
|
{ content, file_path: relativePath, project_id: projectId },
|
|
@@ -2309,22 +2253,22 @@ function createFixCommand() {
|
|
|
2309
2253
|
if (fixableIssues.length > 0) {
|
|
2310
2254
|
spinner.stop();
|
|
2311
2255
|
console.log(`
|
|
2312
|
-
${
|
|
2256
|
+
${chalk7.bold(relativePath)}: Found ${fixableIssues.length} fixable issues.`);
|
|
2313
2257
|
for (const issue of fixableIssues) {
|
|
2314
|
-
console.log(
|
|
2258
|
+
console.log(chalk7.red(`
|
|
2315
2259
|
[${issue.type}] ${issue.title}`));
|
|
2316
|
-
console.log(
|
|
2260
|
+
console.log(chalk7.dim(issue.suggestion || issue.message));
|
|
2317
2261
|
const diff = Diff.createTwoFilesPatch(relativePath, relativePath, content, issue.fixed_content, "Current", "Fixed");
|
|
2318
2262
|
console.log("\n" + diff.split("\n").slice(0, 15).join("\n") + (diff.split("\n").length > 15 ? "\n..." : ""));
|
|
2319
2263
|
const { apply } = await inquirer.prompt([{
|
|
2320
2264
|
type: "confirm",
|
|
2321
2265
|
name: "apply",
|
|
2322
|
-
message: `Apply this fix to ${
|
|
2266
|
+
message: `Apply this fix to ${chalk7.cyan(relativePath)}?`,
|
|
2323
2267
|
default: true
|
|
2324
2268
|
}]);
|
|
2325
2269
|
if (apply) {
|
|
2326
|
-
await
|
|
2327
|
-
console.log(
|
|
2270
|
+
await fs5.writeFile(filePath, issue.fixed_content);
|
|
2271
|
+
console.log(chalk7.green(`\u2705 Fixed applied!`));
|
|
2328
2272
|
fixedCount++;
|
|
2329
2273
|
if (issue.related_step_id) {
|
|
2330
2274
|
const { completeStep } = await inquirer.prompt([{
|
|
@@ -2340,15 +2284,15 @@ ${chalk8.bold(relativePath)}: Found ${fixableIssues.length} fixable issues.`);
|
|
|
2340
2284
|
{ step_id: issue.related_step_id, status: "COMPLETED", project_id: projectId },
|
|
2341
2285
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
2342
2286
|
);
|
|
2343
|
-
console.log(
|
|
2287
|
+
console.log(chalk7.green(`\u{1F680} Roadmap updated! Mission Control is in sync.`));
|
|
2344
2288
|
} catch (err) {
|
|
2345
|
-
console.error(
|
|
2289
|
+
console.error(chalk7.yellow(`Failed to update roadmap: ${err.message}`));
|
|
2346
2290
|
}
|
|
2347
2291
|
}
|
|
2348
2292
|
}
|
|
2349
2293
|
break;
|
|
2350
2294
|
} else {
|
|
2351
|
-
console.log(
|
|
2295
|
+
console.log(chalk7.dim("Skipped."));
|
|
2352
2296
|
}
|
|
2353
2297
|
}
|
|
2354
2298
|
} else {
|
|
@@ -2358,11 +2302,11 @@ ${chalk8.bold(relativePath)}: Found ${fixableIssues.length} fixable issues.`);
|
|
|
2358
2302
|
}
|
|
2359
2303
|
}
|
|
2360
2304
|
spinner.stop();
|
|
2361
|
-
console.log(
|
|
2305
|
+
console.log(chalk7.bold.green(`
|
|
2362
2306
|
|
|
2363
2307
|
\u{1F680} Fix session complete!`));
|
|
2364
2308
|
console.log(`Frank fixed ${fixedCount} detected issues.`);
|
|
2365
|
-
console.log(
|
|
2309
|
+
console.log(chalk7.dim(`Run 'rigstate scan' to verify remaining issues.`));
|
|
2366
2310
|
} catch (error) {
|
|
2367
2311
|
spinner.fail("Fix session failed");
|
|
2368
2312
|
console.error(error.message);
|
|
@@ -2373,14 +2317,14 @@ ${chalk8.bold(relativePath)}: Found ${fixableIssues.length} fixable issues.`);
|
|
|
2373
2317
|
// src/commands/sync.ts
|
|
2374
2318
|
init_esm_shims();
|
|
2375
2319
|
init_config();
|
|
2376
|
-
import { Command as
|
|
2377
|
-
import
|
|
2320
|
+
import { Command as Command7 } from "commander";
|
|
2321
|
+
import chalk11 from "chalk";
|
|
2378
2322
|
import ora5 from "ora";
|
|
2379
2323
|
import axios8 from "axios";
|
|
2380
|
-
import
|
|
2381
|
-
import
|
|
2324
|
+
import fs9 from "fs/promises";
|
|
2325
|
+
import path10 from "path";
|
|
2382
2326
|
function createSyncCommand() {
|
|
2383
|
-
const sync = new
|
|
2327
|
+
const sync = new Command7("sync");
|
|
2384
2328
|
sync.description("Synchronize local state with Rigstate Cloud").option("-p, --project <id>", "Specify Project ID (saves to config automatically)").action(async (options) => {
|
|
2385
2329
|
const spinner = ora5("Synchronizing project state...").start();
|
|
2386
2330
|
try {
|
|
@@ -2394,8 +2338,8 @@ function createSyncCommand() {
|
|
|
2394
2338
|
let projectId = options.project;
|
|
2395
2339
|
if (!projectId) {
|
|
2396
2340
|
try {
|
|
2397
|
-
const manifestPath =
|
|
2398
|
-
const manifestContent = await
|
|
2341
|
+
const manifestPath = path10.join(process.cwd(), ".rigstate");
|
|
2342
|
+
const manifestContent = await fs9.readFile(manifestPath, "utf-8");
|
|
2399
2343
|
const manifest = JSON.parse(manifestContent);
|
|
2400
2344
|
if (manifest.project_id) projectId = manifest.project_id;
|
|
2401
2345
|
} catch (e) {
|
|
@@ -2419,31 +2363,31 @@ function createSyncCommand() {
|
|
|
2419
2363
|
}
|
|
2420
2364
|
const { roadmap, project } = response.data.data;
|
|
2421
2365
|
const timestamp = response.data.timestamp;
|
|
2422
|
-
const targetPath =
|
|
2366
|
+
const targetPath = path10.join(process.cwd(), "roadmap.json");
|
|
2423
2367
|
const fileContent = JSON.stringify({
|
|
2424
2368
|
project,
|
|
2425
2369
|
last_synced: timestamp,
|
|
2426
2370
|
roadmap
|
|
2427
2371
|
}, null, 2);
|
|
2428
|
-
await
|
|
2372
|
+
await fs9.writeFile(targetPath, fileContent, "utf-8");
|
|
2429
2373
|
try {
|
|
2430
|
-
const manifestPath =
|
|
2374
|
+
const manifestPath = path10.join(process.cwd(), ".rigstate");
|
|
2431
2375
|
const manifestContent = {
|
|
2432
2376
|
project_id: projectId,
|
|
2433
2377
|
project_name: project,
|
|
2434
2378
|
last_synced: timestamp,
|
|
2435
2379
|
api_url: apiUrl
|
|
2436
2380
|
};
|
|
2437
|
-
await
|
|
2381
|
+
await fs9.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), "utf-8");
|
|
2438
2382
|
} catch (e) {
|
|
2439
2383
|
}
|
|
2440
|
-
console.log(
|
|
2384
|
+
console.log(chalk11.bold("\n\u{1F9E0} Agent Skills Provisioning..."));
|
|
2441
2385
|
try {
|
|
2442
2386
|
const { provisionSkills: provisionSkills2, generateSkillsDiscoveryBlock: generateSkillsDiscoveryBlock2 } = await Promise.resolve().then(() => (init_skills_provisioner(), skills_provisioner_exports));
|
|
2443
2387
|
const skills = await provisionSkills2(apiUrl, apiKey, projectId, process.cwd());
|
|
2444
|
-
const cursorRulesPath =
|
|
2388
|
+
const cursorRulesPath = path10.join(process.cwd(), ".cursorrules");
|
|
2445
2389
|
try {
|
|
2446
|
-
let rulesContent = await
|
|
2390
|
+
let rulesContent = await fs9.readFile(cursorRulesPath, "utf-8");
|
|
2447
2391
|
const skillsBlock = generateSkillsDiscoveryBlock2(skills);
|
|
2448
2392
|
if (rulesContent.includes("<available_skills>")) {
|
|
2449
2393
|
rulesContent = rulesContent.replace(
|
|
@@ -2456,17 +2400,17 @@ function createSyncCommand() {
|
|
|
2456
2400
|
rulesContent = rulesContent.slice(0, insertPoint + 3) + "\n\n" + skillsBlock + "\n" + rulesContent.slice(insertPoint + 3);
|
|
2457
2401
|
}
|
|
2458
2402
|
}
|
|
2459
|
-
await
|
|
2460
|
-
console.log(
|
|
2403
|
+
await fs9.writeFile(cursorRulesPath, rulesContent, "utf-8");
|
|
2404
|
+
console.log(chalk11.dim(` Updated .cursorrules with skills discovery block`));
|
|
2461
2405
|
} catch (e) {
|
|
2462
2406
|
}
|
|
2463
2407
|
} catch (e) {
|
|
2464
|
-
console.log(
|
|
2408
|
+
console.log(chalk11.yellow(` \u26A0 Skills provisioning skipped: ${e.message}`));
|
|
2465
2409
|
}
|
|
2466
2410
|
try {
|
|
2467
|
-
const logPath =
|
|
2411
|
+
const logPath = path10.join(process.cwd(), ".rigstate", "logs", "last_execution.json");
|
|
2468
2412
|
try {
|
|
2469
|
-
const logContent = await
|
|
2413
|
+
const logContent = await fs9.readFile(logPath, "utf-8");
|
|
2470
2414
|
const logData = JSON.parse(logContent);
|
|
2471
2415
|
if (logData.task_summary) {
|
|
2472
2416
|
await axios8.post(`${apiUrl}/api/v1/execution-logs`, {
|
|
@@ -2476,8 +2420,8 @@ function createSyncCommand() {
|
|
|
2476
2420
|
}, {
|
|
2477
2421
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2478
2422
|
});
|
|
2479
|
-
await
|
|
2480
|
-
console.log(
|
|
2423
|
+
await fs9.unlink(logPath);
|
|
2424
|
+
console.log(chalk11.dim(`\u2714 Mission Report uploaded.`));
|
|
2481
2425
|
}
|
|
2482
2426
|
} catch (e) {
|
|
2483
2427
|
if (e.code !== "ENOENT") {
|
|
@@ -2485,12 +2429,12 @@ function createSyncCommand() {
|
|
|
2485
2429
|
}
|
|
2486
2430
|
} catch (e) {
|
|
2487
2431
|
}
|
|
2488
|
-
spinner.succeed(
|
|
2489
|
-
console.log(
|
|
2432
|
+
spinner.succeed(chalk11.green(`Synced ${roadmap.length} roadmap steps for project "${project}"`));
|
|
2433
|
+
console.log(chalk11.dim(`Local files updated: roadmap.json`));
|
|
2490
2434
|
const { runGuardianWatchdog: runGuardianWatchdog2 } = await Promise.resolve().then(() => (init_watchdog(), watchdog_exports));
|
|
2491
2435
|
const settings = response.data.data.settings || {};
|
|
2492
2436
|
await runGuardianWatchdog2(process.cwd(), settings, projectId);
|
|
2493
|
-
console.log(
|
|
2437
|
+
console.log(chalk11.bold("\n\u{1F4E1} Agent Bridge Heartbeat..."));
|
|
2494
2438
|
try {
|
|
2495
2439
|
const bridgeResponse = await axios8.get(`${apiUrl}/api/v1/agent/bridge`, {
|
|
2496
2440
|
params: { project_id: projectId },
|
|
@@ -2501,10 +2445,10 @@ function createSyncCommand() {
|
|
|
2501
2445
|
const pending = tasks.filter((t) => t.status === "PENDING");
|
|
2502
2446
|
const approved = tasks.filter((t) => t.status === "APPROVED");
|
|
2503
2447
|
if (pending.length > 0 || approved.length > 0) {
|
|
2504
|
-
console.log(
|
|
2505
|
-
console.log(
|
|
2448
|
+
console.log(chalk11.yellow(`\u26A0 Bridge Alert: ${pending.length} pending, ${approved.length} approved tasks found.`));
|
|
2449
|
+
console.log(chalk11.dim('Run "rigstate fix" to process these tasks or ensure your IDE MCP server is active.'));
|
|
2506
2450
|
} else {
|
|
2507
|
-
console.log(
|
|
2451
|
+
console.log(chalk11.green("\u2714 Heartbeat healthy. No pending bridge tasks."));
|
|
2508
2452
|
}
|
|
2509
2453
|
const pings = pending.filter((t) => t.proposal?.startsWith("ping"));
|
|
2510
2454
|
for (const ping of pings) {
|
|
@@ -2515,25 +2459,25 @@ function createSyncCommand() {
|
|
|
2515
2459
|
}, {
|
|
2516
2460
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2517
2461
|
});
|
|
2518
|
-
console.log(
|
|
2462
|
+
console.log(chalk11.cyan(`\u{1F3D3} Pong! Acknowledged heartbeat signal [${ping.id}]`));
|
|
2519
2463
|
}
|
|
2520
2464
|
}
|
|
2521
2465
|
} catch (e) {
|
|
2522
|
-
console.log(
|
|
2466
|
+
console.log(chalk11.yellow(`\u26A0 Could not verify Bridge status: ${e.message}`));
|
|
2523
2467
|
}
|
|
2524
2468
|
if (options.project) {
|
|
2525
|
-
console.log(
|
|
2469
|
+
console.log(chalk11.blue(`Project context saved. Future commands will use this project.`));
|
|
2526
2470
|
}
|
|
2527
2471
|
try {
|
|
2528
|
-
const migrationDir =
|
|
2529
|
-
const files = await
|
|
2472
|
+
const migrationDir = path10.join(process.cwd(), "supabase", "migrations");
|
|
2473
|
+
const files = await fs9.readdir(migrationDir);
|
|
2530
2474
|
const sqlFiles = files.filter((f) => f.endsWith(".sql")).sort();
|
|
2531
2475
|
if (sqlFiles.length > 0) {
|
|
2532
2476
|
const latestMigration = sqlFiles[sqlFiles.length - 1];
|
|
2533
|
-
console.log(
|
|
2477
|
+
console.log(chalk11.dim(`
|
|
2534
2478
|
\u{1F6E1} Migration Guard:`));
|
|
2535
|
-
console.log(
|
|
2536
|
-
console.log(
|
|
2479
|
+
console.log(chalk11.dim(` Latest Local: ${latestMigration}`));
|
|
2480
|
+
console.log(chalk11.yellow(` \u26A0 Ensure DB schema matches this version. CLI cannot verify Remote RLS policies directly.`));
|
|
2537
2481
|
}
|
|
2538
2482
|
} catch (e) {
|
|
2539
2483
|
}
|
|
@@ -2545,15 +2489,15 @@ function createSyncCommand() {
|
|
|
2545
2489
|
);
|
|
2546
2490
|
if (vaultResponse.data.success) {
|
|
2547
2491
|
const vaultContent = vaultResponse.data.data.content || "";
|
|
2548
|
-
const localEnvPath =
|
|
2492
|
+
const localEnvPath = path10.join(process.cwd(), ".env.local");
|
|
2549
2493
|
let localContent = "";
|
|
2550
2494
|
try {
|
|
2551
|
-
localContent = await
|
|
2495
|
+
localContent = await fs9.readFile(localEnvPath, "utf-8");
|
|
2552
2496
|
} catch (e) {
|
|
2553
2497
|
}
|
|
2554
2498
|
if (vaultContent.trim() !== localContent.trim()) {
|
|
2555
|
-
console.log(
|
|
2556
|
-
console.log(
|
|
2499
|
+
console.log(chalk11.bold("\n\u{1F510} Sovereign Foundation (Vault):"));
|
|
2500
|
+
console.log(chalk11.yellow(" Status: Drift Detected / Update Available"));
|
|
2557
2501
|
const { syncVault } = await import("inquirer").then((m) => m.default.prompt([{
|
|
2558
2502
|
type: "confirm",
|
|
2559
2503
|
name: "syncVault",
|
|
@@ -2561,25 +2505,25 @@ function createSyncCommand() {
|
|
|
2561
2505
|
default: false
|
|
2562
2506
|
}]));
|
|
2563
2507
|
if (syncVault) {
|
|
2564
|
-
await
|
|
2565
|
-
console.log(
|
|
2508
|
+
await fs9.writeFile(localEnvPath, vaultContent, "utf-8");
|
|
2509
|
+
console.log(chalk11.green(" \u2705 .env.local synchronized with Vault."));
|
|
2566
2510
|
} else {
|
|
2567
|
-
console.log(
|
|
2511
|
+
console.log(chalk11.dim(" Skipped vault sync."));
|
|
2568
2512
|
}
|
|
2569
2513
|
} else {
|
|
2570
|
-
console.log(
|
|
2514
|
+
console.log(chalk11.dim("\n\u{1F510} Sovereign Foundation: Synced."));
|
|
2571
2515
|
}
|
|
2572
2516
|
}
|
|
2573
2517
|
} catch (e) {
|
|
2574
2518
|
}
|
|
2575
|
-
console.log(
|
|
2519
|
+
console.log(chalk11.dim("\n\u{1F6E1}\uFE0F System Integrity Check..."));
|
|
2576
2520
|
await checkSystemIntegrity(apiUrl, apiKey, projectId);
|
|
2577
2521
|
} catch (error) {
|
|
2578
2522
|
if (axios8.isAxiosError(error)) {
|
|
2579
2523
|
const message = error.response?.data?.error || error.message;
|
|
2580
|
-
spinner.fail(
|
|
2524
|
+
spinner.fail(chalk11.red(`Sync failed: ${message}`));
|
|
2581
2525
|
} else {
|
|
2582
|
-
spinner.fail(
|
|
2526
|
+
spinner.fail(chalk11.red("Sync failed: " + (error.message || "Unknown error")));
|
|
2583
2527
|
}
|
|
2584
2528
|
}
|
|
2585
2529
|
});
|
|
@@ -2595,57 +2539,57 @@ async function checkSystemIntegrity(apiUrl, apiKey, projectId) {
|
|
|
2595
2539
|
const { migrations, rls, guardian_violations } = response.data.data;
|
|
2596
2540
|
if (migrations) {
|
|
2597
2541
|
if (migrations.in_sync) {
|
|
2598
|
-
console.log(
|
|
2542
|
+
console.log(chalk11.green(` \u2705 Migrations synced (${migrations.count} versions)`));
|
|
2599
2543
|
} else {
|
|
2600
|
-
console.log(
|
|
2544
|
+
console.log(chalk11.red(` \u{1F6D1} CRITICAL: DB Schema out of sync! ${migrations.missing?.length || 0} migrations not applied.`));
|
|
2601
2545
|
if (migrations.missing?.length > 0) {
|
|
2602
|
-
console.log(
|
|
2546
|
+
console.log(chalk11.dim(` Missing: ${migrations.missing.slice(0, 3).join(", ")}${migrations.missing.length > 3 ? "..." : ""}`));
|
|
2603
2547
|
}
|
|
2604
|
-
console.log(
|
|
2548
|
+
console.log(chalk11.yellow(` Run 'supabase db push' or apply migrations immediately.`));
|
|
2605
2549
|
}
|
|
2606
2550
|
}
|
|
2607
2551
|
if (rls) {
|
|
2608
2552
|
if (rls.all_secured) {
|
|
2609
|
-
console.log(
|
|
2553
|
+
console.log(chalk11.green(` \u2705 RLS Audit Passed (${rls.table_count} tables secured)`));
|
|
2610
2554
|
} else {
|
|
2611
|
-
console.log(
|
|
2555
|
+
console.log(chalk11.red(` \u{1F6D1} CRITICAL: Security Vulnerability! ${rls.unsecured?.length || 0} tables have RLS disabled.`));
|
|
2612
2556
|
rls.unsecured?.forEach((table) => {
|
|
2613
|
-
console.log(
|
|
2557
|
+
console.log(chalk11.red(` - ${table}`));
|
|
2614
2558
|
});
|
|
2615
|
-
console.log(
|
|
2559
|
+
console.log(chalk11.yellow(' Enable RLS immediately: ALTER TABLE "table" ENABLE ROW LEVEL SECURITY;'));
|
|
2616
2560
|
}
|
|
2617
2561
|
}
|
|
2618
2562
|
if (guardian_violations) {
|
|
2619
2563
|
if (guardian_violations.count === 0) {
|
|
2620
|
-
console.log(
|
|
2564
|
+
console.log(chalk11.green(" \u2705 Guardian: No active violations"));
|
|
2621
2565
|
} else {
|
|
2622
|
-
console.log(
|
|
2623
|
-
console.log(
|
|
2566
|
+
console.log(chalk11.yellow(` \u26A0\uFE0F Guardian: ${guardian_violations.count} active violations`));
|
|
2567
|
+
console.log(chalk11.dim(' Run "rigstate check" for details.'));
|
|
2624
2568
|
}
|
|
2625
2569
|
}
|
|
2626
2570
|
}
|
|
2627
2571
|
} catch (e) {
|
|
2628
|
-
console.log(
|
|
2572
|
+
console.log(chalk11.dim(" (System integrity check skipped - API endpoint not available)"));
|
|
2629
2573
|
}
|
|
2630
2574
|
}
|
|
2631
2575
|
|
|
2632
2576
|
// src/commands/init.ts
|
|
2633
2577
|
init_esm_shims();
|
|
2634
|
-
import { Command as
|
|
2635
|
-
import
|
|
2636
|
-
import
|
|
2637
|
-
import
|
|
2578
|
+
import { Command as Command8 } from "commander";
|
|
2579
|
+
import chalk12 from "chalk";
|
|
2580
|
+
import fs11 from "fs/promises";
|
|
2581
|
+
import path12 from "path";
|
|
2638
2582
|
import ora6 from "ora";
|
|
2639
2583
|
import { execSync } from "child_process";
|
|
2640
2584
|
|
|
2641
2585
|
// src/utils/manifest.ts
|
|
2642
2586
|
init_esm_shims();
|
|
2643
|
-
import
|
|
2644
|
-
import
|
|
2587
|
+
import fs10 from "fs/promises";
|
|
2588
|
+
import path11 from "path";
|
|
2645
2589
|
async function loadManifest() {
|
|
2646
2590
|
try {
|
|
2647
|
-
const manifestPath =
|
|
2648
|
-
const content = await
|
|
2591
|
+
const manifestPath = path11.join(process.cwd(), ".rigstate");
|
|
2592
|
+
const content = await fs10.readFile(manifestPath, "utf-8");
|
|
2649
2593
|
return JSON.parse(content);
|
|
2650
2594
|
} catch {
|
|
2651
2595
|
return null;
|
|
@@ -2656,13 +2600,13 @@ async function loadManifest() {
|
|
|
2656
2600
|
init_config();
|
|
2657
2601
|
import axios9 from "axios";
|
|
2658
2602
|
function createInitCommand() {
|
|
2659
|
-
return new
|
|
2603
|
+
return new Command8("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) => {
|
|
2660
2604
|
const spinner = ora6("Initializing Rigstate project...").start();
|
|
2661
2605
|
let apiKey;
|
|
2662
2606
|
try {
|
|
2663
2607
|
apiKey = getApiKey();
|
|
2664
2608
|
} catch (e) {
|
|
2665
|
-
spinner.fail(
|
|
2609
|
+
spinner.fail(chalk12.red('Not authenticated. Run "rigstate login" first.'));
|
|
2666
2610
|
return;
|
|
2667
2611
|
}
|
|
2668
2612
|
const apiUrl = getApiUrl();
|
|
@@ -2680,7 +2624,7 @@ function createInitCommand() {
|
|
|
2680
2624
|
}
|
|
2681
2625
|
if (!projectId) {
|
|
2682
2626
|
spinner.stop();
|
|
2683
|
-
const
|
|
2627
|
+
const inquirer8 = (await import("inquirer")).default;
|
|
2684
2628
|
spinner.start("Fetching your projects...");
|
|
2685
2629
|
let projects = [];
|
|
2686
2630
|
try {
|
|
@@ -2695,7 +2639,7 @@ function createInitCommand() {
|
|
|
2695
2639
|
}
|
|
2696
2640
|
spinner.stop();
|
|
2697
2641
|
if (projects.length === 0) {
|
|
2698
|
-
const { manualProjectId } = await
|
|
2642
|
+
const { manualProjectId } = await inquirer8.prompt([
|
|
2699
2643
|
{
|
|
2700
2644
|
type: "input",
|
|
2701
2645
|
name: "manualProjectId",
|
|
@@ -2707,7 +2651,7 @@ function createInitCommand() {
|
|
|
2707
2651
|
} else {
|
|
2708
2652
|
const choices = [
|
|
2709
2653
|
{ name: "\u2795 Create New Project", value: "NEW" },
|
|
2710
|
-
new
|
|
2654
|
+
new inquirer8.Separator()
|
|
2711
2655
|
];
|
|
2712
2656
|
projects.forEach((p) => {
|
|
2713
2657
|
choices.push({
|
|
@@ -2715,7 +2659,7 @@ function createInitCommand() {
|
|
|
2715
2659
|
value: p.id
|
|
2716
2660
|
});
|
|
2717
2661
|
});
|
|
2718
|
-
const { selectedId } = await
|
|
2662
|
+
const { selectedId } = await inquirer8.prompt([
|
|
2719
2663
|
{
|
|
2720
2664
|
type: "list",
|
|
2721
2665
|
name: "selectedId",
|
|
@@ -2725,7 +2669,7 @@ function createInitCommand() {
|
|
|
2725
2669
|
}
|
|
2726
2670
|
]);
|
|
2727
2671
|
if (selectedId === "NEW") {
|
|
2728
|
-
const { newName } = await
|
|
2672
|
+
const { newName } = await inquirer8.prompt([
|
|
2729
2673
|
{
|
|
2730
2674
|
type: "input",
|
|
2731
2675
|
name: "newName",
|
|
@@ -2745,7 +2689,7 @@ function createInitCommand() {
|
|
|
2745
2689
|
spinner.stop();
|
|
2746
2690
|
let selectedOrgId = orgs[0]?.id;
|
|
2747
2691
|
if (orgs.length > 1) {
|
|
2748
|
-
const { orgId } = await
|
|
2692
|
+
const { orgId } = await inquirer8.prompt([
|
|
2749
2693
|
{
|
|
2750
2694
|
type: "list",
|
|
2751
2695
|
name: "orgId",
|
|
@@ -2759,7 +2703,7 @@ function createInitCommand() {
|
|
|
2759
2703
|
selectedOrgId = orgId;
|
|
2760
2704
|
}
|
|
2761
2705
|
if (!selectedOrgId) {
|
|
2762
|
-
console.log(
|
|
2706
|
+
console.log(chalk12.yellow("No organization available. Please create the project via the Rigstate dashboard."));
|
|
2763
2707
|
return;
|
|
2764
2708
|
}
|
|
2765
2709
|
spinner.start("Creating new project...");
|
|
@@ -2771,13 +2715,13 @@ function createInitCommand() {
|
|
|
2771
2715
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2772
2716
|
});
|
|
2773
2717
|
if (!createResponse.data.success) {
|
|
2774
|
-
spinner.fail(
|
|
2718
|
+
spinner.fail(chalk12.red("Failed to create project: " + createResponse.data.error));
|
|
2775
2719
|
return;
|
|
2776
2720
|
}
|
|
2777
2721
|
projectId = createResponse.data.data.project.id;
|
|
2778
|
-
spinner.succeed(
|
|
2722
|
+
spinner.succeed(chalk12.green(`Created new project: ${newName}`));
|
|
2779
2723
|
} catch (e) {
|
|
2780
|
-
spinner.fail(
|
|
2724
|
+
spinner.fail(chalk12.red("Project creation API not available. Please create via dashboard."));
|
|
2781
2725
|
return;
|
|
2782
2726
|
}
|
|
2783
2727
|
} else {
|
|
@@ -2787,28 +2731,28 @@ function createInitCommand() {
|
|
|
2787
2731
|
spinner.start(`Linking to project ID: ${projectId}...`);
|
|
2788
2732
|
}
|
|
2789
2733
|
setProjectId(projectId);
|
|
2790
|
-
const manifestPath =
|
|
2734
|
+
const manifestPath = path12.join(process.cwd(), ".rigstate");
|
|
2791
2735
|
const manifestContent = {
|
|
2792
2736
|
project_id: projectId,
|
|
2793
2737
|
last_linked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2794
2738
|
api_url: apiUrl
|
|
2795
2739
|
};
|
|
2796
|
-
await
|
|
2740
|
+
await fs11.writeFile(manifestPath, JSON.stringify(manifestContent, null, 2), "utf-8");
|
|
2797
2741
|
try {
|
|
2798
|
-
await
|
|
2742
|
+
await fs11.access(".git");
|
|
2799
2743
|
} catch {
|
|
2800
2744
|
spinner.text = "Initializing git repository...";
|
|
2801
2745
|
execSync("git init", { stdio: "ignore" });
|
|
2802
2746
|
}
|
|
2803
|
-
spinner.succeed(
|
|
2747
|
+
spinner.succeed(chalk12.green(`\u2705 Linked to project: ${projectId}`));
|
|
2804
2748
|
await generateRules(apiUrl, apiKey, projectId, options.force, spinner);
|
|
2805
2749
|
console.log("");
|
|
2806
|
-
console.log(
|
|
2807
|
-
console.log(
|
|
2808
|
-
console.log(
|
|
2809
|
-
console.log(
|
|
2750
|
+
console.log(chalk12.blue("Next steps:"));
|
|
2751
|
+
console.log(chalk12.dim(" rigstate sync - Sync roadmap and context"));
|
|
2752
|
+
console.log(chalk12.dim(" rigstate watch - Start development loop"));
|
|
2753
|
+
console.log(chalk12.dim(" rigstate focus - Get current task"));
|
|
2810
2754
|
} catch (e) {
|
|
2811
|
-
spinner.fail(
|
|
2755
|
+
spinner.fail(chalk12.red("Initialization failed: " + e.message));
|
|
2812
2756
|
}
|
|
2813
2757
|
});
|
|
2814
2758
|
}
|
|
@@ -2823,67 +2767,67 @@ async function generateRules(apiUrl, apiKey, projectId, force, spinner) {
|
|
|
2823
2767
|
if (response.data.success || response.data.files) {
|
|
2824
2768
|
const files = response.data.files || [];
|
|
2825
2769
|
if (files.length === 0 && response.data.rules) {
|
|
2826
|
-
const rulesPath =
|
|
2827
|
-
await
|
|
2828
|
-
spinner.succeed(
|
|
2770
|
+
const rulesPath = path12.join(process.cwd(), ".cursorrules");
|
|
2771
|
+
await fs11.writeFile(rulesPath, response.data.rules, "utf-8");
|
|
2772
|
+
spinner.succeed(chalk12.green("\u2714 Generated .cursorrules (legacy mode)"));
|
|
2829
2773
|
return;
|
|
2830
2774
|
}
|
|
2831
2775
|
for (const file of files) {
|
|
2832
|
-
const targetPath =
|
|
2833
|
-
const targetDir =
|
|
2834
|
-
await
|
|
2776
|
+
const targetPath = path12.join(process.cwd(), file.path);
|
|
2777
|
+
const targetDir = path12.dirname(targetPath);
|
|
2778
|
+
await fs11.mkdir(targetDir, { recursive: true });
|
|
2835
2779
|
try {
|
|
2836
|
-
await
|
|
2780
|
+
await fs11.access(targetPath);
|
|
2837
2781
|
if (!force && !file.path.startsWith(".cursor/rules/")) {
|
|
2838
|
-
console.log(
|
|
2782
|
+
console.log(chalk12.dim(` ${file.path} already exists. Skipping.`));
|
|
2839
2783
|
continue;
|
|
2840
2784
|
}
|
|
2841
2785
|
} catch {
|
|
2842
2786
|
}
|
|
2843
|
-
await
|
|
2787
|
+
await fs11.writeFile(targetPath, file.content, "utf-8");
|
|
2844
2788
|
}
|
|
2845
2789
|
if (files.length > 0) {
|
|
2846
|
-
const legacyPath =
|
|
2790
|
+
const legacyPath = path12.join(process.cwd(), ".cursorrules");
|
|
2847
2791
|
try {
|
|
2848
|
-
const stats = await
|
|
2792
|
+
const stats = await fs11.stat(legacyPath);
|
|
2849
2793
|
if (stats.isFile()) {
|
|
2850
|
-
await
|
|
2851
|
-
console.log(
|
|
2794
|
+
await fs11.rename(legacyPath, `${legacyPath}.bak`);
|
|
2795
|
+
console.log(chalk12.dim(" Moved legacy .cursorrules to .cursorrules.bak"));
|
|
2852
2796
|
}
|
|
2853
2797
|
} catch (e) {
|
|
2854
2798
|
}
|
|
2855
2799
|
}
|
|
2856
|
-
spinner.succeed(
|
|
2800
|
+
spinner.succeed(chalk12.green(`\u2714 Generated ${files.length} rule files (v${response.data.version || "3.0"})`));
|
|
2857
2801
|
} else {
|
|
2858
|
-
spinner.info(
|
|
2802
|
+
spinner.info(chalk12.dim(" Rules generation skipped (API response invalid)"));
|
|
2859
2803
|
}
|
|
2860
2804
|
} catch (e) {
|
|
2861
|
-
spinner.info(
|
|
2805
|
+
spinner.info(chalk12.dim(` Rules generation failed: ${e.message}`));
|
|
2862
2806
|
}
|
|
2863
2807
|
}
|
|
2864
2808
|
|
|
2865
2809
|
// src/commands/check.ts
|
|
2866
2810
|
init_esm_shims();
|
|
2867
2811
|
init_config();
|
|
2868
|
-
import { Command as
|
|
2869
|
-
import
|
|
2812
|
+
import { Command as Command9 } from "commander";
|
|
2813
|
+
import chalk14 from "chalk";
|
|
2870
2814
|
import ora7 from "ora";
|
|
2871
2815
|
import axios10 from "axios";
|
|
2872
2816
|
import { glob as glob3 } from "glob";
|
|
2873
|
-
import
|
|
2874
|
-
import
|
|
2817
|
+
import fs13 from "fs/promises";
|
|
2818
|
+
import path14 from "path";
|
|
2875
2819
|
import { execSync as execSync2 } from "child_process";
|
|
2876
2820
|
|
|
2877
2821
|
// src/utils/rule-engine.ts
|
|
2878
2822
|
init_esm_shims();
|
|
2879
|
-
import
|
|
2880
|
-
import
|
|
2881
|
-
import
|
|
2823
|
+
import fs12 from "fs/promises";
|
|
2824
|
+
import path13 from "path";
|
|
2825
|
+
import chalk13 from "chalk";
|
|
2882
2826
|
async function checkFile(filePath, rules, rootPath) {
|
|
2883
2827
|
const violations = [];
|
|
2884
|
-
const relativePath =
|
|
2828
|
+
const relativePath = path13.relative(rootPath, filePath);
|
|
2885
2829
|
try {
|
|
2886
|
-
const content = await
|
|
2830
|
+
const content = await fs12.readFile(filePath, "utf-8");
|
|
2887
2831
|
const lines = content.split("\n");
|
|
2888
2832
|
for (const rule of rules) {
|
|
2889
2833
|
const ruleViolations = await evaluateRule(rule, content, lines, relativePath);
|
|
@@ -2974,7 +2918,7 @@ async function evaluateRule(rule, content, lines, filePath) {
|
|
|
2974
2918
|
case "NAMING_CONVENTION": {
|
|
2975
2919
|
const value = rule.value;
|
|
2976
2920
|
const pattern = new RegExp(value.pattern);
|
|
2977
|
-
const fileName =
|
|
2921
|
+
const fileName = path13.basename(filePath);
|
|
2978
2922
|
if (filePath.includes(value.context) && !pattern.test(fileName)) {
|
|
2979
2923
|
violations.push({
|
|
2980
2924
|
file: filePath,
|
|
@@ -3033,12 +2977,12 @@ function checkFunctionLines(content, lines, filePath, rule, limit) {
|
|
|
3033
2977
|
}
|
|
3034
2978
|
function formatViolations(violations) {
|
|
3035
2979
|
for (const v of violations) {
|
|
3036
|
-
const severityColor = v.severity === "critical" ?
|
|
3037
|
-
const lineInfo = v.line ?
|
|
2980
|
+
const severityColor = v.severity === "critical" ? chalk13.red : v.severity === "warning" ? chalk13.yellow : chalk13.blue;
|
|
2981
|
+
const lineInfo = v.line ? chalk13.dim(`:${v.line}`) : "";
|
|
3038
2982
|
console.log(` ${severityColor(`[${v.severity.toUpperCase()}]`)} ${v.file}${lineInfo}`);
|
|
3039
2983
|
console.log(` ${v.message}`);
|
|
3040
2984
|
if (v.details) {
|
|
3041
|
-
console.log(` ${
|
|
2985
|
+
console.log(` ${chalk13.dim(v.details)}`);
|
|
3042
2986
|
}
|
|
3043
2987
|
}
|
|
3044
2988
|
}
|
|
@@ -3067,7 +3011,7 @@ var CACHE_FILE2 = ".rigstate/rules-cache.json";
|
|
|
3067
3011
|
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
3068
3012
|
var CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
3069
3013
|
function createCheckCommand() {
|
|
3070
|
-
return new
|
|
3014
|
+
return new Command9("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) => {
|
|
3071
3015
|
const spinner = ora7();
|
|
3072
3016
|
try {
|
|
3073
3017
|
let projectId = options.project;
|
|
@@ -3083,15 +3027,15 @@ function createCheckCommand() {
|
|
|
3083
3027
|
projectId = getProjectId();
|
|
3084
3028
|
}
|
|
3085
3029
|
if (!projectId) {
|
|
3086
|
-
console.log(
|
|
3087
|
-
console.log(
|
|
3030
|
+
console.log(chalk14.red("\u274C No project context found."));
|
|
3031
|
+
console.log(chalk14.dim(' Run "rigstate link" or pass --project <id>'));
|
|
3088
3032
|
process.exit(2);
|
|
3089
3033
|
}
|
|
3090
3034
|
let apiKey;
|
|
3091
3035
|
try {
|
|
3092
3036
|
apiKey = getApiKey();
|
|
3093
3037
|
} catch {
|
|
3094
|
-
console.log(
|
|
3038
|
+
console.log(chalk14.red('\u274C Not authenticated. Run "rigstate login" first.'));
|
|
3095
3039
|
process.exit(2);
|
|
3096
3040
|
}
|
|
3097
3041
|
spinner.start("Fetching Guardian rules...");
|
|
@@ -3119,17 +3063,17 @@ function createCheckCommand() {
|
|
|
3119
3063
|
} catch (apiError) {
|
|
3120
3064
|
const cached = await loadCachedRules(projectId);
|
|
3121
3065
|
if (cached && !isStale(cached.timestamp, CACHE_MAX_AGE_MS)) {
|
|
3122
|
-
spinner.warn(
|
|
3066
|
+
spinner.warn(chalk14.yellow("Using cached rules (API unavailable)"));
|
|
3123
3067
|
rules = cached.rules;
|
|
3124
3068
|
settings = cached.settings;
|
|
3125
3069
|
} else {
|
|
3126
|
-
spinner.fail(
|
|
3127
|
-
console.log(
|
|
3070
|
+
spinner.fail(chalk14.red("Failed to fetch rules and no valid cache"));
|
|
3071
|
+
console.log(chalk14.dim(` Error: ${apiError.message}`));
|
|
3128
3072
|
process.exit(2);
|
|
3129
3073
|
}
|
|
3130
3074
|
}
|
|
3131
3075
|
spinner.succeed(`Loaded ${rules.length} Guardian rules`);
|
|
3132
|
-
const scanPath =
|
|
3076
|
+
const scanPath = path14.resolve(process.cwd(), targetPath);
|
|
3133
3077
|
let filesToCheck;
|
|
3134
3078
|
if (options.staged) {
|
|
3135
3079
|
spinner.start("Getting staged files...");
|
|
@@ -3138,14 +3082,14 @@ function createCheckCommand() {
|
|
|
3138
3082
|
encoding: "utf-8",
|
|
3139
3083
|
cwd: process.cwd()
|
|
3140
3084
|
});
|
|
3141
|
-
filesToCheck = stagedOutput.split("\n").filter((f) => f.trim()).filter((f) => isCodeFile2(f)).map((f) =>
|
|
3085
|
+
filesToCheck = stagedOutput.split("\n").filter((f) => f.trim()).filter((f) => isCodeFile2(f)).map((f) => path14.resolve(process.cwd(), f));
|
|
3142
3086
|
} catch {
|
|
3143
3087
|
spinner.fail("Not a git repository or no staged files");
|
|
3144
3088
|
process.exit(2);
|
|
3145
3089
|
}
|
|
3146
3090
|
} else {
|
|
3147
|
-
spinner.start(`Scanning ${
|
|
3148
|
-
const pattern =
|
|
3091
|
+
spinner.start(`Scanning ${chalk14.cyan(targetPath)}...`);
|
|
3092
|
+
const pattern = path14.join(scanPath, "**/*");
|
|
3149
3093
|
const allFiles = await glob3(pattern, {
|
|
3150
3094
|
nodir: true,
|
|
3151
3095
|
dot: false,
|
|
@@ -3161,7 +3105,7 @@ function createCheckCommand() {
|
|
|
3161
3105
|
filesToCheck = allFiles.filter((f) => isCodeFile2(f));
|
|
3162
3106
|
}
|
|
3163
3107
|
if (filesToCheck.length === 0) {
|
|
3164
|
-
spinner.warn(
|
|
3108
|
+
spinner.warn(chalk14.yellow("No code files found to check."));
|
|
3165
3109
|
outputResults([], !!options.json);
|
|
3166
3110
|
process.exit(0);
|
|
3167
3111
|
}
|
|
@@ -3170,7 +3114,7 @@ function createCheckCommand() {
|
|
|
3170
3114
|
const results = [];
|
|
3171
3115
|
for (let i = 0; i < filesToCheck.length; i++) {
|
|
3172
3116
|
const file = filesToCheck[i];
|
|
3173
|
-
spinner.text = `Checking ${i + 1}/${filesToCheck.length}: ${
|
|
3117
|
+
spinner.text = `Checking ${i + 1}/${filesToCheck.length}: ${path14.basename(file)}`;
|
|
3174
3118
|
const result = await checkFile(file, rules, process.cwd());
|
|
3175
3119
|
results.push(result);
|
|
3176
3120
|
}
|
|
@@ -3180,47 +3124,47 @@ function createCheckCommand() {
|
|
|
3180
3124
|
outputResults(results, true);
|
|
3181
3125
|
} else {
|
|
3182
3126
|
outputResults(results, false);
|
|
3183
|
-
console.log("\n" +
|
|
3184
|
-
console.log(
|
|
3185
|
-
console.log(`Files checked: ${
|
|
3186
|
-
console.log(`Total violations: ${summary.totalViolations > 0 ?
|
|
3127
|
+
console.log("\n" + chalk14.bold("\u{1F4CA} Summary"));
|
|
3128
|
+
console.log(chalk14.dim("\u2500".repeat(50)));
|
|
3129
|
+
console.log(`Files checked: ${chalk14.cyan(summary.totalFiles)}`);
|
|
3130
|
+
console.log(`Total violations: ${summary.totalViolations > 0 ? chalk14.red(summary.totalViolations) : chalk14.green(0)}`);
|
|
3187
3131
|
if (summary.totalViolations > 0) {
|
|
3188
|
-
console.log(` ${
|
|
3189
|
-
console.log(` ${
|
|
3190
|
-
console.log(` ${
|
|
3132
|
+
console.log(` ${chalk14.red("Critical:")} ${summary.criticalCount}`);
|
|
3133
|
+
console.log(` ${chalk14.yellow("Warning:")} ${summary.warningCount}`);
|
|
3134
|
+
console.log(` ${chalk14.blue("Info:")} ${summary.infoCount}`);
|
|
3191
3135
|
}
|
|
3192
|
-
console.log(
|
|
3136
|
+
console.log(chalk14.dim("\u2500".repeat(50)));
|
|
3193
3137
|
}
|
|
3194
3138
|
if (options.strict !== void 0) {
|
|
3195
3139
|
const strictLevel = typeof options.strict === "string" ? options.strict : "all";
|
|
3196
3140
|
if (strictLevel === "critical" && summary.criticalCount > 0) {
|
|
3197
|
-
console.log(
|
|
3141
|
+
console.log(chalk14.red("\n\u274C Check failed: Critical violations found"));
|
|
3198
3142
|
process.exit(1);
|
|
3199
3143
|
} else if (strictLevel === "all" && summary.totalViolations > 0) {
|
|
3200
|
-
console.log(
|
|
3144
|
+
console.log(chalk14.red("\n\u274C Check failed: Violations found"));
|
|
3201
3145
|
process.exit(1);
|
|
3202
3146
|
}
|
|
3203
3147
|
}
|
|
3204
3148
|
if (summary.totalViolations === 0) {
|
|
3205
|
-
console.log(
|
|
3149
|
+
console.log(chalk14.green("\n\u2705 All checks passed!"));
|
|
3206
3150
|
}
|
|
3207
3151
|
process.exit(0);
|
|
3208
3152
|
} catch (error) {
|
|
3209
|
-
spinner.fail(
|
|
3210
|
-
console.error(
|
|
3153
|
+
spinner.fail(chalk14.red("Check failed"));
|
|
3154
|
+
console.error(chalk14.red("Error:"), error.message);
|
|
3211
3155
|
process.exit(2);
|
|
3212
3156
|
}
|
|
3213
3157
|
});
|
|
3214
3158
|
}
|
|
3215
3159
|
function isCodeFile2(filePath) {
|
|
3216
3160
|
const codeExtensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3217
|
-
const ext =
|
|
3161
|
+
const ext = path14.extname(filePath).toLowerCase();
|
|
3218
3162
|
return codeExtensions.includes(ext);
|
|
3219
3163
|
}
|
|
3220
3164
|
async function loadCachedRules(projectId) {
|
|
3221
3165
|
try {
|
|
3222
|
-
const cachePath =
|
|
3223
|
-
const content = await
|
|
3166
|
+
const cachePath = path14.join(process.cwd(), CACHE_FILE2);
|
|
3167
|
+
const content = await fs13.readFile(cachePath, "utf-8");
|
|
3224
3168
|
const cached = JSON.parse(content);
|
|
3225
3169
|
if (cached.projectId !== projectId) {
|
|
3226
3170
|
return null;
|
|
@@ -3232,16 +3176,16 @@ async function loadCachedRules(projectId) {
|
|
|
3232
3176
|
}
|
|
3233
3177
|
async function saveCachedRules(projectId, rules, settings) {
|
|
3234
3178
|
try {
|
|
3235
|
-
const cacheDir =
|
|
3236
|
-
await
|
|
3179
|
+
const cacheDir = path14.join(process.cwd(), ".rigstate");
|
|
3180
|
+
await fs13.mkdir(cacheDir, { recursive: true });
|
|
3237
3181
|
const cached = {
|
|
3238
3182
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3239
3183
|
projectId,
|
|
3240
3184
|
rules,
|
|
3241
3185
|
settings
|
|
3242
3186
|
};
|
|
3243
|
-
await
|
|
3244
|
-
|
|
3187
|
+
await fs13.writeFile(
|
|
3188
|
+
path14.join(cacheDir, "rules-cache.json"),
|
|
3245
3189
|
JSON.stringify(cached, null, 2)
|
|
3246
3190
|
);
|
|
3247
3191
|
} catch {
|
|
@@ -3263,8 +3207,8 @@ function outputResults(results, json) {
|
|
|
3263
3207
|
if (!hasViolations) {
|
|
3264
3208
|
return;
|
|
3265
3209
|
}
|
|
3266
|
-
console.log("\n" +
|
|
3267
|
-
console.log(
|
|
3210
|
+
console.log("\n" + chalk14.bold("\u{1F50D} Violations Found"));
|
|
3211
|
+
console.log(chalk14.dim("\u2500".repeat(50)));
|
|
3268
3212
|
for (const result of results) {
|
|
3269
3213
|
if (result.violations.length > 0) {
|
|
3270
3214
|
formatViolations(result.violations);
|
|
@@ -3272,8 +3216,125 @@ function outputResults(results, json) {
|
|
|
3272
3216
|
}
|
|
3273
3217
|
}
|
|
3274
3218
|
|
|
3275
|
-
// src/
|
|
3276
|
-
|
|
3219
|
+
// src/commands/hooks.ts
|
|
3220
|
+
init_esm_shims();
|
|
3221
|
+
import { Command as Command10 } from "commander";
|
|
3222
|
+
import chalk15 from "chalk";
|
|
3223
|
+
import fs14 from "fs/promises";
|
|
3224
|
+
import path15 from "path";
|
|
3225
|
+
var PRE_COMMIT_SCRIPT = `#!/bin/sh
|
|
3226
|
+
# Rigstate Guardian Pre-commit Hook
|
|
3227
|
+
# Installed by: rigstate hooks install
|
|
3228
|
+
|
|
3229
|
+
# 1. Silent Sentinel Check (Phase 5)
|
|
3230
|
+
if [ -f .rigstate/guardian.lock ]; then
|
|
3231
|
+
echo "\u{1F6D1} INTERVENTION ACTIVE: Commit blocked by Silent Sentinel."
|
|
3232
|
+
echo " A critical violation ('HARD_LOCK') was detected by the Guardian Daemon."
|
|
3233
|
+
echo " Please fix the violation to unlock the repo."
|
|
3234
|
+
echo ""
|
|
3235
|
+
if grep -q "HARD_LOCK_ACTIVE" .rigstate/guardian.lock; then
|
|
3236
|
+
cat .rigstate/guardian.lock
|
|
3237
|
+
fi
|
|
3238
|
+
exit 1
|
|
3239
|
+
fi
|
|
3240
|
+
|
|
3241
|
+
echo "\u{1F6E1}\uFE0F Running Guardian checks..."
|
|
3242
|
+
|
|
3243
|
+
# Run check with strict mode for critical violations
|
|
3244
|
+
rigstate check --staged --strict=critical
|
|
3245
|
+
|
|
3246
|
+
# Exit with the same code as rigstate check
|
|
3247
|
+
exit $?
|
|
3248
|
+
`;
|
|
3249
|
+
function createHooksCommand() {
|
|
3250
|
+
const hooks = new Command10("hooks").description("Manage git hooks for Guardian integration");
|
|
3251
|
+
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) => {
|
|
3252
|
+
try {
|
|
3253
|
+
const gitDir = path15.join(process.cwd(), ".git");
|
|
3254
|
+
try {
|
|
3255
|
+
await fs14.access(gitDir);
|
|
3256
|
+
} catch {
|
|
3257
|
+
console.log(chalk15.red("\u274C Not a git repository."));
|
|
3258
|
+
console.log(chalk15.dim(' Initialize with "git init" first.'));
|
|
3259
|
+
process.exit(1);
|
|
3260
|
+
}
|
|
3261
|
+
const hooksDir = path15.join(gitDir, "hooks");
|
|
3262
|
+
await fs14.mkdir(hooksDir, { recursive: true });
|
|
3263
|
+
const preCommitPath = path15.join(hooksDir, "pre-commit");
|
|
3264
|
+
let existingContent = "";
|
|
3265
|
+
try {
|
|
3266
|
+
existingContent = await fs14.readFile(preCommitPath, "utf-8");
|
|
3267
|
+
if (existingContent.includes("rigstate")) {
|
|
3268
|
+
console.log(chalk15.yellow("\u26A0 Rigstate pre-commit hook already installed."));
|
|
3269
|
+
console.log(chalk15.dim(' Use "rigstate hooks uninstall" to remove first.'));
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
} catch {
|
|
3273
|
+
}
|
|
3274
|
+
let script = PRE_COMMIT_SCRIPT;
|
|
3275
|
+
if (options.strict === "all") {
|
|
3276
|
+
script = script.replace("--strict=critical", "--strict");
|
|
3277
|
+
}
|
|
3278
|
+
if (existingContent && !existingContent.includes("rigstate")) {
|
|
3279
|
+
const combinedScript = existingContent + "\n\n" + script.replace("#!/bin/sh\n", "");
|
|
3280
|
+
await fs14.writeFile(preCommitPath, combinedScript, { mode: 493 });
|
|
3281
|
+
console.log(chalk15.green("\u2705 Rigstate hook appended to existing pre-commit."));
|
|
3282
|
+
} else {
|
|
3283
|
+
await fs14.writeFile(preCommitPath, script, { mode: 493 });
|
|
3284
|
+
console.log(chalk15.green("\u2705 Pre-commit hook installed!"));
|
|
3285
|
+
}
|
|
3286
|
+
console.log(chalk15.dim(` Path: ${preCommitPath}`));
|
|
3287
|
+
console.log(chalk15.dim(` Strict level: ${options.strict}`));
|
|
3288
|
+
console.log("");
|
|
3289
|
+
console.log(chalk15.cyan("Guardian will now check your code before each commit."));
|
|
3290
|
+
console.log(chalk15.dim('Use "rigstate hooks uninstall" to remove the hook.'));
|
|
3291
|
+
} catch (error) {
|
|
3292
|
+
console.error(chalk15.red("Failed to install hook:"), error.message);
|
|
3293
|
+
process.exit(1);
|
|
3294
|
+
}
|
|
3295
|
+
});
|
|
3296
|
+
hooks.command("uninstall").description("Remove Rigstate pre-commit hook").action(async () => {
|
|
3297
|
+
try {
|
|
3298
|
+
const preCommitPath = path15.join(process.cwd(), ".git", "hooks", "pre-commit");
|
|
3299
|
+
try {
|
|
3300
|
+
const content = await fs14.readFile(preCommitPath, "utf-8");
|
|
3301
|
+
if (!content.includes("rigstate")) {
|
|
3302
|
+
console.log(chalk15.yellow("\u26A0 No Rigstate hook found in pre-commit."));
|
|
3303
|
+
return;
|
|
3304
|
+
}
|
|
3305
|
+
if (content.includes("# Rigstate Guardian Pre-commit Hook") && content.trim().split("\n").filter((l) => l && !l.startsWith("#")).length <= 4) {
|
|
3306
|
+
await fs14.unlink(preCommitPath);
|
|
3307
|
+
console.log(chalk15.green("\u2705 Pre-commit hook removed."));
|
|
3308
|
+
} else {
|
|
3309
|
+
const lines = content.split("\n");
|
|
3310
|
+
const filteredLines = [];
|
|
3311
|
+
let inRigstateSection = false;
|
|
3312
|
+
for (const line of lines) {
|
|
3313
|
+
if (line.includes("Rigstate Guardian Pre-commit Hook")) {
|
|
3314
|
+
inRigstateSection = true;
|
|
3315
|
+
continue;
|
|
3316
|
+
}
|
|
3317
|
+
if (inRigstateSection && line.includes("exit $?")) {
|
|
3318
|
+
inRigstateSection = false;
|
|
3319
|
+
continue;
|
|
3320
|
+
}
|
|
3321
|
+
if (!inRigstateSection && !line.includes("rigstate check")) {
|
|
3322
|
+
filteredLines.push(line);
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
await fs14.writeFile(preCommitPath, filteredLines.join("\n"), { mode: 493 });
|
|
3326
|
+
console.log(chalk15.green("\u2705 Rigstate section removed from pre-commit hook."));
|
|
3327
|
+
}
|
|
3328
|
+
} catch {
|
|
3329
|
+
console.log(chalk15.yellow("\u26A0 No pre-commit hook found."));
|
|
3330
|
+
}
|
|
3331
|
+
} catch (error) {
|
|
3332
|
+
console.error(chalk15.red("Failed to uninstall hook:"), error.message);
|
|
3333
|
+
process.exit(1);
|
|
3334
|
+
}
|
|
3335
|
+
});
|
|
3336
|
+
return hooks;
|
|
3337
|
+
}
|
|
3277
3338
|
|
|
3278
3339
|
// src/commands/daemon.ts
|
|
3279
3340
|
init_esm_shims();
|
|
@@ -3981,7 +4042,7 @@ var GuardianDaemon = class extends EventEmitter3 {
|
|
|
3981
4042
|
setupFileWatcher() {
|
|
3982
4043
|
Logger.info("Starting file watcher...");
|
|
3983
4044
|
this.fileWatcher = createFileWatcher(this.config.watchPath);
|
|
3984
|
-
this.fileWatcher.on("change", (
|
|
4045
|
+
this.fileWatcher.on("change", (path28) => this.handleFileChange(path28));
|
|
3985
4046
|
this.fileWatcher.start();
|
|
3986
4047
|
Logger.info("File watcher active");
|
|
3987
4048
|
}
|
|
@@ -4015,6 +4076,7 @@ var GuardianDaemon = class extends EventEmitter3 {
|
|
|
4015
4076
|
this.emit("skill:suggestion", match);
|
|
4016
4077
|
}
|
|
4017
4078
|
}
|
|
4079
|
+
violationsMap = /* @__PURE__ */ new Map();
|
|
4018
4080
|
async runIntegrityCheck(filePath) {
|
|
4019
4081
|
if (!this.guardianMonitor) return;
|
|
4020
4082
|
if (this.interventionProtocol) this.interventionProtocol.clear(filePath);
|
|
@@ -4023,24 +4085,37 @@ var GuardianDaemon = class extends EventEmitter3 {
|
|
|
4023
4085
|
if (result.violations.length > 0) {
|
|
4024
4086
|
this.handleViolations(filePath, result.violations);
|
|
4025
4087
|
} else {
|
|
4026
|
-
|
|
4088
|
+
if (this.violationsMap.has(filePath)) {
|
|
4089
|
+
this.violationsMap.delete(filePath);
|
|
4090
|
+
this.updateViolationReport();
|
|
4091
|
+
}
|
|
4027
4092
|
}
|
|
4028
4093
|
}
|
|
4029
4094
|
async updateViolationReport(violations) {
|
|
4030
4095
|
const reportPath = path20.join(process.cwd(), ".rigstate", "ACTIVE_VIOLATIONS.md");
|
|
4031
|
-
|
|
4096
|
+
const allViolations = Array.from(this.violationsMap.entries());
|
|
4097
|
+
const totalCount = allViolations.reduce((acc, [, v]) => acc + v.length, 0);
|
|
4098
|
+
let content = `# \u{1F6E1}\uFE0F Guardian Status: ${totalCount > 0 ? "\u26A0\uFE0F ATTENTION" : "\u2705 PASS"}
|
|
4032
4099
|
|
|
4033
4100
|
`;
|
|
4034
4101
|
content += `*Last check: ${(/* @__PURE__ */ new Date()).toLocaleString()}*
|
|
4102
|
+
`;
|
|
4103
|
+
content += `*Files with issues: ${allViolations.length}*
|
|
4035
4104
|
|
|
4036
4105
|
`;
|
|
4037
|
-
if (
|
|
4106
|
+
if (totalCount === 0) {
|
|
4038
4107
|
content += "All systems within architectural limits. Frank is satisfied. \u{1F92B}\n";
|
|
4039
4108
|
} else {
|
|
4040
4109
|
content += "### \u{1F6A8} Active Violations\n\n";
|
|
4041
|
-
for (const
|
|
4042
|
-
|
|
4110
|
+
for (const [file, fileViolations] of allViolations) {
|
|
4111
|
+
const relPath = path20.relative(process.cwd(), file);
|
|
4112
|
+
content += `#### \u{1F4C4} ${relPath}
|
|
4113
|
+
`;
|
|
4114
|
+
for (const v of fileViolations) {
|
|
4115
|
+
content += `- **[${v.severity.toUpperCase()}]**: ${v.message}
|
|
4043
4116
|
`;
|
|
4117
|
+
}
|
|
4118
|
+
content += "\n";
|
|
4044
4119
|
}
|
|
4045
4120
|
content += "\n---\n*Rigstate Daemon is watching. Fix violations to clear this report.*";
|
|
4046
4121
|
}
|
|
@@ -4052,7 +4127,8 @@ var GuardianDaemon = class extends EventEmitter3 {
|
|
|
4052
4127
|
handleViolations(filePath, violations) {
|
|
4053
4128
|
this.state.violationsFound += violations.length;
|
|
4054
4129
|
this.emit("violation", { file: filePath, violations });
|
|
4055
|
-
this.
|
|
4130
|
+
this.violationsMap.set(filePath, violations);
|
|
4131
|
+
this.updateViolationReport();
|
|
4056
4132
|
for (const v of violations) {
|
|
4057
4133
|
const level = v.severity === "critical" ? "error" : v.severity === "warning" ? "warn" : "info";
|
|
4058
4134
|
Logger[level](`[${v.severity.toUpperCase()}] ${filePath}: ${v.message}`);
|
|
@@ -4365,13 +4441,147 @@ async function showStatus() {
|
|
|
4365
4441
|
init_esm_shims();
|
|
4366
4442
|
init_config();
|
|
4367
4443
|
init_suggest();
|
|
4444
|
+
import { Command as Command13 } from "commander";
|
|
4445
|
+
import chalk23 from "chalk";
|
|
4446
|
+
import ora10 from "ora";
|
|
4447
|
+
import axios16 from "axios";
|
|
4448
|
+
import inquirer3 from "inquirer";
|
|
4449
|
+
|
|
4450
|
+
// src/commands/plan.ts
|
|
4451
|
+
init_esm_shims();
|
|
4452
|
+
init_config();
|
|
4368
4453
|
import { Command as Command12 } from "commander";
|
|
4369
4454
|
import chalk22 from "chalk";
|
|
4370
4455
|
import ora9 from "ora";
|
|
4371
4456
|
import axios15 from "axios";
|
|
4457
|
+
import fs20 from "fs/promises";
|
|
4458
|
+
import path23 from "path";
|
|
4372
4459
|
import inquirer2 from "inquirer";
|
|
4460
|
+
function createPlanCommand() {
|
|
4461
|
+
const plan = new Command12("plan");
|
|
4462
|
+
plan.description("Generate an implementation plan for a roadmap task").argument("[taskId]", "Task ID (e.g. T-10) or UUID").action(async (taskId) => {
|
|
4463
|
+
await executePlan(taskId);
|
|
4464
|
+
});
|
|
4465
|
+
return plan;
|
|
4466
|
+
}
|
|
4467
|
+
async function executePlan(taskId) {
|
|
4468
|
+
const spinner = ora9("Initializing Planning Mode...").start();
|
|
4469
|
+
try {
|
|
4470
|
+
const { projectId, apiKey, apiUrl } = getContext();
|
|
4471
|
+
let realId = taskId;
|
|
4472
|
+
let taskTitle = "";
|
|
4473
|
+
let taskDescription = "";
|
|
4474
|
+
if (!taskId) {
|
|
4475
|
+
spinner.text = "Fetching actionable tasks...";
|
|
4476
|
+
const response = await axios15.get(
|
|
4477
|
+
`${apiUrl}/api/v1/roadmap?project_id=${projectId}`,
|
|
4478
|
+
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
4479
|
+
);
|
|
4480
|
+
if (!response.data.success) throw new Error("Failed to fetch roadmap");
|
|
4481
|
+
const tasks = response.data.data.roadmap || [];
|
|
4482
|
+
const choices = tasks.filter((t) => ["ACTIVE", "IN_PROGRESS", "PENDING"].includes(t.status)).map((t) => ({
|
|
4483
|
+
name: `T-${t.step_number}: ${t.title}`,
|
|
4484
|
+
value: t
|
|
4485
|
+
}));
|
|
4486
|
+
if (choices.length === 0) {
|
|
4487
|
+
spinner.fail("No actionable tasks found in roadmap.");
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
spinner.stop();
|
|
4491
|
+
const answer = await inquirer2.prompt([{
|
|
4492
|
+
type: "list",
|
|
4493
|
+
name: "task",
|
|
4494
|
+
message: "Select a task to plan:",
|
|
4495
|
+
choices
|
|
4496
|
+
}]);
|
|
4497
|
+
realId = answer.task.id;
|
|
4498
|
+
taskTitle = answer.task.title;
|
|
4499
|
+
taskDescription = answer.task.description;
|
|
4500
|
+
taskId = `T-${answer.task.step_number}`;
|
|
4501
|
+
} else {
|
|
4502
|
+
spinner.text = `Fetching details for ${taskId}...`;
|
|
4503
|
+
const response = await axios15.get(
|
|
4504
|
+
`${apiUrl}/api/v1/roadmap?project_id=${projectId}`,
|
|
4505
|
+
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
4506
|
+
);
|
|
4507
|
+
const task = response.data.data.roadmap.find(
|
|
4508
|
+
(t) => t.id === taskId || `T-${t.step_number}` === taskId || t.step_number.toString() === taskId
|
|
4509
|
+
);
|
|
4510
|
+
if (!task) throw new Error(`Task ${taskId} not found.`);
|
|
4511
|
+
realId = task.id;
|
|
4512
|
+
taskTitle = task.title;
|
|
4513
|
+
taskDescription = task.description;
|
|
4514
|
+
}
|
|
4515
|
+
spinner.start("Generating Context for Frank...");
|
|
4516
|
+
const contextPath = path23.join(process.cwd(), ".rigstate", "CURRENT_CONTEXT.md");
|
|
4517
|
+
const contextContent = `
|
|
4518
|
+
# \u{1F3AF} Active Mission: ${taskTitle}
|
|
4519
|
+
**ID:** ${taskId}
|
|
4520
|
+
|
|
4521
|
+
## \u{1F4DD} Description
|
|
4522
|
+
${taskDescription}
|
|
4523
|
+
|
|
4524
|
+
## \u{1F6E1}\uFE0F Architectural Constraints
|
|
4525
|
+
- Follow strictly the rules in .cursor/rules/
|
|
4526
|
+
- Ensure zero violations in ACTIVE_VIOLATIONS.md
|
|
4527
|
+
- Update IMPLEMENTATION_PLAN.md before writing code.
|
|
4528
|
+
|
|
4529
|
+
*Generated by Rigstate CLI at ${(/* @__PURE__ */ new Date()).toLocaleString()}*
|
|
4530
|
+
`;
|
|
4531
|
+
await fs20.mkdir(path23.dirname(contextPath), { recursive: true });
|
|
4532
|
+
await fs20.writeFile(contextPath, contextContent.trim());
|
|
4533
|
+
const planPath = path23.join(process.cwd(), "IMPLEMENTATION_PLAN.md");
|
|
4534
|
+
const planExists = await fs20.stat(planPath).then(() => true).catch(() => false);
|
|
4535
|
+
if (!planExists) {
|
|
4536
|
+
const planTemplate = `
|
|
4537
|
+
# \u{1F4CB} Implementation Plan: ${taskTitle}
|
|
4538
|
+
|
|
4539
|
+
## 1. \u{1F50D} Analysis
|
|
4540
|
+
- [ ] Understand the requirements in .rigstate/CURRENT_CONTEXT.md
|
|
4541
|
+
- [ ] Check for existing architectural patterns
|
|
4542
|
+
|
|
4543
|
+
## 2. \u{1F3D7}\uFE0F Proposed Changes
|
|
4544
|
+
[Frank: List the files you intend to modify and the nature of the changes]
|
|
4545
|
+
|
|
4546
|
+
## 3. \u2705 Verification
|
|
4547
|
+
- [ ] Run tests
|
|
4548
|
+
- [ ] Verification Step 1...
|
|
4549
|
+
|
|
4550
|
+
## 4. \u{1F680} Execution
|
|
4551
|
+
[Frank: Log your progress here]
|
|
4552
|
+
`;
|
|
4553
|
+
await fs20.writeFile(planPath, planTemplate.trim());
|
|
4554
|
+
spinner.succeed(chalk22.green("Created new IMPLEMENTATION_PLAN.md"));
|
|
4555
|
+
} else {
|
|
4556
|
+
spinner.info(chalk22.yellow("IMPLEMENTATION_PLAN.md already exists. Preserving it."));
|
|
4557
|
+
}
|
|
4558
|
+
console.log("");
|
|
4559
|
+
console.log(chalk22.bold.blue("\u{1F680} Planning Mode Activated"));
|
|
4560
|
+
console.log(chalk22.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4561
|
+
console.log(`1. Context loaded into: ${chalk22.bold(".rigstate/CURRENT_CONTEXT.md")}`);
|
|
4562
|
+
console.log(`2. Plan template ready: ${chalk22.bold("IMPLEMENTATION_PLAN.md")}`);
|
|
4563
|
+
console.log("");
|
|
4564
|
+
console.log(chalk22.yellow("\u{1F449} NEXT STEP:"));
|
|
4565
|
+
console.log(` Open ${chalk22.bold("IMPLEMENTATION_PLAN.md")} in your IDE.`);
|
|
4566
|
+
console.log(` Tell Frank: ${chalk22.italic('"Read the context and draft the plan."')}`);
|
|
4567
|
+
console.log("");
|
|
4568
|
+
} catch (e) {
|
|
4569
|
+
spinner.fail(chalk22.red(`Planning failed: ${e.message}`));
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
function getContext() {
|
|
4573
|
+
const apiKey = getApiKey();
|
|
4574
|
+
const apiUrl = getApiUrl();
|
|
4575
|
+
const projectId = getProjectId();
|
|
4576
|
+
if (!projectId) {
|
|
4577
|
+
throw new Error("Project ID missing. Run rigstate link.");
|
|
4578
|
+
}
|
|
4579
|
+
return { projectId, apiKey, apiUrl };
|
|
4580
|
+
}
|
|
4581
|
+
|
|
4582
|
+
// src/commands/work.ts
|
|
4373
4583
|
function createWorkCommand() {
|
|
4374
|
-
const work = new
|
|
4584
|
+
const work = new Command13("work");
|
|
4375
4585
|
work.description("Manage development flow (Start, Finish, List)").action(() => {
|
|
4376
4586
|
listInteractive();
|
|
4377
4587
|
});
|
|
@@ -4384,10 +4594,10 @@ function createWorkCommand() {
|
|
|
4384
4594
|
return work;
|
|
4385
4595
|
}
|
|
4386
4596
|
async function listInteractive() {
|
|
4387
|
-
const spinner =
|
|
4597
|
+
const spinner = ora10("Fetching roadmap...").start();
|
|
4388
4598
|
try {
|
|
4389
|
-
const { projectId, apiKey, apiUrl } =
|
|
4390
|
-
const response = await
|
|
4599
|
+
const { projectId, apiKey, apiUrl } = getContext2();
|
|
4600
|
+
const response = await axios16.get(
|
|
4391
4601
|
`${apiUrl}/api/v1/roadmap?project_id=${projectId}`,
|
|
4392
4602
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
4393
4603
|
);
|
|
@@ -4401,7 +4611,7 @@ async function listInteractive() {
|
|
|
4401
4611
|
});
|
|
4402
4612
|
spinner.stop();
|
|
4403
4613
|
if (actionableTasks.length === 0) {
|
|
4404
|
-
console.log(
|
|
4614
|
+
console.log(chalk23.yellow("Roadmap clear. No actionable tasks found."));
|
|
4405
4615
|
return;
|
|
4406
4616
|
}
|
|
4407
4617
|
const choices = actionableTasks.map((t) => {
|
|
@@ -4410,26 +4620,30 @@ async function listInteractive() {
|
|
|
4410
4620
|
if (t.status === "IN_PROGRESS") icon = "\u{1F525}";
|
|
4411
4621
|
if (t.status === "ACTIVE") icon = "\u25B6\uFE0F";
|
|
4412
4622
|
return {
|
|
4413
|
-
name: `${icon} ${
|
|
4623
|
+
name: `${icon} ${chalk23.bold(id)}: ${t.title} [${t.status}]`,
|
|
4414
4624
|
value: t.id
|
|
4415
4625
|
};
|
|
4416
4626
|
});
|
|
4417
|
-
const { taskId } = await
|
|
4627
|
+
const { taskId } = await inquirer3.prompt([{
|
|
4418
4628
|
type: "list",
|
|
4419
4629
|
name: "taskId",
|
|
4420
4630
|
message: "Select a task to manage:",
|
|
4421
4631
|
choices
|
|
4422
4632
|
}]);
|
|
4423
|
-
const { action } = await
|
|
4633
|
+
const { action } = await inquirer3.prompt([{
|
|
4424
4634
|
type: "list",
|
|
4425
4635
|
name: "action",
|
|
4426
4636
|
message: "Action:",
|
|
4427
4637
|
choices: [
|
|
4638
|
+
{ name: "Plan (Draft Blueprint - RECOMMENDED)", value: "plan" },
|
|
4428
4639
|
{ name: "Start (Set IN_PROGRESS)", value: "start" },
|
|
4429
4640
|
{ name: "Finish (Audit & Complete)", value: "finish" },
|
|
4430
4641
|
{ name: "Cancel", value: "cancel" }
|
|
4431
4642
|
]
|
|
4432
4643
|
}]);
|
|
4644
|
+
if (action === "plan") {
|
|
4645
|
+
await executePlan(taskId);
|
|
4646
|
+
}
|
|
4433
4647
|
if (action === "start") await setTaskStatus(taskId, "IN_PROGRESS");
|
|
4434
4648
|
if (action === "finish") await finishTask(taskId);
|
|
4435
4649
|
} catch (e) {
|
|
@@ -4437,45 +4651,45 @@ async function listInteractive() {
|
|
|
4437
4651
|
}
|
|
4438
4652
|
}
|
|
4439
4653
|
async function setTaskStatus(taskId, status) {
|
|
4440
|
-
const spinner =
|
|
4654
|
+
const spinner = ora10(`Setting task ${taskId} to ${status}...`).start();
|
|
4441
4655
|
try {
|
|
4442
|
-
const { projectId, apiKey, apiUrl } =
|
|
4656
|
+
const { projectId, apiKey, apiUrl } = getContext2();
|
|
4443
4657
|
let realId = taskId;
|
|
4444
4658
|
if (taskId.startsWith("T-") || taskId.length < 10) {
|
|
4445
4659
|
spinner.text = "Resolving Task ID...";
|
|
4446
|
-
const lookup = await
|
|
4660
|
+
const lookup = await axios16.get(`${apiUrl}/api/v1/roadmap?project_id=${projectId}`, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
4447
4661
|
const task = lookup.data.data.roadmap.find((t) => `T-${t.step_number}` === taskId || t.step_number.toString() === taskId);
|
|
4448
4662
|
if (!task) throw new Error(`Task ${taskId} not found.`);
|
|
4449
4663
|
realId = task.id;
|
|
4450
4664
|
}
|
|
4451
|
-
await
|
|
4665
|
+
await axios16.post(
|
|
4452
4666
|
`${apiUrl}/api/v1/roadmap/update-status`,
|
|
4453
4667
|
{ step_id: realId, status, project_id: projectId },
|
|
4454
4668
|
{ headers: { "Authorization": `Bearer ${apiKey}` } }
|
|
4455
4669
|
);
|
|
4456
|
-
spinner.succeed(
|
|
4670
|
+
spinner.succeed(chalk23.green(`Task updated to ${status}.`));
|
|
4457
4671
|
if (status === "IN_PROGRESS") {
|
|
4458
|
-
console.log(
|
|
4672
|
+
console.log(chalk23.blue(`
|
|
4459
4673
|
\u{1F4A1} Tip: Provide 'Frank' with context by mentioning @.cursorrules in your chat.`));
|
|
4460
4674
|
}
|
|
4461
4675
|
} catch (e) {
|
|
4462
|
-
spinner.fail(
|
|
4676
|
+
spinner.fail(chalk23.red(`Failed: ${e.message}`));
|
|
4463
4677
|
}
|
|
4464
4678
|
}
|
|
4465
4679
|
async function finishTask(taskId) {
|
|
4466
4680
|
console.log("");
|
|
4467
|
-
console.log(
|
|
4468
|
-
console.log(
|
|
4469
|
-
const auditSpinner =
|
|
4681
|
+
console.log(chalk23.bold.yellow("\u{1F6E1}\uFE0F FRANK'S QUALITY GATE"));
|
|
4682
|
+
console.log(chalk23.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4683
|
+
const auditSpinner = ora10(" Analyzing architectural integrity...").start();
|
|
4470
4684
|
await new Promise((r) => setTimeout(r, 1500));
|
|
4471
4685
|
auditSpinner.succeed("Architecture: VALIDATED (SEC-ARCH-01 Pass)");
|
|
4472
4686
|
await setTaskStatus(taskId, "COMPLETED");
|
|
4473
4687
|
console.log("");
|
|
4474
|
-
console.log(
|
|
4475
|
-
const { projectId, apiKey, apiUrl } =
|
|
4688
|
+
console.log(chalk23.bold.green("\u{1F389} TASK COMPLETE! Momentum Preserved."));
|
|
4689
|
+
const { projectId, apiKey, apiUrl } = getContext2();
|
|
4476
4690
|
await suggestNextMove(projectId, apiKey, apiUrl);
|
|
4477
4691
|
}
|
|
4478
|
-
function
|
|
4692
|
+
function getContext2() {
|
|
4479
4693
|
const apiKey = getApiKey();
|
|
4480
4694
|
const apiUrl = getApiUrl();
|
|
4481
4695
|
const projectId = getProjectId();
|
|
@@ -4488,40 +4702,40 @@ function getContext() {
|
|
|
4488
4702
|
// src/commands/watch.ts
|
|
4489
4703
|
init_esm_shims();
|
|
4490
4704
|
init_config();
|
|
4491
|
-
import { Command as
|
|
4492
|
-
import
|
|
4493
|
-
import
|
|
4705
|
+
import { Command as Command14 } from "commander";
|
|
4706
|
+
import chalk24 from "chalk";
|
|
4707
|
+
import ora11 from "ora";
|
|
4494
4708
|
import chokidar2 from "chokidar";
|
|
4495
|
-
import
|
|
4496
|
-
import
|
|
4709
|
+
import fs21 from "fs/promises";
|
|
4710
|
+
import path24 from "path";
|
|
4497
4711
|
import { execSync as execSync4 } from "child_process";
|
|
4498
|
-
import
|
|
4712
|
+
import axios17 from "axios";
|
|
4499
4713
|
function createWatchCommand() {
|
|
4500
|
-
const watch2 = new
|
|
4714
|
+
const watch2 = new Command14("watch");
|
|
4501
4715
|
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) => {
|
|
4502
|
-
console.log(
|
|
4503
|
-
console.log(
|
|
4716
|
+
console.log(chalk24.bold.blue("\u{1F52D} Rigstate Watch Mode"));
|
|
4717
|
+
console.log(chalk24.dim("Monitoring for task completion..."));
|
|
4504
4718
|
console.log("");
|
|
4505
4719
|
let apiKey;
|
|
4506
4720
|
let projectId;
|
|
4507
4721
|
try {
|
|
4508
4722
|
apiKey = getApiKey();
|
|
4509
4723
|
} catch (e) {
|
|
4510
|
-
console.log(
|
|
4724
|
+
console.log(chalk24.red('Not authenticated. Run "rigstate login" first.'));
|
|
4511
4725
|
return;
|
|
4512
4726
|
}
|
|
4513
4727
|
projectId = getProjectId();
|
|
4514
4728
|
if (!projectId) {
|
|
4515
4729
|
try {
|
|
4516
|
-
const manifestPath =
|
|
4517
|
-
const content = await
|
|
4730
|
+
const manifestPath = path24.join(process.cwd(), ".rigstate");
|
|
4731
|
+
const content = await fs21.readFile(manifestPath, "utf-8");
|
|
4518
4732
|
const manifest = JSON.parse(content);
|
|
4519
4733
|
projectId = manifest.project_id;
|
|
4520
4734
|
} catch (e) {
|
|
4521
4735
|
}
|
|
4522
4736
|
}
|
|
4523
4737
|
if (!projectId) {
|
|
4524
|
-
console.log(
|
|
4738
|
+
console.log(chalk24.red('No project context. Run "rigstate link" or "rigstate sync --project <id>" first.'));
|
|
4525
4739
|
return;
|
|
4526
4740
|
}
|
|
4527
4741
|
const apiUrl = getApiUrl();
|
|
@@ -4531,12 +4745,12 @@ function createWatchCommand() {
|
|
|
4531
4745
|
runTests: options.runTests || false,
|
|
4532
4746
|
testCommand: options.testCommand || "npm test"
|
|
4533
4747
|
};
|
|
4534
|
-
console.log(
|
|
4535
|
-
console.log(
|
|
4748
|
+
console.log(chalk24.dim(`Auto-commit: ${config2.autoCommit ? "ON" : "OFF"}`));
|
|
4749
|
+
console.log(chalk24.dim(`Auto-push: ${config2.autoPush ? "ON" : "OFF"}`));
|
|
4536
4750
|
console.log("");
|
|
4537
4751
|
const fetchActiveTask = async () => {
|
|
4538
4752
|
try {
|
|
4539
|
-
const response = await
|
|
4753
|
+
const response = await axios17.get(`${apiUrl}/api/v1/roadmap`, {
|
|
4540
4754
|
params: { project_id: projectId },
|
|
4541
4755
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4542
4756
|
});
|
|
@@ -4560,17 +4774,17 @@ function createWatchCommand() {
|
|
|
4560
4774
|
};
|
|
4561
4775
|
const checkCriteria = async (criteria) => {
|
|
4562
4776
|
try {
|
|
4563
|
-
const fullPath =
|
|
4777
|
+
const fullPath = path24.resolve(process.cwd(), criteria.path);
|
|
4564
4778
|
switch (criteria.type) {
|
|
4565
4779
|
case "file_exists":
|
|
4566
|
-
await
|
|
4780
|
+
await fs21.access(fullPath);
|
|
4567
4781
|
return true;
|
|
4568
4782
|
case "file_content":
|
|
4569
|
-
const content = await
|
|
4783
|
+
const content = await fs21.readFile(fullPath, "utf-8");
|
|
4570
4784
|
return content.length > 0;
|
|
4571
4785
|
case "content_match":
|
|
4572
4786
|
if (!criteria.match) return false;
|
|
4573
|
-
const fileContent = await
|
|
4787
|
+
const fileContent = await fs21.readFile(fullPath, "utf-8");
|
|
4574
4788
|
return fileContent.includes(criteria.match);
|
|
4575
4789
|
default:
|
|
4576
4790
|
return false;
|
|
@@ -4580,7 +4794,7 @@ function createWatchCommand() {
|
|
|
4580
4794
|
}
|
|
4581
4795
|
};
|
|
4582
4796
|
const completeTask = async (taskId, task) => {
|
|
4583
|
-
const spinner =
|
|
4797
|
+
const spinner = ora11("Completing task...").start();
|
|
4584
4798
|
try {
|
|
4585
4799
|
if (config2.runTests) {
|
|
4586
4800
|
spinner.text = "Running tests...";
|
|
@@ -4592,14 +4806,14 @@ function createWatchCommand() {
|
|
|
4592
4806
|
return;
|
|
4593
4807
|
}
|
|
4594
4808
|
}
|
|
4595
|
-
await
|
|
4809
|
+
await axios17.post(`${apiUrl}/api/v1/roadmap/update-status`, {
|
|
4596
4810
|
project_id: projectId,
|
|
4597
4811
|
chunk_id: taskId,
|
|
4598
4812
|
status: "COMPLETED"
|
|
4599
4813
|
}, {
|
|
4600
4814
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4601
4815
|
});
|
|
4602
|
-
spinner.succeed(
|
|
4816
|
+
spinner.succeed(chalk24.green(`\u2705 Task #${task.step_number} completed: ${task.title}`));
|
|
4603
4817
|
if (config2.autoCommit) {
|
|
4604
4818
|
spinner.start("Committing changes...");
|
|
4605
4819
|
try {
|
|
@@ -4621,7 +4835,7 @@ function createWatchCommand() {
|
|
|
4621
4835
|
}
|
|
4622
4836
|
}
|
|
4623
4837
|
console.log("");
|
|
4624
|
-
console.log(
|
|
4838
|
+
console.log(chalk24.blue("Watching for next task..."));
|
|
4625
4839
|
} catch (e) {
|
|
4626
4840
|
spinner.fail(`Failed to complete task: ${e.message}`);
|
|
4627
4841
|
}
|
|
@@ -4634,7 +4848,7 @@ function createWatchCommand() {
|
|
|
4634
4848
|
const task = await fetchActiveTask();
|
|
4635
4849
|
if (!task) {
|
|
4636
4850
|
if (currentTask) {
|
|
4637
|
-
console.log(
|
|
4851
|
+
console.log(chalk24.green("\u{1F389} All tasks completed! Watching for new tasks..."));
|
|
4638
4852
|
currentTask = null;
|
|
4639
4853
|
}
|
|
4640
4854
|
isProcessing = false;
|
|
@@ -4643,10 +4857,10 @@ function createWatchCommand() {
|
|
|
4643
4857
|
if (!currentTask || currentTask.id !== task.id) {
|
|
4644
4858
|
currentTask = task;
|
|
4645
4859
|
console.log("");
|
|
4646
|
-
console.log(
|
|
4647
|
-
console.log(
|
|
4860
|
+
console.log(chalk24.bold.yellow(`\u{1F4CC} Active Task #${task.step_number}: ${task.title}`));
|
|
4861
|
+
console.log(chalk24.dim(`Status: ${task.status}`));
|
|
4648
4862
|
if (task.verification_criteria) {
|
|
4649
|
-
console.log(
|
|
4863
|
+
console.log(chalk24.dim("Verification: Auto-checking criteria..."));
|
|
4650
4864
|
}
|
|
4651
4865
|
}
|
|
4652
4866
|
if (task.verification_criteria && Array.isArray(task.verification_criteria)) {
|
|
@@ -4659,7 +4873,7 @@ function createWatchCommand() {
|
|
|
4659
4873
|
}
|
|
4660
4874
|
}
|
|
4661
4875
|
if (allPassed) {
|
|
4662
|
-
console.log(
|
|
4876
|
+
console.log(chalk24.green("\u2713 All verification criteria passed!"));
|
|
4663
4877
|
await completeTask(task.id, task);
|
|
4664
4878
|
currentTask = null;
|
|
4665
4879
|
}
|
|
@@ -4684,11 +4898,11 @@ function createWatchCommand() {
|
|
|
4684
4898
|
setTimeout(() => processActiveTask(), 500);
|
|
4685
4899
|
}
|
|
4686
4900
|
});
|
|
4687
|
-
console.log(
|
|
4901
|
+
console.log(chalk24.dim("Watching for file changes... (Ctrl+C to exit)"));
|
|
4688
4902
|
setInterval(() => processActiveTask(), 3e4);
|
|
4689
4903
|
process.on("SIGINT", () => {
|
|
4690
4904
|
console.log("");
|
|
4691
|
-
console.log(
|
|
4905
|
+
console.log(chalk24.dim("Watch mode stopped."));
|
|
4692
4906
|
watcher.close();
|
|
4693
4907
|
process.exit(0);
|
|
4694
4908
|
});
|
|
@@ -4699,42 +4913,42 @@ function createWatchCommand() {
|
|
|
4699
4913
|
// src/commands/focus.ts
|
|
4700
4914
|
init_esm_shims();
|
|
4701
4915
|
init_config();
|
|
4702
|
-
import { Command as
|
|
4703
|
-
import
|
|
4704
|
-
import
|
|
4705
|
-
import
|
|
4916
|
+
import { Command as Command15 } from "commander";
|
|
4917
|
+
import chalk25 from "chalk";
|
|
4918
|
+
import ora12 from "ora";
|
|
4919
|
+
import axios18 from "axios";
|
|
4706
4920
|
import { execSync as execSync5 } from "child_process";
|
|
4707
|
-
import
|
|
4708
|
-
import
|
|
4921
|
+
import fs22 from "fs/promises";
|
|
4922
|
+
import path25 from "path";
|
|
4709
4923
|
function createFocusCommand() {
|
|
4710
|
-
const focus = new
|
|
4924
|
+
const focus = new Command15("focus");
|
|
4711
4925
|
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) => {
|
|
4712
|
-
const spinner =
|
|
4926
|
+
const spinner = ora12("Fetching next objective...").start();
|
|
4713
4927
|
let apiKey;
|
|
4714
4928
|
let projectId;
|
|
4715
4929
|
try {
|
|
4716
4930
|
apiKey = getApiKey();
|
|
4717
4931
|
} catch (e) {
|
|
4718
|
-
spinner.fail(
|
|
4932
|
+
spinner.fail(chalk25.red('Not authenticated. Run "rigstate login" first.'));
|
|
4719
4933
|
return;
|
|
4720
4934
|
}
|
|
4721
4935
|
projectId = getProjectId();
|
|
4722
4936
|
if (!projectId) {
|
|
4723
4937
|
try {
|
|
4724
|
-
const manifestPath =
|
|
4725
|
-
const content = await
|
|
4938
|
+
const manifestPath = path25.join(process.cwd(), ".rigstate");
|
|
4939
|
+
const content = await fs22.readFile(manifestPath, "utf-8");
|
|
4726
4940
|
const manifest = JSON.parse(content);
|
|
4727
4941
|
projectId = manifest.project_id;
|
|
4728
4942
|
} catch (e) {
|
|
4729
4943
|
}
|
|
4730
4944
|
}
|
|
4731
4945
|
if (!projectId) {
|
|
4732
|
-
spinner.fail(
|
|
4946
|
+
spinner.fail(chalk25.red('No project context. Run "rigstate link" first.'));
|
|
4733
4947
|
return;
|
|
4734
4948
|
}
|
|
4735
4949
|
const apiUrl = getApiUrl();
|
|
4736
4950
|
try {
|
|
4737
|
-
const response = await
|
|
4951
|
+
const response = await axios18.get(`${apiUrl}/api/v1/roadmap`, {
|
|
4738
4952
|
params: { project_id: projectId },
|
|
4739
4953
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4740
4954
|
});
|
|
@@ -4760,41 +4974,41 @@ function createFocusCommand() {
|
|
|
4760
4974
|
const nextTask = activeTasks[0];
|
|
4761
4975
|
spinner.stop();
|
|
4762
4976
|
console.log("");
|
|
4763
|
-
console.log(
|
|
4764
|
-
const statusColor = nextTask.status === "IN_PROGRESS" ?
|
|
4765
|
-
console.log(
|
|
4766
|
-
console.log(
|
|
4977
|
+
console.log(chalk25.bold.blue(`\u{1F4CC} Task #${nextTask.step_number || "?"}: ${nextTask.title}`));
|
|
4978
|
+
const statusColor = nextTask.status === "IN_PROGRESS" ? chalk25.yellow : nextTask.status === "ACTIVE" ? chalk25.green : chalk25.dim;
|
|
4979
|
+
console.log(chalk25.dim("Status: ") + statusColor(nextTask.status));
|
|
4980
|
+
console.log(chalk25.dim("\u2500".repeat(60)));
|
|
4767
4981
|
if (nextTask.prompt_content) {
|
|
4768
|
-
console.log(
|
|
4769
|
-
console.log(
|
|
4982
|
+
console.log(chalk25.white(nextTask.prompt_content));
|
|
4983
|
+
console.log(chalk25.dim("\u2500".repeat(60)));
|
|
4770
4984
|
if (options.copy !== false) {
|
|
4771
4985
|
try {
|
|
4772
4986
|
if (process.platform === "darwin") {
|
|
4773
4987
|
execSync5("pbcopy", { input: nextTask.prompt_content });
|
|
4774
|
-
console.log(
|
|
4988
|
+
console.log(chalk25.green("\u2705 Prompt copied to clipboard! Ready to paste (Cmd+V)."));
|
|
4775
4989
|
} else if (process.platform === "linux") {
|
|
4776
4990
|
try {
|
|
4777
4991
|
execSync5("xclip -selection clipboard", { input: nextTask.prompt_content });
|
|
4778
|
-
console.log(
|
|
4992
|
+
console.log(chalk25.green("\u2705 Prompt copied to clipboard!"));
|
|
4779
4993
|
} catch (e) {
|
|
4780
|
-
console.log(
|
|
4994
|
+
console.log(chalk25.yellow("\u2139\uFE0F Copy prompt manually (xclip not available)"));
|
|
4781
4995
|
}
|
|
4782
4996
|
} else {
|
|
4783
|
-
console.log(
|
|
4997
|
+
console.log(chalk25.yellow("\u2139\uFE0F Copy prompt manually (Auto-copy not supported on this OS)"));
|
|
4784
4998
|
}
|
|
4785
4999
|
} catch (e) {
|
|
4786
5000
|
}
|
|
4787
5001
|
}
|
|
4788
5002
|
} else {
|
|
4789
|
-
console.log(
|
|
5003
|
+
console.log(chalk25.yellow("No prompt instructions available."));
|
|
4790
5004
|
if (nextTask.architectural_brief) {
|
|
4791
|
-
console.log(
|
|
5005
|
+
console.log(chalk25.bold("Brief:"));
|
|
4792
5006
|
console.log(nextTask.architectural_brief);
|
|
4793
5007
|
}
|
|
4794
5008
|
}
|
|
4795
5009
|
console.log("");
|
|
4796
5010
|
} catch (e) {
|
|
4797
|
-
spinner.fail(
|
|
5011
|
+
spinner.fail(chalk25.red(`Failed to fetch task: ${e.message}`));
|
|
4798
5012
|
}
|
|
4799
5013
|
});
|
|
4800
5014
|
return focus;
|
|
@@ -4806,26 +5020,26 @@ init_env();
|
|
|
4806
5020
|
// src/commands/config.ts
|
|
4807
5021
|
init_esm_shims();
|
|
4808
5022
|
init_config();
|
|
4809
|
-
import { Command as
|
|
4810
|
-
import
|
|
5023
|
+
import { Command as Command16 } from "commander";
|
|
5024
|
+
import chalk26 from "chalk";
|
|
4811
5025
|
function createConfigCommand() {
|
|
4812
|
-
const config2 = new
|
|
5026
|
+
const config2 = new Command16("config");
|
|
4813
5027
|
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) => {
|
|
4814
5028
|
if (!key) {
|
|
4815
|
-
console.log(
|
|
4816
|
-
console.log(
|
|
5029
|
+
console.log(chalk26.bold("Rigstate Configuration"));
|
|
5030
|
+
console.log(chalk26.dim("\u2500".repeat(40)));
|
|
4817
5031
|
try {
|
|
4818
5032
|
const apiKey = getApiKey();
|
|
4819
|
-
console.log(`${
|
|
5033
|
+
console.log(`${chalk26.cyan("api_key")}: ${apiKey.substring(0, 20)}...`);
|
|
4820
5034
|
} catch (e) {
|
|
4821
|
-
console.log(`${
|
|
5035
|
+
console.log(`${chalk26.cyan("api_key")}: ${chalk26.dim("(not set)")}`);
|
|
4822
5036
|
}
|
|
4823
5037
|
const projectId = getProjectId();
|
|
4824
|
-
console.log(`${
|
|
5038
|
+
console.log(`${chalk26.cyan("project_id")}: ${projectId || chalk26.dim("(not set)")}`);
|
|
4825
5039
|
const apiUrl = getApiUrl();
|
|
4826
|
-
console.log(`${
|
|
5040
|
+
console.log(`${chalk26.cyan("api_url")}: ${apiUrl}`);
|
|
4827
5041
|
console.log("");
|
|
4828
|
-
console.log(
|
|
5042
|
+
console.log(chalk26.dim('Use "rigstate config <key> <value>" to set a value.'));
|
|
4829
5043
|
return;
|
|
4830
5044
|
}
|
|
4831
5045
|
if (!value) {
|
|
@@ -4835,37 +5049,37 @@ function createConfigCommand() {
|
|
|
4835
5049
|
const apiKey = getApiKey();
|
|
4836
5050
|
console.log(apiKey);
|
|
4837
5051
|
} catch (e) {
|
|
4838
|
-
console.log(
|
|
5052
|
+
console.log(chalk26.dim("(not set)"));
|
|
4839
5053
|
}
|
|
4840
5054
|
break;
|
|
4841
5055
|
case "project_id":
|
|
4842
|
-
console.log(getProjectId() ||
|
|
5056
|
+
console.log(getProjectId() || chalk26.dim("(not set)"));
|
|
4843
5057
|
break;
|
|
4844
5058
|
case "api_url":
|
|
4845
5059
|
console.log(getApiUrl());
|
|
4846
5060
|
break;
|
|
4847
5061
|
default:
|
|
4848
|
-
console.log(
|
|
4849
|
-
console.log(
|
|
5062
|
+
console.log(chalk26.red(`Unknown config key: ${key}`));
|
|
5063
|
+
console.log(chalk26.dim("Valid keys: api_key, project_id, api_url"));
|
|
4850
5064
|
}
|
|
4851
5065
|
return;
|
|
4852
5066
|
}
|
|
4853
5067
|
switch (key) {
|
|
4854
5068
|
case "api_key":
|
|
4855
5069
|
setApiKey(value);
|
|
4856
|
-
console.log(
|
|
5070
|
+
console.log(chalk26.green(`\u2705 api_key updated`));
|
|
4857
5071
|
break;
|
|
4858
5072
|
case "project_id":
|
|
4859
5073
|
setProjectId(value);
|
|
4860
|
-
console.log(
|
|
5074
|
+
console.log(chalk26.green(`\u2705 project_id updated`));
|
|
4861
5075
|
break;
|
|
4862
5076
|
case "api_url":
|
|
4863
5077
|
setApiUrl(value);
|
|
4864
|
-
console.log(
|
|
5078
|
+
console.log(chalk26.green(`\u2705 api_url updated`));
|
|
4865
5079
|
break;
|
|
4866
5080
|
default:
|
|
4867
|
-
console.log(
|
|
4868
|
-
console.log(
|
|
5081
|
+
console.log(chalk26.red(`Unknown config key: ${key}`));
|
|
5082
|
+
console.log(chalk26.dim("Valid keys: api_key, project_id, api_url"));
|
|
4869
5083
|
}
|
|
4870
5084
|
});
|
|
4871
5085
|
return config2;
|
|
@@ -4874,42 +5088,42 @@ function createConfigCommand() {
|
|
|
4874
5088
|
// src/commands/mcp.ts
|
|
4875
5089
|
init_esm_shims();
|
|
4876
5090
|
init_config();
|
|
4877
|
-
import { Command as
|
|
4878
|
-
import
|
|
5091
|
+
import { Command as Command17 } from "commander";
|
|
5092
|
+
import chalk27 from "chalk";
|
|
4879
5093
|
import { spawn } from "child_process";
|
|
4880
|
-
import
|
|
4881
|
-
import
|
|
5094
|
+
import path26 from "path";
|
|
5095
|
+
import fs23 from "fs";
|
|
4882
5096
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4883
5097
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
4884
|
-
var __dirname2 =
|
|
5098
|
+
var __dirname2 = path26.dirname(__filename2);
|
|
4885
5099
|
function createMcpCommand() {
|
|
4886
|
-
const mcp = new
|
|
5100
|
+
const mcp = new Command17("mcp");
|
|
4887
5101
|
mcp.description("Run the Rigstate MCP server for AI editors").action(async () => {
|
|
4888
5102
|
const possiblePaths = [
|
|
4889
5103
|
// From packages/cli -> packages/mcp (sibling package)
|
|
4890
|
-
|
|
5104
|
+
path26.resolve(__dirname2, "../../mcp/dist/index.js"),
|
|
4891
5105
|
// If installed globally or via npm
|
|
4892
|
-
|
|
5106
|
+
path26.resolve(__dirname2, "../../../mcp/dist/index.js"),
|
|
4893
5107
|
// Development path from packages/cli/dist
|
|
4894
|
-
|
|
5108
|
+
path26.resolve(__dirname2, "../../../packages/mcp/dist/index.js")
|
|
4895
5109
|
];
|
|
4896
5110
|
let serverPath = "";
|
|
4897
5111
|
for (const p of possiblePaths) {
|
|
4898
|
-
if (
|
|
5112
|
+
if (fs23.existsSync(p)) {
|
|
4899
5113
|
serverPath = p;
|
|
4900
5114
|
break;
|
|
4901
5115
|
}
|
|
4902
5116
|
}
|
|
4903
5117
|
if (!serverPath) {
|
|
4904
|
-
console.error(
|
|
4905
|
-
console.error(
|
|
4906
|
-
console.error(
|
|
5118
|
+
console.error(chalk27.red("\u274C Error: Rigstate MCP Server binary not found."));
|
|
5119
|
+
console.error(chalk27.yellow("Please ensure that the mcp package is built:"));
|
|
5120
|
+
console.error(chalk27.white(" cd packages/mcp && npm run build"));
|
|
4907
5121
|
console.error("");
|
|
4908
|
-
console.error(
|
|
4909
|
-
console.error(
|
|
5122
|
+
console.error(chalk27.dim("Or run directly with:"));
|
|
5123
|
+
console.error(chalk27.white(" npx @rigstate/mcp"));
|
|
4910
5124
|
process.exit(1);
|
|
4911
5125
|
}
|
|
4912
|
-
console.log(
|
|
5126
|
+
console.log(chalk27.dim(`Starting MCP server from: ${serverPath}`));
|
|
4913
5127
|
const env = { ...process.env };
|
|
4914
5128
|
try {
|
|
4915
5129
|
const apiKey = getApiKey();
|
|
@@ -4928,7 +5142,7 @@ function createMcpCommand() {
|
|
|
4928
5142
|
stdio: ["inherit", "inherit", "inherit"]
|
|
4929
5143
|
});
|
|
4930
5144
|
worker.on("error", (err) => {
|
|
4931
|
-
console.error(
|
|
5145
|
+
console.error(chalk27.red(`\u274C Failed to start MCP server: ${err.message}`));
|
|
4932
5146
|
process.exit(1);
|
|
4933
5147
|
});
|
|
4934
5148
|
worker.on("exit", (code) => {
|
|
@@ -4942,8 +5156,8 @@ function createMcpCommand() {
|
|
|
4942
5156
|
|
|
4943
5157
|
// src/commands/nexus.ts
|
|
4944
5158
|
init_esm_shims();
|
|
4945
|
-
import { Command as
|
|
4946
|
-
import
|
|
5159
|
+
import { Command as Command18 } from "commander";
|
|
5160
|
+
import chalk29 from "chalk";
|
|
4947
5161
|
|
|
4948
5162
|
// src/nexus/dispatcher.ts
|
|
4949
5163
|
init_esm_shims();
|
|
@@ -4952,7 +5166,7 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
4952
5166
|
|
|
4953
5167
|
// src/hive/gateway.ts
|
|
4954
5168
|
init_esm_shims();
|
|
4955
|
-
import
|
|
5169
|
+
import axios19 from "axios";
|
|
4956
5170
|
|
|
4957
5171
|
// src/hive/scrubber.ts
|
|
4958
5172
|
init_esm_shims();
|
|
@@ -5011,7 +5225,7 @@ var HiveScrubber = class {
|
|
|
5011
5225
|
};
|
|
5012
5226
|
|
|
5013
5227
|
// src/hive/gateway.ts
|
|
5014
|
-
import
|
|
5228
|
+
import chalk28 from "chalk";
|
|
5015
5229
|
var HiveGateway = class {
|
|
5016
5230
|
client;
|
|
5017
5231
|
enabled;
|
|
@@ -5021,9 +5235,9 @@ var HiveGateway = class {
|
|
|
5021
5235
|
constructor(baseUrl, token) {
|
|
5022
5236
|
this.enabled = !!token;
|
|
5023
5237
|
if (!this.enabled) {
|
|
5024
|
-
console.log(
|
|
5238
|
+
console.log(chalk28.dim("\u26A0\uFE0F Hive Gateway disabled (No Token provided). Running in localized mode."));
|
|
5025
5239
|
}
|
|
5026
|
-
this.client =
|
|
5240
|
+
this.client = axios19.create({
|
|
5027
5241
|
baseURL: baseUrl,
|
|
5028
5242
|
headers: {
|
|
5029
5243
|
"Authorization": `Bearer ${token}`,
|
|
@@ -5041,23 +5255,23 @@ var HiveGateway = class {
|
|
|
5041
5255
|
if (!this.enabled) return false;
|
|
5042
5256
|
const now = Date.now();
|
|
5043
5257
|
if (now - this.lastSignalTime < this.MIN_INTERVAL_MS) {
|
|
5044
|
-
console.warn(
|
|
5258
|
+
console.warn(chalk28.yellow("\u23F3 Hive Gateway Throttled. Signal dropped to preventing spam."));
|
|
5045
5259
|
return false;
|
|
5046
5260
|
}
|
|
5047
5261
|
const scrubResult = HiveScrubber.scrub(signal.ruleContent);
|
|
5048
5262
|
if (scrubResult.riskScore > 20) {
|
|
5049
|
-
console.error(
|
|
5263
|
+
console.error(chalk28.red(`\u{1F6D1} HIVE BLOCKED: Signal contains sensitive data (Risk: ${scrubResult.riskScore})`));
|
|
5050
5264
|
return false;
|
|
5051
5265
|
}
|
|
5052
5266
|
try {
|
|
5053
|
-
console.log(
|
|
5267
|
+
console.log(chalk28.blue(`\u{1F4E1} Uplinking to Hive... [${signal.vector}]`));
|
|
5054
5268
|
const payload = { ...signal, ruleContent: scrubResult.sanitizedContent };
|
|
5055
5269
|
await this.client.post("/signal", payload);
|
|
5056
5270
|
this.lastSignalTime = now;
|
|
5057
|
-
console.log(
|
|
5271
|
+
console.log(chalk28.green("\u2705 Signal Received by Hive Core. Knowledge Shared."));
|
|
5058
5272
|
return true;
|
|
5059
5273
|
} catch (error) {
|
|
5060
|
-
console.error(
|
|
5274
|
+
console.error(chalk28.red(`\u274C Hive Transmission Failed: ${error.message}`));
|
|
5061
5275
|
return false;
|
|
5062
5276
|
}
|
|
5063
5277
|
}
|
|
@@ -5155,15 +5369,15 @@ var NexusDispatcher = class extends EventEmitter4 {
|
|
|
5155
5369
|
};
|
|
5156
5370
|
|
|
5157
5371
|
// src/commands/nexus.ts
|
|
5158
|
-
import
|
|
5372
|
+
import inquirer4 from "inquirer";
|
|
5159
5373
|
function createNexusCommand() {
|
|
5160
|
-
const command = new
|
|
5374
|
+
const command = new Command18("nexus");
|
|
5161
5375
|
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) => {
|
|
5162
|
-
console.log(
|
|
5376
|
+
console.log(chalk29.bold.magenta("\n\u{1F981} Welcome to The Nexus (Phase 8)\n"));
|
|
5163
5377
|
const dryRun = !options.force;
|
|
5164
5378
|
if (!dryRun) {
|
|
5165
|
-
console.log(
|
|
5166
|
-
const { confirm } = await
|
|
5379
|
+
console.log(chalk29.black.bgYellow(" WARNING ") + chalk29.yellow(" Dry-Run disabled! Eitri is authorized to write code."));
|
|
5380
|
+
const { confirm } = await inquirer4.prompt([{
|
|
5167
5381
|
type: "confirm",
|
|
5168
5382
|
name: "confirm",
|
|
5169
5383
|
message: "Are you absolutely sure you want to bypass the Kill-Switch?",
|
|
@@ -5183,26 +5397,26 @@ function createNexusCommand() {
|
|
|
5183
5397
|
};
|
|
5184
5398
|
const dispatcher = new NexusDispatcher(context);
|
|
5185
5399
|
dispatcher.on("order:created", (o) => {
|
|
5186
|
-
console.log(
|
|
5400
|
+
console.log(chalk29.blue(`\u{1F195} [${o.id.slice(0, 6)}] Order Created: `) + o.intent);
|
|
5187
5401
|
});
|
|
5188
5402
|
dispatcher.on("order:started", (o) => {
|
|
5189
|
-
console.log(
|
|
5403
|
+
console.log(chalk29.yellow(`\u23F3 [${o.id.slice(0, 6)}] Processing...`));
|
|
5190
5404
|
});
|
|
5191
5405
|
dispatcher.on("order:blocked", (o) => {
|
|
5192
|
-
console.log(
|
|
5193
|
-
console.log(
|
|
5194
|
-
console.log(
|
|
5406
|
+
console.log(chalk29.red(`\u{1F6D1} [${o.id.slice(0, 6)}] BLOCKED by Kill-Switch`));
|
|
5407
|
+
console.log(chalk29.dim(` Target: ${o.targetAgent} | Action: ${o.action}`));
|
|
5408
|
+
console.log(chalk29.dim(" Run with --force to execute automatically (NOT RECOMMENDED)."));
|
|
5195
5409
|
});
|
|
5196
|
-
dispatcher.on("agent:SINDRE", (o) => console.log(
|
|
5197
|
-
dispatcher.on("agent:EITRI", (o) => console.log(
|
|
5198
|
-
console.log(
|
|
5410
|
+
dispatcher.on("agent:SINDRE", (o) => console.log(chalk29.cyan(`\u{1F916} Sindre (Vault): I'm on it! (${o.action})`)));
|
|
5411
|
+
dispatcher.on("agent:EITRI", (o) => console.log(chalk29.green(`\u{1F477} Eitri (Smith): Ready to build! (${o.action})`)));
|
|
5412
|
+
console.log(chalk29.dim("\u{1F9E0} Frank is analyzing your intent..."));
|
|
5199
5413
|
await new Promise((r) => setTimeout(r, 800));
|
|
5200
5414
|
if (intent.toLowerCase().includes("db") || intent.toLowerCase().includes("database")) {
|
|
5201
5415
|
await dispatcher.dispatch("FRANK", "SINDRE", intent, "db.analyze", { raw: intent });
|
|
5202
5416
|
} else if (intent.toLowerCase().includes("create") || intent.toLowerCase().includes("code")) {
|
|
5203
5417
|
await dispatcher.dispatch("FRANK", "EITRI", intent, "fs.write", { path: "src/demo.ts", content: "// demo" });
|
|
5204
5418
|
} else {
|
|
5205
|
-
console.log(
|
|
5419
|
+
console.log(chalk29.gray("Frank didn't understand. Try 'create file' or 'check database'."));
|
|
5206
5420
|
}
|
|
5207
5421
|
});
|
|
5208
5422
|
return command;
|
|
@@ -5215,32 +5429,32 @@ init_sync_rules();
|
|
|
5215
5429
|
init_esm_shims();
|
|
5216
5430
|
init_governance();
|
|
5217
5431
|
init_config();
|
|
5218
|
-
import { Command as
|
|
5219
|
-
import
|
|
5220
|
-
import
|
|
5432
|
+
import { Command as Command19 } from "commander";
|
|
5433
|
+
import chalk30 from "chalk";
|
|
5434
|
+
import axios20 from "axios";
|
|
5221
5435
|
function createOverrideCommand() {
|
|
5222
|
-
const override = new
|
|
5436
|
+
const override = new Command19("override");
|
|
5223
5437
|
override.description("Emergency Override for Governance Soft Locks").argument("<violationId>", 'ID of the violation to override (or "all")').requiredOption("-r, --reason <reason>", "Description of why this override is necessary").action(async (violationId, options) => {
|
|
5224
5438
|
const { reason } = options;
|
|
5225
|
-
console.log(
|
|
5439
|
+
console.log(chalk30.bold(`
|
|
5226
5440
|
\u{1F513} Initiating Governance Override Protocol...`));
|
|
5227
5441
|
const session = await getSessionState(process.cwd());
|
|
5228
5442
|
if (session.status !== "SOFT_LOCK") {
|
|
5229
|
-
console.log(
|
|
5443
|
+
console.log(chalk30.yellow(" Info: Session is not currently locked."));
|
|
5230
5444
|
return;
|
|
5231
5445
|
}
|
|
5232
|
-
console.log(
|
|
5233
|
-
console.log(
|
|
5446
|
+
console.log(chalk30.dim(` Active Violation: ${session.active_violation}`));
|
|
5447
|
+
console.log(chalk30.dim(` Reason Provided: "${reason}"`));
|
|
5234
5448
|
const success = await performOverride(violationId, reason, process.cwd());
|
|
5235
5449
|
if (success) {
|
|
5236
|
-
console.log(
|
|
5237
|
-
console.log(
|
|
5450
|
+
console.log(chalk30.green(` \u2705 Session UNLOCKED.`));
|
|
5451
|
+
console.log(chalk30.dim(` This event has been logged to the Mission Report.`));
|
|
5238
5452
|
try {
|
|
5239
5453
|
const projectId = getProjectId();
|
|
5240
5454
|
if (projectId) {
|
|
5241
5455
|
const apiUrl = getApiUrl();
|
|
5242
5456
|
const apiKey = getApiKey();
|
|
5243
|
-
await
|
|
5457
|
+
await axios20.post(`${apiUrl}/api/v1/execution-logs`, {
|
|
5244
5458
|
project_id: projectId,
|
|
5245
5459
|
task_id: "OVERRIDE-" + Date.now(),
|
|
5246
5460
|
task_title: `Governance Override: ${violationId}`,
|
|
@@ -5251,13 +5465,13 @@ function createOverrideCommand() {
|
|
|
5251
5465
|
}, {
|
|
5252
5466
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
5253
5467
|
});
|
|
5254
|
-
console.log(
|
|
5468
|
+
console.log(chalk30.dim(` \u2601 Audit log synced to Cloud.`));
|
|
5255
5469
|
}
|
|
5256
5470
|
} catch (e) {
|
|
5257
|
-
console.log(
|
|
5471
|
+
console.log(chalk30.dim(` (Cloud audit sync failed: ${e.message})`));
|
|
5258
5472
|
}
|
|
5259
5473
|
} else {
|
|
5260
|
-
console.log(
|
|
5474
|
+
console.log(chalk30.red(` \u{1F6D1} Override Failed. Check project configuration.`));
|
|
5261
5475
|
}
|
|
5262
5476
|
});
|
|
5263
5477
|
return override;
|
|
@@ -5266,26 +5480,26 @@ function createOverrideCommand() {
|
|
|
5266
5480
|
// src/commands/idea.ts
|
|
5267
5481
|
init_esm_shims();
|
|
5268
5482
|
init_config();
|
|
5269
|
-
import { Command as
|
|
5270
|
-
import
|
|
5271
|
-
import
|
|
5272
|
-
import
|
|
5273
|
-
import
|
|
5483
|
+
import { Command as Command20 } from "commander";
|
|
5484
|
+
import chalk31 from "chalk";
|
|
5485
|
+
import ora13 from "ora";
|
|
5486
|
+
import axios21 from "axios";
|
|
5487
|
+
import inquirer5 from "inquirer";
|
|
5274
5488
|
function createIdeaCommand() {
|
|
5275
|
-
return new
|
|
5489
|
+
return new Command20("idea").description("Capture a new idea or feature request").argument("[title]", "Quick title of the idea").option("-d, --desc <text>", "Detailed description").option("-t, --tag <tags>", "Comma separated tags (e.g. ui,auth)").action(async (title, options) => {
|
|
5276
5490
|
try {
|
|
5277
5491
|
const apiKey = getApiKey();
|
|
5278
5492
|
const apiUrl = getApiUrl();
|
|
5279
5493
|
const projectId = getProjectId();
|
|
5280
5494
|
if (!projectId) {
|
|
5281
|
-
console.error(
|
|
5495
|
+
console.error(chalk31.red("Project context missing. Run rigstate link."));
|
|
5282
5496
|
process.exit(1);
|
|
5283
5497
|
}
|
|
5284
5498
|
let ideaTitle = title;
|
|
5285
5499
|
let ideaDesc = options.desc;
|
|
5286
5500
|
let tags = options.tag ? options.tag.split(",") : [];
|
|
5287
5501
|
if (!ideaTitle) {
|
|
5288
|
-
const ans = await
|
|
5502
|
+
const ans = await inquirer5.prompt([{
|
|
5289
5503
|
type: "input",
|
|
5290
5504
|
name: "title",
|
|
5291
5505
|
message: "Idea Title:"
|
|
@@ -5293,7 +5507,7 @@ function createIdeaCommand() {
|
|
|
5293
5507
|
ideaTitle = ans.title;
|
|
5294
5508
|
}
|
|
5295
5509
|
if (!ideaDesc) {
|
|
5296
|
-
const ans = await
|
|
5510
|
+
const ans = await inquirer5.prompt([{
|
|
5297
5511
|
type: "input",
|
|
5298
5512
|
name: "desc",
|
|
5299
5513
|
message: "Description (Optional):"
|
|
@@ -5302,8 +5516,8 @@ function createIdeaCommand() {
|
|
|
5302
5516
|
}
|
|
5303
5517
|
if (tags.length === 0) {
|
|
5304
5518
|
}
|
|
5305
|
-
const spinner =
|
|
5306
|
-
const response = await
|
|
5519
|
+
const spinner = ora13("Securing idea in the Lab...").start();
|
|
5520
|
+
const response = await axios21.post(
|
|
5307
5521
|
`${apiUrl}/api/v1/ideas`,
|
|
5308
5522
|
{
|
|
5309
5523
|
project_id: projectId,
|
|
@@ -5314,14 +5528,14 @@ function createIdeaCommand() {
|
|
|
5314
5528
|
{ headers: { Authorization: `Bearer ${apiKey}` } }
|
|
5315
5529
|
);
|
|
5316
5530
|
if (response.data.success) {
|
|
5317
|
-
spinner.succeed(
|
|
5318
|
-
console.log(
|
|
5531
|
+
spinner.succeed(chalk31.green("Idea Captured! \u{1F4A1}"));
|
|
5532
|
+
console.log(chalk31.dim(`ID: ${response.data.data?.id || "Saved"}`));
|
|
5319
5533
|
} else {
|
|
5320
5534
|
throw new Error(response.data.error);
|
|
5321
5535
|
}
|
|
5322
5536
|
} catch (e) {
|
|
5323
5537
|
const errorDetail = e.response?.data?.error || e.message;
|
|
5324
|
-
console.error(
|
|
5538
|
+
console.error(chalk31.red(`
|
|
5325
5539
|
Failed to capture idea: ${errorDetail}`));
|
|
5326
5540
|
}
|
|
5327
5541
|
});
|
|
@@ -5330,12 +5544,12 @@ Failed to capture idea: ${errorDetail}`));
|
|
|
5330
5544
|
// src/commands/release.ts
|
|
5331
5545
|
init_esm_shims();
|
|
5332
5546
|
init_config();
|
|
5333
|
-
import { Command as
|
|
5334
|
-
import
|
|
5335
|
-
import
|
|
5336
|
-
import
|
|
5337
|
-
import
|
|
5338
|
-
import
|
|
5547
|
+
import { Command as Command21 } from "commander";
|
|
5548
|
+
import chalk32 from "chalk";
|
|
5549
|
+
import ora14 from "ora";
|
|
5550
|
+
import inquirer6 from "inquirer";
|
|
5551
|
+
import fs24 from "fs/promises";
|
|
5552
|
+
import path27 from "path";
|
|
5339
5553
|
|
|
5340
5554
|
// ../../node_modules/simple-git/dist/esm/index.js
|
|
5341
5555
|
init_esm_shims();
|
|
@@ -5375,8 +5589,8 @@ function pathspec(...paths) {
|
|
|
5375
5589
|
cache.set(key, paths);
|
|
5376
5590
|
return key;
|
|
5377
5591
|
}
|
|
5378
|
-
function isPathSpec(
|
|
5379
|
-
return
|
|
5592
|
+
function isPathSpec(path28) {
|
|
5593
|
+
return path28 instanceof String && cache.has(path28);
|
|
5380
5594
|
}
|
|
5381
5595
|
function toPaths(pathSpec) {
|
|
5382
5596
|
return cache.get(pathSpec) || [];
|
|
@@ -5465,8 +5679,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
5465
5679
|
function forEachLineWithContent(input, callback) {
|
|
5466
5680
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
5467
5681
|
}
|
|
5468
|
-
function folderExists(
|
|
5469
|
-
return (0, import_file_exists.exists)(
|
|
5682
|
+
function folderExists(path28) {
|
|
5683
|
+
return (0, import_file_exists.exists)(path28, import_file_exists.FOLDER);
|
|
5470
5684
|
}
|
|
5471
5685
|
function append(target, item) {
|
|
5472
5686
|
if (Array.isArray(target)) {
|
|
@@ -5870,8 +6084,8 @@ function checkIsRepoRootTask() {
|
|
|
5870
6084
|
commands,
|
|
5871
6085
|
format: "utf-8",
|
|
5872
6086
|
onError,
|
|
5873
|
-
parser(
|
|
5874
|
-
return /^\.(git)?$/.test(
|
|
6087
|
+
parser(path28) {
|
|
6088
|
+
return /^\.(git)?$/.test(path28.trim());
|
|
5875
6089
|
}
|
|
5876
6090
|
};
|
|
5877
6091
|
}
|
|
@@ -6305,11 +6519,11 @@ function parseGrep(grep) {
|
|
|
6305
6519
|
const paths = /* @__PURE__ */ new Set();
|
|
6306
6520
|
const results = {};
|
|
6307
6521
|
forEachLineWithContent(grep, (input) => {
|
|
6308
|
-
const [
|
|
6309
|
-
paths.add(
|
|
6310
|
-
(results[
|
|
6522
|
+
const [path28, line, preview] = input.split(NULL);
|
|
6523
|
+
paths.add(path28);
|
|
6524
|
+
(results[path28] = results[path28] || []).push({
|
|
6311
6525
|
line: asNumber(line),
|
|
6312
|
-
path:
|
|
6526
|
+
path: path28,
|
|
6313
6527
|
preview
|
|
6314
6528
|
});
|
|
6315
6529
|
});
|
|
@@ -7074,14 +7288,14 @@ var init_hash_object = __esm2({
|
|
|
7074
7288
|
init_task();
|
|
7075
7289
|
}
|
|
7076
7290
|
});
|
|
7077
|
-
function parseInit(bare,
|
|
7291
|
+
function parseInit(bare, path28, text) {
|
|
7078
7292
|
const response = String(text).trim();
|
|
7079
7293
|
let result;
|
|
7080
7294
|
if (result = initResponseRegex.exec(response)) {
|
|
7081
|
-
return new InitSummary(bare,
|
|
7295
|
+
return new InitSummary(bare, path28, false, result[1]);
|
|
7082
7296
|
}
|
|
7083
7297
|
if (result = reInitResponseRegex.exec(response)) {
|
|
7084
|
-
return new InitSummary(bare,
|
|
7298
|
+
return new InitSummary(bare, path28, true, result[1]);
|
|
7085
7299
|
}
|
|
7086
7300
|
let gitDir = "";
|
|
7087
7301
|
const tokens = response.split(" ");
|
|
@@ -7092,7 +7306,7 @@ function parseInit(bare, path27, text) {
|
|
|
7092
7306
|
break;
|
|
7093
7307
|
}
|
|
7094
7308
|
}
|
|
7095
|
-
return new InitSummary(bare,
|
|
7309
|
+
return new InitSummary(bare, path28, /^re/i.test(response), gitDir);
|
|
7096
7310
|
}
|
|
7097
7311
|
var InitSummary;
|
|
7098
7312
|
var initResponseRegex;
|
|
@@ -7101,9 +7315,9 @@ var init_InitSummary = __esm2({
|
|
|
7101
7315
|
"src/lib/responses/InitSummary.ts"() {
|
|
7102
7316
|
"use strict";
|
|
7103
7317
|
InitSummary = class {
|
|
7104
|
-
constructor(bare,
|
|
7318
|
+
constructor(bare, path28, existing, gitDir) {
|
|
7105
7319
|
this.bare = bare;
|
|
7106
|
-
this.path =
|
|
7320
|
+
this.path = path28;
|
|
7107
7321
|
this.existing = existing;
|
|
7108
7322
|
this.gitDir = gitDir;
|
|
7109
7323
|
}
|
|
@@ -7115,7 +7329,7 @@ var init_InitSummary = __esm2({
|
|
|
7115
7329
|
function hasBareCommand(command) {
|
|
7116
7330
|
return command.includes(bareCommand);
|
|
7117
7331
|
}
|
|
7118
|
-
function initTask(bare = false,
|
|
7332
|
+
function initTask(bare = false, path28, customArgs) {
|
|
7119
7333
|
const commands = ["init", ...customArgs];
|
|
7120
7334
|
if (bare && !hasBareCommand(commands)) {
|
|
7121
7335
|
commands.splice(1, 0, bareCommand);
|
|
@@ -7124,7 +7338,7 @@ function initTask(bare = false, path27, customArgs) {
|
|
|
7124
7338
|
commands,
|
|
7125
7339
|
format: "utf-8",
|
|
7126
7340
|
parser(text) {
|
|
7127
|
-
return parseInit(commands.includes("--bare"),
|
|
7341
|
+
return parseInit(commands.includes("--bare"), path28, text);
|
|
7128
7342
|
}
|
|
7129
7343
|
};
|
|
7130
7344
|
}
|
|
@@ -7940,12 +8154,12 @@ var init_FileStatusSummary = __esm2({
|
|
|
7940
8154
|
"use strict";
|
|
7941
8155
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
7942
8156
|
FileStatusSummary = class {
|
|
7943
|
-
constructor(
|
|
7944
|
-
this.path =
|
|
8157
|
+
constructor(path28, index, working_dir) {
|
|
8158
|
+
this.path = path28;
|
|
7945
8159
|
this.index = index;
|
|
7946
8160
|
this.working_dir = working_dir;
|
|
7947
8161
|
if (index === "R" || working_dir === "R") {
|
|
7948
|
-
const detail = fromPathRegex.exec(
|
|
8162
|
+
const detail = fromPathRegex.exec(path28) || [null, path28, path28];
|
|
7949
8163
|
this.from = detail[2] || "";
|
|
7950
8164
|
this.path = detail[1] || "";
|
|
7951
8165
|
}
|
|
@@ -7976,14 +8190,14 @@ function splitLine(result, lineStr) {
|
|
|
7976
8190
|
default:
|
|
7977
8191
|
return;
|
|
7978
8192
|
}
|
|
7979
|
-
function data(index, workingDir,
|
|
8193
|
+
function data(index, workingDir, path28) {
|
|
7980
8194
|
const raw = `${index}${workingDir}`;
|
|
7981
8195
|
const handler = parsers6.get(raw);
|
|
7982
8196
|
if (handler) {
|
|
7983
|
-
handler(result,
|
|
8197
|
+
handler(result, path28);
|
|
7984
8198
|
}
|
|
7985
8199
|
if (raw !== "##" && raw !== "!!") {
|
|
7986
|
-
result.files.push(new FileStatusSummary(
|
|
8200
|
+
result.files.push(new FileStatusSummary(path28, index, workingDir));
|
|
7987
8201
|
}
|
|
7988
8202
|
}
|
|
7989
8203
|
}
|
|
@@ -8296,9 +8510,9 @@ var init_simple_git_api = __esm2({
|
|
|
8296
8510
|
next
|
|
8297
8511
|
);
|
|
8298
8512
|
}
|
|
8299
|
-
hashObject(
|
|
8513
|
+
hashObject(path28, write) {
|
|
8300
8514
|
return this._runTask(
|
|
8301
|
-
hashObjectTask(
|
|
8515
|
+
hashObjectTask(path28, write === true),
|
|
8302
8516
|
trailingFunctionArgument(arguments)
|
|
8303
8517
|
);
|
|
8304
8518
|
}
|
|
@@ -8651,8 +8865,8 @@ var init_branch = __esm2({
|
|
|
8651
8865
|
}
|
|
8652
8866
|
});
|
|
8653
8867
|
function toPath(input) {
|
|
8654
|
-
const
|
|
8655
|
-
return
|
|
8868
|
+
const path28 = input.trim().replace(/^["']|["']$/g, "");
|
|
8869
|
+
return path28 && normalize(path28);
|
|
8656
8870
|
}
|
|
8657
8871
|
var parseCheckIgnore;
|
|
8658
8872
|
var init_CheckIgnore = __esm2({
|
|
@@ -8966,8 +9180,8 @@ __export2(sub_module_exports, {
|
|
|
8966
9180
|
subModuleTask: () => subModuleTask,
|
|
8967
9181
|
updateSubModuleTask: () => updateSubModuleTask
|
|
8968
9182
|
});
|
|
8969
|
-
function addSubModuleTask(repo,
|
|
8970
|
-
return subModuleTask(["add", repo,
|
|
9183
|
+
function addSubModuleTask(repo, path28) {
|
|
9184
|
+
return subModuleTask(["add", repo, path28]);
|
|
8971
9185
|
}
|
|
8972
9186
|
function initSubModuleTask(customArgs) {
|
|
8973
9187
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -9297,8 +9511,8 @@ var require_git = __commonJS2({
|
|
|
9297
9511
|
}
|
|
9298
9512
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
9299
9513
|
};
|
|
9300
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
9301
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
9514
|
+
Git2.prototype.submoduleAdd = function(repo, path28, then) {
|
|
9515
|
+
return this._runTask(addSubModuleTask2(repo, path28), trailingFunctionArgument2(arguments));
|
|
9302
9516
|
};
|
|
9303
9517
|
Git2.prototype.submoduleUpdate = function(args, then) {
|
|
9304
9518
|
return this._runTask(
|
|
@@ -9888,18 +10102,18 @@ var simpleGit = gitInstanceFactory;
|
|
|
9888
10102
|
// src/commands/release.ts
|
|
9889
10103
|
var git = simpleGit();
|
|
9890
10104
|
function createReleaseCommand() {
|
|
9891
|
-
return new
|
|
9892
|
-
const spinner =
|
|
10105
|
+
return new Command21("release").description("Ship a new version (Changelog, Tag, Bump)").argument("[type]", "Release type (patch, minor, major)", "patch").action(async (type) => {
|
|
10106
|
+
const spinner = ora14("Preparing release...").start();
|
|
9893
10107
|
try {
|
|
9894
|
-
const { projectId, apiKey, apiUrl } =
|
|
10108
|
+
const { projectId, apiKey, apiUrl } = getContext3();
|
|
9895
10109
|
const status = await git.status();
|
|
9896
10110
|
if (!status.isClean()) {
|
|
9897
10111
|
spinner.fail("Git workspace is dirty. Commit or stash changes first.");
|
|
9898
10112
|
return;
|
|
9899
10113
|
}
|
|
9900
10114
|
spinner.text = "Scanning completed tasks...";
|
|
9901
|
-
const pkgPath =
|
|
9902
|
-
const pkgContent = await
|
|
10115
|
+
const pkgPath = path27.resolve(process.cwd(), "package.json");
|
|
10116
|
+
const pkgContent = await fs24.readFile(pkgPath, "utf-8");
|
|
9903
10117
|
const pkg2 = JSON.parse(pkgContent);
|
|
9904
10118
|
const currentVersion = pkg2.version;
|
|
9905
10119
|
const [major, minor, patch] = currentVersion.split(".").map(Number);
|
|
@@ -9907,8 +10121,8 @@ function createReleaseCommand() {
|
|
|
9907
10121
|
if (type === "major") newVersion = `${major + 1}.0.0`;
|
|
9908
10122
|
if (type === "minor") newVersion = `${major}.${minor + 1}.0`;
|
|
9909
10123
|
if (type === "patch") newVersion = `${major}.${minor}.${patch + 1}`;
|
|
9910
|
-
spinner.succeed(`Bumping ${pkg2.name} from ${
|
|
9911
|
-
const { confirm } = await
|
|
10124
|
+
spinner.succeed(`Bumping ${pkg2.name} from ${chalk32.dim(currentVersion)} to ${chalk32.green(newVersion)}`);
|
|
10125
|
+
const { confirm } = await inquirer6.prompt([{
|
|
9912
10126
|
type: "confirm",
|
|
9913
10127
|
name: "confirm",
|
|
9914
10128
|
message: `Ship v${newVersion}? This will tag git and update changelog (if db ready).`,
|
|
@@ -9919,17 +10133,17 @@ function createReleaseCommand() {
|
|
|
9919
10133
|
return;
|
|
9920
10134
|
}
|
|
9921
10135
|
pkg2.version = newVersion;
|
|
9922
|
-
await
|
|
9923
|
-
const changelogPath =
|
|
10136
|
+
await fs24.writeFile(pkgPath, JSON.stringify(pkg2, null, 4));
|
|
10137
|
+
const changelogPath = path27.resolve(process.cwd(), "CHANGELOG.md");
|
|
9924
10138
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9925
10139
|
const entry = `
|
|
9926
10140
|
## [${newVersion}] - ${date}
|
|
9927
10141
|
- Automated release via Rigstate.
|
|
9928
10142
|
`;
|
|
9929
10143
|
try {
|
|
9930
|
-
await
|
|
10144
|
+
await fs24.appendFile(changelogPath, entry);
|
|
9931
10145
|
} catch {
|
|
9932
|
-
await
|
|
10146
|
+
await fs24.writeFile(changelogPath, "# Changelog\n" + entry);
|
|
9933
10147
|
}
|
|
9934
10148
|
spinner.start("Tagging and pushing...");
|
|
9935
10149
|
await git.add(["package.json", "CHANGELOG.md"]);
|
|
@@ -9937,13 +10151,13 @@ function createReleaseCommand() {
|
|
|
9937
10151
|
await git.addTag(`v${newVersion}`);
|
|
9938
10152
|
await git.push();
|
|
9939
10153
|
await git.pushTags();
|
|
9940
|
-
spinner.succeed(
|
|
10154
|
+
spinner.succeed(chalk32.bold.green(`\u{1F680} Release v${newVersion} shipped!`));
|
|
9941
10155
|
} catch (e) {
|
|
9942
10156
|
spinner.fail(e.message);
|
|
9943
10157
|
}
|
|
9944
10158
|
});
|
|
9945
10159
|
}
|
|
9946
|
-
function
|
|
10160
|
+
function getContext3() {
|
|
9947
10161
|
const apiKey = getApiKey();
|
|
9948
10162
|
const apiUrl = getApiUrl();
|
|
9949
10163
|
const projectId = getProjectId();
|
|
@@ -9954,22 +10168,22 @@ function getContext2() {
|
|
|
9954
10168
|
// src/commands/roadmap.ts
|
|
9955
10169
|
init_esm_shims();
|
|
9956
10170
|
init_config();
|
|
9957
|
-
import { Command as
|
|
9958
|
-
import
|
|
9959
|
-
import
|
|
9960
|
-
import
|
|
10171
|
+
import { Command as Command22 } from "commander";
|
|
10172
|
+
import chalk33 from "chalk";
|
|
10173
|
+
import ora15 from "ora";
|
|
10174
|
+
import axios22 from "axios";
|
|
9961
10175
|
function createRoadmapCommand() {
|
|
9962
|
-
return new
|
|
9963
|
-
const spinner =
|
|
10176
|
+
return new Command22("roadmap").alias("tactical").description("View project roadmap and task status (Tactical View)").action(async () => {
|
|
10177
|
+
const spinner = ora15("Fetching tactical overview...").start();
|
|
9964
10178
|
try {
|
|
9965
10179
|
const apiKey = getApiKey();
|
|
9966
10180
|
const apiUrl = getApiUrl();
|
|
9967
10181
|
const projectId = getProjectId();
|
|
9968
10182
|
if (!projectId) {
|
|
9969
|
-
spinner.fail(
|
|
10183
|
+
spinner.fail(chalk33.red('Project context missing. Run "rigstate link".'));
|
|
9970
10184
|
return;
|
|
9971
10185
|
}
|
|
9972
|
-
const response = await
|
|
10186
|
+
const response = await axios22.get(
|
|
9973
10187
|
`${apiUrl}/api/v1/roadmap?project_id=${projectId}`,
|
|
9974
10188
|
{ headers: { Authorization: `Bearer ${apiKey}` } }
|
|
9975
10189
|
);
|
|
@@ -9979,11 +10193,11 @@ function createRoadmapCommand() {
|
|
|
9979
10193
|
const tasks = response.data.data.roadmap || [];
|
|
9980
10194
|
spinner.stop();
|
|
9981
10195
|
if (tasks.length === 0) {
|
|
9982
|
-
console.log(
|
|
10196
|
+
console.log(chalk33.yellow("\nRoadmap is empty. Use the web UI to define your journey."));
|
|
9983
10197
|
return;
|
|
9984
10198
|
}
|
|
9985
|
-
console.log("\n" +
|
|
9986
|
-
console.log(
|
|
10199
|
+
console.log("\n" + chalk33.bold.underline("\u{1F6F0}\uFE0F TACTICAL OVERVIEW: PROJECT ROADMAP"));
|
|
10200
|
+
console.log(chalk33.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
9987
10201
|
const columns = {
|
|
9988
10202
|
"IN_PROGRESS": [],
|
|
9989
10203
|
"ACTIVE": [],
|
|
@@ -9995,14 +10209,14 @@ function createRoadmapCommand() {
|
|
|
9995
10209
|
columns[t.status].push(t);
|
|
9996
10210
|
}
|
|
9997
10211
|
});
|
|
9998
|
-
displayColumn("\u{1F525} IN PROGRESS", columns.IN_PROGRESS,
|
|
9999
|
-
displayColumn("\u25B6\uFE0F ACTIVE / NEXT", columns.ACTIVE,
|
|
10000
|
-
displayColumn("\u{1F512} LOCKED", columns.LOCKED,
|
|
10001
|
-
displayColumn("\u23F3 PENDING", columns.PENDING,
|
|
10002
|
-
console.log(
|
|
10003
|
-
console.log(
|
|
10212
|
+
displayColumn("\u{1F525} IN PROGRESS", columns.IN_PROGRESS, chalk33.yellow);
|
|
10213
|
+
displayColumn("\u25B6\uFE0F ACTIVE / NEXT", columns.ACTIVE, chalk33.green);
|
|
10214
|
+
displayColumn("\u{1F512} LOCKED", columns.LOCKED, chalk33.blue);
|
|
10215
|
+
displayColumn("\u23F3 PENDING", columns.PENDING, chalk33.gray);
|
|
10216
|
+
console.log(chalk33.dim("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
10217
|
+
console.log(chalk33.dim(`Total: ${tasks.length} tasks | Run "rigstate work" to start coding.`));
|
|
10004
10218
|
} catch (e) {
|
|
10005
|
-
spinner.fail(
|
|
10219
|
+
spinner.fail(chalk33.red(`
|
|
10006
10220
|
Failed to fetch roadmap: ${e.message}`));
|
|
10007
10221
|
}
|
|
10008
10222
|
});
|
|
@@ -10013,57 +10227,57 @@ function displayColumn(title, items, color) {
|
|
|
10013
10227
|
${color.bold(title)}`);
|
|
10014
10228
|
items.sort((a, b) => a.step_number - b.step_number).forEach((item) => {
|
|
10015
10229
|
const id = `T-${item.step_number}`.padEnd(8);
|
|
10016
|
-
const priority = item.priority === "MVP" ?
|
|
10017
|
-
console.log(` ${color("\u2022")} ${
|
|
10230
|
+
const priority = item.priority === "MVP" ? chalk33.magenta(" [MVP]") : "";
|
|
10231
|
+
console.log(` ${color("\u2022")} ${chalk33.bold(id)} ${item.title}${priority}`);
|
|
10018
10232
|
});
|
|
10019
10233
|
}
|
|
10020
10234
|
|
|
10021
10235
|
// src/commands/council.ts
|
|
10022
10236
|
init_esm_shims();
|
|
10023
10237
|
init_config();
|
|
10024
|
-
import { Command as
|
|
10025
|
-
import
|
|
10026
|
-
import
|
|
10027
|
-
import
|
|
10238
|
+
import { Command as Command23 } from "commander";
|
|
10239
|
+
import chalk34 from "chalk";
|
|
10240
|
+
import ora16 from "ora";
|
|
10241
|
+
import inquirer7 from "inquirer";
|
|
10028
10242
|
function createCouncilCommand() {
|
|
10029
|
-
return new
|
|
10030
|
-
const spinner =
|
|
10243
|
+
return new Command23("council").description("Trigger a multi-agent debate regarding a strategic decision").argument("[topic]", "The strategic topic or decision to debate").action(async (topic) => {
|
|
10244
|
+
const spinner = ora16();
|
|
10031
10245
|
try {
|
|
10032
10246
|
const apiKey = getApiKey();
|
|
10033
10247
|
const apiUrl = getApiUrl();
|
|
10034
10248
|
const projectId = getProjectId();
|
|
10035
10249
|
if (!projectId) {
|
|
10036
|
-
console.error(
|
|
10250
|
+
console.error(chalk34.red('Project context missing. Run "rigstate link".'));
|
|
10037
10251
|
return;
|
|
10038
10252
|
}
|
|
10039
10253
|
let sessionTopic = topic;
|
|
10040
10254
|
if (!sessionTopic) {
|
|
10041
|
-
const ans = await
|
|
10255
|
+
const ans = await inquirer7.prompt([{
|
|
10042
10256
|
type: "input",
|
|
10043
10257
|
name: "topic",
|
|
10044
10258
|
message: "What strategic decision shall the Council debate?"
|
|
10045
10259
|
}]);
|
|
10046
10260
|
sessionTopic = ans.topic;
|
|
10047
10261
|
}
|
|
10048
|
-
console.log(
|
|
10049
|
-
console.log(
|
|
10050
|
-
console.log(
|
|
10051
|
-
console.log(
|
|
10262
|
+
console.log(chalk34.bold.magenta("\n\u2696\uFE0F CONVENING THE COUNCIL OF SOVEREIGNTY\n"));
|
|
10263
|
+
console.log(chalk34.dim(`Topic: ${sessionTopic}`));
|
|
10264
|
+
console.log(chalk34.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
10265
|
+
console.log(chalk34.yellow("\n\u{1F9E0} Frank (Architect): Analyzing alignment with Project DNA..."));
|
|
10052
10266
|
await sleep(1500);
|
|
10053
|
-
console.log(
|
|
10054
|
-
console.log(
|
|
10267
|
+
console.log(chalk34.gray(' "This decision affects our backend scalability. I recommend caution."'));
|
|
10268
|
+
console.log(chalk34.blue("\n\u{1F6E1}\uFE0F Sigrid (Curator): Checking historical precedents..."));
|
|
10055
10269
|
await sleep(1500);
|
|
10056
|
-
console.log(
|
|
10057
|
-
console.log(
|
|
10270
|
+
console.log(chalk34.gray(` "Similar patterns in other projects led to technical debt. Let's review RLS."`));
|
|
10271
|
+
console.log(chalk34.green("\n\u{1F4D0} Einar (Analyst): Scanning dependency impact..."));
|
|
10058
10272
|
await sleep(1500);
|
|
10059
|
-
console.log(
|
|
10060
|
-
console.log(
|
|
10061
|
-
console.log(
|
|
10062
|
-
console.log(
|
|
10063
|
-
console.log(
|
|
10064
|
-
console.log(
|
|
10273
|
+
console.log(chalk34.gray(' "Implementation will require updating 3 core services."'));
|
|
10274
|
+
console.log(chalk34.bold.white("\n\u{1F4CB} [FINAL DECISION RECORD]"));
|
|
10275
|
+
console.log(chalk34.white(" Status: Approved with conditions"));
|
|
10276
|
+
console.log(chalk34.white(" Rationale: Value outweighs migration cost. Ensure SEC-SQL-01 compliance."));
|
|
10277
|
+
console.log(chalk34.dim("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
10278
|
+
console.log(chalk34.green("\u2705 Decision saved to Project Brain (ADR-102)"));
|
|
10065
10279
|
} catch (e) {
|
|
10066
|
-
console.error(
|
|
10280
|
+
console.error(chalk34.red(`
|
|
10067
10281
|
Council session aborted: ${e.message}`));
|
|
10068
10282
|
}
|
|
10069
10283
|
});
|
|
@@ -10081,7 +10295,7 @@ async function checkVersion() {
|
|
|
10081
10295
|
import dotenv from "dotenv";
|
|
10082
10296
|
var pkg = require_package();
|
|
10083
10297
|
dotenv.config();
|
|
10084
|
-
var program = new
|
|
10298
|
+
var program = new Command24();
|
|
10085
10299
|
program.name("rigstate").description("CLI for Rigstate - The AI-Native Dev Studio").version(pkg.version);
|
|
10086
10300
|
program.addCommand(createLoginCommand());
|
|
10087
10301
|
program.addCommand(createLinkCommand());
|
|
@@ -10104,25 +10318,27 @@ program.addCommand(createOverrideCommand());
|
|
|
10104
10318
|
program.addCommand(createIdeaCommand());
|
|
10105
10319
|
program.addCommand(createReleaseCommand());
|
|
10106
10320
|
program.addCommand(createRoadmapCommand());
|
|
10321
|
+
program.addCommand(createRoadmapCommand());
|
|
10107
10322
|
program.addCommand(createCouncilCommand());
|
|
10323
|
+
program.addCommand(createPlanCommand());
|
|
10108
10324
|
program.hook("preAction", async () => {
|
|
10109
10325
|
await checkVersion();
|
|
10110
10326
|
});
|
|
10111
10327
|
program.on("--help", () => {
|
|
10112
10328
|
console.log("");
|
|
10113
|
-
console.log(
|
|
10329
|
+
console.log(chalk35.bold("Examples:"));
|
|
10114
10330
|
console.log("");
|
|
10115
|
-
console.log(
|
|
10116
|
-
console.log(
|
|
10331
|
+
console.log(chalk35.cyan(" $ rigstate login sk_rigstate_your_api_key"));
|
|
10332
|
+
console.log(chalk35.dim(" Authenticate with your Rigstate API key"));
|
|
10117
10333
|
console.log("");
|
|
10118
|
-
console.log(
|
|
10119
|
-
console.log(
|
|
10334
|
+
console.log(chalk35.cyan(" $ rigstate scan"));
|
|
10335
|
+
console.log(chalk35.dim(" Scan the current directory"));
|
|
10120
10336
|
console.log("");
|
|
10121
|
-
console.log(
|
|
10122
|
-
console.log(
|
|
10337
|
+
console.log(chalk35.cyan(" $ rigstate scan ./src --project abc123"));
|
|
10338
|
+
console.log(chalk35.dim(" Scan a specific directory with project ID"));
|
|
10123
10339
|
console.log("");
|
|
10124
|
-
console.log(
|
|
10125
|
-
console.log(
|
|
10340
|
+
console.log(chalk35.cyan(" $ rigstate scan --json"));
|
|
10341
|
+
console.log(chalk35.dim(" Output results in JSON format (useful for IDE extensions)"));
|
|
10126
10342
|
console.log("");
|
|
10127
10343
|
});
|
|
10128
10344
|
program.parse(process.argv);
|