membrane-seat 0.3.1__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 (319) hide show
  1. membrane_seat-0.3.1/LICENSE +51 -0
  2. membrane_seat-0.3.1/PKG-INFO +530 -0
  3. membrane_seat-0.3.1/README.md +512 -0
  4. membrane_seat-0.3.1/membrane/PressStart2P.woff2 +0 -0
  5. membrane_seat-0.3.1/membrane/VT323.woff2 +0 -0
  6. membrane_seat-0.3.1/membrane/__init__.py +10 -0
  7. membrane_seat-0.3.1/membrane/absorb.py +652 -0
  8. membrane_seat-0.3.1/membrane/active_models.py +203 -0
  9. membrane_seat-0.3.1/membrane/acts.py +95 -0
  10. membrane_seat-0.3.1/membrane/ann.py +109 -0
  11. membrane_seat-0.3.1/membrane/assets.py +81 -0
  12. membrane_seat-0.3.1/membrane/attention.py +199 -0
  13. membrane_seat-0.3.1/membrane/auth.py +236 -0
  14. membrane_seat-0.3.1/membrane/autonode.py +619 -0
  15. membrane_seat-0.3.1/membrane/backfill.py +175 -0
  16. membrane_seat-0.3.1/membrane/binding.py +200 -0
  17. membrane_seat-0.3.1/membrane/capture.py +206 -0
  18. membrane_seat-0.3.1/membrane/cblite.py +401 -0
  19. membrane_seat-0.3.1/membrane/cblstore.py +572 -0
  20. membrane_seat-0.3.1/membrane/claims.py +430 -0
  21. membrane_seat-0.3.1/membrane/classes.py +136 -0
  22. membrane_seat-0.3.1/membrane/cli.py +605 -0
  23. membrane_seat-0.3.1/membrane/code_evidence.py +113 -0
  24. membrane_seat-0.3.1/membrane/codegraph.py +572 -0
  25. membrane_seat-0.3.1/membrane/codegraph_lane.py +39 -0
  26. membrane_seat-0.3.1/membrane/consequences.py +352 -0
  27. membrane_seat-0.3.1/membrane/consolidate.py +318 -0
  28. membrane_seat-0.3.1/membrane/dreamer.py +350 -0
  29. membrane_seat-0.3.1/membrane/efgate.py +277 -0
  30. membrane_seat-0.3.1/membrane/efield.py +1643 -0
  31. membrane_seat-0.3.1/membrane/efmind.py +225 -0
  32. membrane_seat-0.3.1/membrane/efstore.py +1296 -0
  33. membrane_seat-0.3.1/membrane/eids.py +374 -0
  34. membrane_seat-0.3.1/membrane/embed.py +145 -0
  35. membrane_seat-0.3.1/membrane/entities.py +3034 -0
  36. membrane_seat-0.3.1/membrane/entity_block.py +589 -0
  37. membrane_seat-0.3.1/membrane/entity_query.py +231 -0
  38. membrane_seat-0.3.1/membrane/fidelity.py +133 -0
  39. membrane_seat-0.3.1/membrane/field3d.py +355 -0
  40. membrane_seat-0.3.1/membrane/fieldmap.py +226 -0
  41. membrane_seat-0.3.1/membrane/fieldpulse.py +295 -0
  42. membrane_seat-0.3.1/membrane/file_lane.py +83 -0
  43. membrane_seat-0.3.1/membrane/fn_schema.py +89 -0
  44. membrane_seat-0.3.1/membrane/frame.py +150 -0
  45. membrane_seat-0.3.1/membrane/generator.py +175 -0
  46. membrane_seat-0.3.1/membrane/global_field.py +188 -0
  47. membrane_seat-0.3.1/membrane/ha_bridge.py +151 -0
  48. membrane_seat-0.3.1/membrane/ingest.py +231 -0
  49. membrane_seat-0.3.1/membrane/intent.py +557 -0
  50. membrane_seat-0.3.1/membrane/jobs.py +241 -0
  51. membrane_seat-0.3.1/membrane/jsexec.py +169 -0
  52. membrane_seat-0.3.1/membrane/lanes.py +7175 -0
  53. membrane_seat-0.3.1/membrane/ledger.py +142 -0
  54. membrane_seat-0.3.1/membrane/llm.py +481 -0
  55. membrane_seat-0.3.1/membrane/massage.py +121 -0
  56. membrane_seat-0.3.1/membrane/mcp_server.py +1669 -0
  57. membrane_seat-0.3.1/membrane/minds_models.py +85 -0
  58. membrane_seat-0.3.1/membrane/move.py +162 -0
  59. membrane_seat-0.3.1/membrane/naming.py +219 -0
  60. membrane_seat-0.3.1/membrane/night.py +4010 -0
  61. membrane_seat-0.3.1/membrane/offline.py +238 -0
  62. membrane_seat-0.3.1/membrane/opencode.py +2227 -0
  63. membrane_seat-0.3.1/membrane/outcomes.py +351 -0
  64. membrane_seat-0.3.1/membrane/peers.py +761 -0
  65. membrane_seat-0.3.1/membrane/predict.py +566 -0
  66. membrane_seat-0.3.1/membrane/project_env.py +214 -0
  67. membrane_seat-0.3.1/membrane/rag.py +295 -0
  68. membrane_seat-0.3.1/membrane/reembed.py +59 -0
  69. membrane_seat-0.3.1/membrane/relations.py +131 -0
  70. membrane_seat-0.3.1/membrane/render.py +270 -0
  71. membrane_seat-0.3.1/membrane/restarts.py +437 -0
  72. membrane_seat-0.3.1/membrane/review.py +107 -0
  73. membrane_seat-0.3.1/membrane/router.py +1024 -0
  74. membrane_seat-0.3.1/membrane/score.py +251 -0
  75. membrane_seat-0.3.1/membrane/seat.py +125 -0
  76. membrane_seat-0.3.1/membrane/seat_panel.py +277 -0
  77. membrane_seat-0.3.1/membrane/server.py +3423 -0
  78. membrane_seat-0.3.1/membrane/settings.py +66 -0
  79. membrane_seat-0.3.1/membrane/skills/membrane-codegraph/SKILL.md +35 -0
  80. membrane_seat-0.3.1/membrane/skills/membrane-forget-memory/SKILL.md +76 -0
  81. membrane_seat-0.3.1/membrane/skills/membrane-global-field/SKILL.md +44 -0
  82. membrane_seat-0.3.1/membrane/skills/membrane-ingest/SKILL.md +39 -0
  83. membrane_seat-0.3.1/membrane/skills/membrane-query-field/SKILL.md +57 -0
  84. membrane_seat-0.3.1/membrane/skills/membrane-restart/SKILL.md +53 -0
  85. membrane_seat-0.3.1/membrane/skills/membrane-state/SKILL.md +57 -0
  86. membrane_seat-0.3.1/membrane/skills/membrane-write-memory/SKILL.md +109 -0
  87. membrane_seat-0.3.1/membrane/slash.py +168 -0
  88. membrane_seat-0.3.1/membrane/speaker.py +196 -0
  89. membrane_seat-0.3.1/membrane/speakers.py +72 -0
  90. membrane_seat-0.3.1/membrane/strangers.py +381 -0
  91. membrane_seat-0.3.1/membrane/streams.py +327 -0
  92. membrane_seat-0.3.1/membrane/substrate.py +189 -0
  93. membrane_seat-0.3.1/membrane/thinker.py +1063 -0
  94. membrane_seat-0.3.1/membrane/three.min.js +6 -0
  95. membrane_seat-0.3.1/membrane/token_timeline.py +132 -0
  96. membrane_seat-0.3.1/membrane/toolset.py +429 -0
  97. membrane_seat-0.3.1/membrane/ui/favicon.js +44 -0
  98. membrane_seat-0.3.1/membrane/ui/favicon.svg +10 -0
  99. membrane_seat-0.3.1/membrane/ui/field.js +973 -0
  100. membrane_seat-0.3.1/membrane/ui/field3d.js +1086 -0
  101. membrane_seat-0.3.1/membrane/ui/home.js +2008 -0
  102. membrane_seat-0.3.1/membrane/ui/host.js +42 -0
  103. membrane_seat-0.3.1/membrane/ui/index.html +86 -0
  104. membrane_seat-0.3.1/membrane/ui/panel.js +1924 -0
  105. membrane_seat-0.3.1/membrane/ui/three.min.js +6 -0
  106. membrane_seat-0.3.1/membrane/ui/vosk.js +815 -0
  107. membrane_seat-0.3.1/membrane/ui_serve.py +325 -0
  108. membrane_seat-0.3.1/membrane/universe.py +140 -0
  109. membrane_seat-0.3.1/membrane/update.py +292 -0
  110. membrane_seat-0.3.1/membrane/viewer.html +1797 -0
  111. membrane_seat-0.3.1/membrane/voice.py +1547 -0
  112. membrane_seat-0.3.1/membrane/voice_io.py +198 -0
  113. membrane_seat-0.3.1/membrane/vsa.py +367 -0
  114. membrane_seat-0.3.1/membrane/wakes.py +116 -0
  115. membrane_seat-0.3.1/membrane/watch.py +383 -0
  116. membrane_seat-0.3.1/membrane/watch_agents.py +1682 -0
  117. membrane_seat-0.3.1/membrane_seat.egg-info/PKG-INFO +530 -0
  118. membrane_seat-0.3.1/membrane_seat.egg-info/SOURCES.txt +317 -0
  119. membrane_seat-0.3.1/membrane_seat.egg-info/dependency_links.txt +1 -0
  120. membrane_seat-0.3.1/membrane_seat.egg-info/entry_points.txt +2 -0
  121. membrane_seat-0.3.1/membrane_seat.egg-info/requires.txt +7 -0
  122. membrane_seat-0.3.1/membrane_seat.egg-info/top_level.txt +1 -0
  123. membrane_seat-0.3.1/pyproject.toml +46 -0
  124. membrane_seat-0.3.1/setup.cfg +4 -0
  125. membrane_seat-0.3.1/tests/test_absorb.py +742 -0
  126. membrane_seat-0.3.1/tests/test_act_planner.py +102 -0
  127. membrane_seat-0.3.1/tests/test_active_models.py +85 -0
  128. membrane_seat-0.3.1/tests/test_agent_forget.py +136 -0
  129. membrane_seat-0.3.1/tests/test_agent_minds.py +111 -0
  130. membrane_seat-0.3.1/tests/test_agent_writes.py +113 -0
  131. membrane_seat-0.3.1/tests/test_alert_gate.py +148 -0
  132. membrane_seat-0.3.1/tests/test_arg_aliases_2.py +111 -0
  133. membrane_seat-0.3.1/tests/test_assets.py +40 -0
  134. membrane_seat-0.3.1/tests/test_attention.py +216 -0
  135. membrane_seat-0.3.1/tests/test_autonode.py +577 -0
  136. membrane_seat-0.3.1/tests/test_backfill.py +126 -0
  137. membrane_seat-0.3.1/tests/test_banner.py +256 -0
  138. membrane_seat-0.3.1/tests/test_binding.py +79 -0
  139. membrane_seat-0.3.1/tests/test_blocked_wake.py +189 -0
  140. membrane_seat-0.3.1/tests/test_boot_entity.py +74 -0
  141. membrane_seat-0.3.1/tests/test_boot_order.py +39 -0
  142. membrane_seat-0.3.1/tests/test_capture.py +131 -0
  143. membrane_seat-0.3.1/tests/test_cblstore.py +293 -0
  144. membrane_seat-0.3.1/tests/test_claims.py +146 -0
  145. membrane_seat-0.3.1/tests/test_cliffhanger.py +472 -0
  146. membrane_seat-0.3.1/tests/test_cloud_providers.py +318 -0
  147. membrane_seat-0.3.1/tests/test_code_evidence.py +100 -0
  148. membrane_seat-0.3.1/tests/test_command_library.py +107 -0
  149. membrane_seat-0.3.1/tests/test_command_names.py +101 -0
  150. membrane_seat-0.3.1/tests/test_concurrency_dumps.py +202 -0
  151. membrane_seat-0.3.1/tests/test_concurrent_reads.py +175 -0
  152. membrane_seat-0.3.1/tests/test_consequences.py +151 -0
  153. membrane_seat-0.3.1/tests/test_consolidate.py +138 -0
  154. membrane_seat-0.3.1/tests/test_curiosity.py +100 -0
  155. membrane_seat-0.3.1/tests/test_delegate.py +151 -0
  156. membrane_seat-0.3.1/tests/test_doctrine_native.py +81 -0
  157. membrane_seat-0.3.1/tests/test_doctrine_split.py +91 -0
  158. membrane_seat-0.3.1/tests/test_door_visibility.py +184 -0
  159. membrane_seat-0.3.1/tests/test_drain_bounds.py +56 -0
  160. membrane_seat-0.3.1/tests/test_dropped_stream.py +101 -0
  161. membrane_seat-0.3.1/tests/test_durability.py +296 -0
  162. membrane_seat-0.3.1/tests/test_echo_split.py +145 -0
  163. membrane_seat-0.3.1/tests/test_ef_cli.py +75 -0
  164. membrane_seat-0.3.1/tests/test_ef_prereqs.py +149 -0
  165. membrane_seat-0.3.1/tests/test_efgate.py +118 -0
  166. membrane_seat-0.3.1/tests/test_efield.py +272 -0
  167. membrane_seat-0.3.1/tests/test_efmind.py +97 -0
  168. membrane_seat-0.3.1/tests/test_efstore_cb.py +240 -0
  169. membrane_seat-0.3.1/tests/test_efstore_drain.py +53 -0
  170. membrane_seat-0.3.1/tests/test_efstore_file.py +185 -0
  171. membrane_seat-0.3.1/tests/test_efstore_journal.py +143 -0
  172. membrane_seat-0.3.1/tests/test_eids.py +103 -0
  173. membrane_seat-0.3.1/tests/test_embed_cache.py +150 -0
  174. membrane_seat-0.3.1/tests/test_entities.py +317 -0
  175. membrane_seat-0.3.1/tests/test_entity_block.py +235 -0
  176. membrane_seat-0.3.1/tests/test_entity_coll_cache.py +91 -0
  177. membrane_seat-0.3.1/tests/test_entity_link_args.py +91 -0
  178. membrane_seat-0.3.1/tests/test_entity_query.py +142 -0
  179. membrane_seat-0.3.1/tests/test_entity_scripts.py +400 -0
  180. membrane_seat-0.3.1/tests/test_executor_chain.py +330 -0
  181. membrane_seat-0.3.1/tests/test_executor_link.py +373 -0
  182. membrane_seat-0.3.1/tests/test_fidelity.py +60 -0
  183. membrane_seat-0.3.1/tests/test_field3d.py +173 -0
  184. membrane_seat-0.3.1/tests/test_field3d_routes.py +81 -0
  185. membrane_seat-0.3.1/tests/test_field_pulse.py +168 -0
  186. membrane_seat-0.3.1/tests/test_field_watch.py +197 -0
  187. membrane_seat-0.3.1/tests/test_field_wiring.py +208 -0
  188. membrane_seat-0.3.1/tests/test_fieldmap.py +236 -0
  189. membrane_seat-0.3.1/tests/test_frame.py +160 -0
  190. membrane_seat-0.3.1/tests/test_frame_lint.py +150 -0
  191. membrane_seat-0.3.1/tests/test_frame_wait.py +105 -0
  192. membrane_seat-0.3.1/tests/test_freshness.py +77 -0
  193. membrane_seat-0.3.1/tests/test_getter_news.py +67 -0
  194. membrane_seat-0.3.1/tests/test_getter_path.py +106 -0
  195. membrane_seat-0.3.1/tests/test_global_field.py +93 -0
  196. membrane_seat-0.3.1/tests/test_goal_intents.py +206 -0
  197. membrane_seat-0.3.1/tests/test_goal_progress.py +223 -0
  198. membrane_seat-0.3.1/tests/test_ha_bridge.py +74 -0
  199. membrane_seat-0.3.1/tests/test_ha_detached.py +204 -0
  200. membrane_seat-0.3.1/tests/test_ha_supervisor.py +57 -0
  201. membrane_seat-0.3.1/tests/test_heat_gravity.py +185 -0
  202. membrane_seat-0.3.1/tests/test_history_anchor.py +59 -0
  203. membrane_seat-0.3.1/tests/test_idle_cortex_pick.py +95 -0
  204. membrane_seat-0.3.1/tests/test_ingest_codegraph.py +252 -0
  205. membrane_seat-0.3.1/tests/test_inheritance.py +192 -0
  206. membrane_seat-0.3.1/tests/test_init_speak.py +53 -0
  207. membrane_seat-0.3.1/tests/test_injection_card.py +46 -0
  208. membrane_seat-0.3.1/tests/test_intent_lane.py +251 -0
  209. membrane_seat-0.3.1/tests/test_jobs.py +160 -0
  210. membrane_seat-0.3.1/tests/test_jsexec.py +82 -0
  211. membrane_seat-0.3.1/tests/test_lab_isolation.py +37 -0
  212. membrane_seat-0.3.1/tests/test_lan_discovery.py +222 -0
  213. membrane_seat-0.3.1/tests/test_lane_gate.py +1008 -0
  214. membrane_seat-0.3.1/tests/test_lane_truths.py +68 -0
  215. membrane_seat-0.3.1/tests/test_leadin_text.py +78 -0
  216. membrane_seat-0.3.1/tests/test_ledger.py +123 -0
  217. membrane_seat-0.3.1/tests/test_listen_host.py +32 -0
  218. membrane_seat-0.3.1/tests/test_llm_entity.py +147 -0
  219. membrane_seat-0.3.1/tests/test_llm_wake.py +157 -0
  220. membrane_seat-0.3.1/tests/test_loop_lane.py +152 -0
  221. membrane_seat-0.3.1/tests/test_loop_wiring.py +165 -0
  222. membrane_seat-0.3.1/tests/test_massage.py +112 -0
  223. membrane_seat-0.3.1/tests/test_mcp.py +333 -0
  224. membrane_seat-0.3.1/tests/test_mcp_surface.py +54 -0
  225. membrane_seat-0.3.1/tests/test_message_entities.py +239 -0
  226. membrane_seat-0.3.1/tests/test_midturn_messages.py +118 -0
  227. membrane_seat-0.3.1/tests/test_minds_models.py +87 -0
  228. membrane_seat-0.3.1/tests/test_minds_view.py +51 -0
  229. membrane_seat-0.3.1/tests/test_mirror_demint.py +129 -0
  230. membrane_seat-0.3.1/tests/test_model_chat.py +158 -0
  231. membrane_seat-0.3.1/tests/test_name_lint.py +77 -0
  232. membrane_seat-0.3.1/tests/test_naming.py +89 -0
  233. membrane_seat-0.3.1/tests/test_night.py +230 -0
  234. membrane_seat-0.3.1/tests/test_night_mode.py +203 -0
  235. membrane_seat-0.3.1/tests/test_nursery_ghosts.py +85 -0
  236. membrane_seat-0.3.1/tests/test_offline_mode.py +122 -0
  237. membrane_seat-0.3.1/tests/test_one_spelling.py +103 -0
  238. membrane_seat-0.3.1/tests/test_outcomes.py +157 -0
  239. membrane_seat-0.3.1/tests/test_parallel_minds.py +120 -0
  240. membrane_seat-0.3.1/tests/test_patterns.py +97 -0
  241. membrane_seat-0.3.1/tests/test_peer_cursor.py +81 -0
  242. membrane_seat-0.3.1/tests/test_peers_roster.py +100 -0
  243. membrane_seat-0.3.1/tests/test_person_preempts.py +129 -0
  244. membrane_seat-0.3.1/tests/test_phone_lane.py +47 -0
  245. membrane_seat-0.3.1/tests/test_pick_default_model.py +20 -0
  246. membrane_seat-0.3.1/tests/test_port_probe.py +43 -0
  247. membrane_seat-0.3.1/tests/test_predict.py +205 -0
  248. membrane_seat-0.3.1/tests/test_project_env.py +174 -0
  249. membrane_seat-0.3.1/tests/test_prompt_async_parts.py +101 -0
  250. membrane_seat-0.3.1/tests/test_publish.py +283 -0
  251. membrane_seat-0.3.1/tests/test_query_universe.py +130 -0
  252. membrane_seat-0.3.1/tests/test_queue_once.py +97 -0
  253. membrane_seat-0.3.1/tests/test_recall_loopback.py +107 -0
  254. membrane_seat-0.3.1/tests/test_recall_report.py +77 -0
  255. membrane_seat-0.3.1/tests/test_receipt_lane.py +59 -0
  256. membrane_seat-0.3.1/tests/test_relabel_roles.py +99 -0
  257. membrane_seat-0.3.1/tests/test_relations.py +97 -0
  258. membrane_seat-0.3.1/tests/test_restarts.py +133 -0
  259. membrane_seat-0.3.1/tests/test_restarts_ha.py +35 -0
  260. membrane_seat-0.3.1/tests/test_route_health.py +78 -0
  261. membrane_seat-0.3.1/tests/test_route_health_global.py +52 -0
  262. membrane_seat-0.3.1/tests/test_router.py +457 -0
  263. membrane_seat-0.3.1/tests/test_run_lane.py +220 -0
  264. membrane_seat-0.3.1/tests/test_scan_index.py +237 -0
  265. membrane_seat-0.3.1/tests/test_score.py +130 -0
  266. membrane_seat-0.3.1/tests/test_script_budget.py +79 -0
  267. membrane_seat-0.3.1/tests/test_script_covenant.py +222 -0
  268. membrane_seat-0.3.1/tests/test_script_errors.py +186 -0
  269. membrane_seat-0.3.1/tests/test_script_kinds.py +209 -0
  270. membrane_seat-0.3.1/tests/test_seat_card.py +148 -0
  271. membrane_seat-0.3.1/tests/test_seat_panel.py +149 -0
  272. membrane_seat-0.3.1/tests/test_seat_read_bridge.py +121 -0
  273. membrane_seat-0.3.1/tests/test_selection_persists.py +64 -0
  274. membrane_seat-0.3.1/tests/test_serve.py +87 -0
  275. membrane_seat-0.3.1/tests/test_serve_busy.py +174 -0
  276. membrane_seat-0.3.1/tests/test_serve_delivery.py +66 -0
  277. membrane_seat-0.3.1/tests/test_serve_store_merge.py +137 -0
  278. membrane_seat-0.3.1/tests/test_server.py +929 -0
  279. membrane_seat-0.3.1/tests/test_sharing.py +114 -0
  280. membrane_seat-0.3.1/tests/test_side_index.py +145 -0
  281. membrane_seat-0.3.1/tests/test_slash.py +82 -0
  282. membrane_seat-0.3.1/tests/test_speaker_lane.py +132 -0
  283. membrane_seat-0.3.1/tests/test_speakers.py +114 -0
  284. membrane_seat-0.3.1/tests/test_spec_resolve.py +74 -0
  285. membrane_seat-0.3.1/tests/test_speech_footer.py +62 -0
  286. membrane_seat-0.3.1/tests/test_sse_hub.py +45 -0
  287. membrane_seat-0.3.1/tests/test_stop_button.py +92 -0
  288. membrane_seat-0.3.1/tests/test_strangers.py +182 -0
  289. membrane_seat-0.3.1/tests/test_streamed_rounds.py +165 -0
  290. membrane_seat-0.3.1/tests/test_streams.py +142 -0
  291. membrane_seat-0.3.1/tests/test_sweep_batch3.py +123 -0
  292. membrane_seat-0.3.1/tests/test_sweep_batch4.py +106 -0
  293. membrane_seat-0.3.1/tests/test_sweep_batch5.py +60 -0
  294. membrane_seat-0.3.1/tests/test_sweep_fixes.py +191 -0
  295. membrane_seat-0.3.1/tests/test_symbol_recall.py +140 -0
  296. membrane_seat-0.3.1/tests/test_thinker.py +422 -0
  297. membrane_seat-0.3.1/tests/test_thinker_inject.py +41 -0
  298. membrane_seat-0.3.1/tests/test_thinking_indicator.py +166 -0
  299. membrane_seat-0.3.1/tests/test_timeline_layer.py +108 -0
  300. membrane_seat-0.3.1/tests/test_timelines.py +102 -0
  301. membrane_seat-0.3.1/tests/test_tool_arg_aliases.py +136 -0
  302. membrane_seat-0.3.1/tests/test_tool_inversion.py +179 -0
  303. membrane_seat-0.3.1/tests/test_toolset.py +249 -0
  304. membrane_seat-0.3.1/tests/test_tui_attach.py +54 -0
  305. membrane_seat-0.3.1/tests/test_turn_watchdog.py +127 -0
  306. membrane_seat-0.3.1/tests/test_ui_serve.py +152 -0
  307. membrane_seat-0.3.1/tests/test_update.py +109 -0
  308. membrane_seat-0.3.1/tests/test_v1_post_hang.py +171 -0
  309. membrane_seat-0.3.1/tests/test_vec_first_build.py +82 -0
  310. membrane_seat-0.3.1/tests/test_viewer_gate.py +62 -0
  311. membrane_seat-0.3.1/tests/test_voice.py +786 -0
  312. membrane_seat-0.3.1/tests/test_voice_io.py +83 -0
  313. membrane_seat-0.3.1/tests/test_vsa.py +248 -0
  314. membrane_seat-0.3.1/tests/test_vsa_consumers.py +113 -0
  315. membrane_seat-0.3.1/tests/test_wake_ledger.py +145 -0
  316. membrane_seat-0.3.1/tests/test_watch.py +259 -0
  317. membrane_seat-0.3.1/tests/test_watch_agents.py +453 -0
  318. membrane_seat-0.3.1/tests/test_watch_attach.py +151 -0
  319. membrane_seat-0.3.1/tests/test_watch_cost.py +280 -0
@@ -0,0 +1,51 @@
1
+ Membrane Private Use License
2
+ (version 1, 2026-10-13)
3
+
4
+ Copyright (c) 2026 Dmitrii Chechetkin
5
+
6
+ 0. The grant. Permission is granted, without fee, to any person who
7
+ obtains a copy of this software and its documentation ("the software")
8
+ to use, copy, run, and modify the software privately: for themselves,
9
+ for their household, and on their own machines and home systems —
10
+ including a private home-automation install and any seats or machines
11
+ the person runs for their own purposes.
12
+
13
+ 1. What counts as private use. Private use includes personal, household,
14
+ hobby, educational, and research use, and evaluation or internal
15
+ testing within a workplace, so long as the software is not used in
16
+ the operation of a paid or revenue-generating product, service, or
17
+ offering. A home is private use. A paid hosted product built on the
18
+ software is not.
19
+
20
+ 2. What the grant does not include. Without separate written permission
21
+ from the author, you may not:
22
+ - use the software in the operation of any commercial or
23
+ revenue-generating product, service, or offering;
24
+ - charge money (directly or bundled) for the software or for access
25
+ to it;
26
+ - distribute copies of the software — original or modified — or make
27
+ it available to others as a download, bundle, or appliance;
28
+ - offer the software, or a service built on it, to others.
29
+ The author's own distribution of the software is unaffected by this
30
+ section: the copyright holder's own rights are not limited by this
31
+ license.
32
+
33
+ 3. What you keep. You own your modifications. You may run your modified
34
+ copy privately for as long as you like, and you are encouraged to
35
+ send changes, bug reports, and fixes back to the author (issues and
36
+ pull requests in the software's repository).
37
+
38
+ 4. Other rights. The author may grant additional rights — commercial
39
+ use, distribution, embedding — to anyone, case by case. Ask.
40
+
41
+ 5. Notice. Keep this license and the copyright notice with any copy of
42
+ the software, and inside any file where the original notice stood.
43
+
44
+ 6. The usual disclaimers. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
45
+ WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
46
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
47
+ PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR
48
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
49
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
51
+ IN THE SOFTWARE.
@@ -0,0 +1,530 @@
1
+ Metadata-Version: 2.4
2
+ Name: membrane-seat
3
+ Version: 0.3.1
4
+ Summary: Membrane: a local-first memory field and seat for AI -- its own web UI (`membrane standalone`) or inside Home Assistant (HACS).
5
+ Author: Dmitrii Chechetkin
6
+ License-Expression: LicenseRef-Membrane-Private-Use-1.0
7
+ Project-URL: Homepage, https://github.com/chedim/membrane
8
+ Project-URL: Issues, https://github.com/chedim/membrane/issues
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: numpy>=1.26
13
+ Provides-Extra: couchbase
14
+ Requires-Dist: couchbase>=4.6; extra == "couchbase"
15
+ Provides-Extra: mdns
16
+ Requires-Dist: zeroconf; extra == "mdns"
17
+ Dynamic: license-file
18
+
19
+ # membrane
20
+
21
+ ![Membrane](membrane-home.gif)
22
+
23
+ > A **text-based hypervector entity-field hippocampus for opencode** that
24
+ > learns as you go, shares a Couchbase-backed team memory, and **orchestrates
25
+ > LLM calls** between local and cloud inference.
26
+
27
+ A **Python lab**. It runs as a local HTTP server on
28
+ `127.0.0.1` in front of Ollama (or Anthropic) — technically a proxy, but that
29
+ is the mechanism, not the point. The point is the field.
30
+
31
+ > **Why that name?** The project began as one question — *how do you measure
32
+ > "variety" for a memory that decides absorb-a-cached-answer vs
33
+ > escalate-to-the-model?* — and the answer is what makes the memory above
34
+ > possible and is why it is called **membrane**: a selective, *active* boundary
35
+ > between lived memory (the inside) and the incoming world (the outside) that
36
+ > absorbs what it has the variety for and escalates the rest. The full story
37
+ > lives in [The thermodynamic principle](docs/principle.md) and
38
+ > [The math findings](docs/math-findings.md).
39
+
40
+ This README is the **developer workflow** — install, launch, connect a team
41
+ field, and the daily loop. How the entity field works under the hood, how
42
+ sharing works, and the project's history are in the sub-documents (see
43
+ [Documentation map](#documentation-map)).
44
+
45
+ ---
46
+
47
+ ## Quick start
48
+
49
+ Membrane runs two ways. Both need an [Ollama](https://ollama.com) server with one chat model and one
50
+ embedding model (`ollama pull qwen3:8b && ollama pull mxbai-embed-large`, or any cloud model Ollama
51
+ serves), and 1–3 GB of RAM for the seat.
52
+
53
+ ### Standalone: its own web UI
54
+
55
+ ```bash
56
+ pip install membrane-seat # or: uv tool install membrane-seat
57
+ mkdir ~/bob && cd ~/bob
58
+ membrane standalone # opens http://localhost:4096/ in your browser
59
+ ```
60
+
61
+ You get membrane home: the field in 3D, the chat, and voice ("Hey Bob" — a new membrane is Bob
62
+ until you agree on a name together; it will ask). Other devices on your network reach it at
63
+ `http://<this machine>:4096/`. No login on the local network; a public or proxied caller is
64
+ refused. Voice needs a secure origin, so the microphone works on `localhost` (the first voice use
65
+ downloads ~65 MB of speech models, checked against their checksums).
66
+
67
+ ### Inside Home Assistant (HACS)
68
+
69
+ 1. HACS → ⋮ → Custom repositories → `https://github.com/chedim/membrane`, category *Integration*.
70
+ 2. Install **Membrane**, restart Home Assistant.
71
+ 3. Settings → Devices & services → Add integration → **Membrane** → *Inside Home Assistant*.
72
+ If Home Assistant already has the Ollama integration, it is used; otherwise give Ollama's
73
+ address. Pick the models.
74
+
75
+ Home Assistant then runs the seat as its own child process (started and stopped with HA,
76
+ restarted if it dies; its data in `<config>/membrane/`), opens on membrane home for everyone (HA's
77
+ sidebar folds away; ☰ leads to HA's own pages — switch it off in the integration's options), adds
78
+ the seat as an Assist conversation agent, and its field's readings as sensors.
79
+
80
+ **What it can do in your house:** by default the seat may use Home Assistant through a hidden,
81
+ non-admin, local-only user ("Membrane") — read any state, call any service, and mirror the entities
82
+ it chooses (they update live). It acts on what people ask, but its commands are written by a
83
+ model: turn *Let the seat use Home Assistant* off in the integration's options if you'd rather it
84
+ only talks. It can't change Home Assistant's configuration or users.
85
+
86
+ *Connect to a seat running elsewhere* is for a seat on another machine (the integration is then
87
+ only its UI and agent).
88
+
89
+ ### Bugs and ideas
90
+
91
+ [github.com/chedim/membrane/issues](https://github.com/chedim/membrane/issues) — your membrane
92
+ knows this too: when it finds a bug in itself it drafts the issue and hands you the link to file.
93
+
94
+ ---
95
+
96
+ ## Table of contents
97
+
98
+ - [Quick start](#quick-start)
99
+ - [Installation](#installation)
100
+ - [Install the CLI](#install-the-cli-one-line-no-sudo)
101
+ - [First run in a project](#first-run-in-a-project)
102
+ - [Daily workflow](#daily-workflow)
103
+ - [Other surfaces](#other-surfaces)
104
+ - [Claude Code (Anthropic cloud)](#claude-code-anthropic-cloud)
105
+ - [Sharing a team field (Couchbase)](#sharing-a-team-field-couchbase)
106
+ - [`membrane connect` (recommended)](#membrane-connect-recommended)
107
+ - [Manual setup via env](#manual-setup-via-env)
108
+ - [What sharing guarantees](#what-sharing-guarantees)
109
+ - [Checking on the field](#checking-on-the-field)
110
+ - [Documentation map](#documentation-map)
111
+ - [Development](#development)
112
+ - [Run the tests](#run-the-tests)
113
+ - [The variety toy](#the-variety-toy)
114
+ - [Status](#status)
115
+
116
+ ---
117
+
118
+ ## Installation
119
+
120
+ ### Install the CLI (one line, no sudo)
121
+
122
+ ```bash
123
+ curl -fsSL https://raw.githubusercontent.com/chedim/membrane/main/install.sh | bash
124
+ ```
125
+
126
+ Installs the `membrane` CLI globally, user-local (`~/.local/bin`):
127
+ `uv tool install` if you have [uv](https://docs.astral.sh/uv/), otherwise a
128
+ managed venv at `~/.membrane/venv` + a symlink on your PATH. Re-running it is
129
+ safe (upgrade in place). To install from a local checkout instead (e.g. while
130
+ hacking on membrane):
131
+
132
+ ```bash
133
+ MEMBRANE_REPO=/path/to/membrane bash install.sh
134
+ ```
135
+
136
+ Requires Python ≥ 3.10 (numpy is the only import-time dep); embeddings/chat come from a running
137
+ [Ollama](https://ollama.com). Without installing anything, one-off via uvx:
138
+ `uvx --from "membrane @ git+ssh://git@github.com/chedim/membrane" membrane install`.
139
+
140
+ **Dependencies, honestly:**
141
+
142
+ - **Python ≥ 3.10** + **numpy** — the only import-time dep. `couchbase` (the
143
+ shared field) are installed by default (paho-mqtt was removed
144
+ 2026-10-03 — the mqtt event bus is retired; cross-seat transport is
145
+ couch's peer_chat lane)
146
+ (`pip install -r requirements.txt` / the pyproject) but imported lazily;
147
+ either missing degrades that feature, never the boot.
148
+ - **Ollama** (`brew install ollama` / <https://ollama.com>) — NOT auto-installed; embeddings
149
+ and local chat need it running on `:11434`.
150
+ - **Couchbase** — where the field lives for real seats: one bucket per team,
151
+ the `membrane` scope, nine collections (`events`, `sentences`, `terms`,
152
+ `entity_states`, `entity_deltas`, `relations`, `claims`, `annotations`,
153
+ `origin_stats`), created and indexed on first boot (`ensure_infra`). With no
154
+ cluster configured or reachable the seat degrades to a RAM field — it runs,
155
+ and nothing persists across restarts.
156
+ - **[opencode](https://opencode.ai)** — NOT auto-installed either; `membrane opencode`
157
+ launches it if found on PATH (`sh <(curl ... opencode.ai/install.sh)`), otherwise the
158
+ proxy runs bare and you point any OpenAI-compatible client at `http://127.0.0.1:11500/v1`
159
+ (`--no-launch` skips the spawn entirely). The other surfaces (viewer, review,
160
+ ingest, codegraph) need nothing beyond Python.
161
+ - The **viewer** ships inside the package (three.js + both pixel fonts are vendored,
162
+ served same-origin at `/viewer`, opened in your browser on start; `--no-viewer --no-open`
163
+ to disable) — no CDN, no node, no browser install.
164
+
165
+ ### First run in a project
166
+
167
+ ```bash
168
+ cd ~/projects/my-app
169
+ membrane opencode
170
+ ```
171
+
172
+ That's the whole workflow. On first run in a directory it bootstraps that
173
+ project:
174
+
175
+ - auto-installs the eight agent skills (query / learn / forget / state /
176
+ global-field / codegraph / ingest / restart)
177
+ into `.opencode/skills/` there (project-scoped on purpose — an opencode
178
+ launched elsewhere never sees them; skip with `MEMBRANE_NO_AUTOINSTALL=1`),
179
+ - opens an **entity field** for the project, namespaced by its origin
180
+ (a sha1 tag of the project path) — events, entity states, relations,
181
+ claims — all in the shared scope when one is configured,
182
+ - backfills what it can without cost: the codegraph (code events and
183
+ `calls` relations) and, with `membrane backfill`, the project's history,
184
+ - if no memory sharing is configured, offers (once, interactive shell only)
185
+ to connect a Couchbase cluster for this project — decline and it stays a
186
+ private local field (see
187
+ [Sharing a team field](#sharing-a-team-field-couchbase)).
188
+
189
+ It then starts the OpenAI-compatible proxy on `:11500` (backend Ollama at
190
+ `http://localhost:11434`, override `--backend`/`--model`) and opens the
191
+ opencode TUI **attached to membrane's own serve surface** (stage 3.5:
192
+ membrane IS the server — sessions, turns, tool parts and their history live
193
+ in membrane's stores beside the field; the TUI is a thin client). The
194
+ surface's REST/SSE triple is printed at boot and the basic-auth pair lives
195
+ in `.membrane/serve-auth.json`. Every turn is captured into the field
196
+ (discourse and observations as events), entities move as the conversation
197
+ names them, and the model is grounded by what those entities hold —
198
+ [docs/entity-field.md](docs/entity-field.md) is the design doc.
199
+
200
+ ### Daily workflow
201
+
202
+ Inside opencode, the field answers five canonical frames itself —
203
+ **intercepts: no model call, never learned**:
204
+
205
+ membrane: query the field for <topic> read recall
206
+ membrane: learn that <fact> write a memory (a NOTE event)
207
+ membrane: forget #N tombstone event #N and
208
+ recompute what it touched
209
+ field state memory health/stats
210
+ membrane: suggest review scope suggestions for
211
+ the cross-project commons
212
+
213
+ The agent may also emit these frames in its own prose; answers arrive next
214
+ turn as clearly-marked `[membrane-intercept]` blocks. Writes from model prose
215
+ execute by default (`--no-agent-writes` reverts to report-only): a learn runs
216
+ the same guards as any turn and is audited `origin: agent` (tagged
217
+ `agent-note`).
218
+
219
+ Everything else is ambient. Each turn the model sees what the field holds
220
+ about the entities it names (its evidence sentences, the latest observations,
221
+ the code, relations, conflicts) and — on later turns — only the **diff**:
222
+ which entity states moved since the last message it processed, from
223
+ conversation, code, other seats or entity scripts. Two safety lanes run on
224
+ every turn and stay advisory:
225
+
226
+ - **the gate** finds the earlier ask nearest this one and its answer; when it
227
+ is not stale (no newer observation or conflict on the ask's entities), the
228
+ pair is logged as an **A/B** — the replay next to what the model actually
229
+ answered, judged for agreement. `--replay-ab P` serves the replay on a
230
+ fraction P of eligible turns (default 0 = shadow: you are never bypassed);
231
+ - **the [membrane] monologue** in the thinking channel shows the gate verdict,
232
+ field vitals, and the per-turn memory flow. `/monologue` toggles it.
233
+
234
+ Idle background loops run on a LOCAL cortex by default (`--idle-cortex-model`)
235
+ so a stuck background seat can never burn cloud tokens. Token economics and
236
+ routing: [docs/token-economics.md](docs/token-economics.md).
237
+
238
+ ### Other surfaces
239
+
240
+ | Command | What it does |
241
+ |---|---|
242
+ | `membrane opencode` | the daily driver: seat proxy on :11500 + membrane's own serve surface (loopback) with the opencode TUI **attached as a thin client** — sessions, turns and tool parts live in membrane; opencode is display only (`MEMBRANE_TUI_DIRECT=1` restores the old direct-provider lane) |
243
+ | `membrane serve` | the same seat, headless: membrane's OWN opencode-compatible REST/SSE server on :4096 (opencode replaced, no child process) |
244
+ | `membrane backfill` | rebuild the field from history (code first, then the audit log; idempotent, resumable) |
245
+ | `membrane review` | print what the field learned (annotations, replay A/B with `--ab`) |
246
+ | `membrane connect` | (re)run shared-field onboarding for THIS project |
247
+ | `membrane reset` | kill the seat on :11500 (or `--listen`), relaunch `membrane opencode` fresh |
248
+ | `membrane install` | install `.opencode/skills/*` explicitly (+ `.gitignore` entry); prints the AGENTS.md blurb |
249
+ | `membrane auth` | store a cloud API key (anthropic, openrouter, gemini, groq, github, mistral) in `~/.membrane/auth.json` (600) — its models become routable rungs + picker entries |
250
+ | `membrane move` | migrate the field between stores (`--efield`: copy the entity-field collections between clusters) |
251
+ | `membrane migrate` | interactive migration front door: detects where the field lives, asks for the target, runs `move` |
252
+ | `membrane reembed` | move the field to another embedding model (`--efield --embed-model M`: re-embed every live event, re-apply) |
253
+ | `membrane update` | check the install source, show what changed, apply (`git pull --ff-only`) and re-exec |
254
+ | `membrane ingest` | cold start: absorb docs/README into the field (DOC events; a second ingest is a no-op) |
255
+ | `membrane codegraph` | stdlib-AST call graph (stats / impact / callers / callees) |
256
+ | `membrane doctor` | what's installed/running (CLI, skills, Ollama) + the field's vitals |
257
+ | `membrane tui` / `proxy` / `anthropic` / `demo` | RETIRED — print a pointer to `membrane opencode` |
258
+
259
+ `./run.sh` still works in-repo and delegates to the same CLI (bare = opencode;
260
+ `./run.sh restart` = `membrane reset`).
261
+
262
+ `MEMBRANE_EFIELD` selects the field's mode: `on` (the default: capture,
263
+ embed, apply), `shadow` (capture events only — a lab ablation), `off`.
264
+
265
+ ### Standalone and Home Assistant
266
+
267
+ `membrane standalone` is the seat with its own web UI (membrane home, the chat,
268
+ voice) — see [docs/standalone.md](docs/standalone.md). Inside Home Assistant the
269
+ **Membrane** integration (HACS) runs the seat as HA's child process and makes
270
+ membrane home HA's landing page — see [docs/home-assistant.md](docs/home-assistant.md).
271
+
272
+ ### Serving headless (`membrane serve`)
273
+
274
+ `membrane serve` runs the seat with **no TUI and no opencode at all** —
275
+ membrane hosts its OWN opencode-compatible REST/SSE server
276
+ (`membrane/server.py`): sessions, messages, turns, tool parts, aborts, the
277
+ SSE event stream. Any opencode client connects unchanged: the [mobile
278
+ companion app](https://opencode.app/), IDE plugins, a script. The turn
279
+ loop calls the seat's OWN `/v1` on loopback — gate, injection, capture,
280
+ banner and the routing ladder run through the exact code path every other
281
+ client's turn uses, so the serve surface adds no separate memory, and the
282
+ model's membrane tool invocations (the MCP lane, built-ins all off) appear
283
+ to the client as ordinary tool parts riding `message.part.updated`
284
+ (pending → completed), so you can watch what it's doing from the room.
285
+
286
+ The connection triple is printed at boot:
287
+
288
+ serve: http://<lan-ip>:4096 (native serve, basic auth user opencode)
289
+
290
+ - **Auth is basic auth** (opencode's env names, `OPENCODE_SERVER_USERNAME`
291
+ / `OPENCODE_SERVER_PASSWORD`): no/incorrect credentials get `401`, only
292
+ the pair in `.membrane/serve-auth.json` (mode 600, generated once,
293
+ `--serve-pass` / `--serve-user` to override) gets through. Credentials
294
+ survive restarts, so a device's saved connection keeps working.
295
+ - **Sessions and messages persist** beside the field
296
+ (`serve-sessions.json` / `serve-msgs.json`, atomic write-through), so a
297
+ device's history survives a seat restart. `--serve` + `--no-launch` is
298
+ legal now — the surface is a thread, independent of the launch decision.
299
+ - **The TUI is a client too.** Every launch boot starts the serve surface
300
+ (loopback-only unless `--serve`) and opens the opencode TUI **attached**
301
+ to it (`opencode attach`, same basic-auth pair) — so a desktop session
302
+ and a phone session are the same store: membrane's. The TUI's own turn
303
+ loop, tool loop and local session storage are bypassed entirely; the
304
+ attached client only displays what the server publishes. Old lanes:
305
+ `MEMBRANE_TUI_DIRECT=1` (TUI fronting `/v1` directly) and
306
+ `MEMBRANE_LEGACY_SERVE=1` (the `opencode serve` child).
307
+ - **Exposure is WiFi-only for now** (`--serve-host` defaults to `0.0.0.0`,
308
+ the LAN): reach the server only from a network you own. The planned
309
+ route makes the seat's phone (the boat's agDroid HA server) the host —
310
+ the security model (VPN or LAN-only, no public exposure) gets designed
311
+ there.
312
+ - `--serve-port` (default 4096, walks up if busy) and `--listen` (the
313
+ proxy, still never leaves 127.0.0.1) are independent.
314
+ - **The minds are visible.** `/agents` (or `GET /agent`) lists the
315
+ ambient minds as agents: the three thinking-loop workers (`loop-1..3`,
316
+ each one's description carrying its live claim — the entity it is
317
+ processing — and the event queue's depth) plus `thinker` and `dreamer`
318
+ with their real counters (beats/spoken/ticks, waves/committed/gc).
319
+ The list is served fresh every call from the running process — nothing
320
+ cached, nothing faked.
321
+ - **The loop queue is RAM-only and dies with the seat.** Watch events
322
+ waiting for a thinking loop live in memory (no persistence): a seat
323
+ restart drops the pending queue on purpose — stale reactive work
324
+ outliving its justification is a failure mode, and a clean restart is
325
+ the correct response. If you need an event to survive a restart, it
326
+ belongs in the field (`membrane: learn that ...`), not in the queue.
327
+ - The old lane survives as an ablation: `MEMBRANE_LEGACY_SERVE=1` restores
328
+ the previous design (launch an `opencode serve` child). A failed serve
329
+ bind prints loudly and the seat keeps running without the room-facing
330
+ surface — never a dead seat over a surface.
331
+
332
+ ### Claude Code (Anthropic cloud) — RETIRED
333
+
334
+ The old `./run.sh anthropic` / `--anthropic` observer mode (a proxy on
335
+ `:11435` in front of Claude Code) was cut with the proxy — `membrane
336
+ anthropic` now only prints the retirement pointer. The opencode seat is the
337
+ surface; to route Anthropic models through it, `membrane auth` stores the
338
+ key (`~/.membrane/auth.json`, mode 600) and its models become rungs on the
339
+ router's ladder.
340
+
341
+ ---
342
+
343
+ ## Sharing a team field (Couchbase)
344
+
345
+ By default a seat's field is private (RAM, or a local cluster). To make a team
346
+ share one substrate — same project, different machines, one memory — point
347
+ every seat at the same Couchbase bucket: one bucket per **team**, the
348
+ `membrane` scope, the nine entity-field collections; projects distinguish
349
+ themselves by the **origin** axis (a seat writes ONLY rows keyed by its own
350
+ origin — do NOT add per-project buckets, that would defeat cross-seat
351
+ agreement).
352
+
353
+ ### `membrane connect` (recommended)
354
+
355
+ Run in the project directory; answer four prompts:
356
+
357
+ ```bash
358
+ membrane connect
359
+ # conn string [couchbase://127.0.0.1]
360
+ # user [Administrator]
361
+ # password (hidden)
362
+ # bucket [membrane]
363
+ ```
364
+
365
+ The same offer appears automatically on the first `membrane opencode` /
366
+ `membrane reset` in a project that has no store configured (interactive shell
367
+ only; declining is remembered — it becomes a private field, and `membrane
368
+ connect` re-opens the question).
369
+
370
+ **Secrets never touch the repo.** Credentials are stored per-project OUTSIDE
371
+ it, at `~/.membrane/projects/<slug>.env` (mode 600, slug = project path +
372
+ hash), and are exported into the environment at every launch from that
373
+ directory. A `.env` inside the repo would leak on the first `git add .` —
374
+ that failure mode is designed out.
375
+
376
+ Kill switch: `MEMBRANE_NO_ASK=1` silences the launch-time prompt (an explicit
377
+ `membrane connect` still works, as does plain env config).
378
+
379
+ ### Manual setup via env
380
+
381
+ The classic path still works (cortex-experiment's env convention):
382
+
383
+ export MEMBRANE_STORE=couchbase
384
+ export COUCHBASE_CONN_STRING=couchbase://<team-host>
385
+ export COUCHBASE_USER=... COUCHBASE_PASSWORD=... COUCHBASE_BUCKET=membrane
386
+
387
+ A **local** cluster answering at the default endpoint is auto-detected at
388
+ boot — no config needed on a dev box that already runs one. Unreachable
389
+ cluster → transparent fallback to the RAM field (degradation, never failure).
390
+
391
+ ### What sharing guarantees
392
+
393
+ Mechanics that make sharing collision-free (details in
394
+ [docs/multi-dev-field.md](docs/multi-dev-field.md) and
395
+ [docs/entity-field.md](docs/entity-field.md)):
396
+
397
+ - every event, state, relation and claim is **namespaced by origin** (the
398
+ seat-id where it was born); writes only ever touch own keys; foreign
399
+ rows are read-only inputs to **merged reads** — a foreign entity's
400
+ effective state is the seed plus the mass-weighted mean of every seat's
401
+ displacement;
402
+ - two seats that moved the same entity in opposing directions produce a
403
+ **divergence** — surfaced as a cross-seat conflict in both blocks, never
404
+ silently overwritten (nothing is destroyed);
405
+ - a seat's working set includes foreign states near what the session is
406
+ talking about (ANN) plus the **commons**: claims the same way from two or
407
+ more seats (promoted at night; `disputed` when a seat contradicted it);
408
+ - teammates online get **live peer asks** (bounded fan-out, LAN/VPN);
409
+ `peers: N live` at boot.
410
+
411
+ The full team process — day-one setup checklist, the async work loop across
412
+ time zones, the watch layer, operator rules — is
413
+ **[docs/shared-field-workflow.md](docs/shared-field-workflow.md)**.
414
+
415
+ ---
416
+
417
+ ## Checking on the field
418
+
419
+ - `field state` (in opencode) / `membrane state` / `membrane doctor` — the
420
+ field's vitals: mode and backend, live events by stream, entities by tier
421
+ (nursery/live/dormant), geometry (effective rank, free energy, the conflict
422
+ fraction), replay A/B ledger, the last night pass.
423
+ - `membrane review` (`--ab` for the replay pairs) — what the field learned.
424
+ - The MCP `state` tool exposes the same payload to the agent.
425
+
426
+ What the numbers mean and how the field's "thermodynamics" work:
427
+ [docs/principle.md](docs/principle.md) (plain words) and
428
+ [docs/math-findings.md](docs/math-findings.md) (the measured math), with
429
+ [docs/entity-field.md](docs/entity-field.md) connecting both to the code.
430
+
431
+ ## Lifecycle: updates, restarts, compatibility
432
+
433
+ - **Update check at boot.** On `membrane opencode` / `membrane reset`, membrane
434
+ checks its install source (the git checkout it runs from, or the pip/uv
435
+ direct URL it was installed from). If an update exists it prints the
436
+ CHANGELOG (the commits between you and the remote tip) and asks
437
+ `Update membrane now? [y/N]` in the terminal — answering yes pulls
438
+ (`--ff-only`, a dirty tree is refused) and re-execs with the same argv.
439
+ Non-interactive sessions are never interrupted; `membrane update` runs
440
+ the same path manually. Opt out with `MEMBRANE_NO_UPDATE_CHECK=1`.
441
+ A PyPI install (`membrane-seat`) compares itself with PyPI's latest and asks
442
+ the same way (then `pip install --upgrade` and a restart). Inside Home
443
+ Assistant, updates come through HACS (the integration pins its
444
+ `membrane-seat`).
445
+ - **Restart only from the shell.** `./run.sh restart` (= `membrane
446
+ reset`: kills the seat listening on :11500 — or `--listen` — and
447
+ relaunches `membrane opencode`) is the safe procedure — see the
448
+ membrane-restart skill. Membrane
449
+ never restarts itself while running (no file watcher, no self-re-exec);
450
+ a restart loses nothing: the field re-hydrates from its backend
451
+ (`membrane reembed --efield` is the one way a restart CAN change results
452
+ — moving to another embedding model).
453
+ - **Embedding-model moves.** The field's vectors are pinned to a model
454
+ (`terms` seeds are cached per model); `membrane reembed --efield
455
+ --embed-model M` re-embeds every live event and re-applies the log in
456
+ order — the rebuilt field pins equal to a fresh one.
457
+
458
+ ---
459
+
460
+ ## Documentation map
461
+
462
+ | Doc | What's in it |
463
+ |---|---|
464
+ | [docs/standalone.md](docs/standalone.md) | **Standalone mode** (`membrane standalone`): the web UI, the first run and the name, who can reach it, voice, `settings.json`, updates |
465
+ | [docs/home-assistant.md](docs/home-assistant.md) | **Membrane in Home Assistant** (HACS): setup, the UI takeover, the Assist agent and sensors, what the seat may do in the house, options, where its data lives, its life |
466
+ | [docs/entity-field.md](docs/entity-field.md) | **THE FIELD.** Design: events → entities → readers; the update rule and statistics; relations and claims; injection (full block / state diff); the gate + replay A/B; storage, sharing, the background mind; the e17–e25 evidence. **The division of hands** (the operator/listener/plan tool lanes + the remounted intent lane) |
467
+ | [docs/shared-field-workflow.md](docs/shared-field-workflow.md) | **Team field: the process.** Day-one setup, the async loop, watches, operator rules, go-live checklist |
468
+ | [docs/multi-dev-field.md](docs/multi-dev-field.md) | **Team field: the substrate.** The origin axis, disjoint writers / merged reads, divergence conflicts, the commons — what makes multi-seat sharing collision-free |
469
+ | [docs/global-field.md](docs/global-field.md) | The global commons: facts true beyond one repo; operator promotion, consensus, residency |
470
+ | [docs/background-mind.md](docs/background-mind.md) | **The background mind:** thinker + dreamer on events, the NightClock, births/junk/activity on entity stats, entity scripts and tracks, the intent steering wheel, **the pause** (the operator's stable point: what stops, what keeps), kill switches |
471
+ | [docs/vsa-token-lane.md](docs/vsa-token-lane.md) | **Entity keys + relations (the VSA lane).** `eids.py` canonical ids, `entity_key`/`role_key` binding, the relations composites, structure-awareness numbers, consumers, kill switches |
472
+ | [docs/token-economics.md](docs/token-economics.md) | Where the savings come from (intercepts, the replay lane, the state diff) + the router: the ladder, the ceiling, the outage fallback, the free-tier default budget |
473
+ | [docs/monologue.md](docs/monologue.md) | The `[membrane]` thinking-channel banner: every line explained, the memory flow (gave/learned), `/monologue` toggle |
474
+ | [docs/symbol-birth.md](docs/symbol-birth.md) | The symbol crystallization: how the hierarchy is born — symbols come into being through language; the structural membrane mapping, the consequence to keep |
475
+ | [docs/principle.md](docs/principle.md) | "Only variety absorbs variety" — Ashby's law with the telos flipped; effective rank and free energy measured on entity states; the conflict tax |
476
+ | [docs/math-findings.md](docs/math-findings.md) | The measured math: the substrate-phase experiments (cosine primary, novelty specialist) and e18–e25 (spans, streams, coherence, relations, claims) |
477
+ | [docs/ab-critic-scorecard.md](docs/ab-critic-scorecard.md) | The A/B scorecard vs a plain cosine cache — six criticisms faced honestly |
478
+ | [docs/fork-port-notes.md](docs/fork-port-notes.md) | Fork notes (the fork now runs its own memory design; what it took to port membrane's ideas there) |
479
+ | *the cycled / endless environment* (sibling `cortex-experiment` repo) | The theory notes behind the principle (the loop, and the trap unbounded variety sets) |
480
+
481
+ Retired with the exemplar field (kept in git history, removed from `docs/`):
482
+ `close-the-gap.md` (TencentDB-gap work, superseded by the code-evidence
483
+ lane), `post-restart-plan.md` (the pre-rewrite roadmap), `exploration-game.md`
484
+ and `dev-organism.md` (the toy world and the cell organism — cut in
485
+ `070af25`).
486
+
487
+ ---
488
+
489
+ ## Development
490
+
491
+ Source layout: `membrane/` (the field: `streams` → `efield`/`efstore` →
492
+ `entity_block`/`efgate`/`night`, the seat proxy, the native serve server
493
+ (`server.py`, opencode-compatible), the opencode host (the legacy ablation),
494
+ the CLI), `experiments/` (the e-series rigs behind math-findings), `tests/`
495
+ (unittest + pytest, plain-python runnable).
496
+
497
+ ### Run the tests
498
+
499
+ ```bash
500
+ python -m unittest discover -s tests # or: .venv/bin/python -m unittest discover -s tests
501
+ python -m pytest tests/test_global_field.py tests/test_lab_isolation.py # the field-backed ones
502
+ ```
503
+
504
+ No server needed: everything runs against in-process fakes
505
+ (`tests/_ef_fakes.py` — a sha256-seeded embedder and a lazy fake cluster that
506
+ runs exactly the SQL++ the field emits).
507
+
508
+ ### The variety toy
509
+
510
+ The original variety experiment (what makes a store confident vs unsure —
511
+ the gate's calibration in one command):
512
+
513
+ ```bash
514
+ pip install -r requirements.txt # numpy only
515
+ python experiments/variety_toy.py
516
+ ```
517
+
518
+ Expected: the low-variety store has low effective-rank and low spread; a query
519
+ off its manifold reads as highly novel (gate escalates), while the same query
520
+ against the high-variety store reads as in-manifold (gate acts).
521
+
522
+ ---
523
+
524
+ ## Status
525
+
526
+ Working lab, in daily use on its own development (dogfooded: this repo's own
527
+ field learned the codebase while it was being written — the backfilled field
528
+ answers `membrane state` with ~14k live entities, and its background mind
529
+ digests, dreams, and speaks about its own work). Version **0.2.0b1** — the first beta-testing release; API and flag surfaces may still move. **Private project** — no
530
+ license yet; all rights reserved by the author.