@rigstate/cli 0.7.37 → 0.7.39

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.js CHANGED
@@ -390,19 +390,19 @@ async function syncProjectRules(projectId, apiKey, apiUrl, dryRun = false, versi
390
390
  }
391
391
  const files = syncResponse.data.data.files;
392
392
  if (files && Array.isArray(files)) {
393
- const fs26 = await import("fs/promises");
394
- const path29 = await import("path");
393
+ const fs27 = await import("fs/promises");
394
+ const path30 = await import("path");
395
395
  for (const file of files) {
396
- const filePath = path29.join(process.cwd(), file.path);
397
- await fs26.mkdir(path29.dirname(filePath), { recursive: true });
398
- await fs26.writeFile(filePath, file.content, "utf-8");
396
+ const filePath = path30.join(process.cwd(), file.path);
397
+ await fs27.mkdir(path30.dirname(filePath), { recursive: true });
398
+ await fs27.writeFile(filePath, file.content, "utf-8");
399
399
  }
400
400
  console.log(chalk4.dim(` \u{1F4BE} Wrote ${files.length} rule files to local .cursor/rules/`));
401
401
  try {
402
- const masterPath = path29.join(process.cwd(), ".cursorrules");
402
+ const masterPath = path30.join(process.cwd(), ".cursorrules");
403
403
  let masterContent = "";
404
404
  try {
405
- masterContent = await fs26.readFile(masterPath, "utf-8");
405
+ masterContent = await fs27.readFile(masterPath, "utf-8");
406
406
  } catch {
407
407
  masterContent = "";
408
408
  }
@@ -431,7 +431,7 @@ ${END_MARKER}`;
431
431
 
432
432
  ${governanceBlock}` : governanceBlock;
433
433
  }
434
- await fs26.writeFile(masterPath, newContent, "utf-8");
434
+ await fs27.writeFile(masterPath, newContent, "utf-8");
435
435
  console.log(chalk4.dim(" \u{1F4DC} Updated master .cursorrules (Constitution enforced)"));
436
436
  } catch (e) {
437
437
  console.warn(chalk4.yellow(` \u26A0\uFE0F Could not update .cursorrules: ${e.message}`));
@@ -490,7 +490,7 @@ import chalk5 from "chalk";
490
490
  import ora3 from "ora";
491
491
  import axios3 from "axios";
492
492
  function createGenesisCommand() {
493
- return new Command4("genesis").description("Initialize project foundation (Phase 0). Detects stack and injects foundation steps.").option("--force", "Re-run genesis even if already initialized (use with caution)").option("--status", "Check genesis status without triggering").option("--project-id <id>", "Override project ID (defaults to linked project)").action(async (options) => {
493
+ return new Command4("genesis").description("Initialize project foundation (Phase 0). Detects stack and injects foundation steps.").option("--force", "Re-run genesis even if already initialized (use with caution)").option("--simulate", "Dry-run: Calculate plan without modifying database").option("--status", "Check genesis status without triggering").option("--project-id <id>", "Override project ID (defaults to linked project)").action(async (options) => {
494
494
  const apiKey = getApiKey();
495
495
  const apiUrl = getApiUrl();
496
496
  const projectId = options.projectId || getProjectId();
@@ -505,7 +505,7 @@ function createGenesisCommand() {
505
505
  if (options.status) {
506
506
  await checkGenesisStatus(projectId, apiKey, apiUrl);
507
507
  } else {
508
- await triggerGenesis(projectId, apiKey, apiUrl, options.force ?? false);
508
+ await triggerGenesis(projectId, apiKey, apiUrl, options.force ?? false, options.simulate ?? false);
509
509
  }
510
510
  });
511
511
  }
@@ -565,10 +565,15 @@ async function checkGenesisStatus(projectId, apiKey, apiUrl) {
565
565
  return { complete: false, stepCount: 0 };
566
566
  }
567
567
  }
568
- async function triggerGenesis(projectId, apiKey, apiUrl, force = false) {
568
+ async function triggerGenesis(projectId, apiKey, apiUrl, force = false, simulate = false) {
569
569
  console.log("");
570
- console.log(chalk5.bold.blue("\u{1F3D7}\uFE0F GENESIS PROTOCOL"));
571
- console.log(chalk5.dim("Initializing project foundation..."));
570
+ if (simulate) {
571
+ console.log(chalk5.bold.magenta("\u{1F52E} GENESIS SIMULATION"));
572
+ console.log(chalk5.dim("Dry-run: Calculating plan without executing changes..."));
573
+ } else {
574
+ console.log(chalk5.bold.blue("\u{1F3D7}\uFE0F GENESIS PROTOCOL"));
575
+ console.log(chalk5.dim("Initializing project foundation..."));
576
+ }
572
577
  console.log("");
573
578
  const spinner = ora3("Detecting tech stack...").start();
574
579
  try {
@@ -597,7 +602,7 @@ async function triggerGenesis(projectId, apiKey, apiUrl, force = false) {
597
602
  }
598
603
  const response = await axios3.post(
599
604
  `${apiUrl}/api/v1/genesis`,
600
- { project_id: projectId, force },
605
+ { project_id: projectId, force, simulate },
601
606
  {
602
607
  headers: { Authorization: `Bearer ${apiKey}` },
603
608
  timeout: 6e4
@@ -622,6 +627,28 @@ async function triggerGenesis(projectId, apiKey, apiUrl, force = false) {
622
627
  return false;
623
628
  }
624
629
  const { data } = response.data;
630
+ if (response.data.simulation) {
631
+ console.log(chalk5.bold.magenta("\u{1F52E} SIMULATION RESULTS"));
632
+ console.log(chalk5.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"));
633
+ console.log(`${chalk5.bold("Project:")} ${chalk5.cyan(data.project_name)}`);
634
+ console.log(`${chalk5.bold("Stack:")} ${chalk5.magenta(data.template)}`);
635
+ console.log(`${chalk5.bold("Will Create:")} ${chalk5.white(data.steps_created)} foundation steps`);
636
+ if (data.existing_steps_shifted > 0) {
637
+ console.log(`${chalk5.bold("Will Shift:")} ${chalk5.yellow(`${data.existing_steps_shifted} existing steps down`)}`);
638
+ }
639
+ console.log("");
640
+ console.log(chalk5.bold("\u{1F4CB} Planner Preview:"));
641
+ data.steps.forEach((step) => {
642
+ const stepNum = step.step_number;
643
+ console.log(` ${step.icon || "\u{1F539}"} ${chalk5.bold(`T-${stepNum}`)}: ${step.title}`);
644
+ if (step.verification_path) {
645
+ console.log(` ${chalk5.dim(`Verify: ${step.verification_path}`)}`);
646
+ }
647
+ });
648
+ console.log("");
649
+ console.log(chalk5.dim("To execute this plan, run without --simulate."));
650
+ return true;
651
+ }
625
652
  console.log(chalk5.bold.green("\u2705 GENESIS COMPLETE"));
626
653
  console.log(chalk5.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"));
627
654
  console.log(`${chalk5.bold("Project:")} ${chalk5.cyan(data.project_name)}`);
@@ -1104,7 +1131,7 @@ var require_package = __commonJS({
1104
1131
  "package.json"(exports, module) {
1105
1132
  module.exports = {
1106
1133
  name: "@rigstate/cli",
1107
- version: "0.7.37",
1134
+ version: "0.7.38",
1108
1135
  description: "Rigstate CLI - Code audit, sync and supervision tool",
1109
1136
  type: "module",
1110
1137
  main: "./dist/index.js",
@@ -1161,8 +1188,8 @@ var require_package = __commonJS({
1161
1188
 
1162
1189
  // src/index.ts
1163
1190
  init_esm_shims();
1164
- import { Command as Command25 } from "commander";
1165
- import chalk37 from "chalk";
1191
+ import { Command as Command27 } from "commander";
1192
+ import chalk39 from "chalk";
1166
1193
 
1167
1194
  // src/commands/login.ts
1168
1195
  init_esm_shims();
@@ -1330,9 +1357,9 @@ function createLinkCommand() {
1330
1357
  });
1331
1358
  }
1332
1359
  async function hardenGitIgnore(cwd) {
1333
- const fs26 = await import("fs/promises");
1334
- const path29 = await import("path");
1335
- const ignorePath = path29.join(cwd, ".gitignore");
1360
+ const fs27 = await import("fs/promises");
1361
+ const path30 = await import("path");
1362
+ const ignorePath = path30.join(cwd, ".gitignore");
1336
1363
  const REQUIRED_IGNORES = [
1337
1364
  "# Rigstate - Runtime Artifacts (Do not commit)",
1338
1365
  ".rigstate/ACTIVE_VIOLATIONS.md",
@@ -1347,7 +1374,7 @@ async function hardenGitIgnore(cwd) {
1347
1374
  try {
1348
1375
  let content = "";
1349
1376
  try {
1350
- content = await fs26.readFile(ignorePath, "utf-8");
1377
+ content = await fs27.readFile(ignorePath, "utf-8");
1351
1378
  } catch {
1352
1379
  content = "";
1353
1380
  }
@@ -1355,7 +1382,7 @@ async function hardenGitIgnore(cwd) {
1355
1382
  if (missing.length > 0) {
1356
1383
  console.log(chalk7.dim(" Configuring .gitignore for Rigstate safety..."));
1357
1384
  const toAppend = "\n\n" + REQUIRED_IGNORES.join("\n") + "\n";
1358
- await fs26.writeFile(ignorePath, content + toAppend, "utf-8");
1385
+ await fs27.writeFile(ignorePath, content + toAppend, "utf-8");
1359
1386
  console.log(chalk7.green(" \u2714 .gitignore updated (Artifacts protected)"));
1360
1387
  } else {
1361
1388
  console.log(chalk7.green(" \u2714 .gitignore already hardened"));
@@ -1365,21 +1392,21 @@ async function hardenGitIgnore(cwd) {
1365
1392
  }
1366
1393
  }
1367
1394
  async function installHooks(cwd) {
1368
- const fs26 = await import("fs/promises");
1369
- const path29 = await import("path");
1395
+ const fs27 = await import("fs/promises");
1396
+ const path30 = await import("path");
1370
1397
  try {
1371
- await fs26.access(path29.join(cwd, ".git"));
1398
+ await fs27.access(path30.join(cwd, ".git"));
1372
1399
  } catch {
1373
1400
  console.log(chalk7.dim(" (Not a git repository, skipping hooks)"));
1374
1401
  return;
1375
1402
  }
1376
- const hooksDir = path29.join(cwd, ".husky");
1403
+ const hooksDir = path30.join(cwd, ".husky");
1377
1404
  try {
1378
- const preCommitPath = path29.join(cwd, ".git/hooks/pre-commit");
1405
+ const preCommitPath = path30.join(cwd, ".git/hooks/pre-commit");
1379
1406
  let shouldInstall = false;
1380
1407
  try {
1381
- await fs26.access(preCommitPath);
1382
- const content = await fs26.readFile(preCommitPath, "utf-8");
1408
+ await fs27.access(preCommitPath);
1409
+ const content = await fs27.readFile(preCommitPath, "utf-8");
1383
1410
  if (content.includes("rigstate")) {
1384
1411
  console.log(chalk7.green(" \u2714 Git hooks already active"));
1385
1412
  } else {
@@ -1403,12 +1430,12 @@ echo "\u{1F6E1}\uFE0F Running Guardian checks..."
1403
1430
  rigstate check --staged --strict=critical
1404
1431
  exit $?
1405
1432
  `;
1406
- await fs26.mkdir(path29.dirname(preCommitPath), { recursive: true });
1433
+ await fs27.mkdir(path30.dirname(preCommitPath), { recursive: true });
1407
1434
  if (await fileExists(preCommitPath)) {
1408
- const existing = await fs26.readFile(preCommitPath, "utf-8");
1409
- await fs26.writeFile(preCommitPath, existing + "\n\n" + PRE_COMMIT_SCRIPT2.replace("#!/bin/sh\n", ""), { mode: 493 });
1435
+ const existing = await fs27.readFile(preCommitPath, "utf-8");
1436
+ await fs27.writeFile(preCommitPath, existing + "\n\n" + PRE_COMMIT_SCRIPT2.replace("#!/bin/sh\n", ""), { mode: 493 });
1410
1437
  } else {
1411
- await fs26.writeFile(preCommitPath, PRE_COMMIT_SCRIPT2, { mode: 493 });
1438
+ await fs27.writeFile(preCommitPath, PRE_COMMIT_SCRIPT2, { mode: 493 });
1412
1439
  }
1413
1440
  console.log(chalk7.green(" \u2714 Applied Guardian protection (git-hooks)"));
1414
1441
  }
@@ -1416,10 +1443,10 @@ exit $?
1416
1443
  console.log(chalk7.dim(" (Skipped hooks: " + e.message + ")"));
1417
1444
  }
1418
1445
  }
1419
- async function fileExists(path29) {
1420
- const fs26 = await import("fs/promises");
1446
+ async function fileExists(path30) {
1447
+ const fs27 = await import("fs/promises");
1421
1448
  try {
1422
- await fs26.access(path29);
1449
+ await fs27.access(path30);
1423
1450
  return true;
1424
1451
  } catch {
1425
1452
  return false;
@@ -3469,7 +3496,7 @@ var KnowledgeHarvester = class extends EventEmitter3 {
3469
3496
  pollInterval: 100
3470
3497
  }
3471
3498
  });
3472
- this.watcher.on("add", (path29) => this.handleFileEvent(path29, "add")).on("change", (path29) => this.handleFileEvent(path29, "change"));
3499
+ this.watcher.on("add", (path30) => this.handleFileEvent(path30, "add")).on("change", (path30) => this.handleFileEvent(path30, "change"));
3473
3500
  this.isReady = true;
3474
3501
  }
3475
3502
  async stop() {
@@ -3661,7 +3688,7 @@ var GuardianDaemon = class extends EventEmitter4 {
3661
3688
  setupFileWatcher() {
3662
3689
  Logger.info("Starting file watcher...");
3663
3690
  this.fileWatcher = createFileWatcher(this.config.watchPath);
3664
- this.fileWatcher.on("change", (path29) => this.handleFileChange(path29));
3691
+ this.fileWatcher.on("change", (path30) => this.handleFileChange(path30));
3665
3692
  this.fileWatcher.start();
3666
3693
  Logger.info("File watcher active");
3667
3694
  }
@@ -5364,16 +5391,310 @@ Council session aborted: ${e.message}`));
5364
5391
  });
5365
5392
  }
5366
5393
  function sleep(ms) {
5367
- return new Promise((resolve) => setTimeout(resolve, ms));
5394
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
5368
5395
  }
5369
5396
 
5370
5397
  // src/index.ts
5371
5398
  init_genesis();
5399
+
5400
+ // src/commands/remember.ts
5401
+ init_esm_shims();
5402
+ import { Command as Command25 } from "commander";
5403
+ import chalk37 from "chalk";
5404
+
5405
+ // src/utils/memory-store.ts
5406
+ init_esm_shims();
5407
+ import * as fs26 from "fs";
5408
+ import * as path29 from "path";
5409
+ import { randomUUID } from "crypto";
5410
+ var MEMORIES_DIR = ".rigstate/memories";
5411
+ function getMemoriesDir() {
5412
+ const dir = path29.resolve(process.cwd(), MEMORIES_DIR);
5413
+ if (!fs26.existsSync(dir)) {
5414
+ fs26.mkdirSync(dir, { recursive: true });
5415
+ }
5416
+ return dir;
5417
+ }
5418
+ function saveMemory(input) {
5419
+ const dir = getMemoriesDir();
5420
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5421
+ const memory = {
5422
+ id: randomUUID(),
5423
+ ...input,
5424
+ title: input.title,
5425
+ content: input.content,
5426
+ category: input.category || "CONTEXT",
5427
+ source: input.source || "USER",
5428
+ tags: input.tags || [],
5429
+ importance: input.importance || 5,
5430
+ confidence: input.confidence || 1,
5431
+ created_at: now,
5432
+ updated_at: now,
5433
+ expires_at: input.expires_at || null
5434
+ };
5435
+ const filename = `${memory.id}.json`;
5436
+ const filepath = path29.join(dir, filename);
5437
+ fs26.writeFileSync(filepath, JSON.stringify(memory, null, 2), "utf-8");
5438
+ return memory;
5439
+ }
5440
+ function loadAllMemories() {
5441
+ const dir = getMemoriesDir();
5442
+ const files = fs26.readdirSync(dir).filter((f) => f.endsWith(".json"));
5443
+ const memories = [];
5444
+ for (const file of files) {
5445
+ try {
5446
+ const raw = fs26.readFileSync(path29.join(dir, file), "utf-8");
5447
+ memories.push(JSON.parse(raw));
5448
+ } catch {
5449
+ }
5450
+ }
5451
+ return memories;
5452
+ }
5453
+ function searchMemories(query, limit = 5) {
5454
+ const memories = loadAllMemories();
5455
+ const tokens = tokenize(query);
5456
+ if (tokens.length === 0) return [];
5457
+ const results = [];
5458
+ for (const memory of memories) {
5459
+ if (memory.expires_at && new Date(memory.expires_at) < /* @__PURE__ */ new Date()) {
5460
+ continue;
5461
+ }
5462
+ let score = 0;
5463
+ const matchedFields = [];
5464
+ const titleTokens = tokenize(memory.title);
5465
+ const titleMatches = tokens.filter((t) => titleTokens.includes(t)).length;
5466
+ if (titleMatches > 0) {
5467
+ score += titleMatches * 3;
5468
+ matchedFields.push("title");
5469
+ }
5470
+ const contentLower = memory.content.toLowerCase();
5471
+ const contentMatches = tokens.filter((t) => contentLower.includes(t)).length;
5472
+ if (contentMatches > 0) {
5473
+ score += contentMatches * 1;
5474
+ matchedFields.push("content");
5475
+ }
5476
+ const tagLower = memory.tags.map((t) => t.toLowerCase());
5477
+ const tagMatches = tokens.filter((t) => tagLower.includes(t)).length;
5478
+ if (tagMatches > 0) {
5479
+ score += tagMatches * 4;
5480
+ matchedFields.push("tags");
5481
+ }
5482
+ if (tokens.includes(memory.category.toLowerCase())) {
5483
+ score += 2;
5484
+ matchedFields.push("category");
5485
+ }
5486
+ score *= memory.importance / 5;
5487
+ if (score > 0) {
5488
+ results.push({ memory, score, matchedFields });
5489
+ }
5490
+ }
5491
+ return results.sort((a, b) => b.score - a.score).slice(0, limit);
5492
+ }
5493
+ function getMemoryStats() {
5494
+ const memories = loadAllMemories();
5495
+ const byCategory = {};
5496
+ for (const m of memories) {
5497
+ byCategory[m.category] = (byCategory[m.category] || 0) + 1;
5498
+ }
5499
+ return { total: memories.length, byCategory };
5500
+ }
5501
+ var STOP_WORDS = /* @__PURE__ */ new Set([
5502
+ "the",
5503
+ "a",
5504
+ "an",
5505
+ "is",
5506
+ "are",
5507
+ "was",
5508
+ "were",
5509
+ "in",
5510
+ "on",
5511
+ "at",
5512
+ "to",
5513
+ "for",
5514
+ "of",
5515
+ "with",
5516
+ "by",
5517
+ "from",
5518
+ "and",
5519
+ "or",
5520
+ "not",
5521
+ "this",
5522
+ "that",
5523
+ "it",
5524
+ "we",
5525
+ "you",
5526
+ "they",
5527
+ "my",
5528
+ "our",
5529
+ "your",
5530
+ "its",
5531
+ "his",
5532
+ "her",
5533
+ "how",
5534
+ "what",
5535
+ "why",
5536
+ "when",
5537
+ "where",
5538
+ "which",
5539
+ "who",
5540
+ "do",
5541
+ "does",
5542
+ "did",
5543
+ "has",
5544
+ "have",
5545
+ "had",
5546
+ "be",
5547
+ "been",
5548
+ "being",
5549
+ "will",
5550
+ "would",
5551
+ "can",
5552
+ "could",
5553
+ "should",
5554
+ "shall",
5555
+ "may",
5556
+ "might",
5557
+ "must",
5558
+ "vi",
5559
+ "er",
5560
+ "var",
5561
+ "har",
5562
+ "den",
5563
+ "det",
5564
+ "en",
5565
+ "et",
5566
+ "og",
5567
+ "i",
5568
+ "p\xE5",
5569
+ "til",
5570
+ "fra",
5571
+ "med",
5572
+ "som",
5573
+ "om",
5574
+ "for",
5575
+ "av",
5576
+ "ikke",
5577
+ "hvorfor",
5578
+ "hvordan",
5579
+ "hva",
5580
+ "n\xE5r",
5581
+ "hvor"
5582
+ ]);
5583
+ function tokenize(text) {
5584
+ return text.toLowerCase().replace(/[^a-zA-Z0-9æøåÆØÅ\s]/g, " ").split(/\s+/).filter((t) => t.length > 1 && !STOP_WORDS.has(t));
5585
+ }
5586
+
5587
+ // src/commands/remember.ts
5588
+ init_config();
5589
+ function createRememberCommand() {
5590
+ return new Command25("remember").description("Save a memory to the local knowledge base (.rigstate/memories/)").argument("<text>", "The memory content to save").option("-t, --title <title>", "Title for the memory (defaults to first 60 chars of text)").option("-c, --category <category>", "Category: ADR, DECISION, LESSON, CONTEXT, INSTRUCTION, PATTERN, GOTCHA", "CONTEXT").option("--tags <tags>", 'Comma-separated tags (e.g. "supabase,architecture")').option("-i, --importance <n>", "Importance 1-10 (default: 5)", "5").option("--source <source>", "Source: USER, AGENT, COUNCIL, GOVERNANCE, HARVEST, IMPORT", "USER").action(async (text, options) => {
5591
+ try {
5592
+ const projectId = getProjectId();
5593
+ const title = options.title || text.substring(0, 60) + (text.length > 60 ? "..." : "");
5594
+ const tags = options.tags ? options.tags.split(",").map((t) => t.trim()) : [];
5595
+ const importance = Math.min(10, Math.max(1, parseInt(options.importance, 10) || 5));
5596
+ const memory = saveMemory({
5597
+ title,
5598
+ content: text,
5599
+ category: options.category || "CONTEXT",
5600
+ source: options.source || "USER",
5601
+ tags,
5602
+ importance,
5603
+ project_id: projectId || void 0
5604
+ });
5605
+ console.log("");
5606
+ console.log(chalk37.bold.green("\u{1F9E0} Memory Saved"));
5607
+ console.log(chalk37.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"));
5608
+ console.log(`${chalk37.bold("ID:")} ${chalk37.dim(memory.id)}`);
5609
+ console.log(`${chalk37.bold("Title:")} ${chalk37.cyan(memory.title)}`);
5610
+ console.log(`${chalk37.bold("Category:")} ${chalk37.magenta(memory.category)}`);
5611
+ console.log(`${chalk37.bold("Importance:")} ${"\u2B50".repeat(Math.min(5, Math.ceil(importance / 2)))} (${importance}/10)`);
5612
+ if (tags.length > 0) {
5613
+ console.log(`${chalk37.bold("Tags:")} ${tags.map((t) => chalk37.yellow(`#${t}`)).join(" ")}`);
5614
+ }
5615
+ console.log(chalk37.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"));
5616
+ const stats = getMemoryStats();
5617
+ console.log(chalk37.dim(`Total memories: ${stats.total}`));
5618
+ console.log("");
5619
+ } catch (err) {
5620
+ console.error(chalk37.red(`\u274C Failed to save memory: ${err.message}`));
5621
+ process.exit(1);
5622
+ }
5623
+ });
5624
+ }
5625
+
5626
+ // src/commands/ask.ts
5627
+ init_esm_shims();
5628
+ import { Command as Command26 } from "commander";
5629
+ import chalk38 from "chalk";
5630
+ function createAskCommand() {
5631
+ return new Command26("ask").description("Search local memories instantly (<10ms, offline)").argument("<query>", "Natural language query to search memories").option("-n, --limit <n>", "Maximum results to return", "5").action(async (query, options) => {
5632
+ const limit = parseInt(options.limit, 10) || 5;
5633
+ const startTime = performance.now();
5634
+ const results = searchMemories(query, limit);
5635
+ const elapsed = (performance.now() - startTime).toFixed(1);
5636
+ console.log("");
5637
+ if (results.length === 0) {
5638
+ const stats2 = getMemoryStats();
5639
+ console.log(chalk38.yellow(`\u{1F50D} No memories found for: "${query}"`));
5640
+ console.log(chalk38.dim(` Searched ${stats2.total} memories in ${elapsed}ms.`));
5641
+ if (stats2.total === 0) {
5642
+ console.log("");
5643
+ console.log(chalk38.dim(" No memories yet. Start with:"));
5644
+ console.log(chalk38.white(' rigstate remember "We chose Supabase for real-time and RLS"'));
5645
+ }
5646
+ console.log("");
5647
+ return;
5648
+ }
5649
+ console.log(chalk38.bold(`\u{1F9E0} ${results.length} memor${results.length === 1 ? "y" : "ies"} found`) + chalk38.dim(` (${elapsed}ms)`));
5650
+ console.log(chalk38.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"));
5651
+ for (const { memory, score, matchedFields } of results) {
5652
+ const categoryColor = getCategoryColor(memory.category);
5653
+ const stars = "\u2B50".repeat(Math.min(5, Math.ceil((memory.importance || 5) / 2)));
5654
+ console.log("");
5655
+ console.log(` ${categoryColor(memory.category)} ${chalk38.bold(memory.title)} ${chalk38.dim(`[${stars}]`)}`);
5656
+ const preview = memory.content.length > 120 ? memory.content.substring(0, 120) + "..." : memory.content;
5657
+ console.log(` ${chalk38.white(preview)}`);
5658
+ if (memory.tags && memory.tags.length > 0) {
5659
+ console.log(` ${memory.tags.map((t) => chalk38.yellow(`#${t}`)).join(" ")}`);
5660
+ }
5661
+ const meta = [
5662
+ chalk38.dim(`score:${score.toFixed(1)}`),
5663
+ chalk38.dim(`matched:${matchedFields.join(",")}`),
5664
+ chalk38.dim(`source:${memory.source}`)
5665
+ ];
5666
+ if (memory.created_at) {
5667
+ const date = new Date(memory.created_at).toLocaleDateString("nb-NO");
5668
+ meta.push(chalk38.dim(`date:${date}`));
5669
+ }
5670
+ console.log(` ${meta.join(" ")}`);
5671
+ }
5672
+ console.log("");
5673
+ console.log(chalk38.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"));
5674
+ const stats = getMemoryStats();
5675
+ console.log(chalk38.dim(`Searched ${stats.total} memories in ${elapsed}ms`));
5676
+ console.log("");
5677
+ });
5678
+ }
5679
+ function getCategoryColor(category) {
5680
+ const colors = {
5681
+ "ADR": chalk38.bgBlue.white,
5682
+ "DECISION": chalk38.bgCyan.black,
5683
+ "LESSON": chalk38.bgYellow.black,
5684
+ "CONTEXT": chalk38.bgGreen.black,
5685
+ "INSTRUCTION": chalk38.bgMagenta.white,
5686
+ "PATTERN": chalk38.bgWhite.black,
5687
+ "GOTCHA": chalk38.bgRed.white
5688
+ };
5689
+ return colors[category] || chalk38.dim;
5690
+ }
5691
+
5692
+ // src/index.ts
5372
5693
  init_version();
5373
5694
  import dotenv from "dotenv";
5374
5695
  var pkg = require_package();
5375
5696
  dotenv.config();
5376
- var program = new Command25();
5697
+ var program = new Command27();
5377
5698
  program.name("rigstate").description("CLI for Rigstate - The AI-Native Dev Studio").version(pkg.version);
5378
5699
  program.addCommand(createLoginCommand());
5379
5700
  program.addCommand(createLinkCommand());
@@ -5399,30 +5720,32 @@ program.addCommand(createRoadmapCommand());
5399
5720
  program.addCommand(createCouncilCommand());
5400
5721
  program.addCommand(createPlanCommand());
5401
5722
  program.addCommand(createGenesisCommand());
5723
+ program.addCommand(createRememberCommand());
5724
+ program.addCommand(createAskCommand());
5402
5725
  program.hook("preAction", async () => {
5403
5726
  await checkVersion();
5404
5727
  });
5405
5728
  program.on("--help", () => {
5406
5729
  console.log("");
5407
- console.log(chalk37.bold("Examples:"));
5730
+ console.log(chalk39.bold("Examples:"));
5408
5731
  console.log("");
5409
- console.log(chalk37.cyan(" $ rigstate login sk_rigstate_your_api_key"));
5410
- console.log(chalk37.dim(" Authenticate with your Rigstate API key"));
5732
+ console.log(chalk39.cyan(" $ rigstate login sk_rigstate_your_api_key"));
5733
+ console.log(chalk39.dim(" Authenticate with your Rigstate API key"));
5411
5734
  console.log("");
5412
- console.log(chalk37.cyan(" $ rigstate scan"));
5413
- console.log(chalk37.dim(" Scan the current directory"));
5735
+ console.log(chalk39.cyan(" $ rigstate scan"));
5736
+ console.log(chalk39.dim(" Scan the current directory"));
5414
5737
  console.log("");
5415
- console.log(chalk37.cyan(" $ rigstate genesis"));
5416
- console.log(chalk37.dim(" Initialize project foundation (auto-detects stack)"));
5738
+ console.log(chalk39.cyan(" $ rigstate genesis"));
5739
+ console.log(chalk39.dim(" Initialize project foundation (auto-detects stack)"));
5417
5740
  console.log("");
5418
- console.log(chalk37.cyan(" $ rigstate genesis --status"));
5419
- console.log(chalk37.dim(" Check genesis status without triggering"));
5741
+ console.log(chalk39.cyan(" $ rigstate genesis --status"));
5742
+ console.log(chalk39.dim(" Check genesis status without triggering"));
5420
5743
  console.log("");
5421
- console.log(chalk37.cyan(" $ rigstate scan ./src --project abc123"));
5422
- console.log(chalk37.dim(" Scan a specific directory with project ID"));
5744
+ console.log(chalk39.cyan(" $ rigstate scan ./src --project abc123"));
5745
+ console.log(chalk39.dim(" Scan a specific directory with project ID"));
5423
5746
  console.log("");
5424
- console.log(chalk37.cyan(" $ rigstate scan --json"));
5425
- console.log(chalk37.dim(" Output results in JSON format (useful for IDE extensions)"));
5747
+ console.log(chalk39.cyan(" $ rigstate scan --json"));
5748
+ console.log(chalk39.dim(" Output results in JSON format (useful for IDE extensions)"));
5426
5749
  console.log("");
5427
5750
  });
5428
5751
  program.parse(process.argv);