brainlayer 1.5.76__tar.gz → 1.5.78__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 (266) hide show
  1. {brainlayer-1.5.76 → brainlayer-1.5.78}/PKG-INFO +1 -1
  2. {brainlayer-1.5.76 → brainlayer-1.5.78}/pyproject.toml +1 -1
  3. {brainlayer-1.5.76 → brainlayer-1.5.78}/server.json +2 -2
  4. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/__init__.py +1 -1
  5. brainlayer-1.5.78/src/brainlayer/_build.py +1 -0
  6. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/backup_daily.py +135 -20
  7. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/health_check.py +18 -17
  8. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/maintenance_calendar.py +374 -72
  9. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/observability_backup.py +29 -0
  10. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/service_supervisor.py +46 -4
  11. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/supervisor_adapters.py +81 -4
  12. brainlayer-1.5.78/src/brainlayer/supervisor_diagnostics.py +121 -0
  13. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/supervisor_guard.py +70 -10
  14. brainlayer-1.5.76/src/brainlayer/_build.py +0 -1
  15. {brainlayer-1.5.76 → brainlayer-1.5.78}/.gitignore +0 -0
  16. {brainlayer-1.5.76 → brainlayer-1.5.78}/LICENSE +0 -0
  17. {brainlayer-1.5.76 → brainlayer-1.5.78}/README.md +0 -0
  18. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/hotlane_brainbar_daemon.py +0 -0
  19. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/backup-daily.sh +0 -0
  20. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/brainlayer-env-run.sh +0 -0
  21. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/brainlayer.env.example +0 -0
  22. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.backup-daily.plist +0 -0
  23. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.daemon.plist +0 -0
  24. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.decay.plist +0 -0
  25. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.drain.plist +0 -0
  26. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.health-check.plist +0 -0
  27. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.hotlane-brainbar.plist +0 -0
  28. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.index.plist +0 -0
  29. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.jsonl-backup.plist +0 -0
  30. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.log-cap.plist +0 -0
  31. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.maintenance-nightly.plist +0 -0
  32. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.maintenance-weekly.plist +0 -0
  33. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.maintenance.plist +0 -0
  34. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.observability.plist +0 -0
  35. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.p0-counter.plist +0 -0
  36. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.repair-fts.plist +0 -0
  37. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.t3-ingest.plist +0 -0
  38. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.throughput-watchdog.plist +0 -0
  39. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.tier0-watchdog.plist +0 -0
  40. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.wal-checkpoint.plist +0 -0
  41. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.brainlayer.watch.plist +0 -0
  42. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/com.etanhey.brainlayer-fleet-watchdog.plist +0 -0
  43. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/fleet-watchdog.sh +0 -0
  44. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/install.sh +0 -0
  45. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/jsonl-backup.sh +0 -0
  46. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/launchd/throughput-watchdog.py +0 -0
  47. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/release-verify-signatures.sh +0 -0
  48. {brainlayer-1.5.76 → brainlayer-1.5.78}/scripts/tier0-watchdog.sh +0 -0
  49. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/__main__.py +0 -0
  50. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/_helpers.py +0 -0
  51. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/agent_profiles.py +0 -0
  52. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/agent_provenance.py +0 -0
  53. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/alarm.py +0 -0
  54. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/archive_collapse.py +0 -0
  55. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/archive_lifecycle.py +0 -0
  56. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/backup_retention_invariant.py +0 -0
  57. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/badge_state.py +0 -0
  58. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/bitemporal.py +0 -0
  59. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/brainbar_activation.py +0 -0
  60. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/brainbar_auto_activation.py +0 -0
  61. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/brainbar_hybrid_helper.py +0 -0
  62. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/brainbar_identity.py +0 -0
  63. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cachedelete_purge.swift +0 -0
  64. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/calibrate.py +0 -0
  65. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/chunk_origin.py +0 -0
  66. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/chunk_origin_backfill.py +0 -0
  67. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/chunk_origin_wipe.py +0 -0
  68. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/chunk_write.py +0 -0
  69. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/classify.py +0 -0
  70. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/claude_paths.py +0 -0
  71. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cli/__init__.py +0 -0
  72. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cli/wizard.py +0 -0
  73. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cli_jobs.py +0 -0
  74. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cli_new.py +0 -0
  75. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/cloud_backfill.py +0 -0
  76. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/clustering.py +0 -0
  77. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/component_jobs.py +0 -0
  78. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/config.py +0 -0
  79. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/consolidation_plan.py +0 -0
  80. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/content_class.py +0 -0
  81. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/correction_judge.py +0 -0
  82. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/data/agents_registry.yaml +0 -0
  83. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/data/sandbox_seeds/skill-eval-baseline.json +0 -0
  84. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/db_shrink.py +0 -0
  85. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/decay.py +0 -0
  86. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/decay_backfill.py +0 -0
  87. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/decay_job.py +0 -0
  88. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/dedupe.py +0 -0
  89. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/dedupe_merge.py +0 -0
  90. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/deploy_drift.py +0 -0
  91. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/disk_space.py +0 -0
  92. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/doctor.py +0 -0
  93. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/drain.py +0 -0
  94. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/drain_liveness.py +0 -0
  95. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/drive_credentials.py +0 -0
  96. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/embeddings.py +0 -0
  97. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/engine.py +0 -0
  98. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/enrichment_replay.py +0 -0
  99. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/__init__.py +0 -0
  100. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/abcde_enrich_runner.py +0 -0
  101. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/abcde_variants.py +0 -0
  102. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/abcde_variants.yaml +0 -0
  103. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/benchmark.py +0 -0
  104. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/enrichment_gold.py +0 -0
  105. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/enrichment_graders.py +0 -0
  106. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/enrichment_judge.py +0 -0
  107. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/enrichment_llm_judge.py +0 -0
  108. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/enrichment_quality_benchmark.py +0 -0
  109. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/experiment_store.py +0 -0
  110. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/fixtures/README.md +0 -0
  111. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/labeling/enrichment-labeler.html +0 -0
  112. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/__init__.py +0 -0
  113. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/__main__.py +0 -0
  114. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/baseline_store.py +0 -0
  115. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/cli.py +0 -0
  116. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/models.py +0 -0
  117. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/phoenix_client.py +0 -0
  118. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/regression_gate.py +0 -0
  119. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/phoenix_gate/triggers.py +0 -0
  120. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/eval/pilot_artifact_report.py +0 -0
  121. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/fallback_replay.py +0 -0
  122. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/git_learning.py +0 -0
  123. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/hook_python.py +0 -0
  124. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/hooks/__init__.py +0 -0
  125. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/hooks/indexer.py +0 -0
  126. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/import_sweep.py +0 -0
  127. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/index_admission.py +0 -0
  128. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/index_budget.py +0 -0
  129. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/index_completeness.py +0 -0
  130. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/index_new.py +0 -0
  131. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/index_watchdog.py +0 -0
  132. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/ingest/__init__.py +0 -0
  133. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/ingest/codex.py +0 -0
  134. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/ingest/t3.py +0 -0
  135. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/ingest_denylist.py +0 -0
  136. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/ingest_guard.py +0 -0
  137. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/isolation_proof.py +0 -0
  138. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/job_alerts.py +0 -0
  139. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/job_lifecycle_health.py +0 -0
  140. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/jobs.py +0 -0
  141. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/jsonl_backup.py +0 -0
  142. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg/__init__.py +0 -0
  143. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_cleanup.py +0 -0
  144. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_judge.py +0 -0
  145. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_promotion.py +0 -0
  146. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_repo.py +0 -0
  147. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_review_session.py +0 -0
  148. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_session_finish.py +0 -0
  149. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/kg_session_harvest.py +0 -0
  150. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/launchd_consolidation.py +0 -0
  151. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/launchd_install.py +0 -0
  152. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/launchd_primitive.py +0 -0
  153. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/launchd_revert.py +0 -0
  154. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/lexical_defense.py +0 -0
  155. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/lexical_defense_dictionary.json +0 -0
  156. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/log_cap.py +0 -0
  157. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/maintenance.py +0 -0
  158. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/maintenance_control.py +0 -0
  159. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/__init__.py +0 -0
  160. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/_format.py +0 -0
  161. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/_shared.py +0 -0
  162. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/enrich_handler.py +0 -0
  163. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/entity_handler.py +0 -0
  164. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/palette.py +0 -0
  165. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/search_handler.py +0 -0
  166. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/store_handler.py +0 -0
  167. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp/tags_handler.py +0 -0
  168. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp_socket_config.py +0 -0
  169. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/mcp_stdio_bridge.py +0 -0
  170. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/memory_types.py +0 -0
  171. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/migrate.py +0 -0
  172. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/migration_custody.py +0 -0
  173. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/migration_journal.py +0 -0
  174. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/migration_runtime.py +0 -0
  175. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/notification_policy.py +0 -0
  176. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/observability_surface.py +0 -0
  177. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/observability_transport.py +0 -0
  178. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/p0_longitudinal_count.py +0 -0
  179. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/parent_death.py +0 -0
  180. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/paths.py +0 -0
  181. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pause.py +0 -0
  182. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/phonetic.py +0 -0
  183. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/__init__.py +0 -0
  184. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/agent_enrichment.py +0 -0
  185. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/analyze_communication.py +0 -0
  186. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/batch_extraction.py +0 -0
  187. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/brain_graph.py +0 -0
  188. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/chat_tags.py +0 -0
  189. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/chunk.py +0 -0
  190. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/classify.py +0 -0
  191. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/cloud_scrub.py +0 -0
  192. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/cluster_sampling.py +0 -0
  193. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/code_intelligence.py +0 -0
  194. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/correction_detection.py +0 -0
  195. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/correction_mining.py +0 -0
  196. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/digest.py +0 -0
  197. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/enrichment_prompts.py +0 -0
  198. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/enrichment_results.py +0 -0
  199. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/enrichment_tiers.py +0 -0
  200. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/entity_extraction.py +0 -0
  201. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/entity_resolution.py +0 -0
  202. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/extract.py +0 -0
  203. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/extract_claude_desktop.py +0 -0
  204. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/extract_corrections.py +0 -0
  205. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/extract_markdown.py +0 -0
  206. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/extract_whatsapp.py +0 -0
  207. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/frustration_mining.py +0 -0
  208. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/git_overlay.py +0 -0
  209. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/kg_extraction.py +0 -0
  210. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/kg_extraction_groq.py +0 -0
  211. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/longitudinal_analyzer.py +0 -0
  212. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/obsidian_export.py +0 -0
  213. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/operation_grouping.py +0 -0
  214. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/plan_linking.py +0 -0
  215. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/rate_limiter.py +0 -0
  216. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/relation_backfill.py +0 -0
  217. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/relation_verification.py +0 -0
  218. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/sanitize.py +0 -0
  219. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/secret_scrub.py +0 -0
  220. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/semantic_style.py +0 -0
  221. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/sentiment.py +0 -0
  222. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/session_history.py +0 -0
  223. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/style_embed.py +0 -0
  224. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/style_index.py +0 -0
  225. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/tag_entity_promotion.py +0 -0
  226. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/temporal_chains.py +0 -0
  227. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/time_batcher.py +0 -0
  228. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/unified_timeline.py +0 -0
  229. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/pipeline/write_queue.py +0 -0
  230. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/provenance.py +0 -0
  231. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/provenance_autosupersede.py +0 -0
  232. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/provenance_integration.py +0 -0
  233. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/queue_io.py +0 -0
  234. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/queue_merge.py +0 -0
  235. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/reembed_backfill.py +0 -0
  236. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/retired_services.py +0 -0
  237. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/runtime_store.py +0 -0
  238. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/sandbox_db.py +0 -0
  239. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/scoping.py +0 -0
  240. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/scrub_at_rest.py +0 -0
  241. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/search_fanout.py +0 -0
  242. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/search_profile.py +0 -0
  243. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/search_repo.py +0 -0
  244. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/session_repo.py +0 -0
  245. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/setup.py +0 -0
  246. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/socket_hygiene.py +0 -0
  247. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/source_class_migration.py +0 -0
  248. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/spotlight.py +0 -0
  249. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/storage.py +0 -0
  250. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/store.py +0 -0
  251. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/supervisor_child.py +0 -0
  252. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/supervisor_jobs.py +0 -0
  253. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/system_prompt_guard.py +0 -0
  254. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/t3_linkage_alarm.py +0 -0
  255. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/t3_provenance.py +0 -0
  256. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/t3_sources.py +0 -0
  257. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/tag_normalization.py +0 -0
  258. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/taxonomy.json +0 -0
  259. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/telemetry.py +0 -0
  260. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/timestamp_iso.py +0 -0
  261. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/types.py +0 -0
  262. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/vector_store.py +0 -0
  263. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/wal_checkpoint.py +0 -0
  264. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/watcher.py +0 -0
  265. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/watcher_bridge.py +0 -0
  266. {brainlayer-1.5.76 → brainlayer-1.5.78}/src/brainlayer/writer_telemetry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: brainlayer
