shugonet 0.5.0__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 (65) hide show
  1. shugonet-0.5.0/LICENSE +21 -0
  2. shugonet-0.5.0/PKG-INFO +325 -0
  3. shugonet-0.5.0/README.md +301 -0
  4. shugonet-0.5.0/agent_registry.py +176 -0
  5. shugonet-0.5.0/audit.py +183 -0
  6. shugonet-0.5.0/bluetooth_transport.py +314 -0
  7. shugonet-0.5.0/dashboard.py +465 -0
  8. shugonet-0.5.0/discovery.py +191 -0
  9. shugonet-0.5.0/fallbacks.py +135 -0
  10. shugonet-0.5.0/link_simulator.py +264 -0
  11. shugonet-0.5.0/lora_transport.py +320 -0
  12. shugonet-0.5.0/memory_sync.py +646 -0
  13. shugonet-0.5.0/mesh_query.py +203 -0
  14. shugonet-0.5.0/pg_store.py +202 -0
  15. shugonet-0.5.0/policy.py +41 -0
  16. shugonet-0.5.0/protocol.py +550 -0
  17. shugonet-0.5.0/pyproject.toml +37 -0
  18. shugonet-0.5.0/relay_server.py +299 -0
  19. shugonet-0.5.0/relay_transport.py +241 -0
  20. shugonet-0.5.0/security.py +63 -0
  21. shugonet-0.5.0/setup.cfg +4 -0
  22. shugonet-0.5.0/shugocore_adapter.py +147 -0
  23. shugonet-0.5.0/shugocore_bridge.py +223 -0
  24. shugonet-0.5.0/shugonet.egg-info/PKG-INFO +325 -0
  25. shugonet-0.5.0/shugonet.egg-info/SOURCES.txt +63 -0
  26. shugonet-0.5.0/shugonet.egg-info/dependency_links.txt +1 -0
  27. shugonet-0.5.0/shugonet.egg-info/entry_points.txt +2 -0
  28. shugonet-0.5.0/shugonet.egg-info/requires.txt +18 -0
  29. shugonet-0.5.0/shugonet.egg-info/top_level.txt +27 -0
  30. shugonet-0.5.0/shugonet_client.py +419 -0
  31. shugonet-0.5.0/shugonet_runtime.py +181 -0
  32. shugonet-0.5.0/shugonet_web/__init__.py +16 -0
  33. shugonet-0.5.0/shugonet_web/static/assets/index-BQCxUM6l.css +1 -0
  34. shugonet-0.5.0/shugonet_web/static/assets/index-CDOtMJAn.js +1 -0
  35. shugonet-0.5.0/shugonet_web/static/index.html +15 -0
  36. shugonet-0.5.0/store_forward.py +169 -0
  37. shugonet-0.5.0/tcp_transport.py +446 -0
  38. shugonet-0.5.0/telemetry.py +53 -0
  39. shugonet-0.5.0/tests/test_agent_registry.py +121 -0
  40. shugonet-0.5.0/tests/test_audit.py +79 -0
  41. shugonet-0.5.0/tests/test_bluetooth.py +157 -0
  42. shugonet-0.5.0/tests/test_bridge_sync.py +66 -0
  43. shugonet-0.5.0/tests/test_concurrency.py +375 -0
  44. shugonet-0.5.0/tests/test_dashboard.py +258 -0
  45. shugonet-0.5.0/tests/test_discovery.py +73 -0
  46. shugonet-0.5.0/tests/test_fallbacks.py +109 -0
  47. shugonet-0.5.0/tests/test_host.py +201 -0
  48. shugonet-0.5.0/tests/test_integration.py +284 -0
  49. shugonet-0.5.0/tests/test_link_simulator.py +154 -0
  50. shugonet-0.5.0/tests/test_lora.py +227 -0
  51. shugonet-0.5.0/tests/test_memory_compat.py +256 -0
  52. shugonet-0.5.0/tests/test_memory_sync.py +198 -0
  53. shugonet-0.5.0/tests/test_mesh_query.py +123 -0
  54. shugonet-0.5.0/tests/test_pg_mirror.py +81 -0
  55. shugonet-0.5.0/tests/test_protocol.py +201 -0
  56. shugonet-0.5.0/tests/test_relay.py +192 -0
  57. shugonet-0.5.0/tests/test_shugocore.py +106 -0
  58. shugonet-0.5.0/tests/test_store_forward.py +100 -0
  59. shugonet-0.5.0/tests/test_tcp_transport.py +120 -0
  60. shugonet-0.5.0/tests/test_transport_fallback.py +229 -0
  61. shugonet-0.5.0/tests/test_transports.py +171 -0
  62. shugonet-0.5.0/tests/test_version_handshake.py +153 -0
  63. shugonet-0.5.0/transport_fallback.py +326 -0
  64. shugonet-0.5.0/transports.py +243 -0
  65. shugonet-0.5.0/version.py +30 -0
