@nxuss/lemma 1.8.0 → 1.9.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.
Files changed (76) hide show
  1. package/README.md +126 -176
  2. package/dist/cjs/mcp/prompts.d.ts +10 -1
  3. package/dist/cjs/mcp/prompts.d.ts.map +1 -1
  4. package/dist/cjs/mcp/prompts.js +25 -73
  5. package/dist/cjs/mcp/prompts.js.map +1 -1
  6. package/dist/cjs/mcp/tool-profiles.d.ts +10 -1
  7. package/dist/cjs/mcp/tool-profiles.d.ts.map +1 -1
  8. package/dist/cjs/mcp/tool-profiles.js +12 -3
  9. package/dist/cjs/mcp/tool-profiles.js.map +1 -1
  10. package/dist/cjs/mcp/tools.d.ts.map +1 -1
  11. package/dist/cjs/mcp/tools.js +122 -28
  12. package/dist/cjs/mcp/tools.js.map +1 -1
  13. package/dist/cjs/mcp/utils.d.ts.map +1 -1
  14. package/dist/cjs/mcp/utils.js +19 -6
  15. package/dist/cjs/mcp/utils.js.map +1 -1
  16. package/dist/cjs/security/SemanticScrubber.d.ts +2 -0
  17. package/dist/cjs/security/SemanticScrubber.d.ts.map +1 -1
  18. package/dist/cjs/security/SemanticScrubber.js +53 -13
  19. package/dist/cjs/security/SemanticScrubber.js.map +1 -1
  20. package/dist/cjs/utils/ContextSqueezer.d.ts.map +1 -1
  21. package/dist/cjs/utils/ContextSqueezer.js +55 -22
  22. package/dist/cjs/utils/ContextSqueezer.js.map +1 -1
  23. package/dist/cjs/utils/FileOutline.d.ts +22 -0
  24. package/dist/cjs/utils/FileOutline.d.ts.map +1 -0
  25. package/dist/cjs/utils/FileOutline.js +55 -0
  26. package/dist/cjs/utils/FileOutline.js.map +1 -0
  27. package/dist/cjs/utils/LineNumberMap.d.ts +29 -0
  28. package/dist/cjs/utils/LineNumberMap.d.ts.map +1 -0
  29. package/dist/cjs/utils/LineNumberMap.js +98 -0
  30. package/dist/cjs/utils/LineNumberMap.js.map +1 -0
  31. package/dist/cjs/utils/PatchMatcher.d.ts +2 -0
  32. package/dist/cjs/utils/PatchMatcher.d.ts.map +1 -1
  33. package/dist/cjs/utils/PatchMatcher.js +9 -1
  34. package/dist/cjs/utils/PatchMatcher.js.map +1 -1
  35. package/dist/cjs/utils/ReadWorkspaceCache.d.ts +16 -3
  36. package/dist/cjs/utils/ReadWorkspaceCache.d.ts.map +1 -1
  37. package/dist/cjs/utils/ReadWorkspaceCache.js +20 -8
  38. package/dist/cjs/utils/ReadWorkspaceCache.js.map +1 -1
  39. package/dist/esm/mcp/prompts.d.ts +10 -1
  40. package/dist/esm/mcp/prompts.d.ts.map +1 -1
  41. package/dist/esm/mcp/prompts.js +25 -73
  42. package/dist/esm/mcp/prompts.js.map +1 -1
  43. package/dist/esm/mcp/tool-profiles.d.ts +10 -1
  44. package/dist/esm/mcp/tool-profiles.d.ts.map +1 -1
  45. package/dist/esm/mcp/tool-profiles.js +12 -3
  46. package/dist/esm/mcp/tool-profiles.js.map +1 -1
  47. package/dist/esm/mcp/tools.d.ts.map +1 -1
  48. package/dist/esm/mcp/tools.js +122 -28
  49. package/dist/esm/mcp/tools.js.map +1 -1
  50. package/dist/esm/mcp/utils.d.ts.map +1 -1
  51. package/dist/esm/mcp/utils.js +19 -6
  52. package/dist/esm/mcp/utils.js.map +1 -1
  53. package/dist/esm/security/SemanticScrubber.d.ts +2 -0
  54. package/dist/esm/security/SemanticScrubber.d.ts.map +1 -1
  55. package/dist/esm/security/SemanticScrubber.js +53 -13
  56. package/dist/esm/security/SemanticScrubber.js.map +1 -1
  57. package/dist/esm/utils/ContextSqueezer.d.ts.map +1 -1
  58. package/dist/esm/utils/ContextSqueezer.js +55 -22
  59. package/dist/esm/utils/ContextSqueezer.js.map +1 -1
  60. package/dist/esm/utils/FileOutline.d.ts +22 -0
  61. package/dist/esm/utils/FileOutline.d.ts.map +1 -0
  62. package/dist/esm/utils/FileOutline.js +51 -0
  63. package/dist/esm/utils/FileOutline.js.map +1 -0
  64. package/dist/esm/utils/LineNumberMap.d.ts +29 -0
  65. package/dist/esm/utils/LineNumberMap.d.ts.map +1 -0
  66. package/dist/esm/utils/LineNumberMap.js +93 -0
  67. package/dist/esm/utils/LineNumberMap.js.map +1 -0
  68. package/dist/esm/utils/PatchMatcher.d.ts +2 -0
  69. package/dist/esm/utils/PatchMatcher.d.ts.map +1 -1
  70. package/dist/esm/utils/PatchMatcher.js +9 -1
  71. package/dist/esm/utils/PatchMatcher.js.map +1 -1
  72. package/dist/esm/utils/ReadWorkspaceCache.d.ts +16 -3
  73. package/dist/esm/utils/ReadWorkspaceCache.d.ts.map +1 -1
  74. package/dist/esm/utils/ReadWorkspaceCache.js +19 -8
  75. package/dist/esm/utils/ReadWorkspaceCache.js.map +1 -1
  76. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # 🧠 Lemma v1.8.0
