chat-recall 0.6.4 → 0.6.5

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/mcp-relay.js CHANGED
@@ -118,7 +118,7 @@ function daemonEnabled() {
118
118
  }
119
119
 
120
120
  // src/mcp-relay.ts
121
- var VERSION = true ? "0.6.4" : "0.0.0";
121
+ var VERSION = true ? "0.6.5" : "0.0.0";
122
122
  var SERVER_URL = new URL("./mcp.js", import.meta.url);
123
123
  var SERVER_PATH = fileURLToPath(SERVER_URL);
124
124
  var START_TIMEOUT_MS = 15e3;
package/dist/mcp.js CHANGED
@@ -15259,12 +15259,12 @@ function extractEntities(text, context = {}) {
15259
15259
  if (chosen && looksLikeStrictTool(chosen) && looksLikeStrictTool(rejected)) {
15260
15260
  const c = canonTool(chosen), r = canonTool(rejected);
15261
15261
  if (projectName)
15262
- addTriple(projectName, "chose", c, 0.8);
15263
- addTriple(projectName || "project", "rejected", r, 0.7);
15264
- addTriple(c, "chosen_over", r, 0.8);
15262
+ addTriple(projectName, "chose", c, DECISION_GUESS_CONFIDENCE);
15263
+ addTriple(projectName || "project", "rejected", r, DECISION_GUESS_CONFIDENCE);
15264
+ addTriple(c, "chosen_over", r, DECISION_GUESS_CONFIDENCE);
15265
15265
  }
15266
15266
  } else if (chosen && looksLikeDecisionObject(chosen) && projectName) {
15267
- addTriple(projectName, "chose", canonTool(chosen), 0.8);
15267
+ addTriple(projectName, "chose", canonTool(chosen), DECISION_GUESS_CONFIDENCE);
15268
15268
  }
15269
15269
  }
15270
15270
  }
@@ -15301,7 +15301,7 @@ function extractEntities(text, context = {}) {
15301
15301
  }
15302
15302
  return triples;
15303
15303
  }