shugonet-0.5.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SamurAI-Official
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,325 @@
1
+ Metadata-Version: 2.4
2
+ Name: shugonet
3
+ Version: 0.5.0
4
+ Summary: Networking integration for connecting multiple Shugocore agents together for collaboration between Shugocore agents in simulation and physical spaces, designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth networks.
5
+ Author: SamurAI-Official
6
+ License: MIT
7
+ Keywords: agent,networking,mesh,memory,fallback,shugocore
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Provides-Extra: ws
12
+ Requires-Dist: websocket-client>=1.6; extra == "ws"
13
+ Provides-Extra: relay
14
+ Requires-Dist: requests>=2.32.0; extra == "relay"
15
+ Provides-Extra: serial
16
+ Requires-Dist: pyserial>=3.5; extra == "serial"
17
+ Provides-Extra: ble
18
+ Requires-Dist: bleak>=0.20; extra == "ble"
19
+ Provides-Extra: telemetry
20
+ Requires-Dist: opentelemetry-api>=1.20; extra == "telemetry"
21
+ Provides-Extra: postgres
22
+ Requires-Dist: psycopg2-binary>=2.9; extra == "postgres"
23
+ Dynamic: license-file
24
+
25
+ # Shogunet
26
+
27
+ > Networking integration for connecting multiple Shugocore agents together for
28
+ > collaboration between Shugocore agents in simulation and physical spaces,
29
+ > designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth
30
+ > networks.
31
+
32
+ [![PyPI](https://img.shields.io/pypi/v/shugonet)](https://pypi.org/project/shugonet/)
33
+ ![Release](https://img.shields.io/badge/release-v0.5.0-blue)
34
+ ![Python](https://img.shields.io/badge/python-3.9%E2%80%933.12-blue)
35
+ ![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Android%20%28Termux%2FChaquopy%29-lightgrey)
36
+ ![License](https://img.shields.io/badge/license-MIT-green)
37
+
38
+ ## Installation
39
+
40
+ ```bash
41
+ pip install shugonet
42
+ ```
43
+
44
+ The core is dependency-free (stdlib-only). Optional extras:
45
+
46
+ ```bash
47
+ pip install shugonet[postgres] # PostgreSQL mesh backend (PgSemanticMemory parity)
48
+ pip install shugonet[ws] # rosbridge-style WebSocket transport
49
+ pip install shugonet[relay] # HTTPS relay transport (5G/4G/EDGE)
50
+ pip install shugonet[serial] # LoRa SX126x/SX127x serial modules
51
+ pip install shugonet[ble] # BLE transport
52
+ pip install shugonet[telemetry] # OpenTelemetry integration
53
+ ```
54
+
55
+ The compiled fleet dashboard ships inside the wheel — no JavaScript toolchain
56
+ is needed at install time.
57
+
58
+ Shogunet is the networking layer for [ShugoCore](https://github.com/SamurAI-Official/ShugoCore).
59
+ It lets a fleet of ShugoCore agents — running in Gazebo simulation, on servers,
60
+ on robots, or on Android handsets — discover each other, exchange tasks and
61
+ events, and consolidate a *codependent* memory mesh, over whatever networks the
62
+ mission has available, with deterministic fallback between them.
63
+
64
+ ## Design principles
65
+
66
+ **One protocol, every network.** A single versioned envelope is spoken over all
67
+ transports, from 5G to LoRa. Two codecs exist for it: a JSON codec for
68
+ broadband links and a compact binary codec (16-byte header + TLV payload) for
69
+ constrained links such as LoRa (0.3–27 kbit/s, ~220-byte frames) and BLE.
70
+
71
+ **Memory invariants survive the network.** ShugoCore's memory tiers map to
72
+ network tiers: Tier 0/1 never leave the agent (N0). Tier 2 semantic facts sync
73
+ between paired agents (N1). Tier 3 is read-only everywhere: only *promotion
74
+ proposals* travel, and application stays operator-attributed (N2).
75
+
76
+ **Codependent memory.** Facts propagate with provenance
77
+ `(origin_agent_id, fact_id)`; salience merges additively; pruning propagates as
78
+ tombstones; and reinforcement is a *feedback loop* — when a peer's fact proves
79
+ useful, a tiny `reinforce` message flows back so useful memories survive decay
80
+ fleet-wide. Over LoRa, the loop runs on ~50-byte digest frames; bulk fact
81
+ content moves later over any broadband link (digest anti-entropy).
82
+
83
+ **Pairing is consent.** Only operator-allowlisted agent IDs pair, grants carry
84
+ TTLs, topics are namespaced (`/shugunet/{agent_id}/{topic}`), and every
85
+ ingress/egress field is sanitized and size-capped. Every network event lands in
86
+ a hash-chained audit log.
87
+
88
+ **Deterministic fallback.** Transports form an ordered, health-ranked chain
89
+ with per-transport circuit breakers. If the LAN drops, traffic falls to the
90
+ relay; if everything drops, a bounded store-and-forward WAL replays on
91
+ reconnect. Total transport exhaustion latches the ShugoCore governor through
92
+ its fallback triggers instead of failing silently.
93
+
94
+ ## Network tiers
95
+
96
+ | Class | Networks | Protocol response |
97
+ |---|---|---|
98
+ | Broadband IP | 5G, 4G, WiFi | JSON codec, mesh query fan-out, bulk sync; LAN = direct TCP, cellular = relay hub |
99
+ | Midband IP | EDGE, WiFi-Halow | Compact codec, batching, latency-tolerant profiles |
100
+ | Constrained | LoRa | 16-byte header frames ≤ 220 B, P0/P1 priority only, digest anti-entropy, duty-cycle honored |
101
+ | Short-range | Bluetooth (RFCOMM/BLE) | Stream framing or segmented compact codec; pairing-based discovery |
102
+
103
+ Message priority classes: **P0** control (announce/heartbeat/ack/tombstone) →
104
+ all links · **P1** memory deltas (facts/reinforce/digests) → constrained-capable
105
+ · **P2** tasks and queries → IP links · **P3** bulk snapshots and audit
106
+ shipping → broadband only, deferred under low power / thermal pressure.
107
+
108
+ ## Module map
109
+
110
+ | Module | Responsibility |
111
+ |---|---|
112
+ | `protocol.py` | Envelope schema, 16-byte binary header, JSON + compact TLV codecs, segmentation, validation |
113
+ | `transports.py` | `BaseTransport`, `LinkProfile` registry (7 networks + loopback), loopback bus |
114
+ | `link_simulator.py` | In-process impairment: bandwidth, latency, jitter, loss, MTU, duty cycle |
115
+ | `discovery.py` | Per-medium peer discovery (multicast beacons, hub rendezvous, pairing, duty-cycled LoRa) |
116
+ | `agent_registry.py` | Pairing = consent, allowlists, TTL grants, topic ACLs, sim/phys manifests |
117
+ | `tcp_transport.py` | Length-prefixed TCP transport with announce handshake (WiFi / WiFi-Halow profiles) |
118
+ | `relay_transport.py` / `relay_server.py` | Cellular path: HTTPS relay hub + long-poll client (5G/4G/EDGE, cross-NAT) |
119
+ | `lora_transport.py` | Serial SX126x/SX127x point-to-point transport (optional `pyserial`) |
120
+ | `bluetooth_transport.py` | RFCOMM (AF_BLUETOOTH) and BLE (optional `bleak`) transports |
121
+ | `transport_fallback.py` | Link-aware chain: eligibility, EWMA health ranking, breakers, QoS |
122
+ | `store_forward.py` | Bounded JSONL WAL outbox/inbox with replay + dedup |
123
+ | `memory_sync.py` / `mesh_query.py` | Codependent memory mesh: fact replication, conflict resolution, fan-out queries |
124
+ | `audit.py`, `fallbacks.py`, `policy.py`, `telemetry.py` | ShugoCore-aligned safety surface |
125
+ | `shugocore_bridge.py` | Adapter hosting a Shogunet node beside a ShugoCore `DecisionEngine` |
126
+
127
+ ## Hosting a fleet
128
+
129
+ Shogunet runs as a single server process that owns the fleet's trust plane so
130
+ every ShugoCore agent only needs a ~20-line client runtime to join.
131
+
132
+ ### Start a host
133
+
134
+ ```python
135
+ from host import ShugonetHost
136
+
137
+ host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001)
138
+ host.start()
139
+
140
+ # Grant consent to a joining agent (pairing = consent)
141
+ host.pair("agent-001", manifest={"realm": "phys", "role": "perception"})
142
+
143
+ print(host.status()) # roster, alive count, breaker health, mesh counts
144
+ ```
145
+
146
+ Or from the CLI:
147
+
148
+ ```bash
149
+ python3 host.py --tcp-port 9000 --relay-port 9001
150
+ ```
151
+
152
+ ### Join from a ShugoCore process
153
+
154
+ ```python
155
+ from shugonet_runtime import ShugonetAgentRuntime
156
+
157
+ runtime = ShugonetAgentRuntime(
158
+ agent_id="agent-001",
159
+ host_tcp_host="127.0.0.1",
160
+ host_tcp_port=9000,
161
+ host_relay_url="http://127.0.0.1:9001",
162
+ on_message=lambda sender, msg: print(f"from {sender}: {msg}"))
163
+ runtime.connect_to_host()
164
+
165
+ # Send a task to another agent
166
+ runtime.send("agent-002", "/shugunet/agent-001/task",
167
+ {"action": "scan", "zone": "north"})
168
+
169
+ # Search the fleet's memory
170
+ results = runtime.query("obstacle in zone north")
171
+
172
+ # Sync memory with the fleet
173
+ runtime.sync()
174
+
175
+ # Leave the fleet
176
+ runtime.stop()
177
+ ```
178
+
179
+ ### Cross-platform CLI client
180
+
181
+ Shogunet ships a standard CLI client that works on macOS, Linux, and Windows:
182
+
183
+ ```bash
184
+ # Install (ships with the wheel)
185
+ pip install shugonet
186
+
187
+ # Connect and stay connected (foreground daemon)
188
+ shugonet-client run
189
+
190
+ # One-shot status
191
+ shugonet-client status
192
+
193
+ # One-shot send to a peer
194
+ shugonet-client send agent-002 /shugunet/agent-001/task '{"action":"scan"}'
195
+
196
+ # One-shot memory query
197
+ shugonet-client query "obstacle in zone north"
198
+
199
+ # One-shot digest sync
200
+ shugonet-client sync agent-002
201
+ ```
202
+
203
+ The client is configured via environment variables:
204
+
205
+ | Variable | Default | Description |
206
+ |---|---|---|
207
+ | `SHUGONET_AGENT_ID` | hostname | Agent identifier |
208
+ | `SHUGONET_HOST` | 127.0.0.1 | ShugonetHost address |
209
+ | `SHUGONET_TCP_PORT` | 9000 | TCP port |
210
+ | `SHUGONET_RELAY_URL` | *(none)* | Relay hub URL |
211
+ | `SHUGONET_REALM` | phys | sim or phys realm |
212
+ | `SHUGONET_LOG_LEVEL` | info | Log verbosity |
213
+
214
+ Or use it programmatically:
215
+
216
+ ```python
217
+ from shugonet_client import ShugonetClient
218
+
219
+ client = ShugonetClient(agent_id="robot-1", host="10.0.0.5", tcp_port=9000)
220
+ client.connect()
221
+ client.send("robot-2", "/shugunet/robot-1/status", {"battery": 87})
222
+ print(client.status())
223
+ client.disconnect()
224
+ ```
225
+
226
+ ### Routing model
227
+
228
+ Agents connect **to** the host (hub-and-spoke). The host forwards addressed
229
+ mail to its recipient and fans broadcasts out as addressed copies to every
230
+ other paired agent. Host-addressed mail — heartbeats, mesh queries, memory
231
+ broadcasts — is processed locally by the host's own chain handlers.
232
+
233
+ **Pairing is enforced twice** — at TCP admission (handshake hook) and again on
234
+ every host-processed or forwarded envelope (the relay path has no registry gate
235
+ of its own, so the host re-checks the sender there).
236
+
237
+ ### Failure semantics
238
+
239
+ - **Agent crash/disconnect** → host governor latches `pause` (ShugoCore
240
+ deterministic latch contract).
241
+ - **Message durability** → per-agent `OutboxStore` + `at_least_once` QoS + hub
242
+ mailbox TTL bounds.
243
+ - **Cross-talk** → chain and mesh recipient guards (hardened in the
244
+ concurrency suite) hold at host scale.
245
+
246
+ ### Fleet dashboard
247
+
248
+ Every `ShugunetHost` can expose an operator console — a compiled single-page
249
+ app (TypeScript + SolidJS, built with Vite) served directly by the host over a
250
+ loopback HTTP port. No JavaScript toolchain is needed at install time: the
251
+ built assets ship inside the wheel (`shugonet_web/static`).
252
+
253
+ ```python
254
+ host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001,
255
+ dashboard_port=9002)
256
+ host.start()
257
+ # open http://127.0.0.1:9002 in a browser
258
+ ```
259
+
260
+ The console streams a live event feed (Server-Sent Events), shows the roster,
261
+ transport-chain health, memory-mesh counters, and audit-chain integrity, and
262
+ exposes pair / unpair / resume / broadcast controls. State-changing POSTs are
263
+ audited and can be gated by a token (`dashboard_token=...`).
264
+
265
+ The SPA source lives in `dashboard/`; rebuild it with:
266
+
267
+ ```bash
268
+ cd dashboard && npm ci && npm run build
269
+ ```
270
+
271
+ ## Module map (continued)
272
+
273
+ | Module | Responsibility |
274
+ |---|---|
275
+ | `host.py` | `ShugunetHost`: admit paired agents, route traffic, seed the mesh |
276
+ | `shugonet_runtime.py` | `ShugonetAgentRuntime`: client half a ShugoCore process instantiates |
277
+ | `shugonet_client.py` | `ShugonetClient`: cross-platform CLI and programmatic client |
278
+ | `dashboard.py` | `DashboardServer`: stdlib HTTP operator plane (REST + SSE + SPA) |
279
+ | `pg_store.py` | `PgFactStore`: optional PostgreSQL mesh backend (ShugoCore `PgSemanticMemory` parity) |
280
+
281
+ ## Testing
282
+
283
+ ```bash
284
+ python3 -m unittest discover -s tests -v
285
+ ```
286
+
287
+ The suite is dependency-free and runs everywhere: transports are exercised
288
+ through the loopback bus and the in-process link simulator, which models every
289
+ network's bandwidth, latency, loss, MTU and duty-cycle constraints. The
290
+ integration suite spins up a real `ShugonetHost` with multiple threaded
291
+ `ShugonetAgentRuntime` clients, validates cross-talk isolation, memory
292
+ convergence, peer-lost latching, and unpaired-agent refusal.
293
+
294
+ ## Changelog
295
+
296
+ ### 0.5.0
297
+
298
+ - **ShugoCore 1.20.0 compatibility**: renamed ``agent_runtime.py`` to
299
+ ``shugonet_runtime.py`` to avoid naming collision with ShugoCore's own
300
+ ``agent_runtime`` module. All imports updated accordingly.
301
+ - **Cross-platform CLI client**: ``shugonet-client`` command (installed by
302
+ ``pip``) with ``run``, ``status``, ``send``, ``query``, and ``sync``
303
+ subcommands. Configured via ``SHUGONET_*`` environment variables. Works
304
+ on macOS, Linux, and Windows.
305
+ - **Standard programmatic client**: ``shugonet_client.ShugonetClient`` wraps
306
+ the full runtime in a simple ``connect()`` / ``send()`` / ``disconnect()``
307
+ interface.
308
+ - Version bumped 0.4.0 → 0.5.0.
309
+
310
+ ### 0.4.0
311
+
312
+ - **Fleet dashboard**: stdlib HTTP operator plane (`dashboard.py`) with a
313
+ compiled TypeScript + SolidJS SPA (`dashboard/` → `shugonet_web/static`).
314
+ Serves JSON REST, a live SSE event stream, and the console; ships inside the
315
+ wheel so no JS toolchain is needed at install time.
316
+ - **ShugoCore memory compatibility**: fact schema aligned with
317
+ `SemanticMemory` / `PgSemanticMemory` columns (`kind`, `metadata`,
318
+ `created_at`); `pg_store.PgFactStore` mirrors mesh facts into PostgreSQL
319
+ (optional `postgres` extra).
320
+ - **Version handshake**: `shugonet_version` + `protocol_version` exchanged at
321
+ TCP admission; mismatches emit a `version_mismatch` audit event and refuse
322
+ the join.
323
+ - **Bridge sync test**: `tests/test_bridge_sync.py` keeps Shogunet's
324
+ `shugocore_adapter` and ShugoCore's vendored `shugonet_bridge` from drifting.
325
+ - Version bumped 0.1.0 → 0.4.0.
@@ -0,0 +1,301 @@
1
+ # Shogunet
2
+
3
+ > Networking integration for connecting multiple Shugocore agents together for
4
+ > collaboration between Shugocore agents in simulation and physical spaces,
5
+ > designed to be used over 5G, 4G, EDGE, LoRa, Wifi-Halow, Wifi, and Bluetooth
6
+ > networks.
7
+
8
+ [![PyPI](https://img.shields.io/pypi/v/shugonet)](https://pypi.org/project/shugonet/)
9
+ ![Release](https://img.shields.io/badge/release-v0.5.0-blue)
10
+ ![Python](https://img.shields.io/badge/python-3.9%E2%80%933.12-blue)
11
+ ![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Android%20%28Termux%2FChaquopy%29-lightgrey)
12
+ ![License](https://img.shields.io/badge/license-MIT-green)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install shugonet
18
+ ```
19
+
20
+ The core is dependency-free (stdlib-only). Optional extras:
21
+
22
+ ```bash
23
+ pip install shugonet[postgres] # PostgreSQL mesh backend (PgSemanticMemory parity)
24
+ pip install shugonet[ws] # rosbridge-style WebSocket transport
25
+ pip install shugonet[relay] # HTTPS relay transport (5G/4G/EDGE)
26
+ pip install shugonet[serial] # LoRa SX126x/SX127x serial modules
27
+ pip install shugonet[ble] # BLE transport
28
+ pip install shugonet[telemetry] # OpenTelemetry integration
29
+ ```
30
+
31
+ The compiled fleet dashboard ships inside the wheel — no JavaScript toolchain
32
+ is needed at install time.
33
+
34
+ Shogunet is the networking layer for [ShugoCore](https://github.com/SamurAI-Official/ShugoCore).
35
+ It lets a fleet of ShugoCore agents — running in Gazebo simulation, on servers,
36
+ on robots, or on Android handsets — discover each other, exchange tasks and
37
+ events, and consolidate a *codependent* memory mesh, over whatever networks the
38
+ mission has available, with deterministic fallback between them.
39
+
40
+ ## Design principles
41
+
42
+ **One protocol, every network.** A single versioned envelope is spoken over all
43
+ transports, from 5G to LoRa. Two codecs exist for it: a JSON codec for
44
+ broadband links and a compact binary codec (16-byte header + TLV payload) for
45
+ constrained links such as LoRa (0.3–27 kbit/s, ~220-byte frames) and BLE.
46
+
47
+ **Memory invariants survive the network.** ShugoCore's memory tiers map to
48
+ network tiers: Tier 0/1 never leave the agent (N0). Tier 2 semantic facts sync
49
+ between paired agents (N1). Tier 3 is read-only everywhere: only *promotion
50
+ proposals* travel, and application stays operator-attributed (N2).
51
+
52
+ **Codependent memory.** Facts propagate with provenance
53
+ `(origin_agent_id, fact_id)`; salience merges additively; pruning propagates as
54
+ tombstones; and reinforcement is a *feedback loop* — when a peer's fact proves
55
+ useful, a tiny `reinforce` message flows back so useful memories survive decay
56
+ fleet-wide. Over LoRa, the loop runs on ~50-byte digest frames; bulk fact
57
+ content moves later over any broadband link (digest anti-entropy).
58
+
59
+ **Pairing is consent.** Only operator-allowlisted agent IDs pair, grants carry
60
+ TTLs, topics are namespaced (`/shugunet/{agent_id}/{topic}`), and every
61
+ ingress/egress field is sanitized and size-capped. Every network event lands in
62
+ a hash-chained audit log.
63
+
64
+ **Deterministic fallback.** Transports form an ordered, health-ranked chain
65
+ with per-transport circuit breakers. If the LAN drops, traffic falls to the
66
+ relay; if everything drops, a bounded store-and-forward WAL replays on
67
+ reconnect. Total transport exhaustion latches the ShugoCore governor through
68
+ its fallback triggers instead of failing silently.
69
+
70
+ ## Network tiers
71
+
72
+ | Class | Networks | Protocol response |
73
+ |---|---|---|
74
+ | Broadband IP | 5G, 4G, WiFi | JSON codec, mesh query fan-out, bulk sync; LAN = direct TCP, cellular = relay hub |
75
+ | Midband IP | EDGE, WiFi-Halow | Compact codec, batching, latency-tolerant profiles |
76
+ | Constrained | LoRa | 16-byte header frames ≤ 220 B, P0/P1 priority only, digest anti-entropy, duty-cycle honored |
77
+ | Short-range | Bluetooth (RFCOMM/BLE) | Stream framing or segmented compact codec; pairing-based discovery |
78
+
79
+ Message priority classes: **P0** control (announce/heartbeat/ack/tombstone) →
80
+ all links · **P1** memory deltas (facts/reinforce/digests) → constrained-capable
81
+ · **P2** tasks and queries → IP links · **P3** bulk snapshots and audit
82
+ shipping → broadband only, deferred under low power / thermal pressure.
83
+
84
+ ## Module map
85
+
86
+ | Module | Responsibility |
87
+ |---|---|
88
+ | `protocol.py` | Envelope schema, 16-byte binary header, JSON + compact TLV codecs, segmentation, validation |
89
+ | `transports.py` | `BaseTransport`, `LinkProfile` registry (7 networks + loopback), loopback bus |
90
+ | `link_simulator.py` | In-process impairment: bandwidth, latency, jitter, loss, MTU, duty cycle |
91
+ | `discovery.py` | Per-medium peer discovery (multicast beacons, hub rendezvous, pairing, duty-cycled LoRa) |
92
+ | `agent_registry.py` | Pairing = consent, allowlists, TTL grants, topic ACLs, sim/phys manifests |
93
+ | `tcp_transport.py` | Length-prefixed TCP transport with announce handshake (WiFi / WiFi-Halow profiles) |
94
+ | `relay_transport.py` / `relay_server.py` | Cellular path: HTTPS relay hub + long-poll client (5G/4G/EDGE, cross-NAT) |
95
+ | `lora_transport.py` | Serial SX126x/SX127x point-to-point transport (optional `pyserial`) |
96
+ | `bluetooth_transport.py` | RFCOMM (AF_BLUETOOTH) and BLE (optional `bleak`) transports |
97
+ | `transport_fallback.py` | Link-aware chain: eligibility, EWMA health ranking, breakers, QoS |
98
+ | `store_forward.py` | Bounded JSONL WAL outbox/inbox with replay + dedup |
99
+ | `memory_sync.py` / `mesh_query.py` | Codependent memory mesh: fact replication, conflict resolution, fan-out queries |
100
+ | `audit.py`, `fallbacks.py`, `policy.py`, `telemetry.py` | ShugoCore-aligned safety surface |
101
+ | `shugocore_bridge.py` | Adapter hosting a Shogunet node beside a ShugoCore `DecisionEngine` |
102
+
103
+ ## Hosting a fleet
104
+
105
+ Shogunet runs as a single server process that owns the fleet's trust plane so
106
+ every ShugoCore agent only needs a ~20-line client runtime to join.
107
+
108
+ ### Start a host
109
+
110
+ ```python
111
+ from host import ShugonetHost
112
+
113
+ host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001)
114
+ host.start()
115
+
116
+ # Grant consent to a joining agent (pairing = consent)
117
+ host.pair("agent-001", manifest={"realm": "phys", "role": "perception"})
118
+
119
+ print(host.status()) # roster, alive count, breaker health, mesh counts
120
+ ```
121
+
122
+ Or from the CLI:
123
+
124
+ ```bash
125
+ python3 host.py --tcp-port 9000 --relay-port 9001
126
+ ```
127
+
128
+ ### Join from a ShugoCore process
129
+
130
+ ```python
131
+ from shugonet_runtime import ShugonetAgentRuntime
132
+
133
+ runtime = ShugonetAgentRuntime(
134
+ agent_id="agent-001",
135
+ host_tcp_host="127.0.0.1",
136
+ host_tcp_port=9000,
137
+ host_relay_url="http://127.0.0.1:9001",
138
+ on_message=lambda sender, msg: print(f"from {sender}: {msg}"))
139
+ runtime.connect_to_host()
140
+
141
+ # Send a task to another agent
142
+ runtime.send("agent-002", "/shugunet/agent-001/task",
143
+ {"action": "scan", "zone": "north"})
144
+
145
+ # Search the fleet's memory
146
+ results = runtime.query("obstacle in zone north")
147
+
148
+ # Sync memory with the fleet
149
+ runtime.sync()
150
+
151
+ # Leave the fleet
152
+ runtime.stop()
153
+ ```
154
+
155
+ ### Cross-platform CLI client
156
+
157
+ Shogunet ships a standard CLI client that works on macOS, Linux, and Windows:
158
+
159
+ ```bash
160
+ # Install (ships with the wheel)
161
+ pip install shugonet
162
+
163
+ # Connect and stay connected (foreground daemon)
164
+ shugonet-client run
165
+
166
+ # One-shot status
167
+ shugonet-client status
168
+
169
+ # One-shot send to a peer
170
+ shugonet-client send agent-002 /shugunet/agent-001/task '{"action":"scan"}'
171
+
172
+ # One-shot memory query
173
+ shugonet-client query "obstacle in zone north"
174
+
175
+ # One-shot digest sync
176
+ shugonet-client sync agent-002
177
+ ```
178
+
179
+ The client is configured via environment variables:
180
+
181
+ | Variable | Default | Description |
182
+ |---|---|---|
183
+ | `SHUGONET_AGENT_ID` | hostname | Agent identifier |
184
+ | `SHUGONET_HOST` | 127.0.0.1 | ShugonetHost address |
185
+ | `SHUGONET_TCP_PORT` | 9000 | TCP port |
186
+ | `SHUGONET_RELAY_URL` | *(none)* | Relay hub URL |
187
+ | `SHUGONET_REALM` | phys | sim or phys realm |
188
+ | `SHUGONET_LOG_LEVEL` | info | Log verbosity |
189
+
190
+ Or use it programmatically:
191
+
192
+ ```python
193
+ from shugonet_client import ShugonetClient
194
+
195
+ client = ShugonetClient(agent_id="robot-1", host="10.0.0.5", tcp_port=9000)
196
+ client.connect()
197
+ client.send("robot-2", "/shugunet/robot-1/status", {"battery": 87})
198
+ print(client.status())
199
+ client.disconnect()
200
+ ```
201
+
202
+ ### Routing model
203
+
204
+ Agents connect **to** the host (hub-and-spoke). The host forwards addressed
205
+ mail to its recipient and fans broadcasts out as addressed copies to every
206
+ other paired agent. Host-addressed mail — heartbeats, mesh queries, memory
207
+ broadcasts — is processed locally by the host's own chain handlers.
208
+
209
+ **Pairing is enforced twice** — at TCP admission (handshake hook) and again on
210
+ every host-processed or forwarded envelope (the relay path has no registry gate
211
+ of its own, so the host re-checks the sender there).
212
+
213
+ ### Failure semantics
214
+
215
+ - **Agent crash/disconnect** → host governor latches `pause` (ShugoCore
216
+ deterministic latch contract).
217
+ - **Message durability** → per-agent `OutboxStore` + `at_least_once` QoS + hub
218
+ mailbox TTL bounds.
219
+ - **Cross-talk** → chain and mesh recipient guards (hardened in the
220
+ concurrency suite) hold at host scale.
221
+
222
+ ### Fleet dashboard
223
+
224
+ Every `ShugunetHost` can expose an operator console — a compiled single-page
225
+ app (TypeScript + SolidJS, built with Vite) served directly by the host over a
226
+ loopback HTTP port. No JavaScript toolchain is needed at install time: the
227
+ built assets ship inside the wheel (`shugonet_web/static`).
228
+
229
+ ```python
230
+ host = ShugonetHost(agent_id="fleet-1", tcp_port=9000, relay_port=9001,
231
+ dashboard_port=9002)
232
+ host.start()
233
+ # open http://127.0.0.1:9002 in a browser
234
+ ```
235
+
236
+ The console streams a live event feed (Server-Sent Events), shows the roster,
237
+ transport-chain health, memory-mesh counters, and audit-chain integrity, and
238
+ exposes pair / unpair / resume / broadcast controls. State-changing POSTs are
239
+ audited and can be gated by a token (`dashboard_token=...`).
240
+
241
+ The SPA source lives in `dashboard/`; rebuild it with:
242
+
243
+ ```bash
244
+ cd dashboard && npm ci && npm run build
245
+ ```
246
+
247
+ ## Module map (continued)
248
+
249
+ | Module | Responsibility |
250
+ |---|---|
251
+ | `host.py` | `ShugunetHost`: admit paired agents, route traffic, seed the mesh |
252
+ | `shugonet_runtime.py` | `ShugonetAgentRuntime`: client half a ShugoCore process instantiates |
253
+ | `shugonet_client.py` | `ShugonetClient`: cross-platform CLI and programmatic client |
254
+ | `dashboard.py` | `DashboardServer`: stdlib HTTP operator plane (REST + SSE + SPA) |
255
+ | `pg_store.py` | `PgFactStore`: optional PostgreSQL mesh backend (ShugoCore `PgSemanticMemory` parity) |
256
+
257
+ ## Testing
258
+
259
+ ```bash
260
+ python3 -m unittest discover -s tests -v
261
+ ```
262
+
263
+ The suite is dependency-free and runs everywhere: transports are exercised
264
+ through the loopback bus and the in-process link simulator, which models every
265
+ network's bandwidth, latency, loss, MTU and duty-cycle constraints. The
266
+ integration suite spins up a real `ShugonetHost` with multiple threaded
267
+ `ShugonetAgentRuntime` clients, validates cross-talk isolation, memory
268
+ convergence, peer-lost latching, and unpaired-agent refusal.
269
+
270
+ ## Changelog
271
+
272
+ ### 0.5.0
273
+
274
+ - **ShugoCore 1.20.0 compatibility**: renamed ``agent_runtime.py`` to
275
+ ``shugonet_runtime.py`` to avoid naming collision with ShugoCore's own
276
+ ``agent_runtime`` module. All imports updated accordingly.
277
+ - **Cross-platform CLI client**: ``shugonet-client`` command (installed by
278
+ ``pip``) with ``run``, ``status``, ``send``, ``query``, and ``sync``
279
+ subcommands. Configured via ``SHUGONET_*`` environment variables. Works
280
+ on macOS, Linux, and Windows.
281
+ - **Standard programmatic client**: ``shugonet_client.ShugonetClient`` wraps
282
+ the full runtime in a simple ``connect()`` / ``send()`` / ``disconnect()``
283
+ interface.
284
+ - Version bumped 0.4.0 → 0.5.0.
285
+
286
+ ### 0.4.0
287
+
288
+ - **Fleet dashboard**: stdlib HTTP operator plane (`dashboard.py`) with a
289
+ compiled TypeScript + SolidJS SPA (`dashboard/` → `shugonet_web/static`).
290
+ Serves JSON REST, a live SSE event stream, and the console; ships inside the
291
+ wheel so no JS toolchain is needed at install time.
292
+ - **ShugoCore memory compatibility**: fact schema aligned with
293
+ `SemanticMemory` / `PgSemanticMemory` columns (`kind`, `metadata`,
294
+ `created_at`); `pg_store.PgFactStore` mirrors mesh facts into PostgreSQL
295
+ (optional `postgres` extra).
296
+ - **Version handshake**: `shugonet_version` + `protocol_version` exchanged at
297
+ TCP admission; mismatches emit a `version_mismatch` audit event and refuse
298
+ the join.
299
+ - **Bridge sync test**: `tests/test_bridge_sync.py` keeps Shogunet's
300
+ `shugocore_adapter` and ShugoCore's vendored `shugonet_bridge` from drifting.
301
+ - Version bumped 0.1.0 → 0.4.0.