@shahmilsaari/memory-core 1.0.32 → 1.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +8 -6
  2. package/dist/{approval-queue-YBYRGBHP.js → approval-queue-4RK46FNE.js} +2 -1
  3. package/dist/{ast-analyzer-JM4CIOFY.js → ast-analyzer-WGTJKGAP.js} +1 -0
  4. package/dist/{check-cache-6NWRTZJD.js → check-cache-ZVFHTA2C.js} +1 -0
  5. package/dist/{check-logger-5HYSWA3S.js → check-logger-F4DW4LBY.js} +1 -0
  6. package/dist/chunk-2LNDQGDD.js +37 -0
  7. package/dist/{chunk-23GUWJ6F.js → chunk-4QWIYO2G.js} +3071 -3271
  8. package/dist/{chunk-GIPKVQSA.js → chunk-5T2QBBYT.js} +3 -29
  9. package/dist/chunk-FPRSYCOZ.js +77 -0
  10. package/dist/chunk-HJCPBM7B.js +238 -0
  11. package/dist/chunk-K3NQKI34.js +10 -0
  12. package/dist/chunk-SKR44CRD.js +35 -0
  13. package/dist/{chunk-W6WEAV3S.js → chunk-UMYJQWIE.js} +13 -11
  14. package/dist/{chunk-PQBWHAZN.js → chunk-XAE3RY5D.js} +5 -2
  15. package/dist/{classifier-MZ65R7FK.js → classifier-D5K3X7FQ.js} +1 -0
  16. package/dist/cli.js +244 -80
  17. package/dist/{confidence-gate-ZQDAOS6P.js → confidence-gate-AT2MW4NK.js} +8 -6
  18. package/dist/dashboard/assets/index-BcDOsQwz.css +1 -0
  19. package/dist/dashboard/assets/index-DGx4sRHq.js +2 -0
  20. package/dist/dashboard/index.html +2 -2
  21. package/dist/{dashboard-server-MD6NVL2F.js → dashboard-server-UBZHOPRC.js} +274 -21
  22. package/dist/{db-FLFZZXG3.js → db-RE23O4DV.js} +3 -1
  23. package/dist/{deterministic-validator-PP56B46I.js → deterministic-validator-3LB234OG.js} +1 -0
  24. package/dist/draft-rule-NUXOSRRS.js +11 -0
  25. package/dist/embedding-VIMV6O2P.js +9 -0
  26. package/dist/{evidence-HVMSONTT.js → evidence-WFMGWSOP.js} +1 -0
  27. package/dist/{graph-TFNTB5OK.js → graph-UJJAKNHD.js} +1 -0
  28. package/dist/{incident-capture-RVPZULS7.js → incident-capture-5YUVJJM3.js} +11 -0
  29. package/dist/mcp-server-3N7R46BS.js +14958 -0
  30. package/dist/memory-selection-A5CQ6ZT5.js +29 -0
  31. package/dist/{deepseek-critique-MALVIYGF.js → model-critique-E2GNZ42U.js} +18 -32
  32. package/dist/{ollama-judge-D2LFK5PB.js → ollama-judge-6ZEZN4JV.js} +29 -41
  33. package/dist/{rate-limiter-SLIPCXRF.js → rate-limiter-KIMXTAAU.js} +1 -0
  34. package/dist/{rules-V3QMN3AR.js → rules-UUVIKEDM.js} +1 -0
  35. package/dist/{watch-errors-B3FA26N4.js → watch-errors-DZMW3CFN.js} +28 -33
  36. package/package.json +2 -1
  37. package/templates/AGENTS.md.hbs +11 -27
  38. package/templates/AI_RULES.md.hbs +9 -23
  39. package/templates/ARCHITECTURE.md.hbs +9 -30
  40. package/templates/CLAUDE.md.hbs +10 -35
  41. package/templates/DEVIN.md.hbs +7 -16
  42. package/templates/PROJECT_MEMORY.md.hbs +5 -21
  43. package/templates/amazonq-guidelines.md.hbs +7 -16
  44. package/templates/clinerules.hbs +8 -17
  45. package/templates/copilot-instructions.md.hbs +7 -16
  46. package/templates/cursor-rule.mdc.hbs +4 -9
  47. package/templates/cursorrules.hbs +8 -14
  48. package/templates/gemini-styleguide.md.hbs +7 -16
  49. package/templates/jetbrains-ai.md.hbs +6 -15
  50. package/templates/roo-rule.md.hbs +6 -15
  51. package/templates/windsurfrules.hbs +9 -18
  52. package/dist/dashboard/assets/index-BFwqVRYO.js +0 -2
  53. package/dist/dashboard/assets/index-y7eHWJtq.css +0 -1
package/dist/cli.js CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ buildArchRules,
4
+ buildLayersTemplate
5
+ } from "./chunk-HJCPBM7B.js";
2
6
  import {
3
7
  AGENT_NAMES,
4
8
  MEMORY_FILE,
5
9
  OUTPUT_FILES,
6
- buildArchRules,
7
- buildLayersTemplate,
8
10
  checkCi,
9
11
  checkCommitMsg,
10
12
  checkFile,
@@ -29,18 +31,21 @@ import {
29
31
  toPortableMemory,
30
32
  uninstallHook,
31
33
  writeMemoryFile
32
- } from "./chunk-23GUWJ6F.js";
33
- import "./chunk-PQBWHAZN.js";
34
+ } from "./chunk-4QWIYO2G.js";
35
+ import "./chunk-ZZBQEXEO.js";
36
+ import "./chunk-SKR44CRD.js";
34
37
  import {
35
38
  closePool,
36
39
  getPool,
37
40
  runMigrations
38
- } from "./chunk-GIPKVQSA.js";
39
- import "./chunk-ZZBQEXEO.js";
41
+ } from "./chunk-5T2QBBYT.js";
42
+ import "./chunk-2LNDQGDD.js";
43
+ import "./chunk-XAE3RY5D.js";
44
+ import "./chunk-K3NQKI34.js";
40
45
 