3
- Version: 1.5.76
3
+ Version: 1.5.78
4
4
  Summary: Persistent local memory for AI agents — 16 BrainBar MCP tools, semantic search, knowledge graph, SQLite
5
5
  Project-URL: Homepage, https://brainlayer.etanheyman.com
6
6
  Project-URL: Repository, https://github.com/EtanHey/brainlayer
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "brainlayer"
3
- version = "1.5.76"
3
+ version = "1.5.78"
4
4
  description = "Persistent local memory for AI agents — 16 BrainBar MCP tools, semantic search, knowledge graph, SQLite"
5
5
  license = {text = "Apache-2.0"}
6
6
  readme = "README.md"
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.etanhey/brainlayer",
4
4
  "title": "BrainLayer",
5
5
  "description": "Persistent local memory for AI agents \u2014 semantic search, knowledge graph, and 16 BrainBar MCP tools with ToolAnnotations over SQLite.",
6
- "version": "1.5.76",
6
+ "version": "1.5.78",
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.5.76",
17
+ "version": "1.5.78",
18
18
  "runtimeHint": "pipx",
19
19
  "transport": {
20
20
  "type": "stdio"
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "1.5.76"
5
+ __version__ = "1.5.78"
6
6
  # Git sha the distributed package was built from; stamped by the release build, None in a source tree.
7
7
  # scripts/sprint_gate.py reads it in "keg" mode to prove the served package is the code under test.
8
8
  # No runtime `str | None` annotation: launchd/install.sh imports this under /usr/bin/python3 (3.9).
@@ -0,0 +1 @@
1
+ BUILD_SHA = "67a98f996619eb35ed4358610757936f5c5ef583"
@@ -2763,6 +2763,8 @@ def _verified_drive_file_ids(log_path: Path) -> set[str] | None:
2763
2763
  return None
2764
2764
  latest: dict[str, Mapping[str, Any]] = {}
2765
2765
  for receipt in receipts:
2766
+ if receipt.get("event") == "local_sweep":
2767
+ continue
2766
2768
  drive_file = receipt.get("drive_file")
2767
2769
  file_id = drive_file.get("id") if isinstance(drive_file, dict) else None
2768
2770
  if isinstance(file_id, str) and file_id:
@@ -2876,17 +2878,116 @@ def _recent_local_verified_backup(
2876
2878
  return None
2877
2879
 
2878
2880
 
2879
- def _protected_snapshot_names(staging_dir: Path) -> set[str]:
2881
+ def _weekly_pin_protection(staging_dir: Path) -> tuple[set[str], str | None]:
2882
+ """No snapshot-bound completion receipt exists; weekly custody expires the next day."""
2880
2883
  pin = staging_dir / ".weekly-backup-pin.json"
2881
2884
  try:
2882
2885
  payload = json.loads(pin.read_text())
2883
- if payload["date"] == local_backup_date().isoformat():
2884
- return {Path(payload["snapshot"]).name}
2886
+ if dt.date.fromisoformat(payload["date"]) == local_backup_date():
2887
+ return {Path(payload["snapshot"]).name}, "weekly_pin_pending"
2885
2888
  except FileNotFoundError:
2886
2889
  pass
2887
2890
  except (OSError, ValueError, KeyError, TypeError):
2888
- return {p.name for p in staging_dir.iterdir() if _snapshot_suffix(p.name)} # unreadable custody fails closed
2889
- return set()
2891
+ return {
2892
+ p.name for p in staging_dir.iterdir() if _parse_snapshot_date(p.name) == local_backup_date()
2893
+ }, "pin_unreadable"
2894
+ return set(), None
2895
+
2896
+
2897
+ def _protected_snapshot_names(staging_dir: Path) -> set[str]:
2898
+ return _weekly_pin_protection(staging_dir)[0]
2899
+
2900
+
2901
+ def _archive_drive_md5_matches(receipt: Mapping[str, Any]) -> bool:
2902
+ """Local deletion needs both recorded checksums, including Drive's stored-byte MD5."""
2903
+ drive = receipt.get("drive_file")
2904
+ local_md5 = receipt.get("local_md5")
2905
+ return (
2906
+ isinstance(local_md5, str)
2907
+ and bool(local_md5)
2908
+ and isinstance(drive, dict)
2909
+ and drive.get("md5Checksum") == local_md5
2910
+ )
2911
+
2912
+
2913
+ def _sweep_verified_local_archives(
2914
+ log_path: Path, staging_dir: Path, context: Mapping[str, Any], *, remove_local: bool
2915
+ ) -> list[str]:
2916
+ """Remove older archives only with latest, matching Drive proof, under the job's lock."""
2917
+ if not log_path.exists():
2918
+ return []
2919
+ try:
2920
+ receipts = _read_backup_receipts(log_path, strict=True)
2921
+ except (OSError, ValueError):
2922
+ print("Cannot validate Drive receipts; retaining local archives", flush=True)
2923
+ return []
2924
+ latest = {
2925
+ r["snapshot"]: r for r in receipts if r.get("event") != "local_sweep" and isinstance(r.get("snapshot"), str)
2926
+ }
2927
+ last_sweep = {
2928
+ r["archive"]: r for r in receipts if r.get("event") == "local_sweep" and isinstance(r.get("archive"), str)
2929
+ }
2930
+ verified_ids = _verified_drive_file_ids(log_path) or set()
2931
+ protected, pin_reason = _weekly_pin_protection(staging_dir)
2932
+ removed = []
2933
+ for receipt in latest.values():
2934
+ path = Path(receipt["snapshot"])
2935
+ day = _parse_snapshot_date(path.name)
2936
+ if (
2937
+ receipt.get("db") != context.get("db")
2938
+ or path.parent.resolve() != staging_dir.resolve()
2939
+ or day is None
2940
+ or path.name != f"{day.isoformat()}{_snapshot_suffix(path.name)}"
2941
+ or day >= local_backup_date()
2942
+ or path.is_symlink()
2943
+ or not path.is_file()
2944
+ or path.resolve() == Path(context["db"]).resolve()
2945
+ ):
2946
+ continue
2947
+ drive = receipt.get("drive_file")
2948
+ verified = (
2949
+ receipt.get("uploaded") is True
2950
+ and receipt.get("verified") is True
2951
+ and isinstance(drive, dict)
2952
+ and isinstance(drive.get("id"), str)
2953
+ and drive.get("id") in verified_ids
2954
+ and drive.get("name") == path.name
2955
+ and str(drive.get("size")) == str(path.stat().st_size)
2956
+ )
2957
+ reason = (
2958
+ "not_verified"
2959
+ if not verified
2960
+ else "md5_unverified"
2961
+ if not _archive_drive_md5_matches(receipt)
2962
+ else "opt_out"
2963
+ if not remove_local
2964
+ else pin_reason
2965
+ if path.name in protected
2966
+ else None
2967
+ )
2968
+ if reason is None:
2969
+ try:
2970
+ if _md5_file(path) != drive["md5Checksum"]:
2971
+ reason = "md5_current_mismatch"
2972
+ else:
2973
+ path.unlink()
2974
+ except OSError as exc:
2975
+ print(f"Cannot delete local archive {path}: {exc}", flush=True)
2976
+ reason = "delete_failed"
2977
+ else:
2978
+ if reason is None:
2979
+ removed.append(path.name)
2980
+ # Local housekeeping cannot grant/revoke Drive verification or refresh last-backup status.
2981
+ update = {
2982
+ "event": "local_sweep",
2983
+ "archive": str(path),
2984
+ "at": dt.datetime.now(dt.UTC).isoformat(),
2985
+ "local_removed": reason is None,
2986
+ "local_removed_skip_reason": reason,
2987
+ }
2988
+ if reason is None or last_sweep.get(str(path), {}).get("local_removed_skip_reason") != reason:
2989
+ _append_json_log(log_path, update)
2990
+ return removed
2890
2991
 
2891
2992
 
2892
2993
  def _reclaim_superseded_local(log_path: Path, result: dict[str, Any], staging_dir: Path) -> None:
@@ -3191,6 +3292,7 @@ def run_backup(
3191
3292
  "db": str(resolved_db_path),
3192
3293
  "uploaded": False,
3193
3294
  "local_removed": False,
3295
+ "local_removed_skip_reason": "not_verified",
3194
3296
  "verified": False,
3195
3297
  "backup_log_provenance": _backup_log_provenance(),
3196
3298
  "attempt_reclamation": "unknown",
@@ -3232,6 +3334,9 @@ def run_backup(
3232
3334
  "machine_id": resolved_machine_id,
3233
3335
  }
3234
3336
  )
3337
+ result["local_gzip_retention_deleted"] = _sweep_verified_local_archives(
3338
+ resolved_log_path, Path(staging_dir), result, remove_local=remove_local_after_upload
3339
+ )
3235
3340
  result["consumed_raw_crash_leftovers_deleted"] = _cleanup_consumed_raw_remnants(Path(staging_dir))
3236
3341
  if resolved_log_path.exists():
3237
3342
  try:
@@ -3533,6 +3638,16 @@ def run_backup(
3533
3638
  )
3534
3639
  result["upload_state"] = "verified" if result["verified"] else "failed"
3535
3640
  if result["verified"]:
3641
+ protected, pin_reason = _weekly_pin_protection(snapshot.parent)
3642
+ result["local_removed_skip_reason"] = (
3643
+ "md5_unverified"
3644
+ if not _archive_drive_md5_matches(result)
3645
+ else "opt_out"
3646
+ if not remove_local_after_upload
3647
+ else pin_reason
3648
+ if snapshot.name in protected
3649
+ else None
3650
+ )
3536
3651
  _append_json_log(resolved_log_path, result) # remote proof precedes reclamation
3537
3652
  _reclaim_superseded_local(resolved_log_path, result, snapshot.parent)
3538
3653
  from . import job_alerts
@@ -3543,23 +3658,16 @@ def run_backup(
3543
3658
  result["temp_dirs_removed_after_verification"] = _prune_owned_temps_after_verified(
3544
3659
  snapshot.parent, snapshot
3545
3660
  )
3546
- if remove_local_after_upload and snapshot.name not in _protected_snapshot_names(snapshot.parent):
3547
- snapshot.unlink()
3548
- result["local_removed"] = True
3661
+ if result["local_removed_skip_reason"] is None:
3662
+ try:
3663
+ snapshot.unlink()
3664
+ except OSError as exc:
3665
+ print(f"Cannot delete local archive {snapshot}: {exc}", flush=True)
3666
+ result["local_removed_skip_reason"] = "delete_failed"
3667
+ else:
3668
+ result["local_removed"] = True
3549
3669
  if resume is None:
3550
3670
  _remove_superseded_stalls(stalled, result, snapshot.name[:10])
3551
- verified_drive_names = _verified_snapshot_names_from_log(
3552
- resolved_log_path, db_path=Path(resolved_db_path)
3553
- )
3554
- verified_drive_names.add(snapshot.name)
3555
- result["local_gzip_retention_deleted"] = prune_local_compressed_snapshots(
3556
- snapshot.parent,
3557
- verified_drive_names=verified_drive_names,
3558
- protected_names=_protected_snapshot_names(snapshot.parent)
3559
- | {
3560
- name for name in _compressed_snapshot_names(snapshot.parent) if name not in verified_drive_names
3561
- },
3562
- )
3563
3671
  if retention_enabled:
3564
3672
  try:
3565
3673
  result["retention_deleted"] = prune_drive_backups(
@@ -3620,6 +3728,13 @@ def run_backup(
3620
3728
  result.setdefault("error_code", "drive_upload_interrupted")
3621
3729
  if not nothing_pending:
3622
3730
  _append_json_log(resolved_log_path, result)
3731
+ swept = _sweep_verified_local_archives(
3732
+ resolved_log_path, Path(staging_dir), result, remove_local=remove_local_after_upload
3733
+ )
3734
+ if swept:
3735
+ result["local_gzip_retention_deleted"].extend(swept)
3736
+ if not nothing_pending:
3737
+ _append_json_log(resolved_log_path, result)
3623
3738
  return result
3624
3739
 
3625
3740
 
@@ -1415,23 +1415,24 @@ def _run_health_check_locked(
1415
1415
  }
1416
1416
  )
1417
1417
 
1418
- if config.heal:
1419
- from .supervisor_adapters import adapt_commands
1420
-
1421
- command_runner = adapt_commands(
1422
- command_runner,
1423
- config.pause_sentinel_path,
1424
- required=(
1425
- config.watch_label,
1426
- config.drain_label,
1427
- config.hotlane_label,
1428
- config.health_check_label,
1429
- config.observability_label,
1430
- ),
1431
- tolerate_unavailable=True,
1432
- )
1433
- if error := getattr(command_runner, "control_error", ""):
1434
- add_issue("supervisor_control_unavailable", "critical", f"supervisor control unavailable: {error}")
1418
+ from .supervisor_adapters import adapt_commands
1419
+
1420
+ command_runner = adapt_commands(
1421
+ command_runner,
1422
+ config.pause_sentinel_path,
1423
+ required=(
1424
+ config.watch_label,
1425
+ config.drain_label,
1426
+ config.hotlane_label,
1427
+ config.health_check_label,
1428
+ config.observability_label,
1429
+ ),
1430
+ tolerate_unavailable=True,
1431
+ discover_ownership=True,
1432
+ )
1433
+ if error := getattr(command_runner, "control_error", ""):
1434
+ add_issue("supervisor_control_unavailable", "critical", f"supervisor control unavailable: {error}")
1435
+ if config.heal:
1435
1436
  result.actions.append("heal_failed:supervisor_control_unavailable")
1436
1437
 
1437
1438
  if state.get("_state_corrupt_now"):