1
+ # 🧠 Lemma v1.9.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)
5
5
  [![MCP Tools](https://img.shields.io/badge/MCP%20tools-95-ff69b4?style=flat-square)](https://github.com/Nxusbets/lemma)
6
6
  [![Security](https://img.shields.io/badge/privacy-firewall%20active-blueviolet?style=flat-square)](https://github.com/Nxusbets/lemma)
7
7
  [![Caching](https://img.shields.io/badge/semantic%20memory-enabled-success?style=flat-square)](https://github.com/Nxusbets/lemma)
8
- [![Tests](https://img.shields.io/badge/tests-293%20passing-00c853?style=flat-square)](https://github.com/Nxusbets/lemma)
8
+ [![Tests](https://img.shields.io/badge/tests-333%20passing-00c853?style=flat-square)](https://github.com/Nxusbets/lemma)
9
9
 
10
10
  ```text
11
11
  __
@@ -27,6 +27,57 @@ are advertised to the model each turn. The rest stay one `lemma_toolbox` call aw
27
27
 
28
28
  ## 📋 Changelog
29
29
 
30
+ ### v1.9.0 — The tools stop fighting the agent using them *(NEW)*
31
+
32
+ Lemma's savings only count if the agent actually uses the tools. Five defects were pushing it back
33
+ to its native tools instead — which means the file gets read twice, and Lemma's overhead is charged
34
+ for nothing. Each one below was found by driving the tools as a consumer, not by reading the code.
35
+
36
+ | Change | What it does | Why it matters |
37
+ | :--- | :--- | :--- |
38
+ | **Real line numbers in `read_workspace_file`** | Every line carries its true line number in the original file, mapped through compression rather than renumbered. Squeezer markers get a blank gutter instead of borrowing a neighbour's number. | A compressed read could not be cited (`file.ts:120`) or edited from, so the agent re-read the file with a native tool — paying for it twice and cancelling the squeeze. |
39
+ | **`offset` / `limit`** | Read a line range of a large file, numbered from the range start. | Whole-file reads were the only option, on files where a 30-line window was the actual need. |
40
+ | **Imports are named, not just counted** | `// [Lemma Squeezer: Squeezed 2 import/dependency lines: fs, path]` | "Squeezed 3 import lines" made *"is this module already imported?"* unanswerable without a full re-read. |
41
+ | **`run_workspace_command` timeout: 15s → 120s, configurable to 600s** | `timeoutMs` parameter. | 15s is below the runtime of a real `npm test` or `tsc --noEmit` — the exact commands the output distiller exists for. The tool always timed out, so it was never used. |
42
+ | **Timed-out commands keep their output** | Partial stdout/stderr is distilled and returned with a truncation notice. | The old path discarded everything on timeout, and the partial output is normally where the failure is. |
43
+ | **Allowlist covers real toolchains** | `python`, `pytest`, `cargo`, `go`, `make`, `rg`, `sed`, `awk`, `docker`, `kubectl`, `gh` and more. Still deny-by-default. | A blocked command is not a command prevented — it is a refused round-trip followed by the same command run through an unrestricted shell, outside Lemma's view. |
44
+ | **The read cache stops withholding unsent content** | The dedup key now includes the view (range, numbering, compact mode), not just the path. | Reading lines 1-50 then 51-100 returned `UNCHANGED` for content that had **never been sent**. This was data loss, not just friction. |
45
+ | **`UNCHANGED` carries a symbol outline** | Instead of a bare hash, the marker lists the file's symbols and their lines. | *"Reuse your existing copy"* assumes the agent still has it — but its context gets compacted as a session grows, and the server has no way to know. |
46
+ | **Free sessions stop paying for tools they can't run** | `resolveToolSurface` takes an entitlement check; Pro-gated tools are no longer advertised without a license. They stay registered and discoverable via `lemma_toolbox`. | A free session advertised the full core surface — read, search, patch, run, AST — and refused 14 of those 20 at call time, charging ~3k tokens per turn for the privilege. |
47
+ | **TURBOMODE prompt: ~1,700 → ~894 tokens** | Rule 3 no longer contradicts rule 0. Rationale written for human readers moved into source comments. | *"NEVER read files blindly, always call get_ast_hologram first"* told the model to spend a round-trip to save a read that was often cheaper than the round-trip. |
48
+
49
+ **Safety net for the new gutter:** `apply_workspace_patch` strips a line-number prefix from a search
50
+ block, but only when *every* non-empty line carries one. A lone `1| ` inside real content (a markdown
51
+ table) is left alone. Both cases are covered by tests.
52
+
53
+ Line numbers are exact rather than approximate because of what compression actually does: it only
54
+ *drops* whole lines and normalizes whitespace *within* a line — it never reorders, merges or splits
55
+ them. A line that cannot be located reports no number rather than a wrong one, and does not
56
+ desynchronise the lines after it.
57
+
58
+ **333 tests passing** (up from 309), including a guard that fails the build if a prompt trim removes
59
+ one of the correctness disclosures. It caught a real regression during this work.
60
+
61
+ ### v1.8.1 — Two correctness fixes: secret scrubbing and patch data loss
62
+
63
+ An audit of the tools with no test coverage turned up two bugs where the tool looked done but
64
+ silently produced wrong output.
65
+
66
+ - **`apply_workspace_patch` could corrupt a line.** The exact-match strategy computed
67
+ `startLine`/`endLine` from a raw substring `indexOf`, but the handler always spliced by whole
68
+ line. A search block that was a *fragment* of a line (not the entire line) collapsed
69
+ `startLine === endLine`, and the splice replaced the entire line with just the replacement —
70
+ discarding everything else on it. Exact matches now splice by character offset;
71
+ whitespace-normalized/indent-anchored/fuzzy matches (already full-line windows) are unaffected.
72
+ - **The privacy scrubber only recognized 3 generic patterns.** Default patterns covered
73
+ `API_KEY`/`EMAIL`/`Bearer ...` shapes only — vendor-specific secrets (Stripe, AWS, GitHub,
74
+ Google, Slack, JWTs, PEM private-key blocks) and custom-named secrets (e.g. a project's own
75
+ `_SALT` or `_WEBHOOK_SECRET` env var) passed through unmasked. Also, a project's custom
76
+ `lemma.config.json` patterns silently *replaced* the defaults instead of adding to them, so
77
+ defining one narrow pattern dropped coverage for everything else. Added vendor-specific
78
+ patterns plus a generic `ENV_SECRET` catch-all keyed on variable-name conventions, and custom
79
+ patterns now augment the defaults by default (`replaceDefaults: true` opts into full override).
80
+
30
81
  ### v1.8.0 — The Brain learns from project history, not just what it's told *(NEW)*
31
82
 
32
83
  Every memory in The Brain used to depend on the assistant remembering to call `store_memory`. If
@@ -411,12 +462,34 @@ chmod +x .git/hooks/post-commit
411
462
 
412
463
  ## 💎 Free vs Pro
413
464
 
414
- ### 🆓 Free (34 Tools)
465
+ Of the 95 registered tools, 46 work with no license and 49 require Pro. This split is enforced by
466
+ one allowlist in code (`FREE_TOOLS` in `src/mcp/tools.ts`), not by narrative — if a tool isn't in
467
+ that list, it's Pro, regardless of what a description elsewhere implies.
468
+
469
+ Since v1.9.0, a session without a license does not *advertise* the Pro tools either. Sending their
470
+ schemas every turn only to refuse the call charged roughly 3k tokens per turn for capabilities the
471
+ session could not use. They remain registered and discoverable through `lemma_toolbox`, which is
472
+ where you find out a capability exists and what unlocks it.
473
+
474
+ ### 🆓 Free (46 Tools)
415
475
 
416
476
  These tools work **without a Pro license**. Activate them with just `lemma init`:
417
477
 
418
478
  | Tool | What It Does |
419
479
  | :--- | :--- |
480
+ | `smarter_cache` | Semantic cache lookup before reasoning from scratch |
481
+ | `state_hash_cache` | Reasoning cache keyed to file content hashes — exact invalidation |
482
+ | `token_receipt` | Auditable per-session ledger of how each answer was produced |
483
+ | `search_memory` | Semantic search across The Brain, all projects |
484
+ | `store_memory` | Persist verified solutions/fixes/decisions into The Brain |
485
+ | `get_project_history` | Git log + checkpoints + Brain memories in one call |
486
+ | `token_budget` | Session token/cost dashboard, including Lemma's own overhead |
487
+ | `squeeze_prompt` | Compress code blocks before they enter your own context |
488
+ | `turbosqueeze` | Extreme internal-context compression (never shown to the user) |
489
+ | `read_workspace_file` | Read a file (or a line range) with auto-compression, privacy scrubbing, and real line numbers |
490
+ | `scrub_privacy` | Mask PII, API keys, and secrets from any text block |
491
+ | `summarize_long_text` | Summarize via local Ollama, falls back to truncation |
492
+ | `lemma_toolbox` | List, inspect, and call tools whose schemas were withheld |
420
493
  | `file_fingerprint` | File hash cache — avoid re-reads |
421
494
  | `git_blame_heat` | Git blame + risk scoring |
422
495
  | `type_coverage_report` | TypeScript type safety score |
@@ -426,7 +499,6 @@ These tools work **without a Pro license**. Activate them with just `lemma init`
426
499
  | `auto_context_bundle` | Full context bundle per file |
427
500
  | `repeat_guard` | Duplicate output detector |
428
501
  | `conversation_checkpoint` | Session state save/load |
429
- | `get_project_history` | Git log + checkpoints + Brain memories in one call |
430
502
  | `test_autofix_interceptor` | Test failure → Brain auto-fix |
431
503
  | `prompt_pattern_cache` | Reusable prompt templates |
432
504
  | `infra_discover` | Auto-detect Jenkins, OKD, Terraform |
@@ -452,25 +524,27 @@ These tools work **without a Pro license**. Activate them with just `lemma init`
452
524
  | `terraform_state_list` | List Terraform state resources |
453
525
  | `terraform_drift` | Detect Terraform drift |
454
526
 
455
- ### 💎 Pro (51 Tools)
527
+ ### 💎 Pro (49 Tools)
456
528
 
457
529
  All remaining tools require a Pro license. Activate with `lemma activate <key>` → [Get Pro](https://lemma.nxus.studio/upgrade)
458
530
 
459
531
  | Category | Tools |
460
532
  | :--- | :--- |
461
- | **AI Proxy** | OpenAI/Anthropic/Gemini proxy, exact-match cache, context squeezer, complexity router |
462
- | **Privacy** | Privacy firewall (semantic scrubber), PII masking |
463
- | **The Brain** | Semantic memory, telepathic hints, hybrid consensus, smarter cache, dedup guard |
464
- | **Zero-Token Static** | entropy_score, coupling_radar, pattern_fossil, git_heatmap_risk, precrime_static, dead_export_necromancer |
465
- | **Architecture** | depgraph, refactor, ast_flow_visualizer, imports_skeleton_resolver |
466
- | **Code Intelligence** | get_ast_hologram, validate_patch_sandbox, surgical_ast_insert, get_symbol_surgical_context |
467
- | **Workspace** | read/write/create files, apply patches, search, list dirs, run commands |
468
- | **Optimization** | turbosqueeze, squeeze_prompt, wormhole_squeeze, compress_context, token_budget |
469
- | **PR Review** | review_diff, review_pr, pr_status, generate_pr_workflow |
470
- | **Session** | test_oracle, schema_extract, changelog_auto, env_snapshot, migration_tracer |
471
- | **Automation** | AutoPilot, Auto-Heal, Silent Patch Watcher |
472
-
473
- > **The MCP server is Pro.** All 51 Pro tools — The Brain, PreCrime, AST Hologram, `depgraph`, `refactor`, and every optimization tool — require a Pro license. The 33 Free tools listed above (including all 22 Infrastructure tools) are accessible without activation.
533
+ | **AI Proxy** | OpenAI/Anthropic/Gemini proxy, exact-match cache, complexity router |
534
+ | **The Brain (advanced)** | `get_telepathic_hints`, `query_hybrid_consensus`, `semantic_dedup_guard`, `local_semantic_autofix` basic search/store/smarter_cache are Free |
535
+ | **Zero-Token Static** | `entropy_score`, `coupling_radar`, `pattern_fossil`, `git_heatmap_risk`, `precrime_static`, `dead_export_necromancer` |
536
+ | **Architecture** | `depgraph`, `refactor`, `ast_flow_visualizer`, `imports_skeleton_resolver`, `cognitive_map`, `file_intent_index` |
537
+ | **Code Intelligence** | `get_ast_hologram`, `validate_patch_sandbox`, `surgical_ast_insert`, `get_symbol_surgical_context`, `smart_file_slice`, `diff_only` |
538
+ | **Workspace writes** | `write_workspace_file`, `create_workspace_file`, `apply_workspace_patch`, `multi_file_patch`, `search_workspace`, `list_workspace_dir`, `run_workspace_command`, `output_region` |
539
+ | **Optimization (advanced)** | `wormhole_squeeze`, `compress_context`, `prune_conversation_history` `turbosqueeze`, `squeeze_prompt`, `token_budget` are Free |
540
+ | **PR Review** | `review_diff`, `review_pr`, `pr_status`, `generate_pr_workflow` |
541
+ | **Session & Automation** | `test_oracle`, `schema_extract`, `changelog_auto`, `env_snapshot`, `migration_tracer`, `spec_to_stub`, `batch_tool_calls`, `get_routing_advice`, `get_project_onboarding`, `auto_heal`, `semantic_grep` |
542
+ | **Automation (background)** | AutoPilot, Auto-Heal, Silent Patch Watcher |
543
+
544
+ > **The MCP server itself is Pro.** All 49 Pro tools — the advanced Brain layer, PreCrime, AST
545
+ > Hologram, `depgraph`, `refactor`, every workspace-write tool, and every PR review tool — require a
546
+ > Pro license. The 46 Free tools above (including all 22 Infrastructure tools and `read_workspace_file`
547
+ > with its automatic privacy scrubbing) are accessible without activation.
474
548
 
475
549
  ---
476
550
 
@@ -687,6 +761,8 @@ lemma start
687
761
  | `lemma apply <id>` | Apply a pending fix patch. |
688
762
  | `lemma discard <id>` | Discard a pending fix patch. |
689
763
  | `lemma activate <key>` | Activate Pro license for full MCP access. |
764
+ | `lemma-checkpoint [projectRoot]` | Standalone bin: derive a session checkpoint from repo state (branch, changed files, recent commits) without an assistant call. See [Session checkpoints](#-session-checkpoints). |
765
+ | `lemma-brain-ingest [projectRoot]` | Standalone bin: feed The Brain from git commits and `CHANGELOG.md`, incrementally. See [Feeding The Brain from project history](#-feeding-the-brain-from-project-history). |
690
766
 
691
767
  ### Customizing via `lemma.config.json`
692
768
 
@@ -726,157 +802,32 @@ Just run `lemma init`. Lemma automatically registers its MCP server in your `~/.
726
802
  }
727
803
  ```
728
804
 
729
- Once connected, your IDE gains access to **62 MCP tools** 11 free + 51 Pro. Lemma auto-injects the TurboMode system prompt on handshake.
730
-
731
- ---
732
-
733
- ## 🛠️ MCP Tools Reference (v1.1.0 — 62 Tools)
734
-
735
- ### 🆓 Free Tools (11)
736
-
737
- > These tools work without a Pro license. All are zero-dependency and run locally.
738
-
739
- | Tool | Category | Description |
740
- | :--- | :--- | :--- |
741
- | `file_fingerprint` | Smart Read | SHA256 hash cache. Returns 'unchanged' when hash matches, avoiding re-reads. |
742
- | `git_blame_heat` | Analysis | Git blame + risk scoring per line. Identifies hotspots and high-risk authors. |
743
- | `type_coverage_report` | Analysis | TypeScript type safety score via AST. Reports typed vs untyped, `any` count. |
744
- | `import_tree_context` | Architecture | Bidirectional import graph with reverse dependencies. |
745
- | `read_token_budgeted` | Smart Read | Read file with hard token limit. Returns only relevant sections. |
746
- | `bulk_file_digest` | Smart Read | Read N files in one call. Returns compressed digest. |
747
- | `auto_context_bundle` | Smart Read | One-call bundle: content + imports + types + Brain hints. |
748
- | `repeat_guard` | Optimization | Detects duplicate outputs using Jaccard similarity. |
749
- | `conversation_checkpoint` | Session | Save/load session state to prevent re-explaining context. |
750
- | `test_autofix_interceptor` | Automation | Run tests + Brain search for matching fixes. |
751
- | `prompt_pattern_cache` | Optimization | Find/store optimized prompt templates. |
752
-
753
- ### 🗂️ Workspace Tools
754
-
755
- | Tool | Description |
756
- | :--- | :--- |
757
- | `read_workspace_file` | Read a file with automatic token compression and privacy scrubbing. |
758
- | `write_workspace_file` | Write content to a file, creating parent directories as needed. |
759
- | `create_workspace_file` | Create a new file (fails if exists). Returns minimal ACK. |
760
- | `apply_workspace_patch` | Smart search-and-replace patch — safe against duplicate matches. |
761
- | `multi_file_patch` | Apply patches to multiple files in a single call. |
762
- | `list_workspace_dir` | Recursively list the project structure up to a configurable depth. |
763
- | `search_workspace` | Fast text search (grep) across all project files. |
764
- | `semantic_grep` | Natural language concept search using BM25. |
765
- | `run_workspace_command` | Execute bash commands in the workspace root. Secured by allowlist. Distills long jest/vitest/tsc/eslint output down to the failures and their locations; full output kept retrievable. |
766
- | `output_region` | Retrieve any part of a stored command output verbatim (whole thing, one failing test, or a line range). |
767
- | `file_intent_index` | Group files by domain intent (auth, routing, config). |
768
-
769
- ### 🔬 Code Intelligence Tools
770
-
771
- | Tool | Description |
772
- | :--- | :--- |
773
- | `get_ast_hologram` | Holographic AST Map of all exported symbols. 90% token savings. |
774
- | `validate_patch_sandbox` | Pre-flight validator: runs tsc + syntax check before applying. |
775
- | `diff_only` | Compact line-by-line diff between known states. Session-scoped. |
776
- | `surgical_ast_insert` | Insert code at AST anchor point. 95% output token savings. |
777
- | `get_symbol_surgical_context` | Extract symbol + dependency signatures only. 90% savings. |
778
- | `smart_file_slice` | Read only relevant lines around a query. 85% savings. |
779
- | `schema_extract` | Extract interfaces/types/schemas via AST. 80% savings. |
780
- | `spec_to_stub` | Generate mock stubs from TypeScript interfaces. |
781
- | `ast_flow_visualizer` | Mermaid flowchart from function control flow. |
782
- | `imports_skeleton_resolver` | Import signature mapper for quick reference. |
783
-
784
- ### 🧠 Brain & Memory Tools
785
-
786
- | Tool | Description |
787
- | :--- | :--- |
788
- | `search_memory` | Semantic search across The Brain from all projects globally. |
789
- | `store_memory` | Persist solutions, fixes, decisions into The Brain. |
790
- | `query_hybrid_consensus` | Hybrid cache: 80% threshold → instant answer, 0 cloud tokens. |
791
- | `get_telepathic_hints` | Proactive hints from The Brain based on active file. |
792
- | `smarter_cache` | Predictive cache at 75% threshold before any reasoning. |
793
- | `semantic_dedup_guard` | Brain dedup firewall. Rejects ≥92% similar entries. |
794
- | `local_semantic_autofix` | Offline self-healing from Brain error index. |
795
-
796
- ### ⚙️ Optimization & Privacy Tools
797
-
798
- | Tool | Description |
799
- | :--- | :--- |
800
- | `scrub_privacy` | Mask PII, API keys, secrets from any text block. |
801
- | `squeeze_prompt` | Compress code blocks. Up to 80% token reduction. |
802
- | `turbosqueeze` | Extreme compression: strips comments, imports, whitespace. |
803
- | `wormhole_squeeze` | Reversible unicode compression. 60-70% reduction. |
804
- | `compress_context` | Summarize old conversation turns. Keeps last N intact. |
805
- | `prune_conversation_history` | Intelligently decimate history preserving critical context. |
806
- | `summarize_long_text` | Summarize via Ollama. Falls back to truncation. |
807
- | `token_budget` | Dashboard: multiplier, savings, strategies, recommendations. |
808
- | `get_routing_advice` | Optimal model recommendation from Complexity Router. |
809
- | `get_project_onboarding` | One-shot architectural mental model. |
810
- | `auto_heal` | Auto-diagnose and repair crashes from live context. |
811
- | `batch_tool_calls` | Execute multiple tools in parallel via Promise.all. |
812
-
813
- ### 🔮 Zero-Token Static Intelligence Tools
814
-
815
- > All tools in this section use **zero LLM tokens**. Pure local computation.
816
-
817
- | Tool | Description |
818
- | :--- | :--- |
819
- | `entropy_score` | Mathematical chaos score (0-100) per file. |
820
- | `coupling_radar` | Dependency graph: circular imports, god modules, dead islands. |
821
- | `pattern_fossil` | Zombie code detector: var vs const, callbacks vs async/await. |
822
- | `git_heatmap_risk` | Git churn analysis + co-edit pairs. |
823
- | `precrime_static` | Composite risk predictor combining entropy + coupling + git. |
824
- | `dead_export_necromancer` | Dead code auditor: exported but never imported. |
825
- | `git_blame_heat` | Git blame + per-line risk scoring. |
826
- | `type_coverage_report` | TypeScript type safety score. |
827
- | `import_tree_context` | Bidirectional import graph. |
828
-
829
- ### 🏗️ Architecture & Refactoring Tools
830
-
831
- | Tool | Description |
832
- | :--- | :--- |
833
- | `depgraph` | Real-time dependency graph with depth, format, circular detection. |
834
- | `refactor` | Declarative codemod: rename symbols or move files. |
835
- | `cognitive_map` | Auto-updating knowledge graph of domains and patterns. |
836
-
837
- ### 🔍 PR Review Agent Tools
838
-
839
- | Tool | Description |
840
- | :--- | :--- |
841
- | `review_diff` | Analyze raw diff for bugs, security, best practices. |
842
- | `review_pr` | Full PR review against GitHub, Azure DevOps, GitLab. |
843
- | `pr_status` | Query last review status for a PR. |
844
- | `generate_pr_workflow` | Generate CI/CD workflow YAML for PR reviews. |
845
-
846
- ### 🧪 Testing & Quality Tools
847
-
848
- | Tool | Description |
849
- | :--- | :--- |
850
- | `test_oracle` | Run tests, return only failures with compressed traces. |
851
- | `test_autofix_interceptor` | Run tests + Brain search for matching fixes. |
852
- | `changelog_auto` | Conventional commit changelog from git history. |
853
- | `env_snapshot` | Node/npm versions, deps, .env keys (values hidden). |
854
- | `migration_tracer` | Prisma migration schema diff analysis. |
855
-
856
- ### 📋 Session & Automation Tools
857
-
858
- | Tool | Description |
859
- | :--- | :--- |
860
- | `conversation_checkpoint` | Save/load session state to `.lemma/session/`. |
861
- | `prompt_pattern_cache` | Find/store optimized prompt templates. |
862
- | `review_pr` | Full PR review with auto-approve option. |
805
+ Once connected, your IDE gains access to all **95 MCP tools** (46 Free + 49 Pro see
806
+ [Free vs Pro](#-free-vs-pro) for the full, current split) and Lemma auto-injects the TurboMode
807
+ system prompt on handshake. By default only the tools your project shows evidence of needing are
808
+ *advertised* each turn — see [Tool profiles](#-tool-profiles) — but every tool is registered and
809
+ reachable via `lemma_toolbox` regardless of profile.
863
810
 
864
811
  ### ⚡ TurboMode Auto-Injection
865
812
 
866
- When connected via `lemma mcp`, Lemma auto-injects 12 rules into the agent's system prompt on handshake:
867
-
868
- 1. `turbosqueeze` before writing large code blocks
869
- 2. `smarter_cache` before any reasoning
870
- 3. `store_memory` after every resolved solution
871
- 4. `get_ast_hologram` before reading files
872
- 5. `batch_tool_calls` for parallel operations
873
- 6. `semantic_dedup_guard` before every `store_memory`
874
- 7. No fluff, no chit-chat maximum density
875
- 8. `auto_context_bundle` or `bulk_file_digest` for multi-file ops
876
- 9. `repeat_guard` before long outputs
877
- 10. `conversation_checkpoint` to restore session context
878
- 11. `test_autofix_interceptor` when tests fail
879
- 12. `prompt_pattern_cache` for repetitive prompts
813
+ When connected via `lemma mcp`, Lemma auto-injects its system prompt on handshake. The real,
814
+ current prompt (`LEMMA_TURBOMODE_PROMPT` in `src/mcp/prompts.ts`) states the goal — reduce what
815
+ enters context without ever costing a correct answer — and enforces it with rules including:
816
+
817
+ - A tool call costs tokens too: expect a call to save more than its own round-trip, or skip it.
818
+ - `lemma_toolbox` reaches every tool whose schema was withheld from this session — check it
819
+ before saying a capability is missing.
820
+ - Compression (`turbosqueeze`, `wormhole_squeeze`, `squeeze_prompt`) is for the model's own
821
+ context only; the user always gets the real, uncompressed file.
822
+ - `smarter_cache` hits must be disclosed as cached, never presented as freshly reasoned, and
823
+ re-verified before acting on them.
824
+ - `state_hash_cache` (exact file-hash invalidation) is preferred over `smarter_cache` (semantic
825
+ similarity) whenever the answer depends on specific files.
826
+ - `store_memory` only after a solution is actually verified — an unverified fix stored here
827
+ becomes a false cache hit later.
828
+ - `get_routing_advice` before assuming a mechanical task needs the biggest available model.
829
+ - `surgical_ast_insert` by default for adding to an existing file, instead of rewriting it whole.
830
+ - `token_receipt` for "how much did we save," never an invented estimate.
880
831
 
881
832
  ---
882
833
 
@@ -904,7 +855,15 @@ AUTH_ALLOWED_ORIGINS=https://yourdomain.com
904
855
  ```
905
856
 
906
857
  ### MCP Command Allowlist
907
- `run_workspace_command` only executes commands from an allowlist. Default safe prefixes: `npm`, `npx`, `git`, `tsc`, `node`, `jest`, `eslint`, `ls`, `grep`, and more.
858
+ `run_workspace_command` only executes commands from an allowlist. It is deny-by-default, but the
859
+ defaults cover the toolchains a normal repo builds and tests with — JS/TS (`npm`, `npx`, `pnpm`,
860
+ `tsc`, `jest`, `vitest`, `eslint`), Python (`python`, `pytest`, `ruff`), Go, Rust, Ruby, JVM,
861
+ `make`, version control (`git`, `gh`), read-only shell utilities (`ls`, `grep`, `rg`, `sed`, `awk`,
862
+ `find`), and container/infra CLIs (`docker`, `kubectl`, `terraform`).
863
+
864
+ A command missing from this list is not a command prevented: the agent gets a refusal, then runs the
865
+ same thing through an unrestricted shell where Lemma can neither distil the output nor account for
866
+ it. The list is scoped to keep that from happening for ordinary development work.
908
867
 
909
868
  Extend for your project in `lemma.config.json`:
910
869
  ```json
@@ -921,15 +880,6 @@ See [`.env.security.example`](.env.security.example) for all security-related en
921
880
 
922
881
  ## 🦜 SDK Integrations
923
882
 
924
- ### LangChain
925
- ```typescript
926
- import { LemmaLangChainProvider } from '@nxuss/lemma/langchain';
927
-
928
- const model = new LemmaLangChainProvider({
929
- apiKey: process.env.OPENAI_API_KEY,
930
- });
931
- ```
932
-
933
883
  ### CrewAI
934
884
  ```typescript
935
885
  import { LemmaCrewAIProvider } from '@nxuss/lemma/crewai';
@@ -1,4 +1,13 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- export declare const LEMMA_TURBOMODE_PROMPT = "You are operating in LEMMA TURBOMODE. Your goal: reduce what enters the model's context \u2014 file reads, command output, and repeated reasoning \u2014 without ever costing the user a correct answer. Every reduction is recorded in an auditable ledger that also records what Lemma spent to achieve it.\n\nThere is no fixed multiplier to hit. Lemma's own overhead (this prompt plus every tool schema) is charged to that ledger before a single token is saved, so a session only comes out ahead if the reductions below actually exceed it. Optimize for real net savings, not for a number.\n\n## MANDATORY TURBOMODE RULES \u2014 VIOLATE THESE AND YOU WASTE THE USER'S MONEY\n\n### 0. Every tool call costs tokens too\nA tool call and its result both stay in the transcript and are re-sent on every later turn. Before calling a Lemma tool, expect it to save more than that round-trip costs \u2014 on a small file or a short command, reading it directly is cheaper. Never call a reporting tool on a schedule: a report is not work. Call one only when the user asks how the session is going.\n\n### 0b. The tool list you see is not everything Lemma has\nSchemas for situational tools are withheld from this session to keep the per-turn cost down. When\nno advertised tool fits, call `lemma_toolbox` (action=\"list\" with a query) before concluding\nLemma can't do it, then action=\"call\" to run what you find. Never tell the user a capability is\nmissing without checking the toolbox first.\n\n### 1. Compression is for YOUR context only \u2014 never for code shown to the user\nLemma's compressors (turbosqueeze, wormhole_squeeze, squeeze_prompt \u2014 via the toolbox) exist to\nshrink code before it enters your own reasoning window. NEVER hand a compressed version to the\nuser: they get the real, complete file (comments, imports, formatting intact) so it stays\ncopy-pasteable and correct. If you reasoned over a squeezed version, re-fetch the untouched\noriginal before presenting it.\n\n### 2. smarter_cache (threshold 0.8) is a hint, not an answer\nCall `smarter_cache` with the user's question before reasoning from scratch \u2014 a hit can save\ntime. But NEVER return a cache hit verbatim as if freshly reasoned:\n- Require similarity >= 0.8 (raised from 0.75 \u2014 0.75 was matching questions that weren't\n actually the same question).\n- Always tell the user the answer came from cache (e.g. \"from a cached earlier answer:\").\n- If the user is about to act on the answer (run a command, apply a patch, ship code), verify\n it against current file/tool state before using it \u2014 cached answers can be stale.\n- On a MISS, or on any doubt, reason normally.\n\n### 3. Before reading files \u2192 call get_ast_hologram\nNEVER read files blindly. Always call `get_ast_hologram` first to locate the exact symbols you need. Then read only those specific files. Each unnecessary file read wastes 1000+ tokens.\n\n### 4. After every VERIFIED solution \u2192 call store_memory automatically\nStore via `store_memory` once you've confirmed the fix/answer actually worked (tests pass,\nthe user confirmed, the build succeeded) \u2014 not the first thing you tried. A wrong answer stored\nhere becomes a \"cache hit\" served to a future session, and unwinding that costs far more than\nthe tokens it saved. Verified answers are still free to cache aggressively.\n\n### 5. Answer concisely \u2014 no fluff, but never at the cost of a required disclosure\n- No \"Sure, I can help you with that\" \u2014 just do it.\n- No unnecessary explanation of what you did \u2014 unless asked.\n- No repeating the user's question back to them.\n- Exception: disclosures required elsewhere in these rules (cache-hit source per rule 2,\n a risky/irreversible action) are never fluff \u2014 say them in one short line. Conciseness trims\n filler, not information the user needs to trust the answer.\n\n### 6. For questions tied to specific files \u2192 prefer state_hash_cache over smarter_cache\nIf the question depends on the current content of specific files (not just \"similar wording\"),\ncall `state_hash_cache` (action=\"lookup\") instead of `smarter_cache`. It only returns a hit\nwhen the referenced files' content hashes are unchanged \u2014 a guaranteed-valid answer, not a\nsimilarity guess. After answering, call it again with action=\"store\" to cache it. Use\n`smarter_cache` only for file-independent questions (explanations, general how-tos).\n\n### 7. Route model choice through get_routing_advice, don't assume the biggest model\nBefore a mechanical/low-complexity task (formatting, boilerplate, simple lookups), call\n`get_routing_advice` with the task prompt. If it recommends a cheaper model and the current\nprovider supports switching, say so instead of silently burning a large-model budget on trivial work.\n\n### 8. Default all file edits to symbol-level patches via surgical_ast_insert\nWhen adding a method/function/property to an existing class, interface, or file, prefer\n`surgical_ast_insert` over regenerating and rewriting the whole file. Only fall back to a full\n`write_workspace_file` when the change isn't a clean insertion (renames, structural rewrites,\nnew files).\n\n### 9. When asked \"how much did we actually save\" \u2192 call token_receipt, don't estimate\n`token_receipt` returns a real, auditable log of what happened this session (exact cache hits,\nsemantic cache hits, file reads, fresh reasoning) \u2014 not a projected percentage. Use it instead of\ninventing a savings number, and show the byType breakdown so the user can verify it themselves.\n\n### 10. Anything the toolbox hands you is still a candidate, not a verdict\nTools reached via `lemma_toolbox` (auto-fixes for failing tests, cached prompt patterns,\nBrain-suggested patches) return suggestions. Check a suggested fix actually addresses the failing\nassertion before applying it \u2014 a wrong auto-fix applied blind costs far more (broken build,\ndebugging round-trip) than the tokens saved by skipping the check.\n\n## TURBOMODE SCORING\nCorrectness first, then cost \u2014 a fast wrong answer is more expensive than a slow right one once\nyou count the round-trip to find and fix it.\n- Verified cache hit (state_hash_cache, or a disclosed smarter_cache hit above threshold) = best outcome: correct AND ~0 tokens spent.\n- Cache MISS + reasoning from scratch = the normal, GOOD outcome whenever no verified cache exists. Reasoning is not a failure mode \u2014 it's what you do when you don't already have a trustworthy answer.\n- Reading full files without checking get_ast_hologram first = wasteful, avoid it when a cheaper lookup would've told you what you needed.\n- Any answer delivered without required disclosure (rule 6's exception), or a cached/auto-fixed result used without verification = FAIL, regardless of tokens saved \u2014 it can cost the user far more than tokens once it's wrong.\n\nRemember: the goal is spending fewer tokens on the SAME quality of answer, not a lower-quality answer for fewer tokens.";
2
+ /**
3
+ * This text is injected into the system prompt and re-sent on every turn of the session, so
4
+ * its length is a recurring charge against the very savings it asks for. It is kept to the
5
+ * rules that change behaviour or protect correctness; anything that only restates good default
6
+ * behaviour (be concise, don't pad) was removed rather than paid for on every request.
7
+ *
8
+ * The full rationale and scoring model live in the `lemma-turbomode` prompt resource, which
9
+ * the client can fetch on demand instead of carrying permanently.
10
+ */
11
+ export declare const LEMMA_TURBOMODE_PROMPT = "You are operating in LEMMA TURBOMODE. Reduce what enters the model's context \u2014 file reads, command output, repeated reasoning \u2014 without ever costing the user a correct answer. Lemma's own overhead (this prompt + every tool schema) is charged to the ledger before a single token is saved, so optimize for real net savings, not for a multiplier.\n\n## RULES\n\n**0. Tool calls cost tokens too.** A call and its result stay in the transcript and are re-sent every later turn. Expect a Lemma tool to save more than that round-trip costs \u2014 on a small file or short command, reading it directly is cheaper. Never call a reporting tool on a schedule.\n\n**0b. The advertised list is not everything Lemma has.** Situational schemas are withheld to keep per-turn cost down. Before concluding Lemma can't do something, call `lemma_toolbox` (action=\"list\" with a query), then action=\"call\".\n\n**1. Compression is for YOUR context only.** NEVER hand a compressed version to the user \u2014 they get the real, complete file, comments and imports intact. If you reasoned over a squeezed version, re-fetch the original before presenting it.\n\n**2. A cache hit is a hint, not an answer.** `smarter_cache` requires similarity >= 0.8. Always tell the user the answer came from cache. If they're about to act on it (run a command, apply a patch, ship code), verify against current state first \u2014 cached answers go stale. On a MISS or any doubt, reason normally.\n\n**3. Locate before reading only when locating is cheaper.** Don't know which file? `get_ast_hologram` / `search_workspace` beats reading candidates one by one. Already know the file? Read it \u2014 a lookup round-trip on a small file costs more than the file. `read_workspace_file` carries real line numbers and takes offset/limit, so prefer a targeted range on large files.\n\n**4. store_memory only after verification.** Store once the fix actually worked (tests pass, build succeeded, user confirmed) \u2014 not your first attempt. A wrong answer stored here becomes a false cache hit for a future session, and unwinding that costs far more than it saved.\n\n**5. Never trade a required disclosure for brevity.** A cache-hit source or a risky/irreversible action is not filler. One short line.\n\n**6. File-dependent questions \u2192 state_hash_cache, not smarter_cache.** It only hits when the referenced files' hashes are unchanged: a guaranteed-valid answer instead of a similarity guess. Look up before, store after. Use `smarter_cache` only for file-independent questions.\n\n**7. Edit in place.** `apply_workspace_patch` or `surgical_ast_insert` over rewriting a file with `write_workspace_file`; reserve the full write for renames, structural rewrites and new files. For mechanical work, `get_routing_advice` says whether a cheaper model suffices.\n\n**8. \"How much did we save\" \u2192 token_receipt, don't estimate.** It returns a real auditable log. Show the byType breakdown so the user can verify it.\n\n**9. What the toolbox hands you is a candidate, not a verdict.** Auto-fixes, cached patterns and Brain-suggested patches are suggestions. Check a fix addresses the actual failing assertion before applying it.\n\n## SCORING\nCorrectness first, then cost \u2014 a fast wrong answer costs more than a slow right one once you count the round-trip to fix it. A verified cache hit is best; a MISS followed by reasoning from scratch is the normal GOOD outcome, not a failure. A cached or auto-fixed result delivered without disclosure or verification is a FAIL regardless of tokens saved.\n\nFewer tokens for the SAME quality of answer \u2014 never a worse answer for fewer tokens.";
3
12
  export declare function setupPromptsHandlers(server: Server): void;
4
13
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/mcp/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,eAAO,MAAM,sBAAsB,23NAsFqF,CAAC;AAEzH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA8BzD"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/mcp/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,slHA6BkD,CAAC;AAEtF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA8BzD"}
@@ -3,93 +3,45 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LEMMA_TURBOMODE_PROMPT = void 0;
4
4
  exports.setupPromptsHandlers = setupPromptsHandlers;
5
5
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
6
- exports.LEMMA_TURBOMODE_PROMPT = `You are operating in LEMMA TURBOMODE. Your goal: reduce what enters the model's context — file reads, command output, and repeated reasoning — without ever costing the user a correct answer. Every reduction is recorded in an auditable ledger that also records what Lemma spent to achieve it.
6
+ /**
7
+ * This text is injected into the system prompt and re-sent on every turn of the session, so
8
+ * its length is a recurring charge against the very savings it asks for. It is kept to the
9
+ * rules that change behaviour or protect correctness; anything that only restates good default
10
+ * behaviour (be concise, don't pad) was removed rather than paid for on every request.
11
+ *
12
+ * The full rationale and scoring model live in the `lemma-turbomode` prompt resource, which
13
+ * the client can fetch on demand instead of carrying permanently.
14
+ */
15
+ exports.LEMMA_TURBOMODE_PROMPT = `You are operating in LEMMA TURBOMODE. Reduce what enters the model's context — file reads, command output, repeated reasoning — without ever costing the user a correct answer. Lemma's own overhead (this prompt + every tool schema) is charged to the ledger before a single token is saved, so optimize for real net savings, not for a multiplier.
7
16
 
8
- There is no fixed multiplier to hit. Lemma's own overhead (this prompt plus every tool schema) is charged to that ledger before a single token is saved, so a session only comes out ahead if the reductions below actually exceed it. Optimize for real net savings, not for a number.
17
+ ## RULES
9
18
 
10
- ## MANDATORY TURBOMODE RULESVIOLATE THESE AND YOU WASTE THE USER'S MONEY
19
+ **0. Tool calls cost tokens too.** A call and its result stay in the transcript and are re-sent every later turn. Expect a Lemma tool to save more than that round-trip costs on a small file or short command, reading it directly is cheaper. Never call a reporting tool on a schedule.
11
20
 
12
- ### 0. Every tool call costs tokens too
13
- A tool call and its result both stay in the transcript and are re-sent on every later turn. Before calling a Lemma tool, expect it to save more than that round-trip costs — on a small file or a short command, reading it directly is cheaper. Never call a reporting tool on a schedule: a report is not work. Call one only when the user asks how the session is going.
21
+ **0b. The advertised list is not everything Lemma has.** Situational schemas are withheld to keep per-turn cost down. Before concluding Lemma can't do something, call \`lemma_toolbox\` (action="list" with a query), then action="call".
14
22
 
15
- ### 0b. The tool list you see is not everything Lemma has
16
- Schemas for situational tools are withheld from this session to keep the per-turn cost down. When
17
- no advertised tool fits, call \`lemma_toolbox\` (action="list" with a query) before concluding
18
- Lemma can't do it, then action="call" to run what you find. Never tell the user a capability is
19
- missing without checking the toolbox first.
23
+ **1. Compression is for YOUR context only.** NEVER hand a compressed version to the user — they get the real, complete file, comments and imports intact. If you reasoned over a squeezed version, re-fetch the original before presenting it.
20
24
 
21
- ### 1. Compression is for YOUR context only never for code shown to the user
22
- Lemma's compressors (turbosqueeze, wormhole_squeeze, squeeze_prompt — via the toolbox) exist to
23
- shrink code before it enters your own reasoning window. NEVER hand a compressed version to the
24
- user: they get the real, complete file (comments, imports, formatting intact) so it stays
25
- copy-pasteable and correct. If you reasoned over a squeezed version, re-fetch the untouched
26
- original before presenting it.
25
+ **2. A cache hit is a hint, not an answer.** \`smarter_cache\` requires similarity >= 0.8. Always tell the user the answer came from cache. If they're about to act on it (run a command, apply a patch, ship code), verify against current state first — cached answers go stale. On a MISS or any doubt, reason normally.
27
26
 
28
- ### 2. smarter_cache (threshold 0.8) is a hint, not an answer
29
- Call \`smarter_cache\` with the user's question before reasoning from scratch — a hit can save
30
- time. But NEVER return a cache hit verbatim as if freshly reasoned:
31
- - Require similarity >= 0.8 (raised from 0.75 — 0.75 was matching questions that weren't
32
- actually the same question).
33
- - Always tell the user the answer came from cache (e.g. "from a cached earlier answer:").
34
- - If the user is about to act on the answer (run a command, apply a patch, ship code), verify
35
- it against current file/tool state before using it — cached answers can be stale.
36
- - On a MISS, or on any doubt, reason normally.
27
+ **3. Locate before reading only when locating is cheaper.** Don't know which file? \`get_ast_hologram\` / \`search_workspace\` beats reading candidates one by one. Already know the file? Read it — a lookup round-trip on a small file costs more than the file. \`read_workspace_file\` carries real line numbers and takes offset/limit, so prefer a targeted range on large files.
37
28
 
38
- ### 3. Before reading files call get_ast_hologram
39
- NEVER read files blindly. Always call \`get_ast_hologram\` first to locate the exact symbols you need. Then read only those specific files. Each unnecessary file read wastes 1000+ tokens.
29
+ **4. store_memory only after verification.** Store once the fix actually worked (tests pass, build succeeded, user confirmed) — not your first attempt. A wrong answer stored here becomes a false cache hit for a future session, and unwinding that costs far more than it saved.
40
30
 
41
- ### 4. After every VERIFIED solution call store_memory automatically
42
- Store via \`store_memory\` once you've confirmed the fix/answer actually worked (tests pass,
43
- the user confirmed, the build succeeded) — not the first thing you tried. A wrong answer stored
44
- here becomes a "cache hit" served to a future session, and unwinding that costs far more than
45
- the tokens it saved. Verified answers are still free to cache aggressively.
31
+ **5. Never trade a required disclosure for brevity.** A cache-hit source or a risky/irreversible action is not filler. One short line.
46
32
 
47
- ### 5. Answer concisely no fluff, but never at the cost of a required disclosure
48
- - No "Sure, I can help you with that" — just do it.
49
- - No unnecessary explanation of what you did — unless asked.
50
- - No repeating the user's question back to them.
51
- - Exception: disclosures required elsewhere in these rules (cache-hit source per rule 2,
52
- a risky/irreversible action) are never fluff — say them in one short line. Conciseness trims
53
- filler, not information the user needs to trust the answer.
33
+ **6. File-dependent questions state_hash_cache, not smarter_cache.** It only hits when the referenced files' hashes are unchanged: a guaranteed-valid answer instead of a similarity guess. Look up before, store after. Use \`smarter_cache\` only for file-independent questions.
54
34
 
55
- ### 6. For questions tied to specific files prefer state_hash_cache over smarter_cache
56
- If the question depends on the current content of specific files (not just "similar wording"),
57
- call \`state_hash_cache\` (action="lookup") instead of \`smarter_cache\`. It only returns a hit
58
- when the referenced files' content hashes are unchanged — a guaranteed-valid answer, not a
59
- similarity guess. After answering, call it again with action="store" to cache it. Use
60
- \`smarter_cache\` only for file-independent questions (explanations, general how-tos).
35
+ **7. Edit in place.** \`apply_workspace_patch\` or \`surgical_ast_insert\` over rewriting a file with \`write_workspace_file\`; reserve the full write for renames, structural rewrites and new files. For mechanical work, \`get_routing_advice\` says whether a cheaper model suffices.
61
36
 
62
- ### 7. Route model choice through get_routing_advice, don't assume the biggest model
63
- Before a mechanical/low-complexity task (formatting, boilerplate, simple lookups), call
64
- \`get_routing_advice\` with the task prompt. If it recommends a cheaper model and the current
65
- provider supports switching, say so instead of silently burning a large-model budget on trivial work.
37
+ **8. "How much did we save" → token_receipt, don't estimate.** It returns a real auditable log. Show the byType breakdown so the user can verify it.
66
38
 
67
- ### 8. Default all file edits to symbol-level patches via surgical_ast_insert
68
- When adding a method/function/property to an existing class, interface, or file, prefer
69
- \`surgical_ast_insert\` over regenerating and rewriting the whole file. Only fall back to a full
70
- \`write_workspace_file\` when the change isn't a clean insertion (renames, structural rewrites,
71
- new files).
39
+ **9. What the toolbox hands you is a candidate, not a verdict.** Auto-fixes, cached patterns and Brain-suggested patches are suggestions. Check a fix addresses the actual failing assertion before applying it.
72
40
 
73
- ### 9. When asked "how much did we actually save" → call token_receipt, don't estimate
74
- \`token_receipt\` returns a real, auditable log of what happened this session (exact cache hits,
75
- semantic cache hits, file reads, fresh reasoning) — not a projected percentage. Use it instead of
76
- inventing a savings number, and show the byType breakdown so the user can verify it themselves.
41
+ ## SCORING
42
+ Correctness first, then cost — a fast wrong answer costs more than a slow right one once you count the round-trip to fix it. A verified cache hit is best; a MISS followed by reasoning from scratch is the normal GOOD outcome, not a failure. A cached or auto-fixed result delivered without disclosure or verification is a FAIL regardless of tokens saved.
77
43
 
78
- ### 10. Anything the toolbox hands you is still a candidate, not a verdict
79
- Tools reached via \`lemma_toolbox\` (auto-fixes for failing tests, cached prompt patterns,
80
- Brain-suggested patches) return suggestions. Check a suggested fix actually addresses the failing
81
- assertion before applying it — a wrong auto-fix applied blind costs far more (broken build,
82
- debugging round-trip) than the tokens saved by skipping the check.
83
-
84
- ## TURBOMODE SCORING
85
- Correctness first, then cost — a fast wrong answer is more expensive than a slow right one once
86
- you count the round-trip to find and fix it.
87
- - Verified cache hit (state_hash_cache, or a disclosed smarter_cache hit above threshold) = best outcome: correct AND ~0 tokens spent.
88
- - Cache MISS + reasoning from scratch = the normal, GOOD outcome whenever no verified cache exists. Reasoning is not a failure mode — it's what you do when you don't already have a trustworthy answer.
89
- - Reading full files without checking get_ast_hologram first = wasteful, avoid it when a cheaper lookup would've told you what you needed.
90
- - Any answer delivered without required disclosure (rule 6's exception), or a cached/auto-fixed result used without verification = FAIL, regardless of tokens saved — it can cost the user far more than tokens once it's wrong.
91
-
92
- Remember: the goal is spending fewer tokens on the SAME quality of answer, not a lower-quality answer for fewer tokens.`;
44
+ Fewer tokens for the SAME quality of answer never a worse answer for fewer tokens.`;
93
45
  function setupPromptsHandlers(server) {
94
46
  server.setRequestHandler(types_js_1.ListPromptsRequestSchema, async () => {
95
47
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/mcp/prompts.ts"],"names":[],"mappings":";;;AA2FA,oDA8BC;AAxHD,iEAAsG;AAEzF,QAAA,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wHAsFkF,CAAC;AAEzH,SAAgB,oBAAoB,CAAC,MAAc;IACjD,MAAM,CAAC,iBAAiB,CAAC,mCAAwB,EAAE,KAAK,IAAI,EAAE;QAC5D,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,iBAAiB;oBACvB,WAAW,EAAE,+MAA+M;oBAC5N,SAAS,EAAE,EAAE;iBACd;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,iCAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACjE,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAC9C,OAAO;gBACL,WAAW,EAAE,8CAA8C;gBAC3D,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE;4BACP,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,8BAAsB;yBAC7B;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/mcp/prompts.ts"],"names":[],"mappings":";;;AA2CA,oDA8BC;AAxED,iEAAsG;AAEtG;;;;;;;;GAQG;AACU,QAAA,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qFA6B+C,CAAC;AAEtF,SAAgB,oBAAoB,CAAC,MAAc;IACjD,MAAM,CAAC,iBAAiB,CAAC,mCAAwB,EAAE,KAAK,IAAI,EAAE;QAC5D,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,iBAAiB;oBACvB,WAAW,EAAE,+MAA+M;oBAC5N,SAAS,EAAE,EAAE;iBACd;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,iCAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACjE,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YAC9C,OAAO;gBACL,WAAW,EAAE,8CAA8C;gBAC3D,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE;4BACP,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,8BAAsB;yBAC7B;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -40,10 +40,19 @@ export interface ResolvedToolSurface<T extends {
40
40
  /** Situational groups that matched this project. */
41
41
  activeGroups: string[];
42
42
  }
43
+ export interface ResolveOptions {
44
+ /**
45
+ * Returns false for a tool this session is not licensed to run. Such a tool must not be
46
+ * advertised: its schema would be re-sent every turn purely to be refused at call time.
47
+ * It stays registered and discoverable through `lemma_toolbox`, which is where a user
48
+ * finds out the capability exists and what it takes to unlock it.
49
+ */
50
+ isEntitled?: (name: string) => boolean;
51
+ }
43
52
  export declare function resolveToolSurface<T extends {
44
53
  name: string;
45
54
  description?: string;
46
- }>(allDefinitions: T[], cwd?: string): ResolvedToolSurface<T>;
55
+ }>(allDefinitions: T[], cwd?: string, options?: ResolveOptions): ResolvedToolSurface<T>;
47
56
  /**
48
57
  * One-line-per-tool catalog of everything not advertised, so the model can find and
49
58
  * invoke a hidden tool without its schema having been resident all session.
@@ -1 +1 @@
1
- {"version":3,"file":"tool-profiles.d.ts","sourceRoot":"","sources":["../../../src/mcp/tool-profiles.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,EA0BnC,CAAC;AA4DF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,UAAoE,CAAC;AAkBnG,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;IAC7D,OAAO,EAAE,WAAW,CAAC;IACrB,wCAAwC;IACxC,UAAU,EAAE,CAAC,EAAE,CAAC;IAChB,uFAAuF;IACvF,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,oDAAoD;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,cAAc,EAAE,CAAC,EAAE,EACnB,GAAG,GAAE,MAAsB,GAC1B,mBAAmB,CAAC,CAAC,CAAC,CAmCxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACrD,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAuDR"}
1
+ {"version":3,"file":"tool-profiles.d.ts","sourceRoot":"","sources":["../../../src/mcp/tool-profiles.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,EA0BnC,CAAC;AA4DF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,UAAoE,CAAC;AAkBnG,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;IAC7D,OAAO,EAAE,WAAW,CAAC;IACrB,wCAAwC;IACxC,UAAU,EAAE,CAAC,EAAE,CAAC;IAChB,uFAAuF;IACvF,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,oDAAoD;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACjF,cAAc,EAAE,CAAC,EAAE,EACnB,GAAG,GAAE,MAAsB,EAC3B,OAAO,GAAE,cAAmB,GAC3B,mBAAmB,CAAC,CAAC,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACrD,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAuDR"}
@@ -113,10 +113,19 @@ function readConfiguredProfile(cwd) {
113
113
  return env;
114
114
  return "auto";
115
115
  }
116
- function resolveToolSurface(allDefinitions, cwd = process.cwd()) {
116
+ function resolveToolSurface(allDefinitions, cwd = process.cwd(), options = {}) {
117
117
  const profile = readConfiguredProfile(cwd);
118
+ // `lemma_toolbox` is the only route back to a withheld schema, so no entitlement check may
119
+ // ever remove it — doing so would turn every deferred tool into an unreachable one.
120
+ const entitlementCheck = options.isEntitled ?? (() => true);
121
+ const isEntitled = (name) => name === "lemma_toolbox" || entitlementCheck(name);
118
122
  if (profile === "full") {
119
- return { profile, advertised: allDefinitions, hidden: [], activeGroups: ["*"] };
123
+ const advertised = [];
124
+ const hidden = [];
125
+ for (const def of allDefinitions) {
126
+ (isEntitled(def.name) ? advertised : hidden).push(def);
127
+ }
128
+ return { profile, advertised, hidden, activeGroups: ["*"] };
120
129
  }
121
130
  // Always advertised: it is the only route back to a withheld schema, so hiding it
122
131
  // would turn a deferred tool into a lost one.
@@ -141,7 +150,7 @@ function resolveToolSurface(allDefinitions, cwd = process.cwd()) {
141
150
  const advertised = [];
142
151
  const hidden = [];
143
152
  for (const def of allDefinitions) {
144
- (allowed.has(def.name) ? advertised : hidden).push(def);
153
+ (allowed.has(def.name) && isEntitled(def.name) ? advertised : hidden).push(def);
145
154
  }
146
155
  return { profile, advertised, hidden, activeGroups };
147
156
  }