@shahmilsaari/memory-core 1.0.33 → 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.
- package/README.md +8 -6
- package/dist/{approval-queue-YBYRGBHP.js → approval-queue-4RK46FNE.js} +2 -1
- package/dist/{ast-analyzer-JM4CIOFY.js → ast-analyzer-WGTJKGAP.js} +1 -0
- package/dist/{check-cache-6NWRTZJD.js → check-cache-ZVFHTA2C.js} +1 -0
- package/dist/{check-logger-5HYSWA3S.js → check-logger-F4DW4LBY.js} +1 -0
- package/dist/chunk-2LNDQGDD.js +37 -0
- package/dist/{chunk-23GUWJ6F.js → chunk-4QWIYO2G.js} +3071 -3271
- package/dist/{chunk-GIPKVQSA.js → chunk-5T2QBBYT.js} +3 -29
- package/dist/chunk-FPRSYCOZ.js +77 -0
- package/dist/chunk-HJCPBM7B.js +238 -0
- package/dist/chunk-K3NQKI34.js +10 -0
- package/dist/chunk-SKR44CRD.js +35 -0
- package/dist/{chunk-W6WEAV3S.js → chunk-UMYJQWIE.js} +13 -11
- package/dist/{chunk-PQBWHAZN.js → chunk-XAE3RY5D.js} +5 -2
- package/dist/{classifier-MZ65R7FK.js → classifier-D5K3X7FQ.js} +1 -0
- package/dist/cli.js +246 -82
- package/dist/{confidence-gate-ZQDAOS6P.js → confidence-gate-AT2MW4NK.js} +8 -6
- package/dist/dashboard/assets/index-BcDOsQwz.css +1 -0
- package/dist/dashboard/assets/index-DGx4sRHq.js +2 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/{dashboard-server-LWMXEJHE.js → dashboard-server-UBZHOPRC.js} +273 -20
- package/dist/{db-FLFZZXG3.js → db-RE23O4DV.js} +3 -1
- package/dist/{deterministic-validator-PP56B46I.js → deterministic-validator-3LB234OG.js} +1 -0
- package/dist/draft-rule-NUXOSRRS.js +11 -0
- package/dist/embedding-VIMV6O2P.js +9 -0
- package/dist/{evidence-HVMSONTT.js → evidence-WFMGWSOP.js} +1 -0
- package/dist/{graph-TFNTB5OK.js → graph-UJJAKNHD.js} +1 -0
- package/dist/{incident-capture-RVPZULS7.js → incident-capture-5YUVJJM3.js} +11 -0
- package/dist/mcp-server-3N7R46BS.js +14958 -0
- package/dist/memory-selection-A5CQ6ZT5.js +29 -0
- package/dist/{deepseek-critique-MALVIYGF.js → model-critique-E2GNZ42U.js} +18 -32
- package/dist/{ollama-judge-D2LFK5PB.js → ollama-judge-6ZEZN4JV.js} +29 -41
- package/dist/{rate-limiter-SLIPCXRF.js → rate-limiter-KIMXTAAU.js} +1 -0
- package/dist/{rules-V3QMN3AR.js → rules-UUVIKEDM.js} +1 -0
- package/dist/{watch-errors-B3FA26N4.js → watch-errors-DZMW3CFN.js} +28 -33
- package/package.json +2 -1
- package/templates/AGENTS.md.hbs +11 -27
- package/templates/AI_RULES.md.hbs +9 -23
- package/templates/ARCHITECTURE.md.hbs +9 -30
- package/templates/CLAUDE.md.hbs +10 -35
- package/templates/DEVIN.md.hbs +7 -16
- package/templates/PROJECT_MEMORY.md.hbs +5 -21
- package/templates/amazonq-guidelines.md.hbs +7 -16
- package/templates/clinerules.hbs +8 -17
- package/templates/copilot-instructions.md.hbs +7 -16
- package/templates/cursor-rule.mdc.hbs +4 -9
- package/templates/cursorrules.hbs +8 -14
- package/templates/gemini-styleguide.md.hbs +7 -16
- package/templates/jetbrains-ai.md.hbs +6 -15
- package/templates/roo-rule.md.hbs +6 -15
- package/templates/windsurfrules.hbs +9 -18
- package/dist/dashboard/assets/index-DqbNcMwV.js +0 -2
- 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-
|
|
33
|
-
import "./chunk-
|
|
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-
|
|
39
|
-
import "./chunk-
|
|
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
|
|
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
|
-
"
|
|
185
|
-
"
|
|
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.
|
|
460
|
-
const embeddingModel = values.
|
|
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.
|
|
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.
|
|
564
|
-
printStatusLine("Embedding model", values.
|
|
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 ??
|
|
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
|
-
|
|
725
|
-
|
|
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 ||
|
|
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
|
-
|
|
871
|
-
|
|
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 ??
|
|
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-
|
|
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.
|
|
1946
|
-
values.
|
|
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.
|
|
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.
|
|
2002
|
-
values.
|
|
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-
|
|
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-
|
|
2251
|
-
const { ASTAnalyzer } = await import("./ast-analyzer-
|
|
2252
|
-
const { GraphBuilder } = await import("./graph-
|
|
2253
|
-
const { RuleMatcher } = await import("./rules-
|
|
2254
|
-
const { EvidencePacketBuilder } = await import("./evidence-
|
|
2255
|
-
const { DeterministicValidator } = await import("./deterministic-validator-
|
|
2256
|
-
const { OllamaJudge } = await import("./ollama-judge-
|
|
2257
|
-
const {
|
|
2258
|
-
const { ConfidenceGate, defaultGateConfig } = await import("./confidence-gate-
|
|
2259
|
-
const { CheckCache } = await import("./check-cache-
|
|
2260
|
-
const { CheckLogger } = await import("./check-logger-
|
|
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-
|
|
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
|
|
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.
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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}
|
|
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(
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
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
|
-
|
|
2620
|
-
|
|
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-
|
|
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
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
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-
|
|
2646
|
-
const { ApprovalQueue } = await import("./approval-queue-
|
|
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
|
|
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
|
-
|
|
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",
|
|
2659
|
-
console.log(chalk.green(' \u2713
|
|
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,12 +2847,12 @@ 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
|
|
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",
|
|
2690
2854
|
headers: { "content-type": "application/json" },
|
|
2691
|
-
body: JSON.stringify({ email, username, password
|
|
2855
|
+
body: JSON.stringify({ email, username, password, teamName: teamName || void 0 })
|
|
2692
2856
|
});
|
|
2693
2857
|
const data = await res.json();
|
|
2694
2858
|
if (!res.ok) {
|
|
@@ -2704,11 +2868,11 @@ 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
|
|
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" },
|
|
2711
|
-
body: JSON.stringify({ email, password
|
|
2875
|
+
body: JSON.stringify({ email, password })
|
|
2712
2876
|
});
|
|
2713
2877
|
const data = await res.json();
|
|
2714
2878
|
if (!res.ok) {
|
|
@@ -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,
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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(
|
|
56
|
+
function defaultGateConfig(useCritique = false) {
|
|
55
57
|
return {
|
|
56
58
|
blockConfidenceThreshold: 0.75,
|
|
57
59
|
warnConfidenceThreshold: 0.6,
|
|
58
|
-
|
|
60
|
+
escalateToCritique: useCritique
|
|
59
61
|
};
|
|
60
62
|
}
|
|
61
63
|
export {
|