@nxuss/lemma 0.5.9 β†’ 0.6.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
@@ -1,4 +1,4 @@
1
- # 🧠 Lemma v0.5.3
1
+ # 🧠 Lemma v0.6.0
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@nxuss/lemma.svg?color=orange&style=flat-square)](https://www.npmjs.com/package/@nxuss/lemma)
4
4
  [![License](https://img.shields.io/npm/l/@nxuss/lemma.svg?color=blue&style=flat-square)](https://github.com/Nxusbets/lemma/blob/main/LICENSE)
@@ -25,8 +25,20 @@ Lemma is a high-performance orchestration layer that sits between your developme
25
25
  ### πŸ–₯️ Real-Time Telemetry & Time-Travel Dashboard
26
26
  **Full Observability & Interactive Debugging.** Spin up a gorgeous React-based dashboard at `http://localhost:8081/dashboard/` to monitor your entire AI workflow. View real-time charts of cost savings, token compactions, and cache hits. Walk through complex multi-agent conversations step-by-step using a time-travel slider, select and inspect active agent states, and export detailed telemetry audits instantly.
27
27
 
28
- ### βœ‚οΈ Codebase Context Squeezer & Incremental Diff Engine
29
- **Massive Speedups & Zero Token Waste.** Get instant model responses and make your context windows go up to 10x further. Lemma dynamically optimizes outgoing codebase payloads to prevent redundant data from cluttering your chat, letting you enjoy incredibly long chat histories and ultra-fast generation speeds in Cursor, VS Code, and other IDEs without changing your workflow. Save up to 95% on token consumption automatically.
28
+ ### πŸ›Έ Kiro/Cursor Composer Bypass (Pro Option) πŸ’Ž
29
+ **Autonomous Multi-File Editing For Free.** Exposes `write_workspace_file`, smart `apply_workspace_patch` (smart search-and-replace patching), and sandbox terminal tool `run_workspace_command` (compile/lint check) to Cursor's standard chat or Claude Desktop via MCP. Any standard free chat instantly acts as a fully-featured, unlimited autonomous multi-file Composer without needing a premium Kiro/Cursor Pro subscription.
30
+
31
+ ### 🌌 AST Time-Travel Telemetry: El Multiverso de CΓ³digo (Pro Option) πŸ’Ž
32
+ **Regressive Error Debugging & Time-Travel.** Spawns a background recursive file watcher that debounces filesystem edits and calculates incremental AST diffs on every save. Merges active compiler crash logs to package a chronologically ordered time-traveling timeline resource (`lemma://multiverse/timeline`) so your LLM agents can inspect past codebase states and regressions instantly when you say "It broke".
33
+
34
+ ### πŸ—ΊοΈ Zero-Shot Project Onboarding (Pro Option) πŸ’Ž
35
+ **One-Shot Architecture Map.** Exposes a dynamic onboard resource (`lemma://project/onboarding`) that scans package files, folders, and key directory markers to compile a beautiful, structured markdown guide of your codebase's stack, directory layouts, and design principles so the LLM gets fully onboarded in a single shot.
36
+
37
+ ### 🧠 Cross-Project Bug Telepathy (Pro Option) πŸ’Ž
38
+ **Global Developer Hive Mind.** Lemma dynamically scans and queries vector memory indexes of all other local projects on your computer. If you solved a compiler issue or technical blocker in a different workspace last week, Lemma will telepathically inject that high-confidence solution to the current project's chat without you typing a single word.
39
+
40
+ ### βœ‚οΈ Codebase Context Squeezer & Log Collapsing
41
+ **Massive Speedups & Zero Token Waste.** Get instant model responses and make your context windows go up to 10x further. Lemma dynamically squeezes outgoing codebase payloads, strips comments/whitespaces, and collapses repetitive console logs or redundant compiler stack traces, saving up to 95% on token consumption automatically.
30
42
 
31
43
  ### πŸ›Έ Local Cache-Augmented Response Synthesis (CARS)
32
44
  **Zero-Cost Answer Synthesis.** Experience instantaneous responses for questions similar to what you've asked beforeβ€”without hitting the cloud or spending a single penny on API tokens. Lemma automatically refines past knowledge to answer your current questions in under a second, keeping your work completely private and free of charge.
@@ -141,8 +153,10 @@ Create or edit `lemma.config.json` in your project root to disable or fine-tune
141
153
  | **Privacy Firewall** | βœ… Included | βœ… Advanced Masking |
142
154
  | **Complexity Router** | βœ… Included | βœ… Custom Routing Policies |
143
155
  | **Caching** | Exact Match | **Semantic Memory** |
144
- | **Hive Mind** | Local Only | **Cloud Sync (Team Memory)** |
145
- | **Telepathy** | Basic Sync | **Advanced State Injection** |
156
+ | **Hive Mind** | Local Only | **Cloud Sync (Team Memory) + Cross-Project Telepathy πŸ’Ž** |
157
+ | **AST Time-Travel Telemetry** | ❌ None | **Codebase Multiverse (Cap 10 AST Snapshots) πŸ’Ž** |
158
+ | **Kiro/Cursor Composer Bypass** | ❌ None | **Smart Patches & Sandbox Terminal MCP πŸ’Ž** |
159
+ | **Zero-Shot Onboarding Guide** | ❌ None | **Codebase Architecture Map MCP πŸ’Ž** |
146
160
  | **Telemetry Dashboard** | Basic Stats | **Time-Travel Debugger & 60fps Graph** |
147
161
  | **Limits** | 300 requests/mo | **Unlimited Agentic Power** |
148
162
 
@@ -160,7 +174,7 @@ You don't need to change your habits. Just point your tool's "Base URL" to Lemma
160
174
  * **Custom Apps:** Replace `https://api.openai.com/v1` with `http://localhost:8081/v1` in your SDK initialization.
161
175
 
162
176
  ### πŸ’Ž Pro Integration (Model Context Protocol - MCP)
163
- For **Lemma Pro** users, you can expose Lemma's entire intelligence layer (Privacy Firewall, Semantic Brain Search, and Auto-Heal) directly as native tools using the **Model Context Protocol (MCP)**.
177
+ For **Lemma Pro** users, you can expose Lemma's entire intelligence layer (Privacy Firewall, Semantic Brain Search, and Auto-Heal, plus the new Composer Bypass Suite, AST Timeline, and Zero-Shot Onboarding Map) directly as native tools using the **Model Context Protocol (MCP)**. This lets the LLM read, search, write, patch, and compile files in your workspace autonomously.
164
178
 
165
179
  #### 🟒 Cursor:
166
180
  1. Go to **Settings > Features > MCP**.
@@ -1 +1 @@
1
- {"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AA8NA,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAkMnJ;AAED,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4DvF;AA+iDD,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KhL"}
1
+ {"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AA8NA,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAkMnJ;AAED,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4DvF;AAm2DD,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KhL"}
@@ -162,9 +162,9 @@ async function ensureChromaRunning() {
162
162
  }
163
163
  console.log(`\nπŸ“¦ \x1b[35m[ChromaDB]\x1b[0m ChromaDB is not running on port ${chromaPort}.`);
164
164
  console.log(`πŸ”„ Starting ChromaDB in background...`);
165
+ const chromaDataPath = path_1.default.join(CACHE_DIR, 'chroma_data');
165
166
  try {
166
167
  const { spawn } = require('child_process');
167
- const chromaDataPath = path_1.default.join(process.cwd(), 'chroma_data');
168
168
  if (!fs_1.default.existsSync(chromaDataPath)) {
169
169
  fs_1.default.mkdirSync(chromaDataPath, { recursive: true });
170
170
  }
@@ -187,7 +187,7 @@ async function ensureChromaRunning() {
187
187
  }
188
188
  catch (err) {
189
189
  console.error(`❌ Failed to automatically start ChromaDB: ${err.message}`);
190
- console.error(`πŸ‘‰ Please start it manually: chroma run --path ./chroma_data --port ${chromaPort}`);
190
+ console.error(`πŸ‘‰ Please start it manually: chroma run --path ${chromaDataPath} --port ${chromaPort}`);
191
191
  return false;
192
192
  }
193
193
  }
@@ -608,15 +608,16 @@ async function getEmbedding(text) {
608
608
  return null;
609
609
  }
610
610
  }
611
- async function semanticGet(provider, prompt) {
611
+ async function semanticGet(provider, prompt, projectName = 'global') {
612
612
  if (!await isPro())
613
613
  return null;
614
614
  const emb = await getEmbedding(prompt);
615
615
  if (!emb)
616
616
  return null;
617
+ let localHit = null;
617
618
  try {
618
619
  const collection = await chroma.getOrCreateCollection({
619
- name: 'lemma-cache',
620
+ name: `lemma-cache-${projectName}`,
620
621
  embeddingFunction: dummyEmbeddingFunction,
621
622
  metadata: { "hnsw:space": "cosine" }
622
623
  });
@@ -624,33 +625,83 @@ async function semanticGet(provider, prompt) {
624
625
  queryEmbeddings: [emb],
625
626
  nResults: 10
626
627
  });
627
- if (!res.ids[0] || res.ids[0].length === 0)
628
- return null;
629
- for (let i = 0; i < res.ids[0].length; i++) {
630
- const metadata = res.metadatas[0][i];
631
- if (metadata.provider !== provider)
632
- continue;
633
- const distances = res.distances;
634
- let distance = 1.0;
635
- if (distances && distances[0] && typeof distances[0][i] === 'number') {
636
- distance = distances[0][i];
637
- }
638
- const similarity = Math.max(0, 1 - distance);
639
- const THRESHOLD = 0.82; // raised from 0.7 to 0.82 to prevent false positives
640
- if (similarity >= THRESHOLD) {
641
- return {
642
- data: JSON.parse(metadata.response),
643
- similarity,
644
- id: res.ids[0][i],
645
- prompt: metadata.prompt
646
- };
628
+ if (res.ids[0] && res.ids[0].length > 0) {
629
+ for (let i = 0; i < res.ids[0].length; i++) {
630
+ const metadata = res.metadatas[0][i];
631
+ if (metadata.provider !== provider)
632
+ continue;
633
+ const distances = res.distances;
634
+ let distance = 1.0;
635
+ if (distances && distances[0] && typeof distances[0][i] === 'number') {
636
+ distance = distances[0][i];
637
+ }
638
+ const similarity = Math.max(0, 1 - distance);
639
+ const THRESHOLD = 0.82; // raised from 0.7 to 0.82 to prevent false positives
640
+ if (similarity >= THRESHOLD) {
641
+ localHit = {
642
+ data: JSON.parse(metadata.response),
643
+ similarity,
644
+ id: res.ids[0][i],
645
+ prompt: metadata.prompt,
646
+ hiveMind: false
647
+ };
648
+ break;
649
+ }
647
650
  }
648
651
  }
649
652
  }
650
653
  catch (e) { }
654
+ if (localHit)
655
+ return localHit;
656
+ // ─── Cross-Project Bug Telepathy Fallback ───
657
+ try {
658
+ const collections = await chroma.listCollections();
659
+ const projectCollections = collections.filter((c) => c.name.startsWith('lemma-cache-') && c.name !== `lemma-cache-${projectName}`);
660
+ for (const colInfo of projectCollections) {
661
+ try {
662
+ const col = await chroma.getOrCreateCollection({
663
+ name: colInfo.name,
664
+ embeddingFunction: dummyEmbeddingFunction,
665
+ metadata: { "hnsw:space": "cosine" }
666
+ });
667
+ const otherRes = await col.query({
668
+ queryEmbeddings: [emb],
669
+ nResults: 3
670
+ });
671
+ if (otherRes.ids[0] && otherRes.ids[0].length > 0) {
672
+ for (let i = 0; i < otherRes.ids[0].length; i++) {
673
+ const metadata = otherRes.metadatas[0][i];
674
+ if (metadata.provider !== provider)
675
+ continue;
676
+ const distances = otherRes.distances;
677
+ let distance = 1.0;
678
+ if (distances && distances[0] && typeof distances[0][i] === 'number') {
679
+ distance = distances[0][i];
680
+ }
681
+ const similarity = Math.max(0, 1 - distance);
682
+ const HIVE_THRESHOLD = 0.90; // Higher threshold to avoid false positives across different domains
683
+ if (similarity >= HIVE_THRESHOLD) {
684
+ const originProject = colInfo.name.replace('lemma-cache-', '');
685
+ console.log(`\n🎯 \x1b[32m[Hive Mind Telepathy]\x1b[0m Found a high-confidence solution (Similarity: ${(similarity * 100).toFixed(1)}%) in Project [\x1b[36m${originProject}\x1b[0m]! Reusing solution telepathically.\n`);
686
+ return {
687
+ data: JSON.parse(metadata.response),
688
+ similarity,
689
+ id: otherRes.ids[0][i],
690
+ prompt: metadata.prompt,
691
+ hiveMind: true,
692
+ originProject
693
+ };
694
+ }
695
+ }
696
+ }
697
+ }
698
+ catch { }
699
+ }
700
+ }
701
+ catch { }
651
702
  return null;
652
703
  }
653
- async function semanticSet(provider, prompt, data) {
704
+ async function semanticSet(provider, prompt, data, projectName = 'global') {
654
705
  if (!await isPro())
655
706
  return;
656
707
  const emb = await getEmbedding(prompt);
@@ -658,7 +709,7 @@ async function semanticSet(provider, prompt, data) {
658
709
  return;
659
710
  try {
660
711
  const collection = await chroma.getOrCreateCollection({
661
- name: 'lemma-cache',
712
+ name: `lemma-cache-${projectName}`,
662
713
  embeddingFunction: dummyEmbeddingFunction,
663
714
  metadata: { "hnsw:space": "cosine" }
664
715
  });
@@ -750,7 +801,7 @@ function setSseHeaders(res, fromCache, similarity, tier) {
750
801
  res.setHeader('Cache-Control', 'no-cache');
751
802
  res.setHeader('Connection', 'keep-alive');
752
803
  res.setHeader('X-Accel-Buffering', 'no');
753
- res.setHeader('X-Lemma-Cache', fromCache ? 'HIT' : 'MISS');
804
+ res.setHeader('X-Lemma-Cache', typeof fromCache === 'string' ? fromCache : (fromCache ? 'HIT' : 'MISS'));
754
805
  res.setHeader('X-Lemma-Similarity', (similarity || 1.0).toFixed(3));
755
806
  res.setHeader('X-Lemma-Tier', tier);
756
807
  }
@@ -766,8 +817,8 @@ function buildAntChunk(text, stop) {
766
817
  function buildGemChunk(text, stop) {
767
818
  return { candidates: [{ content: { parts: [{ text }] }, finishReason: stop ? 'STOP' : undefined }] };
768
819
  }
769
- async function simulateHitStream(res, cachedData, provider, model, tier, similarity) {
770
- setSseHeaders(res, true, similarity, tier);
820
+ async function simulateHitStream(res, cachedData, provider, model, tier, similarity, cacheHeader = 'HIT') {
821
+ setSseHeaders(res, cacheHeader, similarity, tier);
771
822
  const id = `lemma-${Date.now()}`;
772
823
  let text = '';
773
824
  try {
@@ -884,6 +935,8 @@ class LemmaServer {
884
935
  this.stats = {};
885
936
  this.dashboardPath = '';
886
937
  this.sessions = new Map();
938
+ this.timeline = [];
939
+ this.lastFileContents = new Map();
887
940
  this.port = port;
888
941
  this.projectName = projectName || detectProject();
889
942
  this.projectDir = ensureProjectDir(this.projectName);
@@ -891,6 +944,7 @@ class LemmaServer {
891
944
  this.app = (0, express_1.default)();
892
945
  this.setupMiddleware();
893
946
  this.setupRoutes();
947
+ this.startWorkspaceTimeWatcher();
894
948
  }
895
949
  setupMiddleware() {
896
950
  this.app.use(express_1.default.json({ limit: '10mb' }));
@@ -1046,7 +1100,7 @@ class LemmaServer {
1046
1100
  // Try to query ChromaDB for semantic cache count
1047
1101
  try {
1048
1102
  const collection = await chroma.getOrCreateCollection({
1049
- name: 'lemma-cache',
1103
+ name: `lemma-cache-${this.projectName}`,
1050
1104
  embeddingFunction: dummyEmbeddingFunction,
1051
1105
  metadata: { "hnsw:space": "cosine" }
1052
1106
  });
@@ -1103,7 +1157,7 @@ class LemmaServer {
1103
1157
  if (!emb)
1104
1158
  throw new Error('Failed to generate embedding');
1105
1159
  const collection = await chroma.getOrCreateCollection({
1106
- name: 'lemma-cache',
1160
+ name: `lemma-cache-${this.projectName}`,
1107
1161
  embeddingFunction: dummyEmbeddingFunction,
1108
1162
  metadata: { "hnsw:space": "cosine" }
1109
1163
  });
@@ -1152,7 +1206,7 @@ class LemmaServer {
1152
1206
  }
1153
1207
  // Clear Chroma DB collection
1154
1208
  try {
1155
- await chroma.deleteCollection({ name: 'lemma-cache' }).catch(() => { });
1209
+ await chroma.deleteCollection({ name: `lemma-cache-${this.projectName}` }).catch(() => { });
1156
1210
  }
1157
1211
  catch (e) {
1158
1212
  console.error(`[CacheClear] Failed to clear Chroma collection: ${e.message}`);
@@ -1169,7 +1223,7 @@ class LemmaServer {
1169
1223
  // Selective delete from Chroma DB collection using provider metadata filter
1170
1224
  try {
1171
1225
  const collection = await chroma.getOrCreateCollection({
1172
- name: 'lemma-cache',
1226
+ name: `lemma-cache-${this.projectName}`,
1173
1227
  embeddingFunction: dummyEmbeddingFunction,
1174
1228
  metadata: { "hnsw:space": "cosine" }
1175
1229
  });
@@ -1185,6 +1239,117 @@ class LemmaServer {
1185
1239
  this.app.get('/api/savings-breakdown', (req, res) => {
1186
1240
  res.json(SavingsLedger_1.savingsLedger.getSnapshot());
1187
1241
  });
1242
+ // Serve codebase timeline snapshots (AST Time-Travel Telemetry)
1243
+ this.app.get('/api/project/timeline', (req, res) => {
1244
+ res.json({ success: true, timeline: this.timeline });
1245
+ });
1246
+ // Dynamic Zero-Shot Onboarding mental model builder
1247
+ this.app.get('/api/project/onboarding', async (req, res) => {
1248
+ try {
1249
+ const cwd = process.cwd();
1250
+ // 1. Parse package.json
1251
+ let pkg = {};
1252
+ const pkgPath = path_1.default.join(cwd, 'package.json');
1253
+ if (fs_1.default.existsSync(pkgPath)) {
1254
+ try {
1255
+ pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
1256
+ }
1257
+ catch { }
1258
+ }
1259
+ // 2. Identify stack & tools
1260
+ const techStack = [];
1261
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
1262
+ if (deps['next'])
1263
+ techStack.push('Next.js (React Web App Framework)');
1264
+ else if (deps['react'])
1265
+ techStack.push('React.js (Frontend library)');
1266
+ if (deps['typescript'])
1267
+ techStack.push('TypeScript (Strict static type safety)');
1268
+ if (deps['prisma'])
1269
+ techStack.push('Prisma (Object-Relational Mapping)');
1270
+ if (deps['tailwindcss'])
1271
+ techStack.push('TailwindCSS (Utility-first styling)');
1272
+ if (deps['express'])
1273
+ techStack.push('Express (NodeJS REST API framework)');
1274
+ if (deps['jest'])
1275
+ techStack.push('Jest (Automated Unit Testing framework)');
1276
+ if (fs_1.default.existsSync(path_1.default.join(cwd, 'Dockerfile')) || fs_1.default.existsSync(path_1.default.join(cwd, 'docker-compose.yml'))) {
1277
+ techStack.push('Docker / Containerization');
1278
+ }
1279
+ if (techStack.length === 0) {
1280
+ techStack.push('Vanilla Node.js / Web stack');
1281
+ }
1282
+ // 3. Scan directory structure
1283
+ let files = [];
1284
+ try {
1285
+ files = fs_1.default.readdirSync(cwd).filter(f => !['node_modules', '.git', 'dist', 'chroma_data', '.lemma'].includes(f));
1286
+ }
1287
+ catch { }
1288
+ // 4. Query core architecture notes from ChromaDB
1289
+ let archMemoriesText = '';
1290
+ try {
1291
+ const emb = await getEmbedding("architectural design guidelines and core stack configuration decisions");
1292
+ if (emb) {
1293
+ const collection = await chroma.getOrCreateCollection({
1294
+ name: `lemma-cache-${this.projectName}`,
1295
+ embeddingFunction: dummyEmbeddingFunction,
1296
+ metadata: { "hnsw:space": "cosine" }
1297
+ });
1298
+ const searchRes = await collection.query({
1299
+ queryEmbeddings: [emb],
1300
+ nResults: 3
1301
+ });
1302
+ if (searchRes.ids[0] && searchRes.ids[0].length > 0) {
1303
+ archMemoriesText = '### 🧠 Stored Architectural Brain Memories\n';
1304
+ searchRes.ids[0].forEach((id, idx) => {
1305
+ const meta = (searchRes.metadatas && searchRes.metadatas[0]) ? searchRes.metadatas[0][idx] : null;
1306
+ if (meta && typeof meta.response === 'string') {
1307
+ try {
1308
+ const responseObj = JSON.parse(meta.response);
1309
+ const contentText = responseObj.choices?.[0]?.message?.content || responseObj.content?.[0]?.text || '';
1310
+ const promptText = typeof meta.prompt === 'string' ? meta.prompt : 'Architecture Note';
1311
+ archMemoriesText += `#### πŸ“Œ DecisiΓ³n: ${promptText}\n${contentText.substring(0, 500)}${contentText.length > 500 ? '...' : ''}\n\n`;
1312
+ }
1313
+ catch { }
1314
+ }
1315
+ });
1316
+ }
1317
+ }
1318
+ }
1319
+ catch (e) {
1320
+ // Silently swallow vector db query errors
1321
+ }
1322
+ // 5. Construct gorgeous onboarding markdown guide
1323
+ const mentalModel = [
1324
+ `# 🧠 Codebase Onboarding & Mental Model: ${this.projectName}`,
1325
+ `This onboarding document was automatically generated by Lemma's Project Brain to align your context in a single shot.`,
1326
+ `\n## πŸ”Œ Project Specifications`,
1327
+ `- **Name:** \`${pkg.name || this.projectName}\``,
1328
+ `- **Version:** \`${pkg.version || '0.1.0'}\``,
1329
+ `- **Description:** ${pkg.description || 'No description available in package.json.'}`,
1330
+ `\n## πŸ› οΈ Detected Technical Stack`,
1331
+ techStack.map(s => `- **${s}**`).join('\n'),
1332
+ `\n## πŸ“‚ Directory Structure (Root)`,
1333
+ files.map(f => {
1334
+ const isDir = fs_1.default.statSync(path_1.default.join(cwd, f)).isDirectory();
1335
+ return `- \`${f}${isDir ? '/' : ''}\``;
1336
+ }).join('\n'),
1337
+ pkg.scripts && Object.keys(pkg.scripts).length > 0
1338
+ ? `\n## πŸ“‹ Standard Project Scripts\n${Object.entries(pkg.scripts).map(([name, cmd]) => `- \`npm run ${name}\`: \`${cmd}\``).join('\n')}`
1339
+ : '',
1340
+ `\n${archMemoriesText}`,
1341
+ `## πŸ’‘ AI Coding Guidelines for this Project`,
1342
+ `1. **Respect Core Stack:** Adhere strictly to the codebase structure and libraries listed above.`,
1343
+ `2. **Leverage the Brain:** Use Lemma MCP tools (\`search_memory\` and \`store_memory\`) to retrieve past solutions and register key architectural changes.`,
1344
+ `3. **Optimize Context:** Keep conversations focused. Lemma transparently compresses repetitive logs and file blocks to protect context window limits.`,
1345
+ `4. **Cortafuegos Local:** Do not worry about API key exposures. Lemma automatically masks local private variables and credentials.`
1346
+ ].filter(Boolean).join('\n');
1347
+ res.json({ success: true, markdown: mentalModel });
1348
+ }
1349
+ catch (err) {
1350
+ res.status(500).json({ success: false, error: err.message });
1351
+ }
1352
+ });
1188
1353
  // Explicit memory storage endpoint (store_memory)
1189
1354
  this.app.post('/api/memory/store', async (req, res) => {
1190
1355
  const { query, response, provider = 'generic' } = req.body || {};
@@ -1197,7 +1362,7 @@ class LemmaServer {
1197
1362
  return res.status(500).json({ error: 'Failed to generate embedding' });
1198
1363
  }
1199
1364
  const collection = await chroma.getOrCreateCollection({
1200
- name: 'lemma-cache',
1365
+ name: `lemma-cache-${this.projectName}`,
1201
1366
  embeddingFunction: dummyEmbeddingFunction,
1202
1367
  metadata: { "hnsw:space": "cosine" }
1203
1368
  });
@@ -1276,6 +1441,105 @@ class LemmaServer {
1276
1441
  this.app.get('/dashboard/*', (req, res) => res.sendFile(path_1.default.join(this.dashboardPath, 'index.html')));
1277
1442
  }
1278
1443
  }
1444
+ startWorkspaceTimeWatcher() {
1445
+ const cwd = process.cwd();
1446
+ const { watch } = require('fs');
1447
+ // Debounced capture function
1448
+ let debounceTimer = null;
1449
+ const pendingChanges = new Set();
1450
+ const ignoreDirs = ['node_modules', '.git', 'dist', 'chroma_data', '.lemma', 'dashboard', 'bin', 'sdks'];
1451
+ const watchDirRecursive = (dir) => {
1452
+ try {
1453
+ const watcher = watch(dir, (eventType, filename) => {
1454
+ if (!filename)
1455
+ return;
1456
+ const fullPath = path_1.default.join(dir, filename);
1457
+ // Heuristic to ignore generated/system folders
1458
+ const relPath = path_1.default.relative(cwd, fullPath);
1459
+ if (ignoreDirs.some(d => relPath.split(path_1.default.sep).includes(d)))
1460
+ return;
1461
+ // Ignore non-source files
1462
+ const ext = path_1.default.extname(filename);
1463
+ if (!['.ts', '.js', '.tsx', '.jsx', '.json', '.py', '.css'].includes(ext))
1464
+ return;
1465
+ pendingChanges.add(fullPath);
1466
+ if (debounceTimer)
1467
+ clearTimeout(debounceTimer);
1468
+ debounceTimer = setTimeout(() => this.captureSnapshot(pendingChanges), 1500);
1469
+ });
1470
+ // Prevent watcher from keeping process alive if in background
1471
+ if (watcher.unref)
1472
+ watcher.unref();
1473
+ // Recursively watch subfolders
1474
+ const files = fs_1.default.readdirSync(dir, { withFileTypes: true });
1475
+ for (const file of files) {
1476
+ if (file.isDirectory() && !ignoreDirs.includes(file.name)) {
1477
+ watchDirRecursive(path_1.default.join(dir, file.name));
1478
+ }
1479
+ }
1480
+ }
1481
+ catch { }
1482
+ };
1483
+ watchDirRecursive(cwd); // Time travel watcher active!
1484
+ }
1485
+ async captureSnapshot(pendingChanges) {
1486
+ const changes = Array.from(pendingChanges);
1487
+ pendingChanges.clear();
1488
+ const changedFiles = [];
1489
+ for (const filePath of changes) {
1490
+ if (!fs_1.default.existsSync(filePath))
1491
+ continue;
1492
+ try {
1493
+ const content = fs_1.default.readFileSync(filePath, 'utf8');
1494
+ const relPath = path_1.default.relative(process.cwd(), filePath);
1495
+ const previousContent = this.lastFileContents.get(filePath) || '';
1496
+ if (content === previousContent)
1497
+ continue;
1498
+ let diff = '';
1499
+ if (previousContent) {
1500
+ const { generateAstDiff } = require('../utils/ContextSqueezer');
1501
+ diff = generateAstDiff(previousContent, content);
1502
+ }
1503
+ this.lastFileContents.set(filePath, content);
1504
+ changedFiles.push({
1505
+ filePath: relPath,
1506
+ content,
1507
+ diff
1508
+ });
1509
+ }
1510
+ catch { }
1511
+ }
1512
+ if (changedFiles.length === 0)
1513
+ return;
1514
+ // Detect current compiler state/errors
1515
+ let status = 'stable';
1516
+ let errorLog = '';
1517
+ // Check if there is a recent crash log in .lemma/live-context.md
1518
+ try {
1519
+ const liveContextPath = path_1.default.join(process.cwd(), '.lemma', 'live-context.md');
1520
+ if (fs_1.default.existsSync(liveContextPath)) {
1521
+ const content = fs_1.default.readFileSync(liveContextPath, 'utf8');
1522
+ if (content.includes('crashed') || content.includes('error') || content.includes('Exception')) {
1523
+ status = 'failure';
1524
+ errorLog = content.substring(0, 1000);
1525
+ }
1526
+ }
1527
+ }
1528
+ catch { }
1529
+ const snapshot = {
1530
+ id: Math.random().toString(36).substring(2, 9),
1531
+ timestamp: Date.now(),
1532
+ changedFiles,
1533
+ status,
1534
+ errorLog
1535
+ };
1536
+ this.timeline.push(snapshot);
1537
+ // Cap at 10 snapshots (FIFO eviction)
1538
+ if (this.timeline.length > 10) {
1539
+ this.timeline.shift();
1540
+ }
1541
+ console.log(`🌌 \x1b[35m[Multiverse]\x1b[0m Captured micro-snapshot ${snapshot.id} (${changedFiles.length} file edits mapped).`);
1542
+ }
1279
1543
  async handleCompletion(req, res, provider) {
1280
1544
  const t0 = Date.now();
1281
1545
  const pro = await isPro();
@@ -1312,16 +1576,20 @@ class LemmaServer {
1312
1576
  }
1313
1577
  // Perform semantic cache check (resolves in ~15ms)
1314
1578
  if (pro) {
1315
- const semHit = await semanticGet(provider, prompt);
1579
+ const semHit = await semanticGet(provider, prompt, this.projectName);
1316
1580
  if (semHit) {
1317
1581
  if (semHit.similarity >= 0.90) {
1318
1582
  await recordStat(this.stats, this.projectName, true, Date.now() - t0, provider, 2000);
1319
1583
  const unmaskedData = semanticScrubber.unmask(semHit.data, tokenMap);
1584
+ const cacheHeader = semHit.hiveMind ? 'HIT-HIVE-MIND' : 'HIT';
1320
1585
  if (isStream)
1321
- return simulateHitStream(res, unmaskedData, provider, originalModel, tier, semHit.similarity);
1322
- res.setHeader('X-Lemma-Cache', 'HIT');
1586
+ return simulateHitStream(res, unmaskedData, provider, originalModel, tier, semHit.similarity, cacheHeader);
1587
+ res.setHeader('X-Lemma-Cache', cacheHeader);
1323
1588
  res.setHeader('X-Lemma-Similarity', semHit.similarity.toFixed(3));
1324
1589
  res.setHeader('X-Lemma-Tier', tier);
1590
+ if (semHit.hiveMind && semHit.originProject) {
1591
+ res.setHeader('X-Lemma-Hive-Origin', semHit.originProject);
1592
+ }
1325
1593
  return res.json(unmaskedData);
1326
1594
  }
1327
1595
  else if (semHit.similarity >= 0.82) { // raised from 0.70 to 0.82 to prevent false positives
@@ -1469,7 +1737,7 @@ Adjusted Answer:`;
1469
1737
  const data = await this.callUpstream(req.body, provider);
1470
1738
  cacheSet(provider, prompt, data);
1471
1739
  if (pro) {
1472
- await semanticSet(provider, prompt, data);
1740
+ await semanticSet(provider, prompt, data, this.projectName);
1473
1741
  await cloudSync.set(prompt, data);
1474
1742
  }
1475
1743
  if (!pro) {
@@ -1724,7 +1992,11 @@ commander_1.program.command('start')
1724
1992
  if (opts.stack) {
1725
1993
  const { spawn } = require('child_process');
1726
1994
  console.log('πŸš€ Launching Lemma Full Stack...');
1727
- const chromaProcess = spawn('chroma', ['run', '--path', './chroma_data'], { stdio: 'ignore', detached: true });
1995
+ const chromaDataPath = path_1.default.join(CACHE_DIR, 'chroma_data');
1996
+ if (!fs_1.default.existsSync(chromaDataPath)) {
1997
+ fs_1.default.mkdirSync(chromaDataPath, { recursive: true });
1998
+ }
1999
+ const chromaProcess = spawn('chroma', ['run', '--path', chromaDataPath], { stdio: 'ignore', detached: true });
1728
2000
  chromaProcess.unref();
1729
2001
  console.log(' βœ… ChromaDB requested');
1730
2002
  const dash = spawn('npm', ['run', 'dev', '--prefix', 'dashboard', '--', '--port', '8082'], { stdio: 'ignore', detached: true });