41
46
  // src/cli.ts
42
47
  import { Command } from "commander";
43
- import { input, select, confirm } from "@inquirer/prompts";
48
+ import { input, select, confirm, password as promptPassword } from "@inquirer/prompts";
44
49
  import chalk from "chalk";
45
50
  import ora from "ora";
46
51
  import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync, rmSync } from "fs";
@@ -143,7 +148,7 @@ var ARCHMIND_RUNTIME_FILES = [
143
148
  ];
144
149
  var CI_WORKFLOW_FILE = ".github/workflows/memory-core.yml";
145
150
  var GITIGNORE_HEADING = "# memory-core generated files";
146
- var DEFAULT_OLLAMA_URL = "http://localhost:11434";
151
+ var DEFAULT_EMBEDDING_URL = "http://localhost:11434";
147
152
  var DEFAULT_EMBEDDING_MODEL = "nomic-embed-text";
148
153
  var DEFAULT_CHAT_MODEL = "llama3.2";
149
154
  var phase1 = getDefaultApplicationContainer();
@@ -176,13 +181,17 @@ function readRuntimeEnv() {
176
181
  for (const [key, value] of Object.entries(process.env)) {
177
182
  if (typeof value === "string" && value !== "") values[key] = value;
178
183
  }
184
+ if (!values.EMBEDDING_URL && values.OLLAMA_URL) values.EMBEDDING_URL = values.OLLAMA_URL;
185
+ if (!values.EMBEDDING_MODEL && values.OLLAMA_MODEL) values.EMBEDDING_MODEL = values.OLLAMA_MODEL;
186
+ if (values.OLLAMA_URL && !process.env.OLLAMA_URL) process.env.OLLAMA_URL = values.OLLAMA_URL;
187
+ if (values.OLLAMA_MODEL && !process.env.OLLAMA_MODEL) process.env.OLLAMA_MODEL = values.OLLAMA_MODEL;
179
188
  return { envPath: getWriteEnvPath(), values };
180
189
  }
