brainlayer 1.4.2__tar.gz → 1.4.3__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 (186) hide show
  1. {brainlayer-1.4.2 → brainlayer-1.4.3}/PKG-INFO +3 -3
  2. {brainlayer-1.4.2 → brainlayer-1.4.3}/README.md +2 -2
  3. {brainlayer-1.4.2 → brainlayer-1.4.3}/pyproject.toml +1 -1
  4. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.drain.plist +5 -6
  5. brainlayer-1.4.3/scripts/launchd/com.brainlayer.p0-counter.plist +49 -0
  6. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/install.sh +7 -2
  7. {brainlayer-1.4.2 → brainlayer-1.4.3}/server.json +3 -3
  8. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/__init__.py +1 -1
  9. brainlayer-1.4.3/src/brainlayer/agent_provenance.py +185 -0
  10. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli/__init__.py +396 -46
  11. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/content_class.py +2 -2
  12. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/doctor.py +85 -9
  13. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/drain.py +23 -18
  14. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/embeddings.py +3 -3
  15. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/health_check.py +301 -4
  16. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/index_new.py +14 -3
  17. brainlayer-1.4.3/src/brainlayer/ingest_denylist.py +64 -0
  18. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/jsonl_backup.py +207 -43
  19. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/_shared.py +117 -10
  20. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/search_handler.py +266 -196
  21. brainlayer-1.4.3/src/brainlayer/p0_longitudinal_count.py +120 -0
  22. brainlayer-1.4.3/src/brainlayer/pipeline/secret_scrub.py +222 -0
  23. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/queue_io.py +22 -15
  24. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/search_repo.py +24 -10
  25. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/vector_store.py +537 -200
  26. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/watcher.py +17 -0
  27. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/watcher_bridge.py +50 -2
  28. {brainlayer-1.4.2 → brainlayer-1.4.3}/.gitignore +0 -0
  29. {brainlayer-1.4.2 → brainlayer-1.4.3}/LICENSE +0 -0
  30. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/backup-daily.sh +0 -0
  31. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/brainlayer-env-run.sh +0 -0
  32. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/brainlayer.env.example +0 -0
  33. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.backup-daily.plist +0 -0
  34. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.decay.plist +0 -0
  35. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.enrichment.plist +0 -0
  36. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.health-check.plist +0 -0
  37. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.hotlane-brainbar.plist +0 -0
  38. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.index.plist +0 -0
  39. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.jsonl-backup.plist +0 -0
  40. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.maintenance-nightly.plist +0 -0
  41. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.maintenance-weekly.plist +0 -0
  42. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.repair-fts.plist +0 -0
  43. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.wal-checkpoint.plist +0 -0
  44. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.watch.plist +0 -0
  45. {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/jsonl-backup.sh +0 -0
  46. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/_helpers.py +0 -0
  47. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/agent_profiles.py +0 -0
  48. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/alarm.py +0 -0
  49. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/backup_daily.py +0 -0
  50. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/bitemporal.py +0 -0
  51. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/brainbar_hybrid_helper.py +0 -0
  52. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/calibrate.py +0 -0
  53. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/chunk_origin.py +0 -0
  54. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/chunk_origin_backfill.py +0 -0
  55. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/classify.py +0 -0
  56. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/claude_paths.py +0 -0
  57. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli/wizard.py +0 -0
  58. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli_new.py +0 -0
  59. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cloud_backfill.py +0 -0
  60. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/clustering.py +0 -0
  61. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/config.py +0 -0
  62. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/correction_judge.py +0 -0
  63. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/data/agents_registry.yaml +0 -0
  64. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/data/sandbox_seeds/skill-eval-baseline.json +0 -0
  65. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/db_shrink.py +0 -0
  66. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay.py +0 -0
  67. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay_backfill.py +0 -0
  68. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay_job.py +0 -0
  69. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/dedupe.py +0 -0
  70. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/deploy_drift.py +0 -0
  71. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/drain_liveness.py +0 -0
  72. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/engine.py +0 -0
  73. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/enrichment_controller.py +0 -0
  74. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/__init__.py +0 -0
  75. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_enrich_runner.py +0 -0
  76. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_variants.py +0 -0
  77. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_variants.yaml +0 -0
  78. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/benchmark.py +0 -0
  79. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_gold.py +0 -0
  80. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_graders.py +0 -0
  81. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_judge.py +0 -0
  82. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_llm_judge.py +0 -0
  83. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_quality_benchmark.py +0 -0
  84. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/experiment_store.py +0 -0
  85. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/fixtures/README.md +0 -0
  86. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/labeling/enrichment-labeler.html +0 -0
  87. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/__init__.py +0 -0
  88. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/__main__.py +0 -0
  89. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/baseline_store.py +0 -0
  90. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/cli.py +0 -0
  91. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/models.py +0 -0
  92. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/phoenix_client.py +0 -0
  93. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/regression_gate.py +0 -0
  94. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/triggers.py +0 -0
  95. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/fallback_replay.py +0 -0
  96. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/git_learning.py +0 -0
  97. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/hooks/__init__.py +0 -0
  98. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/hooks/indexer.py +0 -0
  99. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest/__init__.py +0 -0
  100. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest/codex.py +0 -0
  101. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest_guard.py +0 -0
  102. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/isolation_proof.py +0 -0
  103. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg/__init__.py +0 -0
  104. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_cleanup.py +0 -0
  105. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_judge.py +0 -0
  106. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_promotion.py +0 -0
  107. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_repo.py +0 -0
  108. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_review_session.py +0 -0
  109. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_session_finish.py +0 -0
  110. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_session_harvest.py +0 -0
  111. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/launchd_primitive.py +0 -0
  112. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/lexical_defense.py +0 -0
  113. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/lexical_defense_dictionary.json +0 -0
  114. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/maintenance.py +0 -0
  115. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/__init__.py +0 -0
  116. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/_format.py +0 -0
  117. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/enrich_handler.py +0 -0
  118. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/entity_handler.py +0 -0
  119. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/store_handler.py +0 -0
  120. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/tags_handler.py +0 -0
  121. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp_stdio_bridge.py +0 -0
  122. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/memory_types.py +0 -0
  123. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/migrate.py +0 -0
  124. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/parent_death.py +0 -0
  125. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/paths.py +0 -0
  126. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/phonetic.py +0 -0
  127. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/__init__.py +0 -0
  128. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/agent_enrichment.py +0 -0
  129. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/analyze_communication.py +0 -0
  130. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/batch_extraction.py +0 -0
  131. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/brain_graph.py +0 -0
  132. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/chat_tags.py +0 -0
  133. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/chunk.py +0 -0
  134. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/classify.py +0 -0
  135. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/cluster_sampling.py +0 -0
  136. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/code_intelligence.py +0 -0
  137. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/correction_detection.py +0 -0
  138. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/correction_mining.py +0 -0
  139. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/digest.py +0 -0
  140. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/enrichment.py +0 -0
  141. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/enrichment_tiers.py +0 -0
  142. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/entity_extraction.py +0 -0
  143. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/entity_resolution.py +0 -0
  144. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract.py +0 -0
  145. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_claude_desktop.py +0 -0
  146. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_corrections.py +0 -0
  147. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_markdown.py +0 -0
  148. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_whatsapp.py +0 -0
  149. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/frustration_mining.py +0 -0
  150. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/git_overlay.py +0 -0
  151. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/kg_extraction.py +0 -0
  152. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/kg_extraction_groq.py +0 -0
  153. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/longitudinal_analyzer.py +0 -0
  154. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/obsidian_export.py +0 -0
  155. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/operation_grouping.py +0 -0
  156. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/plan_linking.py +0 -0
  157. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/rate_limiter.py +0 -0
  158. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/sanitize.py +0 -0
  159. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/semantic_style.py +0 -0
  160. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/sentiment.py +0 -0
  161. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/session_enrichment.py +0 -0
  162. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/style_embed.py +0 -0
  163. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/style_index.py +0 -0
  164. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/tag_entity_promotion.py +0 -0
  165. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/temporal_chains.py +0 -0
  166. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/time_batcher.py +0 -0
  167. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/unified_timeline.py +0 -0
  168. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/write_queue.py +0 -0
  169. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance.py +0 -0
  170. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance_autosupersede.py +0 -0
  171. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance_integration.py +0 -0
  172. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/queue_merge.py +0 -0
  173. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/reembed_backfill.py +0 -0
  174. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/sandbox_db.py +0 -0
  175. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/scoping.py +0 -0
  176. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/search_profile.py +0 -0
  177. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/session_repo.py +0 -0
  178. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/setup.py +0 -0
  179. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/storage.py +0 -0
  180. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/store.py +0 -0
  181. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/system_prompt_guard.py +0 -0
  182. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/tag_normalization.py +0 -0
  183. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/taxonomy.json +0 -0
  184. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/telemetry.py +0 -0
  185. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/types.py +0 -0
  186. {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/wal_checkpoint.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brainlayer
3
- Version: 1.4.2
3
+ Version: 1.4.3
4
4
  Summary: Persistent memory MCP server for AI agents — 13 tools, semantic search, knowledge graph, on-device SQLite
5
5
  Project-URL: Homepage, https://brainlayer.etanheyman.com
6
6
  Project-URL: Repository, https://github.com/EtanHey/brainlayer
@@ -80,9 +80,9 @@ Description-Content-Type: text/markdown
80
80
  [![Tests](https://img.shields.io/badge/tests-1%2C848%20Python%20%2B%2054%20Swift-brightgreen.svg)](#testing)
81
81
  [![Website](https://img.shields.io/badge/site-brainlayer.etanheyman.com-d4956a.svg)](https://brainlayer.etanheyman.com)
82
82
 
83
- Every architecture decision, every debugging session, every preference you've expressed — **gone between sessions.** You repeat yourself constantly. Your agent rediscovers bugs it already fixed.
83
+ Every architecture decision, every debugging session, every preference you've expressed — **gone between sessions.** You repeat yourself constantly. Your agents rediscover bugs they already fixed, and re-make choices the team already reasoned through.
84
84
 
85
- BrainLayer gives any MCP-compatible AI agent persistent memory across conversations. One SQLite file. No cloud. No Docker. Just `pip install`.
85
+ BrainLayer gives any MCP-compatible AI agent persistent memory across conversations — and gives a whole **fleet** of agents a shared organizational memory: what one agent learns (a fix, a decision, what eroded and why) becomes experience the others inherit before they repeat the mistake. One SQLite file. No cloud. No Docker. Just `pip install`.
86
86
 
87
87
  ```text
88
88
  "What approach did I use for auth last month?" → brain_search
@@ -9,9 +9,9 @@
9
9
  [![Tests](https://img.shields.io/badge/tests-1%2C848%20Python%20%2B%2054%20Swift-brightgreen.svg)](#testing)
10
10
  [![Website](https://img.shields.io/badge/site-brainlayer.etanheyman.com-d4956a.svg)](https://brainlayer.etanheyman.com)
11
11
 
12
- Every architecture decision, every debugging session, every preference you've expressed — **gone between sessions.** You repeat yourself constantly. Your agent rediscovers bugs it already fixed.
12
+ Every architecture decision, every debugging session, every preference you've expressed — **gone between sessions.** You repeat yourself constantly. Your agents rediscover bugs they already fixed, and re-make choices the team already reasoned through.
13
13
 
14
- BrainLayer gives any MCP-compatible AI agent persistent memory across conversations. One SQLite file. No cloud. No Docker. Just `pip install`.
14
+ BrainLayer gives any MCP-compatible AI agent persistent memory across conversations — and gives a whole **fleet** of agents a shared organizational memory: what one agent learns (a fix, a decision, what eroded and why) becomes experience the others inherit before they repeat the mistake. One SQLite file. No cloud. No Docker. Just `pip install`.
15
15
 
16
16
  ```text
17
17
  "What approach did I use for auth last month?" → brain_search
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "brainlayer"
3
- version = "1.4.2"
3
+ version = "1.4.3"
4
4
  description = "Persistent memory MCP server for AI agents — 13 tools, semantic search, knowledge graph, on-device SQLite"
5
5
  license = {text = "Apache-2.0"}
6
6
  readme = "README.md"
@@ -7,9 +7,11 @@
7
7
  <key>ProgramArguments</key>
8
8
  <array>
9
9
  <string>__BRAINLAYER_ENV_RUN__</string>
10
- <string>__PYTHON_BIN__</string>
11
- <string>-m</string>
12
- <string>brainlayer.drain</string>
10
+ <string>/usr/bin/env</string>
11
+ <string>BRAINLAYER_DRAIN_EMBED=0</string>
12
+ <string>__BRAINLAYER_BIN__</string>
13
+ <string>drain</string>
14
+ <string>--daemon</string>
13
15
  <string>--batch-size</string>
14
16
  <string>50</string>
15
17
  </array>
@@ -25,9 +27,6 @@
25
27
  <string>__BRAINLAYER_ENV_FILE__</string>
26
28
  <key>BRAINLAYER_LAUNCHD_SERVICE</key>
27
29
  <string>drain</string>
28
- <!-- Production leaves drain embedding enabled. Embeddings are precomputed
29
- before BEGIN IMMEDIATE, so vector coverage does not depend on hotlane
30
- liveness and the write-lock window stays bounded. -->
31
30
  </dict>
32
31
  <key>StandardOutPath</key>
33
32
  <string>__HOME__/Library/Logs/brainlayer/drain.out.log</string>
@@ -0,0 +1,49 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>com.brainlayer.p0-counter</string>
7
+ <key>ProgramArguments</key>
8
+ <array>
9
+ <string>__BRAINLAYER_ENV_RUN__</string>
10
+ <string>__BRAINLAYER_BIN__</string>
11
+ <string>p0-counter</string>
12
+ </array>
13
+ <key>EnvironmentVariables</key>
14
+ <dict>
15
+ <key>PATH</key>
16
+ <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:__HOME__/.local/bin</string>
17
+ <key>PYTHONUNBUFFERED</key>
18
+ <string>1</string>
19
+ <key>BRAINLAYER_REPO_ROOT</key>
20
+ <string>__BRAINLAYER_DIR__</string>
21
+ <key>BRAINLAYER_ENV_FILE</key>
22
+ <string>__BRAINLAYER_ENV_FILE__</string>
23
+ <key>BRAINLAYER_LAUNCHD_SERVICE</key>
24
+ <string>p0-counter</string>
25
+ </dict>
26
+ <key>StandardOutPath</key>
27
+ <string>__HOME__/Library/Logs/brainlayer/p0-counter.out.log</string>
28
+ <key>StandardErrorPath</key>
29
+ <string>__HOME__/Library/Logs/brainlayer/p0-counter.err.log</string>
30
+ <key>StartCalendarInterval</key>
31
+ <dict>
32
+ <key>Hour</key>
33
+ <integer>5</integer>
34
+ <key>Minute</key>
35
+ <integer>0</integer>
36
+ </dict>
37
+ <key>ProcessType</key>
38
+ <string>Background</string>
39
+ <key>ExitTimeOut</key>
40
+ <integer>60</integer>
41
+ <key>LowPriorityIO</key>
42
+ <true/>
43
+ <key>SoftResourceLimits</key>
44
+ <dict>
45
+ <key>NumberOfFiles</key>
46
+ <integer>4096</integer>
47
+ </dict>
48
+ </dict>
49
+ </plist>
@@ -17,6 +17,7 @@
17
17
  # ./scripts/launchd/install.sh maintenance # Install recurring maintenance jobs
18
18
  # ./scripts/launchd/install.sh health-check # Install stability health check only
19
19
  # ./scripts/launchd/install.sh hotlane # Install BrainBar hotlane embed/enrich daemon only
20
+ # ./scripts/launchd/install.sh p0-counter # Install daily P0 longitudinal counter only
20
21
  # ./scripts/launchd/install.sh remove # Unload and remove all
21
22
  set -euo pipefail
22
23
 
@@ -330,6 +331,9 @@ case "${1:-all}" in
330
331
  verify_gemini_env_file
331
332
  install_plist hotlane-brainbar
332
333
  ;;
334
+ p0-counter)
335
+ install_plist p0-counter
336
+ ;;
333
337
  all)
334
338
  install_env_runner
335
339
  verify_config_file
@@ -357,7 +361,7 @@ case "${1:-all}" in
357
361
  elif ! install_many jsonl-backup; then
358
362
  failures=1
359
363
  fi
360
- if ! install_many maintenance-nightly maintenance-weekly health-check; then
364
+ if ! install_many maintenance-nightly maintenance-weekly health-check p0-counter; then
361
365
  failures=1
362
366
  fi
363
367
  # Remove old enrich plist only after the replacement enrichment service loads.
@@ -383,11 +387,12 @@ case "${1:-all}" in
383
387
  remove_plist maintenance-weekly 2>/dev/null || true
384
388
  remove_plist health-check 2>/dev/null || true
385
389
  remove_plist hotlane-brainbar 2>/dev/null || true
390
+ remove_plist p0-counter 2>/dev/null || true
386
391
  rm -f "$BRAINLAYER_LIB_DIR/backup-daily.sh"
387
392
  rm -f "$BRAINLAYER_LIB_DIR/jsonl-backup.sh"
388
393
  ;;
389
394
  *)
390
- echo "Usage: $0 [index|watch|enrich|enrichment|decay|drain|hotlane|repair-fts|load [name]|unload [name]|checkpoint|backup|jsonl-backup|maintenance|maintenance-nightly|maintenance-weekly|health-check|all|remove]"
395
+ echo "Usage: $0 [index|watch|enrich|enrichment|decay|drain|hotlane|repair-fts|load [name]|unload [name]|checkpoint|backup|jsonl-backup|maintenance|maintenance-nightly|maintenance-weekly|health-check|p0-counter|all|remove]"
391
396
  exit 1
392
397
  ;;
393
398
  esac
@@ -2,8 +2,8 @@
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.etanhey/brainlayer",
4
4
  "title": "BrainLayer",
5
- "description": "Persistent memory for AI agents — local-first semantic search, knowledge graph, and 12 MCP tools with ToolAnnotations. One SQLite file, no cloud, no API keys.",
6
- "version": "1.4.2",
5
+ "description": "Persistent memory for AI agents \u2014 local-first semantic search, knowledge graph, and 12 MCP tools with ToolAnnotations. One SQLite file, no cloud, no API keys.",
6
+ "version": "1.4.3",
7
7
  "websiteUrl": "https://brainlayer.etanheyman.com",
8
8
  "repository": {
9
9
  "url": "https://github.com/EtanHey/brainlayer",
@@ -14,7 +14,7 @@
14
14
  "registryType": "pypi",
15
15
  "registryBaseUrl": "https://pypi.org",
16
16
  "identifier": "brainlayer",
17
- "version": "1.4.2",
17
+ "version": "1.4.3",
18
18
  "runtimeHint": "pipx",
19
19
  "transport": {
20
20
  "type": "stdio"
@@ -1,3 +1,3 @@
1
1
  """BrainLayer (זיכרון) - Local knowledge pipeline for Claude Code conversations."""
2
2
 
3
- __version__ = "1.4.2"
3
+ __version__ = "1.4.3"
@@ -0,0 +1,185 @@
1
+ """Per-agent-class provenance decisions for transcript quarantine planning.
2
+
3
+ The classifier is pure and side-effect-free. Recon Agent-tool signatures are
4
+ detectable only when caller-provided content is available; source-only report
5
+ runs will classify those rows by path provenance instead.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import fnmatch
11
+ import os
12
+ import re
13
+ from dataclasses import dataclass
14
+ from pathlib import Path
15
+ from typing import Literal
16
+
17
+ from .content_class import normalize_content_class
18
+ from .ingest_denylist import is_denylisted
19
+
20
+ SearchPolicy = Literal["KEEP", "ISOLATE", "OUT"]
21
+ EffectiveVisibility = Literal["default", "operational", "cold"]
22
+
23
+ RECON_BRAIN_WORKER_RE = re.compile(r"\bbrain[-_ ]?worker\b", re.IGNORECASE)
24
+ RECON_WEAVE_RE = re.compile(r"(?<!\w)/weave\b|\bweave[-_ ]+(?:worker|agent|recon)\b", re.IGNORECASE)
25
+ RECON_SESSION_MINER_RE = re.compile(r"\bsession[-_ ]?miner\b", re.IGNORECASE)
26
+ RECON_AGENT_SIGNATURES = (
27
+ RECON_BRAIN_WORKER_RE,
28
+ RECON_WEAVE_RE,
29
+ RECON_SESSION_MINER_RE,
30
+ )
31
+
32
+ FLEET_REPOS = frozenset(
33
+ {
34
+ "orchestrator",
35
+ "golems",
36
+ "skill-creator",
37
+ "brainlayer",
38
+ "voicelayer",
39
+ "cmuxlayer",
40
+ "dashboard",
41
+ "cmux",
42
+ }
43
+ )
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class ProvenanceDecision:
48
+ provenance_tag: str
49
+ search_policy: SearchPolicy
50
+ reason: str
51
+
52
+
53
+ def _abspath(source_file: str | Path) -> Path:
54
+ return Path(os.path.abspath(os.path.expanduser(str(source_file))))
55
+
56
+
57
+ def _has_segment(path: Path, pattern: str) -> bool:
58
+ return any(fnmatch.fnmatchcase(part, pattern) for part in path.parts)
59
+
60
+
61
+ def _under_provider_sessions(path: Path, provider_dir: str) -> bool:
62
+ parts = path.parts
63
+ for index, part in enumerate(parts[:-1]):
64
+ if part == provider_dir and index + 1 < len(parts) and parts[index + 1] == "sessions":
65
+ return True
66
+ return False
67
+
68
+
69
+ def _under_cursor_agent_transcripts(path: Path) -> bool:
70
+ parts = path.parts
71
+ try:
72
+ cursor_index = parts.index(".cursor")
73
+ except ValueError:
74
+ return False
75
+ return "agent-transcripts" in parts[cursor_index + 1 :]
76
+
77
+
78
+ def _project_segment(path: Path) -> str | None:
79
+ parts = path.parts
80
+ for index, part in enumerate(parts[:-1]):
81
+ if part == "projects" and index > 0 and parts[index - 1] == ".claude":
82
+ return parts[index + 1]
83
+ return None
84
+
85
+
86
+ def _repo_from_project_segment(segment: str | None) -> str | None:
87
+ if not segment:
88
+ return None
89
+ normalized = segment.strip("-")
90
+ for marker in ("-Gits-", "--config-"):
91
+ if marker not in normalized:
92
+ continue
93
+ repo = normalized.rsplit(marker, 1)[-1].strip("-")
94
+ return repo.casefold() if repo else None
95
+ return normalized.rsplit("-", 1)[-1].casefold() if normalized else None
96
+
97
+
98
+ def _is_subagent(path: Path) -> bool:
99
+ return "subagents" in path.parts
100
+
101
+
102
+ def _is_direct_claude_session(path: Path) -> bool:
103
+ if is_denylisted(path):
104
+ return False
105
+ parts = path.parts
106
+ if ".claude" not in parts or "projects" not in parts:
107
+ return False
108
+ if _is_subagent(path) or _has_segment(path, "wf_*"):
109
+ return False
110
+ return path.suffix == ".jsonl"
111
+
112
+
113
+ def has_recon_agent_signature(content: str | None) -> bool:
114
+ """Return True when first-chunk/task text identifies recon Agent-tool work."""
115
+ if not content:
116
+ return False
117
+ return any(regex.search(content) for regex in RECON_AGENT_SIGNATURES)
118
+
119
+
120
+ def _has_recon_path_signature(path: Path) -> bool:
121
+ markers = {"brain-worker", "session-miner", "weave"}
122
+ parts = path.parts
123
+ marker_indexes = [index for index, part in enumerate(parts) if part in markers]
124
+ if not marker_indexes:
125
+ return False
126
+
127
+ root_indexes: list[int] = []
128
+ if "subagents" in parts:
129
+ root_indexes.append(parts.index("subagents"))
130
+ if _under_cursor_agent_transcripts(path):
131
+ root_indexes.append(parts.index("agent-transcripts"))
132
+
133
+ return any(marker_index > root_index for marker_index in marker_indexes for root_index in root_indexes)
134
+
135
+
136
+ def classify_provenance(
137
+ source_file: str,
138
+ content_class: str | None = None,
139
+ *,
140
+ content: str | None = None,
141
+ ) -> ProvenanceDecision:
142
+ """Classify a source path into an auditable provenance search policy."""
143
+ del content_class
144
+ path = _abspath(source_file)
145
+
146
+ if has_recon_agent_signature(content) or _has_recon_path_signature(path):
147
+ return ProvenanceDecision("recon-agent", "OUT", "recon Agent-tool signature wins precedence")
148
+
149
+ if _has_segment(path, "wf_*"):
150
+ return ProvenanceDecision("workflow-agent", "ISOLATE", "workflow wf_* path segment")
151
+
152
+ if _under_provider_sessions(path, ".codex"):
153
+ return ProvenanceDecision("codex-session", "KEEP", "Codex session root stays searchable")
154
+
155
+ if _under_cursor_agent_transcripts(path):
156
+ return ProvenanceDecision("cursor-gather", "ISOLATE", "Cursor agent-transcripts root")
157
+
158
+ if _under_provider_sessions(path, ".gemini"):
159
+ return ProvenanceDecision("gemini-session", "OUT", "Gemini session root")
160
+
161
+ if _is_subagent(path):
162
+ repo = _repo_from_project_segment(_project_segment(path))
163
+ if repo in FLEET_REPOS:
164
+ return ProvenanceDecision("fleet-subagent", "KEEP", f"fleet subagent project token {repo}")
165
+ return ProvenanceDecision("product-subagent", "KEEP", "non-fleet product subagent")
166
+
167
+ if _is_direct_claude_session(path):
168
+ return ProvenanceDecision("direct-session", "KEEP", "direct/control Claude session")
169
+
170
+ return ProvenanceDecision("unknown", "KEEP", "no agent provenance rule matched")
171
+
172
+
173
+ def effective_visibility(decision: ProvenanceDecision, content_class: str | None) -> EffectiveVisibility:
174
+ """Map provenance + content class onto P1.4 default/operational/cold visibility."""
175
+ if decision.search_policy == "OUT":
176
+ return "cold"
177
+ if decision.search_policy == "ISOLATE":
178
+ return "operational"
179
+
180
+ normalized = normalize_content_class(content_class)
181
+ if normalized in {"knowledge", "decision"}:
182
+ return "default"
183
+ if normalized == "operational":
184
+ return "operational"
185
+ return "cold"