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.
- {brainlayer-1.4.2 → brainlayer-1.4.3}/PKG-INFO +3 -3
- {brainlayer-1.4.2 → brainlayer-1.4.3}/README.md +2 -2
- {brainlayer-1.4.2 → brainlayer-1.4.3}/pyproject.toml +1 -1
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.drain.plist +5 -6
- brainlayer-1.4.3/scripts/launchd/com.brainlayer.p0-counter.plist +49 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/install.sh +7 -2
- {brainlayer-1.4.2 → brainlayer-1.4.3}/server.json +3 -3
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/__init__.py +1 -1
- brainlayer-1.4.3/src/brainlayer/agent_provenance.py +185 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli/__init__.py +396 -46
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/content_class.py +2 -2
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/doctor.py +85 -9
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/drain.py +23 -18
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/embeddings.py +3 -3
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/health_check.py +301 -4
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/index_new.py +14 -3
- brainlayer-1.4.3/src/brainlayer/ingest_denylist.py +64 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/jsonl_backup.py +207 -43
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/_shared.py +117 -10
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/search_handler.py +266 -196
- brainlayer-1.4.3/src/brainlayer/p0_longitudinal_count.py +120 -0
- brainlayer-1.4.3/src/brainlayer/pipeline/secret_scrub.py +222 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/queue_io.py +22 -15
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/search_repo.py +24 -10
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/vector_store.py +537 -200
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/watcher.py +17 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/watcher_bridge.py +50 -2
- {brainlayer-1.4.2 → brainlayer-1.4.3}/.gitignore +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/LICENSE +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/backup-daily.sh +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/brainlayer-env-run.sh +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/brainlayer.env.example +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.backup-daily.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.decay.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.enrichment.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.health-check.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.hotlane-brainbar.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.index.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.jsonl-backup.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.maintenance-nightly.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.maintenance-weekly.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.repair-fts.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.wal-checkpoint.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/com.brainlayer.watch.plist +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/scripts/launchd/jsonl-backup.sh +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/_helpers.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/agent_profiles.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/alarm.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/backup_daily.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/bitemporal.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/brainbar_hybrid_helper.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/calibrate.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/chunk_origin.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/chunk_origin_backfill.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/classify.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/claude_paths.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli/wizard.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cli_new.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/cloud_backfill.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/clustering.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/config.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/correction_judge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/data/agents_registry.yaml +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/data/sandbox_seeds/skill-eval-baseline.json +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/db_shrink.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay_backfill.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/decay_job.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/dedupe.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/deploy_drift.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/drain_liveness.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/engine.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/enrichment_controller.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_enrich_runner.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_variants.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/abcde_variants.yaml +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/benchmark.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_gold.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_graders.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_judge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_llm_judge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/enrichment_quality_benchmark.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/experiment_store.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/fixtures/README.md +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/labeling/enrichment-labeler.html +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/__main__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/baseline_store.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/cli.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/models.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/phoenix_client.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/regression_gate.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/eval/phoenix_gate/triggers.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/fallback_replay.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/git_learning.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/hooks/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/hooks/indexer.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest/codex.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/ingest_guard.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/isolation_proof.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_cleanup.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_judge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_promotion.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_repo.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_review_session.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_session_finish.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/kg_session_harvest.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/launchd_primitive.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/lexical_defense.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/lexical_defense_dictionary.json +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/maintenance.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/_format.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/enrich_handler.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/entity_handler.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/store_handler.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp/tags_handler.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/mcp_stdio_bridge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/memory_types.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/migrate.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/parent_death.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/paths.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/phonetic.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/__init__.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/agent_enrichment.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/analyze_communication.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/batch_extraction.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/brain_graph.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/chat_tags.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/chunk.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/classify.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/cluster_sampling.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/code_intelligence.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/correction_detection.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/correction_mining.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/digest.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/enrichment.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/enrichment_tiers.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/entity_extraction.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/entity_resolution.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_claude_desktop.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_corrections.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_markdown.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/extract_whatsapp.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/frustration_mining.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/git_overlay.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/kg_extraction.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/kg_extraction_groq.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/longitudinal_analyzer.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/obsidian_export.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/operation_grouping.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/plan_linking.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/rate_limiter.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/sanitize.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/semantic_style.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/sentiment.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/session_enrichment.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/style_embed.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/style_index.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/tag_entity_promotion.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/temporal_chains.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/time_batcher.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/unified_timeline.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/pipeline/write_queue.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance_autosupersede.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/provenance_integration.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/queue_merge.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/reembed_backfill.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/sandbox_db.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/scoping.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/search_profile.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/session_repo.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/setup.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/storage.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/store.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/system_prompt_guard.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/tag_normalization.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/taxonomy.json +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/telemetry.py +0 -0
- {brainlayer-1.4.2 → brainlayer-1.4.3}/src/brainlayer/types.py +0 -0
- {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.
|
|
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
|
[](#testing)
|
|
81
81
|
[](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
|
|
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
|
[](#testing)
|
|
10
10
|
[](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
|
|
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
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
<key>ProgramArguments</key>
|
|
8
8
|
<array>
|
|
9
9
|
<string>__BRAINLAYER_ENV_RUN__</string>
|
|
10
|
-
<string
|
|
11
|
-
<string
|
|
12
|
-
<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
|
|
6
|
-
"version": "1.4.
|
|
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.
|
|
17
|
+
"version": "1.4.3",
|
|
18
18
|
"runtimeHint": "pipx",
|
|
19
19
|
"transport": {
|
|
20
20
|
"type": "stdio"
|
|
@@ -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"
|