pmb-ai 0.1.0__tar.gz

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 (151) hide show
  1. pmb_ai-0.1.0/CHANGELOG.md +71 -0
  2. pmb_ai-0.1.0/CITATION.cff +23 -0
  3. pmb_ai-0.1.0/CODE_OF_CONDUCT.md +24 -0
  4. pmb_ai-0.1.0/CONTRIBUTING.md +110 -0
  5. pmb_ai-0.1.0/LICENSE +201 -0
  6. pmb_ai-0.1.0/MANIFEST.in +44 -0
  7. pmb_ai-0.1.0/Makefile +76 -0
  8. pmb_ai-0.1.0/NOTICE +31 -0
  9. pmb_ai-0.1.0/PKG-INFO +837 -0
  10. pmb_ai-0.1.0/README.md +785 -0
  11. pmb_ai-0.1.0/SECURITY.md +35 -0
  12. pmb_ai-0.1.0/docs/HARDENING_NOTES.md +233 -0
  13. pmb_ai-0.1.0/docs/SETUP_OLLAMA.md +170 -0
  14. pmb_ai-0.1.0/docs/assets/01_connect.png +0 -0
  15. pmb_ai-0.1.0/docs/assets/02_stats.png +0 -0
  16. pmb_ai-0.1.0/docs/assets/03_recall.png +0 -0
  17. pmb_ai-0.1.0/docs/assets/04_doctor.png +0 -0
  18. pmb_ai-0.1.0/docs/assets/05_locomo.png +0 -0
  19. pmb_ai-0.1.0/docs/assets/06_multilingual.png +0 -0
  20. pmb_ai-0.1.0/docs/assets/07_mega.png +0 -0
  21. pmb_ai-0.1.0/docs/assets/08_dashboard.png +0 -0
  22. pmb_ai-0.1.0/docs/assets/09_dashboard_events.png +0 -0
  23. pmb_ai-0.1.0/docs/assets/10_dashboard_recall.png +0 -0
  24. pmb_ai-0.1.0/docs/assets/_template.css +35 -0
  25. pmb_ai-0.1.0/pyproject.toml +103 -0
  26. pmb_ai-0.1.0/setup.cfg +4 -0
  27. pmb_ai-0.1.0/src/pmb/__init__.py +82 -0
  28. pmb_ai-0.1.0/src/pmb/agent_wrapper/__init__.py +34 -0
  29. pmb_ai-0.1.0/src/pmb/agent_wrapper/__main__.py +44 -0
  30. pmb_ai-0.1.0/src/pmb/agent_wrapper/budget.py +62 -0
  31. pmb_ai-0.1.0/src/pmb/agent_wrapper/loop.py +304 -0
  32. pmb_ai-0.1.0/src/pmb/agent_wrapper/policy.py +304 -0
  33. pmb_ai-0.1.0/src/pmb/cli/__init__.py +3 -0
  34. pmb_ai-0.1.0/src/pmb/cli/__main__.py +5 -0
  35. pmb_ai-0.1.0/src/pmb/cli/connect.py +473 -0
  36. pmb_ai-0.1.0/src/pmb/cli/doctor.py +308 -0
  37. pmb_ai-0.1.0/src/pmb/cli/main.py +1385 -0
  38. pmb_ai-0.1.0/src/pmb/cli/ollama_cmd.py +221 -0
  39. pmb_ai-0.1.0/src/pmb/cli/tui_config.py +280 -0
  40. pmb_ai-0.1.0/src/pmb/cli/tui_workspace.py +523 -0
  41. pmb_ai-0.1.0/src/pmb/config.py +712 -0
  42. pmb_ai-0.1.0/src/pmb/core/__init__.py +45 -0
  43. pmb_ai-0.1.0/src/pmb/core/embed_queue.py +232 -0
  44. pmb_ai-0.1.0/src/pmb/core/engine.py +4819 -0
  45. pmb_ai-0.1.0/src/pmb/core/events.py +559 -0
  46. pmb_ai-0.1.0/src/pmb/core/recall_cache.py +107 -0
  47. pmb_ai-0.1.0/src/pmb/core/search.py +714 -0
  48. pmb_ai-0.1.0/src/pmb/core/workspace.py +208 -0
  49. pmb_ai-0.1.0/src/pmb/dashboard/__init__.py +14 -0
  50. pmb_ai-0.1.0/src/pmb/dashboard/server.py +431 -0
  51. pmb_ai-0.1.0/src/pmb/dashboard/static/index.html +920 -0
  52. pmb_ai-0.1.0/src/pmb/eval/__init__.py +5 -0
  53. pmb_ai-0.1.0/src/pmb/eval/locomo_judge.py +283 -0
  54. pmb_ai-0.1.0/src/pmb/graph/__init__.py +33 -0
  55. pmb_ai-0.1.0/src/pmb/graph/entities.py +296 -0
  56. pmb_ai-0.1.0/src/pmb/graph/expansion.py +155 -0
  57. pmb_ai-0.1.0/src/pmb/graph/persons.py +422 -0
  58. pmb_ai-0.1.0/src/pmb/graph/ppr.py +213 -0
  59. pmb_ai-0.1.0/src/pmb/graph/spreading.py +130 -0
  60. pmb_ai-0.1.0/src/pmb/graph/store.py +324 -0
  61. pmb_ai-0.1.0/src/pmb/health/__init__.py +14 -0
  62. pmb_ai-0.1.0/src/pmb/health/adaptive.py +219 -0
  63. pmb_ai-0.1.0/src/pmb/health/auto_consolidate.py +128 -0
  64. pmb_ai-0.1.0/src/pmb/health/conflicts.py +363 -0
  65. pmb_ai-0.1.0/src/pmb/health/consolidate.py +791 -0
  66. pmb_ai-0.1.0/src/pmb/health/feedback.py +209 -0
  67. pmb_ai-0.1.0/src/pmb/health/multilingual_check.py +180 -0
  68. pmb_ai-0.1.0/src/pmb/health/rehearse.py +143 -0
  69. pmb_ai-0.1.0/src/pmb/health/self_test.py +337 -0
  70. pmb_ai-0.1.0/src/pmb/maintenance/__init__.py +6 -0
  71. pmb_ai-0.1.0/src/pmb/maintenance/compact.py +190 -0
  72. pmb_ai-0.1.0/src/pmb/maintenance/scheduler.py +111 -0
  73. pmb_ai-0.1.0/src/pmb/mcp/__init__.py +3 -0
  74. pmb_ai-0.1.0/src/pmb/mcp/perf.py +319 -0
  75. pmb_ai-0.1.0/src/pmb/mcp/server.py +1190 -0
  76. pmb_ai-0.1.0/src/pmb/py.typed +0 -0
  77. pmb_ai-0.1.0/src/pmb/reasoning/__init__.py +27 -0
  78. pmb_ai-0.1.0/src/pmb/reasoning/arcs.py +342 -0
  79. pmb_ai-0.1.0/src/pmb/reasoning/causation.py +353 -0
  80. pmb_ai-0.1.0/src/pmb/reasoning/code_ast.py +213 -0
  81. pmb_ai-0.1.0/src/pmb/reasoning/decompose.py +198 -0
  82. pmb_ai-0.1.0/src/pmb/reasoning/dedup.py +576 -0
  83. pmb_ai-0.1.0/src/pmb/reasoning/fact_extract.py +263 -0
  84. pmb_ai-0.1.0/src/pmb/reasoning/facts.py +179 -0
  85. pmb_ai-0.1.0/src/pmb/reasoning/images.py +180 -0
  86. pmb_ai-0.1.0/src/pmb/reasoning/llm_rerank.py +103 -0
  87. pmb_ai-0.1.0/src/pmb/reasoning/pamvr.py +579 -0
  88. pmb_ai-0.1.0/src/pmb/reasoning/predictive.py +286 -0
  89. pmb_ai-0.1.0/src/pmb/reasoning/query_split.py +166 -0
  90. pmb_ai-0.1.0/src/pmb/reasoning/reflect.py +249 -0
  91. pmb_ai-0.1.0/src/pmb/reasoning/router.py +315 -0
  92. pmb_ai-0.1.0/src/pmb/reasoning/temporal.py +243 -0
  93. pmb_ai-0.1.0/src/pmb/reasoning/typo_fix.py +390 -0
  94. pmb_ai-0.1.0/src/pmb/reasoning/user_names.py +102 -0
  95. pmb_ai-0.1.0/src/pmb/reasoning/vocab_miner.py +313 -0
  96. pmb_ai-0.1.0/src/pmb/security/__init__.py +4 -0
  97. pmb_ai-0.1.0/src/pmb/security/redact.py +161 -0
  98. pmb_ai-0.1.0/src/pmb/signals/__init__.py +16 -0
  99. pmb_ai-0.1.0/src/pmb/signals/decay.py +165 -0
  100. pmb_ai-0.1.0/src/pmb/signals/files.py +91 -0
  101. pmb_ai-0.1.0/src/pmb/signals/git.py +344 -0
  102. pmb_ai-0.1.0/src/pmb/signals/session.py +112 -0
  103. pmb_ai-0.1.0/src/pmb_ai.egg-info/PKG-INFO +837 -0
  104. pmb_ai-0.1.0/src/pmb_ai.egg-info/SOURCES.txt +149 -0
  105. pmb_ai-0.1.0/src/pmb_ai.egg-info/dependency_links.txt +1 -0
  106. pmb_ai-0.1.0/src/pmb_ai.egg-info/entry_points.txt +4 -0
  107. pmb_ai-0.1.0/src/pmb_ai.egg-info/requires.txt +29 -0
  108. pmb_ai-0.1.0/src/pmb_ai.egg-info/top_level.txt +1 -0
  109. pmb_ai-0.1.0/tests/conftest.py +83 -0
  110. pmb_ai-0.1.0/tests/test_agent_wrapper.py +296 -0
  111. pmb_ai-0.1.0/tests/test_arcs.py +230 -0
  112. pmb_ai-0.1.0/tests/test_auto_consolidate.py +172 -0
  113. pmb_ai-0.1.0/tests/test_causation.py +205 -0
  114. pmb_ai-0.1.0/tests/test_config.py +130 -0
  115. pmb_ai-0.1.0/tests/test_conflict_merge.py +177 -0
  116. pmb_ai-0.1.0/tests/test_connect.py +144 -0
  117. pmb_ai-0.1.0/tests/test_connect_codex.py +136 -0
  118. pmb_ai-0.1.0/tests/test_connect_rules.py +113 -0
  119. pmb_ai-0.1.0/tests/test_consolidate.py +470 -0
  120. pmb_ai-0.1.0/tests/test_dashboard.py +149 -0
  121. pmb_ai-0.1.0/tests/test_decompose.py +176 -0
  122. pmb_ai-0.1.0/tests/test_escalation.py +132 -0
  123. pmb_ai-0.1.0/tests/test_fact_tree.py +149 -0
  124. pmb_ai-0.1.0/tests/test_facts.py +138 -0
  125. pmb_ai-0.1.0/tests/test_feedback.py +202 -0
  126. pmb_ai-0.1.0/tests/test_goals_chains.py +179 -0
  127. pmb_ai-0.1.0/tests/test_graph.py +250 -0
  128. pmb_ai-0.1.0/tests/test_hardening.py +423 -0
  129. pmb_ai-0.1.0/tests/test_lightweight_imports.py +166 -0
  130. pmb_ai-0.1.0/tests/test_locomo_judge.py +108 -0
  131. pmb_ai-0.1.0/tests/test_multimodal.py +242 -0
  132. pmb_ai-0.1.0/tests/test_persons.py +197 -0
  133. pmb_ai-0.1.0/tests/test_phase1.py +242 -0
  134. pmb_ai-0.1.0/tests/test_phase2.py +324 -0
  135. pmb_ai-0.1.0/tests/test_phase3.py +360 -0
  136. pmb_ai-0.1.0/tests/test_ppr.py +162 -0
  137. pmb_ai-0.1.0/tests/test_predictive.py +212 -0
  138. pmb_ai-0.1.0/tests/test_query_expansion.py +95 -0
  139. pmb_ai-0.1.0/tests/test_recall_cache.py +163 -0
  140. pmb_ai-0.1.0/tests/test_redact.py +105 -0
  141. pmb_ai-0.1.0/tests/test_reflective.py +246 -0
  142. pmb_ai-0.1.0/tests/test_rehearse.py +134 -0
  143. pmb_ai-0.1.0/tests/test_reranker.py +162 -0
  144. pmb_ai-0.1.0/tests/test_router.py +187 -0
  145. pmb_ai-0.1.0/tests/test_ru_uk_suite.py +316 -0
  146. pmb_ai-0.1.0/tests/test_spreading.py +134 -0
  147. pmb_ai-0.1.0/tests/test_temporal.py +174 -0
  148. pmb_ai-0.1.0/tests/test_tiers.py +163 -0
  149. pmb_ai-0.1.0/tests/test_typo_fix.py +178 -0
  150. pmb_ai-0.1.0/tests/test_typo_fuzzy.py +203 -0
  151. pmb_ai-0.1.0/tests/test_working_memory.py +187 -0