181
190
  function writeRuntimeEnv(values, envPath = getWriteEnvPath()) {
182
191
  const orderedKeys = [
183
192
  "DATABASE_URL",
184
- "OLLAMA_URL",
185
- "OLLAMA_MODEL",
193
+ "EMBEDDING_URL",
194
+ "EMBEDDING_MODEL",
186
195
  "CHAT_PROVIDER",
187
196
  "CHAT_MODEL",
188
197
  "CHAT_BASE_URL",
@@ -456,8 +465,8 @@ async function runModelDoctor() {
456
465
  const { envPath, values } = readRuntimeEnv();
457
466
  const provider2 = getConfiguredProvider(values);
458
467
  const model2 = getConfiguredChatModel(values);
459
- const ollamaUrl = values.OLLAMA_URL ?? DEFAULT_OLLAMA_URL;
460
- const embeddingModel = values.OLLAMA_MODEL ?? DEFAULT_EMBEDDING_MODEL;
468
+ const ollamaUrl = values.EMBEDDING_URL ?? DEFAULT_EMBEDDING_URL;
469
+ const embeddingModel = values.EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
461
470
  const dbUrl = values.DATABASE_URL ?? "";
462
471
  console.log(chalk.bold("\n memory-core model doctor\n"));
463
472
  printStatusLine("Env file", existsSync(envPath) ? envPath : `${envPath} ${chalk.yellow("(will be created on first write)")}`);
@@ -536,7 +545,7 @@ async function printProjectStatus() {
536
545
  const memoryFilePath = join(process.cwd(), MEMORY_FILE);
537
546
  const statsPath = join(process.cwd(), ".memory-core-stats.json");
538
547
  const dbError = await verifyDatabaseConnection(values.DATABASE_URL ?? "");
539
- const ollamaError = await verifyOllamaConnection(values.OLLAMA_URL ?? DEFAULT_OLLAMA_URL);
548
+ const ollamaError = await verifyOllamaConnection(values.EMBEDDING_URL ?? DEFAULT_EMBEDDING_URL);
540
549
  const graphCount = await getGraphSnapshotCount(process.cwd());
541
550
  console.log(chalk.bold("\n memory-core status\n"));
542
551
  printStatusLine("Project", config?.projectName ?? process.cwd().split("/").pop() ?? "unknown");
@@ -555,13 +564,16 @@ async function printProjectStatus() {
555
564
  printStatusLine("Generated files", String(generatedFiles.length));
556
565
  printStatusLine("Hook", existsSync(hookPath) ? "installed" : "not installed");
557
566
  printStatusLine("Stats file", existsSync(statsPath) ? ".memory-core-stats.json" : chalk.gray("none"));
567
+ const { ApprovalQueue: AQ } = await import("./approval-queue-4RK46FNE.js");
568
+ const pendingProposals = new AQ(getArchmindDir()).pending().length;
569
+ printStatusLine("Proposals", pendingProposals > 0 ? chalk.yellow(`${pendingProposals} pending \u2014 run memory-core arch review`) : chalk.gray("0 pending"));
558
570
  printStatusLine("Graph backend", graphBackendLabel(values));
559
571
  printStatusLine("Graph store", graphStoreFilePath(process.cwd()));
560
572
  printStatusLine("Graph snapshots", graphCount === null ? chalk.gray("unavailable") : String(graphCount));
561
573
  console.log();
562
574
  printStatusLine("Database URL", redactDatabaseUrl(values.DATABASE_URL ?? ""));
563
- printStatusLine("Ollama URL", values.OLLAMA_URL ?? DEFAULT_OLLAMA_URL);
564
- printStatusLine("Embedding model", values.OLLAMA_MODEL ?? DEFAULT_EMBEDDING_MODEL);
575
+ printStatusLine("Ollama URL", values.EMBEDDING_URL ?? DEFAULT_EMBEDDING_URL);
576
+ printStatusLine("Embedding model", values.EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL);
565
577
  printStatusLine("Chat provider", provider2);
566
578
  printStatusLine("Chat model", model2);
567
579
  console.log();
@@ -711,7 +723,7 @@ program.command("init").description("Initialize memory-core in the current proje
711
723
  } catch {
712
724
  }
713
725
  try {
714
- const r = await fetch(`${process.env.OLLAMA_URL ?? DEFAULT_OLLAMA_URL}/api/tags`, { signal: AbortSignal.timeout(3e3) });
726
+ const r = await fetch(`${process.env.EMBEDDING_URL ?? process.env.OLLAMA_URL ?? DEFAULT_EMBEDDING_URL}/api/tags`, { signal: AbortSignal.timeout(3e3) });
715
727
  ollamaOk = r.ok;
716
728
  } catch {
717
729
  }
@@ -721,8 +733,8 @@ program.command("init").description("Initialize memory-core in the current proje
721
733
  const chatModel = DEFAULT_CHAT_MODEL;
722
734
  const envValues = {
723
735
  DATABASE_URL: dbUrl,
724
- OLLAMA_URL: DEFAULT_OLLAMA_URL,
725
- OLLAMA_MODEL: DEFAULT_EMBEDDING_MODEL,
736
+ EMBEDDING_URL: DEFAULT_EMBEDDING_URL,
737
+ EMBEDDING_MODEL: DEFAULT_EMBEDDING_MODEL,
726
738
  CHAT_PROVIDER: "ollama",
727
739
  CHAT_MODEL: chatModel,
728
740
  OLLAMA_CHAT_MODEL: chatModel
@@ -758,7 +770,7 @@ program.command("init").description("Initialize memory-core in the current proje
758
770
  while (true) {
759
771
  ollamaUrl = await input({
760
772
  message: "Ollama URL (used for search embeddings)?",
761
- default: ollamaUrl || DEFAULT_OLLAMA_URL
773
+ default: ollamaUrl || DEFAULT_EMBEDDING_URL
762
774
  });
763
775
  const ollamaSpinner = ora(" Testing Ollama connection\u2026").start();
764
776
  try {
@@ -867,8 +879,8 @@ program.command("init").description("Initialize memory-core in the current proje
867
879
  }
868
880
  const envValues = {
869
881
  DATABASE_URL: dbUrl,
870
- OLLAMA_URL: ollamaUrl,
871
- OLLAMA_MODEL: DEFAULT_EMBEDDING_MODEL,
882
+ EMBEDDING_URL: ollamaUrl,
883
+ EMBEDDING_MODEL: DEFAULT_EMBEDDING_MODEL,
872
884
  CHAT_PROVIDER: chatProvider,
873
885
  CHAT_MODEL: chatModel
874
886
  };
@@ -890,7 +902,7 @@ program.command("init").description("Initialize memory-core in the current proje
890
902
  } catch {
891
903
  }
892
904
  try {
893
- const r = await fetch(`${process.env.OLLAMA_URL ?? DEFAULT_OLLAMA_URL}/api/tags`, { signal: AbortSignal.timeout(3e3) });
905
+ const r = await fetch(`${process.env.EMBEDDING_URL ?? process.env.OLLAMA_URL ?? DEFAULT_EMBEDDING_URL}/api/tags`, { signal: AbortSignal.timeout(3e3) });
894
906
  ollamaOk = r.ok;
895
907
  } catch {
896
908
  }
@@ -1159,6 +1171,26 @@ program.command("auto-sync [mode]").description("Show or change automatic agent
1159
1171
  console.log(chalk.green(`Auto-sync ${enabled ? "enabled" : "disabled"}`));
1160
1172
  console.log(chalk.gray(" Manual sync is always available: memory-core sync"));
1161
1173
  });
1174
+ program.command("propose <text>").description("Queue a memory proposal for review before it enters the database").option("-r, --reason <reason>", "Why this should be a rule").option("--confidence <level>", "Confidence level: high, medium, low", "medium").action(async (text, opts) => {
1175
+ const { ApprovalQueue } = await import("./approval-queue-4RK46FNE.js");
1176
+ const { randomUUID } = await import("crypto");
1177
+ const confidence = opts.confidence ?? "medium";
1178
+ const rule = {
1179
+ id: randomUUID(),
1180
+ name: text.length > 80 ? text.slice(0, 77) + "\u2026" : text,
1181
+ description: text,
1182
+ fromLayer: "*",
1183
+ toLayer: "*",
1184
+ allowed: false,
1185
+ severity: "medium",
1186
+ enforcement: "warn"
1187
+ };
1188
+ const queue = new ApprovalQueue(getArchmindDir());
1189
+ queue.add(rule, "pr-review", confidence, opts.reason ? { evidence: opts.reason } : void 0);
1190
+ console.log(chalk.green(`
1191
+ \u2713 Queued. Run ${chalk.bold("memory-core arch review")} to approve.
1192
+ `));
1193
+ });
1162
1194
  program.command("remember <text>").description("Save a new memory to the central database").option("-t, --type <type>", "Memory type (decision|rule|pattern|note)", "decision").option("-s, --scope <scope>", "Scope (global|project)", "project").option("--tags <tags>", "Comma-separated tags").option("-r, --reason <reason>", "Why this rule exists \u2014 helps agents understand intent and debug violations").option("--applies-to <items>", "Comma-separated situations where this memory applies").option("--avoid-when <items>", "Comma-separated situations where this memory should not be used").option("--example <items>", "Comma-separated examples that teach agents how to apply this memory").option("--source <source>", "Human-readable source for this memory").option("--no-sync", "Skip automatic agent file sync after saving").action(async (text, opts) => {
1163
1195
  const config = readProjectConfig();
1164
1196
  const scope = opts.scope?.trim() || "project";
@@ -1738,6 +1770,29 @@ program.command("tune").description("Review and disable noisy rules with high fa
1738
1770
  console.log(chalk.dim("\n No changes made.\n"));
1739
1771
  }
1740
1772
  });
1773
+ program.command("mcp").description("Start the ArchMind MCP server (works with Claude Code, Cursor, VS Code)").option("--transport <type>", "Transport: stdio (Claude Code) or http (Cursor/VS Code)", "stdio").option("-p, --port <port>", "HTTP port (only used with --transport http)", "3001").option("--show-config", "Print MCP config snippets for each editor and exit").option("--verbose", "Log session events to stderr").action(async (opts) => {
1774
+ const transport = opts.transport === "http" ? "http" : "stdio";
1775
+ const port = parseInt(opts.port, 10);
1776
+ const { startMcpServer, printMcpConfig } = await import("./mcp-server-3N7R46BS.js");
1777
+ if (opts.showConfig) {
1778
+ const binPath = process.argv[1];
1779
+ printMcpConfig(transport, port, binPath);
1780
+ return;
1781
+ }
1782
+ if (transport === "stdio") {
1783
+ process.stderr.write(`[archmind-mcp] Starting \u2014 transport: stdio
1784
+ `);
1785
+ process.stderr.write(`[archmind-mcp] Run with --show-config to get editor config snippets
1786
+ `);
1787
+ } else {
1788
+ console.log(` ArchMind MCP Server`);
1789
+ console.log(` Transport: HTTP Port: ${port}`);
1790
+ console.log(` Endpoint: http://127.0.0.1:${port}/mcp`);
1791
+ console.log(` Run memory-core mcp --transport http --show-config for editor setup
1792
+ `);
1793
+ }
1794
+ await startMcpServer({ transport, port, cwd: process.cwd(), verbose: opts.verbose ?? false });
1795
+ });
1741
1796
  program.command("dashboard").description("Start the live Svelte dashboard with WebSocket watch events").option("-p, --port <port>", "Dashboard port", "5178").option("--path <dir>", "Directory to watch (default: current directory)").option("--no-watch", "Serve the dashboard without starting file watch").option("--auth", "Enable JWT authentication (requires MC_JWT_SECRET in .memory-core.env)").action(async (opts) => {
1742
1797
  const resolveDashboardPath = () => {
1743
1798
  if (typeof opts.path === "string" && opts.path.trim().length > 0) return opts.path;
@@ -1755,7 +1810,7 @@ program.command("dashboard").description("Start the live Svelte dashboard with W
1755
1810
  }
1756
1811
  return void 0;
1757
1812
  };
1758
- const { startDashboard } = await import("./dashboard-server-MD6NVL2F.js");
1813
+ const { startDashboard } = await import("./dashboard-server-UBZHOPRC.js");
1759
1814
  await startDashboard({
1760
1815
  port: parseInt(opts.port, 10),
1761
1816
  path: resolveDashboardPath(),
@@ -1942,8 +1997,8 @@ provider.command("set <name>").description("Set the code-checking provider (olla
1942
1997
  const runtimeEnv = readRuntimeEnv();
1943
1998
  const values = { ...runtimeEnv.values };
1944
1999
  values.CHAT_PROVIDER = providerName;
1945
- values.OLLAMA_URL = values.OLLAMA_URL ?? DEFAULT_OLLAMA_URL;
1946
- values.OLLAMA_MODEL = values.OLLAMA_MODEL ?? DEFAULT_EMBEDDING_MODEL;
2000
+ values.EMBEDDING_URL = values.EMBEDDING_URL ?? DEFAULT_EMBEDDING_URL;
2001
+ values.EMBEDDING_MODEL = values.EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
1947
2002
  if (opts.model) {
1948
2003
  values.CHAT_MODEL = opts.model;
1949
2004
  } else if (!values.CHAT_MODEL && !values.OLLAMA_CHAT_MODEL) {
@@ -1993,13 +2048,13 @@ model.command("set <name>").description("Set the chat model used for code checki
1993
2048
  if (opts.provider) values.CHAT_PROVIDER = normalizeProvider(opts.provider);
1994
2049
  const providerName = getConfiguredProvider(values);
1995
2050
  if (opts.embedding) {
1996
- values.OLLAMA_MODEL = name;
2051
+ values.EMBEDDING_MODEL = name;
1997
2052
  } else {
1998
2053
  values.CHAT_MODEL = name;
1999
2054
  if (providerName === "ollama") values.OLLAMA_CHAT_MODEL = name;
2000
2055
  }
2001
- values.OLLAMA_URL = values.OLLAMA_URL ?? DEFAULT_OLLAMA_URL;
2002
- values.OLLAMA_MODEL = values.OLLAMA_MODEL ?? DEFAULT_EMBEDDING_MODEL;
2056
+ values.EMBEDDING_URL = values.EMBEDDING_URL ?? DEFAULT_EMBEDDING_URL;
2057
+ values.EMBEDDING_MODEL = values.EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
2003
2058
  writeRuntimeEnv(values, runtimeEnv.envPath);
2004
2059
  applyRuntimeEnv(values);
2005
2060
  appendMissingGitignoreEntries(LOCAL_STATE_FILES, GITIGNORE_HEADING);
@@ -2244,20 +2299,20 @@ program.command("check").description("Check staged changes against architecture
2244
2299
  const diffRef = opts.diff || "HEAD~1";
2245
2300
  const diag = opts.json ? (msg) => process.stderr.write(msg + "\n") : (msg) => console.log(msg);
2246
2301
  const diagSpinner = (text) => ora({ text, stream: opts.json ? process.stderr : process.stdout });
2247
- const { CheckRateLimiter } = await import("./rate-limiter-SLIPCXRF.js");
2302
+ const { CheckRateLimiter } = await import("./rate-limiter-KIMXTAAU.js");
2248
2303
  const release = await new CheckRateLimiter(process.cwd()).acquire();
2249
2304
  process.on("exit", release);
2250
- const { FileClassifier } = await import("./classifier-MZ65R7FK.js");
2251
- const { ASTAnalyzer } = await import("./ast-analyzer-JM4CIOFY.js");
2252
- const { GraphBuilder } = await import("./graph-TFNTB5OK.js");
2253
- const { RuleMatcher } = await import("./rules-V3QMN3AR.js");
2254
- const { EvidencePacketBuilder } = await import("./evidence-HVMSONTT.js");
2255
- const { DeterministicValidator } = await import("./deterministic-validator-PP56B46I.js");
2256
- const { OllamaJudge } = await import("./ollama-judge-D2LFK5PB.js");
2257
- const { DeepSeekCritique } = await import("./deepseek-critique-MALVIYGF.js");
2258
- const { ConfidenceGate, defaultGateConfig } = await import("./confidence-gate-ZQDAOS6P.js");
2259
- const { CheckCache } = await import("./check-cache-6NWRTZJD.js");
2260
- const { CheckLogger } = await import("./check-logger-5HYSWA3S.js");
2305
+ const { FileClassifier } = await import("./classifier-D5K3X7FQ.js");
2306
+ const { ASTAnalyzer } = await import("./ast-analyzer-WGTJKGAP.js");
2307
+ const { GraphBuilder } = await import("./graph-UJJAKNHD.js");
2308
+ const { RuleMatcher } = await import("./rules-UUVIKEDM.js");
2309
+ const { EvidencePacketBuilder } = await import("./evidence-WFMGWSOP.js");
2310
+ const { DeterministicValidator } = await import("./deterministic-validator-3LB234OG.js");
2311
+ const { OllamaJudge } = await import("./ollama-judge-6ZEZN4JV.js");
2312
+ const { ModelCritique } = await import("./model-critique-E2GNZ42U.js");
2313
+ const { ConfidenceGate, defaultGateConfig } = await import("./confidence-gate-AT2MW4NK.js");
2314
+ const { CheckCache } = await import("./check-cache-ZVFHTA2C.js");
2315
+ const { CheckLogger } = await import("./check-logger-F4DW4LBY.js");
2261
2316
  const configDir = getArchmindDir();
2262
2317
  const classifier = FileClassifier.loadFromConfig(configDir);
2263
2318
  const ruleMatcher = RuleMatcher.loadFromConfig(configDir);
@@ -2389,7 +2444,7 @@ program.command("check").description("Check staged changes against architecture
2389
2444
  }
2390
2445
  let storedMemories = [];
2391
2446
  try {
2392
- const { listMemories } = await import("./db-FLFZZXG3.js");
2447
+ const { listMemories } = await import("./db-RE23O4DV.js");
2393
2448
  const allMemories = await listMemories({ limit: 1e4 });
2394
2449
  const ranked = allMemories.filter((m) => ["rule", "pattern", "decision"].includes(m.type));
2395
2450
  const changedLayers = packet.layersAffected;
@@ -2438,7 +2493,7 @@ program.command("check").description("Check staged changes against architecture
2438
2493
  const primaryDecision = await new OllamaJudge().judge(packet, storedMemories);
2439
2494
  spinner.stop();
2440
2495
  const critiqueEnabled = opts.secondOpinion ?? false;
2441
- const critiqueFn = critiqueEnabled ? async (p) => new DeepSeekCritique().critique(p, primaryDecision) : async () => ({ decision: primaryDecision.decision, confidence: primaryDecision.confidence, reasoning: "skipped", override: false });
2496
+ const critiqueFn = critiqueEnabled ? async (p) => new ModelCritique().critique(p, primaryDecision) : async () => ({ decision: primaryDecision.decision, confidence: primaryDecision.confidence, reasoning: "skipped", override: false });
2442
2497
  const gateDecision = await new ConfidenceGate(defaultGateConfig(critiqueEnabled)).decide(packet, primaryDecision, critiqueFn);
2443
2498
  cache.set(cacheKey, {
2444
2499
  decision: gateDecision.final,
@@ -2455,7 +2510,7 @@ program.command("check").description("Check staged changes against architecture
2455
2510
  suggestedFix: primaryDecision.suggestedFix,
2456
2511
  reasoning: primaryDecision.reasoning,
2457
2512
  confidence: primaryDecision.confidence,
2458
- ...opts.json ? { judge: primaryDecision, critique: gateDecision.deepseek, selfReview: gateDecision.selfReview, evidence: packet } : {}
2513
+ ...opts.json ? { judge: primaryDecision, critique: gateDecision.critique, selfReview: gateDecision.selfReview, evidence: packet } : {}
2459
2514
  };
2460
2515
  if (opts.json) {
2461
2516
  console.log(JSON.stringify(output, null, 2));
@@ -2582,55 +2637,145 @@ function getArchmindDir() {
2582
2637
  return ARCHMIND_DIR;
2583
2638
  }
2584
2639
  var arch = program.command("arch").description("Architecture enforcement: check, review captured rules, watch for errors, log incidents");
2585
- arch.command("review").description("Review and approve/reject auto-captured architecture rules").option("--approve-all", "Approve everything without prompting").option("--reject-all", "Reject everything without prompting").action(async (opts) => {
2586
- const { ApprovalQueue } = await import("./approval-queue-YBYRGBHP.js");
2587
- const { join: join2 } = await import("path");
2640
+ arch.command("review").description("Review and approve/reject auto-captured architecture rules").option("--approve-all", "Approve everything without prompting").option("--reject-all", "Reject everything without prompting").option("--source <source>", "Filter by source: watch, incident, test, bugfix, pr-review").option("--confidence <level>", "Filter by confidence: high, medium, low").option("--older-than <days>", "Reject proposals older than N days without prompting").action(async (opts) => {
2641
+ const { ApprovalQueue } = await import("./approval-queue-4RK46FNE.js");
2588
2642
  const configDir = getArchmindDir();
2589
2643
  const queue = new ApprovalQueue(configDir);
2590
- const pending = queue.pending();
2644
+ let pending = queue.pending();
2645
+ if (opts.olderThan) {
2646
+ const days = parseInt(opts.olderThan, 10);
2647
+ if (!isNaN(days)) {
2648
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
2649
+ const stale = pending.filter((i) => new Date(i.capturedAt).getTime() < cutoff);
2650
+ for (const item of stale) queue.reject(item.id);
2651
+ if (stale.length > 0) console.log(chalk.yellow(` \u2717 Rejected ${stale.length} proposals older than ${days} days`));
2652
+ pending = queue.pending();
2653
+ }
2654
+ }
2655
+ if (opts.source) pending = pending.filter((i) => i.source === opts.source);
2656
+ if (opts.confidence) pending = pending.filter((i) => i.confidence === opts.confidence);
2591
2657
  if (pending.length === 0) {
2592
- console.log(chalk.dim(" No pending rules."));
2658
+ const total = queue.pending().length;
2659
+ console.log(chalk.dim("\n No pending proposals" + (opts.source || opts.confidence ? " matching filter" : "") + "."));
2660
+ if (total > 0) console.log(chalk.dim(` (${total} total pending \u2014 remove filters to see all)`));
2661
+ else console.log(chalk.dim(' Generate proposals: memory-core arch watch \xB7 arch incident \xB7 memory-core propose "..."'));
2593
2662
  return;
2594
2663
  }
2595
2664
  console.log(chalk.bold(`
2596
- Pending rules (${pending.length}):
2665
+ Pending proposals (${pending.length}):
2597
2666
  `));
2598
- if (opts.approveAll) {
2599
- for (const item of pending) queue.approve(item.id);
2600
- const count2 = queue.persistApproved(join2(configDir, "rules.json"));
2601
- console.log(chalk.green(` \u2713 Approved and saved ${count2} rules`));
2602
- return;
2603
- }
2604
2667
  if (opts.rejectAll) {
2605
2668
  for (const item of pending) queue.reject(item.id);
2606
- console.log(chalk.yellow(` \u2717 Rejected ${pending.length} rules`));
2669
+ console.log(chalk.yellow(` \u2717 Rejected ${pending.length} proposals`));
2670
+ return;
2671
+ }
2672
+ if (!opts.approveAll) {
2673
+ for (const item of pending) {
2674
+ console.log(chalk.cyan(` [${item.source.toUpperCase()}]`) + chalk.dim(` ${item.confidence}`) + ` ${item.rule.name}`);
2675
+ console.log(chalk.dim(` ${item.rule.description}`));
2676
+ if (item.evidence) console.log(chalk.dim(` evidence: ${item.evidence.slice(0, 120)}`));
2677
+ if (item.file) console.log(chalk.dim(` file: ${item.file}`));
2678
+ console.log(chalk.dim(` captured: ${new Date(item.capturedAt).toLocaleString()}`));
2679
+ const { confirm: confirm2 } = await import("@inquirer/prompts");
2680
+ const accept = await confirm2({ message: " Keep this rule?" });
2681
+ accept ? queue.approve(item.id) : queue.reject(item.id);
2682
+ console.log(accept ? chalk.green(" \u2713 Kept") : chalk.yellow(" \u2717 Dropped"));
2683
+ console.log();
2684
+ }
2685
+ } else {
2686
+ for (const item of pending) queue.approve(item.id);
2687
+ }
2688
+ const approvedItems = queue.approved();
2689
+ if (approvedItems.length === 0) return;
2690
+ let saved = 0;
2691
+ let skipped = 0;
2692
+ for (const item of approvedItems) {
2693
+ const result = await phase1.services.memoryEngine.remember({
2694
+ type: "rule",
2695
+ scope: "project",
2696
+ title: item.rule.name,
2697
+ content: item.rule.description,
2698
+ reason: `Auto-captured from ${item.source} (confidence: ${item.confidence})`,
2699
+ tags: [item.source, item.rule.severity]
2700
+ });
2701
+ result === "inserted" ? saved++ : skipped++;
2702
+ }
2703
+ queue.clearApproved();
2704
+ if (saved > 0) console.log(chalk.green(` \u2713 Saved ${saved} rules to DB`));
2705
+ if (skipped > 0) console.log(chalk.dim(` ${skipped} already existed, skipped`));
2706
+ if (saved > 0) await autoSyncGeneratedFiles(readProjectConfig(), "arch review");
2707
+ });
2708
+ arch.command("propose <text>").description("Queue a rule proposal for review before it enters memory").option("--reason <reason>", "Why this rule should exist").option("--confidence <level>", "Confidence level: high, medium, low", "medium").action(async (text, opts) => {
2709
+ const { ApprovalQueue } = await import("./approval-queue-4RK46FNE.js");
2710
+ const { randomUUID } = await import("crypto");
2711
+ const confidence = opts.confidence ?? "medium";
2712
+ const rule = {
2713
+ id: randomUUID(),
2714
+ name: text.length > 80 ? text.slice(0, 77) + "\u2026" : text,
2715
+ description: text,
2716
+ fromLayer: "*",
2717
+ toLayer: "*",
2718
+ allowed: false,
2719
+ severity: "medium",
2720
+ enforcement: "warn"
2721
+ };
2722
+ if (opts.reason) {
2723
+ Object.assign(rule, { reason: opts.reason });
2724
+ }
2725
+ const queue = new ApprovalQueue(getArchmindDir());
2726
+ queue.add(rule, "pr-review", confidence);
2727
+ console.log(chalk.green(` \u2713 Queued. Run ${chalk.bold("memory-core arch review")} to approve.
2728
+ `));
2729
+ });
2730
+ arch.command("proposals").description("List all pending rule proposals").action(async () => {
2731
+ const { ApprovalQueue } = await import("./approval-queue-4RK46FNE.js");
2732
+ const queue = new ApprovalQueue(getArchmindDir());
2733
+ const pending = queue.pending();
2734
+ if (pending.length === 0) {
2735
+ console.log(chalk.dim("\n No pending proposals.\n"));
2607
2736
  return;
2608
2737
  }
2738
+ console.log(chalk.bold(`
2739
+ Pending proposals (${pending.length}):
2740
+ `));
2609
2741
  for (const item of pending) {
2610
- console.log(chalk.cyan(` [${item.source.toUpperCase()}]`) + ` ${item.rule.name}`);
2611
- console.log(chalk.dim(` ${item.rule.description}`));
2612
- console.log(chalk.dim(` captured: ${item.capturedAt} confidence: ${item.confidence}`));
2613
- const { confirm: confirm2 } = await import("@inquirer/prompts");
2614
- const accept = await confirm2({ message: " Keep this rule?" });
2615
- accept ? queue.approve(item.id) : queue.reject(item.id);
2616
- console.log(accept ? chalk.green(" \u2713 Kept") : chalk.yellow(" \u2717 Dropped"));
2742
+ console.log(
2743
+ chalk.cyan(` [${item.source.toUpperCase()}]`) + chalk.dim(` ${item.confidence}`) + ` ${item.rule.name}`
2744
+ );
2745
+ console.log(chalk.dim(` captured: ${item.capturedAt}`));
2617
2746
  console.log();
2618
2747
  }
2619
- const count = queue.persistApproved(join2(configDir, "rules.json"));
2620
- if (count > 0) console.log(chalk.green(` \u2713 Saved ${count} rules to .archmind/rules.json`));
2748
+ console.log(chalk.dim(` Run ${chalk.bold("memory-core arch review")} to approve or reject.
2749
+ `));
2621
2750
  });
2622
2751
  arch.command("watch").description("Watch your dev processes and auto-draft rules from errors").action(async () => {
2623
- const { WatchErrors, loadWatchConfig } = await import("./watch-errors-B3FA26N4.js");
2752
+ const { WatchErrors, loadWatchConfig } = await import("./watch-errors-DZMW3CFN.js");
2624
2753
  const configDir = getArchmindDir();
2625
2754
  const config = loadWatchConfig(configDir);
2626
2755
  console.log(chalk.cyan("\n Watching:"));
2627
2756
  for (const cmd of config.commands) console.log(chalk.dim(` \u2022 ${cmd}`));
2628
2757
  console.log(chalk.dim("\n Press Ctrl+C to stop.\n"));
2629
- const watcher = new WatchErrors(config, configDir);
2630
- watcher.start((rule) => {
2631
- console.log(chalk.yellow(` [DRAFT] ${rule.name}`));
2632
- console.log(chalk.dim(` ${rule.description.slice(0, 100)}`));
2633
- console.log(chalk.dim(' Run "memory-core arch review" to approve.\n'));
2758
+ const saveToDb = async (rule) => {
2759
+ await phase1.services.memoryEngine.remember({
2760
+ type: "rule",
2761
+ scope: "project",
2762
+ title: rule.name,
2763
+ content: rule.description,
2764
+ reason: "Auto-captured from watch (high confidence, auto-approved)",
2765
+ tags: ["watch", rule.severity]
2766
+ });
2767
+ };
2768
+ const watcher = new WatchErrors(config, configDir, saveToDb);
2769
+ watcher.start((rule, wasAutoSaved) => {
2770
+ if (wasAutoSaved) {
2771
+ console.log(chalk.green(` [AUTO-SAVED] ${rule.name}`));
2772
+ console.log(chalk.dim(` High confidence \u2014 saved to memory.
2773
+ `));
2774
+ } else {
2775
+ console.log(chalk.yellow(` [QUEUED] ${rule.name}`));
2776
+ console.log(chalk.dim(` ${rule.description.slice(0, 100)}`));
2777
+ console.log(chalk.dim(' Run "memory-core arch review" to approve.\n'));
2778
+ }
2634
2779
  });
2635
2780
  process.on("SIGINT", () => {
2636
2781
  watcher.stop();
@@ -2642,21 +2787,40 @@ arch.command("watch").description("Watch your dev processes and auto-draft rules
2642
2787
  });
2643
2788
  arch.command("incident").description("Log a production incident and capture it as an architecture rule").action(async () => {
2644
2789
  const { input: input2, confirm: confirm2 } = await import("@inquirer/prompts");
2645
- const { IncidentCaptureService } = await import("./incident-capture-RVPZULS7.js");
2646
- const { ApprovalQueue } = await import("./approval-queue-YBYRGBHP.js");
2790
+ const { IncidentCaptureService } = await import("./incident-capture-5YUVJJM3.js");
2791
+ const { ApprovalQueue } = await import("./approval-queue-4RK46FNE.js");
2647
2792
  console.log(chalk.cyan("\n Incident capture\n"));
2648
2793
  const what = await input2({ message: "What broke?" });
2649
2794
  const why = await input2({ message: "Root cause?" });
2650
2795
  const where = await input2({ message: "Which file / layer / pattern?" });
2651
- const rule = new IncidentCaptureService().draftRule({ what, why, where, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
2796
+ const spinner = (await import("ora")).default("Drafting rule with AI\u2026").start();
2797
+ const { rule, confidence } = await new IncidentCaptureService().draftRuleWithAI({ what, why, where, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
2798
+ spinner.stop();
2652
2799
  console.log(chalk.dim(`
2653
2800
  Rule: ${rule.name}`));
2654
- console.log(chalk.dim(` Description: ${rule.description}
2801
+ console.log(chalk.dim(` Description: ${rule.description}`));
2802
+ console.log(chalk.dim(` Confidence: ${confidence}
2655
2803
  `));
2656
- const save = await confirm2({ message: "Save to approval queue?" });
2804
+ if (confidence === "high") {
2805
+ const autoSave = await confirm2({ message: "High confidence \u2014 save directly to memory?" });
2806
+ if (autoSave) {
2807
+ await phase1.services.memoryEngine.remember({
2808
+ type: "rule",
2809
+ scope: "project",
2810
+ title: rule.name,
2811
+ content: rule.description,
2812
+ reason: `Incident: ${what}. Root cause: ${why}`,
2813
+ tags: ["incident", rule.severity]
2814
+ });
2815
+ await autoSyncGeneratedFiles(readProjectConfig(), "incident");
2816
+ console.log(chalk.green(" \u2713 Saved to memory and synced.\n"));
2817
+ return;
2818
+ }
2819
+ }
2820
+ const save = await confirm2({ message: "Save to approval queue for review?" });
2657
2821
  if (save) {
2658
- new ApprovalQueue(getArchmindDir()).add(rule, "incident", "high");
2659
- console.log(chalk.green(' \u2713 Saved. Run "memory-core arch review" to approve.\n'));
2822
+ new ApprovalQueue(getArchmindDir()).add(rule, "incident", confidence, { evidence: `What: ${what}. Why: ${why}. Where: ${where}` });
2823
+ console.log(chalk.green(' \u2713 Queued. Run "memory-core arch review" to approve.\n'));
2660
2824
  } else {
2661
2825
  console.log(chalk.dim(" Discarded.\n"));
2662
2826
  }
@@ -2683,7 +2847,7 @@ var authCmd = program.command("auth").description("Manage dashboard authenticati
2683
2847
  authCmd.command("setup").description("Create the first admin account (dashboard must be running with --auth)").option("--url <url>", "Dashboard URL", "http://localhost:5178").action(async (opts) => {
2684
2848
  const email = await input({ message: "Admin email:" });
2685
2849
  const username = await input({ message: "Admin username:" });
2686
- const password = await input({ message: "Password (min 8 chars):", transformer: () => "****" });
2850
+ const password = await promptPassword({ message: "Password (min 8 chars):" });
2687
2851
  const teamName = await input({ message: "Team name (optional):" });
2688
2852
  const res = await fetch(`${opts.url}/api/auth/setup`, {
2689
2853
  method: "POST",
@@ -2704,7 +2868,7 @@ authCmd.command("setup").description("Create the first admin account (dashboard
2704
2868
  });
2705
2869
  authCmd.command("login").description("Log in to a running dashboard (stores JWT locally)").option("--url <url>", "Dashboard URL", "http://localhost:5178").action(async (opts) => {
2706
2870
  const email = await input({ message: "Email:" });
2707
- const password = await input({ message: "Password:", transformer: () => "****" });
2871
+ const password = await promptPassword({ message: "Password:" });
2708
2872
  const res = await fetch(`${opts.url}/api/auth/login`, {
2709
2873
  method: "POST",
2710
2874
  headers: { "content-type": "application/json" },
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-K3NQKI34.js";
2
3
 
3
4
  // src/models/self-review.ts
4
5
  var SelfReviewValidator = class {
@@ -30,7 +31,7 @@ var ConfidenceGate = class {
30
31
  }
31
32
  config;
32
33
  selfReview = new SelfReviewValidator();
33
- async decide(packet, ollama, deepseek) {
34
+ async decide(packet, ollama, critique) {
34
35
  if (packet.violations.some((v) => v.rule.enforcement === "block")) {
35
36
  return { final: "block", source: "deterministic", ollama, selfReview: { valid: true, reason: "AST violation", issues: [] } };
36
37
  }
@@ -44,18 +45,19 @@ var ConfidenceGate = class {
44
45
  }
45
46
  return { final: "warn", source: "self-review", ollama, selfReview: sr };
46
47
  }
47
- if (this.config.escalateToDeepSeek && (ollama.confidence < this.config.warnConfidenceThreshold || ollama.decision === "warn")) {
48
- const ds = await deepseek(packet);
49
- return { final: ds.decision, source: "deepseek", ollama, deepseek: ds };
48
+ const HIGH_CONFIDENCE = 0.9;
49
+ if (this.config.escalateToCritique && ollama.confidence < HIGH_CONFIDENCE && (ollama.confidence < this.config.warnConfidenceThreshold || ollama.decision === "warn")) {
50
+ const cr = await critique(packet);
51
+ return { final: cr.decision, source: "critique", ollama, critique: cr };
50
52
  }
51
53
  return { final: ollama.decision === "block" ? "warn" : ollama.decision, source: "ollama", ollama };
52
54
  }
53
55
  };
54
- function defaultGateConfig(useDeepSeek = false) {
56
+ function defaultGateConfig(useCritique = false) {
55
57
  return {
56
58
  blockConfidenceThreshold: 0.75,
57
59
  warnConfidenceThreshold: 0.6,
58
- escalateToDeepSeek: useDeepSeek
60
+ escalateToCritique: useCritique
59
61
  };
60
62
  }
61
63
  export {