15304
- var KNOWN_TOOLS, AMBIGUOUS_TOOLS, toolContextRe, TOOL_PATTERNS, DECISION_PATTERNS2, DECISION_OBJECT_STOPWORDS, KNOWN_TOOL_NAMES, CANONICAL_TOOL, canonTool, PROJECT_PATH_PATTERN, PEOPLE_PATTERNS, NOT_PEOPLE;
15304
+ var KNOWN_TOOLS, AMBIGUOUS_TOOLS, toolContextRe, TOOL_PATTERNS, DECISION_PATTERNS2, DECISION_OBJECT_STOPWORDS, KNOWN_TOOL_NAMES, CANONICAL_TOOL, canonTool, DECISION_GUESS_CONFIDENCE, PROJECT_PATH_PATTERN, PEOPLE_PATTERNS, NOT_PEOPLE;
15305
15305
  var init_entity_extractor = __esm({
15306
15306
  "../engine/dist/core/entity-extractor.js"() {
15307
15307
  "use strict";
@@ -15522,6 +15522,7 @@ var init_entity_extractor = __esm({
15522
15522
  "nextjs": "next.js"
15523
15523
  };
15524
15524
  canonTool = (n) => CANONICAL_TOOL[n.toLowerCase()] ?? n;
15525
+ DECISION_GUESS_CONFIDENCE = 0.6;
15525
15526
  PROJECT_PATH_PATTERN = /\/(?:home|Users)\/\w+\/(?:code|projects|work|dev|src)\/(?:\w+\/)?([a-zA-Z][a-zA-Z0-9_-]{1,40})/g;
15526
15527
  PEOPLE_PATTERNS = [
15527
15528
  /\b(?:my name is|I'm|I am)\s+([A-Z][a-z]{1,15}(?:\s+[A-Z][a-z]{1,15})?)/g,
@@ -19727,7 +19728,7 @@ var init_http = __esm({
19727
19728
  CLI_VERSION = JSON.parse(readFileSync35(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
19728
19729
  } catch {
19729
19730
  try {
19730
- if (true) CLI_VERSION = "0.6.4";
19731
+ if (true) CLI_VERSION = "0.6.5";
19731
19732
  } catch {
19732
19733
  }
19733
19734
  }
@@ -20247,7 +20248,7 @@ var init_telemetry = __esm({
20247
20248
  init_sync_client();
20248
20249
  cliVersion2 = () => {
20249
20250
  try {
20250
- return true ? "0.6.4" : "dev";
20251
+ return true ? "0.6.5" : "dev";
20251
20252
  } catch {
20252
20253
  return "dev";
20253
20254
  }
@@ -22157,7 +22158,7 @@ var init_sync_client = __esm({
22157
22158
  ownVersion = JSON.parse(readFileSync37(join48(dir, "../package.json"), "utf-8")).version || ownVersion;
22158
22159
  } catch {
22159
22160
  try {
22160
- if (true) ownVersion = "0.6.4";
22161
+ if (true) ownVersion = "0.6.5";
22161
22162
  } catch {
22162
22163
  }
22163
22164
  }
@@ -23008,6 +23009,118 @@ function resumeCommandFor(sessionId, tool) {
23008
23009
 
23009
23010
  // ../engine/dist/mcp/tools.js
23010
23011
  init_project_resolver();
23012
+
23013
+ // ../engine/dist/core/decision-areas.js
23014
+ var DECISION_AREAS = [
23015
+ "auth",
23016
+ "database",
23017
+ "payments",
23018
+ "api",
23019
+ "frontend",
23020
+ "deploy",
23021
+ "testing",
23022
+ "observability",
23023
+ "security",
23024
+ "pricing",
23025
+ "licensing",
23026
+ "positioning"
23027
+ ];
23028
+ var AREA_SET = new Set(DECISION_AREAS);
23029
+ var AREA_ALIASES = {
23030
+ // auth
23031
+ authentication: "auth",
23032
+ authn: "auth",
23033
+ authz: "auth",
23034
+ authorisation: "auth",
23035
+ authorization: "auth",
23036
+ login: "auth",
23037
+ "sign-in": "auth",
23038
+ signin: "auth",
23039
+ sso: "auth",
23040
+ identity: "auth",
23041
+ // database
23042
+ db: "database",
23043
+ datastore: "database",
23044
+ storage: "database",
23045
+ persistence: "database",
23046
+ orm: "database",
23047
+ migrations: "database",
23048
+ // payments
23049
+ billing: "payments",
23050
+ payment: "payments",
23051
+ checkout: "payments",
23052
+ subscriptions: "payments",
23053
+ // api
23054
+ backend: "api",
23055
+ server: "api",
23056
+ rpc: "api",
23057
+ // frontend
23058
+ ui: "frontend",
23059
+ client: "frontend",
23060
+ web: "frontend",
23061
+ styling: "frontend",
23062
+ css: "frontend",
23063
+ // deploy
23064
+ deployment: "deploy",
23065
+ infra: "deploy",
23066
+ infrastructure: "deploy",
23067
+ hosting: "deploy",
23068
+ ci: "deploy",
23069
+ cd: "deploy",
23070
+ "ci-cd": "deploy",
23071
+ release: "deploy",
23072
+ // testing
23073
+ tests: "testing",
23074
+ test: "testing",
23075
+ qa: "testing",
23076
+ e2e: "testing",
23077
+ // observability
23078
+ monitoring: "observability",
23079
+ logging: "observability",
23080
+ metrics: "observability",
23081
+ alerting: "observability",
23082
+ tracing: "observability",
23083
+ // security
23084
+ secrets: "security",
23085
+ compliance: "security",
23086
+ privacy: "security",
23087
+ // pricing
23088
+ price: "pricing",
23089
+ plans: "pricing",
23090
+ tiers: "pricing",
23091
+ // licensing
23092
+ licence: "licensing",
23093
+ license: "licensing",
23094
+ // positioning
23095
+ marketing: "positioning",
23096
+ branding: "positioning",
23097
+ messaging: "positioning"
23098
+ };
23099
+ function canonArea(raw) {
23100
+ if (!raw)
23101
+ return null;
23102
+ const lowered = raw.trim().toLowerCase();
23103
+ if (!lowered)
23104
+ return null;
23105
+ const slug = lowered.replace(/[\s_/]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-{2,}/g, "-").replace(/^-|-$/g, "");
23106
+ if (!slug)
23107
+ return null;
23108
+ if (AREA_SET.has(slug))
23109
+ return slug;
23110
+ if (AREA_ALIASES[slug])
23111
+ return AREA_ALIASES[slug];
23112
+ return slug.slice(0, 40);
23113
+ }
23114
+ function isKnownArea(key2) {
23115
+ return !!key2 && AREA_SET.has(key2);
23116
+ }
23117
+ var ACCOUNT_SCOPE = "*";
23118
+ function decisionSubject(project, area) {
23119
+ const p = (project || "").trim() || ACCOUNT_SCOPE;
23120
+ return `${p}:${area}`;
23121
+ }
23122
+
23123
+ // ../engine/dist/mcp/tools.js
23011
23124
  import { config } from "dotenv";
23012
23125
 
23013
23126
  // ../engine/dist/mcp/diagnostics.js
@@ -23856,10 +23969,20 @@ var RecallDecisionRecordSchema = z.object({
23856
23969
  subject: z.string().describe('What the decision is about (e.g., "chat-recall", "auth strategy")'),
23857
23970
  decision: z.string().describe('The decision itself in plain words (e.g., "use Postgres full-text search as the default backend")'),
23858
23971
  reason: z.string().optional().describe("Why this was decided \u2014 short rationale"),
23972
+ // The key a reversal supersedes on. Without it the subject is free text, so
23973
+ // "auth", "authentication" and "auth setup" are three separate facts and a
23974
+ // later decision never closes an earlier one — see core/decision-areas.ts.
23975
+ area: z.string().optional().describe(`The area this decides, so a later decision about the SAME area supersedes it. Use one of: ${DECISION_AREAS.join(", ")} \u2014 or any short slug for an area not listed. Without it the decision is recorded but nothing it contradicts is closed.`),
23976
+ project: z.string().optional().describe("Project this decision applies to. Omit for an account-wide decision that applies everywhere."),
23859
23977
  importance: z.number().min(1).max(5).optional().default(4).describe("1\u20135; the classifier surfaces 4+ in wake-up context"),
23860
23978
  session_id: z.string().optional().describe("Session this decision was made in (for traceability)"),
23861
23979
  agent_name: z.string().optional().default("agent").describe("Who recorded the decision (for diary linkage)")
23862
23980
  });
23981
+ var RecallDecisionsSchema = z.object({
23982
+ area: z.string().optional().describe("Only this area"),
23983
+ project: z.string().optional().describe("Resolve for this project"),
23984
+ include_candidates: z.boolean().optional().default(false)
23985
+ });
23863
23986
  var RecallAnalyticsSummarySchema = z.object({
23864
23987
  // No required inputs — returns the same summary the dashboard renders.
23865
23988
  view: z.enum(["summary", "patterns"]).optional().default("summary").describe("summary = spend/activity rollup; patterns = behavioural patterns across sessions")
@@ -24008,6 +24131,7 @@ var LEAN_TOOLS = /* @__PURE__ */ new Set([
24008
24131
  "recall_kg_query",
24009
24132
  "recall_kg_add",
24010
24133
  "recall_decision_record",
24134
+ "recall_decisions",
24011
24135
  "recall_diary_write",
24012
24136
  "recall_diary_read",
24013
24137
  // Health, and the one that pays out on day one.
@@ -24904,13 +25028,19 @@ I asking yesterday?" or "what did I tell the agent in this session?".`,
24904
25028
  name: "recall_decision_record",
24905
25029
  description: `Record an explicit decision so it shows up in wake-up context. Writes a KG triple
24906
25030
  (subject \u2192 decided \u2192 decision) plus a diary entry. Use this when you and the user agree on
24907
- something non-obvious that future sessions should remember.`,
25031
+ something non-obvious that future sessions should remember.
25032
+
25033
+ PASS \`area\`. It is the key a reversal supersedes on: recording a new \`auth\` decision closes the
25034
+ previous \`auth\` one and leaves every other area alone. Without it the decision is stored but
25035
+ nothing it contradicts is closed, and both answers stay live forever.`,
24908
25036
  inputSchema: {
24909
25037
  type: "object",
24910
25038
  properties: {
24911
25039
  subject: { type: "string", description: "What the decision is about" },
24912
25040
  decision: { type: "string", description: "The decision itself" },
24913
25041
  reason: { type: "string", description: "Why this was decided" },
25042
+ area: { type: "string", description: `The area this decides, so a later decision on the same area supersedes it. Standard areas: ${DECISION_AREAS.join(", ")}. Any short slug works for an area not listed.` },
25043
+ project: { type: "string", description: "Project this applies to. Omit for an account-wide decision that applies everywhere." },
24914
25044
  importance: { type: "number", minimum: 1, maximum: 5, default: 4, description: "1-5. Only 4 and 5 surface in the wake-up bundle, so reserve those for decisions a future session must not miss." },
24915
25045
  session_id: { type: "string", description: "Session this decision came out of. Pass your own current session id so the decision can be traced back to the conversation that made it." },
24916
25046
  agent_name: { type: "string", default: "agent", description: "Which agent is recording this, so diary entries stay separable per agent." }
@@ -24918,6 +25048,25 @@ something non-obvious that future sessions should remember.`,
24918
25048
  required: ["subject", "decision"]
24919
25049
  }
24920
25050
  },
25051
+ {
25052
+ name: "recall_decisions",
25053
+ description: `What this codebase has already settled \u2014 read it BEFORE choosing a library, a
25054
+ datastore, an auth method or anything else in a decided area, and you will not rebuild what was
25055
+ already ruled out.
25056
+
25057
+ Returns one effective value per area with the cascade already resolved (project beats account;
25058
+ personal preferences fill gaps and never override a team decision), what each value replaced and
25059
+ when, and the session it came from. Also returns \`gaps\` \u2014 areas nobody has decided, where you are
25060
+ free to choose, and where recording the choice afterwards is worth doing.`,
25061
+ inputSchema: {
25062
+ type: "object",
25063
+ properties: {
25064
+ area: { type: "string", description: `Only this area. Standard areas: ${DECISION_AREAS.join(", ")}.` },
25065
+ project: { type: "string", description: "Resolve for this project, so its overrides win over account-wide decisions. Omit for the account-wide view." },
25066
+ include_candidates: { type: "boolean", default: false, description: "Also return unconfirmed guesses the indexer extracted. These are NOT decisions \u2014 never treat one as settled." }
25067
+ }
25068
+ }
25069
+ },
24921
25070
  {
24922
25071
  name: "recall_analytics_summary",
24923
25072
  description: `Cross-tool spend & activity overview. Returns total sessions, total cost,
@@ -27028,8 +27177,10 @@ ${JSON.stringify(r, null, 2)}
27028
27177
  const wal = getWAL();
27029
27178
  wal.log("decision_record", { subject: params.subject, importance: params.importance });
27030
27179
  const confidence = Math.min(1, params.importance / 5);
27180
+ const area = canonArea(params.area);
27181
+ const kgSubject = area ? decisionSubject(params.project, area) : params.subject;
27031
27182
  await remotePost("/api/kg/add", {
27032
- subject: params.subject,
27183
+ subject: kgSubject,
27033
27184
  predicate: "decided",
27034
27185
  object: params.decision,
27035
27186
  confidence,
@@ -27037,11 +27188,12 @@ ${JSON.stringify(r, null, 2)}
27037
27188
  });
27038
27189
  if (params.reason) {
27039
27190
  await remotePost("/api/kg/add", {
27040
- subject: params.subject,
27191
+ subject: kgSubject,
27041
27192
  predicate: "because",
27042
27193
  object: params.reason,
27043
27194
  confidence,
27044
- source_session: params.session_id
27195
+ source_session: params.session_id,
27196
+ supersede: false
27045
27197
  });
27046
27198
  }
27047
27199
  const diaryText = params.reason ? `Decided: ${params.decision}
@@ -27057,12 +27209,58 @@ Subject: ${params.subject}`;
27057
27209
  return {
27058
27210
  content: [{
27059
27211
  type: "text",
27060
- text: `Decision recorded.
27061
- - KG: ${params.subject} \u2192 decided \u2192 ${params.decision}
27062
- - Diary entry: ${diary.id} (importance ${params.importance})`
27212
+ text: [
27213
+ "Decision recorded.",
27214
+ `- KG: ${kgSubject} \u2192 decided \u2192 ${params.decision}`,
27215
+ area ? `- Area: ${area}${isKnownArea(area) ? "" : " (not a standard area \u2014 kept as a slug)"} \xB7 a later decision on this area supersedes this one` : "- No area given, so nothing this contradicts was closed. Pass `area` to make reversals work.",
27216
+ `- Diary entry: ${diary.id} (importance ${params.importance})`
27217
+ ].join("\n")
27063
27218
  }]
27064
27219
  };
27065
27220
  }
27221
+ // ── The decision register ──────────────────────────────────
27222
+ case "recall_decisions": {
27223
+ const p = RecallDecisionsSchema.parse(args ?? {});
27224
+ requireRemote();
27225
+ const r = await remoteGetQS("/api/decisions", {
27226
+ project: p.project,
27227
+ include_candidates: p.include_candidates ? "1" : "0"
27228
+ });
27229
+ const rows = p.area ? r.decisions.filter((d) => d.area === canonArea(p.area)) : r.decisions;
27230
+ const lines = [];
27231
+ lines.push(r.project ? `Decisions for ${r.project}` : "Decisions \u2014 account-wide");
27232
+ if (rows.length === 0) {
27233
+ lines.push("", p.area ? `Nothing decided for "${p.area}". You are free to choose \u2014 record it afterwards with recall_decision_record.` : "Nothing decided yet.");
27234
+ } else {
27235
+ lines.push("");
27236
+ for (const d of rows) {
27237
+ const tags = [
27238
+ d.override ? "OVERRIDES ACCOUNT" : "",
27239
+ d.inherited ? "inherited from account" : "",
27240
+ d.advisory ? "advisory \u2014 a personal preference, not binding" : ""
27241
+ ].filter(Boolean).join(" \xB7 ");
27242
+ lines.push(`${d.area}: ${d.value}${d.since ? ` (since ${d.since})` : ""}${tags ? ` [${tags}]` : ""}`);
27243
+ if (d.why)
27244
+ lines.push(` why: ${d.why}`);
27245
+ const replaced = d.history.filter((h) => !h.current);
27246
+ for (const h of replaced)
27247
+ lines.push(` replaced: ${h.value} (ended ${h.to})`);
27248
+ if (d.source_session)
27249
+ lines.push(` from session ${d.source_session}`);
27250
+ }
27251
+ }
27252
+ if (!p.area && r.gaps.length) {
27253
+ lines.push("", `Not decided: ${r.gaps.map((g) => g.area).join(", ")}`);
27254
+ lines.push("Free to choose in these. Record the choice so the next session inherits it.");
27255
+ }
27256
+ if (p.include_candidates && r.candidates?.length) {
27257
+ lines.push("", "Unconfirmed guesses from indexing \u2014 NOT decisions, do not treat as settled:");
27258
+ for (const c of r.candidates.slice(0, 10)) {
27259
+ lines.push(` ${c.value} (seen ${c.mentions}\xD7${c.last_seen ? `, latest ${c.last_seen}` : ""})`);
27260
+ }
27261
+ }
27262
+ return { content: [{ type: "text", text: lines.join("\n") }] };
27263
+ }
27066
27264
  // ── Analytics summary ──────────────────────────────────────
27067
27265
  case "recall_analytics_summary": {
27068
27266
  const analyticsParams = RecallAnalyticsSummarySchema.parse(args ?? {});
@@ -27808,7 +28006,7 @@ function installCrashGuards() {
27808
28006
  reportClientEvent2("mcp_crash", { message: err.stack || err.message });
27809
28007
  });
27810
28008
  }
27811
- var RELAY_VERSION = true ? "0.6.4" : "0.0.0";
28009
+ var RELAY_VERSION = true ? "0.6.5" : "0.0.0";
27812
28010
  function daemonIdleSecs() {
27813
28011
  const raw = process.env.CHAT_RECALL_DAEMON_IDLE_SECS;
27814
28012
  if (raw === void 0) return 900;
package/dist/watch.js CHANGED
@@ -13769,12 +13769,12 @@ function extractEntities(text, context = {}) {
13769
13769
  if (chosen && looksLikeStrictTool(chosen) && looksLikeStrictTool(rejected)) {
13770
13770
  const c = canonTool(chosen), r = canonTool(rejected);
13771
13771
  if (projectName)
13772
- addTriple(projectName, "chose", c, 0.8);
13773
- addTriple(projectName || "project", "rejected", r, 0.7);
13774
- addTriple(c, "chosen_over", r, 0.8);
13772
+ addTriple(projectName, "chose", c, DECISION_GUESS_CONFIDENCE);
13773
+ addTriple(projectName || "project", "rejected", r, DECISION_GUESS_CONFIDENCE);
13774
+ addTriple(c, "chosen_over", r, DECISION_GUESS_CONFIDENCE);
13775
13775
  }
13776
13776
  } else if (chosen && looksLikeDecisionObject(chosen) && projectName) {
13777
- addTriple(projectName, "chose", canonTool(chosen), 0.8);
13777
+ addTriple(projectName, "chose", canonTool(chosen), DECISION_GUESS_CONFIDENCE);
13778
13778
  }
13779
13779
  }
13780
13780
  }
@@ -13811,7 +13811,7 @@ function extractEntities(text, context = {}) {
13811
13811
  }
13812
13812
  return triples;
13813
13813
  }
13814
- var KNOWN_TOOLS, AMBIGUOUS_TOOLS, toolContextRe, TOOL_PATTERNS, DECISION_PATTERNS2, DECISION_OBJECT_STOPWORDS, KNOWN_TOOL_NAMES, CANONICAL_TOOL, canonTool, PROJECT_PATH_PATTERN, PEOPLE_PATTERNS, NOT_PEOPLE;
13814
+ var KNOWN_TOOLS, AMBIGUOUS_TOOLS, toolContextRe, TOOL_PATTERNS, DECISION_PATTERNS2, DECISION_OBJECT_STOPWORDS, KNOWN_TOOL_NAMES, CANONICAL_TOOL, canonTool, DECISION_GUESS_CONFIDENCE, PROJECT_PATH_PATTERN, PEOPLE_PATTERNS, NOT_PEOPLE;
13815
13815
  var init_entity_extractor = __esm({
13816
13816
  "../engine/dist/core/entity-extractor.js"() {
13817
13817
  "use strict";
@@ -14032,6 +14032,7 @@ var init_entity_extractor = __esm({
14032
14032
  "nextjs": "next.js"
14033
14033
  };
14034
14034
  canonTool = (n) => CANONICAL_TOOL[n.toLowerCase()] ?? n;
14035
+ DECISION_GUESS_CONFIDENCE = 0.6;
14035
14036
  PROJECT_PATH_PATTERN = /\/(?:home|Users)\/\w+\/(?:code|projects|work|dev|src)\/(?:\w+\/)?([a-zA-Z][a-zA-Z0-9_-]{1,40})/g;
14036
14037
  PEOPLE_PATTERNS = [
14037
14038
  /\b(?:my name is|I'm|I am)\s+([A-Z][a-z]{1,15}(?:\s+[A-Z][a-z]{1,15})?)/g,
@@ -18304,7 +18305,7 @@ var init_http = __esm({
18304
18305
  CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
18305
18306
  } catch {
18306
18307
  try {
18307
- if (true) CLI_VERSION = "0.6.4";
18308
+ if (true) CLI_VERSION = "0.6.5";
18308
18309
  } catch {
18309
18310
  }
18310
18311
  }
@@ -18820,7 +18821,7 @@ var init_telemetry = __esm({
18820
18821
  init_sync_client();
18821
18822
  cliVersion = () => {
18822
18823
  try {
18823
- return true ? "0.6.4" : "dev";
18824
+ return true ? "0.6.5" : "dev";
18824
18825
  } catch {
18825
18826
  return "dev";
18826
18827
  }
@@ -20763,7 +20764,7 @@ var init_sync_client = __esm({
20763
20764
  ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
20764
20765
  } catch {
20765
20766
  try {
20766
- if (true) ownVersion = "0.6.4";
20767
+ if (true) ownVersion = "0.6.5";
20767
20768
  } catch {
20768
20769
  }
20769
20770
  }
@@ -23847,7 +23848,7 @@ try {
23847
23848
  ownVersion2 = JSON.parse(readFileSync39(join48(dir, "../package.json"), "utf-8")).version || ownVersion2;
23848
23849
  } catch {
23849
23850
  try {
23850
- if (true) ownVersion2 = "0.6.4";
23851
+ if (true) ownVersion2 = "0.6.5";
23851
23852
  } catch {
23852
23853
  }
23853
23854
  }
@@ -24195,7 +24196,7 @@ async function runCollectorMigration(opts) {
24195
24196
  init_sync_ledger();
24196
24197
  init_collector_health();
24197
24198
  import { existsSync as existsSync49, readFileSync as readFileSync45, statSync as statSync44 } from "fs";
24198
- var CLI_VERSION3 = true ? "0.6.4" : "0.0.0";
24199
+ var CLI_VERSION3 = true ? "0.6.5" : "0.0.0";
24199
24200
  var DEBOUNCE_MS = 5e3;
24200
24201
  var CLAUDE_DIR = claudeBackend.projectsDir();
24201
24202
  var PLANS_DIR = claudeBackend.plansDir();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chat-recall",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/munhq/chat-recall.git"
@@ -29,7 +29,7 @@ All tools are MCP tools on the `chat-recall` server, named
29
29
  **Reads are safe to call proactively. Writes are not.** Everything below is a
30
30
  read except these, which change stored memory or state — treat each as an edit
31
31
  and apply the test in `chat-recall-memory` before calling one:
32
- `recall_kg_add`, `recall_kg_invalidate`, `recall_decision_record`,
32
+ `recall_kg_add`, `recall_kg_invalidate`, `recall_decision_record`, `recall_decisions`,
33
33
  `recall_diary_write`, `recall_set`, `recall_task_create`, `recall_task_update`,
34
34
  `recall_task_comment`,
35
35
  `recall_task_policy`,
@@ -88,6 +88,7 @@ CLAUDE.md rule is additive and reversible, so take it; ask first before setting
88
88
  **Findings, ranked** — `recall_claude_suggestions` (every finding that becomes an agent-instruction change — the CLAUDE.md rules and skill installs — merged across account scope and every indexed project) and `recall_improvements` (everything else, most urgent first; `create_tasks: true` opens one team task per item). They split the same engines, so an item never appears in both. Neither needs the codeindex binary: without it you still get the account-level half.
89
89
  **What changed** — `recall_edits_timeline` (cross-tool edits), `recall_diff` (per-session diffs), `recall_commits` (did it actually land), `recall_markers` (where a session went sideways).
90
90
  **Durable memory / KG** — `recall_kg_query` / `recall_kg_add` / `recall_kg_invalidate` / `recall_kg_timeline` / `recall_kg_stats`, `recall_decision_record`, `recall_diary_write` / `recall_diary_read`, `recall_set` / `recall_get`.
91
+ **Decisions** — `recall_decisions` (what is already settled per area, cascade resolved; call it before choosing a library or a datastore).
91
92
  **Team** — `recall_tasks` (the shared task board), `recall_task_create`, `recall_task_update` (status, assignee, linked session; task ids look like `t_…`; when you start work on a task, set it `in_progress` and pass your session id as `linked_session_id` so the board can verify the work shipped), `recall_task_comment` (leave a progress note on a card), `recall_task_policy` (read or change WHAT the board files — severity floor, open-card ceiling, cards per run, categories, and the projects that never file at all via `exclude_project` — reach for that one when the user says "do not put work on my board for this repo", e.g. a client's codebase they keep separate; call it with no arguments to read, and reach for it when the user says "only security", "high and critical for now", or asks why a full board has stopped filing), `recall_team_activity` (per-teammate × per-project rollup), `recall_shares` (which projects are shared — private by default, nothing is visible to teammates until shared).
92
93
  **Toolkit sync across tools and devices** — `recall_toolkit_status` (which MCP servers, skills, commands and agents exist, on which tool, on which device — and which of them can be installed elsewhere at all), `recall_toolkit_sync` (queue an install: everything or one type, every device or one machine, or fan a machine's own artifacts across its own tools). Reach for these on "set up my other laptop", "get my MCPs everywhere", "why does this tool not have my skill".
93
94
 
@@ -26,11 +26,27 @@ future sessions inherit them.
26
26
  - `mcp__chat-recall__recall_diary_read` — prior agent diary entries (narrative
27
27
  notes across sessions). `mcp__chat-recall__recall_get` — a scoped key/value.
28
28
 
29
+ ## Check what is already decided (do this BEFORE you choose)
30
+
31
+ - `mcp__chat-recall__recall_decisions` — the decision register, cascade already
32
+ resolved: one value per area (auth, database, payments, deploy, pricing,
33
+ licensing…), what it replaced and when, and the session behind it. Call it
34
+ before picking a library, a datastore or an auth method. If the area is
35
+ already decided, follow it or say plainly that you are proposing a reversal.
36
+ It also returns `gaps` — areas nobody has decided, where you are free to
37
+ choose and should record the choice afterwards.
38
+
39
+ Project overrides beat account-wide decisions. A personal preference is
40
+ returned marked `advisory` and never overrides a team decision.
41
+
29
42
  ## Record new knowledge (do this when something non-obvious is decided)
30
43
 
31
44
  - `mcp__chat-recall__recall_decision_record` — an explicit decision (subject,
32
- decision, reason, importance). Shows up in future wake-up context. Use the
33
- moment you and the user agree on something a later session would need.
45
+ decision, reason, importance). **Pass `area`**: it is the key a reversal
46
+ supersedes on, so recording a new `auth` decision closes the previous one and
47
+ leaves every other area alone. Without it nothing the decision contradicts is
48
+ closed. Shows up in future wake-up context. Use the moment you and the user
49
+ agree on something a later session would need.
34
50
  - `mcp__chat-recall__recall_kg_add` — assert a fact triple
35
51
  (subject → predicate → object, optional `valid_from`). E.g.
36
52
  `("chat-recall", "uses", "Postgres")`.