@@ -0,0 +1,71 @@
1
+ # Changelog
2
+
3
+ All notable changes to PMB are documented here.
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Hardening pass 2 - lazy LanceDB + use-case clarity
8
+
9
+ - **`pmb stats` and friends now run in ~1 s (was ~14 s).** The single biggest user-facing cost was `import lancedb` itself: on Windows it pulls in pyarrow + torch and takes ~22 s to import. `HybridSearch.__init__` triggered that import for every CLI command, even ones that never touch vectors. Fix: `HybridSearch` defers `lancedb.connect(...)` and the table-open to a lazy `_table` property; `Engine.__init__` no longer eagerly calls `reload_bm25()`. The cost is now paid on the first `recall()` or write that actually needs vector search.
10
+ - **README "What gets stored, when" gets a `Which features help which use case` table.** Honest mapping of feature flags to workloads (multi-hop, narrative, temporal, code, multilingual, etc.) - so contributors don't assume every feature must boost LoCoMo recall.
11
+ - **All 88 core tests + 9 smoke tests still pass.**
12
+
13
+ ### Hardening pass 1 - import hygiene + test foundation
14
+
15
+ - **Lazy top-level imports.** `import pmb` no longer pulls in LanceDB, sentence-transformers, numpy, rank_bm25, fastmcp, yaml, torch or transformers. Heavy attributes (`Engine`, `Workspace`, `detect_workspace`) are exposed via PEP 562 `__getattr__` and loaded on first access. Measured: bare `import pmb` is now **2.4 ms** (was ~14 s when the engine was eagerly imported). Same treatment applied to `pmb.core`.
16
+ - **`tests/conftest.py`** added with shared fixtures (`tmp_pmb_home`, `tmp_workspace_dir`, `isolated_engine`) and a `sys.path` fallback so new tests don't need the boilerplate.
17
+ - **`tests/test_lightweight_imports.py`** added - 9 smoke tests that spawn fresh interpreters and assert which heavy modules are loaded after specific imports. If a future change re-introduces an eager heavy import at `pmb/__init__.py` it will fail this suite.
18
+ - **No behaviour change.** All 88 core tests (the `make test` set used in CI) still pass; `from pmb import Engine` still works.
19
+
20
+ ### Recall ablation findings + default changes
21
+
22
+ Ran a full-system ablation across 19 retrieval components on LoCoMo conv-26/30/41 (see `scripts/benchmarks/ablation_full.py`). Key findings:
23
+
24
+ - **`recall.typo_correction = True` was hurting recall by ~6.2 points.** The Levenshtein-≤2 fuzzy rewriter was "correcting" correctly-spelled tokens into similar-looking but wrong entity names. **Default flipped to `False`.** Existing per-workspace overrides are unaffected.
25
+ - **BM25-heavy fusion outperformed the symmetric default.** `recall.bm25_weight` raised `0.5 -> 0.7`. Vector-only retrieval loses 18 points on this dataset; the embedding channel adds only marginal signal.
26
+ - **Net effect on the full 10-conversation LoCoMo benchmark: 91.6 % -> 94.1 % evidence-recall@10** (+2.5 pp, every conversation improved, range now 91.2-96.2 %).
27
+ - **Twelve of nineteen ablated features show 0.000 delta on LoCoMo:** tiers, causation walk, arc expansion, collapse-reflections, reflection-to-edges, predictive cache, code-AST, LRU cache, multi-entity bonus, PPR, adaptive routing, spreading activation, temporal. These are not removed - some are designed for long-term dynamics that LoCoMo doesn't probe - but the README and docs no longer claim they carry the benchmark number.
28
+ - **Cross-encoder reranker (`recall.rerank = True`) regresses 17 points and adds 845 ms p50.** Recommendation removed from default setup; flag is still available as experimental.
29
+
30
+ See `scripts/benchmarks/ablation_full.py` and `docs/HARDENING_NOTES.md` for the raw data and methodology.
31
+
32
+ ## [0.1.0] - Initial public release
33
+
34
+ ### Highlights
35
+
36
+ - Single-file install: `pip install -e .` exposes `pmb` on `$PATH`.
37
+ - 91.6 % evidence-recall@10 on LoCoMo full 10-conversation run (vs published mem0 / Letta / Zep numbers of 70-80 %).
38
+ - 90-140 ms p50 recall latency, 2 ms async writes.
39
+ - 13 semantic layers, 5 access paths, 3 tiers - every layer optional and configurable.
40
+ - Web dashboard + 5-tab terminal TUI for inspection.
41
+ - MCP server for Claude Code, Codex CLI, Cursor.
42
+ - Optional Ollama integration for fully-local LLM ops (consolidation, dedup verify, pmb-chat).
43
+
44
+ ### Architecture decisions worth knowing
45
+
46
+ - **Local-first.** SQLite + LanceDB on disk; no daemon, no service, no network.
47
+ - **Lazy-by-default agent prompt.** PMB is OFF until an explicit trigger ("remember", personal fact, "what did I…"). General Q&A bypasses PMB entirely.
48
+ - **Async writes (fire-and-forget MCP).** `record_batch` returns in ~2 ms; embedding + LanceDB indexing happen in a background thread.
49
+ - **BM25 fallback for cold reads.** First `recall` after process start returns text-match results in ~100 ms while the sentence-transformers model finishes loading.
50
+ - **Multi-layer dedup.** L1 exact (5 ms) + L2 cosine ≥ 0.92 (50 ms) at write time; L2.5 borderline queue for LLM-verified merges; L3 dashboard review tab for ambiguous pairs.
51
+ - **Conservative defaults.** False-merge risk minimised: never merges across event types, threshold 0.92 leaves a safe gap.
52
+
53
+ ### Tools and surfaces
54
+
55
+ - `pmb tui` - five tabs: Memory, Recall, Stats, Dedup, Tune
56
+ - `pmb dashboard` - HTTP dashboard on :8765 with Graph, Events, Performance, Duplicates, Recall Debug
57
+ - `pmb tune` - settings-only TUI (67 knobs)
58
+ - `pmb ollama` - health, install/use models, smoke test
59
+ - `pmb connect codex | claude | cursor` - wires MCP into the agent's config and rules file
60
+ - `pmb dedupe` / `pmb regraph` / `pmb prune-graph` - maintenance ops
61
+
62
+ ### Settings (67 across 9 categories)
63
+
64
+ `recall` (36), `consolidate` (9), `dedup` (6), `chat` (5), `decay` (3), `embedding` (3), `feedback` (2), `ollama` (2), `mcp` (1). All exposed in TUI Tune tab, CLI `pmb config`, and dashboard.
65
+
66
+ ### Known limits
67
+
68
+ - Single-machine. No cross-device sync.
69
+ - Cold first recall after process start blocks on model load if the BM25 fallback path is disabled.
70
+ - Code-AST extraction is Python-only (regex fallback for broken / partial code).
71
+ - Dashboard and TUI assume one workspace at a time.
@@ -0,0 +1,23 @@
1
+ cff-version: 1.2.0
2
+ title: PMB - Personal Memory Brain
3
+ message: >-
4
+ If you use PMB in published research or build on top of it,
5
+ please cite this software.
6
+ type: software
7
+ authors:
8
+ - name: PMB contributors
9
+ repository-code: https://github.com/yourname/pmb
10
+ abstract: >-
11
+ Local-first persistent memory for AI coding agents over MCP.
12
+ Hybrid BM25+vector retrieval with SQLite + LanceDB storage.
13
+ Evidence-recall@10 on LoCoMo: 94.1% across the full 10-conversation
14
+ run with v0.1.0 defaults. Warm-recall p50 latency 65-195 ms;
15
+ no API keys required.
16
+ keywords:
17
+ - mcp
18
+ - memory
19
+ - retrieval
20
+ - ai-agent
21
+ - rag
22
+ license: Apache-2.0
23
+ version: 0.1.0
@@ -0,0 +1,24 @@
1
+ # Code of Conduct
2
+
3
+ ## In short
4
+
5
+ Be respectful. Engage with the work, not the person. Disagree on technical grounds, document trade-offs, move on.
6
+
7
+ ## Specifics
8
+
9
+ - Use the issue tracker for bugs and concrete proposals, not for venting.
10
+ - "It feels slow / wrong / weird" is not a useful report - include timings, repros, version info.
11
+ - Code review is about the code. Personal attacks, slurs, harassment of any kind - instant ban.
12
+ - English is the working language. Other languages welcome in private discussion but PRs and issues should be in English so anyone can participate.
13
+
14
+ ## Reporting issues with conduct
15
+
16
+ Email the maintainer or open a private GitHub conversation. We will read every report.
17
+
18
+ ## Enforcement
19
+
20
+ The maintainers may remove comments, close issues, or ban contributors who repeatedly act against this code. There is no formal three-strike system - egregious behaviour gets a ban on the first occurrence.
21
+
22
+ ---
23
+
24
+ Adapted in spirit from the [Contributor Covenant](https://www.contributor-covenant.org/), kept short on purpose.
@@ -0,0 +1,110 @@
1
+ # Contributing to PMB
2
+
3
+ Thanks for your interest. PMB is intentionally small and opinionated; here is what helps and what doesn't.
4
+
5
+ ## Development setup
6
+
7
+ ```bash
8
+ git clone <repo-url> pmb
9
+ cd pmb
10
+ python -m venv .venv
11
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
12
+ pip install -e .
13
+ pip install textual # for the TUI
14
+ pip install pytest # for tests
15
+ ```
16
+
17
+ Verify:
18
+
19
+ ```bash
20
+ make test # 88 passed in ~80s — the same set CI runs
21
+ make test-smoke # 9 passed in ~5s — import-weight regression tests
22
+ ```
23
+
24
+ ## Running tests
25
+
26
+ **Use `make test`, not `pytest tests/` directly.** The full pytest target (`pytest tests/`) has a known deadlock: several modules trigger parallel `huggingface_hub` model downloads against the same on-disk cache, and the second downloader blocks waiting for a lock the first one hasn't released. Symptom: pytest hangs forever on collection.
27
+
28
+ | Target | What it runs | When to use |
29
+ |---|---|---|
30
+ | `make test` (= `make test-core`) | 8 deterministic files from `.github/workflows/ci.yml`, 88 tests | Default during development; matches CI |
31
+ | `make test-smoke` | `tests/test_lightweight_imports.py`, 9 tests | After touching `pmb/__init__.py` or any module added to the lazy-attribute table |
32
+ | `make test-all-WARN` | The full `tests/` directory | Only if your HF cache is already populated; otherwise it will hang |
33
+ | `pytest tests/test_X.py` | One specific file | Reproducing a single failure |
34
+
35
+ If you add a new test that depends on a HuggingFace download, please mark it (`@pytest.mark.heavy`, manual `pytest -k`) and document why - we'd rather not grow the deadlock surface.
36
+
37
+ ## Project layout
38
+
39
+ ```
40
+ src/pmb/
41
+ core/ - engine, events, search, workspace, recall_cache
42
+ graph/ - entities, persons, store (SQLite-backed)
43
+ reasoning/ - facts, reflect, causation, arcs, temporal, dedup, typo_fix
44
+ mcp/ - FastMCP server, perf tracking, tools schema
45
+ dashboard/ - local web UI (HTTP, no framework)
46
+ cli/ - typer entry points (main, tui_*, ollama_cmd, connect)
47
+ agent_wrapper/ - pmb-chat (optional standalone chat loop)
48
+ health/ - consolidation, doctor checks
49
+ eval/ - LoCoMo judge helpers
50
+ tests/ - pytest, no fixtures spanning files
51
+ scripts/ - benchmarks, demos, profilers
52
+ ```
53
+
54
+ ## Where to add things
55
+
56
+ | You want to… | Touch this |
57
+ |---|---|
58
+ | add a recall ranking signal | `core/engine.py` (search the `recall(` method, ~12 stages) |
59
+ | change a tunable knob | `config.py` (single SCHEMA dict) |
60
+ | add an MCP tool | `mcp/server.py` (decorate with `@mcp.tool()`) |
61
+ | add a CLI command | `cli/main.py` |
62
+ | add a dashboard tab | `dashboard/static/index.html` + a handler in `dashboard/server.py` |
63
+ | add a TUI tab | `cli/tui_workspace.py` |
64
+
65
+ ## Code style
66
+
67
+ - Keep modules focused. The recall pipeline is already large; do not add new top-level layers without a clear reason.
68
+ - Public methods on `Engine` should be readable from a docstring alone.
69
+ - All write-path additions must be sub-100 ms on warm cache. Profile before merging if you add embedding work.
70
+ - Pure-Python where possible. PyTorch is fine (already a dep); avoid adding new heavy dependencies.
71
+
72
+ ## Tests
73
+
74
+ - Unit tests live in `tests/`. They use temp workspaces (`tempfile.mkdtemp`); don't write to `~/.pmb/` from a test.
75
+ - For features that touch recall scoring, add a test in `tests/test_graph.py` style that asserts ordering, not exact scores.
76
+ - The full LoCoMo bench (`scripts/benchmark_locomo.py`) is the integration test for retrieval quality.
77
+
78
+ ## Pull requests
79
+
80
+ - One concern per PR.
81
+ - Include a short description of what changed and **a benchmark line** if recall accuracy or latency could be affected.
82
+ - Updating the README's benchmark numbers is fine when you have new data - link to the run that produced them.
83
+
84
+ ## Hardening passes (style for cross-cutting refactors)
85
+
86
+ If you are doing a sweeping technical-debt pass (lazy imports, exception handling, type annotations, etc.) please follow this protocol so it stays reviewable:
87
+
88
+ 1. **Phase 0 - inventory first.** Before changing anything, post the current state to the PR description: file/line numbers, what each call does, why it exists. For exception-handler changes specifically, see `docs/HARDENING_NOTES.md` for the categorisation we want to preserve.
89
+ 2. **One phase per commit.** Lazy imports, conftest, smoke tests, exception logging - each is its own commit so we can bisect a regression.
90
+ 3. **Run `make test` after every commit.** Not `make test-all-WARN`.
91
+ 4. **Behaviour-preserving by default.** If a change alters runtime behaviour (e.g. converting a silent fallback into an exception), call it out explicitly and add a test.
92
+ 5. **Update CHANGELOG.md.** Hardening counts as a real change; document the measurable effect (`import pmb` time, test count, etc.).
93
+
94
+ ## What we are not looking for
95
+
96
+ - Multi-user, multi-device, cloud sync. PMB is single-user single-machine on purpose.
97
+ - Frontend frameworks. The dashboard is plain HTML/JS; the TUI is textual. Keep it that way.
98
+ - New embedding backends. We have sentence-transformers (default) and fastembed (optional). Adding a third needs a strong case.
99
+
100
+ ## Filing issues
101
+
102
+ Useful issues include: a minimal repro (or a workspace dump), the version of PMB (`pip show pmb`), and what command/agent triggered it. "It feels slow" without timing data is harder to act on - `pmb tui` → `[3] Stats` shows the real numbers.
103
+
104
+ ## Licensing of contributions
105
+
106
+ PMB is licensed under **Apache License 2.0** (see [`LICENSE`](LICENSE)).
107
+
108
+ By submitting a pull request, you agree that your contribution is licensed under the same terms - this is the default behaviour spelled out in Apache 2.0 §5 ("Submission of Contributions"). No separate CLA, no sign-off chain. Just open the PR.
109
+
110
+ If your contribution includes code or assets you did not write, list their origin and license in the PR description so we can add them to [`NOTICE`](NOTICE).
pmb_ai-0.1.0/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for describing the origin of the Work and
141
+ reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 PMB contributors
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,44 @@
1
+ # Files to include in `python -m build` source distribution (sdist).
2
+ # Wheel uses `pyproject.toml` setuptools.packages.find — this is just
3
+ # for sdist completeness.
4
+
5
+ include README.md
6
+ include LICENSE
7
+ include NOTICE
8
+ include CHANGELOG.md
9
+ include CITATION.cff
10
+ include CODE_OF_CONDUCT.md
11
+ include CONTRIBUTING.md
12
+ include SECURITY.md
13
+ include pyproject.toml
14
+ include Makefile
15
+
16
+ # Documentation
17
+ recursive-include docs *.md
18
+ # Logo + screenshots referenced by README.md (rendered on PyPI page)
19
+ recursive-include docs/assets *.png *.css
20
+
21
+ # Test files for downstream packagers who want to verify the install
22
+ recursive-include tests *.py
23
+ include tests/conftest.py
24
+
25
+ # Package data
26
+ recursive-include src/pmb py.typed
27
+ recursive-include src/pmb/dashboard/static *
28
+
29
+ # Exclude development artefacts
30
+ global-exclude __pycache__
31
+ global-exclude *.pyc
32
+ global-exclude *.pyo
33
+ global-exclude .DS_Store
34
+ global-exclude Thumbs.db
35
+ global-exclude *.swp
36
+ global-exclude .gitignore
37
+ prune .venv
38
+ prune .git
39
+ prune .github
40
+ prune scripts/benchmarks/_test_*.py
41
+ prune docs/assets/_capture_server.py
42
+ prune docs/assets/_save_png.py
43
+ prune docs/assets/*.html
44
+ prune .claude
pmb_ai-0.1.0/Makefile ADDED
@@ -0,0 +1,76 @@
1
+ .PHONY: help install dev test test-core test-smoke test-all-WARN lint format clean bench bench-quick tui dashboard
2
+
3
+ help:
4
+ @echo "PMB development targets:"
5
+ @echo " make install - pip install -e ."
6
+ @echo " make dev - install + dev tools (pytest, ruff, textual)"
7
+ @echo ""
8
+ @echo " make test - alias for test-core (CI baseline, 88 tests, ~80s)"
9
+ @echo " make test-core - the 8 deterministic core test files from .github/workflows/ci.yml"
10
+ @echo " make test-smoke - lightweight import smoke tests only (~5s)"
11
+ @echo " make test-all-WARN - full pytest tests/ (KNOWN ISSUE: hangs on huggingface_hub parallel"
12
+ @echo " downloads when the embedding model isn't cached; only run if you"
13
+ @echo " have the HF cache populated)"
14
+ @echo ""
15
+ @echo " make lint - ruff check"
16
+ @echo " make format - ruff format"
17
+ @echo " make clean - remove build artefacts and __pycache__"
18
+ @echo " make bench - full LoCoMo benchmark (10 conversations, ~30 min)"
19
+ @echo " make bench-quick - quick smoke benchmark (3 conversations, ~3 min)"
20
+ @echo " make tui - launch terminal UI"
21
+ @echo " make dashboard - launch web dashboard on :8765"
22
+
23
+ install:
24
+ pip install -e .
25
+
26
+ dev:
27
+ pip install -e ".[dev]"
28
+
29
+ # --------------------------------------------------------------------------
30
+ # Tests. The default `test` target intentionally runs ONLY the 8 core files
31
+ # used by CI. Running `pytest tests/` directly is known to deadlock on first
32
+ # run because several test modules trigger parallel huggingface_hub model
33
+ # downloads against the same cache directory. Until that is fixed, use:
34
+ # - `make test` for the deterministic CI baseline
35
+ # - `make test-smoke` for the import-weight smoke tests
36
+ # - `make test-all-WARN` only if your HF cache is already populated
37
+ # --------------------------------------------------------------------------
38
+
39
+ test: test-core
40
+
41
+ test-core:
42
+ pytest tests/test_graph.py tests/test_persons.py tests/test_goals_chains.py \
43
+ tests/test_fact_tree.py tests/test_recall_cache.py tests/test_config.py \
44
+ tests/test_redact.py tests/test_causation.py -q
45
+
46
+ test-smoke:
47
+ pytest tests/test_lightweight_imports.py -v
48
+
49
+ test-all-WARN:
50
+ @echo "WARNING: full pytest is known to deadlock on parallel HF downloads."
51
+ @echo " If this hangs >60s, Ctrl-C and run 'make test-core' instead."
52
+ pytest tests/ -q
53
+
54
+ lint:
55
+ ruff check src/ tests/ scripts/
56
+
57
+ format:
58
+ ruff format src/ tests/ scripts/
59
+
60
+ clean:
61
+ rm -rf build/ dist/ *.egg-info src/*.egg-info
62
+ find . -type d -name __pycache__ -exec rm -rf {} +
63
+ find . -type d -name .pytest_cache -exec rm -rf {} +
64
+ find . -type d -name .ruff_cache -exec rm -rf {} +
65
+
66
+ bench:
67
+ python scripts/benchmarks/benchmark_locomo.py --n-conversations 10 --top-k 10
68
+
69
+ bench-quick:
70
+ python scripts/benchmarks/benchmark_locomo.py --n-conversations 3 --top-k 10
71
+
72
+ tui:
73
+ pmb tui
74
+
75
+ dashboard:
76
+ pmb dashboard
pmb_ai-0.1.0/NOTICE ADDED
@@ -0,0 +1,31 @@
1
+ PMB - Personal Memory Brain
2
+ Copyright 2026 PMB contributors
3
+
4
+ This product includes software developed by the PMB contributors
5
+ (https://github.com/yourname/pmb).
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ ----------------------------------------------------------------------
14
+
15
+ Third-party components and their licenses:
16
+
17
+ - sentence-transformers (Apache-2.0) - local embedding models
18
+ - LanceDB (Apache-2.0) - local vector store
19
+ - FastMCP (Apache-2.0) - MCP server framework
20
+ - rank-bm25 (Apache-2.0) - BM25 lexical retrieval
21
+ - Typer / Rich (MIT) - CLI rendering
22
+ - Textual (MIT) - TUI workspace
23
+ - NumPy (BSD-3-Clause) - numerical routines
24
+ - PyYAML (MIT) - config loading
25
+
26
+ Optional dependencies pulled in by `pmb[all]`:
27
+ - anthropic (MIT) - consolidation backend
28
+ - fastembed (Apache-2.0) - ONNX embeddings
29
+
30
+ Full license texts for these dependencies ship inside the installed
31
+ distributions (look under site-packages/<pkg>-*.dist-info/licenses/).