brainllm 12.0.0 → 12.1.0

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 CHANGED
@@ -10,7 +10,7 @@ A persistent, graph-structured second brain for Claude and any MCP client — bu
10
10
 
11
11
  [**brainllm site**](https://miisodev.github.io/BrainLLM/) · [How it works](https://miisodev.github.io/BrainLLM/how-it-works.html) · [Use cases](https://miisodev.github.io/BrainLLM/use-cases.html) · [Docs](https://miisodev.github.io/BrainLLM/docs.html)
12
12
 
13
- [![Version](https://img.shields.io/badge/version-12.0.0-f59e0b?style=flat-square)](https://github.com/miisodev/BrainLLM/releases)
13
+ [![Version](https://img.shields.io/badge/version-12.1.0-f59e0b?style=flat-square)](https://github.com/miisodev/BrainLLM/releases)
14
14
  [![CI](https://img.shields.io/github/actions/workflow/status/miisodev/BrainLLM/ci.yml?branch=main&style=flat-square&label=CI&color=f59e0b)](https://github.com/miisodev/BrainLLM/actions/workflows/ci.yml)
15
15
  [![License: MIT](https://img.shields.io/badge/license-MIT-a1a1aa?style=flat-square)](./LICENSE)
16
16
  [![Runtime: Bun](https://img.shields.io/badge/runtime-Bun%20%E2%89%A5%201.0-a1a1aa?style=flat-square&logo=bun&logoColor=white)](https://bun.sh)
package/dist/index.js CHANGED
@@ -25454,6 +25454,9 @@ var SingletonKinds = [
25454
25454
  "protocols",
25455
25455
  "selfcorrection"
25456
25456
  ];
25457
+ function isSingletonKind(k) {
25458
+ return SingletonKinds.includes(k);
25459
+ }
25457
25460
  var Statuses = ["active", "resolved", "superseded", "dormant", "eternal"];
25458
25461
  var RelationTypes = [
25459
25462
  "relatesTo",
@@ -27243,7 +27246,7 @@ function structureRuleFor(kind) {
27243
27246
 
27244
27247
  // src/router.ts
27245
27248
  function isSingleton(kind) {
27246
- return SingletonKinds.includes(kind);
27249
+ return isSingletonKind(kind);
27247
27250
  }
27248
27251
  function kindHome(cfg, kind) {
27249
27252
  switch (kind) {
@@ -28739,12 +28742,13 @@ rather than listing them unconditionally for every caller to work around.`, {
28739
28742
  const relations = relationSnippet(note);
28740
28743
  return { id, lastModified: note.dateModified.slice(0, 10), content, ...relations ? { relations } : {} };
28741
28744
  };
28742
- const [biography, goals, preferences, responsibilities, protocols] = await Promise.all([
28745
+ const [biography, goals, preferences, responsibilities, protocols, selfcorrection] = await Promise.all([
28743
28746
  fetchSingleton(cfg.master.biography),
28744
28747
  fetchSingleton(cfg.master.goals),
28745
28748
  fetchSingleton(cfg.master.preferences),
28746
28749
  fetchSingleton(cfg.llm.responsibilities),
28747
- fetchSingleton(cfg.llm.protocols)
28750
+ fetchSingleton(cfg.llm.protocols),
28751
+ cfg.llm.selfcorrection ? fetchSingleton(cfg.llm.selfcorrection) : Promise.resolve(null)
28748
28752
  ]);
28749
28753
  let diaryEntry = null;
28750
28754
  if (cfg.llm.diary) {
@@ -28764,14 +28768,15 @@ rather than listing them unconditionally for every caller to work around.`, {
28764
28768
  const contents = await Promise.all(candidates.map((n) => trilium.getNoteContent(n.noteId).catch(() => "")));
28765
28769
  return contents.filter(hasAddendumMarker).length;
28766
28770
  }).catch(() => null);
28767
- const singletonStubs = [
28768
- ["biography", biography],
28769
- ["goals", goals],
28770
- ["preferences", preferences],
28771
- ["responsibilities", responsibilities],
28772
- ["protocols", protocols]
28773
- ];
28774
- const touchedToday = singletonStubs.filter(([, s]) => s.lastModified === d).map(([name]) => name);
28771
+ const singletonStubs = {
28772
+ biography,
28773
+ goals,
28774
+ preferences,
28775
+ responsibilities,
28776
+ protocols,
28777
+ selfcorrection
28778
+ };
28779
+ const touchedToday = Object.keys(singletonStubs).filter((k) => singletonStubs[k]?.lastModified === d);
28775
28780
  const pending = {
28776
28781
  addendums: pendingAddendums === null ? "unknown" : pendingAddendums,
28777
28782
  maintenanceFlags: hygiene?.flagged.length ?? 0,
@@ -28784,19 +28789,19 @@ rather than listing them unconditionally for every caller to work around.`, {
28784
28789
  ...scoped ? { scope: "agent" } : {},
28785
28790
  ...!full ? { mode: "light", note: "Singleton content and the diary body are omitted (default) \u2014 fetch via master()/llm() only where lastModified indicates a revision is needed; start() already served all singletons in full, and diary() needs only the id." } : {},
28786
28791
  master: { biography, goals, preferences },
28787
- llm: { responsibilities, protocols },
28792
+ llm: { responsibilities, protocols, ...selfcorrection ? { selfcorrection } : {} },
28788
28793
  diary: diaryEntry,
28789
28794
  maintenance: hygiene ? { scanned: hygiene.scanned, fixed: hygiene.fixed.length, transitions: hygiene.transitions, flagged: hygiene.flagged, ...hygiene.suppressed ? { suppressed: hygiene.suppressed } : {} } : "skipped",
28790
28795
  pending,
28791
28796
  audit: scoped ? undefined : {
28792
- consistency: "Read all five singletons and check for ambiguity, internal contradiction, or claims that disagree across them. Fix what you find with revise() BEFORE close(), so the log records a brain that already agrees with itself.",
28797
+ consistency: "Read every singleton and check for ambiguity, internal contradiction, or claims that disagree across them. Fix what you find with revise() BEFORE close(), so the log records a brain that already agrees with itself.",
28793
28798
  alignment: "Then check correlation, not just agreement: do responsibilities and protocols actually serve what biography, goals and preferences describe? A protocol can be perfectly consistent and still be serving a goal that has moved.",
28794
- readThem: `master("biography"|"goals"|"preferences") and llm("responsibilities"|"protocols") \u2014 or one section at a time with section=. Written today: ${touchedToday.length ? touchedToday.join(", ") : "none"}.`
28799
+ readThem: `master("biography"|"goals"|"preferences") and llm("responsibilities"|"protocols"|"selfcorrection") \u2014 or one section at a time with section=. Written today: ${touchedToday.length ? touchedToday.join(", ") : "none"}.`
28795
28800
  },
28796
28801
  next: [
28797
28802
  ...scoped ? ["Scoped run \u2014 the user's master singletons and your LLM singletons are OUT of scope and deliberately not listed here."] : [
28798
28803
  "Update master singletons (biography / goals / preferences) via revise() with session observations about the user.",
28799
- "Update LLM singletons (responsibilities / protocols) via revise() with session observations about yourself."
28804
+ "Update LLM singletons (responsibilities / protocols / selfcorrection) via revise() with session observations about yourself \u2014 selfcorrection takes what you got WRONG and what generalises from it, not what you did."
28800
28805
  ],
28801
28806
  ...scoped ? [] : ["Audit the singletons against each other and against each other's PURPOSE \u2014 see audit= above. This is the step that catches an operating rule still serving a goal that has moved."],
28802
28807
  scoped ? `Call addendum() \u2014 fold only what is in your lane; leaving out-of-scope addendums for the next interactive session is correct, and the call itself satisfies the gate. (${pending.addendums} note(s) currently carry addendum markers.)` : pending.addendums === 0 ? "Call addendum() \u2014 0 notes currently carry addendum markers, so this should come back clean; the call still satisfies the gate." : `Call addendum() \u2014 ${pending.addendums} note(s) carry addendum markers; fold each into its section.`,
@@ -32431,7 +32436,7 @@ function createServer(origin = null) {
32431
32436
  const s = new McpServer({
32432
32437
  name: "BrainLLM",
32433
32438
  title: "BrainLLM",
32434
- version: "12.0.0",
32439
+ version: "12.1.0",
32435
32440
  icons: brandingIcons(origin)
32436
32441
  });
32437
32442
  registerTools(s, trilium, brainRef);
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "dxt_version": "0.1",
3
3
  "name": "brainllm",
4
4
  "display_name": "BrainLLM",
5
- "version": "12.0.0",
5
+ "version": "12.1.0",
6
6
  "description": "Turns TriliumNext Notes into a persistent, graph-structured second brain for Claude and other LLM clients.",
7
7
  "long_description": "BrainLLM is an MCP server that organises memory into five purpose-built areas (Master, LLM, Memory, Knowledge, Insights). The model supplies content while the server owns placement, format, lifecycle, dates and backups. Includes a full raw ETAPI surface for advanced use. Requires a running TriliumNext instance and the Bun runtime.",
8
8
  "author": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainllm",
3
- "version": "12.0.0",
3
+ "version": "12.1.0",
4
4
  "mcpName": "io.github.miisodev/brainllm",
5
5
  "description": "MCP server that turns TriliumNext Notes into a persistent, graph-structured second brain for Claude and other LLM clients.",
6
6
  "author": "Kevin Miiso Novo <miisodev@gmail.com>",
package/server.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.miisodev/brainllm",
4
4
  "description": "Persistent graph-structured memory for LLMs in TriliumNext Notes — readable and editable by humans.",
5
- "version": "12.0.0",
5
+ "version": "12.1.0",
6
6
  "websiteUrl": "https://github.com/miisodev/BrainLLM#readme",
7
7
  "repository": {
8
8
  "url": "https://github.com/miisodev/BrainLLM",
@@ -12,7 +12,7 @@
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "brainllm",
15
- "version": "12.0.0",
15
+ "version": "12.1.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },