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.
- membrane_seat-0.3.1/LICENSE +51 -0
- membrane_seat-0.3.1/PKG-INFO +530 -0
- membrane_seat-0.3.1/README.md +512 -0
- membrane_seat-0.3.1/membrane/PressStart2P.woff2 +0 -0
- membrane_seat-0.3.1/membrane/VT323.woff2 +0 -0
- membrane_seat-0.3.1/membrane/__init__.py +10 -0
- membrane_seat-0.3.1/membrane/absorb.py +652 -0
- membrane_seat-0.3.1/membrane/active_models.py +203 -0
- membrane_seat-0.3.1/membrane/acts.py +95 -0
- membrane_seat-0.3.1/membrane/ann.py +109 -0
- membrane_seat-0.3.1/membrane/assets.py +81 -0
- membrane_seat-0.3.1/membrane/attention.py +199 -0
- membrane_seat-0.3.1/membrane/auth.py +236 -0
- membrane_seat-0.3.1/membrane/autonode.py +619 -0
- membrane_seat-0.3.1/membrane/backfill.py +175 -0
- membrane_seat-0.3.1/membrane/binding.py +200 -0
- membrane_seat-0.3.1/membrane/capture.py +206 -0
- membrane_seat-0.3.1/membrane/cblite.py +401 -0
- membrane_seat-0.3.1/membrane/cblstore.py +572 -0
- membrane_seat-0.3.1/membrane/claims.py +430 -0
- membrane_seat-0.3.1/membrane/classes.py +136 -0
- membrane_seat-0.3.1/membrane/cli.py +605 -0
- membrane_seat-0.3.1/membrane/code_evidence.py +113 -0
- membrane_seat-0.3.1/membrane/codegraph.py +572 -0
- membrane_seat-0.3.1/membrane/codegraph_lane.py +39 -0
- membrane_seat-0.3.1/membrane/consequences.py +352 -0
- membrane_seat-0.3.1/membrane/consolidate.py +318 -0
- membrane_seat-0.3.1/membrane/dreamer.py +350 -0
- membrane_seat-0.3.1/membrane/efgate.py +277 -0
- membrane_seat-0.3.1/membrane/efield.py +1643 -0
- membrane_seat-0.3.1/membrane/efmind.py +225 -0
- membrane_seat-0.3.1/membrane/efstore.py +1296 -0
- membrane_seat-0.3.1/membrane/eids.py +374 -0
- membrane_seat-0.3.1/membrane/embed.py +145 -0
- membrane_seat-0.3.1/membrane/entities.py +3034 -0
- membrane_seat-0.3.1/membrane/entity_block.py +589 -0
- membrane_seat-0.3.1/membrane/entity_query.py +231 -0
- membrane_seat-0.3.1/membrane/fidelity.py +133 -0
- membrane_seat-0.3.1/membrane/field3d.py +355 -0
- membrane_seat-0.3.1/membrane/fieldmap.py +226 -0
- membrane_seat-0.3.1/membrane/fieldpulse.py +295 -0
- membrane_seat-0.3.1/membrane/file_lane.py +83 -0
- membrane_seat-0.3.1/membrane/fn_schema.py +89 -0
- membrane_seat-0.3.1/membrane/frame.py +150 -0
- membrane_seat-0.3.1/membrane/generator.py +175 -0
- membrane_seat-0.3.1/membrane/global_field.py +188 -0
- membrane_seat-0.3.1/membrane/ha_bridge.py +151 -0
- membrane_seat-0.3.1/membrane/ingest.py +231 -0
- membrane_seat-0.3.1/membrane/intent.py +557 -0
- membrane_seat-0.3.1/membrane/jobs.py +241 -0
- membrane_seat-0.3.1/membrane/jsexec.py +169 -0
- membrane_seat-0.3.1/membrane/lanes.py +7175 -0
- membrane_seat-0.3.1/membrane/ledger.py +142 -0
- membrane_seat-0.3.1/membrane/llm.py +481 -0
- membrane_seat-0.3.1/membrane/massage.py +121 -0
- membrane_seat-0.3.1/membrane/mcp_server.py +1669 -0
- membrane_seat-0.3.1/membrane/minds_models.py +85 -0
- membrane_seat-0.3.1/membrane/move.py +162 -0
- membrane_seat-0.3.1/membrane/naming.py +219 -0
- membrane_seat-0.3.1/membrane/night.py +4010 -0
- membrane_seat-0.3.1/membrane/offline.py +238 -0
- membrane_seat-0.3.1/membrane/opencode.py +2227 -0
- membrane_seat-0.3.1/membrane/outcomes.py +351 -0
- membrane_seat-0.3.1/membrane/peers.py +761 -0
- membrane_seat-0.3.1/membrane/predict.py +566 -0
- membrane_seat-0.3.1/membrane/project_env.py +214 -0
- membrane_seat-0.3.1/membrane/rag.py +295 -0
- membrane_seat-0.3.1/membrane/reembed.py +59 -0
- membrane_seat-0.3.1/membrane/relations.py +131 -0
- membrane_seat-0.3.1/membrane/render.py +270 -0
- membrane_seat-0.3.1/membrane/restarts.py +437 -0
- membrane_seat-0.3.1/membrane/review.py +107 -0
- membrane_seat-0.3.1/membrane/router.py +1024 -0
- membrane_seat-0.3.1/membrane/score.py +251 -0
- membrane_seat-0.3.1/membrane/seat.py +125 -0
- membrane_seat-0.3.1/membrane/seat_panel.py +277 -0
- membrane_seat-0.3.1/membrane/server.py +3423 -0
- membrane_seat-0.3.1/membrane/settings.py +66 -0
- membrane_seat-0.3.1/membrane/skills/membrane-codegraph/SKILL.md +35 -0
- membrane_seat-0.3.1/membrane/skills/membrane-forget-memory/SKILL.md +76 -0
- membrane_seat-0.3.1/membrane/skills/membrane-global-field/SKILL.md +44 -0
- membrane_seat-0.3.1/membrane/skills/membrane-ingest/SKILL.md +39 -0
- membrane_seat-0.3.1/membrane/skills/membrane-query-field/SKILL.md +57 -0
- membrane_seat-0.3.1/membrane/skills/membrane-restart/SKILL.md +53 -0
- membrane_seat-0.3.1/membrane/skills/membrane-state/SKILL.md +57 -0
- membrane_seat-0.3.1/membrane/skills/membrane-write-memory/SKILL.md +109 -0
- membrane_seat-0.3.1/membrane/slash.py +168 -0
- membrane_seat-0.3.1/membrane/speaker.py +196 -0
- membrane_seat-0.3.1/membrane/speakers.py +72 -0
- membrane_seat-0.3.1/membrane/strangers.py +381 -0
- membrane_seat-0.3.1/membrane/streams.py +327 -0
- membrane_seat-0.3.1/membrane/substrate.py +189 -0
- membrane_seat-0.3.1/membrane/thinker.py +1063 -0
- membrane_seat-0.3.1/membrane/three.min.js +6 -0
- membrane_seat-0.3.1/membrane/token_timeline.py +132 -0
- membrane_seat-0.3.1/membrane/toolset.py +429 -0
- membrane_seat-0.3.1/membrane/ui/favicon.js +44 -0
- membrane_seat-0.3.1/membrane/ui/favicon.svg +10 -0
- membrane_seat-0.3.1/membrane/ui/field.js +973 -0
- membrane_seat-0.3.1/membrane/ui/field3d.js +1086 -0
- membrane_seat-0.3.1/membrane/ui/home.js +2008 -0
- membrane_seat-0.3.1/membrane/ui/host.js +42 -0
- membrane_seat-0.3.1/membrane/ui/index.html +86 -0
- membrane_seat-0.3.1/membrane/ui/panel.js +1924 -0
- membrane_seat-0.3.1/membrane/ui/three.min.js +6 -0
- membrane_seat-0.3.1/membrane/ui/vosk.js +815 -0
- membrane_seat-0.3.1/membrane/ui_serve.py +325 -0
- membrane_seat-0.3.1/membrane/universe.py +140 -0
- membrane_seat-0.3.1/membrane/update.py +292 -0
- membrane_seat-0.3.1/membrane/viewer.html +1797 -0
- membrane_seat-0.3.1/membrane/voice.py +1547 -0
- membrane_seat-0.3.1/membrane/voice_io.py +198 -0
- membrane_seat-0.3.1/membrane/vsa.py +367 -0
- membrane_seat-0.3.1/membrane/wakes.py +116 -0
- membrane_seat-0.3.1/membrane/watch.py +383 -0
- membrane_seat-0.3.1/membrane/watch_agents.py +1682 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/PKG-INFO +530 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/SOURCES.txt +317 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/dependency_links.txt +1 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/entry_points.txt +2 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/requires.txt +7 -0
- membrane_seat-0.3.1/membrane_seat.egg-info/top_level.txt +1 -0
- membrane_seat-0.3.1/pyproject.toml +46 -0
- membrane_seat-0.3.1/setup.cfg +4 -0
- membrane_seat-0.3.1/tests/test_absorb.py +742 -0
- membrane_seat-0.3.1/tests/test_act_planner.py +102 -0
- membrane_seat-0.3.1/tests/test_active_models.py +85 -0
- membrane_seat-0.3.1/tests/test_agent_forget.py +136 -0
- membrane_seat-0.3.1/tests/test_agent_minds.py +111 -0
- membrane_seat-0.3.1/tests/test_agent_writes.py +113 -0
- membrane_seat-0.3.1/tests/test_alert_gate.py +148 -0
- membrane_seat-0.3.1/tests/test_arg_aliases_2.py +111 -0
- membrane_seat-0.3.1/tests/test_assets.py +40 -0
- membrane_seat-0.3.1/tests/test_attention.py +216 -0
- membrane_seat-0.3.1/tests/test_autonode.py +577 -0
- membrane_seat-0.3.1/tests/test_backfill.py +126 -0
- membrane_seat-0.3.1/tests/test_banner.py +256 -0
- membrane_seat-0.3.1/tests/test_binding.py +79 -0
- membrane_seat-0.3.1/tests/test_blocked_wake.py +189 -0
- membrane_seat-0.3.1/tests/test_boot_entity.py +74 -0
- membrane_seat-0.3.1/tests/test_boot_order.py +39 -0
- membrane_seat-0.3.1/tests/test_capture.py +131 -0
- membrane_seat-0.3.1/tests/test_cblstore.py +293 -0
- membrane_seat-0.3.1/tests/test_claims.py +146 -0
- membrane_seat-0.3.1/tests/test_cliffhanger.py +472 -0
- membrane_seat-0.3.1/tests/test_cloud_providers.py +318 -0
- membrane_seat-0.3.1/tests/test_code_evidence.py +100 -0
- membrane_seat-0.3.1/tests/test_command_library.py +107 -0
- membrane_seat-0.3.1/tests/test_command_names.py +101 -0
- membrane_seat-0.3.1/tests/test_concurrency_dumps.py +202 -0
- membrane_seat-0.3.1/tests/test_concurrent_reads.py +175 -0
- membrane_seat-0.3.1/tests/test_consequences.py +151 -0
- membrane_seat-0.3.1/tests/test_consolidate.py +138 -0
- membrane_seat-0.3.1/tests/test_curiosity.py +100 -0
- membrane_seat-0.3.1/tests/test_delegate.py +151 -0
- membrane_seat-0.3.1/tests/test_doctrine_native.py +81 -0
- membrane_seat-0.3.1/tests/test_doctrine_split.py +91 -0
- membrane_seat-0.3.1/tests/test_door_visibility.py +184 -0
- membrane_seat-0.3.1/tests/test_drain_bounds.py +56 -0
- membrane_seat-0.3.1/tests/test_dropped_stream.py +101 -0
- membrane_seat-0.3.1/tests/test_durability.py +296 -0
- membrane_seat-0.3.1/tests/test_echo_split.py +145 -0
- membrane_seat-0.3.1/tests/test_ef_cli.py +75 -0
- membrane_seat-0.3.1/tests/test_ef_prereqs.py +149 -0
- membrane_seat-0.3.1/tests/test_efgate.py +118 -0
- membrane_seat-0.3.1/tests/test_efield.py +272 -0
- membrane_seat-0.3.1/tests/test_efmind.py +97 -0
- membrane_seat-0.3.1/tests/test_efstore_cb.py +240 -0
- membrane_seat-0.3.1/tests/test_efstore_drain.py +53 -0
- membrane_seat-0.3.1/tests/test_efstore_file.py +185 -0
- membrane_seat-0.3.1/tests/test_efstore_journal.py +143 -0
- membrane_seat-0.3.1/tests/test_eids.py +103 -0
- membrane_seat-0.3.1/tests/test_embed_cache.py +150 -0
- membrane_seat-0.3.1/tests/test_entities.py +317 -0
- membrane_seat-0.3.1/tests/test_entity_block.py +235 -0
- membrane_seat-0.3.1/tests/test_entity_coll_cache.py +91 -0
- membrane_seat-0.3.1/tests/test_entity_link_args.py +91 -0
- membrane_seat-0.3.1/tests/test_entity_query.py +142 -0
- membrane_seat-0.3.1/tests/test_entity_scripts.py +400 -0
- membrane_seat-0.3.1/tests/test_executor_chain.py +330 -0
- membrane_seat-0.3.1/tests/test_executor_link.py +373 -0
- membrane_seat-0.3.1/tests/test_fidelity.py +60 -0
- membrane_seat-0.3.1/tests/test_field3d.py +173 -0
- membrane_seat-0.3.1/tests/test_field3d_routes.py +81 -0
- membrane_seat-0.3.1/tests/test_field_pulse.py +168 -0
- membrane_seat-0.3.1/tests/test_field_watch.py +197 -0
- membrane_seat-0.3.1/tests/test_field_wiring.py +208 -0
- membrane_seat-0.3.1/tests/test_fieldmap.py +236 -0
- membrane_seat-0.3.1/tests/test_frame.py +160 -0
- membrane_seat-0.3.1/tests/test_frame_lint.py +150 -0
- membrane_seat-0.3.1/tests/test_frame_wait.py +105 -0
- membrane_seat-0.3.1/tests/test_freshness.py +77 -0
- membrane_seat-0.3.1/tests/test_getter_news.py +67 -0
- membrane_seat-0.3.1/tests/test_getter_path.py +106 -0
- membrane_seat-0.3.1/tests/test_global_field.py +93 -0
- membrane_seat-0.3.1/tests/test_goal_intents.py +206 -0
- membrane_seat-0.3.1/tests/test_goal_progress.py +223 -0
- membrane_seat-0.3.1/tests/test_ha_bridge.py +74 -0
- membrane_seat-0.3.1/tests/test_ha_detached.py +204 -0
- membrane_seat-0.3.1/tests/test_ha_supervisor.py +57 -0
- membrane_seat-0.3.1/tests/test_heat_gravity.py +185 -0
- membrane_seat-0.3.1/tests/test_history_anchor.py +59 -0
- membrane_seat-0.3.1/tests/test_idle_cortex_pick.py +95 -0
- membrane_seat-0.3.1/tests/test_ingest_codegraph.py +252 -0
- membrane_seat-0.3.1/tests/test_inheritance.py +192 -0
- membrane_seat-0.3.1/tests/test_init_speak.py +53 -0
- membrane_seat-0.3.1/tests/test_injection_card.py +46 -0
- membrane_seat-0.3.1/tests/test_intent_lane.py +251 -0
- membrane_seat-0.3.1/tests/test_jobs.py +160 -0
- membrane_seat-0.3.1/tests/test_jsexec.py +82 -0
- membrane_seat-0.3.1/tests/test_lab_isolation.py +37 -0
- membrane_seat-0.3.1/tests/test_lan_discovery.py +222 -0
- membrane_seat-0.3.1/tests/test_lane_gate.py +1008 -0
- membrane_seat-0.3.1/tests/test_lane_truths.py +68 -0
- membrane_seat-0.3.1/tests/test_leadin_text.py +78 -0
- membrane_seat-0.3.1/tests/test_ledger.py +123 -0
- membrane_seat-0.3.1/tests/test_listen_host.py +32 -0
- membrane_seat-0.3.1/tests/test_llm_entity.py +147 -0
- membrane_seat-0.3.1/tests/test_llm_wake.py +157 -0
- membrane_seat-0.3.1/tests/test_loop_lane.py +152 -0
- membrane_seat-0.3.1/tests/test_loop_wiring.py +165 -0
- membrane_seat-0.3.1/tests/test_massage.py +112 -0
- membrane_seat-0.3.1/tests/test_mcp.py +333 -0
- membrane_seat-0.3.1/tests/test_mcp_surface.py +54 -0
- membrane_seat-0.3.1/tests/test_message_entities.py +239 -0
- membrane_seat-0.3.1/tests/test_midturn_messages.py +118 -0
- membrane_seat-0.3.1/tests/test_minds_models.py +87 -0
- membrane_seat-0.3.1/tests/test_minds_view.py +51 -0
- membrane_seat-0.3.1/tests/test_mirror_demint.py +129 -0
- membrane_seat-0.3.1/tests/test_model_chat.py +158 -0
- membrane_seat-0.3.1/tests/test_name_lint.py +77 -0
- membrane_seat-0.3.1/tests/test_naming.py +89 -0
- membrane_seat-0.3.1/tests/test_night.py +230 -0
- membrane_seat-0.3.1/tests/test_night_mode.py +203 -0
- membrane_seat-0.3.1/tests/test_nursery_ghosts.py +85 -0
- membrane_seat-0.3.1/tests/test_offline_mode.py +122 -0
- membrane_seat-0.3.1/tests/test_one_spelling.py +103 -0
- membrane_seat-0.3.1/tests/test_outcomes.py +157 -0
- membrane_seat-0.3.1/tests/test_parallel_minds.py +120 -0
- membrane_seat-0.3.1/tests/test_patterns.py +97 -0
- membrane_seat-0.3.1/tests/test_peer_cursor.py +81 -0
- membrane_seat-0.3.1/tests/test_peers_roster.py +100 -0
- membrane_seat-0.3.1/tests/test_person_preempts.py +129 -0
- membrane_seat-0.3.1/tests/test_phone_lane.py +47 -0
- membrane_seat-0.3.1/tests/test_pick_default_model.py +20 -0
- membrane_seat-0.3.1/tests/test_port_probe.py +43 -0
- membrane_seat-0.3.1/tests/test_predict.py +205 -0
- membrane_seat-0.3.1/tests/test_project_env.py +174 -0
- membrane_seat-0.3.1/tests/test_prompt_async_parts.py +101 -0
- membrane_seat-0.3.1/tests/test_publish.py +283 -0
- membrane_seat-0.3.1/tests/test_query_universe.py +130 -0
- membrane_seat-0.3.1/tests/test_queue_once.py +97 -0
- membrane_seat-0.3.1/tests/test_recall_loopback.py +107 -0
- membrane_seat-0.3.1/tests/test_recall_report.py +77 -0
- membrane_seat-0.3.1/tests/test_receipt_lane.py +59 -0
- membrane_seat-0.3.1/tests/test_relabel_roles.py +99 -0
- membrane_seat-0.3.1/tests/test_relations.py +97 -0
- membrane_seat-0.3.1/tests/test_restarts.py +133 -0
- membrane_seat-0.3.1/tests/test_restarts_ha.py +35 -0
- membrane_seat-0.3.1/tests/test_route_health.py +78 -0
- membrane_seat-0.3.1/tests/test_route_health_global.py +52 -0
- membrane_seat-0.3.1/tests/test_router.py +457 -0
- membrane_seat-0.3.1/tests/test_run_lane.py +220 -0
- membrane_seat-0.3.1/tests/test_scan_index.py +237 -0
- membrane_seat-0.3.1/tests/test_score.py +130 -0
- membrane_seat-0.3.1/tests/test_script_budget.py +79 -0
- membrane_seat-0.3.1/tests/test_script_covenant.py +222 -0
- membrane_seat-0.3.1/tests/test_script_errors.py +186 -0
- membrane_seat-0.3.1/tests/test_script_kinds.py +209 -0
- membrane_seat-0.3.1/tests/test_seat_card.py +148 -0
- membrane_seat-0.3.1/tests/test_seat_panel.py +149 -0
- membrane_seat-0.3.1/tests/test_seat_read_bridge.py +121 -0
- membrane_seat-0.3.1/tests/test_selection_persists.py +64 -0
- membrane_seat-0.3.1/tests/test_serve.py +87 -0
- membrane_seat-0.3.1/tests/test_serve_busy.py +174 -0
- membrane_seat-0.3.1/tests/test_serve_delivery.py +66 -0
- membrane_seat-0.3.1/tests/test_serve_store_merge.py +137 -0
- membrane_seat-0.3.1/tests/test_server.py +929 -0
- membrane_seat-0.3.1/tests/test_sharing.py +114 -0
- membrane_seat-0.3.1/tests/test_side_index.py +145 -0
- membrane_seat-0.3.1/tests/test_slash.py +82 -0
- membrane_seat-0.3.1/tests/test_speaker_lane.py +132 -0
- membrane_seat-0.3.1/tests/test_speakers.py +114 -0
- membrane_seat-0.3.1/tests/test_spec_resolve.py +74 -0
- membrane_seat-0.3.1/tests/test_speech_footer.py +62 -0
- membrane_seat-0.3.1/tests/test_sse_hub.py +45 -0
- membrane_seat-0.3.1/tests/test_stop_button.py +92 -0
- membrane_seat-0.3.1/tests/test_strangers.py +182 -0
- membrane_seat-0.3.1/tests/test_streamed_rounds.py +165 -0
- membrane_seat-0.3.1/tests/test_streams.py +142 -0
- membrane_seat-0.3.1/tests/test_sweep_batch3.py +123 -0
- membrane_seat-0.3.1/tests/test_sweep_batch4.py +106 -0
- membrane_seat-0.3.1/tests/test_sweep_batch5.py +60 -0
- membrane_seat-0.3.1/tests/test_sweep_fixes.py +191 -0
- membrane_seat-0.3.1/tests/test_symbol_recall.py +140 -0
- membrane_seat-0.3.1/tests/test_thinker.py +422 -0
- membrane_seat-0.3.1/tests/test_thinker_inject.py +41 -0
- membrane_seat-0.3.1/tests/test_thinking_indicator.py +166 -0
- membrane_seat-0.3.1/tests/test_timeline_layer.py +108 -0
- membrane_seat-0.3.1/tests/test_timelines.py +102 -0
- membrane_seat-0.3.1/tests/test_tool_arg_aliases.py +136 -0
- membrane_seat-0.3.1/tests/test_tool_inversion.py +179 -0
- membrane_seat-0.3.1/tests/test_toolset.py +249 -0
- membrane_seat-0.3.1/tests/test_tui_attach.py +54 -0
- membrane_seat-0.3.1/tests/test_turn_watchdog.py +127 -0
- membrane_seat-0.3.1/tests/test_ui_serve.py +152 -0
- membrane_seat-0.3.1/tests/test_update.py +109 -0
- membrane_seat-0.3.1/tests/test_v1_post_hang.py +171 -0
- membrane_seat-0.3.1/tests/test_vec_first_build.py +82 -0
- membrane_seat-0.3.1/tests/test_viewer_gate.py +62 -0
- membrane_seat-0.3.1/tests/test_voice.py +786 -0
- membrane_seat-0.3.1/tests/test_voice_io.py +83 -0
- membrane_seat-0.3.1/tests/test_vsa.py +248 -0
- membrane_seat-0.3.1/tests/test_vsa_consumers.py +113 -0
- membrane_seat-0.3.1/tests/test_wake_ledger.py +145 -0
- membrane_seat-0.3.1/tests/test_watch.py +259 -0
- membrane_seat-0.3.1/tests/test_watch_agents.py +453 -0
- membrane_seat-0.3.1/tests/test_watch_attach.py +151 -0
- 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
|
+

|
|
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.
|